(转载)MultiAnimation
原文:http://kay.zhang.blog.163.com/blog/static/3493716520084100395228/
multiAnimation是个很酷的东西。我们知道利用AnimationController可以随意的加载.x中的各种动画集。可是如果不做任何设置,只是在一个Track上切换动画集的话,就会出现动作突然变化的效果,十分不自然,比如说:当.x模型在程序中是立正的时候,我们发出命令:敬礼!他的右手手就会直接从裤缝瞬移到太阳穴,没有一个变化的过程。而我们要的效果是:我们下令敬礼 之后,他的手会从裤缝慢慢的移动到太阳穴。整个是一个连续的过程。
这要怎么实现呢?其实AnimationController已经提供了动画集之间平滑过度的功能。
如果两个动画集切换,则至少需要2个的轨道(Track),我们记作Track0,和Track1。实现平滑过度的实质就是两个轨道之间的你进我退。我们要做的是设置“你进”的时间长度和 “我退”的时间长度就行了。
代码如下:
DWORD dwCurrentTrack = 0; // 全局变量,记录当前的轨道号 0 或 1
void CSkinMesh::SetAnimSet(char* animname)
{
DWORD dwNewTrack = ( dwCurrentTrack == 0 ? 1 : 0 ); // 取和当前轨道号相对的编号,0取1,1取0.
LPD3DXANIMATIONSET pAS; // 定义一个动画集,用来读取.x模型中的动画集
m_pAnimController->GetAnimationSetByName( animname, & pAS ); // 依照函数参数的名称来读取动画集
m_pAnimController->SetTrackAnimationSet( dwNewTrack, pAS ); // 将此动画集设置加入到新的轨道上
pAS->Release();
m_pAnimController->UnkeyAllTrackEvents( dwCurrentTrack ); // 清除原先轨道上的事件
m_pAnimController->UnkeyAllTrackEvents( dwNewTrack ); // 清除新轨道上的事件
float time = g_TotalTime; // 得到全局的总时间
float Duration = 2.8f; // 设置变化的时长,我们令“你进”和“我退”的过程时间长度一致。
m_pAnimController->KeyTrackEnable( dwCurrentTrack, FALSE, time+Duration );
m_pAnimController->KeyTrackSpeed( dwCurrentTrack, 0.0f, time, Duration, D3DXTRANSITION_LINEAR );
m_pAnimController->KeyTrackWeight( dwCurrentTrack, 0.0f, time, Duration, D3DXTRANSITION_LINEAR );
m_pAnimController->SetTrackEnable( dwNewTrack, TRUE );
m_pAnimController->KeyTrackSpeed( dwNewTrack, 1.0f, time, Duration, D3DXTRANSITION_LINEAR );
m_pAnimController->KeyTrackWeight( dwNewTrack, 1.0f, time, Duration, D3DXTRANSITION_LINEAR );
dwCurrentTrack = dwNewTrack; // 将新轨道设置为当前轨道,为下次变换做准备。
}
每次调用这个函数时,就会在2.8秒(Duration 变量)内实现两个动画轨道的互相更替。从而实现渐变的效果。比如们么的模型正在立正,我们调用pSkinMesh->SetAnimSet("敬礼");,之后他就会自动插关键帧来实现平滑的过度了。这在游戏中的应用非常广泛。