新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → DXUT源码分析 ---- 类CDXUTMeshFile 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 9695 个阅读者浏览上一篇主题  刷新本主题   平板显示贴子 浏览下一篇主题
     * 贴子主题: DXUT源码分析 ---- 类CDXUTMeshFile 举报  打印  转邮箱  推荐  站内收藏  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      院校:(无权查看)
      注册:2004/7/21
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 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);

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/12/26 10:52:00
      鲜花(0)  鸡蛋(0)        点击这里获取本站专享China-pub购书优惠券
     GoogleAdSense
      
      
      威望:8
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/6/17 16:49:04

    本主题贴数3,分页: [1]

     *树形目录 (最近20个回帖) 顶端 
    主题:  DXUT源码分析 ---- 类CDXUTMeshFile(12886字) - 卷积内核,2008年12月26日
        回复:  好我顶啊!!!(16字) - 秋十三,2009年1月2日
        回复:  该代码片段负责从指定的资源中加载网格模型,D3DXF_FILELOADRESOURCE的声明如下:..(3206字) - 卷积内核,2008年12月26日

    W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    265.625ms