need help about "shortestArcQuat"

Post Reply
magicianfc
Posts: 1
Joined: Tue Jun 01, 2010 6:57 am

need help about "shortestArcQuat"

Post by magicianfc »

Code: Select all

SIMD_FORCE_INLINE btQuaternion 
shortestArcQuat(const btVector3& v0, const btVector3& v1) 
{
	btVector3 c = v0.cross(v1);
	btScalar  d = v0.dot(v1);

	if (d < -1.0 + SIMD_EPSILON)
	{
		btVector3 n,unused;
		btPlaneSpace1(v0,n,unused);
		return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0
	}

	btScalar  s = btSqrt((1.0f + d) * 2.0f);
	btScalar rs = 1.0f / s;

	return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
}
let's assume theta = the angle between v0 and v1.
from s = btSqrt((1.0f + d) * 2.0f), I know s =2*cos(theta/2);
so I think rs should be sin(theta/2), rs = sqrt(1-pow(s/2,2)), and last return value should
be like [x*sin(theta/2),y*sin(theta/2),z*sin(theta/2),cos(theta/2)].

but why rs = 1.0f/s ;?
andbody can give me an explaination? thank you all!
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: need help about "shortestArcQuat"

Post by Dirk Gregorius »

You can look into this slide from Essential Math: http://www.essentialmath.com/Quaternions.pps
I also recommend the book and the bunch of free material they offer here: http://www.essentialmath.com/tutorial.htm

I think the basic idea goes back to Stan Melax and was published in Game Programming Gems 1. Stan is also on the forum sometimes.
robagar
Posts: 48
Joined: Fri May 21, 2010 1:49 am

Re: need help about "shortestArcQuat"

Post by robagar »

It's one of the reasons quaternions are so useful for orientations - you can use linear interpolation to get from one orientation to another, without messing about with angles. Apart from anything else it's quick, since you don't need any trig functions.
melax
Posts: 42
Joined: Mon Apr 24, 2006 4:55 pm

Re: need help about "shortestArcQuat"

Post by melax »

magicianfc wrote: let's assume theta = the angle between v0 and v1.
from s = btSqrt((1.0f + d) * 2.0f), I know s =2*cos(theta/2);
so I think rs should be sin(theta/2), rs = sqrt(1-pow(s/2,2)), and last return value should
be like [x*sin(theta/2),y*sin(theta/2),z*sin(theta/2),cos(theta/2)].

but why rs = 1.0f/s ;?
andbody can give me an explaination? thank you all!
Note that the cross product vector is not necessarily of unit length, its proportional to the sin of theta. So rs (1/s) by itself will not be equal to sin(theta/2).
Essentially
(qx,qy,qz) = (cx,cy,cz) * sin(t/2)/sin(t)

using the half angle and circle identity formulas morphs the sin(t/2)/sin(t) into the look-ma-no-trig implementation that you see in the code.
its written up in Game programming gems 1, section 2.10. The jist of it is:

half angle identity from your calculus book: sin(t/2)=sqrt((1-cos(t))/2)
the circle identity: sin*sin+cos*cos=1

Code: Select all

 sin(t/2)    sqrt((1-cos(t))/2)
 -------- = --------------------  
 sin(t)      sqrt(1-cos(t)*cos(t))
and cos(t) you simply get from the dot product. The rest is easy to derive.

I believe an early chapter in the book Real time Rendering (Haines, Moller) has very similar derivation for the matrix equivalent.

stan
Post Reply