类CDXUTMesh的使用

 

这个类的定义和实现分别位于DXUTMesh.h和DXUTMesh.cpp中,其定义如下:

// -----------------------------------------------------------------------------
//  Name: class CDXUTMesh
//  Desc: Class for loading and rendering file-based meshes
// -----------------------------------------------------------------------------
class  CDXUTMesh
{
public :
    WCHAR                            m_strName[
512 ];
    LPD3DXMESH                        m_pMesh;   
//  Managed mesh
    
    
//  Cache of data in m_pMesh for easy access

    IDirect3DVertexBuffer9
*             m_pVB;
    IDirect3DIndexBuffer9
*             m_pIB;
    IDirect3DVertexDeclaration9
*     m_pDecl;
    DWORD                           m_dwNumVertices;
    DWORD                           m_dwNumFaces;
    DWORD                           m_dwBytesPerVertex;

    DWORD                           m_dwNumMaterials; 
//  Materials for the mesh
    D3DMATERIAL9 *                    m_pMaterials;
    CHAR                            (
* m_strMaterials)[MAX_PATH];
    IDirect3DBaseTexture9
**          m_pTextures;
    
bool                             m_bUseMaterials;

public :
    
//  Rendering
    HRESULT Render( LPDIRECT3DDEVICE9 pd3dDevice, 
                    
bool  bDrawOpaqueSubsets  =   true ,
                    
bool  bDrawAlphaSubsets  =   true  );

    HRESULT Render( ID3DXEffect 
* pEffect,
                    D3DXHANDLE hTexture 
=  NULL,
                    D3DXHANDLE hDiffuse 
=  NULL,
                    D3DXHANDLE hAmbient 
=  NULL,
                    D3DXHANDLE hSpecular 
=  NULL,
                    D3DXHANDLE hEmissive 
=  NULL,
                    D3DXHANDLE hPower 
=  NULL,
                    
bool  bDrawOpaqueSubsets  =   true ,
                    
bool  bDrawAlphaSubsets  =   true  );

    
//  Mesh access
    LPD3DXMESH GetMesh() {  return  m_pMesh; }

    
//  Rendering options
     void     UseMeshMaterials(  bool  bFlag ) { m_bUseMaterials  =  bFlag; }
    HRESULT SetFVF( LPDIRECT3DDEVICE9 pd3dDevice, DWORD dwFVF );
    HRESULT SetVertexDecl( LPDIRECT3DDEVICE9 pd3dDevice, 
const  D3DVERTEXELEMENT9  * pDecl, 
                           
bool  bAutoComputeNormals  =   true bool  bAutoComputeTangents  =   true
                           
bool  bSplitVertexForOptimalTangents  =   false  );

    
//  Initializing
    HRESULT RestoreDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice );
    HRESULT InvalidateDeviceObjects();

    
//  Creation/destruction
    HRESULT Create( LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strFilename );
    HRESULT Create( LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXFILEDATA pFileData );
    HRESULT Create(LPDIRECT3DDEVICE9 pd3dDevice, ID3DXMesh
*  pInMesh, D3DXMATERIAL *  pd3dxMaterials, DWORD dwMaterials);

    HRESULT CreateMaterials(LPCWSTR strPath, IDirect3DDevice9 
* pd3dDevice, 
                            D3DXMATERIAL
*  d3dxMtrls, DWORD dwNumMaterials);
    HRESULT Destroy();

    CDXUTMesh( LPCWSTR strName 
=  L " CDXUTMeshFile_Mesh "  );
    
virtual   ~ CDXUTMesh();
};

 

该类中包含的成员函数按其作用可分为6类。

第一类是构造和析构函数,函数CDXUTMesh()和~CDXUTMesh()分别是该类的构造函数和析构函数,其作用分别是进行一些初始化工作以及在类CDXUTMesh的对象被销毁时完成最后的销毁工作。

CDXUTMesh::CDXUTMesh( LPCWSTR strName )
{
StringCchCopy( m_strName, 512, strName );
    m_pMesh              = NULL;
m_pMaterials = NULL;
m_pTextures = NULL;
m_bUseMaterials = TRUE;
m_pVB = NULL;
m_pIB = NULL;
m_pDecl = NULL;
m_strMaterials = NULL;
m_dwNumMaterials = 0;
m_dwNumVertices = 0;
m_dwNumFaces = 0;
m_dwBytesPerVertex = 0;
}
CDXUTMesh::~CDXUTMesh()
{
Destroy();
}

第二类是获取网格函数,它仅包含一个函数GetMesh(),实现也非常简单,即返回类CDXUTMesh的成员变量m_pMesh。

LPD3DXMESH GetMesh() { return m_pMesh; }

第三类是设备恢复和丢失时所采取的操作函数,这里所包含的两个成员函数RestoreDeviceObjects()和InvalidateDeviceObjects()分别是在设备恢复和丢失时调用,用于恢复和释放相应的资源。

HRESULT CDXUTMesh::RestoreDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice )
{
return S_OK;
}
HRESULT CDXUTMesh::InvalidateDeviceObjects()
{
SAFE_RELEASE( m_pIB );
SAFE_RELEASE( m_pVB );
SAFE_RELEASE( m_pDecl );
    return S_OK;
}

第四类是创建和销毁函数,这里首先重载了3个创建网格模型函数Create(),它们依次用于从指定的.x文件创建网格模型,从接口ID3DXFileData创建网格模型,从输入的网格模型中创建新的网格模型。函数CreateMaterials()用于创建网格模型中所需的材质和纹理。函数Destroy()用来在程序退出时销毁指定的资源。

来看第一个Create()函数的实现:

HRESULT CDXUTMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strFilename )
{
    WCHAR        strPath[MAX_PATH];
    LPD3DXBUFFER pAdjacencyBuffer 
=  NULL;
    LPD3DXBUFFER pMtrlBuffer 
=  NULL;
    HRESULT      hr;

    
//  Cleanup previous mesh if any
    Destroy();

    
//  Find the path for the file, and convert it to ANSI (for the D3DX API)
    DXUTFindDXSDKMediaFileCch( strPath,  sizeof (strPath)  /   sizeof (WCHAR), strFilename );

    
//  Load the mesh
     if (FAILED(hr  =  D3DXLoadMeshFromXW(strPath, D3DXMESH_MANAGED, pd3dDevice,  & pAdjacencyBuffer,  & pMtrlBuffer, NULL,
                                      
& m_dwNumMaterials,  & m_pMesh)))
    {
        
return  hr;
    }

    
//  Optimize the mesh for performance
     if ( FAILED( hr  =  m_pMesh -> OptimizeInplace(
                        D3DXMESHOPT_COMPACT 
|  D3DXMESHOPT_ATTRSORT  |  D3DXMESHOPT_VERTEXCACHE,
                        (DWORD
* ) pAdjacencyBuffer -> GetBufferPointer(), NULL, NULL, NULL)))
    {
        SAFE_RELEASE( pAdjacencyBuffer );
        SAFE_RELEASE( pMtrlBuffer );
        
return  hr;
    }

    
//  Set strPath to the path of the mesh file

    WCHAR
*  pLastBSlash  =  wcsrchr( strPath, L ' // '  );

    
if ( pLastBSlash )
        
* (pLastBSlash  +   1 =  L ' /0 ' ;
    
else
        
* strPath  =  L ' /0 ' ;

    D3DXMATERIAL
*  d3dxMtrls  =  (D3DXMATERIAL * ) pMtrlBuffer -> GetBufferPointer();
    hr 
=  CreateMaterials( strPath, pd3dDevice, d3dxMtrls, m_dwNumMaterials );

    SAFE_RELEASE( pAdjacencyBuffer );
    SAFE_RELEASE( pMtrlBuffer );

    
//  Extract data from m_pMesh for easy access

    D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];

    m_dwNumVertices    
=  m_pMesh -> GetNumVertices();
    m_dwNumFaces       
=  m_pMesh -> GetNumFaces();
    m_dwBytesPerVertex 
=  m_pMesh -> GetNumBytesPerVertex();

    m_pMesh
-> GetIndexBuffer(  & m_pIB );
    m_pMesh
-> GetVertexBuffer(  & m_pVB );
    m_pMesh
-> GetDeclaration( decl );

    pd3dDevice
-> CreateVertexDeclaration( decl,  & m_pDecl );

    
return  hr;
}

 

函数首先销毁旧的资源,并调用DXUTFindDXSDKMediaFileCch()通过文件名查找文件所在的路径,接着调用D3DXLoadMeshFromXW()从文件中加载网格模型。

DXUTFindDXSDKMediaFileCch()的实现分析请参阅DXUT源码分析 ---- 媒体文件查找函数

    WCHAR        strPath[MAX_PATH];
LPD3DXBUFFER pAdjacencyBuffer = NULL;
LPD3DXBUFFER pMtrlBuffer = NULL;
HRESULT hr;
    // Cleanup previous mesh if any
Destroy();
    // Find the path for the file, and convert it to ANSI (for the D3DX API)
DXUTFindDXSDKMediaFileCch( strPath, sizeof(strPath) / sizeof(WCHAR), strFilename );
    // Load the mesh
if(FAILED(hr = D3DXLoadMeshFromXW(strPath, D3DXMESH_MANAGED, pd3dDevice, &pAdjacencyBuffer, &pMtrlBuffer, NULL,
&m_dwNumMaterials, &m_pMesh)))
{
return hr;
}

接着调用OptimizeInplace()对网格模型进行优化,该函数调用时第一个参数的含义如下:

D3DXMESHOPT_COMPACT — 从mesh中移除没有用的顶点和索引项。

D3DXMESHOPT_ATTRSORT — 根据属性给三角形排序并调整属性表,这将使DrawSubset执行更有效。

D3DXMESHOPT_VERTEXCACHE — 增加顶点缓存的命中率。

   // Optimize the mesh for performance
if( FAILED( hr = m_pMesh->OptimizeInplace(
D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
(DWORD*) pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL)))
{
SAFE_RELEASE( pAdjacencyBuffer );
SAFE_RELEASE( pMtrlBuffer );
return hr;
}

接下来,函数将模型文件所在的路径存储在strPath,如果没有路径,则strPath置为NULL。

   // Set strPath to the path of the mesh file
    WCHAR* pLastBSlash = wcsrchr( strPath, L'//' );
    if( pLastBSlash )
*(pLastBSlash + 1) = L'/0';
else
*strPath = L'/0';

接下来,函数调用CreateMaterials()创建存储材质和纹理的内存,并释放邻接信息缓存和材质缓存。

    D3DXMATERIAL* d3dxMtrls = (D3DXMATERIAL*) pMtrlBuffer->GetBufferPointer();
hr = CreateMaterials( strPath, pd3dDevice, d3dxMtrls, m_dwNumMaterials );
    SAFE_RELEASE( pAdjacencyBuffer );
SAFE_RELEASE( pMtrlBuffer );

最后,函数获取模型的顶点数,面数,每个顶点所占的字节大小,顶点索引缓存,顶点缓存,顶点声明,以方便以后访问。

    // Extract data from m_pMesh for easy access
    m_dwNumVertices    = m_pMesh->GetNumVertices();
m_dwNumFaces = m_pMesh->GetNumFaces();
m_dwBytesPerVertex = m_pMesh->GetNumBytesPerVertex();
    m_pMesh->GetIndexBuffer( &m_pIB );
m_pMesh->GetVertexBuffer( &m_pVB );
m_pMesh->GetDeclaration( decl );
    pd3dDevice->CreateVertexDeclaration( decl, &m_pDecl );
    return hr;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值