最新文章
泰课在线 | 微信拼团成功后如何获取课程?
08-09 17:57
Unity教程 | 使用ARKit为iOS开发AR应用
07-31 17:23
Unity Pro专业版7折订阅四选一工具包之VR开发与艺术设计
07-28 11:47
网友使用虚幻UE4实现CAVE 多通道立体渲染的沉浸式环境
07-27 11:57
VR晕动症调查:未来5年内大部分VR晕动症将得到解决
07-27 11:26
AMD CEO:未来3-5年最重要 希望5年达1亿VR用户
07-27 10:44
骨架节点索引揭秘
在处理动画部分的代码时,我们常常会遇到“骨骼索引(bone index)”。由于实际上存在几种不同类型的骨骼索引,所以刚开始接触动画相关代码时,很容易感到困惑。因此,本文将详细解释为何会有这几种不同的骨骼索引,以及它们之间的区别。
三种主要的骨骼索引
一共有三种主要的骨骼索引,在浏览动画相关代码时,理解它们是十分必要的。它们分别是:
- 网格体骨骼索引(Mesh Bone Index)
- 骨架骨骼索引(Skeleton Bone Index)
- 压缩姿势骨骼索引(FCompactPoseBoneIndex)
网格体骨骼索引(Mesh Bone Index)
网格体骨骼索引是骨架网格体(SkeletalMesh)的一部分,其中包含了所有关节、连接及依赖顺序,并且在渲染 SkeletalMesh 时会被使用。若要查看这个网格体骨骼索引,只需将导入的 SkeletalMesh 在 Persona 中打开,就能看到其所包含的所有关节信息。
通过网格体骨骼索引,我们可以访问 SkeletalMeshComponent 中的 SpaceBases 或 LocalAtoms。
骨架骨骼索引(Skeleton Bone Index)
既然网格体骨骼索引是 SkeletalMesh 的一部分,那么骨架骨骼索引又是什么呢?如果您使用过 Persona,应该已经了解 USkeleton 这类资源。这类资源会在导入 SkeletalMesh 时被创建,或者在指定一个已存在的 SkeletalMesh 时被创建。USkeleton 是一个 USkeletalMesh 所有关节的集合。如果您不清楚为何骨架中包含多个网格体关节,可以查看 Wes Bunn 的这个视频,其中有详细的解说。
在虚幻引擎 4 中,USkeleton 资源为骨架的每个骨骼节点包含了一个参考姿势。骨架骨骼索引就是这些骨骼列表的索引。在每个动画序列数据中,记录着内部的索引和骨架骨骼索引的关系。我们利用这些关系为正确的骨骼节点播放正确的动画数据。然而,这也带来了一个问题:当骨架发生改变时,我们必须调整动画序列帧里的数据信息。这意味着修改骨架数据时,相应的动画数据会被标记为 “Dirty” 并需要重新保存。
最初的计划是只使用 USkeleton 来解压动画数据,并确保解压后的数据和相应 SkeletalMeshComponent 能够正确对应。乍一看,这是个不错的想法,但实际上并不可行。因为我们需要在 SkeletalControls 工作时就解压模型数据,例如,当使用 IK 来处理多个物体时,骨架的骨骼节点位置数据就失去了意义。
需要注意的是,骨架的骨骼参考姿势的变化数据仅在动画重定向时使用。
如果在 Persona 中打开一个骨架,可能会看到如下信息:默认情况下,会显示所有骨骼,这些是 USkeleton 中的骨骼。如果选择了 “Show Mesh Bone” 后,将只会显示当前预览的模型所具有的骨骼信息。由此可见,USkeleton 的骨骼索引和 USkeletalMesh 的骨骼索引并不一致。
压缩姿势骨骼索引(FCompactPoseBoneIndex)
FCompactPoseBoneIndex 是一组只能用于 FCompactPose 的索引。FCompactPose 是运行时的骨骼设置组合,它是一组连续的列表,只包含当前模型 LOD 下的关节信息。当存在多个 LOD 时,可以对一些骨骼节点进行优化。在 FCompactPose 之前,曾使用过 branch,但由于 branch 的不可预测性会带来性能上的问题。而 FCompactPoseBoneIndex 能让我们避免使用 Brancher 来遍历。
FCompactPoseBoneIndex 本质上是一个整型,其具有自己的类型定义主要是为了提高代码的明确性。如果一个函数使用这个类型作为参数,或者返回这个类型,我们就能清楚地知道这里是骨骼索引在起作用。同时,这也意味着不会错误地调用函数,例如在原本应该调用其他索引的地方调用了 compact 索引,或者在应该调用 compact 索引的地方调用其他索引,编译器会检查并发现这类错误。
我们核心的动画代码都会用到 FCompactPose。在 API 上,这三种类型的骨骼索引都会被使用。可以在 USkeleton 中找到 SkeletalMesh 和 Skeleton 互相转换的大部分 API(FSkeletonToMeshLinkup)。
总结
- 网格体骨骼索引(Mesh Bone Index):用于 SkeletalMeshComponent 的 SpaceBases 或 LocalAtoms 中,是网格体的骨骼索引。
- 骨架骨骼索引(Skeleton Bone Index):是所有 SkeletalMesh 的关节集合,用于动画数据跟踪索引,动画数据根据这个索引来更新数据。
- FCompactPoseBoneIndex:是所有关节的子集,在 Mesh 的 LOD 上工作。例如,LOD 0 会和 MeshIndex 匹配,而 LOD 1 或者 LOD 2 则只会是其中的一部分,不会匹配所有 MeshIndex。
以下是一个从 CompactPoseBoneIndex 转换到 Mesh Bone 的示例:
// iterate through all compact pose
for (FCompactPoseBoneIndex BoneIndex : Output.Pose.ForEachBoneIndex())
{
// ask mesh pose for the compact pose
FMeshPoseBoneIndex MeshPoseBoneIndex = Output.Pose.GetBoneContainer().MakeMeshPoseIndex(BoneIndex);
// assuming local mesh buffer is your buffer for skeletalmesh
Output.Pose[BoneIndex] = LocalMeshBuffer[MeshPoseBoneIndex.GetInt()];
}
最后,实际上 USkeleton 并不是表达它的最佳名称。
希望本文能帮助大家理解不同类型的骨骼索引。