Sign in to follow this  
irreversible

Extracting Euler rotation from direction

Recommended Posts

After some research, it seems what I need is not quite nearly as straightforward as I'd like (well, at least not for me since I'm dense about mathematics): I have a face normal and the world-space up vector (which is always pointing straight up) and I need to turn the normal vector into regular Euler angles (that is, I need to extract the normal's rotation vector (or matrix) relative to some random fixed point). Can anyone give a clear and simple explanation how I do this (remember, I'm dense about mathematics :) ). I know I can get the direction vector from yaw and pitch like this: direction.x = sin(yaw) * cos(pitch); direction.y = sin(-pitch); direction.z = cos(yaw) * cos(pitch); Which is kind of moot since I don't know how to derive yaw and pitch from this. And roll is missing altogether... Bleh - I hate my left hemisphere (of the brain!) :/

Share this post


Link to post
Share on other sites
Do you NEED the euler angles? Or could you settle for an AxisAngle or quaternion?

If you use the cross product between the world up and face normal you'll get an axis angle pair.

Vec result = Cross(worldUp, normal);
Vec axis = result.Normalized();
float angle = asin(result.Length());

You can easily construct a quaternion or matrix from the axis angle pair.

In case you do want the euler angles you'd actually need a reference plane. So two vectors, such as worldUp and +X as your reference plane. You'd then find a rotation which would align the normal to the plane, and then again to align the normal to the worldUp. You'd only need the two angles, polar coordinates. You wouldn't need the "roll." To reconstruct the normal you'd just follow the coordinates backwards, rotating in the up/+x plane, then away from it.

Share this post


Link to post
Share on other sites
Sorry, I failed to describe what I'm trying to do: in simple terms - I need to replace the face with another object that points in the same direction. For this, as far as I figure, the easiest method would be to extract the rotation matrix or vector from the face and apply it to the new object.

I'm not sure if quaternions would be a good choice for this (seeing as Euler angles at least make sense to me; quaternions are just a black box with no windows). Assuming a static reference plane is no problem. What I can't wrap my head around is the actual math involved...

And what about collinearity? If my up-vector always points up, should I simply treat an up-pointing normal as a special case?

Share this post


Link to post
Share on other sites
I'd bet that this problem is most naturally and easily thought of in terms of rotation matrices.

So you want a rotation matrix that will transform some fixed vector (up?) to the normal vector for some face. This still leaves you with a degree of freedom (picture spinning about the normal), so you need to decide what other vectors you want to correspond. For instance, maybe you want the vector in the x direction to transform to a vector along the first edge of the triangle/face in question.

Anyway, what I'm saying is that you just need to figure out how three linearly-independent vectors transform. And since you're in 3d, you really only need to determine how two transform; you can use their cross product as the third.

Share this post


Link to post
Share on other sites
Quote:
Original post by irreversible
And what about collinearity? If my up-vector always points up, should I simply treat an up-pointing normal as a special case?


A matrix is a wonderful thing ;)

xAxis = { m.m00, m.m01, m.m02 }
yAxis = { m.m10, m.m11, m.m12 }
zAxis = { m.m20, m.m21, m.m22 }
position = { m.m30, m.m31, m.m32 }

and the following are fairly useful:

Z = X cross Y
X = Y cross Z
Y = Z cross X

so lets starts with a position at the origin, I'll assume X is forward, and Y is up. So, our forward vector is (1,0,0). Up vector is (0,1,0). The z axis is (forward cross up). Plug in the values and....

xAxis = { 1,0,0 }
yAxis = { 0,1,0 }
zAxis = { 0,0,1 }
position = { 0,0,0 }

... we have the identity matrix. Which makes sense, because our object is at the origin in it's default orientation. If you plug in any direction vectors at all for forward/up/position, you'll generate a valid matrix! Try it for a few direction vectors and you'll suddenly understand matrices a whole lot more ;)

You could also use a quat here since quats are basically matrices without the translation....

The one thing you absolutely do not want to do, is use Euler angles!

Share this post


Link to post
Share on other sites
Aight, I've been doing some reading up and apparently Euler angles are a bad indeed :). So then - constructing a rotation matrix. I have a couple of questions and a few points I can't quite understand. First off, I read Diana Gruber's article on rotation matrices, which was a surprising easy read. From that I derived the following code (being a C++ programmer, naturally 0 is a valid row index for me!):


mRotation.LoadIdentity();

vNormal = VecNormalize(vNormal);

//3rd row
mRotation.SetEntry( 8, vNormal.x);
mRotation.SetEntry( 9, vNormal.y);
mRotation.SetEntry(10, vNormal.z);

//2nd row
TVector3D vRow1 = TVector3D(0, 1, 0) - (vNormal * VecDotProduct(&TVector3D(0, 1, 0), &vNormal)); //<- what if vNormal and up vector are collinear?
mRotation.SetEntry(4, vRow1.x);
mRotation.SetEntry(5, vRow1.y);
mRotation.SetEntry(6, vRow1.z);

//1st row
TVector3D vRow0 = VecCrossProduct(vUp, vNormal);
mRotation.SetEntry(0, vRow0.x);
mRotation.SetEntry(1, vRow0.y);
mRotation.SetEntry(2, vRow0.z);



Am I right in assuming that I can treat this as a view matrix, vNormal being the LookAt vector, vUp being the world up vector (0, 1, 0) being the absolute up vector and vRow0 being the riht vector?

This link seems to reference a different solution (which in addition to being different is also column-major):


zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)

xaxis.x yaxis.x zaxis.x 0
xaxis.y yaxis.y zaxis.y 0
xaxis.z yaxis.z zaxis.z 0
-dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye) l



There's also that last line... Am I on the right track here? RobTheBloke: I'm sure it's me, but I don't seem to be getting the magic behind your post :). Also - there's still the question of collinearity.

PS - I'm using OpenGL, so the whole row-major/column-major thing is confusing me a lot...

PPS - yeah, sorry for being dense here - I'm sure anyone who falls a bit on the other side (the non-mathematical other side, that is...) can identify with me :)

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