I don't think there is an simple way to do it, but you can manually compute the transform of each body.
First you'd need to compute the
relative transform of each body in its parent's local frame. Then after rotating the palm you would compute the new world-frame transforms down each chain of linked parts always doing the parent before its children.
I've done this using an array of indices that indicate each body's parent in an array. I've got an array of btRigidBody* that represent all the bodies of the hand, and an array of parent indieces:
Code: Select all
btRigidBody bodies[NUM_BODIES_IN_HAND];
int parentIndices[NUM_BODIES_IN_HAND];
So the ith element of
parentIndices is the index into
bodies of the parent of the ith body in
bodies. Each body's parent must preceed it in the
bodies array and the topmost parent (the palm in your case?) has no parent, so it must come first in
bodies and its corresponding value in
parentIndices is
-1 which is an
invalid index.
Once you have those arrays set up (maybe you already do?) then you can iterate over them to compute current local transforms and then iterate again to compute new world-transforms.
In code it would look something like this:
Code: Select all
// BEFORE the main root body is moved to its new position
// loop over bodies to compute local transforms
btTransform localTransforms[NUM_BODIES_IN_HAND];
for (int = 1; i < NUM_BODIES_IN_HAND; ++i)
{
btRigidBody* parent = bodies[parentIndeces[i]]];
btTransform parentTransform = parent->getWorldTransform();
// NOTE: the new childWorldTransform could be computed like so:
// childWorldTransform = parentWorldTransform * childLocalTransform
// HENCE: after doing math we can derive the formula for computing the childLocalTransform:
// childLocalTransform = invParentWorldTransform * childWorldTransform
localTransforms[i] = parentWorldTransform.inverse() * bodies[i]->getWorldTransform();
}
//...
// AFTER the main root body has been moved to a new transform
// compute the new world-frame transforms of the child bodies
for (int = 1; i < NUM_BODIES_IN_HAND; ++i)
{
// using the formula:
// childWorldTransform = parentWorldTransform * childLocalTransform
bodies[i]->setWorldTransform(bodies[parentIndices[i]]->getWorldTransform() * localTransforms[i]);
}
Note that slamming the positions of bodies in Bullet risks putting them into penetration with other bodies and causing glitches when the penetration resolution code kicks in. An alternative would be to push them there by poking their velocities or applying forces, but that would be even more math. So... try just moving them first: maybe it will Just Work.