ID3DXMesh
接口基础
几何信息的获取
//获取顶点缓冲
HRESULT
ID3DXMesh::GetVertexBuffer(LPDIRECT3DVERTEXBUFFER9* ppVB);
//获取索引缓冲
HRESULT ID3DXMesh::GetIndexBuffer(LPDIRECT3DVERTEXBUFFER9*
ppVB);
例:
//获取顶点缓冲,获取索引缓冲
LPD3DXMESH Mesh;
IDirect3DvertexBuffer9* pVB = NULL;
IDirect3DvertexBuffer9* pIB = NULL;
Mesh-> GetVertexBuffer(&pVB);
Mesh-> GetVertexBuffer(&pIB);
填充顶点与索引缓冲
HRESULT ID3DXMesh::LockVertexBuffer(
DWORD Flags,
//加锁的方式
LPVOID* ppData
//返回被锁定的顶点缓冲区指针
)
HRESULT ID3DXMesh::LockIndexBuffer(
DWORD Flags,
//加锁的方式
LPVOID* ppData
//返回被锁定的顶点缓冲区指针
)
HRESULT ID3DXMesh::UnlockVertexBuffer();
//解锁的方式
HRESULT ID3DXMesh::UnlockIndexBuffer();
//解锁的方式
//与Mesh的几何结构有关的ID3DXMesh接口的方法:
DWORD GetFVF() -------返回顶点的格式
DWORD GetNumVertices() --------返回顶点缓冲中的顶点数
DWORD GetNumBytesPerVertex() --------返回一个顶点所占的字节数
DWORD GetNumFaces() --------返回Mesh的面数,也就是三角形数
子集与属性缓冲
一个Mesh由数个子集组成,子集是Mesh中的一组使用相同属性渲染的三角形,这里
的属性指的是材质,纹理,渲染状态。每一个子集使用唯一的非负整数表示其ID;
获取属性缓冲
DWORD* buffer = NULL;
Mesh->LockAttributeBuffer(lockingFlags,&buffer);
//对属性缓冲区进行操作
Mesh->UnlockAttributeBuffer();
渲染
HRESULT DrawSubset(
DWORD AttribId
//属性ID指示Mesh中的子集,按照子集的ID渲染哪
个图形
);
例:
1.
Mesh->DrawSubset(
0
);
2.
for
(int i =
0
;i
{
Device->SetMaterial(mtrls[i]);
Device->SetTexture(0,textures[i]);
Mesh->DrawSubset(i);
}
=================================================================
==============
DirectX
=================================================================
==============
ID3DXMesh
接口相关
优化Mesh
HRESULT OptimizeInplace(
DWORD Flags,
//执行优化的类型
CONST
DWORD *pAdjacencyIn,
//没有优化的Mesh的临接数组
DWORD *pAdjacencyOut,
//输出优化的Mesh的临接数组
DWORD *pFaceRemap,
//接受面重射信息
LPD3DXBUFFER *ppVertexRemap
//返回顶点重影射信息
);
参数Flags可取值以下一值或几种值的组合:
D3DXMESHOPT_COMPACT
//删除没有用的顶点和索引项
D3DXMESHOPT_ATTRSORT
//根据属性给三角形排列顺序并调整属性表,这将使
DrawSubset方法更有效的执行
D3DXMESHOPT_VERTEXCACHE
//增加顶点缓冲的命中率
D3DXMESHOPT_STRIPREORDER
//重组顶点索引使三角形带尽量长
D3DXMESHOPT_IGNOREVERTS
//只优化索引,忽略顶点
注意: D3DXMESHOPT_VERTEXCACHE和D3DXMESHOPT_STRIPREORDER不能同时使用;
下面是对一个网格进行优化的片段
DWORD adjacencyInfo[Mesh->GetNumFaces()*
3
];
Mesh->GenerateAdjacency(
0.
0f,adjacencyInfo);
//用于保存优化的Mesh的数组
DWORD optimizedAdjacencyInfo[Mesh->GetNumFaces()*
3
];
Mesh->OptimizeInplace(
D3DXMESHOPT_ATTRSORT|
D3DXMESHOPT_COMPACT|
D3DXMESHOPT_VERTEXCACHE,
adjacencyInfo,
optimizedAdjacencyInfo,
0
,
0
);
还有一种方法是输出一个优化后的Mesh而不是在原来的基础上修改;
HRESULT Optimize(
DWORD Flags,
//执行优化的类型
CONST
DWORD *pAdjacencyIn,
//没有优化的MESH临近数组
DWORD *pAdjacencyOut,
//输出优化的MESH临近数组
DWORD *pFaceRemap,
//接受面重射信息
LPD3DXBUFFER *ppVertexRemap,
//返回顶点重影射信息
LPD3DXMESH *ppOptMesh
//返回新的网格
);
属性表
如果一个 MESH 使用 D3DXMESHOPT_ATTRSORT 进行优化,那么将创建一个
D3DXATTRIBUTERANGE结构的属性表数组:
typedef struct _D3DXATTRIBUTERANGE
{
DWORD AttribId; //子集的ID
DWORD FaceStart; //该自己的面的起始值
// FaceStart*3就是起始三角形在索引缓冲的序号
DWORD FaceCount; //子集的面数,也就是三角形数
DWORD VertexStart; //该子集的起始顶点在顶点缓冲中的序号
DWORD VertexCount; //该子集包含的顶点数
}
D3DXATTRIBUTERANGE;
访问MESH的属性表
HRESULT GetAttributeTable(
D3DXATTRIBUTERANGE *pAttribTable,
//获取属性表的指针
DWORD *pAttribTableSize
//属性表的大小,即属性的数量
);
此方法可以完成两个功能:返回属性表的属性数,返回完整的属性表
返回属性表的元素个数:
DWORD num =
0
;
Mesh->GetAttributeTable(
0
,&num);
//要得到属性表的元素个数可以给第一个参
数传NULL
然后就可以得到属性表了
D3DXATTRIBUTERANGE table = new D3DXATTRIBUTERANGE[num];
Mesh-> GetAttributeTable(table,&num);
还可以使用ID3DXMesh::SetAttribute Table方法直接修改属性表。
D3DXATTRIBUTERANGE attributeTable[
12
];
//填充属性表的值
Mesh->SetAttributeTable(attributeTable,
12
);
=================================================================
==============
.X
应用..XX文件
1
.提取多边形网格信息:
HRESULT WINAPI D3DXLoadMeshFromX(
LPCTSTR pFilename,
//X文件路径和文件名
DWORD Options,
//指定生成多边形网格属性
LPDIRECT3DDEVICE9 pD3DDevice,
//D3D设备指针
LPD3DXBUFFER *ppAdjacency,
//存储多边形临接信息
LPD3DXBUFFER *ppMaterials,
//存储材质的内存地址
LPD3DXBUFFER *ppEffectInstances,
//存储模型特殊效果的内存地址
DWORD *pNumMaterials,
//存储材质数目的内存指针
LPD3DXMESH *ppMesh
//存储生成的多边形网格的内存地址
);
下面函数片段从名为game
.
x的文件里读取3D模型:
if
(FAILED(D3DXLoadMeshFromX(L"game
.
x",
//X文件名
D3DXMESH_MANAGED,
//保存在系统管理内存中
g_pd3dDevice,
//D3D设备
NULL,
/ /无需返回临接信息
&pD3DXMtrlBuffer,
//返回材质信息
NULL,
//无需返回
&g_dwNumMaterials,
//返回材质的数目,即MESH的子
集
&g_pMesh
//返回的MESH接口对象
) ) )
{
MessageBox(NULL,L"Couldnot findgame.x",L"Mesh",MB_OK);
returnE_FAIL;
}
2.
ID3DXBuffer
接口:
GetBufferPointer();
//返回指向数据块首地址的指针
GetBufferSize();
//返回数据块中的大小
注意:ID3DXBuffer 指向的数据块本身是没有数据类型的,所以需要强制转换, 同时
ID3DXBuffer本身也是一个COM对象,所以使用完之后需要调用Release方法释放.
例如:
D3DXMATERIAL*d3dxMaterials= (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
pD3DXMtrlBuffer->Release();
3
.载入纹理和材质:
typedef struct D3DXMATERIAL
{
D3DMATERIAL9 MatD3D; //物体的材质信息
LPSTR pTextureFilename; //物体的纹理文件名称
}
D3DXMATERIAL;
下面程序片断用于获取3D模型的材质和纹理信息:
//从材质集合中把材质和纹理信息解压读取出来
D3DXMATERIAL*d3dxMaterials= (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
g_pMeshMaterials= newD3DMATERIAL9[g_dwNumMaterials];
g_pMeshTextures = newLPDIRECT3DTEXTURE9[g_dwNumMaterials];
注意:函数D3DXLoadMeshFromX调用成功后返回的是一个材质结构体数组,第i个材质信息
对应的第i个网格模型的子集,因此可以使用简单的循环来对整个网格进行渲染;
for
(DWORDi=
0
; i
{
//拷贝材质
g_pMeshMaterials[i]= d3dxMaterials[i].MatD3D;
//设置材质漫反射的颜色
g_pMeshMaterials[i].Ambient= g_pMeshMaterials[i].Diffuse;
//创建纹理
if(FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,
d3dxMaterials[i].pTextureFilename,
& g_pMeshTextures[i])))
{
g_pMeshTextures[i]=NULL;
}
}
//释放材质缓冲区的内容;
pD3DXMtrlBuffer->Release();
4
.绘制网格模型
下面代码片断就是一个网格模型的渲染函数:
//逐块渲染网格模型
for
( DWORDi=
0
;i
{
//设置材料和纹理
g_pd3dDevice->SetMaterial(&g_pMeshMaterials[i]);
g_pd3dDevice->SetTexture(0, g_pMeshTextures[i]);
//渲染模型
g_pMesh->DrawSubset(i );
}
=================================================================