第九回: 3D模型(.x)
不知不觉间,这个3D游戏从头编的教程已经连载了2个月,就如预期的一样,一周一篇的坚持下来了,连我自己都有些不相信,但这的确是真的,我想任何事情都差不多,只要你有一个明确目标,然后一步步向着目标前进,不管目标再远都总有达到的一天。
今天这一回完成后,这个教程也就到此告一段落了,如果你是一直跟着我的教程,那么今天之后你完全可以自豪的说:“3D游戏我也会做!”。
不过也不要以为3D游戏就这么简单,这些只是最基本的功能,就如同2D游戏中的画点函数一样基本,如果想要做出真正的3D游戏,还需要你坚持不泻的努力。我也会努力,所以今后也会不定期的出来和大家继续探讨些高级的3D技巧,要说的就是这些,下面开始今天的话题吧。
2D游戏中的精灵和建筑的都是美术们预先画好的图片,那么3D中是什么呢?答案是‘模型’,是3DMAX或是MAYA做出来3D模型,模型中存储了顶点的位置、面的组成、顶点的纹理坐标、材质和贴图等等我们需要的信息。一般的3D游戏都有自己的模型格式,D3D也有一种模型格式,那就是.x文件。
D3D已经为我们做好.x文件的支持,所以使用起来非常的方便,只需要简单的几条函数就可以把一个模型渲染出来了。如果你不去写3D导出插件,那么我们可能永远也不需要了解.x的文件格式,但是我们必须了解.x是怎么做出来的:
1、 在3DMAX中建立模型。
2、 导出为*.3ds格式。
3、 使用D3D提供的conv3ds.exe工具就可以把*.3ds格式的文件转化成.x文件。
(conv3ds.exe在Dx8sdk中有提供,在本回的例子程序包中也有一份^_^)
OK,现在.x文件也有了,开始写程序吧。
先要使用D3D给我们提供的模型接口定义一个模型的指针出来。
LPD3DXMESH g_pMesh = NULL; // 模型对象指针
D3DMATERIAL8* g_pMeshMaterials = NULL; // 模型的材质数组(一个模型可以有多个材质)
LPDIRECT3DTEXTURE8* g_pMeshTextures = NULL; // 模型的纹理数组(一个模型可以有多个纹理)
DWORD g_dwNumMaterials = 0L; // 材质的数量(等于纹理数量)
一、接着就是从.x文件读入我们的模型。
// 材质缓冲
LPD3DXBUFFER pD3DXMtrlBuffer;
// 读入tiger.x到我们的模型
if( FAILED( D3DXLoadMeshFromX(
"Tiger.x", // [输入].x文件名
D3DXMESH_SYSTEMMEM, // [输入]使用系统内存
g_pd3dDevice, // [输入]d3d设备指针
NULL, // 不用管
&pD3DXMtrlBuffer, // [输出]获取模型的材质缓冲
&g_dwNumMaterials, // [输出]材质的数量
&g_pMesh ) ) ) // [输出]模型对象指针
{
return E_FAIL;
}
三、遗憾的是D3DXMESH并没有为什么提供模型的材质和纹理管理,所以必须自己做这件事情。
// 获取材质指针
D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer-> GetBufferPointer();
g_pMeshMaterials = new D3DMATERIAL8[g_dwNumMaterials];
g_pMeshTextures = new LPDIRECT3DTEXTURE8[g_dwNumMaterials];
for( DWORD i=0; i<g_dwNumMaterials; 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();
四、一切准备就绪,渲染吧。要注意,在.x文件被读入时,模型是被切分了的,每一个材质对应一部分的模型。
// 根据材质的数量我们的模型被切分了,每个材质对应一部分
// 所以渲染的时候也要分几个部分渲染
for( DWORD i=0; i<g_dwNumMaterials; i++ )
{
// 为这一部分设置材质
g_pd3dDevice->SetMaterial( &g_pMeshMaterials[i] );
g_pd3dDevice->SetTexture( 0, g_pMeshTextures[i] );
// 渲染这一部分
g_pMesh->DrawSubset( i );
}
很快,程序运行的结果也出来了:
一切都弄好了,是不是感到不可思议的简单?我也是这样认为,不过实际上很少看到有商业的游戏直接使用.x文件,大多数都是自己写插件,我也写过一个,不过对于大家入门来说,.x已经足够了。没有必要所有人都去写游戏引擎吧,你说对不对?了解3D的基本实现原理后,我想以后你去做真正的3D游戏时,心里就不会一点底都没有了。
“天下没有不散的宴席,一切全都会逝去…”
让我们在郑钧的歌声中说一声再见吧。
[下载本回完整源程序]
主页:http://www.gpgame.com
http://www.gpgame.net
邮件:softboy@sina.com
soft于2002-8-23
<全文完>
返回