赞
踩
例如,有下面的结构:
每根子骨骼的坐标系都可以跟父骨骼关联,第一根骨骼与世界坐标系关联:
如果矩阵A0是第一根骨骼的世界变换矩阵,A1是第二根骨骼变换到第一根骨骼的矩阵,往后依次类推,那么第i根骨骼变换到世界坐标系的变换矩阵就是:
在我们上述的例子中,M2 = A2A1A0, M1 = A1A0 and M0 = A0,就是每根骨骼对于的世界坐标系变换矩阵:
高光的那整条骨骼链叫做骨架(skeleton)。3D几何模型叫做皮肤(skin)。皮肤顶点与绑定空间相关联(整个皮肤相关联的局部坐标系)。每个骨骼影响一系列子皮肤的位置和形状。
和上述不同的地方是,把各个骨骼变换到世界坐标系的矩阵拆解开,先找到变换到根空间的矩阵,然后变换到世界坐标系;第二个不同点是从下往上,这样比从上往下更高效。第n根骨骼的变换如下:
这里p是骨骼i的父骨骼的编号,toRootp从p的局部坐标系映射到根局部坐标系。
有一个小问题是,被骨骼影响的顶点并不在骨骼坐标系统中,而是在绑定空间中。所以在应用公式对顶点进行变换之前,我们先要将顶点从绑定空间变换到影响它的骨骼的空间中,所以叫抵消变换(offset transformation)。
所以现在可以定义一个最终变换:
我们定义了一个骨架动画的类SkinnedData.h/.cpp在Skinned Mesh Demo中。
我们首先对每个骨骼单独在局部坐标系移动,然后考虑其父节点的移动,然后变换到根空间。
我们定义一些列动画的动画片段(animation clip):
///<summary> /// Examples of AnimationClips are "Walk", "Run", "Attack", "Defend". /// An AnimationClip requires a BoneAnimation for every bone to form /// the animation clip. ///</summary> struct AnimationClip { // Smallest end time over all bones in this clip. float GetClipStartTime()const; // Largest end time over all bones in this clip. float GetClipEndTime()const; // Loops over each BoneAnimation in the clip and interpolates // the animation. void Interpolate(float t, std::vector<XMFLOAT4X4>& boneTransforms)const; // Animation for each bone. std::vector<BoneAnimation> BoneAnimations; };
我们可以使用unordered_map保存这些片段:
std::unordered_map<std::string, AnimationClip> mAnimations;
AnimationClip& clip = mAnimations["attack"];
最终,每个骨骼需要抵消变换矩阵,并且需要一个数据结构表示骨架结构。所以我们骨骼动画最终数据结构如下:
class SkinnedData { public: UINT BoneCount()const; float GetClipStartTime(const std::string& clipName)const; float GetClipEndTime(const std::string& clipName)const; void Set(std::vector<int>& boneHierarchy, std::vector<DirectX::XMFLOAT4X4>& boneOffsets, std::unordered_map<std::string, AnimationClip>& animations); // In a real project, you’d want to cache the result if there was a // chance that you were calling this several times with the same // clipName at the same timePos. void GetFinalTransforms(const std::string& clipName, float timePos, std::vector<DirectX::XMFLOAT4X4>& finalTransforms)const; private: // Gives parentIndex of ith bone. std::vector<int> mBoneHierarchy; std::vector<DirectX::XMFLOAT4X4> mBoneOffsets; std::unordered_map<std::string, AnimationClip> mAnimations; };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。