XNA 蒙皮動畫的導入與控制


糾結了將近一個月的東西..終於有點成果了,使用官方例子SkinningSample_4_0修改來的從maya導入蒙皮動畫到XNA中,以及對動畫的基本控制,基本上沒問題了。現在就來總結下。

首先是目錄:

1.對官方例子的簡單解說。
  1.1.基本概念
  1.2.蒙皮信息的傳遞
  1.3.播放蒙皮動畫
  1.4.AnimationPlayer類

2.模型蒙皮動畫導入經驗。
  2.1. 蒙皮綁定
  2.2.關節關鍵幀
  2.3.導出模型
  2.4.內容處理器

  2.5.其他

3.我加入的。
  3.1.多段動畫
  3.2.模型骨骼點跟蹤
  3.3.其他

 

1.                                                                                                                                                                                                                                                                       

1.1.                                                                                                                                     

   開始解說之前先要明確幾個概念,首先是關於關鍵幀的概念,官方例子中和maya中是不一樣的。在maya中的關鍵幀就是一個動作,從一個關鍵幀動作變化到另一個關鍵幀動作之間一段連續的變換就是關鍵幀動畫,蒙皮動畫就是靠關鍵幀動畫來做的(不明白的同學請去看maya的有關教程)。而在XNA的例子中,我們會看到一個List<Keyframe> Keyframes(關鍵幀) 屬性,這個屬性表示的是整個動畫中對每一個骨骼(maya中叫關節joint)的變換矩陣和變換執行的時刻。所以我們會看到maya的一段60幀的動畫導到這里后,Keyframes中會有2000多個關鍵幀...嗯。這很正常,如果模型骨骼更多的話,這個值會更大。

  然后是模型骨骼的名稱問題,maya中的關節(joint),即是XNA中的骨骼(bone),然后XNA中還把一個模型的全部骨骼稱為骨架(skeleton). 


1.2.                                                                                                                                     
  官方例子通過一個名為SkinnedModelPipeline的自定義內容管道從fbx模型文件,中取出有關蒙皮動畫的信息,信息如下:

   //綁定姿勢
List<Matrix> bindPose = new List<Matrix>();
//骨架中每個骨骼的頂點位置矩陣
List<Matrix> inverseBindPose = new List<Matrix>();
//骨架層次
List<int> skeletonHierarchy = new List<int>();
//骨骼名字
List<string> SkeletonName = new List<string>();

  然后將這些信息存儲在一個SkinningData類的實例中,放在模型類的Tag屬性中傳遞到游戲程序中,然后在程序中通過一個AnimationPlayer類讀取Tag的內容進行動畫的播放。


1.3.                                                                                                                                     
  播放時需要確定要播放的是哪段動畫,一段動畫稱為一個動畫剪輯,程序中使用AnimationClip類來表示,方法如下:

          //從模型的Tag屬性中取出蒙皮信息
skinningData = currentModel.Tag as SkinningData;

if (skinningData == null)
throw new InvalidOperationException
("This model does not contain a SkinningData tag.");

// 創建一個動畫播放器
animationPlayer = new AnimationPlayer(skinningData);
//從蒙皮信息中取出動畫剪輯
clipAll = skinningData.AnimationClips["Take 001"];
//這些是非必要性的剪輯介紹
clipAll.ModelName = "Brave.fbx";
clipAll.Introduce = "循環播放的攻擊動畫";
//播放
animationPlayer.StartClip(clipAll);

  這樣就能播放動畫了,但這里有一個問題,一個模型中只能包含一段動畫(至少我目前沒有找到maya中一個模型包含多段動畫的方法,如果有人知道的話,請求賜教~),即一個動畫剪輯,一旦animationPlayer.StartClip(Clip);就會被全部播放完,不過實際游戲中,我們的一個模型總會包含着多段互相獨立的動畫,比如,走路,跳躍,攻擊等。 這里我使用的方法的將動畫剪輯導出成一個.clip的自定義文件,這樣讀取一個模型和多個不同的.clip文件后,就可以使模型做出多種動畫,這個待會會介紹~方法其實非常簡單。

 

1.4.                                                                                                                                     
  AnimationPlayer的工作原理,基本上就是從AnimationClip里取出Keyframes,然后對每個骨骼按照指定的時間順序的進行變換。

2.                                                                                                       
  首先是maya中的操作,我使用的是maya2012中文版,蒙皮動畫的制作方法就不介紹了(我也是剛學幾個星期的新手而已...),這里只說下,導出到XNA中需要注意的地方。


2.1.                                                                                                                                     
  蒙皮綁定時,注意使用‘互交式蒙皮綁定’其他的綁定會出現問題。。比如蒙皮變形,位置錯亂之類的。


2.2.                                                                                                                                     
  制作動畫時注意關鍵幀要設在關節上,不能設在IK控制柄上,XNA是不認識控制柄的。還有各種約束也是不認的。注意關節的命名,盡量使用有意義的名稱,比如:jointR_Hand,jointL_Leg之類的,以便在XNA中識別。


2.3.                                                                                                                                     
  導出模型文件類型,自然是選fbx,注意勾上動畫選項,我記得默認是沒有勾選的。

2.4                                                                                                                                     
  XNA中,注意選擇fbx文件的內容處理器,方法是在VS中的右擊加入的.fbx文件,選擇 Content Processor為 SkinnedModelProcessor。
2.5                                                                                                                                     

  注意,如果導入的模型不帶紋理的話,需要在XNA中加入一張白色的紋理,否則無法顯示材質顏色。

 

3.                                                                                               

我加入的地方,為了模型動畫基本可用,我對官方例子做了些修改,接下來會一一介紹,當然官方也對這個例子做過擴充這是他做的改進:

SkinningControl:
對原例的改動:
1.  增加播放狀態PlayState: Loop,Once,Pause
2.  增加NewPlay(clip,playstate)方法,該方法傳入一個動畫片段clip和播放狀態playstate,它會重置動畫片段,並按照傳入狀態開始播放.
3.  增加Play(playstate)方法,該方法只修改播放狀態,不重置動畫片段.
4.  增加finish事件,該事件接受void類型無參數的委托,在動畫播放結束觸發.

這個例子可以到XNA游戲世界論壇里下到。

3.1.                                                                                                                                     
  首先是為了使一個模型使用多段動畫,我把動畫剪輯信息導出到了一個.clip文件中。

.clip文件:

-------
Brave.fbx
Brave站立不動
416.16:00:00
16
00:00:00
{ {M11:0.9063078 M12:-3.279216E-09 M13:-0.4226182 M14:0} {M21:-7.622232E-09 M22:1 M23:-8.576585E-11 M24:0}
{M31:0.4226182 M32:-4.653076E-10 M33:0.9063078 M34:0} {M41:0.483943 M42:5.205487E-08 M43:1.118171E-08 M44:1} }

----------
這是.clip文件的內容,可以看出保存的數據有:
這個文件適用的模型名稱;
這個文件的內容介紹;
動畫的持續時間;
變換骨骼的編號;
執行變換的時刻;
變換矩陣;

保存與讀取的方法寫在了AnimationClip類中:

View Code

 

3.2.                                                                                                                                     
  模型骨骼點跟蹤,即在運動中的模型中跟蹤某個骨骼的位置,下圖的那個三角形藍色的角所在的點,就是被跟蹤的骨骼位置,會隨着骨骼的變化而變化。
實現代碼是:

 

View Code

 

這里的一個問題是旋轉,由於是通過骨骼的位置來跟蹤,如果直接對模型進行旋轉的話,跟蹤位置就會出錯,因為模型旋轉后骨骼數據並不會發生變化,所以對模型的旋轉要改為對模型骨骼的根節點的旋轉,代碼:

View Code

在AnimationPlayer的Update中調用旋轉更新

View Code

  這樣就隨時獲得一個骨骼的位置,再通過 List<int> BonesHierarchy獲得其父骨骼就無敵了~。比如獲得手臂上的兩個父子骨骼后就可以知道手臂此時所指的方向。

這兩個圖演示的是腳上骨骼的跟蹤~:

 

3.3                                                                                                                                     

  然后還加入一些模型控制比如,平移,旋轉,逆放等,寫在了SkinningSample.cs的KeyboardControl()與 ModelControl()里。一開始按下‘9’會出現異常,因為‘9’播放的動畫是讀取.clip文件來的動畫,要把路徑設置正確。加入了一個模型關節名稱的List,和 骨骼層級(父子關系)的List List<string> SkeletonName, List<int> BonesHierarchy,在AnimationPlayer類中。

嗯..第一次寫那么長的博文,有什么不足的地方還請各位多多指教。

 

接下來是資源:

http://115.com/file/dpxnombj#

Brave(GNX-Y903VW)模型文件(Maya2012)pose01.rar

http://115.com/file/be8hrraf#

SkinningSample_4_0(管道調試方法).rar


http://115.com/file/e7z6tbs6#

clip文件.rar


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM