摘 要: 人體骨骼蒙皮動畫技術(shù)是計(jì)算機(jī)動畫領(lǐng)域研究的熱點(diǎn)和難點(diǎn)。針對當(dāng)前骨骼蒙皮動畫中關(guān)節(jié)斷裂、皮膚塌陷、頂點(diǎn)計(jì)算量大、執(zhí)行效率低等問題,首先分析了其原理及實(shí)現(xiàn)過程,然后以Visual Studio 2012+XNA4.0為平臺,設(shè)計(jì)實(shí)現(xiàn)了一個骨骼蒙皮動畫的引擎框架,并采用優(yōu)化旋轉(zhuǎn)算法、動畫混合、GPU更新頂點(diǎn)等關(guān)鍵技術(shù),提高了動畫的執(zhí)行效率,增強(qiáng)了動畫的真實(shí)感。
關(guān)鍵詞: 骨骼蒙皮動畫; XNA; GPU; 動畫混合
中圖分類號:TP391.9 文獻(xiàn)標(biāo)志碼:A 文章編號:1006-8228(2013)03-13-04
0 引言
計(jì)算機(jī)動畫技術(shù)已被廣泛應(yīng)用到電影、游戲、軍事、航空等領(lǐng)域,它的研究對象包括現(xiàn)實(shí)生活或虛擬世界中的云霧雨、河流、各種植物、動物等等,但其中最有難度和最有挑戰(zhàn)性的對象之一就是人體動畫[1]。人體運(yùn)動非常復(fù)雜,人的形狀不規(guī)則,肌肉隨著人體的運(yùn)動而變形,頭發(fā)、皮膚和衣服模擬起來很困難。另外,由于人類對自身的運(yùn)動非常熟悉,不協(xié)調(diào)的運(yùn)動很容易被觀察者所察覺。人體的行為通常包括細(xì)微行為(如表情變化)、局部行為(如閉眼、手勢等)和全身行為(如走、跳、跑等)。本文在分析骨骼蒙皮動畫原理的基礎(chǔ)上,利用XNA4.0較好地實(shí)現(xiàn)了人體骨骼蒙皮動畫,并采用多種關(guān)鍵技術(shù)對動畫進(jìn)行優(yōu)化。
1 骨骼蒙皮動畫原理
目前實(shí)時人體動畫技術(shù)可分為三類:關(guān)鍵幀動畫、關(guān)節(jié)動畫和骨骼蒙皮動畫。
關(guān)鍵幀動畫需要首先存儲每一幀動畫的網(wǎng)格模型,實(shí)質(zhì)上是一種以空間換時間的動畫技術(shù)。它的優(yōu)點(diǎn)是計(jì)算量小,速度快,角色也更逼真。如果場景中有幾百個動畫模型共享相同的動畫,這種方法將很有用。但是它的局限性也很明顯,首先是占用空間較大,其次是靈活性差,很難與用戶進(jìn)行交互,所以關(guān)鍵幀動畫一般用于簡單的連續(xù)動作的模擬。XNA中使用關(guān)鍵幀動畫模型很簡單,因?yàn)閄NA有處理靜態(tài)模型的類。
關(guān)節(jié)動畫是基于面模型的建模方法中的一種,它將骨架層(Skeleton layer)(如圖1左)和皮膚層(Skin layer)(如圖1右)進(jìn)行剛性連接,動畫過程中,通過骨架運(yùn)動帶動相應(yīng)的皮膚頂點(diǎn)運(yùn)動[2]。在該方法中,皮膚相對于與之相連的骨骼并沒有發(fā)生運(yùn)動,所以只需要用矩陣描述各個骨骼的相對于父骨骼運(yùn)動,不考慮皮膚的彈性變形,實(shí)現(xiàn)簡單,計(jì)算速度比關(guān)鍵幀動畫慢。但由于是剛性連接,在兩段骨骼交接處,容易產(chǎn)生裂縫,影響效果。所以關(guān)節(jié)動畫適合對皮膚精度要求不高的場合,如模擬機(jī)器人行為。
骨骼蒙皮動畫可以看作是關(guān)鍵幀動畫和關(guān)節(jié)動畫的組合,是目前比較流行的動畫技術(shù)。它在關(guān)節(jié)動畫的基礎(chǔ)上,利用頂點(diǎn)混合(Vertex Blend)技術(shù),改變皮膚層頂點(diǎn)的數(shù)據(jù)結(jié)構(gòu),使其存儲影響這些頂點(diǎn)位置的骨骼信息及影響的權(quán)值,然后通過“蒙皮”算法得到頂點(diǎn)的最終位置。使用“蒙皮”算法相當(dāng)于在骨骼關(guān)節(jié)上動態(tài)蒙皮,有效解決了裂縫問題。但由于“蒙皮”算法中權(quán)值的指定是由人工完成,而且在較大關(guān)節(jié)部分(如肩膀)權(quán)值的指定很困難,容易出現(xiàn)如“塌陷(collapse)”、“裹糖紙( candy wrapper)”效應(yīng)等變形問題[2]。文獻(xiàn)[3]中,夏開建等提出了一種改進(jìn)的“蒙皮”算法,使用向皮膚可變區(qū)域中增加輔助節(jié)點(diǎn)的方法很好地改善了變形問題,本文將按此改進(jìn)的“蒙皮”算法進(jìn)行皮膚頂點(diǎn)位置的計(jì)算。
2 基于XNA的骨骼蒙皮動畫的設(shè)計(jì)
2.1 動畫模型的創(chuàng)建
骨骼蒙皮動畫的創(chuàng)建一般分為模型的創(chuàng)建和動畫的創(chuàng)建,逼真的動畫模型需要由具有豐富經(jīng)驗(yàn)的建模師和動畫師通過專業(yè)的3D軟件如3DMAX、Maya等實(shí)現(xiàn)。模型中還需要存儲相關(guān)數(shù)據(jù)信息:
2.1.1 模型數(shù)據(jù)
靜態(tài)的模型包括骨骼層以及包圍它的皮膚層。模型中需要存儲用于骨骼蒙皮動畫的相關(guān)信息,主要包括骨骼的層次結(jié)構(gòu)和皮膚的頂點(diǎn)信息。骨骼的層次結(jié)構(gòu)是指按照角色的身體特征構(gòu)成一個層次結(jié)構(gòu)。圖2給出了人體骨骼的層次結(jié)構(gòu),箭頭由父骨骼指向子骨骼,從子骨骼用矩陣乘法累積到最頂層的根骨骼,就可求得每個子骨骼相對于世界坐標(biāo)系的變換矩陣。皮膚的頂點(diǎn)信息包括頂點(diǎn)的索引、與頂點(diǎn)關(guān)聯(lián)的骨骼索引及權(quán)值、頂點(diǎn)的顏色、頂點(diǎn)的法向量等。
2.1.2 動畫數(shù)據(jù)
從程序員的角度來看,動畫數(shù)據(jù)就是動畫過程中的骨骼關(guān)鍵幀以及變換矩陣,由它們來決定模型的運(yùn)動。在XNA中,可以將動畫的變換矩陣存放在模型內(nèi)部,但是對于動畫比較復(fù)雜的模型,一般存儲在單獨(dú)的animation文件中,這樣便于對模型進(jìn)行驅(qū)動和人機(jī)交互,以及進(jìn)行動畫混合。
2.2 數(shù)據(jù)的載入
在使用XNA進(jìn)行游戲編程時,首先要將3D軟件創(chuàng)建的動畫模型文件(X格式或FBX格式)轉(zhuǎn)換成XNB格式,才能被XNA的內(nèi)容讀取器(Content Reader)讀取。在XNA中,程序員使用內(nèi)容管道(Content Pipeline)來加載硬盤上的資源[4](如3D模型、2D圖像、聲音等)。這個過程分為兩步:當(dāng)項(xiàng)目被編譯時,內(nèi)容管線從硬盤讀取資源,將它處理成二進(jìn)制文件存放在硬盤上;當(dāng)游戲運(yùn)行時,直接從二進(jìn)制文件中讀取數(shù)據(jù)。這樣做的好處在于:大量的計(jì)算在游戲運(yùn)行之前處理完畢,可提高游戲運(yùn)行速度;同時,先前存儲的二進(jìn)制數(shù)據(jù)可以被PC、Xbox 360、Zune和Windows Phone讀取,從而實(shí)現(xiàn)了跨平臺。
雖然XNA的內(nèi)容管道可以很方便地進(jìn)行資源的加載,但它并不完全支持骨骼蒙皮動畫,因?yàn)樗梢詫?dǎo)入帶有骨骼蒙皮動畫數(shù)據(jù)的X文件或FBX文件,但輸出時并不處理所有的骨骼蒙皮動畫數(shù)據(jù)。要在XNA中添加對骨骼蒙皮動畫的支持,程序員需要擴(kuò)展默認(rèn)的模型處理器(model processor),創(chuàng)建一個新的處理過程并存儲模型的骨骼和動畫數(shù)據(jù)。圖3顯示了擴(kuò)展內(nèi)容管道所需創(chuàng)建的類,添加了對骨骼蒙皮動畫模型的支持,新增加的類使用灰色字體和黑框標(biāo)識。除此以外,還需要創(chuàng)建新的類存儲、寫入和讀取這些數(shù)據(jù)。
2.3 骨骼蒙皮動畫的更新
在游戲的運(yùn)行過程中,角色需要時刻準(zhǔn)備與用戶進(jìn)行交互,完成相應(yīng)的動畫,這也是實(shí)時動畫技術(shù)的一個必備功能。從程序員的角度來說,就是根據(jù)用戶的輸入實(shí)時更新角色的狀態(tài)。
2.3.1 骨骼信息的更新
首先根據(jù)動畫的播放時間確定該動畫在該時刻的兩個插值關(guān)鍵幀,然后按照播放時間對這兩個關(guān)鍵幀進(jìn)行插值,從而確定每一塊骨骼該時刻在局部坐標(biāo)系下的變換矩陣(平移和旋轉(zhuǎn)信息),最后與父骨骼在世界坐標(biāo)系下的變換矩陣相乘便得到了每一塊骨骼的在世界坐標(biāo)系下的變換信息[5]。在插值過程中,平移過程可使用普通的線性插值完成,而旋轉(zhuǎn)過程則通過四元數(shù)的球面線性插值來實(shí)現(xiàn)。
2.3.2 皮膚頂點(diǎn)信息的更新
對于皮膚頂點(diǎn),根據(jù)每個頂點(diǎn)所關(guān)聯(lián)的骨骼以及對應(yīng)的權(quán)值,使用“蒙皮”算法計(jì)算皮膚頂點(diǎn)的位置。“蒙皮”算法本質(zhì)上是一種插值算法,它的基本思想是使關(guān)節(jié)處的皮膚頂點(diǎn)受到與之鄰近的幾段骨骼的影響,影響大小由權(quán)值確定。其公式如下:
其中,vd是初始狀態(tài)的皮膚頂點(diǎn)在世界坐標(biāo)系中的坐標(biāo);Di表示在初始狀態(tài)下第i段骨骼由局部坐標(biāo)系到世界坐標(biāo)系的變換矩陣;表示皮膚頂點(diǎn)在第i段骨骼局部坐標(biāo)系中的坐標(biāo)值;Mi表示第i段骨骼在當(dāng)前位置由局部坐標(biāo)系到世界坐標(biāo)系的變換矩陣。ωi表示第i段骨骼對于當(dāng)前頂點(diǎn)的權(quán)值,v表示變形后的皮膚頂點(diǎn)在世界坐標(biāo)系中的坐標(biāo)。
2.4 骨骼蒙皮動畫的優(yōu)化
2.4.1 旋轉(zhuǎn)算法的優(yōu)化
旋轉(zhuǎn)是骨骼蒙皮動畫最基本的操作,因此旋轉(zhuǎn)算法的優(yōu)劣與動畫的最終效果密切相關(guān)。傳統(tǒng)的XNA編程通常使用歐拉角表示旋轉(zhuǎn),需要三個浮點(diǎn)數(shù)分別表示繞三個坐標(biāo)軸的旋轉(zhuǎn)。本文使用四元數(shù)表示旋轉(zhuǎn),四元數(shù)需要4個浮點(diǎn)數(shù),雖然比歐拉角多使用一個浮點(diǎn)數(shù)導(dǎo)致耗費(fèi)的內(nèi)存增加,但四元數(shù)可以避免使用歐拉角帶來的抖動和萬向節(jié)鎖的缺陷。不僅如此,四元數(shù)還可以根據(jù)動畫的逝去時間(elapseTime)和動畫長度(animLength)對前后兩個關(guān)鍵幀進(jìn)行球面線性插值,從而求得該時刻的變換矩陣。球面線性插值公式如下:
其中p,q是源和目標(biāo)四元數(shù);t是取值為0和1之間的插值參數(shù);θ是兩個四元數(shù)之間的實(shí)際角度。
2.4.2 動畫混合
動畫混合就是利用兩個或多個已有動畫序列進(jìn)行混合從而生成一個新動畫,如把走路和揮手相結(jié)合,就形成了走路揮手的動畫。這種技術(shù)在生成新動畫的同時,還節(jié)省了動畫載入的時間以及動畫存儲的內(nèi)存開銷,而且減輕了動畫師制作動畫的工作量。
本文在動畫設(shè)計(jì)過程中已將動畫分為兩部分:上半身動畫和下半身動畫,在角色實(shí)際運(yùn)動過程中可根據(jù)與用戶或與環(huán)境的交互來進(jìn)行不同動畫效果的組合。上半身動畫主要是手部動畫,包括:走、跑、蹲、揮手、拔槍、射擊、死亡等;下半身動畫主要是腿部動畫,包括:走、跑、蹲、死亡等。最基本的動畫混合就是將上、下半身動畫進(jìn)行組合生成多種新的動畫,這一類混合動畫的驅(qū)動方式與骨骼蒙皮動畫驅(qū)動方式相似,不過,要在更新時同時計(jì)算出上、下半身骨骼的變換矩陣。另一類動畫混合是兩種動作的過渡,如人在跑動過程中拔槍射擊或是跑動過程中中彈死亡,這些都需要在各個動畫之間進(jìn)行無縫銜接。在實(shí)現(xiàn)中,需要在動畫變化的瞬間凍結(jié)前一個動畫,并獲得當(dāng)前關(guān)鍵幀,然后與下一個動畫的第一個關(guān)鍵幀進(jìn)行差值,從而實(shí)現(xiàn)平滑過渡[7]。
2.4.3 GPU編程更新頂點(diǎn)
在可編程圖形處理器出現(xiàn)之前,骨骼蒙皮動畫中大量的計(jì)算都是由CPU來完成的。但隨著圖形硬件性能的提高,尤其是GPU中使用頂點(diǎn)渲染器和像素渲染器,以及現(xiàn)在的流處理器,使得GPU的綜合運(yùn)算能力得到了很大的提高,而其特有的向量運(yùn)算和矩陣運(yùn)算能力更是超越了CPU[6]。因此,可以充分發(fā)揮GPU的運(yùn)算特點(diǎn),分擔(dān)CPU在運(yùn)算上的壓力。
GPU主要是針對圖形渲染的特點(diǎn)設(shè)計(jì)的,在GPU內(nèi)部存在頂點(diǎn)渲染、光柵化、像素渲染這樣的流水線,但在頂點(diǎn)之間、像素之間是沒有任何關(guān)聯(lián)性和依賴性的。因此GPU適合做大規(guī)模的并行運(yùn)算,而不適合用來做邏輯性和復(fù)雜性很高的算法運(yùn)算,其運(yùn)算結(jié)果也不會被保存下來供下次運(yùn)算使用。因此,要將骨骼蒙皮動畫的某些運(yùn)算交給 GPU來執(zhí)行,這些運(yùn)算必須保持算法簡單,且適用于大量數(shù)據(jù)。通過分析2.3節(jié)中骨骼蒙皮動畫所涉及到的運(yùn)算可以發(fā)現(xiàn):骨骼信息的更新涉及插值運(yùn)算、遞歸運(yùn)算、矩陣運(yùn)算,其運(yùn)算結(jié)果還需保留以便進(jìn)行頂點(diǎn)信息的更新,所以骨骼信息的更新不能使用GPU進(jìn)行計(jì)算;而頂點(diǎn)信息的更新針對的是每個頂點(diǎn),頂點(diǎn)與頂點(diǎn)之間不存在依賴關(guān)系,僅僅利用與其關(guān)聯(lián)的骨骼和骨骼影響權(quán)值,使用骨骼的全局變換矩陣進(jìn)行頂點(diǎn)數(shù)據(jù)的更新,更新結(jié)果無需保留而是直接顯示在屏幕上。可見,該過程非常適合于在GPU中進(jìn)行處理[8]。這樣,就可以使用CPU更新骨骼信息,GPU更新頂點(diǎn)信息,二者協(xié)同完成骨骼蒙皮動畫的更新。
3 基于XNA的骨骼蒙皮動畫的實(shí)現(xiàn)
本文使用Visual Studio 2012+XNA4.0進(jìn)行骨骼蒙皮動畫的實(shí)現(xiàn)。綜合以上對骨骼蒙皮動畫的分析與設(shè)計(jì),下面將對其進(jìn)行實(shí)現(xiàn)。程序結(jié)構(gòu)設(shè)計(jì)圖如圖4所示,程序的實(shí)現(xiàn)分為模型和動畫的創(chuàng)建、數(shù)據(jù)載入、數(shù)據(jù)讀出和數(shù)據(jù)更新四個部分。在數(shù)據(jù)更新部分,對骨骼信息的更新在CPU中進(jìn)行,將CPU中計(jì)算得到的骨骼在世界坐標(biāo)系中的變換矩陣以及頂點(diǎn)與骨骼的關(guān)聯(lián)信息傳入GPU中,在GPU部分使用HLSL進(jìn)行頂點(diǎn)的更新并輸出到屏幕。圖5為程序?qū)崿F(xiàn)的主要類圖:KeyFrameSequence類用于獲取動畫序列的關(guān)鍵幀并進(jìn)行插值運(yùn)算;GameAnimateModel類用于矩陣轉(zhuǎn)換、動畫混合、動畫播放等;GamePlayer類用于與用戶進(jìn)行交互;Game1類為XNA中程序的主類,是程序運(yùn)行的入口。
4 結(jié)束語
本文從骨骼蒙皮動畫的原理出發(fā),以XNA為開發(fā)平臺,設(shè)計(jì)并實(shí)現(xiàn)了骨骼蒙皮動畫。在實(shí)現(xiàn)過程中對動畫的旋轉(zhuǎn)算法進(jìn)行了優(yōu)化;使用動畫混合技術(shù)實(shí)現(xiàn)了人物各個動作的無縫銜接;將頂點(diǎn)更新及渲染交給GPU來完成。這些措施提高了動畫的執(zhí)行效率,增強(qiáng)了動畫的真實(shí)感。隨著3D技術(shù)的發(fā)展,骨骼蒙皮動畫技術(shù)以其優(yōu)良的執(zhí)行效率及較為逼真的動畫效果,成為了實(shí)時動畫領(lǐng)域最受歡迎的技術(shù)之一。如何實(shí)現(xiàn)更加逼真的動畫混合,怎樣協(xié)調(diào)CPU與GPU的利用率,必將成為下一步研究的熱點(diǎn)。
參考文獻(xiàn):
[1] AUBEL A. Anatomically-based human body deformations[D].
Université de Marne-la-Vallée,F(xiàn)rance,2002.
[2] 吳小,馬利莊,顧寶軍.計(jì)算機(jī)動畫中人體建模與皮膚變形技術(shù)的研
究現(xiàn)狀與展望[J].中國圖象圖形學(xué)報,2008.12(4):65-73
[3] 夏開建,王士同.改進(jìn)的骨骼蒙皮算法模擬皮膚變形[J].計(jì)算機(jī)應(yīng)用
與軟件,2009.26(12):174-176
[4] Alexandre Santos Lob?o A.Beginning XNA 3.0 Game Program-
ming From Novice to Professional[M].Apress,2009:305-319
[5] 袁會杰.骨骼動畫技術(shù)的研究與實(shí)現(xiàn)[D].電子科技大學(xué),2010.
[6] 陳軍.復(fù)雜三維場景的數(shù)據(jù)處理及骨骼動畫實(shí)現(xiàn)[D].浙江大學(xué),2008.
[7] 雷濤,羅維薇,王毅.一種具有逼真效果的虛擬人動畫生成方法[J].計(jì)
算機(jī)應(yīng)用研究,2012.29(10):35-37
[8] Method in Real-time Skeletal Character Animation[J].International
Journal of Virtual Reality,2011.10(3):25