• <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 閱讀(1294) 評論(0)  編輯 收藏 引用 所屬分類: ■ DXUT Research

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            国产香蕉久久精品综合网| 99久久综合国产精品免费| 亚洲狠狠婷婷综合久久蜜芽 | 欧美午夜A∨大片久久 | 狠狠色婷婷久久一区二区三区| 一本色道久久99一综合| 一本色道久久综合狠狠躁| 久久99国产亚洲高清观看首页 | 亚洲欧美伊人久久综合一区二区| 国内精品综合久久久40p| 99麻豆久久久国产精品免费| 看全色黄大色大片免费久久久| 少妇无套内谢久久久久| 国产精品久久久福利| 一级a性色生活片久久无| 无码人妻久久久一区二区三区| 97超级碰碰碰碰久久久久| 人妻少妇久久中文字幕一区二区 | 国产91久久精品一区二区| 久久久久亚洲av毛片大| 国产精品久久久久久久久| 久久久高清免费视频| 久久精品国产精品亚洲下载| 久久综合狠狠综合久久综合88| 热RE99久久精品国产66热| 国产成人精品久久综合| 精品久久人妻av中文字幕| 亚洲精品蜜桃久久久久久| 久久频这里精品99香蕉久| 久久久久无码专区亚洲av| 93精91精品国产综合久久香蕉| 97久久综合精品久久久综合| 亚洲熟妇无码另类久久久| 久久综合久久综合亚洲| 少妇被又大又粗又爽毛片久久黑人| 久久这里只精品国产99热| av无码久久久久久不卡网站| 国产精品久久成人影院| 国产成人99久久亚洲综合精品| 色综合色天天久久婷婷基地| 亚洲天堂久久精品|