D游戲角色動(dòng)畫_第1頁(yè)
D游戲角色動(dòng)畫_第2頁(yè)
D游戲角色動(dòng)畫_第3頁(yè)
D游戲角色動(dòng)畫_第4頁(yè)
D游戲角色動(dòng)畫_第5頁(yè)
已閱讀5頁(yè),還剩20頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、3D游戲角色動(dòng)畫 摘要:本文主要描述了3D游戲角色動(dòng)畫的原理及應(yīng)用,從介紹微軟的X文件到最為廣泛應(yīng)用的骨骼蒙皮動(dòng)畫,另外簡(jiǎn)要的介紹了下漸變動(dòng)畫的原理。關(guān)鍵詞:Role Animation Skeletal Animation Morphing Animation Skinned Mesh Abstract:Introduce 3D Game Role Animation, for example Skeletal Animation and Skinned Mesh etc. 目錄:一 概述3D角色動(dòng)畫的應(yīng)用二 3D游戲動(dòng)畫基礎(chǔ)-基于時(shí)間的運(yùn)動(dòng)三 3D游戲角色動(dòng)畫 1 介紹微軟的X文件 2 骨

2、骼蒙皮動(dòng)畫的原理與實(shí)現(xiàn) 3 增加場(chǎng)景數(shù)據(jù) 4 簡(jiǎn)介漸變動(dòng)畫四 結(jié)束語(yǔ)正文:一 概述3D角色動(dòng)畫的應(yīng)用3D角色動(dòng)畫是計(jì)算機(jī)動(dòng)畫技術(shù)的一個(gè)重要組成部分,也是計(jì)算機(jī)圖形學(xué)的一個(gè)分支。無(wú)論是在離線渲染環(huán)境下,還是在實(shí)時(shí)渲染環(huán)境下,3D角色動(dòng)畫都得到了廣泛的應(yīng)用。在離線渲染環(huán)境下,主要應(yīng)用于動(dòng)畫電影制作和各類廣告制作。動(dòng)畫電影制作中所使用的3D角色動(dòng)畫技術(shù)的一個(gè)重要特點(diǎn)是動(dòng)畫數(shù)據(jù)量大,渲染需要耗費(fèi)大量時(shí)間,因此動(dòng)畫作品必須預(yù)先制作,渲染,然后轉(zhuǎn)化成視頻文件播放。在實(shí)時(shí)渲染環(huán)境下,主要應(yīng)用于虛擬現(xiàn)實(shí),視頻游戲,甚至是建模軟件,動(dòng)畫制作軟件。現(xiàn)在,隨著計(jì)算機(jī)硬件技術(shù)的發(fā)展,特別是帶有硬件加速功能的顯卡性能的

3、提高,很多曾經(jīng)只能在離線環(huán)境下應(yīng)用的技術(shù),都轉(zhuǎn)移到實(shí)時(shí)渲染環(huán)境中來(lái)。其中,實(shí)時(shí)渲染的角色動(dòng)畫技術(shù)得到了發(fā)展且被廣泛的應(yīng)用。目前,實(shí)時(shí)角色動(dòng)畫技術(shù)大體可分為三種類型。第一類是關(guān)節(jié)動(dòng)畫(Skeletal Animation)。關(guān)節(jié)動(dòng)畫中的角色由若干獨(dú)立的部分組成。每一個(gè)部分對(duì)應(yīng)著一個(gè)獨(dú)立的網(wǎng)格模型,不同的部分按照角色的特點(diǎn)組織成一個(gè)層次結(jié)構(gòu)。比如說(shuō),一個(gè)人體模型可以由頭,上身,左上臂,左前臂,左手,右上臂,右前臂,右手,左大腿,左小腿,左腳,右大腿,右小腿,右腳等各部分組成。而某個(gè)部分,可能是另一個(gè)部分的子節(jié)點(diǎn),同時(shí)又是另一個(gè)部分的父節(jié)點(diǎn)。比如上面的人體模型中,右前臂就是右上臂的子節(jié)點(diǎn),同時(shí)也是右

4、手的父節(jié)點(diǎn)。而右上臂是上身的子節(jié)點(diǎn),后者則是軀體的子節(jié)點(diǎn)。通過(guò)改變不同部分之間的相對(duì)位置,比如夾角,位移等等,就可以實(shí)現(xiàn)所需要的各種動(dòng)畫效果。這類動(dòng)畫的優(yōu)點(diǎn)很多。首先,在動(dòng)畫序列的關(guān)鍵幀中只需要存儲(chǔ)節(jié)點(diǎn)間的相對(duì)變化,因此動(dòng)畫文件占用的空間很小。其次,可以實(shí)現(xiàn)很多復(fù)雜的動(dòng)畫效果,如果應(yīng)用程序支持反向動(dòng)力學(xué)還可以動(dòng)態(tài)實(shí)現(xiàn)預(yù)先存儲(chǔ)的動(dòng)畫序列之外的新的動(dòng)畫效果。當(dāng)然這類動(dòng)畫也有不少缺點(diǎn)。其中之一是由于角色模型是一個(gè)層次模型,要獲得某一個(gè)部分相對(duì)于世界坐標(biāo)的位置,必須從根結(jié)點(diǎn)開始遍歷該節(jié)點(diǎn)所有的祖先節(jié)點(diǎn)累計(jì)計(jì)算模型的世界變換。但最關(guān)鍵的問(wèn)題是在不同部分的結(jié)合處往往會(huì)有很明顯的接縫,這會(huì)嚴(yán)重的影響模型的真

5、實(shí)感。第二類是漸變動(dòng)畫(Morphing Animation)。這種動(dòng)畫中的角色由一系列的漸變網(wǎng)格模型構(gòu)成。在動(dòng)畫序列的關(guān)鍵幀中記錄著組成網(wǎng)格的各個(gè)頂點(diǎn)的新位置或者是相對(duì)于原位置的改變量。通過(guò)在相鄰關(guān)鍵幀之間插值來(lái)直接改變?cè)摼W(wǎng)格模型中各個(gè)頂點(diǎn)的位置就可以實(shí)現(xiàn)動(dòng)畫效果。相對(duì)于關(guān)節(jié)動(dòng)畫,單一網(wǎng)格模型動(dòng)畫的角色看上去更真實(shí),也不會(huì)有關(guān)節(jié)動(dòng)畫所面臨的接縫問(wèn)題。由于沒(méi)有使用層次模型,獲得模型網(wǎng)格頂點(diǎn)在世界坐標(biāo)中位置的計(jì)算量也很小。但是,這類動(dòng)畫的適應(yīng)性很弱,角色很難通過(guò)實(shí)時(shí)計(jì)算來(lái)與環(huán)境進(jìn)行良好的互動(dòng),以獲得預(yù)先存儲(chǔ)的動(dòng)畫序列之外的動(dòng)畫效果。另一方面,由于關(guān)鍵幀要存儲(chǔ)網(wǎng)格模型所有的頂點(diǎn)信息,動(dòng)畫文件占用的

6、空間比較大。第三類是骨骼蒙皮動(dòng)畫(Skinned Mesh)。骨骼蒙皮動(dòng)畫可以看作是關(guān)節(jié)動(dòng)畫和漸變動(dòng)畫的結(jié)合。他同時(shí)兼有關(guān)節(jié)動(dòng)畫的靈活和漸變動(dòng)畫的逼真。后面將詳細(xì)介紹骨骼蒙皮動(dòng)畫的技術(shù)細(xì)節(jié)。3D角色動(dòng)畫技術(shù)和其它動(dòng)畫技術(shù)相結(jié)合,就能創(chuàng)造出絢麗多彩的游戲世界。二 3D游戲動(dòng)畫基礎(chǔ)-基于時(shí)間的運(yùn)動(dòng)在一個(gè)游戲項(xiàng)目中,計(jì)時(shí)扮演了一個(gè)重要的角色。基于時(shí)間的運(yùn)動(dòng),也就是創(chuàng)建計(jì)時(shí)器來(lái)控制運(yùn)動(dòng)。它能夠產(chǎn)生這樣一種動(dòng)畫效果:同樣處理10000毫秒的動(dòng)畫,在性能好的計(jì)算機(jī)上得到平滑完整的動(dòng)畫效果,在性能不好的計(jì)算機(jī)上顯得跳幀,但也能夠在10000毫秒的時(shí)候完成任務(wù),和性能好的計(jì)算機(jī)是同步的?;舅悸肥鞘孪仍O(shè)置好動(dòng)

7、畫關(guān)鍵幀序列,在主循環(huán)中判斷出第一個(gè)動(dòng)畫關(guān)鍵幀和下一個(gè)動(dòng)畫關(guān)鍵幀的編號(hào),利用一個(gè)時(shí)間計(jì)數(shù)器去定位相對(duì)于第一動(dòng)畫關(guān)鍵幀的位置。隨著時(shí)間計(jì)數(shù)器的增長(zhǎng),不斷從第一個(gè)動(dòng)畫關(guān)鍵幀的位置移動(dòng)至下一個(gè)動(dòng)畫關(guān)鍵幀的位置。主要分為以下幾個(gè)步驟:1設(shè)置動(dòng)畫關(guān)鍵幀序列。2計(jì)算出每一幀的時(shí)間Time,Time是相對(duì)于程序開始運(yùn)行的毫秒數(shù)。3定位出第一個(gè)動(dòng)畫關(guān)鍵幀和下一個(gè)動(dòng)畫關(guān)鍵幀。4利用Time計(jì)算出相對(duì)于第一個(gè)動(dòng)畫關(guān)鍵幀的毫秒數(shù),再利用這個(gè)偏移毫秒數(shù)計(jì)算出相對(duì)于第一個(gè)動(dòng)畫幀的偏移位置。5設(shè)置變換矩陣。6回到第2步。 上圖表示了4幀的關(guān)鍵幀動(dòng)畫,其中第0幀和第3幀變換矩陣相同。下面直接看代碼,我將結(jié)合代碼詳細(xì)敘述。t

8、ypedef struct sKeyframe DWORD Time; D3DMATRIX matTransformation; sKeyframe;/關(guān)鍵幀的結(jié)構(gòu),DWORD Time為執(zhí)行該幀的時(shí)間,D3DMATRIX /matTransformation為在該幀時(shí)模型的變換矩陣。sKeyframe g_Keyframes4 = / Keyframe 0, 0ms 0, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1

9、.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f , / Keyframe 1, 40ms 400, 0.000796f, 1.000000f, 0.000000f, 0.000000f, -1.000000f, 0.000796f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.000000f, 50.000000f, 0.000000f, 0.000000f, 1.000000f , / Keyframe 2, 80ms 800, -0.9999

10、99f, 0.001593f, 0.000000f, 0.000000f, -0.001593f, -0.999999f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.000000f, 25.000000f, 25.000000f, 0.000000f, 1.000000f , / Keyframe 3, 120ms 1200, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f,

11、0.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f ;/定義了4幀的關(guān)鍵動(dòng)畫。其中第3幀和第0幀的變換矩陣一樣,為了使動(dòng)畫能進(jìn)入循環(huán)狀態(tài)。void DoFrame() /此函數(shù)在循環(huán)內(nèi) static DWORD StartTime = timeGetTime(); DWORD Time = timeGetTime() - StartTime;/用timeGetTime()得到一個(gè)操作系統(tǒng)運(yùn)行的毫秒數(shù),儲(chǔ)存到static變量以后將不再改變,/DWORD Time變量不斷改變,為本程序運(yùn)行的毫秒數(shù)。

12、Time %= (g_Keyframes3.Time+1);/得到一個(gè)不斷從0到1200變化的毫秒數(shù)。 DWORD Keyframe = 0; / 從第0幀開始。 for(DWORD i=0;i<4;i+) / 如果Time>= 某一關(guān)鍵幀的時(shí)間,將關(guān)鍵幀定位于此幀。 if(Time >= g_Keyframesi.Time) Keyframe = i; DWORD Keyframe2 = (Keyframe=3) ? Keyframe:Keyframe + 1;/得到接下來(lái)的關(guān)鍵幀,如/果Keyframe為第3關(guān)鍵動(dòng)畫幀,Keyframe2也為第3關(guān)鍵動(dòng)畫幀。/當(dāng)Keyfr

13、ame=1200時(shí)這種情況才成立,幾率很小。一般情況下,Keyframe2=Keyframe+1。 DWORD TimeDiff = g_KeyframesKeyframe2.Time - g_KeyframesKeyframe.Time; if(!TimeDiff) TimeDiff=1;/計(jì)算兩個(gè)sKeyframe的時(shí)間差,當(dāng)Keyframe=Keyframe2=3時(shí),TimeDiff=0,/此時(shí)另TimeDiff=1。 float Scalar = (float)(Time - g_KeyframesKeyframe.Time) / (float)TimeDiff; / Scalar取

14、/值為0,1),利用Time計(jì)算出相對(duì)于Keyframe的偏移毫秒數(shù),再除以兩/幀的時(shí)間差。 D3DXMATRIX matInt = D3DXMATRIX(g_KeyframesKeyframe2.matTransformation) - D3DXMATRIX(g_KeyframesKeyframe.matTransformation); matInt *= Scalar; /用于計(jì)算相對(duì)于Keyfrme的偏移位置。 matInt += D3DXMATRIX(g_KeyframesKeyframe.matTransformation); / 計(jì)算出該幀處相/對(duì)于Keyfrme的偏移位置。 g_

15、pD3DDevice->SetTransform(D3DTS_WORLD, &matInt); / 設(shè)置 world transformation matrix 設(shè)置完變換矩陣,剩下的事情就只是渲染了。創(chuàng)建計(jì)時(shí)器控制動(dòng)畫的技術(shù)是非常簡(jiǎn)單有效的,這是現(xiàn)代計(jì)算機(jī)游戲動(dòng)畫的基礎(chǔ),因此,必須深刻理解它的內(nèi)容。三 3D游戲角色動(dòng)畫1 介紹微軟的X文件 制作3D游戲角色動(dòng)畫需要與之相關(guān)的“動(dòng)畫容器”。這個(gè)“容器”中儲(chǔ)存著動(dòng)畫的數(shù)據(jù)。微軟的X文件正是這樣的一種容器。由于微軟的影響力,它們公司設(shè)計(jì)的X文件也廣為流傳。X文件是一套基于模版定義的文件,理論上它能夠容納任何數(shù)據(jù)。也就意味著不僅僅是3D

16、模型文件,任何用于游戲引擎加載的外部資源都可以被包含于X文件之中。下面我們?cè)敿?xì)的介紹下X文件。為了得到一個(gè)直觀的印象,我們首先瀏覽下它的全貌。xof 0302txt 0032template Header <3D82AB43-62DA-11cf-AB39-0020AF71E433>DWORD major;DWORD minor;DWORD flags;template Frame <3D82AB46-62DA-11cf-AB39-0020AF71E433>FrameTransformMatrixMeshHeader 1;0;1;Frame Scene_Root Fram

17、eTransformMatrix 1.000000, 0.000000, 0.000000, 0.000000,0.000000, 1.000000, 0.000000, 0.000000,0.000000, 0.000000, 1.000000, 0.000000,0.000000, 0.000000, 0.000000, 1.000000; Frame Pyramid_Frame FrameTransformMatrix 1.000000, 0.000000, 0.000000, 0.000000,0.000000, 1.000000, 0.000000, 0.000000,0.00000

18、0, 0.000000, 1.000000, 0.000000,0.000000, 0.000000, 0.000000, 1.000000;Mesh PyramidMesh 5;0.00000;10.00000;0.00000;,-10.00000;0.00000;10.00000;,10.00000;0.00000;10.00000;,-10.00000;0.00000;-10.00000;,10.00000;0.00000;-10.00000;6;3;0,1,2;,3;0,2,3;,3;0,3,4;,3;0,4,1;,3;2,1,4;,3;2,4,3;MeshMaterialList 1

19、;6;0,0,0,0,0,0;Material Material0 1.000000; 1.000000; 1.000000; 1.000000;0.000000; 0.050000; 0.050000; 0.050000;0.000000; 0.000000; 0.000000; 首先看頭文件xof 0302txt 0032。xof表示這是一個(gè)真正的X文件。0302txt表示通知程序使用Directx的X文件,版本為3.2的模版,其中txt表示此文件為文本文件,可讀,并非是一個(gè)2進(jìn)制文件。0032表示一個(gè)浮點(diǎn)數(shù)的位數(shù)為32,如果想要用64位的浮點(diǎn)數(shù),可以寫成0064。下面我們將按照以下七個(gè)步

20、驟進(jìn)行介紹和說(shuō)明。第一,聲明一個(gè)模版:假設(shè)聲明 template ContactEntry ,首先需要用guidgen.exe產(chǎn)生一個(gè)GUID。產(chǎn)生的GUID如下:/ 4C9D055B-C64D-4bfe-A7D9-981F507E45FFDEFINE_GUID(<<name>>,0x4c9d055b, 0xc64d, 0x4bfe, 0xa7, 0xd9, 0x98, 0x1f, 0x50, 0x7e, 0x45, 0xff);之后需要在程序代碼中加入:#include "initguid.h"/ At beginning of source co

21、de file - add DEFINE_GUIDsDEFINE_GUID(ContactEntry, 0x4c9d055b, 0xc64d, 0x4bfe, 0xa7, 0xd9, 0x98, 0x1f, 0x50, 0x7e, 0x45, 0xff);還要在X文件中加入:template ContactEntry <4C9D055B-C64D-4bfe-A7D9-981F507E45FF>這里介紹下聲明模版用到的數(shù)據(jù)類型:關(guān)鍵字 描述WORD 16-bit value (short)DWORD 32-bit value (32-bit int or long)FLOAT IEE

22、E float value (float)DOUBLE 64-bit floating-point value (double)CHAR 8-bit signed value (signed char)UCHAR 8-bit unsigned value (unsigned char)BYTE 8-bit unsigned value (unsigned char)STRING A NULL-terminated string (char)array Signifies an array of following data type to follow ()使用數(shù)據(jù)類型的舉例:DWORD Va

23、lue; array STRING Text20;/定義一個(gè)名為Text的數(shù)組,類型為STRING,大小為20。DWORD ArraySize; array STRING NamesArraySize; /可以將大小設(shè)置為變量?,F(xiàn)在,我們聲明一個(gè)ContactEntry模版:template ContactEntry <4C9D055B-C64D-4bfe-A7D9-981F507E45FF>STRING Name; / The contact's nameSTRING PhoneNumber; / The contact's phone numberDWORD A

24、ge; / The contact's age實(shí)例化一個(gè)模版對(duì)象:ContactEntry JimsEntry "Jim Adams""(800) 555-1212"30;JimsEntry 可以用這樣的形式引用一個(gè)數(shù)據(jù)對(duì)象。例如,在一個(gè)animation sequence template中引用一個(gè)Frame data object做為其內(nèi)嵌數(shù)據(jù)對(duì)象。也可以利用引用表示一個(gè)數(shù)據(jù)對(duì)象的副本,沒(méi)有必要重復(fù)書寫這個(gè)數(shù)據(jù)對(duì)象。第二,內(nèi)嵌數(shù)據(jù)對(duì)象和模版約束:首先,我們分別聲明了三個(gè)不同的模版,請(qǐng)仔細(xì)看它們的區(qū)別。template ClosedTempla

25、te <4C9D055B-C64D-4bfe-A7D9-981F507E45FF>DWORD ClosedData;template OpenTemplate <4C9D055B-C64D-4bff-A7D9-981F507E45FF>DWORD OpenData;.template RestrictedTemplate <4C9D055B-C64D-4c00-A7D9-981F507E45FF>DWORD RestrictedData;ClosedTemplateOpenTemplateClosedTemplate看起來(lái)沒(méi)有什么不同,因?yàn)樗褪菢?biāo)準(zhǔn)的模版聲

26、明。在OpenTemplate中包含一個(gè).,表示這是一個(gè)開放模版。開放模版允許在中內(nèi)嵌任何數(shù)據(jù)對(duì)象。例如,你可以實(shí)例化OpenTemplate,在里面定義一個(gè)OpenData變量和內(nèi)嵌一個(gè)ClosedTemplate的實(shí)例。最后的RestrictedTemplate為約束模版。約束模版實(shí)例化時(shí)只允許包含它列出的數(shù)據(jù)對(duì)象,如,不能在RestrictedTemplate包含ClosedTemplate,OpenTemplate以外的數(shù)據(jù)對(duì)象。第三,充分利用DirectX .X Standard Templates:正如上面提到的,X文件廣泛用于包含一個(gè)mesh信息。一個(gè)Standard Templ

27、ates包含了各種信息。Table 3: DirectX .X Standard TemplatesTemplate Name DescriptionAnimation: Defines animation data for a single frame.AnimationKey: Defines a single key frame for the parent animation template.AnimationOptions: Contains animation playback information.AnimationSet: Contains a collection of

28、animation templates.Boolean: Holds a Boolean value.Boolean2d: Holds two Boolean values.ColorRGB: Contains red, green, and blue color values.ColorRGBA: Contains red, green, blue, and alpha color values.Coords2d: Defines two coordinate values.FloatKeys: Contains an array of floating-point values.Frame

29、TransformMatrix: Holds the transformation matrix for a parent Frame template.Frame: A frame-of-reference template that defines a hierarchy.Header: The .X file header that contains version numbers.IndexedColor: Contains an indexed color value.Material: Contains material color values.Matrix4x4: Holds

30、a 4x4 homogenous matrix container.Mesh: Contains a single mesh's data.MeshFace: Holds a mesh's face data.MeshFaceWraps: Contains the texture wrapping for mesh faces.MeshMaterialList: Contains the material for face-mapping values.MeshNormals: Holds normals used for mesh data.MeshTextureCoords

31、: Holds texture coordinates used for mesh data.MeshVertexColors: Holds vertex color information used for mesh vertices.Patch: Defines a control patch.PatchMesh: Contains a patch mesh (much like the Mesh template).Quaternion: Holds a quaternion value.SkinWeights: Contains an array of weight values ma

32、pped to a mesh's vertices. Used in skinned meshes.TextureFilename: Contains the texture file name to use for a material.TimedFloatKeys: Contains an array of FloatKeys templates.Vector: Holds a 3D coordinate value.VertexDuplicationIndices: Informs you which vertices are duplicates of other vertic

33、es.XSkinMeshHeader: Used by skinned meshes to define the number of bones contained in a mesh.我們可以在DirectX9SDK的安裝目錄下搜索到“rmxfguid.h”字樣的頭文件。在rmxfguid.h中定義了各個(gè)模版的宏,例如:/* 3D82AB44-62DA-11cf-AB39-0020AF71E433 */DEFINE_GUID(TID_D3DRMMesh,0x3d82ab44, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0

34、x33);每個(gè)模版名加上前綴TID_D3DRM就是宏定義名。既然微軟已經(jīng)幫助我們定義了那么多的模版,我們可以根據(jù)需求,充分的去利用這些模版。另外,這些模版往往會(huì)有相關(guān)的幫助函數(shù),我們使用它們可以事半功倍。第四,創(chuàng)建X文件接口: 我們已經(jīng)對(duì)X文件的模版概念有所了解,現(xiàn)在將使用它們。當(dāng)然,要想使用首先得訪問(wèn)X文件。訪問(wèn)任何X文件首先要調(diào)用DirectXFileCreate函數(shù)創(chuàng)建一個(gè)IDirectXFile接口,這個(gè)接口就代表了一個(gè)X文件。IDirectXFile *pDXFile = NULL;HRESULT Result = DirectXFileCreate(&pDXFile);/用

35、&pDXFile返回指向接口的指針。用SUCCEEDED或者FAILED宏判斷返回值是否有效。創(chuàng)建完IDirectXFile接口,我們要注冊(cè)一個(gè)定制模版或者標(biāo)準(zhǔn)模版。定制模版是自己定義的模版,標(biāo)準(zhǔn)模版是微軟幫我們定義的模版,其實(shí)它們之間沒(méi)有本質(zhì)的區(qū)別,你現(xiàn)在要做的就是告訴IDirectXFile接口,使用二者之中的哪種。如何注冊(cè)定制模版呢?下面舉個(gè)例子更容易理解。你可以把X文件中的模版移除,直接在代碼里定義那些模版。IDirectXFile接口支持這樣的特性。需要調(diào)用IDirectXFile:RegisterTemplates函數(shù)。HRESULT IDirectXFile:Regist

36、erTemplates(LPVOID pvData, / 一個(gè)定義模版數(shù)據(jù)的緩存,應(yīng)該精確無(wú)誤。DWORD cbSize); / pvData緩存的字節(jié)數(shù)??梢匀缦露x一個(gè)模版數(shù)據(jù):char *Templates = ""xof 0303txt 0032 /標(biāo)準(zhǔn)X文件頭。template CustomTemplate <4c944580-9e9a-11cf-ab43-0120af71e433> DWORD Length; array DWORD ValuesLength; "之后在用RegisterTemplates將其注冊(cè):pFile->Reg

37、isterTemplates(Templates, strlen(Templates);如何注冊(cè)標(biāo)準(zhǔn)模版呢?首先需要在代碼中包含rmxfguid.h和rmxftmpl.h。rmxfguid.h定義了各個(gè)標(biāo)準(zhǔn)模版的GUDI,rmxftmpl.h以2進(jìn)制數(shù)據(jù)形式定義了標(biāo)準(zhǔn)模版數(shù)據(jù)的緩存和其字節(jié)數(shù)。然后調(diào)用RegisterTemplates將其注冊(cè):pFile->RegisterTemplates(D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES);第五,打開X文件:創(chuàng)建完IDirectXFile接口,注冊(cè)模版之后需要打開X文件,枚舉其數(shù)據(jù)對(duì)象。調(diào)用IDirect

38、XFile:CreateEnumObject函數(shù)。HRESULT IDirectXfile:CreateEnumObject(LPVOID pvSource, / .X filenameDXFILELOADOPTIONS dwLoadOptions, / Load optionsLPDIRECTXFILEENUMOBJECT* ppEnumObj); / Enum interface當(dāng)調(diào)用CreateEnumObject函數(shù),用pvSource指定一個(gè)文件的名字,用ppEnumObj返回一個(gè)枚舉對(duì)象接口指針。用dwLoadOptions指定load操作方式。當(dāng)指定DXFILELOAD_FROM

39、FILE值,告訴DirectX從磁盤載入一個(gè)文件。還有DXFILELOAD_FROMRESOURCE,DXFILELOAD_FROMMEMORY和DXFILELOAD_FROMURL分別表示從一個(gè)資源,內(nèi)存緩沖和Internet上加載X文件。當(dāng)從Internet加載文件時(shí),需要為其指定完整的網(wǎng)址。下面代碼從磁盤加載X文件:/ Filename = filename to load ("test.x" for example)IDirectXFileEnumObject *pEnum;pFile->CreateEnumObject(LPVOID)Filename, DX

40、FILELOAD_FROMFILE, &pEnum);Filename指向一個(gè)有效的文件名,pEnum返回一個(gè)枚舉對(duì)象接口指針。第六,枚舉數(shù)據(jù)對(duì)象:注冊(cè)完模版,打開X文件并且得到一個(gè)枚舉對(duì)象接口,下面需要從X文件讀出數(shù)據(jù)。枚舉對(duì)象接口指針指向文件的第一個(gè)數(shù)據(jù)對(duì)象,因?yàn)槊恳粋€(gè)數(shù)據(jù)對(duì)象可能包含內(nèi)嵌數(shù)據(jù)對(duì)象或者引用的數(shù)據(jù)對(duì)象,所以與第一個(gè)數(shù)據(jù)對(duì)象同在一層級(jí)的其它數(shù)據(jù)對(duì)象為同層級(jí)數(shù)據(jù)對(duì)象。至于包含的子數(shù)據(jù)對(duì)象的類型,需要對(duì)其分別的行進(jìn)詢問(wèn)。可以使用HRESULT IDirectXFileEnumObject:GetNextDataObject (LPDIRECTXFILEDATA* ppDat

41、aObj)得到一個(gè)IDirectXFileData接口。它只有一個(gè)參數(shù):IDirectXFileData *pData;HRESULT hr = pEnum->GetNextDataObject(&pData);利用此函數(shù),可以不斷地訪問(wèn)同一層級(jí)的數(shù)據(jù)對(duì)象接口,具體代碼如下:while(SUCCEEDED(pEnum->GetNextDataObject(&pData) / 這里可以對(duì)pData數(shù)據(jù)對(duì)象進(jìn)行操作。pData->Release();/釋放接口。當(dāng)返回值為FAILED,表示已經(jīng)訪問(wèn)完所有的接口。當(dāng)訪問(wèn)值為SUCCEEDED,你需要繼續(xù)判斷這個(gè)數(shù)據(jù)對(duì)

42、象是否包含子對(duì)象。利用接口IDirectXFileObject,和HRESULT IDirectXFileData:GetNextObject( LPDIRECTXFILEOBJECT* ppChildObj)函數(shù),代碼如下:IDirectXFileObject *pObject;while(SUCCEEDED(pData->GetNextObject(&pObject) / 如果一個(gè)子對(duì)象存在,需要繼續(xù)詢問(wèn)它,判斷出它的類型為內(nèi)嵌數(shù)據(jù)對(duì)象或者引用的數(shù)/ 據(jù)對(duì)象。pObject->Release();/ 釋放接口。接下來(lái)詢問(wèn)接口,看其是否為內(nèi)嵌數(shù)據(jù)對(duì)象:IDirectXFi

43、leData *pSubData;if(SUCCEEDED(pObject->QueryInterface( IID_IDirectXFileData, (void*)&pSubData) / 如果詢問(wèn)內(nèi)嵌數(shù)據(jù)對(duì)象成功,可以對(duì)pSubData數(shù)據(jù)對(duì)象進(jìn)行操作pSubData->Release();/釋放接口??雌涫欠駷橐脭?shù)據(jù)對(duì)象:IDirectXFileDataReference *pRef;IDirectXFileData *pSubData;if(SUCCEEDED(pSubObj->QueryInterface( IID_IDirectXFileDataRef

44、erence, (void*)&pRef) / 如果詢問(wèn)引用的數(shù)據(jù)對(duì)象成功,解析出引用的原型。pRef->Resolve(&pSubData);/這里可以對(duì)pData數(shù)據(jù)對(duì)象進(jìn)行操作。pRef->Release();pSubData->Release();/釋放接口。現(xiàn)在整理下思路:大體的思路其實(shí)很簡(jiǎn)單,首先枚舉最頂層的數(shù)據(jù)對(duì)象,然后判斷其是否有子對(duì)象,這個(gè)子對(duì)象可能是內(nèi)嵌對(duì)象或者引用對(duì)象二者之一,分別詢問(wèn)其接口,就可以判斷出具體的類型。下面是完整的Parse模版的函數(shù):BOOL Parse(char *Filename)IDirectXFile *pFile

45、 = NULL;IDirectXFileEnumObject *pEnum = NULL;IDirectXFileData *pData = NULL;if(FAILED(DirectXFileCreate(&pFile)return FALSE;/注冊(cè)標(biāo)準(zhǔn)模版。if(FAILED(pFile->RegisterTemplates( (LPVOID)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES)return FALSE;/創(chuàng)建一個(gè)枚舉對(duì)象接口。if(FAILED(pDXFile->CreateEnumObject(LPVOID)Filena

46、me, DXFILELOAD_FROMFILE, &pEnum) pFile->Release();return FALSE;/ 遍歷所有的頂層數(shù)據(jù)對(duì)象。while(SUCCEEDED(pEnum->GetNextDataObject(&pData) / 用ParseObject解析其子數(shù)據(jù)對(duì)象。ParseObject(pData);pData->Release();pEnum->Release();pFile->Release();return TRUE;這個(gè)函數(shù)的主要部分在ParseObject(pData),它負(fù)責(zé)解析子數(shù)據(jù)對(duì)象:void P

47、arseObject(IDirectXFileData *pData) IDirectXFileObject *pObject = NULL; IDirectXFileData *pSubData = NULL; IDirectXFileDataReference *pRef = NULL; while(SUCCEEDED(pData->GetNextObject(&pObject) if(SUCCEEDED(pObject->QueryInterface( IID_IDirectXFileDataReference, (void*)&pRef) pRef->

48、Resolve(&pSubData); ParseObject(pSubData); pSubData->Release(); pRef->Release(); if(SUCCEEDED(pObject->QueryInterface( IID_IDirectXFileData, (void*)&pSubData) ParseObject(pSubData); pSubData->Release(); pObject->Release(); 這是個(gè)遞歸函數(shù),調(diào)用函數(shù)自身。判斷子對(duì)象的類別,對(duì)其繼續(xù)解析,直到返回值為FAILED,表示已沒(méi)有子對(duì)象。從

49、上面可以看出,這個(gè)函數(shù)除了枚舉所有的對(duì)象,并沒(méi)有做任何事情,下面就要從這些數(shù)據(jù)對(duì)象檢索數(shù)據(jù)。第七,從數(shù)據(jù)對(duì)象檢索數(shù)據(jù):當(dāng)你用IDirectXFileData接口指針指向一個(gè)有效的數(shù)據(jù)對(duì)象,可以調(diào)用IDirectXFileData:GetName函數(shù)得到該數(shù)據(jù)對(duì)象的名字。函數(shù)原型為:HRESULT IDirectXFileData:GetName(LPSTR pstrNameBuf, / 名字緩沖LPDWORD pdwBufLen); / 名字緩沖的大小可以這樣使用這個(gè)函數(shù):DWORD Size;pData->GetName(NULL, &Size);char *Name = ne

50、w charSize;pData->GetName(Name, &Size);首先聲明一個(gè)DWORD Size變量,調(diào)用GetName函數(shù)時(shí)將第一個(gè)參數(shù)設(shè)為NULL,在Size返回名字緩沖的大小。之后利用這個(gè)Size值創(chuàng)建存放名字的緩沖,再調(diào)用GetName在Name中返回?cái)?shù)據(jù)對(duì)象的名字。得到了數(shù)據(jù)對(duì)象的名字,你需要得到這個(gè)數(shù)據(jù)對(duì)象的模版GUID,去判斷這個(gè)數(shù)據(jù)對(duì)象是否為你想使用的那個(gè)模版的數(shù)據(jù)對(duì)象。利用IDirectXFileData:GetType函數(shù),其原型為:HRESULT IDirectXFileData:GetType(const GUID * ppguid);可以這

51、樣使用這個(gè)函數(shù):const GUID *TemplateGUID = NULL;pData->GetType(&TemplateGUID);/在TemplateGUID中返回該數(shù)據(jù)對(duì)象對(duì)應(yīng)模版的GUID。現(xiàn)在去匹配這個(gè)GUID,看它是否為你想使用的模版的數(shù)據(jù)對(duì)象。if(*TemplateGUID = TID_D3DRMMeshNormals) / 如果匹配成功,這里可以繼續(xù)處理這個(gè)模版的數(shù)據(jù)對(duì)象。最后將介紹GetData函數(shù),用它真正的得到了數(shù)據(jù)對(duì)象的數(shù)據(jù)。其原型為:HRESULT IDirectXFileData:GetData(LPCSTR szMember, / 設(shè)置為NU

52、LLDWORD *pcbSize, / 數(shù)據(jù)的大小void *ppvData); / 數(shù)據(jù)指針下面介紹用GetData得到數(shù)據(jù)對(duì)象結(jié)構(gòu)的大小和數(shù)據(jù)對(duì)象的數(shù)據(jù)。假設(shè)有這樣一個(gè)顏色的模版:template ColorRGBA <35FF44E0-6C7C-11cf-8F52-0040333594A3>FLOAT red;FLOAT green;FLOAT blue;FLOAT alpha;你想訪問(wèn)基于此模版的數(shù)據(jù)對(duì)象的數(shù)據(jù)你可以這樣做: DWORD DataSize;float *DataPtr;pData->GetData(NULL, &DataSize, (void*

53、)&DataPtr);float red = *DataPtr+;float green = *DataPtr+;float blue = *DataPtr+;float alpha = *DataPtr+;得到指向數(shù)據(jù)對(duì)象的數(shù)據(jù)的指針后,就像訪問(wèn)一般的結(jié)構(gòu)一樣簡(jiǎn)單。當(dāng)然,你可以做得更直接:typedef struct float red, green, blue, alpha; sColorRGBA;/定一個(gè)結(jié)構(gòu)方便訪問(wèn)數(shù)據(jù)對(duì)象的數(shù)據(jù)。sColorRGBA *Color;DWORD DataSize;pData->GetData(NULL, &DataSize,(void*)&Color);這樣訪問(wèn)數(shù)據(jù)時(shí)更直接:float red = Color->red;float blue = Color->blue;float green = Color->green;float alpha = Color->alpha;訪問(wèn)單個(gè)變量是很簡(jiǎn)單的,下面繼續(xù)介紹訪問(wèn)數(shù)組或字符串。訪問(wèn)數(shù)組:DWOR

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論