CSharpGL(50)使用Assimp加載骨骼動畫


CSharpGL(50)使用Assimp加載骨骼動畫

在(http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html)介紹了C++用Asismp庫加載骨骼動畫的原理和流程。

在(http://wiki.jikexueyuan.com/project/modern-opengl-tutorial/tutorial45.html)是其中文版譯文。

本文用CSharpGL借助Assimp庫實現加載和渲染骨骼動畫的功能。

下載

CSharpGL已在GitHub開源,歡迎對OpenGL有興趣的同學加入(https://github.com/bitzhuwei/CSharpGL

在.NET下使用Assimp

三維模型解析庫Assimp本身是用C++編寫的,所幸有一個C#的封裝(https://github.com/assimp/assimp-net)。使用此封裝即可直接在CSharpGL中調用Assimp了。

將Assimp32.dll、Assimp64.dll和AssimpNet.dll都放到項目所在目錄下,在Reference中添加對AssimpNet.dll的引用即可。

 

 

渲染骨骼動畫

Assimp加載模型后得到的數據結構如下:

1 public sealed class Scene
2 {
3     public Animation[] Animations { get; }
4     public Material[] Materials { get; }
5     public Mesh[] Meshes { get; }
6     public Node RootNode { get; }
7 }

按我的理解,其中的RootNode就是骨骼的根結點。整個骨骼構成一個樹結構。每個結點都包含一個mat4 Transform矩陣,用於描述自己相對於父結點的方位變化。子結點代表的骨骼,其絕對方位由根結點的Transform逐步地乘到自己的Transform來得到。“絕對方位”指的就是在Model Space中的方位。

 

如圖所示,紅色的小方塊描述了骨骼所在的絕對位置(這里的骨骼對應人體的關節)。從紅到白漸變的線條描述了骨骼之間的父子關系,紅色一端為父結點,白色一端為子結點。兩腳之間的那個紅色小方塊,就是根結點RootNode。用半透明方式渲染的兩臂水平擺放的,就是模型的默認位置。

上圖這個模型,只有一個“拿起燈左右查看”的動作(Animation)。其他模型可能有多個動作,它們構成一個數組(Assimp.Animation[])。每個Animation都指定了這個模型的所有骨骼在所有關鍵幀上的Transform值。這樣,通過按時間順序依次經歷各個關鍵幀(更准確地說,是在2個相鄰的關鍵幀之間插值),就可以得到骨骼在各個時刻的Transform。再讓模型的頂點依附於骨骼而動,就實現了骨骼動畫。

模型上的一個頂點,要記錄自己都依附於哪幾個骨骼,自己對這幾個骨骼依附的權重分別是多少(權重之和為1)。然后,就可以從默認的初始位置(用半透明方式渲染的兩臂水平擺放的那個位置)變換到骨骼要求的位置。

頂點的這一變換過程我還沒弄明白。這里需要的Offset Matrix到底是什么。據我查資料,外加計算,Offset Matrix就是那個讓骨骼結點變換到絕對方位的矩陣的逆矩陣。但是總覺得有點想不通的地方,確不知道是哪里。

經高人goodpgr提醒,Offset Matrix就是那個讓骨骼結點變換到model space的矩陣的逆。非常感謝!

將其推導過程陳列如下:

「Offset Matrix就是那個讓骨骼結點變換到絕對方位的矩陣的逆矩陣」:
可以改寫成
「Offset Matrix就是那個讓骨骼結點變換到model space的矩陣的逆」:
因為skin mesh的頂點資料是在model space定義的
假設在右小腿附近有1個頂點P,用model space的三把尺和原點來測量
它在model space可能是 p'=(10,20,0)
(y向上是天空)
但對右小腿Bone來說,用它的三把尺和原點測量頂點P
得到的值可能是 p=(10,0,0) => local bone space
假設右小腿Bone的階層長這樣
RootBone // 右骨盆Bone // 右大腿Bone // 右小腿Bone
它們對映到的矩陣分別是
Mroot // Mc // Mb // Ma
那 p和p'會有下面的關系
p'=(Mroot Mc Mb Ma) p
(Mroot Mc Mb Ma)^-1 p'=p
MatrixModelSpaceToBoneLocal * p' = p
MatrixModelSpaceToBoneLocal = Offset_Matrix
mesh綁定到bone上,實際上是綁定到bone的local space
但一開始mesh的資料是在model space建模的

總結

骨骼動畫的原理網上有很多介紹了。我還沒有透徹理解,所以不對本文的原理部分負責。

 


免責聲明!

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



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