以下操作过程使用在 HumanIK API 中提供的函数,以编程方式创建新的 HIKCharacter 并设置其角色化。
在您尝试在自己的代码中执行该角色化过程之前,应先阅读并理解本文档以下部分中的内容:
必须为角色创建 HIKCharacterDefinition:即确定根据该定义创建的所有 HIKCharacter 中存在的节点或关节的蓝图。
该类包含一个主要成员:mUsedNode,它是一个整数阵列,其中包含在 HIKNodeId 枚举中列出的每个可能预先确定的关节的元素。必须创建 HIKCharacterDefinition 类的实例,然后设置 mUsedNode 阵列中每个元素的值,以指示是否应在 HIKCharacterDefinition 中使用相应的节点 ID。
要将节点 ID 标记为将在 HIKCharacterDefinition 中使用,请将 mUsedNode 阵列中相应元素的值设置为 HIKNodeUsed。要将节点 ID 标记为在 HIKCharacterDefinition 中未使用,请将 mUsedNode 索引中相应元素的值设置为 HIKNodeNotUsed。
例如,以下代码示例显示一种典型方法,用来创建 HIKCharacterDefinition 并初始化要用于根据该定义创建的所有 HIKCharacter 的节点。
// 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;
} 在特定情况下还会使用 HIKNodeUsed 和 HIKNodeNotUsed 的两个备选方法:
您的 HIKCharacterDefinition 必须至少启用 HumanIK 所需的全部十五个节点。请参见将关节映射到 HumanIK 节点和效应器。
要根据在初始化步骤中创建的 HIKCharacterDefinition 来创建 HIKCharacter,请调用 HIKCharacterCreate() 函数。此函数需要以下参数:
HIKCharacter * MyChar = HIKCharacterCreate(&MyDef, &malloc, AutodeskCustomerString, AutodeskCustomerKey); if (MyChar == 0) { // the character could not be created. Handle the error here. }
新创建的 HIKCharacter 仅包含在 HIKCharacterDefinition 中设置了 HIKNodeUsed、HIKNodeLimits 或 HIKNodeParentOffset 标志的关节。
如果 HIKCharacterCreate() 函数返回空指针,则最有可能是许可证密钥或角色定义出现问题。请参见疑难解答以获取帮助。
此时,您已经具有一个已初始化一组关节(如踝部、膝部、肘部等)的角色。但是,您必须进一步定义角色的骨架,方法是在角色以默认 T 形站姿站立时提供每个关节的平移、旋转和缩放。有关该 T 形站姿的详细信息,请参见默认 T 形站姿。
通过为角色使用的每个节点调用 HIKSetCharacterizeNodeStateTQSfv() 函数,您可以提供这些默认位置和旋转。此函数需要以下参数:
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);
}
} 作为 HIKSetCharacterizeNodeStateTQSfv() 的备选方法,您可以调用 HIKSetCharacterizeNodeStatefv() 函数,它接受以 4x4 变换矩阵表示的平移、方向和缩放值。有关该矩阵的详细信息,请参见变换矩阵。
如果要设置角色节点的自由度,以限制其旋转到不适当的或不切实际的外形,则必须在此时设置限制。
请注意,只能为通过在 HIKCharacterDefinition 中向其指定 HIKNodeLimits 标志而指定的那些节点设置自由度。请参见上面的步骤以编程方式角色化 HIKCharacter。
要设置角色的自由度,请对每个所需的节点调用 HIKSetLimitsfv() 函数。有关接受的参数的详细信息,请参见 API 参考中的函数说明。请注意,自由度始终在局部空间中指定,并且必须以弧度而非度为单位。
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);
有关详细信息,请参见自由度。
为 HIKCharacter 使用的每个节点提供适当的平移、旋转和缩放值后,必须通过调用 HIKCharacterizeGeometry() 函数,并将指针传递到 HIKCharacter 来完成角色的几何体。
bool result = HIKCharacterizeGeometry(MyChar); if (result == false) { // The characterization was unsuccessful; handle the error. }
完成角色化后,HIKCharacter 即可供使用。继续执行在初始化中列出的步骤,以设置您的角色所需的其他 HumanIK 对象。
如果 HIKCharacterizeGeometry() 函数返回 false,则最有可能是角色的 T 形站姿出现问题。请参见疑难解答以获取帮助。