When building a two step process: first creating the chains, then posing the chains. This section will explain these two steps in detail.
The reason two steps are used is root and bone orientations are difficult to set at chain creation time. Methods like X3DObject.Add2DChain or X3DObject::Add2DChain, X3DObject.Add3DChain or X3DObject::Add3DChain and ChainRoot.AddBone or ChainRoot::AddBone create bones using target positions, but calculate orientation automatically. To ensure the desired bone orientation we set poses explicitly in a separate step after the chain has been created.
When you create chains you are specifying the position of each joint in global coordinates. You specify the first two joint positions via the X3DObject.Add2DChain or X3DObject::Add2DChain or X3DObject.Add3DChain or X3DObject::Add3DChain methods and any subsequent ones to the ChainRoot.AddBone or ChainRoot::AddBone method.
While a chain is made up of separate objects, its elements are interrelated so it is much easier to import an entire chain at once rather than each element one at a time. For the initial creation of a chain using the X3DObject.Add2DChain or X3DObject::Add2DChain or X3DObject.Add3DChain or X3DObject::Add3DChain methods, you must specify positions for both the root and tip of the second bone. To add bones you must have a ChainRoot or ChainRoot object (since it is this interface which implements the ChainRoot.AddBone or ChainRoot::AddBone method). Therefore to create any chain element you require data from at least one other chain element, so it is much easier to create the chain all at once.
The third and fourth arguments in X3DObject.Add2DChain or X3DObject::Add2DChain are used to control the root's orientation and the 2D chain plane. Since you can pose each element explicitly later, you need to provide only default values for them.
NewScene( null, false ); // Set up vectors for specifying positions, etc. var l_oPosRoot = XSIMath.CreateVector3(); // Chain root l_oPosRoot.Set( -7.40740740740709E-03, -2.65333293080546, 0 ); var l_oPosEff = XSIMath.CreateVector3(); // Chain effector l_oPosEff.Set( 2.36296296296296, -0.088938533993479, 0 ); var l_oNormal = XSIMath.CreateVector3(); // Skeleton plane normal l_oNormal.Set( 0, 0, 0 ); var l_oPosEff_Bone1 = XSIMath.CreateVector3(); // Effector for 2nd bone l_oPosEff_Bone1.Set( 2.22222222222221E-02, 2.29757879483154, 0 ); var l_oPosEff_Bone2 = XSIMath.CreateVector3(); // Effector for 3rd bone l_oPosEff_Bone2.Set( 0.466666666666667, 3.54271827074025, 0 ); // Create chain var l_oChainRoot = ActiveSceneRoot.Add2DChain( l_oPosRoot, l_oPosEff, l_oNormal, si2DChainNormalDegree ); var l_oFirstBone = l_oChainRoot.Bones(0); // Add remaining bones l_oChainRoot.AddBone( l_oPosEff_Bone1, siChainBonePin ); l_oChainRoot.AddBone( l_oPosEff_Bone2, siChainBonePin );
The trick with posing chains is to avoid triggering a chain's IK solver. IK solvers are triggered whenever the position of a bone or effector is controlled, which includes anything that could change position, such as changing the position value in a property page, constraining in position, position expressions, scripted ops on the kinematics node, etc. Even setting transforms from the SDK are considered position control, and the IK evaluations that result lead to problems importing pose data onto chains.
If you set a pose while controlling position, the IK solver will evaluate and write its solution to the chain, thereby overwriting the poses that have just been set. Therefore, to ensure you are setting the correct poses on your chains you must avoid triggering a chain's IK solver.
In Softimage v3.5 or earlier the only way to avoid the IK solver was to avoid controlling positions. This was done by posing in FK(rotations) only. Chains can be posed in FK either by using the Rotate command, or by setting rotation parameters in the local or global transform. Neither of these approaches will control position so the IK solver will not overwrite the pose.
However, as of v4.0 you can actually mute the IK Solver before setting the pose.
This example continues from JScript Example: Creating Chains and Bones and demonstrates how to turn off the IK Solver before posing the chains.
// Create transform for pose (ie., if you are writing an importer this // transform would be provided instead of this one) var l_oNewPose = XSIMath.CreateTransform(); var l_oMatrix4Rot = XSIMath.CreateMatrix3(); l_oMatrix4Rot.Set( 1.0,1.0,0.0, -1.0,1.0,0.0, 0.0,0.0,-1.0 ); // Turn off IK Solver var l_oKineChainProp = l_oFirstBone.Properties( "Kinematic Chain" ); var l_oMuteOpParam = l_oKineChainProp.Parameters( "muteikop" ); l_oMuteOpParam.Value = true; // Apply the Transform l_oNewPose.SetRotationFromMatrix3( l_oMatrix4Rot ); // Turn the IK Solver back on l_oMuteOpParam.Value = false;
Except where otherwise noted, this work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License