网格(一)
几何信息
ID3DXBaseMesh接口包含一个顶点缓存(用来存储网格顶点)和一个索引缓存(用来决定顶点怎样构成网格的三角形单元)。
HRESULT ID3DXMesh::GetVertexBuffer(LPDIRECT3DVERTEXBUFFER9* ppVB);
HRESULT ID3DXMesh::GetIndexBuffer(LPDIRECT3DINDEXBUFFER9* ppIB);
例子:
Mesh->GetVertexBuffer( &vb );
IDirect3DIndexBuffer9* ib = 0;
Mesh->GetIndexBuffer( &ib );
锁定缓存 再进行读写操作
HRESULT ID3DXMesh::LockVertexBuffer(DWORD Flags, BYTE ** ppDate);
……
HRESULT ID3DXMesh::UnlockVertexBuffer();
HRESULT ID3DXMesh::LockIndexBuffer(DWORD Flags, BYTE ** ppDate);
……
HRESULT ID3DXMesh::UnlockIndexBuffer();
其中Flags 描述了如何进行锁定。
下面是另外一些与mesh几何结构有关的ID3DXMesh接口方法:
DWORD GetFVF() //返回顶点的格式
DWORD GetNumVertices() // 返回顶点缓存中的顶点数
DWORD GetNumBytesPerVertex() //返回一个顶点所占的字节数
DWORD GetNumFaces() //返回在mesh中的面(三角形)数
子集和属性缓存
一个网格(mesh)由一个或数个子集组成。一个子集(subset)是网格中一组可用相同属性渲染的一组三角形。这里的属性是指材质,纹理和渲染状态。
为了区分不同的子集, 每个子集指定一个唯一的非负整数值。 网格中的每个三角形单元都被赋予一个属性ID指定三角形势单元所属的子集。 这些三角殂单元的属性ID被存储在网格的属性缓存(attribute buffer)中该 属性能在上是一个DWORD的数组。属性缓存中元素的个数与风格中布片的个数相等。
邻接信息
之所要计算邻接信息是为了要优化属性表。
每个三角形面片都有3个条边 帮每个面片最多可有3 个邻接三角形,所以邻接数组的维数必须为ID2DXBaseMesh::GetNumFaces()*3, 网格中的每个三角形都有3个可能的邻接面片。 如果邻接数组中某一项等于ULONG MAX=4294967295,慢表明网格中某一特定边没有邻接面片。
许多 D3D网格创建函数都能够输出邻接信息, 也可使用如下方法
HRESULT ID3DXMesh::GenerateAdjacency(
FLOAT fEpsilon,
DWORD * pAdjacenc
)
说明一下
· fEpsilon 一个很小的正数(epsilon)值, 指定在某种距离度量下, 两个点接近到种程度方可认为这两点为同一点。
·pAdhacency 指向一个DOWRD类型的数组的指针, 该数组中存储了邻接信息
例如:
Mesh->GenerateAdjacency(0.0f, &adjacencyBuffer[0]);
绘制
ID3DXMesh接口提供了DrawSubset(DWORD AttribId)方法来绘制AttribId指示的子集中的各个三角形。
例如,要绘制子集0中的所有三角形,我们将这样写:
Mesh->DrawSubset(0);
为了绘制整个mesh,我们必须绘制mesh的所有子集。这是非常方便的用0,1,2,…,n-1来标识子集,这里的n是子集的总数。且有一个相对应的材质和纹理数组,即子集i与材质和纹理数组的第i项对应。这就使我们能够简单的用循环来渲染mesh:
网格优化
为了更高效地绘制一个网格, 我们可对该 风格中的顶点和索引进行重组。这个过程称为网格优化(Optimizing)。用直南的方法来完成优化。
HRESULT ID3DXMesh::OptimizeInplace(
DWORD Flags,
CONST DWORD* pAdjacencyIn,
DWORD* pAdjacencyOut,
DWORD* pFaceRemap,
LPD3DXBUFFER* ppVertexRemap
);
·Flags 表示执行什么类型的优化方法。它可以是下面的一个或几个的组合:
·D3DXMESHOPT_COMPACT 从网格中移除无用的顶点和索引项。
· D3DXMESHOPT_ATTRSORT根据属性给三角形排序并调整属性表,这将使DrawSubset执行更有效。
·D3DXMESHOPT_VERTEXCACHE 增加顶点缓存的命中率。
·D3DXMESHOPT_STRIPREORDE重组顶点索引使三角带尽可能的长。
·D3DXMESHOPT_IGNOREVERTS只优化索引信息,忽略顶点信息。
注意:D3DXMESHOPT_VERTEXCACHE和 D3DXMESHOPT_STRIPREORDER不能同时使用。
·pAdjacencyIn 指向未优化的网格的邻接数组的指针。
·pAdjacencyOut 指向一个DWORD数组,该数组被用来填充优化好了的网格邻接信息。该数组的维数必须有ID3DXMesh::GetNumFaces() * 3个元素。可以将其设置为0。
·pFaceRemap 指向一个DWORD数组,该数组直译了网格面片的重绘信息。该数组的维数应为ID3DXMesh::GetNumFaces()。当一个网格被优化时,索引缓存的面可能被移动;也就是说,在pFaceRemap中的第i项表示第i个原始面被移动到的面索引值。如果不需要该信息,可以将其设置为0。
·ppVertexRemap 指向ID3DXMesh对象指针的地址,该对象中保存了顶点的重给信息。该缓存包含的顶点数应为ID3DXMesh::GetNumVertices()个顶点。当一个网格被优化后,顶点可能被移动。顶点绘制信息用来说明原来的顶点被移动到新位置;也就是说,在ppVertexRemap中的第i项表示原来的第i个顶点的新位置。如果不需要该信息,可以将其设置为0。
一个更简单的方法是Optimize方法,它输出一个优化的mesh,而不是在原来mesh的基础上进行优化:
HRESULT Optimize(
DWORD Flags,
CONST DWORD * pAdjacencyIn,
DWORD * pAdjacencyOut,
DWORD * pFaceRemap,
LPD3DXBUFFER * ppVertexRemap,
LPD3DXMESH * ppOptMesh
);
属性表(P162)
当一个mesh被使用D3DXMESHOPT_ATTRSORT参数来优化后,mesh的几何信息将按照属性进行排序,这样各个子集的顶点/索引将组成连续的块。
网格(D3DXCreateMeshFVF)
HRESULT D3DXCreateMeshFVF(
DWORD NumFaces,
DWORD NumVertices,
DWORD Options,
DWORD FVF,
LPDIRECT3DDEVICE9 pDevice,
LPD3DXMESH *ppMesh
);
·NumFaces 网格将具有的面片总数。 大于0
·NunVertices 网格将有的总数。 大于0
·Options创建网格时所使用的创建标记。
·D3DXMESH_32BIT 网格将使用32位索引。
·D3DXMESH_MANAGED 网格数据将被存储于托管池中
·D3DXMESH_WRITEONLY 指定网格为只读
·D3DMXESH_DYNAMIC 网格缓存将使用动态内存
·FVF 存储在该 网格中的顶点的灵活顶点格式
·pDevice 与该网格相关的设备指针
·ppMesh 所创建的网格对象的指针
例如:
//12个三角形和24个顶点
{
Device->SetMaterial( mtrls[i] );
Device->SetTexture( 0, textures[i] );
Mesh->DrawSubset(i);
}
《DirectX 9.0 3D 游戏开发编程基础》笔记
江西理工大学 FangSH