The following procedure creates a new HIKCharacter and sets up its characterization programmatically, using functions provided in the HumanIK API.
Before you attempt to carry out this characterization process in your own code, you should read and understand the material in the following sections of this documentation:
You must create an HIKCharacterDefinition for your character: a blueprint that identifies which Nodes, or joints, will be present in all HIKCharacters created from that definition.
This class contains one main member: mUsedNodes, an array of integers that contains an element for each possible pre-determined joint listed in the HIKNodeId enumeration. You must create an instance of the HIKCharacterDefinition class, and set the value of each element in the mUsedNodes array to indicate whether or not the corresponding Node ID should be used in the HIKCharacterDefinition.
To flag a Node ID to be used in your HIKCharacterDefinition, set the value of the corresponding element in the mUsedNode array to HIKNodeUsed. To flag a Node ID as unused in the HIKCharacterDefinition, set the value of the corresponding element in the mUsedNode index to HIKNodeNotUsed.
For example, the following code example shows a typical method of creating an HIKCharacterDefinition and initializing the Nodes that will be used for all HIKCharacters created from that definition.
// first, create an array containing the Node IDs
// that represent joints you want to use. This example uses only
// the mandatory Node Ids required by HumanIK, listed below.
int gCharacterJointTotal = 15;
const int fJointIds[] = {HipsNodeId,
LeftHipNodeId,
LeftKneeNodeId,
LeftAnkleNodeId,
RightHipNodeId,
RightKneeNodeId,
RightAnkleNodeId,
WaistNodeId,
LeftShoulderNodeId,
LeftElbowNodeId,
LeftWristNodeId,
RightShoulderNodeId,
RightElbowNodeId,
RightWristNodeId,
HeadNodeId};
// Next, create an HIKCharacterDefinition object, and initialize
// its memory space to 0 (or HIKNodeNotUsed).
HIKCharacterDefinition MyDef;
memset(&MyDef, 0, sizeof(HIKCharacterDefinition));
// Finally, iterate through the array of Node IDs to be used, and
// set the corresponding element in the mUsedNodes array to
// HIKNodeUsed.
int ii;
for (ii = 0; ii < gCharacterJointTotal; ++ii)
{
MyDef.mUsedNodes[fJointIds[ii]] = HIKNodeUsed;
} Two alternatives to HIKNodeUsed and HIKNodeNotUsed are also used in specific situations:
Your HIKCharacterDefinition must enable at a minimum all fifteen Nodes required by HumanIK. See Mapping Joints to HumanIK Nodes and Effectors.
To create an HIKCharacter based on the HIKCharacterDefinition you created in step Initialization, call the HIKCharacterCreate() function. This function requires the following arguments:
HIKCharacter * MyChar = HIKCharacterCreate(&MyDef, &malloc, AutodeskCustomerString, AutodeskCustomerKey); if (MyChar == 0) { // the character could not be created. Handle the error here. }
The newly created HIKCharacter contains only the joints set with the HIKNodeUsed, HIKNodeLimits or HIKNodeParentOffset flags in the HIKCharacterDefinition.
If the HIKCharacterCreate() function returns a null pointer, you most likely have a problem with either your license key or your character definition. See Troubleshooting for help.
At this point, you have a character initialized with a set of joints such as ankles, knees, elbows, etc. However, you must further define your character’s skeleton by providing the translation, rotation and scaling of each of its joints when the character is standing in a default T-stance. For details on this T-stance, see The Default T-Stance.
You can provide these default positions and rotations by calling the HIKSetCharacterizeNodeStateTQSfv() function for each Node used by your character. This function requires the following arguments:
float trans[4]; float quat[4]; float scale[4]; for (ii = 0; ii < LastNodeId; ++ii) { if (sSuccess == fJointIds.find(ii)) { HIKSetCharacterizeNodeStateTQSfv(MyChar, ii, trans, quat, scale); } }
As an alternative to HIKSetCharacterizeNodeStateTQSfv(), you can call the HIKSetCharacterizeNodeStatefv() function, which accepts translation, orientation and scaling values expressed in a 4x4 transform matrix. For details on this matrix, see Transform Matrices.
If you want to set Degrees of Freedom on your character’s Nodes, to restrict them from rotating into undesirable or unrealistic configurations, you must set the limits at this time.
Note that you can only set Degrees of Freedom for Nodes that you have designated by assigning them the HIKNodeLimits flag in your HIKCharacterDefinition. See step Characterizing an HIKCharacter Programmatically above.
To set your character’s Degrees of Freedom, call the HIKSetLimitsfv() function for each desired Node. See the function description in the API Reference for details on the accepted parameters. Note that Degrees of Freedom are always specified in local space, and must be provided in radians, not in degrees.
const float minValues[] = {0.0f, 0.7854f, 0.0f};
const float maxValues[] = {1.571f, 1.571f, 0.0f};
const float preRot[] = {0.0f, 0.0f, 0.0f, 1.0f};
const float postRot[] = {0.0f, 0.0f, 0.0f, 1.0f};
HIKSetLimitsfv (MyCharacter1, RightKneeNodeId, minValues, maxValues, preRot, postPost, HIKActiveMinX | HIKActiveMaxX | HIKActiveMinY | HIKActiveMaxY, HIKOrderEulerXYZ);
For more information, see Degrees of Freedom.
Once you have provided appropriate translation, rotation and scaling values for each Node used by your HIKCharacter, you must finalize your character’s geometry by calling the HIKCharacterizeGeometry() function, and passing a pointer to your HIKCharacter.
bool result = HIKCharacterizeGeometry(MyChar); if (result == false) { // The characterization was unsuccessful; handle the error. }
Once you have finalized the characterization, your HIKCharacter is ready for use. Continue with the steps listed under Initialization to set up the other HumanIK objects required for your character.
If the HIKCharacterizeGeometry() function returns false, you most likely have a problem with your character’s T-stance. See Troubleshooting for help.