骨骼动画初步完成

75 篇文章 10 订阅
50 篇文章 156 订阅

骨骼动画初步完成

        演示程序下载地址:这里 

骨骼动画是角色动画的重要组成部分,因为只有把骨骼的位置摆准确了才能正确反映角色地姿势,后面的蒙皮动画就好做了。花了我十多天的时间,一直在琢磨着如何顺利地进行骨骼位置的变换,以达到MikuMikuDance中的样子。我做了很多实验,这回也算是有一定的成果吧,虽然关于反向运动学(Inverse Kinematics,IK)的部分我还没有吃透,不过做出一个东西,想分享分享。

         关于骨骼的实现,一开始使用的是多叉树,后面发现使用多叉树进行遍历并不是那么好,因为要求的是层序遍历,我写过二叉树,发现层序遍历比较难实现,而先序遍历需要一个栈数据结构来保存父骨骼的变换,显得有些多余。我从PMD格式中读取骨骼数据,在PMD中骨骼数据是线性存储的,于是我想能不能也用线性存储这些数据,再辅以一些数据结构实现多叉树的功能?

         最终我发现了多值散列表(MultiHash),我是这么做的,在骨骼读入后不久做一次遍历,以每个骨骼的索引为键,骨骼的层次关系(Hierachy)为值来建立多值散列表。因为模型的骨骼旋转和平移数据都是相对于父骨骼,考虑到要使用VBO,无法像以前那样push和pop模型矩阵,因此有必要将相对的旋转和平移转为绝对的旋转和平移。这个时候只需要对散列表中某一骨骼的层次关系进行遍历然后累加即可。下面是实现上述功能的关键代码:

voidMMDAnimationPrivate::InitBoneHierarchy( void )// 初始化骨骼的层次(孩子在尾端,祖先在首端)
{
   // 需要MMDRenderHandler的骨骼列表
   QVector<MMDRenderHandler::Bone>& bones = m_pRenderHandler->Bones();
 
   for ( int i = 0; i < bones.size( ); ++i )
    {
       quint16 parent = bones[i].parent;
 
       m_BoneHierarchy.insert( i, i );// 先将自己压入层次中
       while ( parent != quint16( -1 ) )
       {
           m_BoneHierarchy.insert( i, parent );// 将父骨骼压入层次中
           parent = bones[parent].parent;
       }
    }
}

……

// 旋转进行叠加
for ( int i = 0; i < bones.size( ); ++i)
{
   Quaternion absRotation;
   foreach ( quint16 index, m_BoneHierarchy.values( i ) )
    {
       absRotation *= bones[index].rotation;
    }
   bones[i].rotation = absRotation;
}

         这里给出运行程序截图:

 


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值