//=============================================================================
// Name: XFileModelClass.h
// Des: 一个封装了X文件载入与渲染功能的类头文件
// 2013年 4月7日 Create by 浅墨
//=============================================================================
#pragma once
#include "D3DUtil.h"
class XFileModelClass
{
private:
LPDIRECT3DDEVICE9 m_pd3dDevice; //D3D设备对象
LPD3DXMESH m_pMesh; //网格模型对象
DWORD m_dwNumMaterials; //材质的数量
D3DMATERIAL9* m_pMaterials; //模型材质结构体的实例
LPDIRECT3DTEXTURE9 * m_pTextures; //模型纹理结构体的实例
public:
XFileModelClass(IDirect3DDevice9 *pd3dDevice); //构造函数
~XFileModelClass(void); //析构函数
public:
HRESULT LoadModelFromXFile(WCHAR* strFilename ); //从.X文件读取三维模型到内存中
HRESULT RenderModel( ); //渲染三维网格模型
};
//=============================================================================
// Name: XFileModelClass.h
// Des: 一个封装了X文件载入与渲染功能的类源文件
// 2013年 4月7日 Create by 浅墨
//=============================================================================
#include <d3dx9.h>
#include <tchar.h>
#include "XFileModelClass.h"
//-----------------------------------------------------------------------------
// Desc: 构造函数
//-----------------------------------------------------------------------------
XFileModelClass::XFileModelClass(IDirect3DDevice9* pd3dDevice)
{
//给各个成员变量赋初值
m_pd3dDevice = pd3dDevice;
}
//--------------------------------------------------------------------------------------
// Name: XFileModelClass::LoadModelFromXFile()
// Desc: 从.X文件读取三维模型到内存中
//--------------------------------------------------------------------------------------
HRESULT XFileModelClass::LoadModelFromXFile( WCHAR* strFilename )
{
//--------------------------------------------------------------------------------------
// 【文件模型载入三部曲之一】:通过X文件加载网格模型
//--------------------------------------------------------------------------------------
LPD3DXBUFFER pAdjacencyBuffer = NULL; //网格模型邻接信息
LPD3DXBUFFER pD3DXMtrlBuffer = NULL; //存储网格模型材质的缓存对象
//从磁盘文件加载网格模型
//strFilename: 指向需要加载的.x文件的磁盘路径和文件名的字符串
//D3DXMESH_MANAGED: 创建网格时的附加项
//g_pd3dDevice: Direct3D设备指针
//pAdjacencyBuffer: 保存网格的邻接信息,也就是包含每个多边形周围的多边形的缓冲区的内存地址
//&pD3DXMtrlBuffer:保存网格的所有子集的材质
//NULL: 存储网格模型的特殊效果,通常为NULL
//m_dwNumMaterials: 存储所有子集材质的数目,配合第5个参数
//m_pMesh: 指向从文件生成的Direct3D网格模型的指针,以便之后对网格模型的访问
D3DXLoadMeshFromX( strFilename, D3DXMESH_MANAGED, m_pd3dDevice, &pAdjacencyBuffer,
&pD3DXMtrlBuffer, NULL, &m_dwNumMaterials, &m_pMesh );
//--------------------------------------------------------------------------------------
// 【文件模型载入三部曲之二】:载入材质和纹理
//--------------------------------------------------------------------------------------
// 读取材质和纹理数据
D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
m_pTextures = new LPDIRECT3DTEXTURE9[m_dwNumMaterials];
//逐子集提取材质属性和纹理文件名
for( DWORD i=0; i<m_dwNumMaterials; i++ )
{
//获取材质,并设置一下环境光的颜色值
m_pMaterials[i] = d3dxMaterials[i].MatD3D; //材质信息
m_pMaterials[i].Ambient = m_pMaterials[i].Diffuse; //漫反射颜色光
//创建一下纹理对象
m_pTextures[i] = NULL;
if( d3dxMaterials[i].pTextureFilename != NULL &&
strlen(d3dxMaterials[i].pTextureFilename) > 0 )
{
//创建纹理
if( FAILED( D3DXCreateTextureFromFileA( m_pd3dDevice,d3dxMaterials[i].pTextureFilename, &m_pTextures[i] ) ) )
{
MessageBox(NULL, L"SORRY~!没有找到纹理文件!", L"XFileModelClass类读取文件错误", MB_OK);
}
}
}
//优化网格模型
//第一个参数为执行何种优化方法,
//D3DXMESHOPT_COMPACT: 从网格中移除没用的顶点和索引
//D3DXMESHOPT_ATTRSORT: 根据属性给三角形排序并调整属性表
//D3DXMESHOPT_STRIPREORDER: 重组顶点索引,让三角形尽可能长
//第二个参数:指针,指向优化前的邻接数组
//第三个参数:指针,指向优化后的邻接数组,如果不需要优化后的信息,填NULL
//第四个参数:填充面重映射信息,一般为NULL
//第五个参数:保存网格顶点的重映射信息,一般为NULL
m_pMesh->OptimizeInplace( D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_STRIPREORDER,
(DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL );
return S_OK;
}
//--------------------------------------------------------------------------------------
// Name: XFileModelClass::RenderModel()
// Desc: 渲染三维网格模型
//--------------------------------------------------------------------------------------
HRESULT XFileModelClass::RenderModel( )
{
//--------------------------------------------------------------------------------------
// 【文件模型载入三部曲之三】:绘制网格模型
//--------------------------------------------------------------------------------------
for( DWORD i=0; i<m_dwNumMaterials; i++ )
{
m_pd3dDevice->SetMaterial( &m_pMaterials[i] );
m_pd3dDevice->SetTexture( 0, m_pTextures[i] );
m_pMesh->DrawSubset( i );
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Desc: 析构函数
//-----------------------------------------------------------------------------
XFileModelClass::~XFileModelClass(void)
{
//释放网格模型材质
SAFE_DELETE_ARRAY(m_pMaterials);
//释放网格模型纹理
if( m_pTextures )
{
for( DWORD i = 0; i < m_dwNumMaterials; i++ )
{
SAFE_RELEASE(m_pTextures[i]);
}
SAFE_DELETE_ARRAY(m_pTextures);
}
//释放网格模型对象
SAFE_RELEASE(m_pMesh);
}
调用:
XFileModelClass* g_pXFileModel1 = NULL; //模型类的第一个对象
XFileModelClass* g_pXFileModel2 = NULL; //模型类的第二个对象
XFileModelClass* g_pXFileModel3 = NULL; //模型类的第三个对象
XFileModelClass* g_pXFileModel4 = NULL; //模型类的第四个对象
Objects_Init()
描述:渲染资源初始化函数,在此函数中进行要被渲染的物体的资源的初始化
//载入第一个模型
g_pXFileModel1 = new XFileModelClass(g_pd3dDevice);
HR( g_pXFileModel1->LoadModelFromXFile(L"knight.X" ));
//载入第二个模型
g_pXFileModel2 = new XFileModelClass(g_pd3dDevice);
HR( g_pXFileModel2->LoadModelFromXFile(L"dragon.X" ));
//载入第三个模型
g_pXFileModel3 = new XFileModelClass(g_pd3dDevice);
HR( g_pXFileModel3->LoadModelFromXFile(L"Demon.X" ));
//载入第四个模型
g_pXFileModel4 = new XFileModelClass(g_pd3dDevice);
HR( g_pXFileModel4->LoadModelFromXFile(L"angle.X" ));
Direct3D_Render()
描述:使用Direct3D进行渲染
//-----------------------------【绘制游戏模型】-----------------------------
//定义一些矩阵,准备对模型进行矩阵变换
D3DXMATRIX mScal1, mScal2, mTrans1, mTrans2, mTrans3, mTrans4;
D3DXMATRIX mFinal1, mFinal2, mFinal3, mFinal4;
//第一个模型的绘制,首先是“调合”出这个模型合适的世界矩阵,然后再绘制
D3DXMatrixTranslation(&mTrans1, 50.0f, 400.0f, 0.0f);
D3DXMatrixScaling(&mScal1,3 .0f, 3.0f, 3.0f);
mFinal1=mTrans1*mScal1*g_matWorld;
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mFinal1);//设置模型的世界矩阵,为绘制做准备
g_pXFileModel1->RenderModel( );
//第二个模型的绘制,首先是“调合”出这个模型合适的世界矩阵,然后再绘制
D3DXMatrixTranslation(&mTrans2, 200.0f, 0.0f, 0.0f);
mFinal2=mTrans2*mFinal1;
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mFinal2);
g_pXFileModel2->RenderModel( );
//第三个模型的绘制,首先是“调合”出这个模型合适的世界矩阵,然后再绘制
D3DXMatrixTranslation(&mTrans3, -200.0f, 0.0f, 0.0f);
mFinal3=mTrans3*mFinal1;
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mFinal3);
g_pXFileModel3->RenderModel( );
//第四个模型的绘制,首先是“调合”出这个模型合适的世界矩阵,然后再绘制
D3DXMatrixScaling(&mScal2,10.0f,10.0f,10.0f);
D3DXMatrixTranslation(&mTrans4, 10.0f, 20.0f, 250.0f);
mFinal4=mTrans4*mScal2*mFinal1;
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mFinal4);
g_pXFileModel4->RenderModel( );