irrlicht动作融合的使用姿势

动作融合是一种将当前动作跟目标动作中骨骼位置进行动态插值的算法。得到的结果可以使角色的动作表现更加的平滑。

irrlicht引擎也提供了相应的功能,下面就这个功能的使用方法进行说明。

功能函数

引用下irrlicht的代码

//! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2)
//! you must call animateJoints(), or the mesh will not animate
void CAnimatedMeshSceneNode::setTransitionTime(f32 time)
{
    const u32 ttime = (u32)core::floor32(time*1000.0f);
    if (TransitionTime==ttime)
        return;
    TransitionTime = ttime;
    if (ttime != 0)
        setJointMode(EJUOR_CONTROL);
    else
        setJointMode(EJUOR_NONE);
}

使用这个函数,就可以在播放下一个动作的时候自动进行插值。但是,只使用这一个函数,只会让你的模型骨骼便的不受控制。
好在这个时候我们注意到函数前面的两行注释,什么意思呢?

设置融合时间,单位秒(注意:这个需要有骨骼,并且设置骨骼模式为2,就是EJUOR_CONTROL)
你必须调用animateJoints(),否则动画可就不动了哟

然而注释没有提到的是,你必须没一帧都调用animateJoints(),否则动画还是不动哟
这里有英文版解释

Now if you also want your mesh to animate using any built-in animation in the model, call:
Node->animateJoints();
In your game loop, before drawAll().
意思就是你如果要播已有的动画,你需要在游戏的主循环中调用animateJoints();

步骤

  1. 设置 setTransitionTime(f32 time)
  2. 每帧调用 animateJoints()

做完这两件事,你就可以可到动作融合可以正常使用了。

更多的要求

但是还不够。当功能正常使用的时候,我们可能会有更多的需求:

  • 对不同的动作设置不同的动作融合
  • 某些特别的动作不要融合

前面的两个步骤,在动作融合及不融合来回切换的时候会导致模型节点不受控制。有两处问题,再看代码

void CAnimatedMeshSceneNode::setTransitionTime(f32 time)
{
    const u32 ttime = (u32)core::floor32(time*1000.0f);
    // 问题2
    if (TransitionTime==ttime)
        return;
    TransitionTime = ttime;
    if (ttime != 0)
        setJointMode(EJUOR_CONTROL);
    else
        setJointMode(EJUOR_NONE);   // 问题1
}

问题1:在把动画的融合设置为0时,期望的是关闭动作融合。但实际导致骨骼模式变成NONE,子节点不能正常变换位置。手动调用 node->setJointMode(scene::EJUOR_READ)解决
问题2:试想下面的操作过程,

  1. 设置融合时间setTransitionTime(0.3)
  2. 关闭动作融合setJointMode(scene::EJUOR_READ)
  3. 再次设置setTransitionTime(0.3)

第三步操作时,代码在 if (TransitionTime==ttime)处返回,于是没有自动执行setJointMode(EJUOR_CONTROL);
所以结论是:在setTransitionTime时同时设置setJointMode(MODE)来避免这个问题

if (m_AniPlayData.blend > 0) {
    node->setTransitionTime(m_AniPlayData.blend);
    node->setJointMode(irr::scene::EJUOR_CONTROL);
} else {
    node->setTransitionTime(0);
    node->setJointMode(irr::scene::EJUOR_READ);
}

最后完整的步骤是:

  1. 设置 setTransitionTime(f32 time)
  2. 同1时设置 setJointMode(MODE);
  3. 每帧调用 animateJoints()

至此,动画融合就完全可用了。

PS:如果你的主模型的子节点也需要做动画的话,对子节点也需要上述三个步骤。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 111. [动画系统]如何将其他类型的动画转换成关键帧动画? 动画->点缓存->关键帧 112. [动画]Unit...
    胤醚貔貅阅读 13,203评论 3 89
  • 转载一篇高质量博文,原地址请戳这里转载下来方便今后查看。1 背景不能只分析源码呀,分析的同时也要整理归纳基础知识,...
    Elder阅读 1,954评论 0 24
  • 1 背景 不能只分析源码呀,分析的同时也要整理归纳基础知识,刚好有人微博私信让全面说说Android的动画,所以今...
    未聞椛洺阅读 2,755评论 0 10
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,572评论 6 30
  • 喜欢是情感众多类目中的一种,介于沉溺和无察之间,像深且阔的湖面上微风抚过的涟漪,不易察觉,等你细看,却已消逝不见。...
    偶然之音阅读 291评论 0 0