Class dxMesh wraps the mesh object included with DirectX 8, and loads and manages the mesh's materials and textures.

 




This function initializes the object from a .X file stored in the resource (game.dat) file. Note that pstrPathName is a path into that resource file, not a file on the hard drive. Example:

pMesh->LoadXFileFromNuke( m_dxFileMgr, m_pd3dDevice, "Mesh/Ships/doog.X" );

IMPORTANT: LoadXFileFromNuke will treat the texture filenames inside the .X file as paths into the resource file! This is a bit of a pain - when you convert a 3DS file to a X file, you'll need to first export a text-based X file and edit it to change the texture paths.


   

#ifndef NONUKEFILE
    HRESULT dxMesh::LoadXFileFromNuke( CNukeFile *pResFile, LPDIRECT3DDEVICE8 pd3dDevice, LPSTR pstrPathName )
    {
        .
        .
        .
    }

 

 

 



LoadXFile works the same as LoadXFileFromNuke...

Render renders the mesh! If you pass true to the first boolean parameter, it will render the progressive (LOD) version of the mesh (after you've set it up), otherwise it'll use the original, full detail mesh. Mesh vertices are divided into what're called subsets. A subset is a group of primitives that all have the same material and texture applied to them. If you model a mesh that has distinct parts with different materials on each part, one way to achieve animation procedurally is by rendering one subset at a time, and modifying the world matrix in-between. Generally, leave the default parameter.

Note that there's no position or rotation information for meshes - when you call render, make sure you've already set up your model, view, and projection matrices.


   

    HRESULT LoadXFile( LPDIRECT3DDEVICE8 pd3dDevice, LPSTR pstrPathName );
    HRESULT Render( BOOL bRenderProgessiveMesh = FALSE, DWORD iSubset = ALL_SUBSETS );

 



The usual accessors. GetMesh and GetProgressiveMesh return the respective DirectX interfaces to the mesh.

GetMeshCenter and GetMeshRadius together return the ideal bounding sphere for the mesh.

GetNumVertices and GetNumFaces return the vertex and face counts for the full detail, non-progressive mesh.


   

    // accessors
    LPD3DXMESH  GetMesh()               { return m_pMesh; }
    LPD3DXPMESH GetProgressiveMesh()    { return m_pProgMesh; }

    D3DXVECTOR3 GetMeshCenter()         { return m_vObjectCenter; }
    FLOAT       GetMeshRadius()         { return m_fObjectRadius; }

    DWORD       GetNumVertices();
    DWORD       GetNumFaces();

    BOOL        IsReady()               { return ( m_pMesh != NULL ); }

 

 

 

 





OptimizeMesh just wraps a call to ID3DXMesh::OptimizeInplace. You can pass it a combination of the following flags:

D3DXMESHOPT_ATTRSORT
    Reorders faces to optimize for fewer attribute bundle state changes and enhanced ID3DXBaseMesh::DrawSubset performance.
D3DXMESHOPT_COMPACT
    Reorders faces to remove unused vertices and faces.
D3DXMESHOPT_IGNOREVERTS
    Optimize the faces only; do not optimize the vertices.
D3DXMESHOPT_STRIPREORDER
    Reorders faces to maximize length of adjacent triangles.
D3DXMESHOPT_VERTEXCACHE
    Reorders faces to increase the cache hit rate of vertex caches.

For what we're doing, I don't think this feature will boost performance enough to make up for the additional load time.


   

    // mesh options
    HRESULT OptimizeMesh( DWORD dwOptFlags );

 

 


Here's a great feature - progessive meshes. DirectX 8 makes it easy and very fast to implement level of detail on meshes. After you initialize the mesh with LoadXFile(), call MakeProgressiveMesh(), and then set the desired number of vertices or faces you want. DirectX will smartly degrade the mesh until it reaches that detail level (run the ShipTweak program to see it working). The values you pass need to be less than the values returned by GetNumVertices() and GetNumFaces().


   

    // make this mesh progessive (enable LOD)
    HRESULT MakeProgressiveMesh();

    // set the LOD by face or vertex count
    HRESULT SetPMNumVertices( DWORD dwNumVertices );
    DWORD   GetPMNumVertices();
    HRESULT SetPMNumFaces( DWORD dwNumFaces );
    DWORD   GetPMNumFaces();

 

 

 



That's it for meshes.