Bones and Skeletons |
The IFXSkeletonModifier class manages information about all bones that form a skeleton. This information comprises:
Basic bone information, such as size, rotation, name, parent, and constraints.
Bone weight information, which links each bone to zero or more vertices in the IFXMeshGroup that represents the model's mesh. (The weight indicates how strongly a bone influences a vertex.)
Note: You do not need to worry about populating the IFXSkeletonModifier with this data, as it is handled by the IFXAuthorGeomCompiler class. You do, however, need to populate the IFXAuthorMesh with this information. See Scenegraph Models:Putting Authoring Data into IFXAuthorMeshGroup.
Bones and all the meshes they control must be treated as a single entity in Shockwave 3D, stored in a single IFXModelResource. To share bones between two models, create duplicate skeletal hierarchies in each IFXModelResource (including bone names), and weight the mesh vertices only to bones in the same IFXModelResource. Bones are named entities, and are matched with motion tracks of the same name in an IFXMotionResource by the IFXMixerConstruct. If the IFXMotionResource was created for a skeleton with the same hierarchy and bone names as the one in the IFXModelResource, the IFXModel pointing to that IFXModelResource will animate properly.
In short, a number of scenegraph entities from the authoring tool (a complete bone hierarchy and its associated meshes) are collapsed into a single entity in the Shockwave 3D scenegraph (an IFXModel node that points to the IFXModelResource containing all the mesh and bone data for an animated figure).
To control the animation of the mesh, a hierarchy of bone segments must be carefully aligned with the original mesh. Each bone acts as a transform, with a displacement (translation) and rotation. By convention, each bone is aligned with its local X-axis. Displacements are stored as 3-D vectors. Rotations are stored as quaternions. Each bone transform is stored relative to the endpoint of the parent bone. A bones endpoint is located on its X-axis displaced by a fixed bone length, also given for each bone. This convention means that where each bones base is attached to its parent tip (endpoint) there is zero displacement. Using relative rotations results in near linear chains of bones having near-identity rotations.
Vertex weights tie the bones and mesh together. Each vertex in the mesh is tied to as many as nine bones. Each vertex-bone relationship has a scalar weight. The total weighting of any vertex should add up to exactly 100% (numerically, all weights should add to 1.0, and be in the range of 0.0 to 1.0). Vertices that are not tied to any bone will end up fully weighted to the first bone in your skeleton, which will produce unexpected results. If a vertex is tied to only one bone, that vertex will move with that bone as though it were connected to the bone by a rigid rod. For very coarse characters, this may be acceptable, but detailed characters will show excessive stretching and twisting at the joints because these effects will often occur on single faces. Tying a vertex to multiple bones will smooth out the transition between the transforms of those bones.
Once the bones are linked to their mesh through the vertex weights and the IFXSkeletonModifier, they must be animated. The animation of a set of bones is specified by the IFXMotionResource object. An IFXNode in the Node Hierarchy Palette can be animated if it has an IFXSkeletonModifierParam object linked to it, and an IFXSkeletonModifier object linked to its IFXModelResource. The IFXSkeletonModifierParam object is used by the IFXNode to select one or more animations to play in sequence or together.
The animation tracks (IFXMotionTrack objects) in an IFXMotionResource are linked to the bones in an IFXSkeletonModifier by the IFXMixerConstruct using names in a one-to-one correspondence: if a motion in the IFXMotionResource has the same name as a bone in the IFXSkeletonModifier, then that bone will be controlled by that motion track. Bones whose names do not appear in an IFXMotionResource will not move, unless a motion is applied to the bone as a result of mapping an additional IFXMotionResource to the model at the same time through the IFXSkeletonModifierParam object associated with that scene graph node. Motions in the IFXMotionResource object that don't correspond to any named bone in the IFXSkeletonModifer object will be ignored.
See http://www.intel.com/ial/3dsoftware/doc.htm for additional information.
The transform of a scenegraph node (IFXNode) is represented in terms of its parent. If the IFXNode is a root-level node, then its scale, rotation, and translation are represented in world space at time zero. If the IFXNode is the child of another IFXNode, then its full transformation matrix is represented in terms of its parent's coordinate space, both at time zero.
The mesh coordinates of an IFXModelResource are represented in terms of the coordinate system defined by the IFXNode. All mesh vertices must be expressed in terms of this coordinate system. If the IFXModelResource consisted of two spheres, one at +Z, and one at -Z, and a center at the origin, then all the coordinates for one sphere will have positive Z coordinates, and all those for the other will have negative Z coordinates.
To capture bulk motion, that is, simple keyframed animation and not skeletal animation, of an IFXModelResource,
calculate the transformation of the object in respect to that of its
parent, both at time zero.
calculate the transformation of the object with respect to its parent, both at time T, and multiply these results by the inverse of the first transformation.
The result is the transformation of the object at time T relative to time 0, expressed in terms of its parent.
Note: This transformation refers only to the IFXNode, no matter how many bones and meshes from the scenegraph are contained in an IFXModelResource.
Sample code for capturing the keyframed motion of an object:
Matrix mInitialObjectWorldTM = object->GetTransform(0);
Matrix mInitialParentWorldTM = IdentityMatrix;
Matrix mInitialObjectTM = IdentifyMatrix;
if object->hasParent(){
mInitialParentWorldTM = object->GetParent()->GetTransform(0);
}// Transform relative to our parent at time zero - this
// gives us our reference transformation.
mInitialObjectTM = mInitialObjectWorldTM *
Inverse(mInitialParentWorldTM)// Now step through the animation.
for (currTime = startTime; currTime < endTime; currTime += stepTime)
{Matrix mCurrentObjectWorldTM = object->GetTransform(currTime);
Matrix mCurrentParentWorldTM = IdentityMatrix;
Matrix mCurrentObjectTM = IdentityMatrix;
Matrix mKeyframeTM = IdentityMatrix;if object->hasParent()
{
mCurrentParentWorldTM =
object->GetParent()->GetTransform(currTime);}
// Transform relative to the parent at time currTime
mCurrentObjectTM = mCurrentObjectWorldTM *
Inverse(mCurrentParentWorldTM);
// Motion is now relative to the transform (in
// the same coordinate system) at time zero.
mKeyframeTM = mCurrentObjectTM * Inverse(mInitialObjectTM);// Now that you have the transform for the object,
// extract the position, rotation quaternion, and scale
//and place it into an IFXMotionResource.}
The bone data that goes into the IFXModelResource specifies the reference pose of the skeleton. In reference mode, the skeleton must be positioned to fall within the mesh data in the scene to animate properly. The keyframes specifying the motion of the bones go into the IFXMotionResources.
The root bone in the IFXModelResource must also be the root node of the entire hierarchy stored within the IFXModelResource, and hence the node which defines the transform for the IFXNode that refers to this IFXModelResource. An IFXModelResource may contain only a single bone root node.
The reference rotation and position of the root bone is expressed in world space at time zero. The reference rotation and position of all non-root bones are expressed in terms of the coordinate system defined by the X-axis of their immediate parent. See Bone Rotation illustration.
When capturing animation, the root bone's current position and rotation are expressed in terms of its transformation at time zero. The position and rotation of all non-root bones are expressed in terms of the coordinate system defined by the X axis of their immediate parent, both at the current time.
In a concatenation, the rotation order is ZYX: M=rot(Z) * rot(Y) * rot(X), x'=M * x
A vertex converting from local into world space does it in reverse: twist about X, bend about Y, bend about Z.
§See asterisked (*) statement at Legal Information © 2001 Intel Corporation.