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!
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.
Your question was asked and answered on math.stackexchange.com A summary of it is:
- calculate the axis of rotation as the cross product of the 2 vectors.
- 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:
- normalize your vectors (yours are already normalized)
- calculate the rotation angle as -1 * dot product of the 2 vectors.
- calculate the axis as the cross product of the 2 vectors.
- 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.
- calculate the rotation matrix from the quaternion, but only extract inner 3x3 instead of using the entire 4x4 matrix.
© 2022 - 2024 — McMap. All rights reserved.