• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當自強而不息

            DXUT源碼分析 ---- 類CDXUTMeshFile

            類CDXUTMeshFile位于DXUTMesh.h和DXUTMesh.cpp中,繼承自類CDXUTMeshFrame,其實類CDXUTMeshFrame本身只完成一些基礎操作,不是最終使用的一個類,CDXUTMeshFile在CDXUTMeshFrame的基礎上將各種操作進一步封裝。

            在.x網格模型中使用框架的主要目的是實現模型自身包含的動畫,而CDXUTMeshFile和CDXUTMeshFrame雖然考慮了網格模型的層次框架,可是并沒有實現對網格模型動畫的播放,所以通常不直接使用這兩個類,因為對于不包含動畫信息的靜態網格模型CDXUTMesh類就已經足夠了。當然也完全可以像使用CDXUTMesh類一樣使用CDXUTMeshFile類來操作不包含動畫信息的網格模型。

            來看看CDXUTMeshFile的定義:

            //-----------------------------------------------------------------------------
            // Name: class CDXUTMeshFile
            // Desc: Class for loading and rendering file-based meshes
            //-----------------------------------------------------------------------------
            class CDXUTMeshFile : public CDXUTMeshFrame
            {
                HRESULT LoadMesh( LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXFILEDATA pFileData, CDXUTMeshFrame
            * pParentFrame );
                HRESULT LoadFrame( LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXFILEDATA pFileData, CDXUTMeshFrame
            * pParentFrame );

            public:
                HRESULT Create( LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strFilename );
                HRESULT CreateFromResource( LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strResource, LPCWSTR strType );

                
            // For pure devices, specify the world transform. 
                
            // If the world transform is not specified on pure devices, this function will fail.
                HRESULT Render( LPDIRECT3DDEVICE9 pd3dDevice, D3DXMATRIX* pmatWorldMatrix = NULL );

                CDXUTMeshFile() : CDXUTMeshFrame( L
            "CDXUTMeshFile_Root" ) {}
            };


            LoadMesh()負責從ID3DXFileData中加載一個網格,該函數是內部調用的,其實質是調用CDXUTMesh::Create()函數來加載。

            HRESULT CDXUTMeshFile::LoadMesh(LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXFILEDATA pFileData, CDXUTMeshFrame* pParentFrame)
            {
                
            // Currently only allowing one mesh per frame
                if( pParentFrame->m_pMesh )
                    
            return E_FAIL;

                
            // Get the mesh name

                CHAR  strAnsiName[
            512= {0};
                WCHAR strName[
            512];
                SIZE_T dwNameLength 
            = 512;
                HRESULT hr;

                
            if( FAILED( hr = pFileData->GetName(strAnsiName, &dwNameLength) ) )
                    
            return hr;

                MultiByteToWideChar(CP_ACP, 
            0, strAnsiName, -1, strName, 512);
                strName[
            511= 0;

                
            // Create the mesh

                pParentFrame
            ->m_pMesh = new CDXUTMesh(strName);

                
            if( pParentFrame->m_pMesh == NULL )
                    
            return E_OUTOFMEMORY;

                pParentFrame
            ->m_pMesh->Create( pd3dDevice, pFileData );

                
            return S_OK;
            }
             

            LoadFrame()用于從ID3DXFileData中加載一個框架:

            HRESULT CDXUTMeshFile::LoadFrame(LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXFILEDATA pFileData, CDXUTMeshFrame* pParentFrame)
            {
                LPD3DXFILEDATA   pChildData 
            = NULL;
                GUID             Guid;
                SIZE_T             cbSize;
                CDXUTMeshFrame
            *  pCurrentFrame;
                HRESULT             hr;

                
            // Get the type of the object
                if( FAILED( hr = pFileData->GetType( &Guid ) ) )
                    
            return hr;

                
            if(Guid == TID_D3DRMMesh)
                {
                    hr 
            = LoadMesh(pd3dDevice, pFileData, pParentFrame);

                    
            if( FAILED(hr) )
                        
            return hr;
                }
                
            if(Guid == TID_D3DRMFrameTransformMatrix)
                {
                    D3DXMATRIX
            * pmatMatrix;
                    hr 
            = pFileData->Lock(&cbSize, (LPCVOID*&pmatMatrix);

                    
            if( FAILED(hr) )
                        
            return hr;

                    
            // Update the parent's matrix with the new one
                    pParentFrame->SetMatrix(pmatMatrix);
                }
                
            if(Guid == TID_D3DRMFrame)
                {
                    
            // Get the frame name
                    CHAR   strAnsiName[512= "";
                    WCHAR  strName[
            512];
                    SIZE_T dwNameLength 
            = 512;
                    SIZE_T cChildren;

                    
            if( FAILED( hr = pFileData->GetName(strAnsiName, &dwNameLength) ) )
                        
            return hr;

                    MultiByteToWideChar(CP_ACP, 
            0, strAnsiName, -1, strName, 512);
                    strName[
            511= 0;

                    
            // Create the frame
                    pCurrentFrame = new CDXUTMeshFrame(strName);
                    
            if(pCurrentFrame == NULL)
                        
            return E_OUTOFMEMORY;

                    pCurrentFrame
            ->m_pNext = pParentFrame->m_pChild;
                    pParentFrame
            ->m_pChild = pCurrentFrame;

                    
            // Enumerate child objects

                    pFileData
            ->GetChildren(&cChildren);

                    
            for (UINT iChild = 0; iChild < cChildren; iChild++)
                    {
                        
            // Query the child for its FileData
                        hr = pFileData->GetChild(iChild, &pChildData);

                        
            if( SUCCEEDED(hr) )
                        {
                            hr 
            = LoadFrame(pd3dDevice, pChildData, pCurrentFrame);
                            SAFE_RELEASE( pChildData );
                        }

                        
            if( FAILED(hr) )
                            
            return hr;
                    }
                }

                
            return S_OK;
            }

            首先,該函數調用GetType()獲取對象的GUID:
                // Get the type of the object
            if( FAILED( hr = pFileData->GetType( &Guid ) ) )
            return hr;

            接下來根據GUID分別進行相應的操作,若是網格則調用LoadMesh()加載網格,若是框架變換矩陣則設置變換矩陣,若是框架,相應的操作有些復雜,首先獲取框架的名稱并將其轉化為widechar類型:

                   if( FAILED( hr = pFileData->GetName(strAnsiName, &dwNameLength) ) )
            return hr;
                    MultiByteToWideChar(CP_ACP, 0, strAnsiName, -1, strName, 512);
            strName[511] = 0;

            接著新建一個CDXUTMeshFrame對象并將其添加進鏈表:

                    // Create the frame
            pCurrentFrame = new CDXUTMeshFrame(strName);
            if(pCurrentFrame == NULL)
            return E_OUTOFMEMORY;
                    pCurrentFrame->m_pNext = pParentFrame->m_pChild;
            pParentFrame->m_pChild = pCurrentFrame;

            最后遍歷子框架并遞歸調用LoadFrame()加載框架:

                    // Enumerate child objects
                    pFileData->GetChildren(&cChildren);
                    for (UINT iChild = 0; iChild < cChildren; iChild++)
            {
            // Query the child for its FileData
            hr = pFileData->GetChild(iChild, &pChildData);
                        if( SUCCEEDED(hr) )
            {
            hr = LoadFrame(pd3dDevice, pChildData, pCurrentFrame);
            SAFE_RELEASE( pChildData );
            }
                        if( FAILED(hr) )
            return hr;
            }

             

            第一個Create()函數負責從模型文件加載網格模型:

            HRESULT CDXUTMeshFile::Create(LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strFilename)
            {
                LPD3DXFILE           pDXFile   
            = NULL;
                LPD3DXFILEENUMOBJECT pEnumObj  
            = NULL;
                LPD3DXFILEDATA       pFileData 
            = NULL;
                HRESULT hr;
                SIZE_T cChildren;

                
            // Create a x file object
                if( FAILED( hr = D3DXFileCreate(&pDXFile) ) )
                    
            return E_FAIL;

                
            // Register templates for d3drm and patch extensions.
                if( FAILED( hr = pDXFile->RegisterTemplates((void*) D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES) ) )
                {
                    SAFE_RELEASE( pDXFile );
                    
            return E_FAIL;
                }

                
            // Find the path to the file, and convert it to ANSI (for the D3DXOF API)

                WCHAR strPath[MAX_PATH];
                CHAR  strPathANSI[MAX_PATH];
                DXUTFindDXSDKMediaFileCch(strPath, 
            sizeof(strPath) / sizeof(WCHAR), strFilename);
                    
                WideCharToMultiByte(CP_ACP, 
            0, strPath, -1, strPathANSI, MAX_PATH, NULL, NULL);
                strPathANSI[MAX_PATH 
            - 1= 0;
                
                
            // Create enum object
                hr = pDXFile->CreateEnumObject((void*) strPathANSI, D3DXF_FILELOAD_FROMFILE, &pEnumObj);

                
            if( FAILED(hr) )
                {
                    SAFE_RELEASE( pDXFile );
                    
            return hr;
                }

                
            // Enumerate top level objects (which are always frames)
                pEnumObj->GetChildren(&cChildren);

                
            for (UINT iChild = 0; iChild < cChildren; iChild++)
                {
                    hr 
            = pEnumObj->GetChild(iChild, &pFileData);
                    
            if (FAILED(hr))
                        
            return hr;

                    hr 
            = LoadFrame(pd3dDevice, pFileData, this);
                    SAFE_RELEASE(pFileData);

                    
            if( FAILED(hr) )
                    {
                        SAFE_RELEASE(pEnumObj);
                        SAFE_RELEASE(pDXFile);
                        
            return E_FAIL;
                    }
                }

                SAFE_RELEASE(pFileData);
                SAFE_RELEASE(pEnumObj);
                SAFE_RELEASE(pDXFile);

                
            return S_OK;
            }

            首先函數創建了一個ID3DXFileData對象并注冊了XFILE標準模板:
                // Create a x file object
            if( FAILED( hr = D3DXFileCreate(&pDXFile) ) )
            return E_FAIL;
                // Register templates for d3drm and patch extensions.
            if( FAILED( hr = pDXFile->RegisterTemplates((void*) D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES) ) )
            {
            SAFE_RELEASE( pDXFile );
            return E_FAIL;
            }

            接下來查找網格模型文件將路徑存儲在strPath中,并將該路徑轉化為ANSI類型存儲在strPathANSI中:

                // Find the path to the file, and convert it to ANSI (for the D3DXOF API)
                WCHAR strPath[MAX_PATH];
            CHAR strPathANSI[MAX_PATH];
            DXUTFindDXSDKMediaFileCch(strPath, sizeof(strPath) / sizeof(WCHAR), strFilename);
                WideCharToMultiByte(CP_ACP, 0, strPath, -1, strPathANSI, MAX_PATH, NULL, NULL);
            strPathANSI[MAX_PATH - 1] = 0;

            再接下來創建一個ID3DXFileEnumObject枚舉對象負責從.x文件中讀取數據:

                // Create enum object
            hr = pDXFile->CreateEnumObject((void*) strPathANSI, D3DXF_FILELOAD_FROMFILE, &pEnumObj);
                if( FAILED(hr) )
            {
            SAFE_RELEASE( pDXFile );
            return hr;
            }

            函數CreateEnumObject()聲明如下:

            Creates an enumerator object that will read a .x file.

            HRESULT CreateEnumObject(
            LPCVOID pvSource,
            D3DXF_FILELOADOPTIONS loadflags,
            ID3DXFileEnumObject ** ppEnumObj
            );

            Parameters

            pvSource
            [out] The data source. Either:
            • A file name
            • A D3DXF_FILELOADMEMORY structure
            • A D3DXF_FILELOADRESOURCE structure
            Depending on the value of loadflags.
            loadflags
            [in] Value that specifies the source of the data. This value can be one of the D3DXF_FILELOADOPTIONS flags.
            ppEnumObj
            [out] Address of a pointer to an ID3DXFileEnumObject interface, representing the created enumerator object.

            Return Values

            If the method succeeds, the return value is S_OK. If the method fails, the return value can be one of the following: D3DXFERR_BADVALUE, D3DXFERR_PARSEERROR.

            Remarks

            After using this method, use one of the ID3DXFileEnumObject methods to retrieve a data object.

            再接下來通過ID3DXFileEnumObjec枚舉對象讀取數據并調用LoadFrame()加載框架:

                // Enumerate top level objects (which are always frames)
            pEnumObj->GetChildren(&cChildren);
                for (UINT iChild = 0; iChild < cChildren; iChild++)
            {
            hr = pEnumObj->GetChild(iChild, &pFileData);
            if (FAILED(hr))
            return hr;
                    hr = LoadFrame(pd3dDevice, pFileData, this);
            SAFE_RELEASE(pFileData);
                    if( FAILED(hr) )
            {
            SAFE_RELEASE(pEnumObj);
            SAFE_RELEASE(pDXFile);
            return E_FAIL;
            }
            }

            最后釋放不再使用的COM對象:

                SAFE_RELEASE(pFileData);
            SAFE_RELEASE(pEnumObj);
            SAFE_RELEASE(pDXFile);

             

            第二個Create()函數與第一個非常類似,只是該函數負責從資源加載網格模型:

            HRESULT CDXUTMeshFile::CreateFromResource(LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strResource, LPCWSTR strType)
            {
                LPD3DXFILE           pDXFile   
            = NULL;
                LPD3DXFILEENUMOBJECT pEnumObj  
            = NULL;
                LPD3DXFILEDATA       pFileData 
            = NULL;
                HRESULT hr;
                SIZE_T cChildren;

                
            // Create a x file object
                if( FAILED( hr = D3DXFileCreate(&pDXFile) ) )
                    
            return E_FAIL;

                
            // Register templates for d3drm and patch extensions.
                if( FAILED( hr = pDXFile->RegisterTemplates((void*) D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES) ) )
                {
                    SAFE_RELEASE( pDXFile );
                    
            return E_FAIL;
                }
                
                CHAR strTypeAnsi[MAX_PATH];
                CHAR strResourceAnsi[MAX_PATH];

                WideCharToMultiByte(CP_ACP, 
            0, strType, -1, strTypeAnsi, MAX_PATH, NULL, NULL);
                strTypeAnsi[MAX_PATH 
            - 1= 0;

                WideCharToMultiByte(CP_ACP, 
            0, strResource, -1, strResourceAnsi, MAX_PATH, NULL, NULL);
                strResourceAnsi[MAX_PATH 
            - 1= 0;

                D3DXF_FILELOADRESOURCE dxlr;

                dxlr.hModule 
            = NULL;
                dxlr.lpName 
            = strResourceAnsi;
                dxlr.lpType 
            = strTypeAnsi;

                
            // Create enum object
                hr = pDXFile->CreateEnumObject((void*&dxlr, D3DXF_FILELOAD_FROMRESOURCE, &pEnumObj);

                
            if( FAILED(hr) )
                {
                    SAFE_RELEASE( pDXFile );
                    
            return hr;
                }

                
            // Enumerate top level objects (which are always frames)

                pEnumObj
            ->GetChildren(&cChildren);

                
            for (UINT iChild = 0; iChild < cChildren; iChild++)
                {
                    hr 
            = pEnumObj->GetChild(iChild, &pFileData);
                    
            if (FAILED(hr))
                        
            return hr;

                    hr 
            = LoadFrame(pd3dDevice, pFileData, this);
                    SAFE_RELEASE( pFileData );

                    
            if( FAILED(hr) )
                    {
                        SAFE_RELEASE(pEnumObj);
                        SAFE_RELEASE(pDXFile);
                        
            return E_FAIL;
                    }
                }

                SAFE_RELEASE(pFileData);
                SAFE_RELEASE(pEnumObj);
                SAFE_RELEASE(pDXFile);

                
            return S_OK;
            }

            唯一需要解釋的代碼是:

                D3DXF_FILELOADRESOURCE dxlr;
                dxlr.hModule = NULL;
            dxlr.lpName = strResourceAnsi;
            dxlr.lpType = strTypeAnsi;
                // Create enum object
            hr = pDXFile->CreateEnumObject((void*) &dxlr, D3DXF_FILELOAD_FROMRESOURCE, &pEnumObj);

            該代碼片段負責從指定的資源中加載網格模型,D3DXF_FILELOADRESOURCE的聲明如下:

            Identifies resource data.

            typedef struct D3DXF_FILELOADRESOURCE {
            HMODULE hModule;
            LPCSTR lpName;
            LPCSTR lpType;
            } D3DXF_FILELOADRESOURCE, *LPD3DXF_FILELOADRESOURCE;

            Members

            hModule
            Handle of the module containing the resource to be loaded. If this member is NULL, the resource must be attached to the executable file that will use it.
            lpName
            Pointer to a string specifying the name of the resource to be loaded. For example, if the resource is a mesh, this member should specify the name of the mesh file.
            lpType
            Pointer to a string specifying the user-defined type identifying the resource.

            Remarks

            This structure identifies a resource to be loaded when an application uses the ID3DXFile::CreateEnumObject method and specifies the D3DXF_FILELOAD_FROMRESOURCE flag.

             

            Render()函數負責網格模型的渲染,它允許用戶在調用時設置一個世界坐標矩陣:

            HRESULT CDXUTMeshFile::Render(LPDIRECT3DDEVICE9 pd3dDevice, D3DXMATRIX* pmatWorldMatrix)
            {
                
            // For pure devices, specify the world transform. 
                
            // If the world transform is not specified on pure devices, this function will fail.

                
            // Set up the world transformation
                D3DXMATRIX matSavedWorld, matWorld;

                
            if (NULL == pmatWorldMatrix)
                    pd3dDevice
            ->GetTransform(D3DTS_WORLD, &matSavedWorld);
                
            else
                    matSavedWorld 
            = *pmatWorldMatrix;

                D3DXMatrixMultiply(
            &matWorld, &matSavedWorld, &m_mat);
                pd3dDevice
            ->SetTransform(D3DTS_WORLD, &matWorld);

                
            // Render opaque subsets in the meshes
                if(m_pChild)
                    m_pChild
            ->Render(pd3dDevice, TRUE, FALSE, &matWorld);

                
            // Enable alpha blending
                pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
                pd3dDevice
            ->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA);
                pd3dDevice
            ->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

                
            // Render alpha subsets in the meshes
                if(m_pChild)
                    m_pChild
            ->Render(pd3dDevice, FALSE, TRUE, &matWorld);

                
            // Restore state
                pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
                pd3dDevice
            ->SetTransform(D3DTS_WORLD, &matSavedWorld);

                
            return S_OK;
            }

            因為CDXUTMeshFile繼承自CDXUTMeshFrame,并且該類的默認構造函數定義如下:

            CDXUTMeshFile() : CDXUTMeshFrame( L"CDXUTMeshFile_Root" ) {}

            也就是說在創建該類對象時默認創建了一個CDXUTMeshFrame對象,這也意味著在加載網格模型時所有后續的CDXUTMeshFrame對象都是該對象的子對象,所以下面的代碼是合法的:

                // Render opaque subsets in the meshes
            if(m_pChild)
            m_pChild->Render(pd3dDevice, TRUE, FALSE, &matWorld);
                // Enable alpha blending
            pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
            pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
            pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
                // Render alpha subsets in the meshes
            if(m_pChild)
            m_pChild->Render(pd3dDevice, FALSE, TRUE, &matWorld);
                // Restore state
            pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
            pd3dDevice->SetTransform(D3DTS_WORLD, &matSavedWorld);

            先渲染所有不透明的子框架對象,再渲染所有半透明的子框架對象,最后恢復到先前的渲染狀態。


            posted on 2008-06-01 10:13 lovedday 閱讀(1288) 評論(0)  編輯 收藏 引用 所屬分類: ■ DXUT Research

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            国产精品美女久久久久AV福利| 亚洲精品午夜国产VA久久成人| 精品久久久久久久无码| 精品久久久噜噜噜久久久| 久久亚洲国产午夜精品理论片| 香港aa三级久久三级| 亚洲第一永久AV网站久久精品男人的天堂AV | 狠狠色丁香婷综合久久| 国产精品永久久久久久久久久| 亚洲婷婷国产精品电影人久久| 日韩精品久久久久久久电影蜜臀| 久久亚洲国产欧洲精品一| 久久精品青青草原伊人| 91精品国产91久久久久久蜜臀| 久久成人小视频| 国产精品久久久久9999| 久久久久久久精品妇女99| 精品久久久久久综合日本| 久久人人爽人人爽人人片AV不| 久久激情亚洲精品无码?V| 久久天天躁狠狠躁夜夜网站| 色综合合久久天天给综看| 91久久国产视频| 国产精品对白刺激久久久| 久久这里只有精品首页| 久久亚洲国产成人精品无码区| 91视频国产91久久久| 性色欲网站人妻丰满中文久久不卡 | 伊人久久精品无码av一区| 久久综合色区| 欧洲国产伦久久久久久久| 激情久久久久久久久久| 51久久夜色精品国产| 欧美久久精品一级c片片| 77777亚洲午夜久久多喷| 久久精品人人槡人妻人人玩AV| 无码人妻久久一区二区三区免费丨 | 久久精品国产99久久久香蕉| 久久中文娱乐网| 久久精品国产一区二区| 久久夜色撩人精品国产|