本想学习PRT技术,但是觉得这个技术太高级,而且就中国现在的技术来看,还未到这个程度。但是PRT技术一定要学,一定要掌握,才能不致于落后国际水平太多。这几天学习了一下骨骼动画。以前记得参加齐鲁软件大赛的时候,用Ogre很简单的就实现了骨骼动画。现在终于可以自己在DX基础上亲手完成这个3d游戏中最重要的技术。

骨骼动画中有许多我们需要注意的。简单屡一下骨骼动画中需要知道的基本知识点。

  1. 首先我们需要一个骨架。这些骨架中的骨骼有父子关系,有兄弟关系。父关节的运动是会带动子关节的。就像我们的上臂动会带动前臂一样。
  2. 骨架和人物网格建立绑定空间中。因为每个骨骼都可以绕着它们的关节旋转,要表达这些旋转我们必须在关节处建立一个骨骼空间,这样就能方便的表示骨骼在关节上的旋转。骨骼的这些旋转运动(或者直接说骨骼)是用矩阵表示。

  3. 在骨骼空间中,我们采用三个向量来表示骨骼运动(或者说骨骼)。RST(Rotation,Scaling,Translation)Values。Rotation代表骨骼在骨骼空间中的旋转变换,由四元数(Quaternion)表示,因为需要平滑动画,我们经常需要对两个动作中的旋转进行差值,所以必须用四元数。Scaling表示骨骼的缩放变换。Translation表示子骨骼相对于父骨骼的偏移。因为父骨骼有骨骼大小,而父骨骼自身无法表示。所以为了给父骨骼腾出骨骼空间,子骨骼必须要进行相当于父骨骼大小的偏移

  4. 每个骨骼在运动时会牵扯附着在其表面的皮肤,也就是相应部分的人物网格。为了让骨骼旋转能运用于这些网格,我们必须将网格变换到骨骼空间中去。这样每个骨骼中应该包含相应的网格从绑定空间到其骨骼空间的变换矩阵,称为平移矩阵(OffsetMatrix)。
  5. 每个骨骼的最终位置不光取决于其自身的旋转,还取决于其父骨骼的旋转。所以要想表示每个骨骼最终在角色空间(我认为一般情况下角色空间和绑定空间是一样的,只要骨架不进行偏移)。这样我们为了需要求出每个骨骼在角色空间中位置,我们需要将其父节点的变换应用与子节点的变换。而父节点也会被其父节点影响。这是一个递归过程,所以我们必须找到祖先。一般就是盆骨。从祖先往下,将其变换运用到其子节点,再由子节点运用到其子子节点。这样我们为每个骨骼求出了一个变换矩阵,这个矩阵我们称为组合矩阵(CombineMatrix),这个矩阵可以将骨骼变换从骨骼空间转换到角色空间。
  6. 人物网格最终在角色空间中的位置,由平移矩阵(OffsetMatrix)和组合矩阵(CombineMatrix)共同决定。因为网格应该先变换到骨骼空间,所以采用OffsetMatrix,然后再由骨骼空间变换到角色空间,所以采用CombineMatrix。
  7. 这样只要我们不断更新每个骨骼的旋转矩阵,然后重新建立CombineMatrix。我们再和OffsetMatrix进行组合,就能不断的得到新的骨骼姿态,就能让人物网格动起来。
  8. 为了达到关节处的平滑过度,也就是关节旋转不是完全僵硬的。我们采用一个顶点可以被多个骨骼影响的方法。这样在关节处的顶点,受关节处两端的骨骼影响,这样关节一端的骨骼运动不会完全带动这个顶点运动,而这个顶点还会受另一端骨骼的牵制。就想人皮一样,在关节处会被拉伸。所以称为Skinned Mesh(我称其为蒙皮网格)。而这种思想被称为顶点混合(Vertex Blending ),可以这么理解,将关节处顶点分别用两端骨骼的矩阵进行变换,得出两个新的顶点,然后将这两个顶点按照一定比率进行插值(混合)得到最终的顶点,所以称为顶点混合。而且在骨骼动画中经过长期研究发现,正常情况下一个顶点最多被四个骨骼影响。所以DX中顶点的数据中,最多有四个混合权重值。

接下来介绍SkinnedMesh案例中的重点和难点。

  1. DX中每个骨骼由D3DXFRAME表示。虽然名字都点不恰当,但是Frame确实很通用,因为骨骼运动不光可以用于动物,还可以用于其它任何网格。
  2. 由于D3DXFRAME中没有组合矩阵的信息,所以我们需要派生D3DXFRAME,添加上组合矩阵。
  3. DX中用D3DXMESHCONTAINER表示人物网格及其相应的材质等其他附属信息。需要特别注意的是D3DXFRAME有D3DMESHCONTAINER的指针。所以每个骨骼都有指向人物网格容器的指针。但是一般情况下(人物网格只有一个),只有一个D3DXFRAME的指针是有效的。
  4. DX中,为了让我们对骨架层次(Hierarchy)的控制更灵活,DX在创建骨架时让我们自己实现D3DXFRAME和D3DXMESHCONTAINER的创建和销毁接口。而我们需要做的就是继承ID3DXAllocateHierarchy,并改写其中有且仅有的四个虚函数。
  5. 在创建D3DXMESHCONTAINER和创建D3DXFRAME接口中一定要注意,传向该函数的所有指针对应的内存都属于DX,我们最好自己重新复制或者添加引用。因为我们DX创建的内存我们无法随心所欲的控制。所以我们需要对网格接口添加引用等操作,这样只有当我们也释放这个接口,这个接口对应的内存再会被销毁。
  6. 在创建Effect文件时要注意,我们必须要知道每个顶点至多可以被几个骨骼影响。因为这个数字会影响顶点数据中混合权重数组(Weight)的值。假如最多影响是2,那么4个混合权重值中前两个是有效的,后面的就无法保证了。所以我们只能用前两个混合权重值,另外两个不要碰。

我的经验教训:

  1. 为了这个错误,程序出现和难以理解的内存泄露,并耗费我大约1个多小时的时间。错误是这样的,在建立完骨架之后,我从D3DXFRAME中找到的D3DXMESHCONTAINER的指针。然后对其中的mesh添加的引用:pMeshContainer = pFrame->pMeshContainer; pMeshContainer->MeshData.pMesh->AddRef();然后在最后的Destroy中,使用这样的语句释放网格:SAFE_RELEASE( pMeshContainer->MeshData.pMesh );就是这样很正常的处理隐藏的重大问题。解决的方法是修改Destroy的销毁语句:pMeshContainer->MeshData.pMesh->Release(); 当我自己改到这里发现没内存泄露之后,楞了良久,才明白。pMeshContainer指向的是一块共有内存,如果我对这个共有内存进行修改,那么其他试图对这个共有内存进行的操作就会出错。因为SAFE_RELEASE中不光释放对象,还将对象置为空。所以其他的SAFE_RELEASE就行不通了。所以我们要对物体网格指针备份一个专门给自己用。原本看案例的代码发现其备份了一个,我还想又是一个多余操作,现在看来还是自己太大意啊。毕竟MS的总体水平排在那。

以上都是自己这个水平的理解。如有不对,敬请指出。共同进步,不胜感激。

最后附上很好的学习资料:d3dx_skinnedmesh.pdf,可以到我的资源处下载。

SkinnedMesh DX9相关推荐

  1. gpu programming guide for g80(dx9)

    为什么80%的码农都做不了架构师?>>>    http://developer.nvidia.com/object/gpu_programming_guide.html 大量零散的 ...

  2. 【转】3D图形引擎(DX9): FX

    [转]3D图形引擎(DX9): FX 做图形程序已经很多年了,积累了一些经验. 来这个论坛也有好几年了,遇到问题的时候,也会在这里发帖子问,也很感谢大家的回答与帮助,希望能多认识一些朋友,大家多交流. ...

  3. ParallaxOcclusionMapping( POM ) DX9

    ParallaxOcclusionMapping(后面成为POM)是一个不错的高级技术,在我看来它是至今让我印象最深刻的技术.与其说是视差,不如说准确的视线与高度图交点算法.在<Real-tim ...

  4. 创建Direct3D9设备-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(5)

    创建Direct3D9设备 若要创建 Direct3D 设备,请先创建 Direct3D 对象 (请参阅 Direct3DCreate9) . Direct3D 对象创建的所有呈现设备共享相同的物理资 ...

  5. 一篇文章搞定DX9.0c 环境里的3DXSpriet !!

    四年前写过一篇<一篇文章搞定3DXSpriet !! >得到了很多的反馈,现在那篇文章中的好多代码已经不可以再用了,所以对其中的一些代码做了改动,为了方便初学者掌握3DXSpriet,再写 ...

  6. DX9的一些方法介绍-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(9)

    DX9的一些方法介绍(IDirect3D9) 在前边的源码中,引用了一些DX9的方法,我这里做了一个笔记,大家可以看看. 1,IDirect3DDevice9::SetTexture 方法:将纹理分配 ...

  7. 实战!从画面到性能DX9/DX10/DX11全对比

    和WIN7同行 HD5000显卡独享DX11 Windows7带着DirectX 11发布了已经有了一段时间了,但目前市场里我们只能看到来自ATI的HD5000系列 显卡能够提供对DirectX 11 ...

  8. DX9贴图-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(11)

    DX9贴图 先准备2张图片,蜘蛛为m1.png,单眼怪物为m2.png 创建一个Form1.frm,输入如下源码: Private Sub Form_Load()'新手注意:游戏编程中, '通常将窗体 ...

  9. DX9显示文字-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(14)

    DX9显示文字 创建Form1,输入以下源码: Private Sub Form_Load()'新手注意:游戏编程中, '通常将窗体的 BorderStyle 设置为"Fixed singl ...

最新文章

  1. 负载均衡算法-权重随机均衡
  2. Belkatalog CMS SQL 注入漏洞(图)
  3. 【缅怀妈妈系列诗歌】之十:妈妈,孩儿答应您
  4. 第 6 期 Arthas 征文活动开启!(内附第 5 期获奖名单)
  5. mysqlclient==1.3.7对应mysql版本_Python通过MySQLdb访问操作MySQL数据库
  6. Python02 标准输入输出、数据类型、变量、随记数的生成、turtle模块详解
  7. day32—CSS多列布局学习
  8. linux下的ssh端口号修改,如何在 Linux 中更改 SSH 端口
  9. 转----ASP.NET中常用的优化性能方法
  10. django ----CBV中加装饰器
  11. Android studio ,Gradle 添加so库
  12. UIWebView控件的简易浏览器小案例
  13. 1114. Family Property (25)-PAT甲级真题(并查集)
  14. jquery获得select option的值 和对select option的操作
  15. python中格式化输出是什么意思_Python中 {:.0f} 格式化输出,{0:^30}什么意思 . format(name))...
  16. 小心你的Python程序,它会是你的一面镜子。小方块闯迷宫.py源代码简析。
  17. 巧用位运算实现大小写转换
  18. LATEX 幻灯片入门
  19. 工序作业指导书怎么做?如何制作工序作业指导书?
  20. java关于hashmap编程题_在Java中,关于HashMap类的描述,以下说法错误的是( )。...

热门文章

  1. moodle php平台,“MOODLE平台安装与使用”
  2. Single Image Reflection Removal
  3. 转:如何选择 Excel 中的数据列,然后将数据粘贴到文本文件中?
  4. 对话Wetez卡咩:项目方才是Staking经济中最大的赢家 | 陀螺非正式会谈
  5. 我的天空 我的未来 我的梦
  6. mysql反向递归查询_递归查询所有下级部门树形结构反向递归获取所有ID集合
  7. 人工神经元网络基本构成,人工神经网络主要有
  8. MySQL运维(二)MySQL分库分表概念及实战、读取分离详解
  9. 数据可视化作品有哪些
  10. 量化投资:为什么在中国发展之路任重而道远