VC++游戏开发随记之四十四.docx
- 文档编号:8496306
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:54
- 大小:3.36MB
VC++游戏开发随记之四十四.docx
《VC++游戏开发随记之四十四.docx》由会员分享,可在线阅读,更多相关《VC++游戏开发随记之四十四.docx(54页珍藏版)》请在冰豆网上搜索。
VC++游戏开发随记之四十四
Vc++2010游戏开发笔记四十四浅墨DirectX教程十二网格模型和X文件使用面面观
在本篇文章中,我们一起详细探索了Direct3D网格相关的知识,对当前两款主流的三维建模软件(3DSMax和Maya)进行了介绍,了解了如何从3DSMax中导出X文件,以及如何从X文件加载三维模型到DirectX游戏程序中。
文章最后,我们依旧配了一个比较好玩的demo来让大家对本篇文章所学的知识融会贯通,最后提供了这个demo详细注释的源代码下载。
首先我们复习一个之前讲过的概念。
在计算机所描绘的3D世界中,所有的物体模型(如树木,人物,山峦)都是通过多边形网格来逼近表示的,就像这幅DOTA中的英雄幻影刺客(PA)的对比图一样:
幻影刺客镇文~嗯,我们开讲~
一、网格模型技术的前生今世
网格模型是一种将物体模型的顶点数据、纹理、材质等信息存储在一个外部文件中的3D物体模型。
对于那些简单的图元描述的图形,比如点,线,三角形等等,我们可以通过写代码指定顶点数据,索引数据,法线向量,纹理和材质等等信息。
但对于复杂的3D物体的话,采用这种方式显然是不现实的。
因此,Direct3D提供了一种称作网格模型的技术,可以从各种特定的文件格式中读取和绘制3D图形,极大地方便了游戏的开发。
使用网格模型最普遍的方式是从外部的3D模型文件中加载一个网格。
而这些3D模型通常都是由3D建模软件生成的,比较复杂的网格数据。
目前市面上主流的3D建模软件有3DSMax和Maya。
而目前流行的3D模型文件格式有.3ds、.max、.obj以及.mb。
其中.3ds、.max为3DSMax常用的格式,.mb为Maya常用的格式,而.obj为3DSMax和Maya通用的文件格式。
二、认识三维建模软件
再不厌其烦地说一遍,我们在通常的三维游戏开发中,常常要涉及到非常复杂的三维物体数据模型,如果用我们之前讲的知识,顶点缓存索引缓存,通过写代码来构造这些三维模型,显然是不合实际的。
这些复杂物体的模型通常需要利用专业的三维建模软件来制作。
目前市面上主流的3D建模软件有3DSMax和Maya。
这两款在三维建模行业作为竞争对手的软件,目前同为Autodesk公司所有,这倒是有些令人匪夷所思。
下面我们先来分别介绍一下当前市场上主流的三维建模软件(当然,不仅仅是用于三维建模这么简单)3DSMax和Maya。
Ⅰ、3DSMax软件简介
3DStudioMax,常简称为3dsMax或MAX,是Autodesk公司开发的基于PC系统的三维动画渲染和制作软件。
其前身是基于DOS操作系统的3DStudio系列软件,最新版本是2012。
在WindowsNT出现以前,工业级的CG制作被SGI图形工作站所垄断。
3DStudioMax+WindowsNT组合的出现一下子降低了CG制作的门槛,首选开始运用在电脑游戏中的动画制作,后更进一步开始参与影视片的特效制作,例如X战警II,最后的武士等。
3dsMax软件截图:
Ⅱ、Maya软件简介
Maya是美国Autodesk公司出品的世界顶级的三维动画软件,应用对象是专业的影视广告,角色动画,电影特技等。
Maya功能完善,工作灵活,易学易用,制作效率极高,渲染真实感极强,是电影级别的高端制作软件。
Maya软件截图:
Ⅲ、Maya和3dsMax的区别与联系
MAYA和3dMax都是高端3D软件,两者之间都有很多相同的功能,像创建模型,渲染材质,动画制作等等.但就运用实际情况而言,Max更加适合于游戏,建筑学,室内设计等等,而MAYA可以说是专门为影视特效而生的一款软件,这也是当初Alias设计MAYA的意图.MAYA在如角色动画/运动学模拟/以及完美的材质系统,使得MAYA所创造出来的3维效果如此逼真,可以说全世界的电影特效工作室都必须用到MAYA
MAYA的用户界面也比3dsmax要人性化点,Maya是Alias|Wavefront(2003年7月更名为Alias)公司的产品,作为三维动画软件的后起之秀,深受业界欢迎和钟爱。
MAYA软件应用主要是动画片制作、电影制作、电视栏目包装、电视广告、游戏动画制作等。
3dsmax软件应用主要是动画片制作、游戏动画制作、建筑效果图、建筑动画等。
MAYA的基础层次更高,3dsmax属于普及型三维软件,有条件当然学MAYA。
Maya的CG功能十分全面,建模、粒子系统、毛发生成、植物创建、衣料仿真等等。
可以说,当3dsmax用户匆忙地寻找第三方插件时,Maya用户已经可以早早地安心工作了。
可以说,从建模到动画,到速度,Maya都非常出色。
Maya主要是为了影视应用而研发的。
3dMAX和Maya都是功能强大的三维制作软件,各有很大优点,但是,不同的行业用不同的软件会让制作比较轻松,所以说,3dMAX和Maya究竟哪个好,哪个更好用与所从事的行业有着一定联系。
3dMAX在建筑动画效果上要强于Maya,而Maya在影视动画上又略胜于3dmax,两款软件没有太大的本质性区别,只是看个人掌握哪个软件比较顺手罢了。
目前,业内已开始对软件使用做了一些细分。
3dmax主要用来做建筑,国内多数公司喜欢拿他做游戏,附带着可以做影视动画,建模比较方便。
Maya主要用来做影视动画,在动画和动力学模块上很强大,国内不少游戏公司慢慢将max转Maya了。
其他的栏目包装,广告等两者都可用到。
最终没有谁好谁坏之分,只有用处不同,两软件都是相通的。
以前国内学Maya的不多,因为没有中文版,教程也少,现在不一样了,教程也是不少了。
3dMAX和Maya各有其优势,用户可以根据自身的项目需求自主选择软件,其最大的区别就是3dMAX可以不费力气得到你想要的东西,Maya可能要花很多精力但是可以做出随心所欲的东西,灵活性要强。
Maya和3dsMax都可以做出如下效果(虽然这些模型本身是3dsMax做出来的):
擎天柱
大黄蜂
好了,认识到3D制作软件的神奇了,下面我们对本文的主角——X文件来一个介绍。
三、对X文件的认识
在Direct3D中,我们一般都采用.X文件来存储网格数据。
X文件格式是微软定义的3D模式文件格式,其中包括网格的纹理,动画以及用户定义对象的一些数据等。
需要注意的是,.X文件通常并未存储具体的纹理数据,它只包含纹理贴图的文件名,所以我们常常会发现,X文件会和一些图片文件比如.BMP、.DDS一同出没,放在一起,比如本次demo中我们使用的初音模型,除了.X文件本身miki.X之外,还有数十张BMP位图纹理图片配合着miki.X。
四、从3DSMax中导出.X文件方法详解
由于我们是初次接触三维模型文件的载入,当然得先学走,也就是先学Direct3D自带的.X模型文件的载入和使用,.X文件作为微软定义的3D模式文件格式,Direct3D的默认三维模型格式,Direct3D自然对其有着非常好的支持度,有大量的函数辅助着.X文件的使用。
至于学到后头了,我们就可以通过一些代码的编写(或者说使用游戏引擎的时候),直接在Direct3D中使用3ds、.max、.obj以及.mb等主流三维建模软件本身的文件。
不过现在我们作为初学者,当前掌握好.X模型文件使用的各方各面,就能应付绝大多数场合了。
想要从3DSMax中导出.X文件,简单来说,有三个要素,我们分别来详细说一说。
第一个要素,当然是3DSMax软件的下载和安装。
浅墨目前安装的是3DSMax2012的32位版。
大家可以XX一下,下载并安装,至于软件的破解,网上教程很多,这里就不具体讲了。
第二个要素,Panda插件的下载和配置。
这个Panda插件熟话说就是能让3DSMax支持导出.X格式文件的一个插件。
通常我们在3DSMax中打开一个3D模型后,点左上角的【主菜单
】->【导出】之后,在弹出的导出选项框中并没有我们想要的.X文件。
所以我们需要下载并配置一下与我们3DSMax相对应的Panda插件,来让导出选项中有我们的.X文件,这样才能完成3DS中的模型到.X文件的导出。
以便我们在我们的DirectX游戏程序中通过.X文件来载入好看的三维模型。
3DSMax2012版本的Panda插件浅墨已经为大家准备好了,链接如下:
点击转到下载页面
下载之后,打开压缩包,把里面的对应安装版本位数的dle文件(32位对应X86字样,64位对应X64字样)放到3dsMax安装目录下的plugins之中,然后重启3dsMax即可。
例如浅墨自己的3dsMax2012安装在D盘的D:
\ProgramFiles\Autodesk\目录之下,那么对应的就在D:
\ProgramFiles\Autodesk\3dsMax2012\plugins目录中添加dle插件文件,如图:
然后,重启一下3DSmax2012,我们就可以发现,导出选项中有了X文件导出项了。
第三个要素,也就是导出X文件的具体步骤了。
首先,正所谓巧妇难为无米之炊,我们需要有一个导出的对象,也就是一个三维的模型。
模型嘛,可以自己用3dsMax现场做(想做出个像模像样的模型一时半会儿显然不现实,而且这一般都是美工童鞋的工作,我们可是写程序的筒子们),也可以自己去网上下载,这里推荐一个论坛,有大量的3D模型资源:
Max用的是.max,而Maya用的是.mb,而另外一种.obj是万金油格式,3dsMax和Maya两者都可用,所以想在3dsMax与Maya之间通用的话,就用.obj)
好了,继续讲,我们下载好了Dota英雄幻影刺客的.max模型,解压缩包,点击HeroWarden.max模型文件,于是就打开了这个模型,如图。
然后,就像之前提到的,点击左上角的【主菜单
】->【导出】。
如图:
这时就会弹出一个【选择要导出的文件】对话框。
在弹出的这个对话框的【保存类型】中选择【PandaDirectX(*.X)】,然后自己取一个文件名(这里我们取名Warden,魔兽3中幻影刺客模型所对应的人物名称——守望者),设定好保存的路径,点【保存】。
如图。
然后会弹出一个名为【PandaSoftDirectXExporter】的窗口,在里面我们可以进行一些导出模型参数的设定和修改。
如下:
如果没有什么需要特殊设置的,点【确定】就行了。
然后经过3dsMax的处理,我们就发现在我们设定的保存路径下多了.X文件以及配套的纹理了。
这样,如果我们想要在我们写的游戏程序中使用这个幻影刺客(守望者)的三维模型,把这两个文件一起放到我们工程中相应的地方就可以了。
另外提一点,Maya中可以用cvXporter插件来导出X文件,对应于3dsMax中的Panda插件。
之前讲了那么多无非是在为.X文件的诞生造势,下面就开始隆重介绍如何在Direct3D程序中载入X文件的具体知识吧~
而想利用.X文件来在游戏程序中载入三维模型的话,首先就需要将.X文件中的各种数据分别加载到内存中,而这些数据主要包括顶点数据、材质数据和纹理数据等等。
首先,我们需要介绍一下与网格模型相关的一个重要的接口——ID3DXMESH。
五、网格模型接口ID3DXMESH
在Direct3D中,微软为我们提供了ID3DXMesh接口表示网格,这个接口继承自ID3DXBaseMesh接口。
网格模型接口ID3DXMesh实际上是三维物体的顶点缓存的集合,他将为我们创建顶点缓存、定义灵活顶点格式和绘制顶点缓冲区等功能封装在一个COM对象中,这样复杂三维物体的绘制就显得非常简便了。
其中,ID3DXMESH接口中的D3DXCreateMesh()可用于创建一个Direct3D网格模型对象,我们可以在MSDN中查到该函数声明是这样的:
[cpp] viewplaincopyprint?
1.HRESULT D3DXCreateMesh(
2. _In_ DWORD NumFaces,
3. _In_ DWORD NumVertices,
4. _In_ DWORD Options,
5. _In_ const LPD3DVERTEXELEMENT9*pDeclaration,
6. _In_ LPDIRECT3DDEVICE9pD3DDevice,
7. _Out_ LPD3DXMESH *ppMesh
8.);
然后开始介绍一下这个函数。
■第一个参数,DWORD类型的NumFaces,表示创建网格模型的多边形数目。
■第二个参数,DWORD类型的NumVertices,表示创建网格的顶点数目。
■第三个参数,DWORD类型的Options,表示创建网格时的附加选项,他的取值为D3DXMESH枚举体中的一个或者多个值。
这个枚举体定义如下:
[cpp] viewplaincopyprint?
1.typedef enum D3DXMESH {
2. D3DXMESH_32BIT = 0x001,
3. D3DXMESH_DONOTCLIP = 0x002,
4. D3DXMESH_POINTS = 0x004,
5. D3DXMESH_RTPATCHES = 0x008,
6. D3DXMESH_NPATCHES = 0x4000,
7. D3DXMESH_VB_SYSTEMMEM = 0x010,
8. D3DXMESH_VB_MANAGED = 0x020,
9. D3DXMESH_VB_WRITEONLY = 0x040,
10. D3DXMESH_VB_DYNAMIC = 0x080,
11. D3DXMESH_VB_SOFTWAREPROCESSING =0x8000,
12. D3DXMESH_IB_SYSTEMMEM = 0x100,
13. D3DXMESH_IB_MANAGED = 0x200,
14. D3DXMESH_IB_WRITEONLY = 0x400,
15. D3DXMESH_IB_DYNAMIC = 0x800,
16. D3DXMESH_IB_SOFTWAREPROCESSING =0x10000,
17. D3DXMESH_VB_SHARE = 0x1000,
18. D3DXMESH_USEHWONLY = 0x2000,
19. D3DXMESH_SYSTEMMEM = 0x110,
20. D3DXMESH_MANAGED = 0x220,
21. D3DXMESH_WRITEONLY = 0x440,
22. D3DXMESH_DYNAMIC = 0x880,
23. D3DXMESH_SOFTWAREPROCESSING =0x18000
24.} D3DXMESH, *LPD3DXMESH;
一般情况下,我们都把这个Options取为D3DXMESH_SYSTEMMEM或者D3DXMESH_MANAGED,表示对Direct3D顶点缓冲区和索引缓冲区使用D3DPOOL_SYSTEMMEM或者D3DPOOL_MANAGED内存。
■第四个参数,constLPD3DVERTEXELEMENT9类型的*pDeclaration,表示顶点包含哪些信息。
这个参数的作用类似于我们之间一直在用的灵活顶点格式(FVF),表示顶点包含了哪些具体数据,但是它却高于灵活顶点格式。
它的类型LPD3DVERTEXELEMENT9表示顶点元素,主要用于我们来没讲到的可编程渲染流水线之中,在此我们暂且不用去多做考虑。
■第五个参数,LPDIRECT3DDEVICE9类型的pD3DDevice,就是我们的金钥匙,Direct3D设备的指针了。
■第六个参数,LPD3DXMESH类型的*ppMesh,指向我们创建好的网格模型对象指针的地址,用于返回创建好的网格模型对象。
可以说我们调用D3DXCreateMesh就是为了创建并得到这个指针地址。
后面关于我们创建好的网格模型的访问,都靠这个ppMesh参数了。
需要注意的是,这个创建好网格模型对象的D3DXCreateMesh函数我们通常很少直接去用它,而且直接用它往往也意义不大。
它总是“真人不露相”,被封装在了其他Direct3D函数之中,默默地为我们服务。
介绍完网格模型接口ID3DXMESH相关的知识,下面就来看看从X文件载入模型的具体步骤。
六、X文件模型载入三步曲
Ⅰ.三步曲之一:
通过.X文件加载网格模型
上面讲到了D3DXCreateMesh函数很少去直接应用,因为我们常常都是通过载入.X文件来生成网格模型的,用到的函数是D3DXLoadMeshFromX。
我们可以在MSDN中查到这个函数的声明如下:
[cpp] viewplaincopyprint?
1.HRESULT D3DXLoadMeshFromX(
2. _In_ LPCTSTR pFilename,
3. _In_ DWORD Options,
4. _In_ LPDIRECT3DDEVICE9 pD3DDevice,
5. _Out_ LPD3DXBUFFER *ppAdjacency,
6. _Out_ LPD3DXBUFFER *ppMaterials,
7. _Out_ LPD3DXBUFFER *ppEffectInstances,
8. _Out_ DWORD *pNumMaterials,
9. _Out_ LPD3DXMESH *ppMesh
10.);
■第一个参数,LPCTSTR类型的pFilename,显然就是一个指向我们需要加载的.X文件的磁盘路径和文件名的字符串了。
■第二个参数,DWORD类型的Options,表示创建网格时的附加选项,他的取值为D3DXMESH枚举体中的一个或者多个值。
这个参数我们刚才在讲D3DXCreateMesh时已经讲过了,具体参看D3DXCreateMesh的第三个参数,在这里就不赘述了。
■第三个参数,LPDIRECT3DDEVICE9类型的pD3DDevice,也就是我们的金钥匙,Direct3D设备的指针。
■第四个参数,LPD3DXBUFFER类型的*ppAdjacency,用于保存加载网格的邻接信息,也就是包含每个多边形周围的多边形信息的缓冲区的内存地址。
■第五个参数,LPD3DXBUFFER类型的*ppMaterials,用于保存网格的所有子集的材质,指向用于存储模型材质和纹理文件名的缓冲区的地址,而材质的数目存在之后第七个参数pNumMaterials中了。
■第六个参数,LPD3DXBUFFER类型的*ppEffectInstances,用于存储网格模型的特殊效果,指向用于存储模型效果实例的缓冲区的内存地址,这个参数通常设为NULL就可以了。
■第七个参数,DWORD类型的*pNumMaterials,它配合着第五个参数,用于存储所有子集材质的数目。
■第八个参数,LPD3DXMESH类型的*ppMesh,指向我们从文件生成的Direct3D网格模型指针的地址。
可以说我们调用D3DXLoadMeshFromX就是为了从文件加载X文件的模型信息并进行模型的创建,从而能得到这个指向创建好的模型的指针地址。
后面关于我们创建好的网格模型的访问,都靠这个ppMesh参数了。
我们应该可以发现,在上面我们的D3DXLoadMeshFromX函数中引入了一个新的Direct3D类型,他就是LPD3DXBUFFER。
LPD3DXBUFFER因数据操作的方便性而诞生,我们称它为泛型数据结构。
它的好处是可以存储顶点位置坐标、材质、纹理等多种类型的Direct3D数据,而不必对每种数据都去声明一种函数接口类型。
可使用接口函数ID3DXBuffer:
:
GetBufferPointer()获取缓冲区中的数据,使用ID3DXBuffer:
:
GetBufferSize()获得缓冲区数据大小、这两个接口函数的声明如下:
[cpp] viewplaincopyprint?
1.LPVOID GetBufferPointer();
2.DWORD GetBufferSize();
没错,这就是原型声明,因为这两个函数都没有参数,所以他们的身子显得非常单薄。
比如,我们要从网格模型中提取材质属性和纹理文件名,那么代码就是像这样写:
[cpp] viewplaincopyprint?
1.D3DXMATERIAL *pMtrls =(D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();
Ⅱ.三步曲之二:
载入材质和纹理
如果之前的D3DXLoadMeshFromX函数调用成功的话,那么参数ppMaterials就会获得.X文件中三维模型的材质和纹理等信息,而pNumMaterials参数就会获得材质的数目。
X文件中的材质信息是以D3DXMATERIAL结构类型的数组形式储存的。
其中,该结构定义了D3DMATERIAL9结构类型的成员和一个指向以NULL结尾的字符串指针,而该字符串用于指定与网格子集相关的纹理贴图文件名。
我们可以在MSDN中查到D3DXMATERIAL结构体的定义如下:
[cpp] viewplaincopyprint?
1.typedef struct D3DXMATERIAL {
2. D3DMATERIAL9 MatD3D; //材质信息
3. LPSTR pTextureFilename; //纹理贴图文件
4.} D3DXMATERIAL, *LPD3DXMATERIAL;
当我们加载X文件后,需要遍历整个D3DXMATERIAL结构类型的数组,用于取出保存在ID3DXBuffer接口对象中的材质信息。
由于X文件中并未存储具体的纹理数据,它只包含纹理贴图的文件名,因此需要我们自己根据该文件名创建相应的纹理对象。
就像这样:
[cpp] viewplaincopyprint?
1.// 从X文件中加载网格数据
2. LPD3DXBUFFER pAdjBuffer = NULL;
3. LPD3DXBUFFER pMtrlBuffer =NULL;
4.
5.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VC 游戏 开发 随记 四十四