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

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            性高朝久久久久久久久久| 青青草原综合久久大伊人精品| 久久久久这里只有精品| 久久免费视频一区| 久久精品国产亚洲av麻豆图片| 激情伊人五月天久久综合| 国产成人久久精品麻豆一区 | 久久久久久A亚洲欧洲AV冫| 精品久久久久久无码国产| 久久伊人精品一区二区三区| 欧美熟妇另类久久久久久不卡| 欧美日韩中文字幕久久伊人| 亚洲伊人久久成综合人影院 | 久久精品国产国产精品四凭 | 亚洲乱码精品久久久久..| 99久久婷婷国产综合精品草原| 久久久久久久久66精品片| 久久久91精品国产一区二区三区| 一本综合久久国产二区| 久久精品亚洲男人的天堂| 久久精品国产精品国产精品污| 久久中文字幕人妻丝袜| 国产亚洲成人久久| 久久这里只有精品久久| 久久久久成人精品无码中文字幕| 亚洲精品无码久久久| 久久久精品久久久久久| 色综合合久久天天综合绕视看| 亚洲成色WWW久久网站| 久久精品aⅴ无码中文字字幕不卡| 精品久久久久国产免费| yellow中文字幕久久网| 国产91久久综合| 精品99久久aaa一级毛片| 久久99精品久久久久久水蜜桃| 久久青草国产精品一区| 久久亚洲高清观看| 国内精品久久久久影院网站| 精品久久人人爽天天玩人人妻| 国产国产成人久久精品| 久久成人18免费网站|