Jump to content
  • Advertisement
Sign in to follow this  
kfcpri

Given a direction(vector) and a wanted direction(vector), how do you get a rotation?

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Given a direction(vector) and a wanted direction(vector), how do you get a rotation, like, quaternion?? E.g. I am facing 1,0,1. And I want to face 2,5,4. How do I get the thing(either in quaternion or angle-rotating axis form) that, when applied to 1,0,1 would become 2,5,4? All I can find is telling you how to get the resulting direction with a starting direction and a rotation, but not what I mentioned. Please help.

Share this post


Link to post
Share on other sites
Advertisement
>>Given a direction(vector) and a wanted direction(vector), how do you get a rotation, like, quaternion??

Cross product!!!

Vector3 rotation_vec = Direction cross Wanted_Direction

You'd want to normalize the direction and wanted direction vectors. Then, the inverse sine (asin) will give you the angle to rotate through, and the direction that rotation_vec points in is the axis.

double angle = asinf(rotation_vec.Length());
rotation_vec.Normalize();

Quaternion quat_rotation;
quat_rotation.w = angle;
quat_rotation.xyz = rotation; //normalized at this point

That should give you a basic idea.

Share this post


Link to post
Share on other sites
Quote:


Vector3 rotation_vec = Direction cross Wanted_Direction
double angle = asinf(rotation_vec.Length());
rotation_vec.Normalize();

Quaternion quat_rotation;
quat_rotation.w = angle;
quat_rotation.xyz = rotation; //normalized at this point



tthibault, I dont think that actually works.

Taking the cross product of two normalized angles will yield another normalized vector(length always equal to one). Although this is indeed your "axis of rotation", you cannot obtain how far to rotate between the two directions by taking the length of an already normalized vector (it will always be one). I think you need ot use the cross product to find the axis to rotate on and the dot product to find out how far to rotate along this axis.

This is the code I would use:



// Note: Directions should be normalized
DirStart.Normalize();
DirEnd.Normalize();

// Find axis to rotate along
VECTOR3 rotAxis = DirStart.Cross(DirEnd);

// Use dot product and arccos to detrmin how far to rotate along previous axis
float angle = acos( DirStart.Dot(DirEnd));

// and borrowing from tthibault to fill in a quaternion...
quat_rotation.w = angle;
quat_rotation.xyz = rotAxis;

// or you can use something like this in direct3d to build a rotational matrix
D3DMatrixRotationAxis(rotMat, &axis, angle);


Hope this helps

Share this post


Link to post
Share on other sites
The dot-product shows the correspondence
a . b = |a| * |b| * cos( < a,b > )

The cross-product shows the correspondence
|a x b| = |a| * |b| * |sin( < a,b > )|

So, even if both input vectors show unit length, the length of the resulting vector (in the case of the cross-product) _is_ depending on the included angle. Else a cross-product of self
a x a
were not able to disappear for any non zero length vector. But, looking at the computation formula for the cross-product, one can see that e.g.
(a x a)x := ay*az - az*ay
(and similarly for y and z) always disappears.

Share this post


Link to post
Share on other sites
In addition to the axis-angle method, there are some other methods for directly computing the quaternion that rotates one vector onto another. It's covered in one of the first two GPG books, but there's an even nicer algorithm that I've seen online (among other things, it doesn't require the input to be unit length).

One nice thing about the 'direct' methods is that unlike the axis-angle methods you don't have to handle near-aligned vectors (parallel and pointing in the same direction) as a special case.

I just googled for the algorithm I had in mind, but couldn't find it; I'm pretty sure though that it's discussed somewhere on this site.

Oh, and here's one more method; it does require unit-length input, but handles near-aligned vectors uniformly:
vector3 mid = normalize(v1+v2);
q.set(cross(v1,mid),dot(v1,mid));
(I may or may not have gotten that right...)

[Edit: Fixed error in code.]

[Edited by - jyk on May 30, 2006 11:03:47 AM]

Share this post


Link to post
Share on other sites
>>Taking the cross product of two normalized angles will yield another normalized vector(length always equal to one)

Wait, no, it still works...

|A x B| = |A| * |B| * sin(theta)


if A and B are have a length of 1, you just take the asin of the length, getting theta.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!