• <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>

            麒麟子

            ~~

            導(dǎo)航

            <2008年12月>
            30123456
            78910111213
            14151617181920
            21222324252627
            28293031123
            45678910

            統(tǒng)計(jì)

            常用鏈接

            留言簿(12)

            隨筆分類

            隨筆檔案

            Friends

            WebSites

            積分與排名

            最新隨筆

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            [導(dǎo)入]DX 骨骼動(dòng)畫

            第一,了解骨骼結(jié)構(gòu)(Skeletal Structures)和骨層級(jí)(Bone Hierarchies):

            骨骼結(jié)構(gòu)就是連續(xù)很多的骨頭(Bone)相結(jié)合,形成的骨層級(jí)。第一個(gè)骨頭叫做根骨(root bone),是形成骨骼結(jié)構(gòu)的關(guān)鍵點(diǎn)。其它所有的骨骼作為孩子骨(child bone)或者兄弟骨(sibling bone)附加在根骨之上。所謂的“骨”用一個(gè)幀(frame)對(duì)象表示。在Directx中,用一個(gè)D3DXFRAME結(jié)構(gòu)或者X文件中的Frame template來表示幀對(duì)象。下面看一下Frame template和D3DXFRAME結(jié)構(gòu)的定義:

            template Frame
            {
                    < 3D82AB46-62DA-11cf-AB39-0020AF71E433 >
                    FrameTransformMatrix frameTransformMatrix;      // 骨骼相對(duì)于父節(jié)點(diǎn)的坐標(biāo)變換矩陣,就是一個(gè)matrix
                    Mesh mesh;                                      // 骨骼的Mesh
            }

            typedef struct _D3DXFRAME
            {
            LPSTR                   Name;                   // 骨骼名稱
            D3DXMATRIX         TransformationMatrix;        // 相對(duì)與父節(jié)點(diǎn)的坐標(biāo)變換矩陣
            LPD3DXMESHCONTAINER     pMeshContainer; // LPD3DXMESHCONTAINER對(duì)象,
            //用來加載MESH,還有一些附加屬性,見SDK
            struct _D3DXFRAME       *pFrameSibling;         // 兄弟節(jié)點(diǎn)指針,和下面的子節(jié)點(diǎn)指針
            // 一塊作用構(gòu)成骨骼的層次結(jié)構(gòu)。   
                struct _D3DXFRAME       *pFrameFirstChild;   // 子節(jié)點(diǎn)指針
            } D3DXFRAME, *LPD3DXFRAME;


            注意D3DXFRAME * pFrameSibling和D3DXFRAME * pFrameFirstChild,主要是利用這兩個(gè)指針形成骨層級(jí)。pFrameSibling把一個(gè)骨頭連接到兄弟層級(jí),相對(duì)的,pFrameFirstChild把一個(gè)骨頭連接到子層級(jí)。通常,你需要用建模軟件為你的程序創(chuàng)建那些骨骼結(jié)構(gòu),輸出骨層級(jí)到X文件以便使用。Microsoft有3D Studio Max和Maya的輸出插件(exporter),可以輸出骨骼和動(dòng)畫數(shù)據(jù)到X文件。很多建模程序也都有這樣的功能。


            利用D3DXFRAME pointers指針形成了一個(gè)兄弟幀和孩子幀的鏈表。

            在前面template Frame中已經(jīng)提及過每個(gè)Frame數(shù)據(jù)對(duì)象中存放著一個(gè)變換矩陣,這個(gè)矩陣描述了該骨骼相對(duì)于父骨骼的位置。另外在根Frame數(shù)據(jù)對(duì)象中內(nèi)嵌了一個(gè)標(biāo)準(zhǔn)的Mesh數(shù)據(jù)對(duì)象。Frame定義了骨骼的層級(jí),而Mesh中的SkinWeights數(shù)據(jù)對(duì)象定義了Frame代表的骨頭。我們用D3DXFRAME結(jié)構(gòu)容納從X文件加載進(jìn)來的Frame數(shù)據(jù)對(duì)象。為了更好的容納Frame數(shù)據(jù)對(duì)象,我們需要擴(kuò)展下D3DXFRAME結(jié)構(gòu):

            struct D3DXFRAME_EX : D3DXFRAME
            {
            D3DXMATRIX matCombined;   // 組合變換矩陣,用于儲(chǔ)存變換的骨骼矩陣
            D3DXMATRIX matOriginal;   // 從X文件加載的原始變換矩陣
            D3DXFRAME_EX()
            {
                Name = NULL;
                pMeshContainer = NULL;
                pFrameSibling = pFrameFirstChild = NULL;
                D3DXMatrixIdentity(&matCombined);
                D3DXMatrixIdentity(&matOriginal);
                D3DXMatrixIdentity(&TransformationMatrix);
            }

            ~D3DXFRAME_EX()
            {
                delete [] Name;          Name = NULL;
                delete pFrameSibling;    pFrameSibling = NULL;
                delete pFrameFirstChild; pFrameFirstChild = NULL;
            }
            }

            利用我們以前介紹的cXParse類可以遍歷X文件的數(shù)據(jù)對(duì)象,從而加載出Frame數(shù)據(jù)對(duì)象。下面的代碼都是寫在方法ParseObject中,如下:

            // 判斷當(dāng)前分析的是不是Frame節(jié)點(diǎn)
            if( objGUID == TID_D3DRMFrame )
            {
            // 引用對(duì)象直接返回,不需要做分析。一個(gè)數(shù)據(jù)段實(shí)際定義一次后可以被其他模板引用,例
            //如后面的Animation動(dòng)畫模板就會(huì)引用這里的Frame
            // 節(jié)點(diǎn),標(biāo)識(shí)動(dòng)畫關(guān)聯(lián)的骨骼。
            if( pDataObj->IsReference() )
            return true;
                    // D3DXFRAME_EX為D3DXFRAME的擴(kuò)展結(jié)構(gòu),增加些數(shù)據(jù)成員
                    D3DXFRAME_EX *pFrame = new D3DXFRAME_EX();

            // 得到名稱
                    pFrame->Name = GetObjectName( pDataObj );

            // 注意觀察文件就可以發(fā)現(xiàn)一個(gè)Frame要么是根Frame,父節(jié)點(diǎn)不存在, 要么作為某

            //個(gè)Frame的孩子Frame而存在。
                    if( NULL == pData )
                    {
                            // 作為根節(jié)點(diǎn)的兄弟節(jié)點(diǎn)加入鏈表。
                            pFrame->pFrameSibling = m_pRootFrame;
                            m_pRootFrame = pFrame;
                            pFrame = NULL;
                        // 將自定義數(shù)據(jù)指針指向自己,供子節(jié)點(diǎn)引用。
                            pData = ( void** )&m_pRootFrame;
                     }
                     else
                     {
                            // 作為傳入節(jié)點(diǎn)的子節(jié)點(diǎn)
                            D3DXFRAME_EX *pDataFrame = ( D3DXFRAME_EX* )( *pData );
                            pFrame->pFrameSibling = pDataFrame->pFrameFirstChild;
                            pDataFrame->pFrameFirstChild = pFrame;
                            pFrame = NULL;
                            pData = ( void** )&pDataFrame->pFrameFirstChild;
                      }
            }

            記住我們只需要做一件事情,判斷類型,分配匹配的對(duì)象然后拷貝數(shù)據(jù),下面來分析Frame中的matrix,

            // frame的坐標(biāo)變換矩陣, 因?yàn)閙atrix必然屬于某個(gè)Frame所以pData必須有效
            else if( objGUID == TID_D3DRMFrameTransformMatrix && pData )
            {
                      // 我們可以肯定pData指向某個(gè)Frame
                      D3DXFRAME_EX *pDataFrame = ( D3DXFRAME_EX* )( *pData );
                      // 先取得緩沖區(qū)大小,應(yīng)該是個(gè)標(biāo)準(zhǔn)的4x4矩陣
                      DWORD size = 0;
                      LPCVOID buffer = NULL;

                      hr = pDataObj->Lock( &size, &buffer );
                      if( FAILED( hr ) )
            return false;

                      // 拷貝數(shù)據(jù)
                      if( size == sizeof( D3DXMATRIX ) )
                      {
                           memcpy( &pDataFrame->TransformationMatrix, buffer, size );
                           pDataObj->Unlock();
                           pDataFrame->matOriginal = pDataFrame->TransformationMatrix;
                      }
            }

            第二,修改和更新骨骼層級(jí):

            加載完骨骼層級(jí)之后,你可以操作它,更改骨骼的方位。你需要?jiǎng)?chuàng)建一個(gè)遞歸函數(shù),按照名字找到相應(yīng)的Frame數(shù)據(jù)對(duì)象。這個(gè)函數(shù)如下:

            D3DXFRAME_EX *FindFrame(D3DXFRAME_EX *Frame, char *Name)
            {
            if(Frame && Frame->Name && Name) {
            // 如果名字找到,返回一個(gè)Frame指針
            if(!strcmp(Frame->Name, Name)) // strcmp函數(shù)比較兩個(gè)字符串,如果兩個(gè)字符串相等,返回0
            return Frame;
            }
            // 在sibling frames找匹配的名字
            if(Frame && Frame->pFrameSibling) {
            D3DXFRAME_EX *FramePtr = FindFrame((D3DXFRAME_EX*)Frame->pFrameSibling, Name);
            if(FramePtr)
            return FramePtr;

            }
            // 在child frames找匹配的名字
            if(Frame && Frame->pFrameFirstChild) {
            D3DXFRAME_EX *FramePtr = FindFrame((D3DXFRAME_EX*)Frame->pFrameFirstChild,Name);
            if(FramePtr)
            return FramePtr;
            }
            // 如果沒有找到,返回 NULL
            return NULL;
            }

            如果你想找到一個(gè)叫“Leg”的Frame,可以把“Leg”傳入FindFrame函數(shù),并且提供指向RootFrame的指針:
            // pRootframe 為D3DXFRAME_EX root frame 指針
            D3DXFRAME_EX *Frame = FindFrame(pRootFrame, "Leg");
            if(Frame) {
            // 可以在這里做一些處理,比如旋轉(zhuǎn)操作
            // 你在這里可以稍微的旋轉(zhuǎn)這個(gè)骨頭
            D3DXMatrixRotationY(&Frame->TransformationMatrix, 1.57f);
            }

            一旦你修改變換骨頭,你需要更新整個(gè)骨骼層級(jí),也就是把變換的組合矩陣存入D3DXFRAME_EX結(jié)構(gòu)的matCombined成員中,用于后面的渲染。下面的函數(shù)應(yīng)該增加到D3DXFRAME_EX結(jié)構(gòu)中,如下:

            void UpdateHierarchy(D3DXMATRIX *matTransformation = NULL)
            {
                D3DXFRAME_EX *pFramePtr;
                D3DXMATRIX matIdentity;
                // 如果為空,用一個(gè)全同矩陣
                if(!matTransformation) {
                  D3DXMatrixIdentity(&matIdentity);
                  matTransformation = &matIdentity;
                }
                // 把變換矩陣組合到matCombined中
                matCombined = TransformationMatrix * (*matTransformation);
                // 更新兄弟層級(jí)
                if((pFramePtr = (D3DXFRAME_EX*)pFrameSibling))
                  pFramePtr->UpdateHierarchy(matTransformation);
                // 更新孩子層級(jí)
                if((pFramePtr = (D3DXFRAME_EX*)pFrameFirstChild))
                  pFramePtr->UpdateHierarchy(&matCombined);
            }
            現(xiàn)在matCombined儲(chǔ)存著每個(gè)骨骼相對(duì)于原點(diǎn)的變換矩陣,然后只要把各個(gè)頂點(diǎn)附在相應(yīng)的骨骼上,就能渲染了。

            第三,使用蒙皮網(wǎng)格:

            蒙皮網(wǎng)格和普通網(wǎng)格的唯一不同點(diǎn)就是看XskinMeshHeader和SkinWeights模版是否存在。如果把這兩個(gè)模版從任何一個(gè)蒙皮網(wǎng)格里面移走的話,就可以得到一個(gè)普通網(wǎng)格。在X文件中,我們將會(huì)發(fā)現(xiàn)一個(gè)GUID為TID_D3DRMMesh的模版,這表示模版里面存有一個(gè)網(wǎng)格。利用D3D的幫助函數(shù)D3DXLoadSkinMeshFromXof將會(huì)加載蒙皮網(wǎng)格和其它補(bǔ)充性數(shù)據(jù)。只需要向它傳遞一個(gè)IDirectXFileData指針,然后它將為你做剩下的事情。現(xiàn)在介紹下D3DXLoadSkinMeshFromXof函數(shù):

            HRESULT D3DXLoadSkinMeshFromXof(
            LPD3DXFILEDATA pxofMesh,        //X文件數(shù)據(jù)接口
            DWORD Options,                   //加載參數(shù)
            LPDIRECT3DDEVICE9 pD3DDevice, //使用的三維設(shè)備
            LPD3DXBUFFER * ppAdjacency,      //鄰接信息緩沖接口
            LPD3DXBUFFER * ppMaterials,       //材質(zhì)緩沖接口
            LPD3DXBUFFER * ppEffectInstances, //效果實(shí)例接口
            DWORD * pMatOut,                 //材質(zhì)數(shù)
            LPD3DXSKININFO * ppSkinInfo,      //蒙皮信息接口
            LPD3DXMESH * ppMesh             //加載的網(wǎng)格模型接口
            );


            文章來源:http://ly-weiwei.blog.163.com/blog/static/72975283200922394958876

            posted on 2009-03-23 21:50 麒麟子 閱讀(237) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            狼狼综合久久久久综合网| 久久久久一本毛久久久| 国产成人久久AV免费| 精品国产综合区久久久久久| 久久久久亚洲AV成人网| 久久这里都是精品| 国产午夜久久影院| 2021国产精品久久精品| 国产成人精品久久二区二区| 日韩久久无码免费毛片软件| 久久久久久国产精品免费无码 | 亚洲欧美日韩精品久久| 色99久久久久高潮综合影院| 国产精品美女久久久| 伊人久久大香线蕉AV色婷婷色| 夜夜亚洲天天久久| 久久久久亚洲av无码专区导航| 亚洲精品高清一二区久久| 国产精品九九久久免费视频| MM131亚洲国产美女久久| 精品久久久久久国产| 久久99精品久久久久久噜噜| 久久精品国产亚洲网站| 国产精品国色综合久久| 久久人人爽人人爽人人片AV高清 | 久久天天躁狠狠躁夜夜不卡| 精品久久人人爽天天玩人人妻 | 久久精品免费一区二区三区| 无码人妻精品一区二区三区久久| 亚洲国产一成久久精品国产成人综合 | 久久久久国产精品嫩草影院| 久久中文字幕视频、最近更新 | 久久亚洲AV成人无码国产| 久久亚洲AV成人无码软件| 无码8090精品久久一区| 久久精品这里只有精99品| 人人狠狠综合久久亚洲88| 久久中文娱乐网| 久久成人精品| 亚洲欧美日韩精品久久亚洲区 | 久久精品国产2020|