适用于版本 2.3 及以上
unigine anim 从3Dmax 或从 fbx 之类的文件中导出的anim文件总是有些问题。anim文件在sdk/bin 下有一个resourceEditor.exe 可以进行查看。 比如一套动画,导出后莫名其妙的变成两套,并且动画的命名也是存在问题,动画名为default 和Take001。 因为 这个原因,导致给人物A播放动画anim1 ,会影响同mesh的人物B播放动画 anim2 。
anim文件名并不是真正的内部的动画名。 下面c++代码可以让内部动画变成一套动画,并且真实修改动画对应的动画名,解决上面提到的那个问题。当然,完全可以改成usc(unigine script)代码。
void AnimManager::convertAnimFile(const char* inpath, const char* outpath, const char* animName)
{
MeshPtr animOut = Unigine::Mesh::create();
MeshPtr anim = Unigine::Mesh::create();
int ret = anim->load(inpath);
int size = anim->getNumBones();
Vector<short> bones;
for (int i = 0; i < anim->getNumBones(); i++)
{
const char* name = anim->getBoneName(i);
animOut->addBone(name,anim->getBoneParent(i));
animOut->setBoneTransform(i, anim->getBoneTransform(i));//骨骼初始位置
bones.append(i);
}
//下面是处理动画帧,动画帧都是以相对transform矩阵的形式存放。相对于上一帧的transform矩阵。
int animationId = animOut->addAnimation(animName);
animOut->setAnimationBones(animationId, bones);
int frameNum = anim->getNumAnimationFrames(0);
animOut->setNumAnimationFrames(animationId, frameNum);
Vector<Math::mat4> mats;
for (int i = 0; i < frameNum; i++) {
mats.clear();
anim->getAnimationFrame(0, i, mats);//获取到一帧动画(所有骨骼相对transform矩阵的数组)
animOut->setAnimationFrame(animationId, i, mats);
}
animOut->save(outpath);
}
unigine 如此存放animation是有原的,这样方便动画的融合计算。要求第(n+1)%total_frame_num帧的骨骼位置,那么可以matx*matn(matx表示当前骨骼的位置及mat0*mat1*mat2......,mat0表示骨骼初始位置,mat1到matn表示从n帧到n+1帧保存的相对transform矩阵)。当需要进行动画融合时,可以用inverse(mat0)*mat0*mat1.....matn,从而获取到第n帧的变化量mat1*.....matn。然后再将变化量乘入到要融合的目标模型中去。
init(){
......
mesh_combined.setNumLayers(3);
// punch animation
mesh_combined.setAnimation(0,fullPath("samples/animation/animations/agent_punch.anim"));
// inverse reference frame into the 2 layer
mesh_combined.setAnimation(1,fullPath("samples/animation/animations/agent_idle.anim"));
mesh_combined.setFrame(1,0.0f);
mesh_combined.inverseLayer(2,1);//将layer 1的初始位置的inverses值存储到2中,注意2不会存储变化量。
......
}
update(){
......
mesh_combined.setFrame(0,0.0f);
mesh_combined.setFrame(1,time * animation_speed);//控制layer1 的帧的播放。
// multiple 1 layer by inverse reference frame
mesh_combined.mulLayer(1,2,1);//求取当前帧的所有骨骼的变化量。
// combine two animations
mesh_combined.mulLayer(0,0,1,4.0f);//将变化量直接乘入layer0中。
......
}