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

3D游戏从头编–第九回: 3D模型(.x)

2013年10月03日 ⁄ 综合 ⁄ 共 2882字 ⁄ 字号 评论关闭

::金点时空::

第九回: 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

<全文完>


返回

金点时空 2000/8/24

抱歉!评论已关闭.