View Full Version : General 3D math question

07-06-2004, 11:22 AM
This is not lscript specific question but maybe someone will point me in the right direction.

Let say I have a polygon in modeler that is rotated along all three axes. I need to perform some operations on the polygon, but for simplicity of my code, first I would like to rotate the polygon so that its normal points directly in the Y+ direction (or any other, as long as it is aligned to some axis). Once I performed the operation I'd like to rotate the polygon back to its original angles.

What is the best way to approach this? I tried 3x3 matrix rotation but could not get it to work properly. I think Im getting close but I guess I'm missing some tiny (I hope) bit knowledge here.

Is there any use of the angles given by the polygon normal or maybe polygon normal vector has no use here? Can I rotate all angles at once or do I have to rotate one angle at the time? Do I have to use quaternions (which I can learn if neccesary) or can I do without? What is the best(fastest?) vs. simplest solution (although speed is not my main concern, since I'll be working on small sets of points)?


07-06-2004, 11:58 AM
JettoLocal does that for you I believe- http://www.3dfightclub.com/~jettocrack/lightwave/plugins/jettolocal/index.htm

If you need to expand on that perhaps the author will share his method with you.

07-06-2004, 02:07 PM
Yes, JettoLocal does it and this is exactly what I had in mind. I guess I forgot to mention that I need to do such rotation as a part of "operation" in my own plugin that I am writting.

I am not expecting someone to give me exact code, just point me in the right direction

07-08-2004, 04:17 PM
I've never used LScript or even know what it is but if you need to align a polygon to an axis and you have it's normal you can do it like so.

First you take each component of the normal and remove it's sign. (Don't know if this is the correct english term for what you have to do) If the normal was normalized you should now have three values ranging from 0..1 instead of -1..1
x = fabs(polygon.normal_x)
y = fabs(polygon.normal_y)
z = fabs(polygon.normal_z)
(C source code to do that)

Then you "invert" the normal component that is the axis you want to align to. For example if you want to align to the Y axis you do
y = 1.0 - y
(that's more C code)

Now you create a 3x3 matrix which is rotated with your normals. Around the X axis you use your x variable as angle, the same for Y and Z. The extend of those values should be a quarter of a turn, so if your variables are ranging from 0..1 and your function to create a rotated matrix take 360 as a full turn you have to multiply your values by 90 before using them to rotate.

Now all you have to do is rotate your polygon with the matrix you just created and the resulting polygon will be aligned to the Y axis.

As for rotating it back I suppose you can just inverse the rotation angles, but I have not done this myself.

Uuuuhm, I hope this helps. :)

07-09-2004, 07:19 AM
Thanks for the reply and I hope you got your pdf already :)

Your solution is actually something along the the way I tried to do it, but it didnt quite work (for me?). It did work for a single axis at time, but not for all three simultaneously or all three in sequence. I tried quaternions, same results.
I did not invert the axis or take absolute values as you suggest. That is a small change in my current code. I'll try it.

Now, I either did some small or big mistake in my code or the whole approach is incorrect. I'm aware of the complexities of 3d rotation (order matters, etc) and I'm still looking for a solution. I know people must do it everyday, but for some reason no tutorial on the web addresses this issue directly. I can find all matrix/quaternion rotations I want, but I did not find a tutorial how to rotate between local-world coordinates, which, i think, is what I need.

I bought a 3d math for gfx + game programmers book yesterday (published by wordware), hopefully it will help me. So far it looks promising and it will refresh/improve my rather dusty linear algebra knowledge.

07-09-2004, 08:36 AM
Hm...*thinking hard*
Ok, i think you can build the rotation matrix from three orthogonal unit-vectors describing your local coordinate system, e.g. poly-normal, one poly-edge and the cross-product them.
Each vector is one column of the matrix.

To "undo" this rotation just inverse the matrix, which for rotation matrices is IIRC simply the transpose.
And by definition follows [M]*([M]^-1) = [1], menaing your local coordinate system gets transformed onto the 3 coordinate axis.

Hope this was all correct...

I could also tell you to reconstruct the euler angles from the rotation matrix (even for 3 different rotation orders...but it's no fun), because i needed it for my TextureGuide Plugin, think i got it somewhere from ome OpenSourceTools for LW...
but i guess that's overkill here, and it took me days to get everything right.

might add some things: the local coordinate system must have the same orientation as Modeler's.
And i assumed you define matrix multiplication like usually in math books, i.e.

|m11 m12 m13| |v1|
|m21 m22 m23| * |v2|
|m31 m32 m33| |v3|

and not like apparently often used in OpenGL

|m11 m12 m13|
|v1 v2 v3| * |m21 m22 m23|
|m31 m32 m33|

Otherwise colums become rows...

07-09-2004, 09:04 AM
Thanks, I got the PDF now. :) Hope I can change my nick, this board seems really nice.

It is very important that the normal is normalized, but if it works for one axis I suppose it is.
The method works fine for me in a test I've made in C with OpenGL but now that I think about it might be purely by coincidence, my scene was simply a cube centered around origo. Anyways, here's my C code to align a polygon to the Z axis:
// Get polygon normal
float nx = fabs(supermodel.face[iFace].normal[iVert].x);
float ny = fabs(supermodel.face[iFace].normal[iVert].y);
float nz = 1.0f - fabs(supermodel.face[iFace].normal[iVert].z);

// Get polygon rotation matrix

// Create unit matrix

// Rotate the matrix around the three axises
glRotatef(nx*90.0f, 1,0,0);
glRotatef(ny*90.0f, 0,1,0);
glRotatef(nz*90.0f, 0,0,1);Now I can use the created matrix to rotate the polygon so it is aligned with the Z axis. When I think about it it might just be parallel with the Z axis, not coplanar. But maybe that doesn't matter to you. And it is not centered, it will be rotated with the matrix around origo of the scene.

07-12-2004, 03:10 PM
Thanks for your replies. I didnt get a chance to try your suggestions yet (too busy with work and 2 kids) but I will soon.

07-13-2004, 12:51 PM
I have found an answer. This is exactly what I needed. Works like a charm and no euler angles are involved:


Thank you all for help and contributions!

07-13-2004, 01:43 PM
Uhm...yea that's pretty much what i tried to explain, if the global vectors are <1, 0, 0>, <0, 1, 0> and <0, 0, 1> the dot products collapse into one component of each local unit vector and the matrix rows/colums become those local vectors for the (inverse) transformation matrix...? :)

07-13-2004, 02:10 PM
yup, i just wasnt quite sure how to construct the matrix (dot products) :)

I guess what confused me was all the places that gave the example of the transformation matrix (which was rotation matrix in fact, i think) in terms of angle rotation along an axis.
Then they told me to multiply 3 matrices to get final rotation.. but then the order of operation matters etc and as you said, converting between matrix and euler angles is a bit more involved and then how would I get euler angles and their order, etc, then we have gimbal lock, blah...

As I thought, I was taking wrong approach. :D

07-13-2004, 03:29 PM
dot product...
(x1, x2, x3)dot(y1, y2, y3) = x1*y1 + x2*y2 + x3*y3;
Becomes just a scalar. And it's the same as |x|*|y|*cos(alpha)...

That's pretty nice, you can for example orthogonalize two vectors easily that way...