# Direction Vector to Rotation Matrix

This topic is 2440 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello!
I've been trying to solve a (rather simple?) problem lately. I'm surprised I haven't been able to find anything really useful on the net so far.

The thing is I have 3d direction vector. Use it to set the direction of an object in 3d space. To do that I need of course a transformation matrix.
I have a function that properly calculates the LookAt matrix. However it is correct for the view transformation. I had no success in using it to calculate the rotation of the object.

I have also tried using trigonometry using (assuming Y is up):
 if(dir.getY() != 0.0f) xAngle = (float)Math.toDegrees(Math.atan((dir.getZ()*dir.getZ()+dir.getX()*dir.getX())/dir.getY())); if(dir.getZ() != 0.0f) yAngle = (float)Math.toDegrees(Math.atan(dir.getX()/dir.getZ())); TransformationMatrix.calculateRotationMatrix(xAngle, yAngle, 0.0f); 
However this does produce proper results only in certain situations.

Can anybody suggest a solution?

Thanks a lot

##### Share on other sites

...
The thing is I have 3d direction vector. Use it to set the direction of an object in 3d space. To do that I need of course a transformation matrix.
I have a function that properly calculates the LookAt matrix. However it is correct for the view transformation. I had no success in using it to calculate the rotation of the object.
...

The difference between the view transformation (a global-to-local transformation) and its camera transformation (a local-to-global transformation) is that the one is the inverse of the other. So, if your implementation actually computes a view transformation, then invert the resulting matrix and you're done.

Because the view transformation usually is composed of a translation and a rotation only, like so
T( p ) * R
for column vectors, its inverse is probably computed simply as
( T( p ) * R )[sup]-1[/sup] = R[sup]-1[/sup] * T( p )[sup]-1[/sup] = R[sup]t[/sup] * T( -p )
where the t denotes the transpose operation, so you may avoid a full-fledged matrix inversion implementation. (You have to reorder the matrices if you use row vectors, of course.)

##### Share on other sites

( T( p ) * R )[sup]-1[/sup] = R[sup]-1[/sup] * T( p )[sup]-1[/sup] = R[sup]t[/sup] * T( -p )

I'm trying to experiment with the transpose of the rotational part of the LookAt matrix, without much success unfortunately.
However the weird thing is that with the transposed matrix I get some scaling effects when applied to a mesh. Should that happen?

##### Share on other sites
Ok. Solved. Sort of

I've managed to implement a function using hybrid method. It seems to work. However is not very elegant.
For anyone interested:

 public static TransformationMatrix calculateDirectionalMatrix(Vector3d dir, Vector3d up) { float [] matrix = new float[16]; //Calculating as if a normal LookAt function: Vector3d forward = new Vector3d(dir); //Only with inverted direction and no height component. forward.setX(-forward.getX()); forward.setY(0.0f); forward.normalize(); Vector3d side = Vector3d.cross(forward , up); side.normalize(); Vector3d plane_up = Vector3d.cross(side , forward); plane_up.normalize(); matrix[0] = side.getX(); matrix[1] = plane_up.getX(); matrix[2] = -forward.getX(); matrix[3] = 0.0f; matrix[4] = side.getY(); matrix[5] = plane_up.getY(); matrix[6] = -forward.getY(); matrix[7] = 0.0f; matrix[8] = side.getZ(); matrix[9] = plane_up.getZ(); matrix[10] = -forward.getZ(); matrix[11] = 0.0f; matrix[12] = 0.0f; matrix[13] = 0.0f; matrix[14] = 0.0f; matrix[15] = 1.0f; //Complete directional matrix for the XZ part of the direction. TransformationMatrix ret = new TransformationMatrix(matrix); //Now if relevant we calculate the height component of the direction using the trigonometry function. if(dir.getY() != 0.0f) { float angle = (float)Math.toDegrees(Math.asin(dir.getY())); TransformationMatrix Y = TransformationMatrix.calculateRotationMatrix(angle, 0.0f, 0.0f); //We multiply matrices as D = XZ * Y; ret.multiply(Y); } //TADA! return ret; }  Edited by Yezu666

##### Share on other sites
If you have a direction vector (I'm assuming this means your "forward" vector), then all you need to do to create the transformation matrix is create a basis using that vector.

Pseudocode:

vector3 tempUp = [0, 1, 0]
vector3 right = forward.cross(tempUp)
vector3 up = right.cross(forward)

matrix3x3 rotationMat =

[ right.x forward.x up.x ]
[ right.y forward.y up.y ]
[ right.z forward.z up.z ]

(haven't double checked but i'm almost sure this is correct)

EDIT: this all depends on whether you're using a right-handed or left-handed system (column-major or row-major matrices)

##### Share on other sites

I'm trying to experiment with the transpose of the rotational part of the LookAt matrix, without much success unfortunately.
However the weird thing is that with the transposed matrix I get some scaling effects when applied to a mesh. Should that happen?

Definitely not.

Ok. Solved. Sort of

I've managed to implement a function using hybrid method. It seems to work. However is not very elegant.
For anyone interested:

 public static TransformationMatrix calculateDirectionalMatrix(Vector3d dir, Vector3d up) { float [] matrix = new float[16]; //Calculating as if a normal LookAt function: Vector3d forward = new Vector3d(dir); //Only with inverted direction and no height component. forward.setX(-forward.getX()); forward.setY(0.0f); // <<< setY forward.setY(-forward.getY()); // <<< setY forward.normalize(); ...

That code snippet is probably wrong: It negates the x component of the local forward vector variable, sets the y component to 0 and afterwards negates it, and does nothing with the z component. However, the method is ... abstruse. Why do you suppress the y component first and later consider it by rotation?

If you have a direction vector (I'm assuming this means your "forward" vector), then all you need to do to create the transformation matrix is create a basis using that vector.

Pseudocode:

vector3 tempUp = [0, 1, 0]
vector3 right = forward.cross(tempUp)
vector3 up = right.cross(forward)

matrix3x3 rotationMat =

[ right.x forward.x up.x ]
[ right.y forward.y up.y ]
[ right.z forward.z up.z ]

(haven't double checked but i'm almost sure this is correct)

EDIT: this all depends on whether you're using a right-handed or left-handed system (column-major or row-major matrices)

Well, not to be offending, but ...

1. A rotation matrix must be orthonormal. I.e. the length of each column / row vector must be 1. The cross product gives you a vector with the length
| a x b | = | a | * | b | * sin( <a,b> )
that is generally not 1 due to the sine, even if the participating vectors are of unit length. So some re-normalization is missed in your code!

E.g.

vector3 tempUp = [0, 1, 0]
forward.normalize();
vector3 right = forward.cross(tempUp)
right.normalize();
vector3 up = right.cross(forward)
up.normalize(); // (should not be necessary)

2. You've forgotten to mention that the matrix is for column vector use. "column-major" and "row-major" are terms that describe how the elements of a 2D matrix construct are arranged in linear (i.e. 1D) memory. Your code does no deal with this aspect in any way. Instead you meant "column vector use" vs. "row vector use".

3. How does "this all depends on whether you're using a right-handed or left-handed system" ?

4. Right-/left-handedness and matrix layout has absolutely nothing in common.

##### Share on other sites
Not offended in any way

1. Oops... I forgot to normalize the vectors... Thanks!

2. The handedness affects the order in which you do the cross product

3. By row-major and column-major I meant the same thing as row-vectors and column-vectors (I've always heard of the term row-major and column-major referred to matrices)

##### Share on other sites

Not offended in any way

Thanks

2. The handedness affects the order in which you do the cross product

Assuming you compute the cross-product of e[sub]x[/sub] and e[sub]y[/sub], i.e. the unit vectors in x and y direction.
e[sub]x[/sub] x e[sub]y[/sub] = [ 1 0 0 ][sup]t[/sup] x [ 0 1 0 ][sup]t[/sup] = [ 0 0 1 ][sup]t[/sup]
what give you the unit vector in z direction. No dependency of a handedness, because [ 0 0 1 ][sup]t[/sup] is correct in both systems!

If you would instead compute it in reverse order
e[sub]y[/sub] x e[sub]x[/sub] = [ 0 1 0 ][sup]t[/sup] x [ 1 0 0 ][sup]t[/sup] = [ 0 0 -1 ][sup]t[/sup]
you would get a wrong result!

3. By row-major and column-major I meant the same thing as row-vectors and column-vectors (I've always heard of the term row-major and column-major referred to matrices)

Using column or else row vectors is important for the matrix product. The correspondence between 2 matrices is the transpose:
( M * v )[sup]t[/sup] = v[sup]t[/sup] * M[sup]t[/sup]
where the left side uses a column vector v and the right side its row vector equivalent. Notice that the order is reverse, and notice that the vector / matrix is transposed compared to the original one.

On the other hand, row major layout means that a matrix
[ a b ]
[ c d ]
is stored number sequence
{ a b c d }
in memory, while the same matrix stored using column major layout looks like
{ a c b d }
This issue has nothing to do with matrix math but simply with the need for computer programs and/or file formats to serialize the 2D data of a matrix.

##### Share on other sites

That code snippet is probably wrong: It negates the x component of the local forward vector variable, sets the y component to 0 and afterwards negates it, and does nothing with the z component. However, the method is ... abstruse. Why do you suppress the y component first and later consider it by rotation?

Well Indeed I made a typo. The part:
forward.setY(-forward.getY());is not needed. (Fixed it BTW )

I remove the Y component, because the upper method didn't provide proper rotation for it. So effectively I've split the operation into two rotations and then I multiply the resulting matrices. The method is not very straight forward but provides correct results. I'd gladly change it I if could find something simpler that calculates correctly.

Although I haven't noticed so far, I think there are errors in my LookAt function. AFAIK the resulting matrix should be orthonormal and the scaling effect after transposition suggests it is not. I must look into it. However I would be very happy if You could help me. Here is the code:

 public static TransformationMatrix calculateLookAtMatrix(Vector3d eye, Vector3d center, Vector3d up) { float [] matrix = new float[16]; Vector3d forward = Vector3d.sub(center , eye); forward.normalize(); Vector3d side = Vector3d.cross(forward , up); side.normalize(); Vector3d plane_up = Vector3d.cross(side , forward); plane_up.normalize(); matrix[0] = side.getX(); matrix[1] = plane_up.getX(); matrix[2] = -forward.getX(); matrix[3] = 0.0f; matrix[4] = side.getY(); matrix[5] = plane_up.getY(); matrix[6] = -forward.getY(); matrix[7] = 0.0f; matrix[8] = side.getZ(); matrix[9] = plane_up.getZ(); matrix[10] = -forward.getZ(); matrix[11] = 0.0f; matrix[12] = 0.0f; matrix[13] = 0.0f; matrix[14] = 0.0f; matrix[15] = 1.0f; Vector3d neweye = new Vector3d(eye); neweye.reverse(); TransformationMatrix ret = new TransformationMatrix(matrix); ret.multiply(TransformationMatrix.calculateTranslationMatrix(neweye)); return ret; } 
thanks a lot for the help

##### Share on other sites

vector3 tempUp = [0, 1, 0]
vector3 right = forward.cross(tempUp)
vector3 up = right.cross(forward)

matrix3x3 rotationMat =

[ right.x forward.x up.x ]
[ right.y forward.y up.y ]
[ right.z forward.z up.z ]

Thanks for the suggestion. I've tried this method but I don't seem to get a correct transformation from it. I'll keep trying, though

##### Share on other sites
I definitely need to brush up on this stuff to have it clear in my head. Thanks haegarr, hopefully we've helped the OP

@Yezu666,

##### Share on other sites

Although I haven't noticed so far, I think there are errors in my LookAt function. AFAIK the resulting matrix should be orthonormal and the scaling effect after transposition suggests it is not. I must look into it. However I would be very happy if You could help me. Here is the code:

Please bear in mind that some aspects of the implementation are not clear yet. So I must guess some things...

public static TransformationMatrix calculateLookAtMatrix(Vector3d eye, Vector3d center, Vector3d up) { float [] matrix = new float[16]; Vector3d forward = Vector3d.sub(center , eye); forward.normalize(); 
I assume that Vector3d.sub(a, b) computes a-b (in this order).

 Vector3d side = Vector3d.cross(forward , up); side.normalize(); Vector3d plane_up = Vector3d.cross(side , forward); plane_up.normalize(); 
Normalizing "plane_up" is not strictly necessary, because both arguments "side" and "forward" have unit length and "side" is guaranteed to be orthogonal to "forward".

 matrix[0] = side.getX(); matrix[1] = plane_up.getX(); matrix[2] = -forward.getX(); matrix[3] = 0.0f; matrix[4] = side.getY(); matrix[5] = plane_up.getY(); matrix[6] = -forward.getY(); matrix[7] = 0.0f; matrix[8] = side.getZ(); matrix[9] = plane_up.getZ(); matrix[10] = -forward.getZ(); matrix[11] = 0.0f; matrix[12] = 0.0f; matrix[13] = 0.0f; matrix[14] = 0.0f; matrix[15] = 1.0f; 
Now things become a bit complicated.

1. You're negating (solely) the forward direction, so your camera is defined to look along its local negative z direction, right?

2. Because you're about to compute the transposed matrix, from the indexing I conclude that you're using the column major layout, right? I mean that the matrix indices are arranged like so:
[ 0 4 8 12 ]
[ 1 5 9 13 ]
[ 2 6 10 14]
[ 3 7 11 15]

If that is right it would further mean that you are using column vectors.

 Vector3d neweye = new Vector3d(eye); neweye.reverse(); TransformationMatrix ret = new TransformationMatrix(matrix); ret.multiply(TransformationMatrix.calculateTranslationMatrix(neweye)); 
The ret.multiply computes probably R[sup]t[/sup] * T( -eye ) here. This order would be correct if and only if you're using column vectors. Do you do so? Unfortunately, nothing in the shown code gives a clear criterion whether you do so.

 return ret; } 
Nothing to say here

##### Share on other sites

2. The handedness affects the order in which you do the cross product

Actually, (spatial) handedness has no effect on how the cross product is computed or how the arguments should be ordered.

3. By row-major and column-major I meant the same thing as row-vectors and column-vectors (I've always heard of the term row-major and column-major referred to matrices)[/quote]
Although these terms are commonly conflated, they refer to two completely different and unrelated things (as haegarr explained above).

##### Share on other sites
Thanks jyk and haegarr for clearing this up

EDIT: can you go into a little more detail please?

From Wolfram Mathworld... http://mathworld.wolfram.com/CrossProduct.html

It says that the way the cross-product is computed there assumes the right-hand rule. Now I'm confused.

##### Share on other sites

EDIT: can you go into a little more detail please?

From Wolfram Mathworld... http://mathworld.wol...ossProduct.html

It says that the way the cross-product is computed there assumes the right-hand rule. Now I'm confused.

I'm not sure why that specification is made (perhaps it's because the example in the diagram is with respect to a right-handed system).

In any case, the cross product is computed in the same way regardless of handedness; the 'right-hand rule' and 'left-hand rule' are just mnemonics to remember in which direction the cross product will point in a coordinate system with a given handedness.

##### Share on other sites
yeh i need it! direction of cross product lololol

how can you be sure that direction is correct lol