Archived

This topic is now archived and is closed to further replies.

Needs help with my CCD system

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

Recommended Posts

I just got my CCD IK implementation working and I have a question about it. When I apply the algorithm to something like a character''s arm, you end up having twisting on some of the bones. While the system is technically solving the system (ie the bones are indeed pointing towards the goal point), the result looks poor. For implemeting a head-look-at solver, I ran into the same thing, however I was able to solve the sitaution by taking my output and rotating the bone about it''s axis so that it points as much "up" as it can (if that makes sense). However, with an arbitrary bone linkage, such as a characters arm, I don''t see how I can use the same kind of cheat. This is my main concern.

Share on other sites
Well, I came up with a solution, but it requires a whole lot of extra math... here''s my ik algorithm:

tQuatBone *IKBones[3];
float initialBoneRotation[3];
int itteration, bone, i;
tPoint3 affectorPoint;
tPoint3 targetVector, goalVector, orthoAxis;
tPoint3 u, v, w;
tQuaternion q, inverseParent, baseRotation;
float theta;

if (!fTargetPoint)
return kFalse;

IKBones[0] = skeleton->mGetBone ("L Wrist01");
IKBones[1] = skeleton->mGetBone ("L ForeArm02");
IKBones[2] = skeleton->mGetBone ("L UpperArm02");

// get our initial rotations
for (bone = 0; bone < 3; bone++)
{
u.mSet (0, 1, 0);
v.mSet (0, 1, 0);
w.mSet (1, 0, 0);
IKBones[bone]->fParent->fOutput.mTransform (u);
IKBones[bone]->fParent->fOutput.mTransform (w);
IKBones[bone]->fOutput.mTransform (v);

w = w.mCrossProduct (u);
theta = acos (u.mDotProduct (v));

if (w.mDotProduct (v) > 0.0f)
initialBoneRotation[bone] = theta;
else
initialBoneRotation[bone] = 3.14159 + (3.14159 - theta);
}

for (itteration = 0; itteration < 10; itteration++)
{
for (bone = 0; bone < 3; bone++)
{
affectorPoint.mSet (IKBones[0]->fLength, 0, 0);
IKBones[0]->fOutput.mTransform (affectorPoint);
affectorPoint += IKBones[0]->fFinalWorldPosition;

targetVector = affectorPoint - IKBones[bone]->fFinalWorldPosition;
targetVector.mNormalize ();

goalVector = *fTargetPoint - IKBones[bone]->fFinalWorldPosition;
goalVector.mNormalize ();

orthoAxis = targetVector.mCrossProduct (goalVector);
orthoAxis.mNormalize ();

q.mCreateRotation (orthoAxis, acos (targetVector.mDotProduct (goalVector)));
inverseParent = IKBones[bone]->fParent->fOutput.mInverse ();
q = q * IKBones[bone]->fOutput;
IKBones[bone]->fBaseOutput = inverseParent * q;

for (i = bone; i >= 0; i--)
IKBones->mUpdateBone ();
}
}

// now fix up the rotations based on the initial rotations (for all bones but the lowest bone)
for (bone = 1; bone >= 0; bone--)
{
u.mSet (0, 1, 0);
v.mSet (0, 1, 0);
w.mSet (1, 0, 0);
IKBones[bone]->fParent->fOutput.mTransform (u);
IKBones[bone]->fParent->fOutput.mTransform (w);
IKBones[bone]->fOutput.mTransform (v);

w = w.mCrossProduct (u);
theta = acos (u.mDotProduct (v));

if (w.mDotProduct (v) > 0.0f)
q.mCreateRotation (1, 0, 0, -theta + initialBoneRotation[bone]);
else
q.mCreateRotation (1, 0, 0, -(3.14159 + (3.14159 - theta)) + initialBoneRotation[bone]);

IKBones[bone]->fBaseOutput *= q;

// send this down the heirarchy
for (i = bone; i >= 0; i--)
IKBones[i]->mUpdateBone ();

}

// treat the lowest bone special
{
tPoint3 forward, up, right, idealUp;

forward.mSet (1, 0, 0);
up.mSet (0, 1, 0);
idealUp.mSet (0, 0, 1);

IKBones[2]->fOutput.mTransform (forward);
IKBones[2]->fOutput.mTransform (up);

idealUp -= forward * idealUp.mDotProduct (forward);
idealUp.mNormalize ();

right = idealUp.mCrossProduct (forward);

if (up.mDotProduct (right) > 0.0f)
q.mCreateRotation (1, 0, 0, acos (up.mDotProduct (idealUp)));

else
q.mCreateRotation (1, 0, 0, -acos (up.mDotProduct (idealUp)));

IKBones[2]->fBaseOutput *= q;
IKBones[2]->mUpdateBone ();
}

I spend a whole bunch of time fixing the bone-spinning... is there a bette way to do this?

1. 1
2. 2
Rutin
19
3. 3
4. 4
5. 5

• 9
• 9
• 9
• 14
• 12
• Forum Statistics

• Total Topics
633294
• Total Posts
3011242
• Who's Online (See full list)

There are no registered users currently online

×