The problem is in the special case where the two vectors are collinear, but facing opposite directions. Refer to line 00301 in the code snippit below, where d approaches -1:
Code: Select all
00296 shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
00297 {
00298 btVector3 c = v0.cross(v1);
00299 btScalar d = v0.dot(v1);
00300
00301 if (d < -1.0 + SIMD_EPSILON)
00302 return btQuaternion(0.0f,1.0f,0.0f,0.0f); // just pick any vector
00303
00304 btScalar s = btSqrt((1.0f + d) * 2.0f);
00305 btScalar rs = 1.0f / s;
00306
00307 return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
00308 }
When I wrote the game gem i focused more on explaining how the half angle formulas could be used to make a robust implemetation as v1 and v0 converged to the same vector - a much more common case. I mention the opposite case (v0=-v1) but didn't include all the details or provide a proper implementation in the code. I probably should have discussed this more. I suspect there are a lot of implementations out there that dont quite handle this properly. Perhaps this post should also go into bullet's general discussion forum too.