# Look-at quaternion

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

## Recommended Posts

Hi! Can some fantastic, brilliantly clever genius tell me how to make a look-at quaternion please? What I need is a quaternion that will rotate an object, e.g. an arrow, to point down a vector, assuming that with no rotation the arrow points down the z axis. It would be nice if someone knew how to specify a roll angle in radians along that vector too, however I won't push my luck now. I have got something working for now: working out the yaw and pitch angles with arctan and arcsin and passing them with the roll to my Yaw-Pitch-Roll function. However, this is very ugly accounting for where vector.X or Z is negative, and it must be much slower than it could be with all the trig involved. I will be most grateful - thanks!

##### Share on other sites
Something like this should do the trick:

// This is your identity (no rotation) axis - Z in your casevector3 IdentityAxis( 0.0f, 0.0f, 1.0f );// Compute cosine of angles between your identity axis and direction you want to faceDirection.Normalize();float CosAngle = Dot( IdentityAxis, Direction );if( CosAngle < -1.0f )    CosAngle = -1.0f;    else if( CosAngle > 1.0f )    CosAngle = 1.0f;    // Compute anglefloat Angle = acos( CosAngle );    // Compute axis to rotate about// TO DO: Check for Direction being the IdentityAxisvector3 Axis = Cross( IdentityAxis, Direction );Axis.Normalize();// We now know the angle and axis to rotate around    // This could be used to construct a quaternion or matrix etc.quaternion Q;Q.SetupFromAxisAndAngle( Axis, Angle );

##### Share on other sites
I'll try that - thanks!

##### Share on other sites
You don't need to clamp the dot product if you've got 2 normalized vectors.
Look at www.geometrictools.com in the math section I think to find a quaternion function called 'Align', which handles parellel vectors.

##### Share on other sites
Quote:
 Original post by DrGUIYou don't need to clamp the dot product if you've got 2 normalized vectors.

You have to clamp the dot product because it can result in values outside of -1 to 1, due to precision error, and then acos() will return NaN.

This is a frequent problem. If NaN is appearing in your results, the first thing to look for is the very common mistake of not clamping the parameter to acos() or asin().

##### Share on other sites
Ahhh - precision - yeeesss

##### Share on other sites
I agree with John. If you don't clamp, precision errors can cause the dot product to be < -1 or > 1 - which causes acos() to be undefined. Try if for yourself if you don't believe us :)

##### Share on other sites
Here's mine now:
/// <summary>/// Computes a quaternion that rotates unit-length vector v1 to unit-length vector v2. The rotation is about/// the axis perpendicular to both v1 and v2, with angle of that between v1 and v2. If v1 and v2 are parallel,/// any axis of rotation is used, such as the permutation (v2.Z,v2.X,v2.Y).</summary>/// <param name="v1">Normalized vector that the computed quaternion rotates from to v2.</param>/// <param name="v2">Normalized vector that the computed quaternion rotates to from v1.</param>/// <returns>A quaternion that rotates v1 to v2.</returns>public static Quaternion Align(Vector3 v1, Vector3 v2){#if DEBUG	float sqrLen1 = v1.LengthSq();	float sqrLen2 = v2.LengthSq();	System.Diagnostics.Debug.Assert(sqrLen1 > 1 - ZeroTolerence && sqrLen1 < 1 + ZeroTolerence &&	                                sqrLen2 > 1 - ZeroTolerence && sqrLen2 < 1 + ZeroTolerence,			                                                                                        MsgVecNonNormalized);#endif	// If V1 and V2 are not parallel, the axis of rotation is the unit-length	// vector U = Cross(V1,V2)/Length(Cross(V1,V2)).  The angle of rotation,	// A, is the angle between V1 and V2.  The quaternion for the rotation is	// q = cos(A/2) + sin(A/2)*(ux*i+uy*j+uz*k) where U = (ux,uy,uz).	//	// (1) Rather than extract A = acos(Dot(V1,V2)), multiply by 1/2, then	//     compute sin(A/2) and cos(A/2), we reduce the computational costs by	//     computing the bisector B = (V1+V2)/Length(V1+V2), so cos(A/2) =	//     Dot(V1,B).	//	// (2) The rotation axis is U = Cross(V1,B)/Length(Cross(V1,B)), but	//     Length(Cross(V1,B)) = Length(V1)*Length(B)*sin(A/2) = sin(A/2), in	//     which case sin(A/2)*(ux*i+uy*j+uz*k) = (cx*i+cy*j+cz*k) where	//     C = Cross(V1,B).	Vector3 bisector = v1 + v2;	bisector.Normalize();	float cosHalfAngle = Vector3.Dot(v1, bisector);	Vector3 cross;	if (cosHalfAngle > ZeroTolerence || cosHalfAngle < -ZeroTolerence) {		cross = Vector3.Cross(v1, bisector);	} else {		cross = Vector3.Cross(v1, new Vector3(v2.Z, v2.X, v2.Y));		//cosHalfAngle = 0.0f;  - already is very close		//cross.Normalize();	}#if DEBUG	float sqrLen = cross.X*cross.X+cross.Y*cross.Y+cross.Z*cross.Z+cosHalfAngle*cosHalfAngle;	System.Diagnostics.Debug.Assert(sqrLen > 1 - ZeroTolerence && sqrLen < 1 + ZeroTolerence);#endif	return new Quaternion(cross.X, cross.Y, cross.Z, cosHalfAngle);}

##### Share on other sites
Good work - I do this by creating a lookat matrix then use that matrix as a source for a quaternion.

##### Share on other sites
http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
http://www.euclideanspace.com/maths/algebra/vectors/lookat/index.htm

• 34
• 12
• 10
• 9
• 9
• ### Forum Statistics

• Total Topics
631354
• Total Posts
2999505
×