Sign in to follow this  
William_Fagerstrom

Rotating a face normal

Recommended Posts

Okay here is a probably quiet simple problem but at the moment I just don't quiet know how to approach it... I would like to know how to rotate a face so that the normal of that face is equal to (0,0,-1). Also a potentiality silly question: Does the value of each of elements in a normalized point have any relation to Cos? Something in the back of my mind is telling me that the normal (1,0,0) is T = cos_inv(1) = 0, where T is the angle around the X axis. Is that correct?

Share this post


Link to post
Share on other sites
Okay reading my post I don't think I was entirely clear, this is what I want to achieve.

I have a face, a triangle. Its normal is something like "(x:0.25832, y:0.12354, x:-.326523)". That could be any value. I would like to know how I could determine what rotations I need to apply to the points that make up the face so that its normal becomes (x:0,y:0,z:-1).

Whats the best way to do this?

Share this post


Link to post
Share on other sites
Quote:

I would like to know how to rotate a face so that the normal of that face is equal to (0,0,-1).


Build a matrix with the at being the inverse of the face normal (inverse because you said z=-1).
You'll need a guess for the "up" to build the matrix, since you have a triangle already, just take any edge.
Then invert the resultant matrix, and multiply all your verts by that matrix.
Tada. Your triangle is now at the origin, facing down negative Z.

in pseudo code:

mat.at = -FaceNormal;
mat.up = normalize(tri.A - tri.B);
mat.left = mat.up cross mat.at
mat.up = mat.at cross mat.up

mat.pos = (tri.A + tri.B + tri.C) / 3
inverseMat = invert(mat);
newtri.A = tri.A * inverseMat;
newtri.B = tri.B * inverseMat;
newtri.C = tri.C * inverseMat;


any point or ray you have in "world space" you can multiply by inverseMat to get it into your new "local space". For instance a vector from a light to the face center, you could convert into local space.
any point or ray you have in "local space" you multiply by mat to get it back to "world space".

*edit: the line "mat.up = mat.at cross mat.up" isn't really needed in the exact example I posted. The reason I included it is because your "up guess" also affects the final orientation of the matrix. You may want to use the world up <0,1,0> instead of a triangle's edge. In that case, the up and normal aren't guaranteed to be at right angles to one another, thus you have to use this line to make sure the final up is at a right angle to both at and left.

Quote:

Also a potentiality silly question: Does the value of each of elements in a normalized point have any relation to Cos? Something in the back of my mind is telling me that the normal (1,0,0) is T = cos_inv(1) = 0, where T is the angle around the X axis. Is that correct?

Errrrr...... kinda.
A normal is usually representitive of a ray from the origin to a point on a sphere of radius 1 around the origin. You can decompose that ray any way you like to figure out the rotation you'd need to move your "at" axis to line up with the ray in question. The decomposition to a rotation will, by nature of the math involved relate to sin/cos in some way.

For instance, you could decompose it as latitude/longitude
Then the point is (assuming Y is up, positive Z is at>
< sin(theta) * sin(alpha), cos(alpha), cos(theta)*sin(alpha) >

You could decompose it into euler angles around each axis, but you end up with a LOT of aliasing and order-of-operation issues.

You could decompose it to a quaternion, a succinct representation of an axis of rotation and an angle around that axis.

And, you can do what I showed above, and build a matrix that represents the coordinate space where "at" is your normal. Said matrix then represents a rotated world. Using a matrix multiply, you can rotate any point in the identity "world space" into your new "local space" and back.

[Edited by - KulSeran on December 29, 2009 2:13:03 AM]

Share this post


Link to post
Share on other sites
[quote]Original post by KulSeran
Quote:

in pseudo code:

mat.at = -FaceNormal;
mat.up = normalize(tri.A - tri.B);
mat.left = mat.up cross mat.at
mat.up = mat.at cross mat.up

mat.pos = (tri.A + tri.B + tri.C) / 3
inverseMat = invert(mat);
newtri.A = tri.A * inverseMat;
newtri.B = tri.B * inverseMat;
newtri.C = tri.C * inverseMat;



Thank you very very much for your reply. There is just one part of this I don't get and thats the way you define 'mat'. What are these .at, .up and .left properties? As far as I can tell its something to do with XNA but I'm not using C#.

Or MS products for that matter. (Noting against MS) I have just set my self the task of learning from the ground up, without my hand being held by .NET or XNA. Or any other library.

Share this post


Link to post
Share on other sites
Quote:
There is just one part of this I don't get and thats the way you define 'mat'. What are these .at, .up and .left properties? As far as I can tell its something to do with XNA but I'm not using C#.
It's just pseudocode - I doubt it's XNA-related.

In this context, 'left', 'up', and 'at' simply refer to the first three columns/rows of the matrix (whether they're columns or rows depends on whether column or row vectors are being used). In other words, each is simply a 3-element vector (xyz).

It's fairly conventional for 'at' to correspond to the +/- z axis, 'up' to correspond to the y axis, and left/right/side to correspond to the x axis. It doesn't have to be done this way, but it makes sense for polygons/billboards (since it places the polygon in the xy plane in local space).

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
It's just pseudocode - I doubt it's XNA-related.


I have just never heard of that terminology before. I have done two units at uni on math so far and I have never heard of "at,left,right,pos" at all.

would this be correct?



and what is this pos variable?

There is no documentation about this terminology as far as I can tell. Except in MSDN which is very bad.

[Edited by - William_Fagerstrom on December 30, 2009 3:40:50 PM]

Share this post


Link to post
Share on other sites
It's more common terminology in 3D graphics, due to the way "look-at" camera matrices are constructed:

http://www.songho.ca/opengl/gl_lookattoaxes.html
http://www.opengl.org/wiki/GluLookAt_code

you may find this wiki page to have a slightly more indepth explination of why the KulSeran's method works:
http://www.devmaster.net/wiki/Coordinate_systems#Transforming_Between_Coordinate_Systems

Share this post


Link to post
Share on other sites
Quote:
Original post by William_Fagerstrom
Quote:
Original post by silvermace
for column major matrices, its the 4th column, for row major matrices its the 4th row. This is the translation part of a typical 4x4 graphics matrix.


SO my matrix would look somethng like this?
Element 44 should be 1, not 0. Otherwise, yes, that looks right.

Share this post


Link to post
Share on other sites
Okay so I have implemented KulSeran's algorithm and it works, but not to the effect that I want. It has some scaling in it or something... I only want it to rotate.

**edit**
The algorithm only works for some faces and not others...

I.e.
{(1, 1, 0), (1, 1, -50), (1, 50, 0)} to {(1, 1, 0), (50, 1, 0), (1, 50, 0)}

What I am trying to do is rotate every poly in a model so its flat and I can the crate a net.

[Edited by - William_Fagerstrom on January 1, 2010 7:53:40 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this