反向运动学解算

以下各部分概括介绍了使用 HumanIK 反向运动学解算器为角色计算新位置所需的过程。

步骤 1. 更新 HIKCharacterState

调用 HumanIK 反向运动学解算器改变角色在正向运动学动画过程中执行的移动时,通常将角色在每一帧的当前姿势作为起点。在初始化阶段创建的 HIKCharacterState 中提供此当前姿势。

计算每个效应器的到达约束集时,反向运动学解算器会考虑到此当前姿势。例如,对于角色的左膝效应器,如果将到达平移设置为 0.5,则会将角色的左膝节点放置在为左膝效应器指定的平移和此 HIKCharacterState 包含的左膝节点平移之间的中途。请参见Reach

HumanIK 提供了多个选项,用于同步 HIKCharacterState 的节点与游戏引擎中角色关节的当前 FK 位置和旋转。有关所有可用选项的详细信息,请参见设定和检索动画数据

一种常用方法是,在 HIKCharacterState() 中对每个节点调用 HIKSetNodeStateTQSfv() 函数。此函数需要以下参数:

例如:

HIKSetNodeStateTQSfv (MyCharacter, MyCharState, RightHandNodeId,
                                             myModel.GetTranslation(RightHandNodeId), 
                                             myModel.GetQuatRotation(RightHandNodeId), 
                                             myModel.GetScaling(RightHandNodeId));

步骤 2. 设置效应器的位置和旋转

对于每个帧,必须设置 HIKEffectorSetState 以包含每个角色肢体所需的位置和旋转。不必设置所有效应器的位置和旋转,只需设置通过为到达平移或到达旋转约束设置非零值指定为目标点的那些效应器的位置和旋转。实际上其他效应器将被反向运动学解算器忽略,它们的位置和方向对最终解没有任何影响。

可以使用以下任一方法设置效应器的位置和旋转:

直接设置效应器的位置和旋转

HumanIK 提供了多个选项,用于设置效应器的三维位置和方向。有关所有可用选项的详细信息,请参见设定和检索动画数据

一种常用方法是,在 HIKEffectorSetState 中对每个效应器调用 HIKSetEffectorStateTQSfv() 函数。此函数需要以下参数:

  • 指向 HIKEffectorSetState 的指针。
  • 要操纵的效应器的唯一 ID。此效应器 ID 可以是 humanik.h 文件中 HIKEffectorId 枚举列出的任何值。

    请注意,此效应器 ID 与创建 HIKCharacterDefinition 时指定的对应关节的节点 ID 不同。

  • 四个浮点数组成的三个独立阵列,表示效应器的平移、四元数旋转和缩放值。

HIKEffectorSetState 中设置的平移、方向和缩放值应当以 HumanIK 用于其内部计算的规格化空间来表示。对于在角色的默认 T 形站姿中不包含任何旋转或缩放偏移的节点,此规格化空间完全等效于全局空间。对于在角色的默认 T 形站姿中包含旋转或缩放偏移的节点,如果要使用效应器来为角色设置所需的方向或缩放,可能需要改为调用 HIKSetCharacterSpaceEffectorStateTQSfv() 函数。有关规格化空间的其他详细信息,请参见设定和检索 HIKEffectorSetState 中的数据

例如:

HIKSetEffectorStateTQSfv (MyEffectorSet, RightHandEffectorId, targetTranslation,
                                                              targetQuatRotation,
                                                              targetScaling);

通过 HIKCharacterState 初始化效应器集

可以在 HIKEffectorSetState 中设置效应器的位置和旋转,以匹配 HIKCharacterState 内的节点。进行此初始化之后,可以将偏移应用到选定效应器的平移和旋转。

在以下情景下,这是常用的方法:

要通过 HIKCharacterState 初始化效应器集,请调用 HIKEffectorSetFromCharacter 函数。此函数需要以下参数:

例如:

HIKEffectorSetFromCharacter (MyChar, MyEffectorSet, MyCharState, MyPropertySet);

初始化 HIKEffectorSetState 后,就可以修改每个效应器的位置和旋转,方法是使用 HIKGetEffectorStateTQSfv() 函数检索效应器的矩阵,将偏移应用到返回的值,然后使用 HIKSetEffectorStateTQSfv() 函数重新应用修改后的值。例如:

const float trans[4];
const float quatRot[4];
const float scale[4];
HIKGetEffectorStateTQSfv (MyEffectorSet, RightHandEffectorId, trans, quatRot, scale);
...  // offset trans, quatRot and/or scale values here  
HIKSetEffectorStateTQSfv (MyEffectorSet, RightHandEffectorId, trans, quatRot, scale);

步骤 3. 设置效应器的约束

可以在 HIKEffectorSetState 中为每个效应器单独控制到达平移、到达旋转、Pull 和 Resist 值。

默认情况下,这些约束中的每个约束都设置为值 0;这将导致反向运动学解算器将角色的所有关节固定在提供给解算器的 HIKCharacterState 中表示的姿势,这通常包含角色的当前 FK 姿势。要让反向运动学解算器将效应器考虑在内,必须使用以下函数为这些约束设置新值:

这些函数都需要以下参数:

例如,以下行将导致右手的一半移动到其效应器的位置,在必要时拉动身体的其余部分,同时右肘倾向于保持其原来的角度:

HIKSetTranslationActive(MyEffectorState, RightHandEffectorId, 0.5f);
HIKSetPull(MyEffectorState, RightHandEffectorId, 1.0f);
HIKSetResist(MyEffectorState, RightElbowEffectorId, 0.75f);

步骤 4. 设置解算步骤

反向运动学解算过程分为若干个步骤,其中每个步骤计算选定关节链的新位置、约束(例如“拉动”)的效果或者特殊变换(例如地板接触(请参见脚和手接触)或挤压和拉伸(请参见使用挤压和拉伸))的结果。

要确定将由反向运动学解算器执行的解算步骤,请调用 HIKSetIKSolvingStep() 函数。此函数接受两个参数:

例如:

HIKSetIKSolvingStep (MyEffectorState, HIKSolvingStepAll);

可以指定 HIKSolvingStep 枚举中列出的多个解算步骤,方法是将这些步骤与 | 运算符(按位或)连接。例如:

HIKSetIKSolvingStep (MyEffectorState, HIKSolvingStepBodyPull |

步骤 5. 设置角色特性

通过更改 HIKPropertySetState 中的配置设置,可以控制 HumanIK 反向运动学解算器的许多不同方面。

HIKPropertySetStates 通过一组连贯的默认值进行了初始化,因此不必更改任何值即可使 HumanIK 正常工作。该步骤是可选的。但是,通过设置适用于每个角色的特性值,通常可以获得更棒、更逼真的效果。这特别适用于支持标量距离值的角色特性,因为这些特性的默认值的大小是针对大约 180 个单位高的角色确定的。

有关可用于角色的配置选项以及如何设置这些选项的值的详细信息,请参见角色特性

步骤 6. 启动解算器

要启动 HumanIK 反向运动学解算器,请调用 HIKSolveForEffectorSet 函数。此函数需要以下参数:

例如:

HIKSolveForEffectorSet (MyChar, MyCharState, MyEffectorSet, MyPropertySet);

步骤 7. 检索生成的 HIKCharacterState

反向运动学解算器将其为角色生成的姿势存储在作为参数传入的同一 HIKCharacterState 中。必须在此 HIKCharacterState 中检索每个节点的平移、方向和缩放,然后将其应用回游戏引擎角色。

HumanIK 提供了多个选项,用于在 HIKCharacterState 中检索节点的三维位置和旋转。有关所有可用选项的详细信息,请参见设定和检索动画数据

检索为角色计算的姿势的一种常用方法是,在 HIKCharacterState 中对每个节点调用 HIKGetNodeStateTQSfv() 函数。此函数需要以下参数:

例如:

const float trans[4];
const float quatRot[4];
const float scale[4];
HIKGetNodeStateTQSfv (MyCharState, RightHandNodeId, trans, quatRot, scale); 
... // apply retrieved values back to game engine here 

由您决定是否将检索到的每个节点的值重新应用回游戏引擎中角色的相应关节。