Get xyz angles between vectors?
Asked Answered
I

2

13

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!

Inrush answered 2/3, 2017 at 12:0 Comment(0)
D
13

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.

Dyan answered 2/3, 2017 at 14:5 Comment(6)
this didn't quite work: i did this with u and v being the same vector, and i basicallly got the vector back (out = (0, 0, 1), in = (0, 0, 1)). it also didnt work with other vectrosInrush
What is your overall process to get a new vector? I'm curious to see what your ultimate goal is. Also, as stated above, there may be some strangeness with vectors that are the same, if you're using the acos. In Lua, for instance, I have had to clamp the input to keep from getting NaN as a result.Dyan
Okay. And my goal is to get the difference of rotation on the tree axis, so i can insert these values into rotation matrices, and using these for rotating a nother vector. Then the rotated vectors y-axia will be aligned with my other vector.Inrush
In this case, I would recommend constructing an arbitrary axis rotation matrix. Rather than performing three rotations, it can done in one with the appropriate choice of axis. I will update my answer to discuss this approach.Dyan
Ok. Thank you for your great help!Inrush
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)))Danaides
B
0

Your question was asked and answered on math.stackexchange.com A summary of it is:

  1. calculate the axis of rotation as the cross product of the 2 vectors.
  2. Then use the Rodrigues formula to calculate the rotation matrix.

I would add that alternatively, you could calculate the rotation using a quaternion for higher accuracy, at the expense of several more steps. For the quaternion method:

  1. normalize your vectors (yours are already normalized)
  2. calculate the rotation angle as -1 * dot product of the 2 vectors.
  3. calculate the axis as the cross product of the 2 vectors.
  4. calculate the quaternion (the Barfoot quaternion rather than the Hamilton quaternion) using the rotation axis and angle. Barfoot, Forbes, & Furgale 2010, "Pose estimation using linearized rotations and quaternion algebra", Acta Astronautica (2010), doi:10.1016/j.actaastro.2010.06.049. I calculated the Hamilton quaternion then converted it to the Barfoot in my own code, but one could calculate the Barfoot quaternion directly.
  5. calculate the rotation matrix from the quaternion, but only extract inner 3x3 instead of using the entire 4x4 matrix.
Bedabble answered 23/9, 2022 at 22:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.