试验过在IrrLicht中导入播放骨骼动画模型的朋友可能会发现,引擎存在下列问题:一, 当一次循环结束时会产生无效帧,在原模型不远的位置出现一片不规则的图片,严重影响显示效果。二,当模型包含旋转动作时发现模型在旋转过程中方向会突然反向,猜想也是计算错误。针对这两个问题,可以采用如下解决办法。
针对出现无效帧的问题,代码做如下修改:
在类SMS3DMeshBuffer的loadFile方法中(请对照原代码)
// 获得旋转的关键帧
//>>rxue add
s32 j;
SKeyframe k;
MS3DKeyframe* eka = NULL; // this contains data of first keyframe
f32 first = 0; // this is time of first keyframe
//<<rxue add end
for (j=0; j<pJoint->NumRotationKeyframes; ++j)
{
MS3DKeyframe* kf = (MS3DKeyframe*)pPtr;
pPtr += sizeof(MS3DKeyframe);
//>>rxue add
if(j==0)
{
eka = kf;
first = kf->Time;
}
k.timeindex = (kf->Time-first) * 1000.0f;
//<<rxue add end
k.data.X = kf->Parameter[0];
k.data.Y = kf->Parameter[1];
k.data.Z = kf->Parameter[2];
jnt.RotationKeys.push_back(k);
}
//>>rxue add
totalTime -= first;
if(eka)
{
k.timeindex = totalTime;
k.data.X = eka->Parameter[0];
k.data.Y = eka->Parameter[1];
k.data.Z = eka->Parameter[2];
jnt.RotationKeys.push_back(k);
}
eka = NULL;
//<<rxue add end
// 获得变换的关键帧
first = 0; //rxue add
for (j=0; j<pJoint->NumTranslationKeyframes; ++j)
{
MS3DKeyframe* kf = (MS3DKeyframe*)pPtr;
pPtr += sizeof(MS3DKeyframe);
//>>rxue add
if(j==0)
{
eka = kf;
first = kf->Time;
}
k.timeindex = (kf->Time-first) * 1000.0f;
//<<rxue add end
k.data.X = kf->Parameter[0];
k.data.Y = kf->Parameter[1];
k.data.Z = kf->Parameter[2];
jnt.TranslationKeys.push_back(k);
}
//>> rxue add Let's add one keyframe to the end
if(eka)
{
k.timeindex = totalTime;
k.data.X = eka->Parameter[0];
k.data.Y = eka->Parameter[1];
k.data.Z = eka->Parameter[2];
jnt.TranslationKeys.push_back(k);
}
//<<rxue add end
旋转反向的问题:
修改SMS3DMeshBuffer类的getKeyframeData方法如下:(注意:s32type为增加的参数,所以函数声明也要做相应修改)
void CAnimatedMeshMS3D::getKeyframeData(core::array<SKeyframe>& keys, f32 time, core::vector3df& outdata,s32 type)
{
if(type == 0)
{
for (s32 i=0; i<(s32)keys.size()-1; ++i)
{
if (keys[i].timeindex <= time && keys[i+1].timeindex >= time)
{
f32 interpolate = (time - keys[i].timeindex)/(keys[i+1].timeindex - keys[i].timeindex);
outdata = keys[i].data + ((keys[i+1].data - keys[i].data) * interpolate);
return;
}
}
}
else
{
for (s32 i=0; i<(s32)keys.size()-1; ++i)
{
if (keys[i].timeindex <= time && keys[i+1].timeindex >= time)
{
irr::core::quaternion q1(keys[i].data.X,keys[i].data.Y,keys[i].data.Z);
irr::core::quaternion q2(keys[i+1].data.X,keys[i+1].data.Y,keys[i+1].data.Z);
f32 interpolate = (time - keys[i].timeindex)/(keys[i+1].timeindex - keys[i].timeindex);
q2 = q1.slerp(q1,q2,interpolate);
q2.toEuler(outdata);
return;
}
}
}
}
SMS3DMeshBuffer类animate方法修改如下:
//find keyframe translation and roation
//getKeyframeData(Joints[i].TranslationKeys, time, translation);
//getKeyframeData(Joints[i].RotationKeys, time, rotation);
getKeyframeData(Joints[i].TranslationKeys, time, translation,0);//rxue
getKeyframeData(Joints[i].RotationKeys, time, rotation,1);//rxue 重新计算
至此,解决了模型动画的播放问题。在我们这里测试正常,有问题的朋友可以留言讨论。