SkinnedMesh DX9

本想学习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,可以到我的资源处下载。

时间: 2024-09-20 00:28:41

SkinnedMesh DX9的相关文章

vc6 0-请教一下安装了DX9,VC6.0不显示函数的问题

问题描述 请教一下安装了DX9,VC6.0不显示函数的问题 请教一下各位大神,我在电脑上安装了DX9 sdk之后,在目录中把include和lib都包含进去了,但是在写的过程中像打"lpD3DDevice->"后没有显示函数的列表,也没有参数提示,这是声明的"LPDIRECT3DDEVICE9"的. 但是声明的"LPDIRECT3DDEVICE"设备后,"lpD3DDevice->"就有函数显示了. 请问一下怎么让

ShadowMap DX9

 ShadowMap基本的思想很简单,首先从聚光灯角度对场景建立并保存场景深度.然后在正常渲染场景中,比较每个渲染点到灯的距离值(或者说到灯的深度值)是否比对应的已经建立在场景深度中的值要大,也就是说要远,如果远证明从当前视点观察的此点在灯角度中看不见,所以该渲染点处于阴影中,否则,不然.   首先分析一下ShadowMap的优劣: 优点: ShadowMap只适合较近距离的阴影投射,由于32位浮点数的精度有限,所以在较远距离下,会将在阴影边界附近出现错误现象.一种是隐隐约约的阴影(即阴影中带有

错误信息-编译DX9程序出现奇怪的错误,请大牛帮忙解决,谢谢

问题描述 编译DX9程序出现奇怪的错误,请大牛帮忙解决,谢谢 1>g:directx 2007included3dx9math.h(787) : error C2143: syntax error : missing ',' before '*' 1>g:directx 2007included3dx9math.h(792) : error C2143: syntax error : missing ',' before '*' 1>g:directx 2007included3dx9m

ParallaxOcclusionMapping( POM ) DX9

ParallaxOcclusionMapping(后面成为POM)是一个不错的高级技术,在我看来它是至今让我印象最深刻的技术.与其说是视差,不如说准确的视线与高度图交点算法.在<Real-time Rendering>中也见过他的前身-ParallaxMapping,但是POM的精确度更高,对于斜视效果也很不错,这将让它在未来的重要技术中占有一席之地.闲话少说,还是重在实质技术.   在DX9的samples中,由ATI提高的POM案例,确实是一个不错的实践机会.看过2006的Dynamic

MultiAnim DX9

这个案例比SkinnedMesh多的我觉得只是与骨骼动画更多的接口的认识.   MultiAnim主要的知识是: 在D3D中,一个动画控制接口有多个轨道,每个轨道上都独立的控制.我们可以控制轨道是否启用,速度,权重,优先级别.然后同个优先级别的每个轨道的动画会按对应的权重进行混合,最后不同优先级别再度混合.   这种独立有条理的结构同时也可以实现一个动画平滑过渡到另一个动画.   这些在我上传的d3dx_skinnedmesh.pdf都提及到了,而且系统全面.这里只总结MultiAnim中给我更

HDRPipeline DX9

 HDR这个词汇在我看过的书或资料中多次出现,从<Real-time Rendering>到SDK里面的偶尔出现,一直对其是一种莫名的感觉,HDR是什么,High Dynamic Range,范围很广,为什么要HDR呢?因为了更好的画面.这些很浅显的认识让我一直云里雾里.终于在DX9的sample中有这么个简单的HDR教学实例,确实让我了解很多.在网上看到3d本身渲染的未经过HDR处理的图片和经过HDR处理过的图片比较起来,HDR所带来的图片确实让我折服.因为HDR处理后的图片让人感到身临其境

ShadowVolume DX9

 之前写过ShadowVolume,但是那是老版本(DX8)的DXSDK中的sample.而老版本并不是一个很好的解决方案.而DX9中的ShadowVolume还算是比较可取的方案.在这里主要对DX9中的ShadowVolume中的重点难点进行梳理.详细的细节,必须参考sample中的代码.   DX9中的shadowVolume最大的特点是建立了阴影体网格,而不是之前DX8中的动态生成轮廓边集合.建立阴影体网格最大的好处就是通过GPU来分担原来由CPU负责的轮廓边识别.而且由于新的阴影体积总体

DX9.0与opengl2.0的转换

问题描述 用DX9.0及HLSL写的地形渲染算法对应转换为opengl2.0来实现,有没有高手从事过相关方面的开发经验或相关资料,望不吝赐教... 解决方案 解决方案二:求解啊....解决方案三:使用ANGLE,你可以搜索ANGLE项目.

Post Process DX9

这个案例是一个大杂烩,它把很多常用的操作以单独模块的形式进行组装以实现一定的效果.这里面最重要的是所有的这些技术都是后处理技术,也就是在正常渲染完成后对生成的场景帧(或者说纹理,图片)进行加工处理.Post Process与以往案例最大的不同在于将物体的几何信息分别存贮在不同的渲染表面中.这样做的好处,在后处理中仍然能得到需要各种的信息.另外后处理的一个强大之处在于,当场景有多个或多种灯光时,我们不用对物体一一采用各种光照模型,因为很多像素对应的fragment(将要写入这个像素的某个物体小碎片