Offsetting face-normals by worldOrientation

Hello there!
Here’s a some code from a longtime project of mine, edited for the sake of brevity.



...

for mesh in obj.meshes:
        for m_index in range(len(mesh.materials)):
            for v_index in range(mesh.getVertexArrayLength(m_index)):
                vertex = mesh.getVertex(m_index, v_index)
                vertexNorm = vertex.getNormal()
...

In short the code grants access to an object’s vertex-normals.

I use these to calculate face-normals, as these are not readily accessible in the BGE.

Here comes the part I can’t work out on my own:

Vertex-normals are local to the object, and so the calculated face-normals are too.
[ATTACH=CONFIG]462103[/ATTACH]
I’m attempting to offset the face-normals by the object’s world orientation, making them global - but my math skills are inefficient.

I’m currently reading up on rotation-matrices at the moment, and have made some progress, but I’m beginning to realize my math skills are inadequate : S

That’s it for now : ) Keep Blendering people!

Once you have your face normal, try multiplying that by the worldOrientation. Try converting your normal to a vector first with mathutils.Vector(faceNormal) (faceNormal should be in list or sequence format).

Multiplying a vector by a rotation matrix will apply a rotation to a vector.

Roger wilco! I’ll edit this post as soon as I get that done, should be within my capacities : P

Hehe, I have a feeling I’m about to learn something really, extremely useful :slight_smile:

Thanks for your reply I’ll report back asap! : D

EDIT: Dude… no… what the… it just works, no conversion to vector even needed, it just works right out of the box… hmmmm… this is… fascinating…

PS: Thank you, just thank you. I got totally carried away by this. I can make some real progress with this : D

Welcome! Happy blending :slight_smile:

Thank you! And yes happy blending indeed! :slight_smile:
Thanks to your input, a long time project of mine, is a single step from being released! : D

I only have one question left: if I have a normalized vector, for instance [0.0,0.0,-1.0], could I somehow turn that into a matrix like the one returned by .worldOrientation?

A normalized vector has a length of 1.0. The vector you show is indeed normalized. Could it be you mean this is a normal vector?

Normal vectors should be normalized too, but this is not what makes them a normal vector.

May I ask why you think you need a rotation matrix and why you think the input is this vector?

Explanation on the solution given at post#2:

In general Vertex position is described in the object space. The are position vectors providing the position of a vertex in object space. This makes a lot of sense as they usually should appear as a single object - means they should all equally follow the objects transformations.

Be aware vertex coordinates describe a position but no direction.

A vertex normal is described in object space too. In difference to vertex coordinates they are pure vectors. This means they have no position, but a direction. They can be anywhere. For better imagination they are typically drawn from the vertex they belong.

The combination of vertex position and vertex normal gives the vertex a direction (the vertex normal vector).

Object space to scene space
To transform a vector from object space to scene (world) space you multiply it with the objects world transformation matrix. This can be useful when you want an object at the visible position of a vertex (without establishing a parent/child relationship). You can use it to transform normals to scene space too.



object = ...
vectorInObjectSpace = ...

vectorInWordSpace = object.worldTransform * vectorInObjectSpace 


Scene space to object space
You can even convert vectors in scene space to object space. For example you want to deform a mesh in a way that it matches a position in scene.



object = ...
vectorInWordSpace = ...

vectorInObjectSpace = object.worldTransform.inverted() * vectorInWordSpace 


Normals
As normals have no position you can use the rotation matrix only (ignoring position and shear):


vectorInWordSpace = object.worldOrentation * vectorInObjectSpace
# and
vectorInObjectSpace = object.worldOrentation.inverted() * vectorInWordSpace 

This is a little bit but not noticeable faster (as it is a 3x3 rather than a 4x4 matrix). Be aware this does not apply to the position (vertex.XYZ).

That is why post#2 two is a good solution.

Hmmm, well, I guess it is a normal vector, sort of in a technical way, maybe? xD Maybe if I explain, you can tell me, yes or no?
: P

I have the linear velocity of an object as a vector like so: [x,y,z], call it a heading vector, I then make it so that it’s magnitude is equal to 1. So it is not technically the normal of a vertex, but it shares the same properties.

The input from Mirror|rorriM helped me make the .blend at the bottom of this post.
Basically the vertex normals of an object in the .blend are rendered in world space instead of object space, if that makes sense.

At least I think they do, or well they appear to do that, you’ll see what I mean in the .blend : P

I made the .blend, because I wanted to be able to offset the vertex normals of an object, based on its heading. Which is the reason I started this thread.

The solution which Mirror|rorriM provided, was to multiply the vertex normals by the object’s worldOrientation. That got me the proof of concept, in the form of the .blend below : D

The next step to my understanding, is to convert the heading vector to an orientation matrix, which I’ll use instead of or in conjunction with worldOrientation, in my current implementation.

That’s a really concise and precise explanation : D My matrix math in general, and understanding of the worldTransform matrix aren’t complete yet, so there’s probably some knowledge that I’m unable to glean from your post, but I do understand the trick with the 3x3 instead of the 4x4, and why you say post#2 is a good solution : ) Thanks for the enlightenment :slight_smile:
And now I’m beginning to see excellent potential with the manipulation of the worldTransform matrix : D

PS: Just move the mouse to see the script in action ; )

EditX5: Typos, clarity and terminology.

Attachments

Windtunnel_Test_BGE_RECODE_01.blend (528 KB)

A normal vector is orthogonal to something.

In 3D it can be used to describe a plane (together with a position).

A normalized vector (as said before) simply means the vector has a length of 1.0. Not all vectors are normalized. Normalized vectors allow certain mathematical operations without caring the length (as it results in a multiplication by 1). This makes them much easier to calculate.

Be careful, the linear velocity is a vector too, but has nothing to do with position or normal vectors. It describes the potential positional change within a certain time (1 sec). [I call it “potential” as the velocity can change within this second resulting in a different position after that second.]

The linear velocity has two attributes:

  • the direction
  • the speed (which is the length of the vector)

Changing the length changes the speed (but not the direction). That is why you need to be careful about it.

It has nothing to do with normal. Linear velocity can be a normal to another vector or a plane (by being orthogonal to it). By itself, it does not need this.

A practical example would be “planetary gravity”. The gravity is orthogonal to the sphere below the object (mean it points to the gravity center). The orthogonal vector/plane is the tangent of the sphere between the center and the current position of the object.

Sure they do. I remember someone used that method to change the vertex normals to achieve better shading on branch foliage, by turning the vertex normals towards the point in scene.

You converted the normals to colors. It looks nice, but I guess you can achieve he same effect with a GLSL shader. Even node materials can use such input (I never used that, but I know it is possible).

If I understand you correctly you want to transform the (vertex color or normal vector) dependent on the current linear velocity direction.

Let me think about the effect. When the object moves left (or right) the object turns red. When moving up/down it turns blue and so on.

As you do not want a solid color, the color should be depend on the direction the face/vertex is facing.

Yes that makes sense.

The rotation matrix you are looking for needs the 3 vectors: the forward vector (I guess you want the linear velocity), the side vector (left/right) and the up-vector. All vectors are orthogonal to each other!

To form a rotation matrix all these vectors need to be normalized (have a length of 1.0).

Unfortunately you need to provide at least one of the other vectors. The linear velocity does not provide the plane these vectors need to reside on (remember they need to be orthogonal). A typical vector is a vector that points nearest to global Z (called up-vector). Du to the fact the vector needs to be orthogonal, it can only be the real global Z, when the force is on the XY plane, which is pretty unlikely.

Just now, I forgot all of my mathematical knowledge :eek:. I can only remember you need some sort of cross product. But I have to look if I can find the mathematics skill somewhere under my bed … (sleeping on a maths book does 100% not help … wait that was the stochastics book:no:).