这一节教程是关于如何用Directx11实现SkeletalAnimation(骨骼动画)的,代码的结构如下:
在谈论SkeletalAnimation之前,我们先看看大名鼎鼎的虚幻四引擎的动画系统中的Skeleton,如下图所示:
在上面图左边方框显示的人物骨骼的层级关系图,也就是右边方框中的人物的各种黑色骨头的层级关系图。那么人物的骨骼的层级关系图是怎么样的?看着上面人物骨骼层级关系图,其实很容易想到一个经典的数据结构,也就是“树”,也就是说人物的各个骨头之间呈现的为“子母关系”,这里将每根骨头都是“骨骼树”中的一个节点,那么除了根节点之外,其它节点都存在母节点,如图中的骨骼“clavicle_l”就是骨骼“upperarm_l”的母节点。
假设骨骼A依据一个另外骨骼B为母节点,那么B骨骼变换时,A骨骼也会相应进行变换。如下图所示:
总体来看,各个骨骼之间的关系用一个图来表示如下:
假设我们有三个骨骼Bone0,Bone1,Bone2,这三个骨骼呈现的为下图中的这样的层级关系:
3D模型文件中,每根骨骼都存在其独自的局部空间坐标系,就如同在3D模型文件格式读取的切线向量一开始是存在于TangnetSpace(切线空间)。当然,各个骨骼的坐标系之间存在一定的关系的,这个与上面介绍的“骨骼层级关系--树”是相关的。在很多3D文件中,如M3D文件,每根骨骼的Scale,Translation,Quat定义了其局部空间的变换(Transform),这个变换有什么用呢?这个变换允许我们将一个骨骼的坐标系变换到其母骨骼的坐标系中.
我们上面说过,在3D模型文件中,每根骨骼定义的(由Translation,Scale,Quat组成)变换矩阵,负责把其独自的坐标系变换到其母骨骼的坐标系。那么依据这个原理,骨骼树中的叶点代表的骨骼通过自底向上的计算,将其的坐标系最终变换到根节点的母空间,而根节点的母空间就是根节点定义的变换矩阵将根节点的坐标系变换到的空间,也就是我们3D渲染中的LocalSpace。一句话总结:根节点的母空间就是LocalSpace
下面图展示了包围着骨骼的人物的网格。人物的网格由大量的三角形片元构成,而构成三角形片元的顶点的位置则是由骨骼的变换矩阵所影响,这样就造成了每帧骨骼动画下,人物的网格出现了变换的结果。当然,一段动画下,同一根骨骼在不同画面帧下的变换矩阵是不一样的,所以每帧画面下构成了人物3D网格的每个三角形片元的顶点的位置自然不同了,这将在后面介绍3D动画格式M3D详细解释。
在(3)中我们解释了构成人物网格的三角形片元的顶点的位置被骨骼所影响,但是这里的顶点有条件限制:指的是在绑定空间(BindSpace)。顶点的绑定空间,也就是3D模型被朔造所在的空间。而我们已经在(2)中求出每个骨骼变换到世界空间的矩阵,这里假设第i个骨骼变换到世界空间的矩阵为ToRoot(i).这里我们对顶点进行处理:
一,先把顶点变换到骨骼的局部空间位置,也就是进行OffsetTransform(i)
二,将变换到骨骼局部空间位置的顶点进行ToRoot的变换
如下图所示:
也就是顶点最终的变换矩阵为FinalMatrix=OffsetTransform(i)*ToRoot(i).
为什么是顶点混合?拿上面(3)和(4)的人物3D网格来当例子,用一句通俗的话来说,顶点混合就是一个顶点的变换是同时受到多个骨骼的影响。比如说,我们存在一个顶点VertexA,而存在四个骨骼Bone0,Bone1,Bone2,Bone3,并且这四个骨骼相应的最终变换矩阵为Bone0FinalMatrix,Bone1FinalMatrix,Bone2FinalMatrix,Bone3FinalMatrix。这里假设VertexA被Bone0,Bone1,Bone2,Bone3所影响,并且被Bone0影响程度分别为Weight0, 被Bone1影响程度为Weight1, 被Bone2影响程度为Weight2, 被Bone3影响程度为Weight3.
这里: weight0+weight1+weight2+weight3=1.0f
那么顶点混合起到什么作用?其实这种以加权值混合的方式在3D图形学非常常见,起到让某种显示效果平滑过度的作用。
下一篇链接:D3D11教程四十二中之3D动画格式M3D