平民程序 - linghuye's blog

天下风云出我辈,一入江湖岁月催。皇图霸业谈笑中,不胜人生一场醉。提剑跨骑挥鬼雨,白骨如山鸟惊飞。尘事如潮人如水,只笑江湖几人回。

随笔 - 221, 文章 - 0, 评论 - 680, 引用 - 0
数据加载中……

骨骼动画实践

1.一套Skeleton由若干Bone组成,在数据存储上通常表现为Bone结构数组.
2.一个Bone表达一个空间Transform概念,在代码上本质归结为一个Transform Matrix.
3.一个Bone有两种概念上的变换: 1.自身的变换矩阵  2.与父骨骼整合后的变换矩阵.
4.一个Bone在数据文件中通常存储的是自身的变换矩阵,存储x,y,z的Translation,四元数Rotation,及x,y,z的Scale(或直接一个4*4矩阵).
5.一个Bone存储的是多个变换矩阵,对应多个关键帧.
6.某个动画序列给出在该动画中每个骨骼从哪一帧变换到哪一帧,以及变换的插值法(线性,Hermit,Bezier,Spline).
7.Bone数组之间呈N树关系,由唯一的root(ID=-1)向下遍历所有子节点(Bone结构标出自己的父节点ID).
8.每个骨骼对附属于它(与之关联)的模型顶点施加空间变换.
9.对模型顶点进行分组,一个组内的所有顶点附属于(受影响于)某个或某些Bone.
10.每个骨骼施加的空间变换是其自身空间变换与其父骨骼空间变换的累积,而其父骨骼的空间变换以次向上类推.
11.换而言之,即施加的空间变换为分支向上所有节点的自身距阵的乘积.
12.以数学标准而言 integrated = parentMatrix * matSelf;  vOut = integrated * vIn(DirectX反数学标准).
13.骨骼相连处节点出现权重现象概念,即一个点同时受多个骨骼影响,此影响有权重数,都在8之顶点分组中定义.
14.在一个动画时刻,设帧N,向每个骨骼询问在帧N时的变换矩阵,每个骨骼推算帧N的前后相邻的关键帧,取出变换数据,作数学变换插值,得出变换矩阵.对受该骨骼影响的每个点施加该矩阵影响,得出此刻该点的位置.

 

Sample:
// 泛化骨骼类型,假设仅有骨骼数据与应用相关.
template<class bone_type>
class CSkeleton
{
public:
CSkeleton()
{
}

~CSkeleton()
{
}

public:
void AddBone(bone_type* pBone)
{
m_vecBones.push_back(pBone);
}

void FrameSkeletonTransformMatrixs(int nCurFrame)
{
matrix_type rootMat;
rootMat.set_identity();

//从骨骼系统的根部开始递归算出各骨骼的变换距阵.
const int rootID = -1;
FrameChildBonesTransformMatrixs(rootMat, rootID, nCurFrame);
}

matrix_type& GetSkeletonTransformMatrix(int nBoneID)
{
return m_vecBones[nBoneID]->IntegratedTransformMatrix();
}

protected:
void FrameChildBonesTransformMatrixs(const matrix_type& parentMat, int nParentID, nCurFrame)
{
int nBonesCount = m_vecBones.size();
for(int id = 0; id < nBonesCount; id++)
{
//找出nParentID的所有子节点骨骼
bone_type* bone = m_vecBones[id];
if(bone->ParentID() == nParentID)
{
//计算骨骼的在分支上的完整的变换距阵.
CalcuBoneTransformMatrix(bone, parentMat, nFrame);
//递归
FrameChildBonesTransformMatrixs(bone->IntegratedTransformMatrix(), bone->BoneID(), nCurFrame);
}
}
}

void CalcuBoneTransformMatrix(bone_type* bone, const matrix_type& parentMatrix, int nFrame)
{
matrix_type& mat = bone->IntegratedTransformMatrix();

//计算取出bone自有的变换距阵数据.
bone->CalcuBoneOwnTransformMatrix(m_nCurFrame, mat);

//与父骨骼变换距阵累积.
mat = parentMatrix * mat;
}

public:
typedef std::vector<bone_type*> CBoneVector;
CBoneVector m_vecBones;
};

/*************************************************
**  与CSkeleton合作的Bone所需实现的语义接口.
*************************************************/
class CBoneBaseImpl
{
public:
matrix_type m_transformMatrix;

public:
CBoneBaseImpl()
{
}

~CBoneBaseImpl()
{
}

public:
matrix_type& IntegratedTransformMatrix()
{
return m_transformMatrix;
}

bool CalcuBoneOwnTransformMatrix(matrix_type& matRes)
{
}

int ParentID()
{
}

int BoneID()
{
}
};

posted on 2005-08-13 17:25 linghuye 阅读(845) 评论(0)  编辑 收藏 引用 所属分类: 3D图形学研究

只有注册用户登录后才能发表评论。