概览
本教程介绍了导入源文件的网格的方法,使用的方式是DXUT,但是,没有DXUT也可以使用网格。
在本教程中,你通过导入一个文件中的模型将它绘制在窗口中,这个模型已经包含了经过坐标映射的纹理。
源代码
(SDK root)\Samples\C++\Direct3D10\Tutorials\Tutorial09。
网格(Meshes)
在源代码中设置每个顶点是非常繁琐的工作,因此,我们通常都是导入已经制作好的模型。
网格就是一组预先定义好的顶点数据,这些数据常常还包含法线向量,颜色,材质和纹理坐标等额外信息。只需知道网格文件的格式,就可以进行导入和绘制。
网格用于独立于程序保存源文件,这样就可以重用网格。所以,网格是储存在单独的文件中的。它们很少由程序本身生成,而是在3D建模工具中创建的。上一个教程中创建的立方体可以储存为一个单独的文件,然后可以被重新加载。使用建模工具最大的好处是设置纹理坐标,这样就可以得到完美的匹配。
DXUT使用CDXUTMesh10类处理网格, 它是对D3DX Mesh类的封装。这个类包含了导入、绘制、销毁一个网格的方法。我们使用的文件格式为.X文件,有许多转换器可以将其他格式的文件转换为.X格式。
创建网格
要导入一个模型,我们首先需要创建一个CDXUTMesh10对象,本例中名为g_Mesh,通常对象名称应该与文件名称匹配,这样更容易将两者联系起来。
1
|
CDXUTMesh10 g_Mesh;
|
然后调用Create方法读取X文件并将它储存到这个对象中。Create方法需要X文件的名称、顶点格式,格式中的顶点数量作为参数。还有一个名为optimize的可选参数,它可以调用D3DX函数重新排列网格的面和顶点,这可以提高绘制的性能。
本例中,我们导入的文件名称为“tiny.x”。定义这个网格的顶点格式包含顶点坐标,法线和纹理坐标。我们必须指定输入格式进行匹配,如下所示
1
2
3
4
5
6
7
|
// Define the input layout
const
D3D10_INPUT_ELEMENT_DESC layout[] =
{
{
"POSITION"
, 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
{
"NORMAL"
, 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
{
"TEXCOORD"
, 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 },
};
|
之后,我们调用Create方法导入模型。最后一个参数是顶点格式的元素数量。因为包含坐标、法线和纹理坐标,所以为3。
1
2
|
// 加载网格
V_RETURN( g_Mesh.Create( pd3dDevice, L
"tiny.x"
, (D3D10_INPUT_ELEMENT_DESC*)layout, 3 ) );
|
如果不出错,现在g_Mesh就包含了新导入的网格的顶点缓存、索引缓存、纹理和材质,然后我们就可以进行绘制了。
绘制网格
在前面的教程中,因为我们必须完全控制顶点缓存和索引缓存,所以每一帧都需要正确地创建它们。但是使用模型时这些元素被抽象了,所以我们只需提供绘制所需的effects technique,它会帮你完成所有的工作。
和前一个教程的区别在于我们移除了开始绘制立方体前的OnD3DframeRender部分代码,用网格绘制调用代替。在绘制网格前设置正确的输入格式是一个好习惯,这能确保网格的格式与输入编译器匹配。
1
2
3
4
|
//
// Set the Vertex Layout
//
pd3dDevice->IASetInputLayout( g_pVertexLayout );
|
实际绘制代码是通过调用CDXUTMesh10类中的Render方法实现的。当technique的缓存正确链接之后就可以进行绘制了,此方法的参数为D3D10Device,Effect和Effect中的Technique。
1
2
3
4
|
//
// 绘制网格
//
g_Mesh.Render( pd3dDevice, g_pEffect, g_pTechnique );
|
如果模型的世界矩阵正确,那么我们就可以看到前一个教程中的立方体被一个更复杂的模型代替了。注意:这个模型比立方体大得多,所以需要进行缩放才能让模型匹配屏幕大小。
销毁网格
和所有对象一样,CDXUTMesh10对象必须在使用后进行销毁,这是通过调用Destroy方法实现的。
1
|
g_Mesh.Destroy();
|