骨骼动画3
第三界简单的骨骼动画、骨骼动画理论
Keep in touch :zpxocivuby@126.com
目的:指导别人使用矩阵
任务:编写教程,编写代码
阅读对象:d3d入门者,c/c++熟练,windows编程熟练,VC IDE熟练
描述:
这一届我们来做一个简单的骨骼动画(非常简单啊!只有两个线段啊!)并且介绍一下实现思想是什么
在3d世界中,人物的动画过程主要有两种实现方式:
1. key frame animation(关键帧动画)
a) 是将要播放的关键帧都做好放到存储介质中(文件,内存),播放时一帧帧的调出来
2. (骨骼动画)
a) 是将动作对象分解成一个个的键(joint),和骨(bone)要使对象动作只要将joint和bone进行矩阵坐标转换就可以了
第一种方式我们暂时不研究(等我写完骨骼动画后我会再介绍的),我们只关心第二种实现方式。
下图就是一个最最基本的骨骼构成模式
图1
其中键有:A,B,C,D;骨有a,b,c;我们现在假设ABCD的坐标是A(1,0,Z),B(0,0,Z)C(0,1,Z)D(1,1,Z),我们想让a,c骨骼动起来,而b不动
图2
经过变换之后我们的图1就变成图2了。现在我们来看看用数学表达是怎样表示上面的转换我们设C>C’转了r度,D>D’在C不变的情况下(什么?为什么C不变?这个……你自己考虑吧)转了t度,则C’的坐标是(x’,y’,Z),D’的坐标是(x’’,y’’,Z)。什么坐标是怎么计算出来的?你可真着急啊当然是通过矩阵变换的啊
计算步骤:
第一步:我们首先认为C和D点是一起的也就是说当C移动时D也随之移动,这样我们可以计算出C’和D’’的坐标都是绕A点以垂直于AC和CD的平面的向量旋转的,通过转换矩阵我们可以得到C’D’’的向量坐标,
第二步: 再处理D’’向D’转动,这是可以将C”点看成是转点,计算得出D’的向量坐标
好了,我们来看一下代码吧
为了方便操作,我将原本在setup函数中的vertices变量放到了外边,成了全局变量(这样不是一个好的方法,但这只是一时之举,少后我将会改正)
Vertex* vertices;
在程序中我们将键(joint)设成一个点,骨(bone)则是一个线段
其中要注意的代码只有一段,那就是在display()函数中的下列语句
//申明了四个点,其中tempA,tempB,tempC各代表ACD三个点tempD代表了一个临时的数据存放空间,主要是用来放转换之后的C’C’’D’的位置数据
D3DXVECTOR3* tempA = new D3DXVECTOR3(vertices[0]._x,vertices[0]._y,vertices[0]._z); //将ABC复制到temp里面
D3DXVECTOR3* tempB = new D3DXVECTOR3(vertices[1]._x,vertices[1]._y,vertices[1]._z);
D3DXVECTOR3* tempC = new D3DXVECTOR3(vertices[2]._x,vertices[2]._y,vertices[2]._z);
D3DXVECTOR3* tempD =new D3DXVECTOR3() ;
//计算BA
D3DXVECTOR3* BA = &(*tempB-*tempA);//计算出向量BA
//计算CA
D3DXVECTOR3* CA = &(*tempC-*tempA); //计算出向量CA
//将BA在垂直BA方向上旋转ax
D3DXMatrixRotationAxis(&RAba,(D3DXVec3Cross(tempD,BA,CA)),ax);//前面介绍过这个函数
// D3DXVec3Cross函数的功能是将BA向量和CA向量进行X(不能读成”埃克司”啊,应该是“叉乘”)乘,(得到的是一个垂直于BA和CA的向量)
D3DXMatrixRotationAxis(&RAcb,(D3DXVec3Cross(tempD,BA,CA)),ax);
D3DXVec3TransformNormal(BA,BA,&RAba);//该函数的功能是将BA向量通过转换矩阵RAba变成BA’
D3DXVec3TransformNormal(CA,CA,&RAcb);
*tempB = (*BA+*tempA);
//重新对内存中的数据进行复制
vertices[1]._x=tempB->x;
vertices[1]._y=tempB->y;
vertices[1]._z=tempB->z;
*tempC = (*CA+*tempA);
//计算C'B'
D3DXVECTOR3* CB = &(*tempC-*tempB);
//将C'B'在垂直C'B'方向上旋转ax
D3DXMatrixRotationAxis(&RAba,(D3DXVec3Cross(tempD,BA,CA)),-ax);
D3DXVec3TransformNormal(CB,CB,&RAba);
*tempC = (*CB+*tempB);
vertices[2]._x=tempC->x;
vertices[2]._y=tempC->y;
vertices[2]._z=tempC->z;
好了运行一下吧,看看有什么效果!
怎么样是不是很“裸”(这是我上大学时,我们班人常说的一个字,意思说:很差劲,很白痴,无能,发泄的意思,反正不是个好东西了,是我们班人发明的哦,没有授权你不能使用的啊“^_^”)
的确这段代码对付这两个线段是可以了,可是要有上百个上千个怎么办啊?没关系了,我们可以将代码重构一下。写的更加复杂一些,并且使用一些OO(面向对象)方法,和design pattern(设计模式),这些将会在下一界中介绍。
备:写这些东西好累啊,白天上班晚上还要回来写东西真的很累啊,所以这个周休息一下下周再写。
附件下载地址http://blog.blogchina.com/upload/2004-12-02/20041202090040332679.rar