HumanIK 对象和内存管理

本部分提供有关 HumanIK 对象的内存使用的详细信息,并提供几种内置方法,用于管理由这些对象使用的内存。

对象内存要求

HumanIK 对象具有以下内存要求:

HIKCharacter

HIKCharacter 的大小取决于其配置。

  • HIKCharacter 的基础大小是 9616 个字节。
  • HIKCharacter 使用的每个节点另外需要 240 个字节。
  • 使用自由度配置的每个节点另外需要 192 个字节。
  • 具有父偏移的每个节点另外需要 48 个字节,除非该节点也具有自由度(上文指定给 DOF 的值包括一个 48 个字节的父偏移)。

您可以通过调用 HIKCharacterSize() 函数来确定现有 HIKCharacter 的内存的当前大小。此函数需要一个参数:指向 HIKCharacter 的指针。

或者,您可以通过调用 HIKCharacterDefinitionSize() 函数,在创建 HIKCharacter 之前确定其内存的预期大小。此函数需要一个参数:将用于创建 HIKCharacterHIKCharacterDefinition

HIKCharacterState

HIKCharacterState 的大小取决于其 HIKCharacter 使用多少节点。

  • HIKCharacterState 的基础大小是 144 个字节。
  • 角色使用的每个节点另外需要 96 个字节。

您可以通过调用 HIKCharacterStateSize() 函数来确定现有 HIKCharacterState 的内存的当前大小。此函数需要一个参数:指向 HIKCharacterState 的指针。

HIKEffectorSetState

每个 HIKEffectorSetState 需要 3296 个字节。

HIKPropertySetState

每个 HIKPropertySetState 需要 1936 个字节。

通过分配和取消分配内存来创建对象

HumanIK 中需要分配内存的所有函数(如HumanIK 快速入门一章中介绍的用于创建 HIKCharacterHIKCharacterStateHIKEffectorSetStateHIKPropertySetState 的函数)需要引用用于分配该内存的回调函数。您可以使用标准 malloc 函数,或使用与 malloc 遵循相同类型定义的其他任何自定义内存分配函数。

同样,HumanIK 快速入门一章中介绍的用于销毁这些对象的函数需要引用回调函数,该回调函数用于释放分配给该对象的内存资源。您可以使用标准 free 函数,或使用与 free 遵循相同类型定义的其他任何自定义内存分配函数。

例如,以下代码使用 mallocfree 创建和销毁 HIKCharacterState

HIKCharacterState* lcharacterState = HIKCharacterStateCreate(character1, &malloc);
...
HIKCharacterStateDestroy(lcharacterState, &free);

在预分配的内存中创建对象

您可以在预分配的内存缓冲区中的指定位置创建新的 HumanIK 对象,而不需要在每次创建 HIKCharacterHIKCharacterStateHIKEffectorSetStateHIKPropertySetState 时分配新内存。通过预分配单个内存池并在该缓冲区中的指定指针处创建所有相关的 HumanIK 对象,您可以将相关的 HumanIK 对象保留在连续的内存块中,从而提高性能。

要通过此方法创建对象,请调用 HIKCharacterCreateInPlace()HIKCharacterStateCreateInPlace()HIKEffectorSetCreateInPlace()HIKPropertySetCreateInPlace() 函数。这些函数与HumanIK 快速入门一章中介绍的对象创建函数需要相同的参数,但不同的是,这些函数需要指向有效内存位置的空指针,而不需要引用回调函数以分配内存。此指针必须是 16 个字节对齐的,并且缓冲区必须足够大,以便包含创建的对象。请参见上面的 HumanIK 对象和内存管理

例如:

HIKCharacterState* lcharacterState = HIKCharacterStateCreateInPlace(character1, bufferAlignedTo16);

在这种情景下,分配和取消分配内存缓冲区最有可能在 HumanIK 的外部处理;因此,通过这种方法创建对象时,通常无需通过调用清理中介绍的 HumanIK 对象销毁函数来显式销毁对象。

使用连续的内存块

为了获得最佳性能,强烈建议尽可能在单个连续的内存块中分配所有相关对象。例如,尝试在单个连续的内存块中分配 HIKCharacter 对象,该对象表示每个游戏角色,这些角色与它们使用的所有相关的 HIKCharacterStateHIKEffectorSetStateHIKPropertySetState 对象相邻。这能够使 HumanIK 解算器在读取和写入数据时需要在内存中的不同位置之间执行的跳过量减到最少。

在内存中移动对象

您可以在不同的内存位置之间自由移动 HIKCharacterHIKCharacterStateHIKEffectorSetStateHIKPropertySetState。通过此方法,您可以使用自定义流化过程将 HIK 对象加载到内存中,并且直接从自定义流中检索对象以用于游戏。

从文件创建对象

您可以从文件加载之前保存的 HIKCharacterHIKCharacterStateHIKEffectorSetStateHIKPropertySetState。有关详细信息,请参见保存和加载 HumanIK 对象