现在的位置: 首页 > 综合 > 正文

在DirectX9.0中使用Mesh(1)

2013年04月27日 ⁄ 综合 ⁄ 共 4076字 ⁄ 字号 评论关闭

10.          Mesh Part One

本文译自《Introduction to 3D Game Programming with DirectX 9.0》第十章“Mesh Part One”,敬请斧正。

 

D3DX中,有很多函数都使用了ID3DXMesh接口,如D3DXCreate*之类。ID3DXMesh接口的主要功能继承自ID3DXBaseMesh父类接口,还有其他的Mesh接口也是从ID3DXBaseMesh接口继承的,如ID3DXPMesh接口,这个接口用于Progressive Mesh,把它翻译成“渐进Mesh”,不知是否合适。

本节要达到的目标:

l          学习ID3DXMesh对象的内部数据组织

l          学习创建一个ID3DXMesh对象

l          学习优化ID3DXMesh

l          学习渲染ID3DXMesh

10.1.        几何结构信息

接口ID3DXBaseMesh具有顶点缓冲和顶点索引缓冲,分别用于存储Mesh的顶点数据和顶点的索引数据,二者结合在一起才能够渲染出组成Mesh的三角形。使用下面的两个方法可得到指向两个缓冲区的指针:

HRESULT ID3DXMesh::GetVertexBuffer(LPDIRECT3DVERTEXBUFFER9* ppVB);

HRESULT ID3DXMesh::GetIndexBuffer(LPDIRECT3DINDEXBUFFER9* ppIB);

下面是一个关于上述两个方法用法的例子:

IDirect3DVertexBuffer9* pVB=NULL;

Mesh->GetVertexBuffer(&pVB);

 

IDirect3DIndexBuffer9* pIB=NULL;

Mesh->GetIndexBuffer(&pIB);

另外,如果想修改顶点缓冲和顶点索引缓冲,需要先使用下面的两个方法加锁:

HRESULT ID3DXMesh::LockVertexBuffer(DWORD Flags,LPVOID* ppData);

HRESULT ID3DXMesh::LockIndexBuffer(DWORD Flags,LPVOID* ppData);

参数Flags用于说明加锁的方式,参数ppData返回被锁定的内存的地址。记住,如果加锁成功还需要调用与之配对的解锁函数:

HRESULT ID3DXMesh::UnlockVertexBuffer();

HRESULT ID3DXMesh::UnlockIndexBuffer();

下面是另外一些与Mesh的几何结构有关的ID3DXMesh接口的方法:

l          DWORD GetFVF(); --返回顶点的格式

l          DWORD GetNumVertices(); --返回顶点缓冲中的顶点数

l          DWORD GetNumBytesPerVertex(); --返回一个顶点所占的字节数

l          DWORD GetNumFaces(); --返回Mesh的面数,也就是三角形数

10.2.        子集和属性缓冲

一个Mesh由数个子集组成。子集是Mesh中的一组使用相同属性渲染的三角形。这里的属性指的是材质、纹理、渲染状态。每一个子集用一个唯一的非负整数表示其ID,如0123等。

Mesh中的每一个三角形都与一个属性ID相关联,表示该三角形属于该子集。例如,在一个表示房子的Mesh中,组成地板的三角形具有属性ID 0,这就表示这些三角形属于子集0;同样的,组成墙的三角形的属性ID1,他们属于子集1

三角形的属性ID存储在Mesh的属性缓冲中,这是一个DWORD数组。因为每个面对应属性缓冲中的一项,所以属性缓冲中的项目数等于Mesh中的面的个数。属性缓冲中的项目和索引缓冲定义的三角形一一对应;也就是说,属性缓冲的第I项和索引缓冲中定义的第I个三角形相对应。三角形I有下面三个索引缓冲中的索引项定义:

A=I*3

B=I*3 + 1

C=I*3 + 2

可以使用下面的方法访问属性缓冲:

DWORD* buffer=NULL;

Mesh->LockAttributeBuffer(lockingFlags,&buffer);

// do something...

Mesh->UnlockAttributeBuffer();

10.3.        渲染

接口ID3DXMesh提供了DrawSubset(DWORD AttribID)方法渲染参数AttribID指示的子集中的各个三角形。例如,如果渲染子集0中的所有三角形,可以使用如下方法:

Mesh->DrawSubset(0);

如果要渲染整个Mesh,需要分别渲染Mesh的各个子集。因为子集序列与Mesh使用的材质、纹理的序列相对应,即子集I和材质、纹理数组的第I项对应,所以可以使用一个简单的循环渲染Mesh

for (int i=0;i<numSubsets;i++)

{

    Device->SetMaterial(mtrls[i]);

    Device->SetTexture(0,textures[i]);

    Mesh->DrawSubset(i);

}

10.4.        优化

为了更加有效的渲染Mesh,可以重新组织其中的顶点和索引,也就是优化Mesh。可以使用如下方法进行优化:

HRESULT ID3DXMesh::OptimizeInplace(

    DWORD Flags,

    CONST DWORD *pAdjacencyIn,

    DWORD *pAdjacencyOut,

    DWORD *pFaceRemap,

    LPD3DXBUFFER *ppVertexRemap

);

l          Flags –优化选项,告诉该方法执行什么类型的优化。可以区下面的一个或几个值:

n          D3DXMESHOPT_COMPACT –删除没有用的顶点和索引项

n          D3DXMESHOPT_ATTRSORT –根据属性给三角形排序并调整属性表,这将使DrawSubset方法更有效的执行

n          D3DXMESHOPT_VERTEXCACHE –增加顶点缓冲的命中率

n          D3DXMESHOPT_STRIPREORDER –重组顶点索引使三角形条带(Triangle Strip)尽量长

n          D3DXMESHOPT_IGNOREVERTS –只优化索引,忽略顶点

l          pAdijacencyIn –没有优化的Mesh的邻接数组

l          pAdjacencyOut –输出优化的Mesh的邻接信息的数组。这个DWORD数组必须有ID3DXMesh::GetNumFaces() * 3个元素。如果不需要该信息,可以传递NULL

l          pFaceRemap –一个DWORD数组,用于接收面重影射信息。这个数组应不小于ID3DXMesh::GetNumFaces()。当Mesh被优化时,由索引缓冲定义的面可能被移动,也就是说,如果pFaceRemap的第I项表示第I个原始面被移到的面索引值。如果不需要该信息,可以使用NULL

l          ppVertexRemap –指向ID3DXBuffer的指针的地址,返回顶点重影射信息。该缓冲区应包含ID3DXMesh::GetNumVertices()个顶点。当Mesh被优化时,顶点可能被移动,该重影射信息用于说明原来的顶点被移动到新位置,也就是说,ppVertexRemap的第I项指示原来的第I个顶点的新位置。如果不需要该信息,可以使用NULL

// Get the adjacency info of the non-optimized mesh.

DWORD adjacencyInfo[Mesh->GetNumFaces() * 3];

Mesh->GenerateAdjacency(0.0f, adjacencyInfo);

// Array to hold optimized adjacency info.

DWORD optimizedAdjacencyInfo[Mesh->GetNumFaces() * 3];

Mesh->OptimizeInplace(

    D3DXMESHOPT_ATTRSORT |

    D3DXMESHOPT_COMPACT |

    D3DXMESHOPT_VERTEXCACHE,

    adjacencyInfo,

    optimizedAdjacencyInfo,

    0,

    0);

另一个相似的方法是Optimize(),它输出一个优化的Mesh,而不是在原来Mesh的基础上进行优化:

HRESULT ID3DXMesh::Optimize(

    DWORD Flags,

    CONST DWORD *pAdjacencyIn,

    DWORD *pAdjacencyOut,

    DWORD *pFaceRemap,

    LPD3DXBUFFER *ppVertexRemap,

    LPD3DXMESH *ppOptMesh

);

10.5.        属性表

如果一个Mesh使用D3DXMESHOPT_ATTRSORT标志进行优化,Mesh的结构信息将按属性进行排序,这样各个子集的顶点/顶点索引将组成连续的块。

除了进行几何信息的排序外,D3DXMESHOPT_ATTRSORT优化选项还将创建一个属性表。该表是D3DXATTRIBUTERANGE结构的一个数组,其中的每一项对应Mesh的一个子集并指示顶点/顶点索引的一个连续块,这个子集的几何信息就包含在这个块里。结构D3DXATTRIBUTERANGE的定义如下:

typedef struct _D3DXATTRIBUTERANGE

{

    DWORD AttribId;

    DWORD FaceStart;

    DWORD FaceCount;

    DWORD VertexStart;

抱歉!评论已关闭.