Get xyz angles between vectors?

11,212

If you want to get the x, y, and z angles between two vectors, take the dot product of the projections of the two vectors onto the orthogonal plane of the axis you want.

That is, if you want the z-angle between the two vectors, create xy-plane vectors of the originals. To do this, make a vector that ignores the z-component of the vectors.

vec3 u = vec3( ... ); // your input vector
vec3 v = vec3( ... ); // your other input vector
float x_angle = acos( dot( u.yz, v.yz ) );
float y_angle = acos( dot( u.xz, v.xz ) );
float z_angle = acos( dot( u.xy, v.xy ) );

Note that it doesn't matter if you use u.xz or u.zx since you would be using the dot product. Just be sure to use the same order for both vectors within the dot product. Also, lines 3 - 5 of the code here assume unit vectors as there is no mention of vector lengths in the expression.

It should also be noted that the use of acos can lead to errors for small values of the argument. To avoid this, the difference between the 2D projection vectors can be taken, and used with the atan2 function.

Edit

At the suggestion that the ultimate goal is to construct a rotation matrix to reorient other vectors with the same transformation, I suggest using the axis-angle approach (otherwise known as arbitrary axis rotations). The method involves finding the angle between the two vectors (dot product) and an appropriate rotation axis about which this angle is subtended (cross product).

First step, you want to find the angle between the two vectors using the dot product.

float angle = acos( dot( u, v ) ); // for unit vectors

Next, to find the axis of rotation, use the cross product. Knowing that the cross product will yield a vector perpendicular to both u and v, crossing them in either order will give an appropriate axis.

vec3 axis = cross( u, v ); // again, for unit vectors
// normalize this if need be

The form of the matrix you will want to use can be found under the heading of Rotation matrix from axis and angle on this Wikipedia article. I recommend storing some temporary values to make the calculation run faster.

float c = cos(angle);
float s = sin(angle);
float t = 1 - c;

Once you have this matrix constructed, simply multiply it by any vector to reapply the original transform.

Share:
11,212

Related videos on Youtube

Admin
Author by

Admin

Updated on September 14, 2022

Comments

  • Admin
    Admin over 1 year

    How can i get the x, y and z rotation values between two unit vectors? I can't use the dot product, because that gives me only one value. I want to use rotation matrices for rotating on each axis,and for those i need the angular differences on each axis. I have tried the dot product of only two components, but i got a little confused. Is there a quick and easy way for doing this? Maybe i was doing it wrong with the two component thing, but i don't know. Best would be, if anyone knows a glsl method to do this exact thing!

  • Luca
    Luca over 3 years
    for lazy people (and future me): (((c+x*x*t , x*y*t-z*s, x*z*t+y*s, 0), (y*x*t+z*s, c+y*y*t, y*z*t-x*s, 0), z*x*t-y*s, z*y*t+x*s, c+z*z*t,0), 0,0,0,1)))