关键帧和动画
Keyframes and Animation
关键帧就是预先记录各个级别的动画数据。前面的机械手和太阳系系统都是在运行的时候计算出动画的。
关键帧就是一个对于模型各级别在某个时刻的重要位置。比如关键转完处,动作变向处等。
通过一定算法,计算机能自动计算出其关键帧之间的动作位置。这样我们就能产生平滑的动画了。如果做过flash和photoshop的朋友都知道这个概念。
但是怎么计算出?用什么算法?这就是个非常复杂的大问题了。比如用photoshop的会知道bezier曲线,那是由挺复杂的数学支持的。
而且一般不直接用矩阵来计算,而是把变换矩阵分解为三个部分旋转(rotation),缩放( scaling), 移位(translation),(为什么?因为算法需要)。使用Direct3D函数:D3DXMatrixDecompose .
一般会用到四元组来表示旋转。
计算中间帧的过程,计算t时段的中间帧:
1 找到两个关键帧Kj和kj+1发生在t0,和t1,这样t0<=t<=t1。
2 单位化t∈[t0,t1]到t∈[0,1],并使用插值算法计算其旋转矩阵。
如下计算其中间帧的旋转矩阵:
struct Keyframe { float time; D3DXQUATERNION R; D3DXVECTOR3 S; D3DXVECTOR3 T; }; //用L返回计算所得的变换矩阵。 void interpolateBone(Keyframe& K0, Keyframe& K1, D3DXMATRIX& L) { // Transform to [0, 1] float t0 = K0.time; float t1 = K1.time; float lerpTime = (t - t0) / (t1 - t0); // Compute interpolated RST values. D3DXVECTOR3 lerpedT; D3DXVECTOR3 lerpedS; D3DXQUATERNION lerpedR; D3DXVec3Lerp(&lerpedT, &K0.T, &K1.T, lerpTime);//Direct3D函数,线性插值算法 D3DXVec3Lerp(&lerpedS, &K0.S, &K1.S, lerpTime); D3DXQuaternionSlerp(&lerpedR, &K0.R, &K1.R, lerpTime);//圆形插值算法 // Build and return the interpolated to-parent // matrix for this bone. D3DXMATRIX T, S, R; D3DXMatrixTranslation(&T, lerpedT.x, lerpedT.y, lerpedT.z); D3DXMatrixScaling(&S, lerpedS.x, lerpedS.y, lerpedS.z); D3DXMatrixRotationQuaternion(&R, &lerpedQ); L = R * S * T;//用L返回计算所得的变换矩阵。 }
.X文件可以存储相关矩阵信息。D3DX中有API IDSDXAnimationController接口可以自动计算其中间位置。