2021SC@SDUSC
把三维网格顶点联系至骨骼的过称称为蒙皮。蒙皮用的网格是通过其顶点联系上骨骼的。每个顶点可绑定到一个或多个关节。若绑定至多个顶点,该顶点的位置为把它绑定到单一关节后的位置,再求其加权平均。
每个顶点需要信息:
- 该顶点绑定的(一个或多个)关节的索引;
- 对于绑定的每个关节,提供一个权重因子。
游戏引擎会限制每个顶点能绑定的关节数目,典型的限制为每顶点4个关节。
原因如下:首先,4个8位关节索引能方便地包裹为一个32位字,此外,每顶点使用2个、3个及4个关节所产生的质量很容易区分,但大多数人并不能分辨出每个顶点4个关节以上的质量差别。
典型的蒙皮顶点数据结构
struct SkinnedVertex
{
float m_position[3];
float m_normal[3];
float m_u, m_v; // 纹理坐标
U8 m_jointIndex[4]; // 关节索引
float m_jointWeight[3]; // 关节权重
};
线性混合蒙皮的本质
蒙皮的诀窍:顶点只有一个关节(即常说的骨骼,但是《游戏引擎架构》喜欢把它叫关节)影响时,顶点在关节空间中始终不变。
在被多个关节影响时,对于每个关节空间都会有这么一个不变的顶点位置。把这些顶点位置转化到模型空间,然后按权重对它们进行加权平均(线性混合),就可以得到模型空间下的顶点。于是,蒙皮效果就出现了。
这一步也可以让它直接转换到世界空间以节省一次矩阵乘法。但是如果场景中需要大量的实例,先转换到模型空间是更优的选择。
对每个关节而言,把顶点从bindpose变化到当前姿势的矩阵为蒙皮矩阵。每个顶点对应多个蒙皮矩阵,他们组成了蒙皮矩阵调色板。
提取信息
一个自定义Component,在Component里写上一个提取SkinnedMeshRenderer中所有必要信息的函数,序列化到Component上。
[HideInInspector]
[SerializeField]
public Matrix4x4[] bindPoses;
[HideInInspector]
public Vector3[] vertices;
[HideInInspector]
public Vector4[] tangents;
[HideInIns