IK/Rotational math issues
by Jeff Raab · in Torque 3D Professional · 07/19/2011 (9:48 am) · 1 replies
I've been butting heads with this for quite a while, and at this point, I'm confused on the reasons the rotations don't work correctly. I've been working on implementing an IK solution, using the CCD implementation.
The math is sound and provent, but I can't get it to agree with Torque.
Below is the core guts of the CCD function itself:
We basically grab the current bone's vector, then our 'goal' vector(in testing, it's the eye node of the player model). Create a cross product, and use that to rotate the difference in degrees towards the goal.
Issues I've noted, however, is that even though the math is solid, and is definitely in-range to resolve, it behaves bizzarely. The arm(3 bones, upper arm, forearm and hand) will rotate so that the hand goes right past the eye node, diregarding the IK solution. It's set up to use a squaredDistance lookup between the hand node and the goal point of the eye node.
It has to be something with needing to go from MatrixF, to Quat(via an AngAxis) and back again.
It's likely rather obvious what the problem is, but I'm at a complete loss for what is going wrong with it at this point.
As such, I figured I'd throw this up here, and see if anyone with a bit better understanding of the 3d math in torque may have an idea.
The math is sound and provent, but I can't get it to agree with Torque.
Below is the core guts of the CCD function itself:
// create the vector to the current bone pos
curVector = curEnd - rootPos;
// create the desired bone position vector
targetVector = endPos - rootPos;
curVector.normalize();
targetVector.normalize();
cosAngle = mDot(curVector, targetVector);
if (cosAngle < 0.9999999)
{
if(cosAngle < -0.9999999)
{
//the 2 vectors are collinear
// check if we can use cross product of source vector and [1, 0, 0]
crossResult.set(0, curVector.x, -curVector.y);
if( crossResult.magnitudeSafe() < 1.0e-10 )
{
// nope! we need cross product of source vector and [0, 1, 0]
crossResult.set( -curVector.z, 0, curVector.x ) ;
}
}
else
{
// use the cross product to check which way to rotate
crossResult = mCross(curVector, targetVector);
}
crossResult.normalize();
turnAngle = mAcos(cosAngle); // get the angle
if(turnAngle > M_PI / 12) //max angle change
{
turnAngle = M_PI / 12;
}
QuatF rotation = QuatF(AngAxisF(crossResult,-turnAngle));
rotation.normalize();
MatrixF xfm = *getLocalBoneTrans(shapeInstance, ikchain->chain[link]);
QuatF qRot = QuatF(xfm);
qRot *= rotation;
TSTransform::setMatrix(qRot, xfm.getPosition(), &xfm);
storeBoneTrans(shapeInstance, ikchain->chain[link]->boneNode, xfm);
}
if (--link < 0)
link = ikchain->chain.size()-1; // START OF THE CHAIN, RESTARTWe basically grab the current bone's vector, then our 'goal' vector(in testing, it's the eye node of the player model). Create a cross product, and use that to rotate the difference in degrees towards the goal.
Issues I've noted, however, is that even though the math is solid, and is definitely in-range to resolve, it behaves bizzarely. The arm(3 bones, upper arm, forearm and hand) will rotate so that the hand goes right past the eye node, diregarding the IK solution. It's set up to use a squaredDistance lookup between the hand node and the goal point of the eye node.
It has to be something with needing to go from MatrixF, to Quat(via an AngAxis) and back again.
It's likely rather obvious what the problem is, but I'm at a complete loss for what is going wrong with it at this point.
As such, I figured I'd throw this up here, and see if anyone with a bit better understanding of the 3d math in torque may have an idea.
Associate Ross Pawley
rotation *= qRot; TSTransform::setMatrix(rotation, xfm.getPosition(), &xfm);