以编程方式角色化 HIKCharacter

以下操作过程使用在 HumanIK API 中提供的函数,以编程方式创建新的 HIKCharacter 并设置其角色化。

在您尝试在自己的代码中执行该角色化过程之前,应先阅读并理解本文档以下部分中的内容:

步骤 1. 创建 HIKCharacterDefinition

必须为角色创建 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;
} 

在特定情况下还会使用 HIKNodeUsedHIKNodeNotUsed 的两个备选方法:

您的 HIKCharacterDefinition 必须至少启用 HumanIK 所需的全部十五个节点。请参见将关节映射到 HumanIK 节点和效应器

步骤 2. 根据 HIKCharacterDefinition 创建 HIKCharacter

要根据在初始化步骤中创建的 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 中设置了 HIKNodeUsedHIKNodeLimitsHIKNodeParentOffset 标志的关节。

如果 HIKCharacterCreate() 函数返回空指针,则最有可能是许可证密钥或角色定义出现问题。请参见疑难解答以获取帮助。

步骤 3. 设置 HIKCharacter 的几何体

此时,您已经具有一个已初始化一组关节(如踝部、膝部、肘部等)的角色。但是,您必须进一步定义角色的骨架,方法是在角色以默认 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 变换矩阵表示的平移、方向和缩放值。有关该矩阵的详细信息,请参见变换矩阵

步骤 4. 设置自由度(可选)

如果要设置角色节点的自由度,以限制其旋转到不适当的或不切实际的外形,则必须在此时设置限制。

请注意,只能为通过在 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);

有关详细信息,请参见自由度

步骤 5. 完成角色化

HIKCharacter 使用的每个节点提供适当的平移、旋转和缩放值后,必须通过调用 HIKCharacterizeGeometry() 函数,并将指针传递到 HIKCharacter 来完成角色的几何体。

例如:

bool result = HIKCharacterizeGeometry(MyChar);
if (result == false)
{ 
    // The characterization was unsuccessful; handle the error. 
}

完成角色化后,HIKCharacter 即可供使用。继续执行在初始化中列出的步骤,以设置您的角色所需的其他 HumanIK 对象。

如果 HIKCharacterizeGeometry() 函数返回 false,则最有可能是角色的 T 形站姿出现问题。请参见疑难解答以获取帮助。