• [原创]IrrLicht中MS3D模型骨骼动画支持bug的排除


    试验过在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 重新计算
    至此,解决了模型动画的播放问题。在我们这里测试正常,有问题的朋友可以留言讨论。

  • 相关阅读:
    ytu 2030: 求实数绝对值(水题)
    [PHP] 链表数据结构(单链表)
    PHP将数据写入指定文件中
    PHP获取文件后缀名
    PHP数组序列化和反序列化
    PHP二维数组(或任意维数组)转换成一维数组的方法汇总
    PHP获取文件大小的方法详解
    PHP中嵌套函数被调用时出现报错的问题
    PHP递归排序
    PHP实现简单倒计时
  • 原文地址:https://www.cnblogs.com/flysnow/p/461831.html
Copyright © 2020-2023  润新知