LoadMesh and DrawMesh

http://hi.baidu.com/zyb_debug/blog/item/d2ee04171d48ab5bf2de32d7.html
利用上篇文章的D3DXMESHCONTAINER_EX,LoadMesh和DrawMesh都是简单的基础类函数,
以后就不用每次载入的时候都写那一大堆平凡的代码。

HRESULT LoadMesh(
        D3DXMESHCONTAINER_EX 
** ppMesh, 
        IDirect3DDevice9 
* pDevice, 
        
char   * Filename,  char   * TexturePath  /*  =   */ ,
        DWORD NewFVF 
/*  = 0  */ , DWORD LoadFlags  /*  = D3DXMESH_SYSTEMMEM  */
        )
    {

        ID3DXMesh 
* pLoadMesh  =  NULL;
        HRESULT hr;

        
//  Error checking
         if ( ! ppMesh  ||   ! pDevice  ||   ! Filename  ||   ! TexturePath)
            
return  E_FAIL;

        
//  Use system memory if converting FVF
        DWORD TempLoadFlags  =  LoadFlags;
        
if (NewFVF)
            TempLoadFlags 
=  D3DXMESH_SYSTEMMEM;

        
//  Load the mesh using D3DX routines
        ID3DXBuffer  * MaterialBuffer  =  NULL,  * AdjacencyBuffer  =  NULL;
        DWORD NumMaterials;
        
if (FAILED(hr = D3DXLoadMeshFromXA(Filename, TempLoadFlags,
            pDevice, 
& AdjacencyBuffer,
            
& MaterialBuffer, NULL,
            
& NumMaterials,  & pLoadMesh)))
            
return  hr;

        
//  Convert to new FVF first as needed
         if (NewFVF) {
            ID3DXMesh 
* pTempMesh;

            
//  Use CloneMeshFVF to convert mesh
             if (FAILED(hr = pLoadMesh -> CloneMeshFVF(LoadFlags, NewFVF, pDevice,  & pTempMesh))) {
                ReleaseCOM(AdjacencyBuffer);
                ReleaseCOM(MaterialBuffer);
                ReleaseCOM(pLoadMesh);
                
return  hr;
            }

            
//  Free prior mesh and store new pointer
            ReleaseCOM(pLoadMesh);
            pLoadMesh 
=  pTempMesh; pTempMesh  =  NULL;
        }

        
//  Allocate a D3DXMESHCONTAINER_EX structure
        D3DXMESHCONTAINER_EX  * pMesh  =   new  D3DXMESHCONTAINER_EX();
        
* ppMesh  =  pMesh;

        
//  Store mesh name (filename), type, and mesh pointer
        pMesh -> Name  =  _strdup(Filename);
        pMesh
-> MeshData.Type  =  D3DXMESHTYPE_MESH;
        pMesh
-> MeshData.pMesh  =  pLoadMesh; pLoadMesh  =  NULL;

        
//  Store adjacency buffer
        DWORD AdjSize  =  AdjacencyBuffer -> GetBufferSize();
        
if (AdjSize) {
            pMesh
-> pAdjacency  =   new  DWORD[AdjSize];
            memcpy(pMesh
-> pAdjacency, AdjacencyBuffer -> GetBufferPointer(), AdjSize);
        }
        ReleaseCOM(AdjacencyBuffer);

        
//  Build material list
         if ( ! (pMesh -> NumMaterials  =  NumMaterials)) {

            
//  Create a default material
            pMesh -> NumMaterials  =   1 ;
            pMesh
-> pMaterials    =   new  D3DXMATERIAL[ 1 ];
            pMesh
-> pTextures     =   new  IDirect3DTexture9 * [ 1 ];

            ZeroMemory(pMesh
-> pMaterials,  sizeof (D3DXMATERIAL));
            pMesh
-> pMaterials[ 0 ].MatD3D.Diffuse.r  =   1.0f ;
            pMesh
-> pMaterials[ 0 ].MatD3D.Diffuse.g  =   1.0f ;
            pMesh
-> pMaterials[ 0 ].MatD3D.Diffuse.b  =   1.0f ;
            pMesh
-> pMaterials[ 0 ].MatD3D.Diffuse.a  =   1.0f ;
            pMesh
-> pMaterials[ 0 ].MatD3D.Ambient    =  pMesh -> pMaterials[ 0 ].MatD3D.Diffuse;
            pMesh
-> pMaterials[ 0 ].MatD3D.Specular   =  pMesh -> pMaterials[ 0 ].MatD3D.Diffuse;
            pMesh
-> pMaterials[ 0 ].pTextureFilename  =  NULL;
            pMesh
-> pTextures[ 0 ]                    =  NULL;

        } 
else  {

            
//  Load the materialsx

            D3DXMATERIAL 
* Materials  =  (D3DXMATERIAL * )MaterialBuffer -> GetBufferPointer();
            pMesh
-> pMaterials  =   new  D3DXMATERIAL[pMesh -> NumMaterials];
            pMesh
-> pTextures   =   new  IDirect3DTexture9 * [pMesh -> NumMaterials];

            
for (DWORD i = 0 ;i < pMesh -> NumMaterials;i ++ ) {
                pMesh
-> pMaterials[i].MatD3D  =  Materials[i].MatD3D;
                pMesh
-> pMaterials[i].MatD3D.Ambient  =  pMesh -> pMaterials[i].MatD3D.Diffuse;

                
//  Load the texture if one exists
                pMesh -> pTextures[i]  =  NULL;
                
if (Materials[i].pTextureFilename) {
                    
char  TextureFile[MAX_PATH];
                    sprintf_s(TextureFile,MAX_PATH, 
" %s%s " , TexturePath, 
                        Materials[i].pTextureFilename);
                    D3DXCreateTextureFromFileA(pDevice,
                        TextureFile,
                        
& pMesh -> pTextures[i]);
                }
            }
        }
        ReleaseCOM(MaterialBuffer);

        
//  Optimize the mesh for better attribute access
        pMesh -> MeshData.pMesh -> OptimizeInplace(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL);

        
//  Clear pMesh pointer just in case
        pMesh  =  NULL;

        
return  S_OK;

    }

    
//  Draw the first mesh in a linked list of objects
    HRESULT DrawMesh(D3DXMESHCONTAINER_EX  * pMesh)
    {

        IDirect3DDevice9 
* pD3DDevice;
        DWORD LastState, OldAlphaState, OldSrcBlend, OldDestBlend;

        
//  Error checking
         if ( ! pMesh)
            
return  E_FAIL;
        
if ( ! pMesh -> MeshData.pMesh)
            
return  E_FAIL;
        
if ( ! pMesh -> NumMaterials  ||   ! pMesh -> pMaterials)
            
return  E_FAIL;

        
//  Get the device interface
        pMesh -> MeshData.pMesh -> GetDevice( & pD3DDevice);

        
//  Release vertex shader if being used
        pD3DDevice -> SetVertexShader(NULL);
        pD3DDevice
-> SetVertexDeclaration(NULL);

        
//  Save render states
        pD3DDevice -> GetRenderState(D3DRS_ALPHABLENDENABLE,  & OldAlphaState);
        pD3DDevice
-> GetRenderState(D3DRS_SRCBLEND,  & OldSrcBlend);
        pD3DDevice
-> GetRenderState(D3DRS_DESTBLEND,  & OldDestBlend);
        LastState 
=  OldAlphaState;

        
//  Setup pointer for mesh to draw, either regular or skinned
        ID3DXMesh  * pDrawMesh  =  ( ! pMesh -> pSkinMesh) ? pMesh -> MeshData.pMesh:pMesh -> pSkinMesh;

        
//  Look through all subsets
         for (DWORD i = 0 ;i < pMesh -> NumMaterials;i ++ ) {

            
//  Set material and texture
            pD3DDevice -> SetMaterial( & pMesh -> pMaterials[i].MatD3D);
            pD3DDevice
-> SetTexture( 0 , pMesh -> pTextures[i]);

            
//  Enable or disable alpha blending per material
             if (pMesh -> pMaterials[i].MatD3D.Diffuse.a  !=   1.0f ) {
                
if (LastState  !=  TRUE) {
                    LastState 
=  TRUE;
                    pD3DDevice
-> SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
                    pD3DDevice
-> SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); // SRCCOLOR);
                    pD3DDevice -> SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);
                }
            } 
else  {
                
if (LastState  !=  FALSE) {
                    LastState 
=  FALSE;
                    pD3DDevice
-> SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
                }
            }

            
//  Draw the mesh subset
            pDrawMesh -> DrawSubset(i);
        }

        
//  Restore alpha blending states
         if (LastState  !=  OldAlphaState) {
            pD3DDevice
-> SetRenderState(D3DRS_ALPHABLENDENABLE, OldAlphaState);
            pD3DDevice
-> SetRenderState(D3DRS_SRCBLEND, OldSrcBlend);
            pD3DDevice
-> SetRenderState(D3DRS_DESTBLEND, OldDestBlend);
        }

        
//  Make sure to release the device object!
        pD3DDevice -> Release();

        
//  Return success
         return  S_OK;

    }
Posted on 2009-09-12 16:04 zyb_debug 阅读(1139) 评论(1)   编辑  收藏 引用

你可能感兴趣的:(LoadMesh and DrawMesh)