I’m updating this first post with a link to my test .blend. Here it is:
QuaternionTest_254_Final.blend
The implementation is a bit different from the method outlined in the post below, but is now fully functional. See my later post for a full description.
Original post follows:
I’ve been away from Blender for a while so that the 2.5 series API can stabilise a bit, but have recently become inspired to attack the rag doll mesh deform issue again.
I’ve searched around and it seems that there is still no facility to deform a mesh using physics (like blowing up npcs and having them crash into walls and draped over scenery etc.). If there is any progress on this elsewhere then I would appreciate a link.
My theory is to construct a rigid body network that corresponds to the structure of an armature. It would haveone rigid body for each bone with rigid body joints connecting the netwok into an amature-like structure on which physics calculations can be run When the npc is killed there will be a trigger that stops all actions on the armature, tuns off the regular object collision and activates the rigid body structure. The rigid bodies that are linked together will respond to physics and the environment like a rag doll. Since each rigid body corresponds to a bone in the armature, the rotation of each rigid body can be used to set the rotation of it’s corresponding bone. This would drive the armature and hence deform the mesh using “rag doll physics”.
The main issue with this approach is that bone rotations can be get/set only in bone space. The orientation of a bone’s space is dependent on it’s initial orientation and how that orientation has been rotated by each bone closer to the root bone.
ie. The rotation of the foot bone is given relative to the bone space of the foot bone, the bone space of the foot bone has been rotated by the lower leg bone, the lower leg bone has in turn been rotated by the upper leg and the hip before it reaches the root bone at the end of the chain.
Taking all this into account, I have made some notes. Any thoughts on this would be appreciated.
The issue is each bone’s orientation is given in it’s bone space. The bone space has been rotated from it’s rest orientation by each bone in the hierarchy down to the root bone.
Need to find the rotation of each bone in bone space.
#######################################
Formulae used:
To apply a rotation use the sandwich product:
Qo0 = quaternion representing starting orientation
Qo1 = quaternion representing resulting orientation after first rotation
Qo2 = quaternion representing resulting orientation after first rotation then second rotation
Qr1 = quaternion representing first rotation to be applied
Qr2 = quaternion representing second rotation to be appliedFirst rotation: Qo1 = Qr1 * Qo0 * Qr1.inverse Second rotation: Qo2 = Qr2 * Qo1 * Qr2.inverse
>> Qo2 = Qr2 * (Qr1 * Qo0 * Qr1.inverse) * Qr2.inverse
>> Qo2 = (Qr2 * Qr1) * Qo0 * (Qr1.inverse * Qr2.inverse)>> Qo2 = (Qr2 * Qr1) * Qo0 * (Qr2 * Qr1).inverse
(Note reversal of Qr1 and Qr2 in the right hand of the sandwich product when taking the inverse of both components together.) Subsequent rotations can be applied in the same way, see combining rotations below.
Combining rotations:
R = total rotation
R0 = root bone’s rotation
R1 = first bone’s rotation
RN = rotation of Nth boneR = R(N-1) * ... * R1 * R0 R.inverse = R0.inverse * R1.inverse * ... * R(N-1).inverse (As required for sandwich product.)
Note:
For unit quaternions, as used to represent rotations, the conjugate is equal to the inverse. Since it
is a faster operation to find the conjugate compared to finding the inverse and all quaternions are unit,
quaternion.conjugate will be used instead of quaternion.inverse in the final code.
#######################################
Procedure:
1>> Find orientation of bone space in the global frame. This is not provided by the game engine so needs to be calculated.
Orientation of bone space can be determined by applying all rotations of all parent bones in the global frame to the rest orientation of the bone in the global frame.
spaceRotation represents the rotation required to transform the bone space from rest to it’s current orientation.
spaceRotation(of bone N space) = bone(N-1)rot * ... * bone1rot * bone0rot boneSpaceOrientation = spaceRotation * restOrientation * spaceRotation.inverse
2>> Find rotation from rest in the global frame by applying the inverse of the rest orientation to the current orientation. This will rotate the current orientation so that the deviation from the identity will represent the rotation from the rest position in the global frame.
rotationFromRest = restOrientation.inverse * currentOrientation * restOrientation.inverse.inverse The inverse of an inverse gives the original value so simplifies to:
>> rotationFromRest = restOrientation.inverse * currentOrientation * restOrientation
3>> Apply orientation of bone space to rotation from rest to convert rotation into bone space.
boneRotation = boneSpaceOrientation * rotationFromRest * boneSpaceOrientation.inverse
#######################################
Final notes:
All of this code is required because bone rotations can only be set in bone space.
This procedure would be greatly simplified by the facility to get/set bone orientations in global space in addition to the current single option of bone space. If coded into the game engine in C/C++ this would probably have a far faster operation speed. Using the current orientation of the rigid body object whose rest orientation corresponds to the rest orientation of the bone, it would be a simple matter of using the following line of code for each rigid body/bone pair to apply the ragdoll effect to the armature/mesh: bone1.worldOrientation = obj1.worldOrientation
Edit:
To clarify…
restOrientation
is the rest orientation of both a bone and it’s corresponding rigid body object in the global frame of reference (world space).
currentOrientation
is the current orientation of a rigid body object that will be used to calculate the rotation of the corresponding bone in the global frame.
spaceRotation
is the combined rotations of all bones from the root to the curent bone being considered in the global frame.
rotationFromRest
is the rotation required to rotate a rigid body object from it’s rest orientation to it’s current orientation.
boneSpaceOrientation
is the orientation of a bone’s space in the global frame of reference. If a bone had no rotation in it’s own bone space, this would be it’s world orientation. We need to set the bone’s rotation relative to this orientation.
boneRotation
is the whole point of the exercise. This is the rotation in it’s own space that a bone has to have in order to have it’s correct final orientation that corresponds to the orientation of it’s rigid body companion object.