⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 meshloader.cpp

📁 DX例子中等难度的。全是新例子。VC2003
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//=============================================================================
// File: MeshLoader.cpp
//=============================================================================
#include "dxstdafx.h"
#pragma warning(disable: 4995)
#include "meshloader.h"
#include <fstream>
#pragma warning(default: 4995)
using namespace std;


//-----------------------------------------------------------------------------
// Desc: 构造函数
//-----------------------------------------------------------------------------
CMeshLoader::CMeshLoader()
{
    m_pd3dDevice = NULL;  
    m_pMesh = NULL;  
    ZeroMemory( m_strMediaDir, sizeof(m_strMediaDir) );
}


//-----------------------------------------------------------------------------
// Desc: 析构函数
//-----------------------------------------------------------------------------
CMeshLoader::~CMeshLoader()
{
    Destroy();
}


//-----------------------------------------------------------------------------
// Desc: 释放网格模型材质、纹理已经网格模型对象
//-----------------------------------------------------------------------------
void CMeshLoader::Destroy()
{
	//释放材质和纹理
    for( int iMaterial=0; iMaterial < m_Materials.GetSize(); iMaterial++ )
    {
        Material* pMaterial = m_Materials.GetAt( iMaterial );
        
		//避免对同一纹理对象释放两次
        for( int x=iMaterial+1; x < m_Materials.GetSize(); x++ )
        {
            Material* pCur = m_Materials.GetAt( x );
            if( pCur->pTexture == pMaterial->pTexture )
                pCur->pTexture = NULL;
        }
 
        SAFE_RELEASE( pMaterial->pTexture );
        SAFE_DELETE( pMaterial );
    }

    m_Materials.RemoveAll();
    m_Vertices.RemoveAll();
    m_Indices.RemoveAll();
    m_Attributes.RemoveAll();

	//释放网格模型
    SAFE_RELEASE( m_pMesh );
    m_pd3dDevice = NULL;
}


//-----------------------------------------------------------------------------
// Desc: 创建网格模型相关对象
//-----------------------------------------------------------------------------
HRESULT CMeshLoader::Create( IDirect3DDevice9* pd3dDevice, const WCHAR* strFilename )
{
    HRESULT hr;
    WCHAR str[ MAX_PATH ] = {0};

    //先释放原来的相关内容
    Destroy();

    //保存设备指针
    m_pd3dDevice = pd3dDevice;

    //从指定.obj文件加载相关对象
    V_RETURN( LoadGeometryFromOBJ( strFilename ) );

    //保存当前完整
    WCHAR wstrOldDir[MAX_PATH] = {0};
    GetCurrentDirectory( MAX_PATH, wstrOldDir );
    SetCurrentDirectory( m_strMediaDir );

    //提取材质和纹理
    for( int iMaterial=0; iMaterial < m_Materials.GetSize(); iMaterial++ )
    {
        Material* pMaterial = m_Materials.GetAt( iMaterial );
        if( pMaterial->strTexture[0] )
        {   
			//避免创建相同的纹理两次
            bool bFound = false;
            for( int x=0; x < iMaterial; x++ )
            {
                Material* pCur = m_Materials.GetAt( x );
                if( 0 == wcscmp( pCur->strTexture, pMaterial->strTexture ) )
                {
                    bFound = true;
                    pMaterial->pTexture = pCur->pTexture;
                    break;
                }
            }

            //创建纹理
            if( !bFound )
            {
				//应先从纹理文件路径中提取纹理文件名

                V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, pMaterial->strTexture ) );
                V_RETURN( D3DXCreateTextureFromFile( pd3dDevice,  str, //pMaterial->strTexture, 
                                                    &(pMaterial->pTexture )));
            }
        }
    }

    //恢复当前路径
    SetCurrentDirectory( wstrOldDir );

    //创建网格对象
    ID3DXMesh* pMesh = NULL;
	V_RETURN( D3DXCreateMeshFVF( m_Indices.GetSize() / 3, m_Vertices.GetSize(), 
                              D3DXMESH_MANAGED | D3DXMESH_32BIT, 
							  D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, 
                              pd3dDevice, &pMesh ) ); 
    
    //复制顶点数据到网格对象
    VERTEX* pVertex;
    V_RETURN( pMesh->LockVertexBuffer( 0, (void**) &pVertex ) );
    memcpy( pVertex, m_Vertices.GetData(), m_Vertices.GetSize() * sizeof(VERTEX) );
    pMesh->UnlockVertexBuffer();
    m_Vertices.RemoveAll();
    
    //复制索引数据到网格对象
    DWORD* pIndex;
    V_RETURN( pMesh->LockIndexBuffer( 0, (void**) &pIndex ) );
    memcpy( pIndex, m_Indices.GetData(), m_Indices.GetSize() * sizeof(DWORD) );
    pMesh->UnlockIndexBuffer();
    m_Indices.RemoveAll();
    
    //复制属性数据到网格对象
    DWORD* pSubset;
    V_RETURN( pMesh->LockAttributeBuffer( 0, &pSubset ) );
    memcpy( pSubset, m_Attributes.GetData(), m_Attributes.GetSize() * sizeof(DWORD) );
    pMesh->UnlockAttributeBuffer();
    m_Attributes.RemoveAll();

	//对网格模型进行优化
    DWORD* aAdjacency = new DWORD[pMesh->GetNumFaces() * 3];
    if( aAdjacency == NULL )
        return E_OUTOFMEMORY;

    V( pMesh->GenerateAdjacency(1e-6f,aAdjacency) );
    V( pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, aAdjacency, NULL, NULL, NULL) );
    
    SAFE_DELETE_ARRAY( aAdjacency );
    m_pMesh = pMesh;

    return S_OK;
}


//-----------------------------------------------------------------------------
// Desc: 从.obj文件加载数据
//-----------------------------------------------------------------------------
HRESULT CMeshLoader::LoadGeometryFromOBJ( const WCHAR* strFileName )
{
    WCHAR strMaterialFilename[MAX_PATH] = {0};
    WCHAR wstr[MAX_PATH];
    char str[MAX_PATH];
    HRESULT hr;

    //根据文件名查找文件
    V_RETURN( DXUTFindDXSDKMediaFileCch( wstr, MAX_PATH, strFileName ) );
    WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, MAX_PATH, NULL, NULL );

    //保存.obj文件完整路径
    StringCchCopy( m_strMediaDir, MAX_PATH-1, wstr );
    WCHAR* pch = wcsrchr( m_strMediaDir, L'\\' );
    if( pch )
        *pch = NULL;

	//为顶点位置坐标、纹理坐标和法线数据创建临时存储空间
    CGrowableArray< D3DXVECTOR3 > Positions;
    CGrowableArray< D3DXVECTOR2 > TexCoords;
    CGrowableArray< D3DXVECTOR3 > Normals;
    
	//第一个子网格使用默认材质
    Material* pMaterial = new Material();
    if( pMaterial == NULL )
        return E_OUTOFMEMORY;

    InitMaterial( pMaterial );
    StringCchCopy( pMaterial->strName, MAX_PATH-1, L"default" );
    m_Materials.Add( pMaterial );

    DWORD dwCurSubset = 0;

    // File input
    WCHAR strCommand[256] = {0};
    wifstream InFile( str );
    if( !InFile )
        return DXTRACE_ERR( L"wifstream::open", E_FAIL );
    
    for(;;)
    {
        InFile >> strCommand;
        if( !InFile )
            break;
        
        if( 0 == wcscmp( strCommand, L"#" ) )
        {
            // Comment
        }
        else if( 0 == wcscmp( strCommand, L"v" ) )
        {
            // Vertex Position
            float x, y, z;
            InFile >> x >> y >> z;
            Positions.Add( D3DXVECTOR3( x, y, z ) ); 
        }
        else if( 0 == wcscmp( strCommand, L"vt" ) )
        {
            // Vertex TexCoord
            float u, v;
            InFile >> u >> v;
            TexCoords.Add( D3DXVECTOR2( u, v ) );
        }
        else if( 0 == wcscmp( strCommand, L"vn" ) )
        {
            // Vertex Normal
            float x, y, z;
            InFile >> x >> y >> z;
            Normals.Add( D3DXVECTOR3( x, y, z ) );
        }
        else if( 0 == wcscmp( strCommand, L"f" ) )
        {
            // Face
            UINT iPosition, iTexCoord, iNormal;
            VERTEX vertex;

            for( UINT iFace=0; iFace < 3; iFace++ )
            {
                ZeroMemory( &vertex, sizeof(VERTEX) );

                // OBJ format uses 1-based arrays
                InFile >> iPosition;
                vertex.position = Positions[ iPosition-1 ];

                if( '/' == InFile.peek() )
                {
                    InFile.ignore();

                    if( '/' != InFile.peek() )
                    {
                        // Optional texture coordinate
                        InFile >> iTexCoord;
                        vertex.texcoord = TexCoords[ iTexCoord-1 ];
                    }

                    if( '/' == InFile.peek() )
                    {
                        InFile.ignore();

                        // Optional vertex normal
                        InFile >> iNormal;
                        vertex.normal = Normals[ iNormal-1 ];
                    }
                }

                // If a duplicate vertex doesn't exist, add this vertex to the Vertices
                // list. Store the index in the Indices array. The Vertices and Indices
                // lists will eventually become the Vertex Buffer and Index Buffer for
                // the mesh.
                DWORD index = AddVertex( iPosition, &vertex );
                m_Indices.Add( index );
            }
            m_Attributes.Add( dwCurSubset );
        }
        else if( 0 == wcscmp( strCommand, L"mtllib" ) )
        {
            // Material library
            InFile >> strMaterialFilename;
        }
        else if( 0 == wcscmp( strCommand, L"usemtl" ) )
        {
            // Material

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -