Ive been trying for hours now to develop an algorithm that will given two vectors: find a matrix which when multiplied with vector A results in vector B; both A and B being normalized.
Ive done tons of trigonometrie aproaches and aleways ended up with an algorithm that will work for most angles but not all.
Any ideas?
-CProgrammer
You can use the cross product of the two vectors to find the axis of rotation necessary and the angle needed for the rotation. Then all you need to do is to convert that information into a rotation matrix. (assuming three dimensions.)
That was my initial aproach as well. Basically I used the dot product to get the z rotation, then rotated vector one by that then got the y rotation and so on. The vector product was used to find out in which direction to rotate. Didnt seem to do the trick however.
Anyone have another solution? Perhaps I just have a mistake in mine, ill keep searching in the meantime.
-CProgrammer
Anyone have another solution? Perhaps I just have a mistake in mine, ill keep searching in the meantime.
-CProgrammer
The dot product is not the cross product. Your described "initial approach" is not the same as the method SiCrane suggested. In fact, I'm not seeing how you used the dot product to get just "the Z rotation." Whatever you were doing was most likely rather weird, unless I misunderstand.
Anyway:
Take the cross product of vector one (v1) and vector two (v2). This gives you a vector N that is perpendicular to the plane formed by v1 and v2; it is within this plane that we wish to rotate, thus the axis we wish to rotate about is N. Now, use the dot product to find D, the angle between v1 and v2: D = acos(v1 dot v2).
Now, we have an axis N, and an angle D. Rotating v1 around N by D will yeild v2. Both N and D constitute enough information to build an axis-angle rotation matrix.
Anyway:
Take the cross product of vector one (v1) and vector two (v2). This gives you a vector N that is perpendicular to the plane formed by v1 and v2; it is within this plane that we wish to rotate, thus the axis we wish to rotate about is N. Now, use the dot product to find D, the angle between v1 and v2: D = acos(v1 dot v2).
Now, we have an axis N, and an angle D. Rotating v1 around N by D will yeild v2. Both N and D constitute enough information to build an axis-angle rotation matrix.
A = [x, y, z]
B = [w, v, u]
Want:
M*A == B
Define:
M := [M_ij]
Then:
M*A = [
x*M_00 + y*M_01 + z * M_02,
x*M_10 + y*M_11 + z * M_12,
x*M_20 + y*M_21 + z * M_22
]
So, we want:
w == x*M_00 + y*M_01 + z * M_02
v == x*M_10 + y*M_11 + z * M_12
u == x*M_20 + y*M_21 + z * M_22
First note: If A == [0,0,0], there is no solution unless B=[0,0,0].
Without loss of generality, assume x != 0.
Set
M_00 = w/x
M_10 = v/x
M_20 = u/x
and all other entries to 0. Problem solved.
(If x is zero, and y or z is not, then simply do the analagous equivilent for a different strip of the matrix.)
Second note: While the above answer answers your question, I doubt your question is what you really want the answer to.
B = [w, v, u]
Want:
M*A == B
Define:
M := [M_ij]
Then:
M*A = [
x*M_00 + y*M_01 + z * M_02,
x*M_10 + y*M_11 + z * M_12,
x*M_20 + y*M_21 + z * M_22
]
So, we want:
w == x*M_00 + y*M_01 + z * M_02
v == x*M_10 + y*M_11 + z * M_12
u == x*M_20 + y*M_21 + z * M_22
First note: If A == [0,0,0], there is no solution unless B=[0,0,0].
Without loss of generality, assume x != 0.
Set
M_00 = w/x
M_10 = v/x
M_20 = u/x
and all other entries to 0. Problem solved.
(If x is zero, and y or z is not, then simply do the analagous equivilent for a different strip of the matrix.)
Second note: While the above answer answers your question, I doubt your question is what you really want the answer to.
Given the above posts, I'm not sure if I understand your problem entirely. If it is exactly as you said in the first post, then I beleive you are overcomplicating the problem. In general, it's trivially easy to find such a matrix M such that AM = B, but that matrix might not correspond with a rotation.
I'm assuming that you are looking for a rotation matrix, since finding any matrix is too easy. In that case there are several ways to construct the matrix. One easy way is to use quaternions, and then convert the quaternion rotation into a rotation matrix. If you have something set up for this, then this is quite easy, and is simpler and better than the iterative way that you are doing it now.
Otherwise you could find the coordinates of each vector in spherical coordinates, calculate the difference, and use the result to construct the rotation matrix. This is actually pretty much what you seem to be doing. Be careful though; taking the dot product between two vectors will tell you the cosine of the angle between the vectors in the plane that they lie on. Using the angle found in the dot product to rotate about just the z-axis, as you mentioned, will not work.
I'm assuming that you are looking for a rotation matrix, since finding any matrix is too easy. In that case there are several ways to construct the matrix. One easy way is to use quaternions, and then convert the quaternion rotation into a rotation matrix. If you have something set up for this, then this is quite easy, and is simpler and better than the iterative way that you are doing it now.
Otherwise you could find the coordinates of each vector in spherical coordinates, calculate the difference, and use the result to construct the rotation matrix. This is actually pretty much what you seem to be doing. Be careful though; taking the dot product between two vectors will tell you the cosine of the angle between the vectors in the plane that they lie on. Using the angle found in the dot product to rotate about just the z-axis, as you mentioned, will not work.
Thanks guys. Youve been very helpfull. Yes I was looking to get three actual rotation matrices but after reading these posts ive come to the conclusion that maybe its best to change what im looking for. Ive rearranged my code to work with having one rotation matrix that does the job. Im gonna try the suggestions using the vector product.
However Im not quite sure how to create a rotation matrix for an arbitrary vector N and the angle D mentioned by jpetrie.
PS: Any matrix wont work since this is for vertex transformation and that would only solve the problem for one vertex.
CProgrammer
[Edited by - CProgrammer on June 27, 2006 5:44:17 AM]
However Im not quite sure how to create a rotation matrix for an arbitrary vector N and the angle D mentioned by jpetrie.
PS: Any matrix wont work since this is for vertex transformation and that would only solve the problem for one vertex.
CProgrammer
[Edited by - CProgrammer on June 27, 2006 5:44:17 AM]
The idea is essentially equivalent to the construction of the viewing transformation matrix. A quick and dirty summary (you can find much more detailed examples of this derivation on Google if you search):
So you have an axis of rotation, R and an angle N. To apply this rotation, we first want to build a matrix that brings us into the coordinate system where the Z axis is aligned with R. Then we can apply a rotation of N about Z (using the traditional Z-axis rotation matrix). Then we want to bring the result back into our original coordinate system.
So, if M is our coordinate system transformation, then the resulting final transformation F will be F = M * R(z) * inverse(M), where R(z) is the traditional Z axis rotation matrix. All that remains is to compute M.
This is done just like the computation of the rotational portion of the view transform (in fact, its exactly the same thing). First define an "up-vector" (it need not actually point up, it just has to not be aligned with R); call this vector UP. The cross product of R and UP gives us a vector perpendicular to the plane formed by R and UP; this vector is the "X axis" of our new coordinate system. Similarly the cross product of the X axis vector we just computed and R yeilds an actual "up" vector (the "Y axis" of our new coordinate system). R is the third and final Z axis of the coordinate system.
If all these vectors are normalized, we now have an orthonormal basis for a coordinate system. The "special orthogonal matrix" property tells us that we can write the vectors as columns of the 3x3 rotational part of a matrix to get a rotation matrix that rotates us into that coordinate system. It also tells us that inverse(M) == transpose(M) for such a matrix, so we now have an easy way to compute the inverse of M (which we'll need).
Finally, we can simply do F = M * R(z) * transpose(M) to get a final transformation matrix that rotates by N about the axis defined by R.
Note that if you look around via Google, you can also find pages that both derive this transformation (probably much more eloquently and more strictly proofread than my quick write-up) and also give you a big ugly formula for what each component of the matrix works out to be. Both are equivalent, so you can use whichever you are more comfortable with.
[Edited by - jpetrie on June 27, 2006 9:18:50 AM]
So you have an axis of rotation, R and an angle N. To apply this rotation, we first want to build a matrix that brings us into the coordinate system where the Z axis is aligned with R. Then we can apply a rotation of N about Z (using the traditional Z-axis rotation matrix). Then we want to bring the result back into our original coordinate system.
So, if M is our coordinate system transformation, then the resulting final transformation F will be F = M * R(z) * inverse(M), where R(z) is the traditional Z axis rotation matrix. All that remains is to compute M.
This is done just like the computation of the rotational portion of the view transform (in fact, its exactly the same thing). First define an "up-vector" (it need not actually point up, it just has to not be aligned with R); call this vector UP. The cross product of R and UP gives us a vector perpendicular to the plane formed by R and UP; this vector is the "X axis" of our new coordinate system. Similarly the cross product of the X axis vector we just computed and R yeilds an actual "up" vector (the "Y axis" of our new coordinate system). R is the third and final Z axis of the coordinate system.
If all these vectors are normalized, we now have an orthonormal basis for a coordinate system. The "special orthogonal matrix" property tells us that we can write the vectors as columns of the 3x3 rotational part of a matrix to get a rotation matrix that rotates us into that coordinate system. It also tells us that inverse(M) == transpose(M) for such a matrix, so we now have an easy way to compute the inverse of M (which we'll need).
Finally, we can simply do F = M * R(z) * transpose(M) to get a final transformation matrix that rotates by N about the axis defined by R.
Note that if you look around via Google, you can also find pages that both derive this transformation (probably much more eloquently and more strictly proofread than my quick write-up) and also give you a big ugly formula for what each component of the matrix works out to be. Both are equivalent, so you can use whichever you are more comfortable with.
[Edited by - jpetrie on June 27, 2006 9:18:50 AM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement