DirectX游戏编程第11章全20章

上传人:枫** 文档编号:569820177 上传时间:2024-07-31 格式:PPT 页数:29 大小:611.51KB
返回 下载 相关 举报
DirectX游戏编程第11章全20章_第1页
第1页 / 共29页
DirectX游戏编程第11章全20章_第2页
第2页 / 共29页
DirectX游戏编程第11章全20章_第3页
第3页 / 共29页
DirectX游戏编程第11章全20章_第4页
第4页 / 共29页
DirectX游戏编程第11章全20章_第5页
第5页 / 共29页
点击查看更多>>
资源描述

《DirectX游戏编程第11章全20章》由会员分享,可在线阅读,更多相关《DirectX游戏编程第11章全20章(29页珍藏版)》请在金锄头文库上搜索。

1、第11章 网格(1) 在在DirectX中,除了中,除了ID3DXMesh接口从接口从ID3DXBaseMesh接口继承外,另一个主要的接口继承外,另一个主要的Mesh接口接口ID3DXPMesh(Progressive Mesh)也从也从ID3DXBaseMesh接口继承,如何运用不接口继承,如何运用不同类型的同类型的Mesh接口,也将是本章讨论的内容。接口,也将是本章讨论的内容。主要目标:学习ID3DXMesh对象的内部数据组织。学习ID3DXMesh对象的创建。学习ID3DXMesh对象的优化方法。渲染ID3DXMesh对象。211.1 几 何 信 息ID3DXBaseMesh接口包括了

2、一个用于保存网格中顶点数据的接口包括了一个用于保存网格中顶点数据的顶点缓冲区和一个用于记录三角形顶点在顶点缓冲区中索引信顶点缓冲区和一个用于记录三角形顶点在顶点缓冲区中索引信息的索引缓冲区。息的索引缓冲区。在在ID3DXBaseMesh中,可以通过下面的方法得到指向这些缓中,可以通过下面的方法得到指向这些缓冲区的指针:冲区的指针:HRESULT ID3DXMesh:GetVertexBuffer(LPDIRECT3DVERTEXBUFFER9 *ppVB);HRESULT ID3DXMesh:GetIndexBuffer(LPDIRECT3DINDEXBUFFER9 *ppIB);可以通过下列

3、方式对这些方法进行调用:可以通过下列方式对这些方法进行调用:IDirect3DVertexBuffer9 *vb = 0;Mesh-GetVertexBuffer(&vb);IDirect3DIndexBuffer9 *ib = 0;Mesh-GetIndexBuffer(&ib);311.1 几 何 信 息如果需要锁定缓冲区以进行缓冲区读写,可以通过下如果需要锁定缓冲区以进行缓冲区读写,可以通过下面的方法来实现,注意这里锁定的将是整个顶点缓冲面的方法来实现,注意这里锁定的将是整个顶点缓冲区或索引缓冲区:区或索引缓冲区:HRESULT ID3DXMesh:LockVertexBuffer(DW

4、ORD Flags, BYTE *ppData);HRESULT ID3DXMesh:LockIndexBuffer(DWORD Flags, BYTE *ppData);对锁定缓冲区的访问结束后,应该调用相应的对锁定缓冲区的访问结束后,应该调用相应的Unlock方法解除缓冲区锁定,如下所示:方法解除缓冲区锁定,如下所示:HRESULT ID3DXMesh:UnlockVertexBuffer();HRESULT ID3DXMesh:UnlockIndexBuffer();411.1 几 何 信 息下面是下面是ID3DXMesh接口提供的用于获得相关几接口提供的用于获得相关几何数据信息的另外几

5、个方法:何数据信息的另外几个方法:DWORD GetFVF(); /返回一个描述顶点格式的DWORDDWORD GetNumVertices(); /返回顶点缓冲区中的顶点数目DWORD GetNumBytesPerVertex(); /返回每个顶点所用的字节数DWORD GetNumFaces(); /获得网格的面数511.2 网格子集(Subset)和属性缓冲区网格由一个或者多个网格子集组成。网格子集网格由一个或者多个网格子集组成。网格子集是一个网格中可被按照同样属性进行渲染的三是一个网格中可被按照同样属性进行渲染的三角形的集合。角形的集合。 图图11.1阐述了一个代表房子的网格怎样被划分

6、阐述了一个代表房子的网格怎样被划分成不同的网格子集。成不同的网格子集。611.2 网格子集(Subset)和属性缓冲区每个三角形对应的子集每个三角形对应的子集ID被存储在网格的属性缓冲区被存储在网格的属性缓冲区中,这个缓冲区是一个中,这个缓冲区是一个DWORD类型的数组。由于网类型的数组。由于网格中的每一个面格中的每一个面(一个三角形对应一个面一个三角形对应一个面)在属性缓冲在属性缓冲区中都有一个对应的元素,因此缓冲区中的元素个数区中都有一个对应的元素,因此缓冲区中的元素个数等于网格中面的数量。等于网格中面的数量。 图图11.2展示了属性缓冲区中的元素与索引缓冲区中的展示了属性缓冲区中的元素与

7、索引缓冲区中的三角形之间的对应关系。三角形之间的对应关系。711.2 网格子集(Subset)和属性缓冲区通过如下代码,可以锁定属性缓冲区,通过如下代码,可以锁定属性缓冲区,并获得指向属性缓冲区的指针:并获得指向属性缓冲区的指针:DWORD *buffer = 0;Mesh-LockAttributeBuffer(lockingFlags, &buffer);/.读或写属性缓冲区Mesh-UnlockAttributeBuffer();811.3 网格的渲染ID3DXMesh接口提供了接口提供了DrawSubset方法来渲染指定方法来渲染指定网格子集中的所有三角形。网格子集中的所有三角形。 如

8、果要渲染整个网格,就需要渲染网格中的所有子集。如果要渲染整个网格,就需要渲染网格中的所有子集。可以按顺序为每个网格子集指定网格可以按顺序为每个网格子集指定网格ID为为0、1、2、n-1,这里,这里n是网格子集的数量,然后依次指定每是网格子集的数量,然后依次指定每个网格子集对应的材质和纹理。最后,通过简单的循个网格子集对应的材质和纹理。最后,通过简单的循环就可以渲染一个完整的网格:环就可以渲染一个完整的网格:for(int i=0; iSetMaterial(mtrlsi);Device-SetTexture(0, texturesi);Mesh-DrawSubset(i);911.4 网 格

9、优 化网格的顶点和索引可以进行重新组织以便更有网格的顶点和索引可以进行重新组织以便更有效率地渲染网格,即对网格进行优化。在效率地渲染网格,即对网格进行优化。在ID3DXMesh接口中对网格的优化通过如下方法接口中对网格的优化通过如下方法进行:进行:HRESULT ID3DXMesh:OptimizeInplace( DWORD Flags, CONST DWORD *pAdjacencyIn, DWORD *pAdjacencyOut, DWORD *pFaceRemap, LPD3DXBUFFER *ppVertexRemap);1011.4 网 格 优 化另一个可以使用的、与另一个可以使用

10、的、与OptimizeInplace类似的方法类似的方法是是Optimize。使用。使用Optimize时,可以通过最后一个参时,可以通过最后一个参数返回一个新的优化过的网格,而不是对所调用的网数返回一个新的优化过的网格,而不是对所调用的网格本身进行优化。格本身进行优化。此方法的原型如下:此方法的原型如下:HRESULT ID3DXMesh:Optimize( DWORD Flags, CONST DWORD *pAdjacencyIn, DWORD *pAdjacencyOut, DWORD *pFaceRemap, LPD3DXBUFFER *ppVertexRemap, LPD3DXME

11、SH *ppOptMesh / 通过这个参数传出优化后的网格); 1111.5 网格属性表当使用当使用D3DXMESHOPT_ATTRSORT标志对网格进标志对网格进行优化后,网格中的几何图元将被按照其属性重新划行优化后,网格中的几何图元将被按照其属性重新划分到顶点缓冲区和索引缓冲区的连续存储块中,这些分到顶点缓冲区和索引缓冲区的连续存储块中,这些存储块就是将用于渲染的网格子集,在图存储块就是将用于渲染的网格子集,在图11.3中,几中,几何图元和对应的属性缓冲区都被按照属性排序过,因何图元和对应的属性缓冲区都被按照属性排序过,因此同一种属性的几何图元在缓冲区中是连续的。此同一种属性的几何图元在

12、缓冲区中是连续的。 1211.5 网格属性表这个属性表就是一个存放这个属性表就是一个存放D3DXATTRIBUTERANGE结构的数组。属性表里的每一个元素都对应到网格中结构的数组。属性表里的每一个元素都对应到网格中的一个网格子集,用于描述这个网格子集中的几何图的一个网格子集,用于描述这个网格子集中的几何图元在顶点缓冲区和索引缓冲区中的存储信息。元在顶点缓冲区和索引缓冲区中的存储信息。D3DXATTRIBUTERANGE结构声明如下:结构声明如下:typedef struct _D3DXATTRIBUTERANGE DWORD AttribId;DWORD FaceStart;DWORD Fa

13、ceCount; DWORD VertexStart;DWORD VertexCount; D3DXATTRIBUTERANGE;1311.5 网格属性表通过下面的方法访问网格属性表:通过下面的方法访问网格属性表:HRESULT ID3DXMesh:GetAttributeTable( D3DXATTRIBUTERANGE *pAttribTable, DWORD *pAttribTableSize );这个方法可以用来完成两个任务:这个方法可以用来完成两个任务:返回属性表中存储的元素的数量。通过一个D3DXATTRIBUTERANGE结构的数组来获得指定的属性数据。1411.5 网格属性表如

14、果需要得到属性表里面元素的数量,需要再把第一个参数赋如果需要得到属性表里面元素的数量,需要再把第一个参数赋值为值为0:DWORD numSubsets = 0;Mesh-GetAttributeTable(0, &numSubsets);知道了元素的数量后,就可以直接用当前的属性表来填写知道了元素的数量后,就可以直接用当前的属性表来填写D3DXATTRIBUTERANGE数组了,如下所示:数组了,如下所示:D3DXATTRIBUTERANGE table = new D3DXATTRIBUTERANGE numSubsets;Mesh-GetAttributeTable(table, &num

15、Subsets);同时可以直接用同时可以直接用ID3DXMesh:SetAttributeTable方法来设置方法来设置属性表。下面的例子设置了一个具有属性表。下面的例子设置了一个具有12个网格子集的属性表:个网格子集的属性表:D3DXATTRIBUTERANGE attributeTable12;/ .fill attributeTable array with data/ 用当前数据填充属性表Mesh-SetAttributeTable(attributeTable, 12);1511.6 邻 接 信 息邻接数组是一个邻接数组是一个DWORD类型的数组,邻接数类型的数组,邻接数组中的每一个

16、元素都对应于网格中的一个三角组中的每一个元素都对应于网格中的一个三角形。比如,第形。比如,第i个元素代表了由以下这三个索引个元素代表了由以下这三个索引所组成的三角形:所组成的三角形:A = i3B = i3 + 1 C = i3 + 2注意当邻接数组存储的元素值为注意当邻接数组存储的元素值为ULONG_MAX(=4294967295)时,表示三角形时,表示三角形当前的边没有邻接三角形。当前的边没有邻接三角形。 1611.6 邻 接 信 息由于三角形有三个边,因由于三角形有三个边,因此每一个三角形都会有三此每一个三角形都会有三个邻接三角形,在图个邻接三角形,在图11.4中,每一个三角形都在邻中,

17、每一个三角形都在邻接数组里面有三个对应元接数组里面有三个对应元素来指明与其邻接的三角素来指明与其邻接的三角形。形。 邻接数组的大小必须为网邻接数组的大小必须为网格中的面数的三倍格中的面数的三倍(假设面假设面为三角形为三角形),用来存放网格,用来存放网格中每个三角形对应的三个中每个三角形对应的三个邻接三角形的索引值。邻接三角形的索引值。1711.6 邻 接 信 息许多许多D3DX的网格创建函数都可以输出邻接信的网格创建函数都可以输出邻接信息,也可用下面的方法来获得邻接信息:息,也可用下面的方法来获得邻接信息:HRESULT ID3DXMesh:GenerateAdjacency( FLOAT f

18、Epsilon, DWORD *pAdjacency);例如:例如:DWORD adjacencyInfoMesh-GetNumFaces() * 3;Mesh-GenerateAdjacency(0.001f, adjacencyInfo);1811.7 网格的克隆(Cloning)需要把一个网格的数据拷贝到另一个网格中去,需要把一个网格的数据拷贝到另一个网格中去,这个工作可以通过这个工作可以通过ID3DXBaseMesh:CloneMeshFVF方法来完方法来完成:成: HRESULT ID3DXMesh:CloneMeshFVF( DWORD Options, DWORD FVF, LP

19、DIRECT3DDEVICE9 pDevice, LPD3DXMESH *ppCloneMesh);1911.7 网格的克隆(Cloning)注意这个方法允许目标网格的灵活顶点格式和源网格注意这个方法允许目标网格的灵活顶点格式和源网格的灵活顶点格式不同。例如,假设现有的网格的灵活的灵活顶点格式不同。例如,假设现有的网格的灵活顶点格式为顶点格式为D3DFVF_XYZ,而需要灵活顶点格式为,而需要灵活顶点格式为D3DFVF_XYZ| D3DFVF_NORMAL的网格,那么可的网格,那么可以按照以下方法编写程序:以按照以下方法编写程序:/假定mesh和device都是可用的ID3DXMesh *cl

20、one = 0;Mesh-CloneMeshFVF( Mesh-GetOptions(), / 使用与源网格同样的设置 D3DFVF_XYZ | D3DFVF_NORMAL,/ 指定目标网格的FVF Device, &clone);2011.8 网格的创建(D3DXCreateMeshFVF)下面显示了如何使用下面显示了如何使用D3DXCreateMeshFVF函函数来创建一个网格:数来创建一个网格: HRESULT D3DXCreateMeshFVF( DWORD NumFaces, DWORD NumVertices, DWORD Options, DWORD FVF, LPDIRECT3

21、DDEVICE9 pDevice, LPD3DXMESH *ppMesh);2111.8 网格的创建(D3DXCreateMeshFVF)还可以用还可以用D3DXCreateMesh方法来创建网格,方法来创建网格,它的原型是:它的原型是:HRESULT D3DXCreateMesh( DWORD NumFaces, DWORD NumVertices, DWORD Options, CONST LPD3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pDevice, LPD3DXMESH *ppMesh);2211.8 网格的创建(D3DXCr

22、eateMeshFVF)D3DXDeclaratorFromFVF通过一个给定的通过一个给定的FVF输出一个输出一个D3DVERTEXELEMENT9结构结构的数组。的数组。注意这里注意这里MAX_FVF_DECL_SIZE是一个枚举是一个枚举变量,定义如下:变量,定义如下:typedef enum MAX_FVF_DECL_SIZE = 18 MAX_FVF_DECL_SIZE;2311.9 示例:创建并渲染一个网格 本节的示例程序将渲染一个代表箱子的网格,本节的示例程序将渲染一个代表箱子的网格,如图如图11.5所示。所示。这个示例展示了在本章讨论的大部分函数,包这个示例展示了在本章讨论的大

23、部分函数,包括下面的操作:括下面的操作:创建一个网格。为网格填充立方体的几何信息。指定网格中的网格子集。创建网格邻接信息。优化网格。渲染网格。2411.9 示例:创建并渲染一个网格在函数中首先创建一个网格:在函数中首先创建一个网格:bool Setup()HRESULT hr = 0;hr = D3DXCreateMeshFVF(12,24,D3DXMESH_MANAGED,Vertex:FVF,Device,&Mesh);要完成这些工作,先锁定这两个缓冲区,然后把数据要完成这些工作,先锁定这两个缓冲区,然后把数据填写到缓冲区中:填写到缓冲区中:参见教材P1702511.9 示例:创建并渲染一

24、个网格在这个示例中,指定索引缓冲区里的前在这个示例中,指定索引缓冲区里的前4个三角形存在于网格个三角形存在于网格子集子集0中,接下来中,接下来4个三角形存在于网格子集个三角形存在于网格子集1中,最后中,最后4个三角个三角形形(总共总共12个个)存在于网格子集存在于网格子集2中,可以通过下面的代码来完中,可以通过下面的代码来完成这些工作:成这些工作:参见教材P170在优化网格之前,必须要计算出网格的邻接信息:在优化网格之前,必须要计算出网格的邻接信息:std:vector adjacencyBuffer(Mesh-GetNumFaces() * 3);Mesh-GenerateAdjacency

25、(0.0f, &adjacencyBuffer0);然后就可以进行网格的优化了:然后就可以进行网格的优化了:hr = Mesh-OptimizeInplace(D3DXMESHOPT_ATTRSORT |D3DXMESHOPT_COMPACT |D3DXMESHOPT_VERTEXCACHE,&adjacencyBuffer0,0, 0, 0);2611.9 示例:创建并渲染一个网格下面通过这个示例输出的下面通过这个示例输出的Mesh Dump.txt文件文件中的内容,展示通过中的内容,展示通过dumpAttributeTable()函函数输出的网格属性表信息:数输出的网格属性表信息:参见教材

26、P172可以发现这些数据与我们为网格所指定的数据可以发现这些数据与我们为网格所指定的数据(3个网格子集、每个网格子集里面有个网格子集、每个网格子集里面有4个三角个三角形形)完全吻合。完全吻合。最后,可以用下面的代码来渲染网格,在渲染最后,可以用下面的代码来渲染网格,在渲染方法中循环遍历每一个网格子集,设置相关的方法中循环遍历每一个网格子集,设置相关的纹理,然后渲染网格子集。纹理,然后渲染网格子集。2711.9 示例:创建并渲染一个网格渲染实际上是一个很简单的工作:渲染实际上是一个很简单的工作:bool Display(float timeDelta)if(Device)/ .这里更新Frame

27、的代码忽略掉了Device-Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,0x00000000, 1.0f, 0);Device-BeginScene();for(int i=0; iSetTexture(0, Texturesi);Mesh-DrawSubset(i);Device-EndScene();Device-Present(0, 0, 0, 0);return true;2811.10 小 结一个网格包括了顶点、索引和属性缓冲区。顶点和索引缓冲区一个网格包括了顶点、索引和属性缓冲区。顶点和索引缓冲区存放了网格的几何信息存放了网格的几何

28、信息(顶点和三角形顶点和三角形)。属性缓冲区为每个三。属性缓冲区为每个三角形保存了一个相应的元素,它指定了三角形所处的网格子集。角形保存了一个相应的元素,它指定了三角形所处的网格子集。网格可以用网格可以用OptimizeInplace或者或者Optimize方法来优化。优化方法来优化。优化可以令网格的渲染更有效率。在优化网格时,如果指定了可以令网格的渲染更有效率。在优化网格时,如果指定了D3DXMESHOPT_ATTRSORT标志位,将生成一个属性表。标志位,将生成一个属性表。如果有属性表,网格就可以通过一个简单的查询属性表操作来如果有属性表,网格就可以通过一个简单的查询属性表操作来渲染整个网格子集。渲染整个网格子集。网格的邻接信息是一个网格的邻接信息是一个DWORD数组,网格中的每个三角形在数组,网格中的每个三角形在这个数组中都对应了三个索引值,这三个索引值分别指定与这这个数组中都对应了三个索引值,这三个索引值分别指定与这个三角形所邻接的三个三角形。个三角形所邻接的三个三角形。可以通过可以通过D3DXCreateMeshFVF方法来创建空网格,然后通过方法来创建空网格,然后通过合适的锁定方法合适的锁定方法(LockVertexBuffer、LockIndexBuffer和和LockAttributeBuffer)向网格中写入有效的数据。向网格中写入有效的数据。29

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 工作计划

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号