[轉]cocos2dx blender 骨骼動畫實現

前言 cocos2d-x 中相關部分代碼介紹 背景知識介紹

參考http://www.3dkingdoms.com/weekly/weekly.php?a=4php

  1. 簡單3d 模型支持html

    第一步實現對3d 模型的簡單支持,完成一個CCSprite3D 類
    參考CCSprite 類 以及 CCGLProgram 代碼 主要修改 draw 方法。
    添加了定點數組pos 繪製索引數組index. 以及若干 3d 變換相關的成員方法 平移 旋轉 縮放。
    對draw方法的改造,首先增長對opengl 矩陣進行計算的stdTransform, 將3d空間中的變換 矩陣乘到 MV 矩陣上面。
    注意cocos2d 使用了兩種投影方式,一種是 平行投影,一種是3d 透視投影,默認使用的3d 投影, 這種方式下MV矩陣也被修改,將座標原點移動到了屏幕的右下角。
    3d繪製須要 開啓depth_test 深度測試。
    以後只須要將頂點數組傳入vertexAttribPointer 中 將索引數組傳給glDrawElements 中便可.
    測試時能夠手動寫一個 正方體的 頂點數組數據。
    注意要對模型進行必定的縮放,不然屏幕上面會看不到。
    使用 畫 line 以及 畫頂點 方式 繪製 能夠用來調試。python

  2. 3d 模型 基本變換支持數組

    http://en.wikipedia.org/wiki/Transformation_matrix
    cocos2dx 中使用kazmath 這個數學庫,這個庫中的矩陣kmMat4使用列優先的方式存儲,即0 1 2 3 存儲的是 矩陣第一列數據。
    對應平移變換隻須要修改 最後一列的 前3行數據便可,分別對應x y z 平移。
    http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
    對於旋轉,通常使用四元式進行計算,所以對於旋轉能夠先按照四元式進行計算,最後轉化成一個矩陣便可。
    四元式 經過對旋轉軸和相對於軸的旋轉角度來表示(經過一些sin cos計算),兩個四元式之間的插值使用圓插值(slerp).
    基本的 x y z 軸的旋轉矩陣 能夠參考2維度旋轉矩陣的構造方法。
    http://onlinemca.com/mca_course/kurukshetra_university/semester5/computergraphics/three_d_transformation.php
    對於縮放直接修改矩陣主對角線上面的值便可。
    下面這些矩陣對頂點的計算 都是按照 行優先矩陣 左乘以 頂點列向量, 至關於列優先矩陣 右乘以 頂點行向量 來計算結果的。在給opengl 傳入矩陣的時候 是以 列優先的方式傳入數據的。 http://www.opengl.org/archives/resources/faq/technical/transformations.htm
    在kazmath 這個庫裏面 矩陣是以列優先方式存儲,矩陣相乘的時候第一個矩陣的第一行 乘以 第二個矩陣的第一列 獲得第一個元素,便是第一個矩陣左乘第二個矩陣。
    http://www.mindcontrol.org/~hplus/graphics/matrix-layout.html
    貌似在direct3d中傳入的矩陣數據是按照行優先的順序的,所以在direct中若是要作兩個矩陣的乘法,第一個矩陣左乘第二個矩陣,則選取的矩陣元素和opengl是不一樣的。
    固然這裏使用的左乘 是數學上面的左乘的概念,即用一個矩陣的 第一行 乘以 第二個矩陣的第一列 獲得第一個元素。
    注意矩陣乘法是不能夠交換了,所以對於這三種變換,不一樣的乘順序會產生不一樣的結果。舉例以下:
    旋轉矩陣 左乘 平移矩陣,則旋轉矩陣中的值將會影響到平移的值,而平移的數值不會影響結果中的旋轉部分的值,結果就是在世界空間中 對象是旋轉必定角度以後,沿着這個角度進行平移的。
    若是平移矩陣 左乘 旋轉矩陣, 平移的值不會影響結果中的旋轉部分, 旋轉也不會影響平移。結果就是物體如今本地旋轉,可是以後 仍是沿着世界座標中原來的軸進行平移。
    先考慮 縮放矩陣 左乘 旋轉矩陣 結果就是 至關於在原來的旋轉矩陣上面 同一行 乘以一個相同的係數, 這個矩陣在做用到頂點的時候 這個 係數能夠提取出來,則至關於 對頂點先進行了旋轉 接着 仍是按照原來的 世界座標的方向 進行縮放, 這樣獲得的是一個 切拉伸的效果,這樣物體會變形。
    那麼 旋轉矩陣 左乘 縮放 矩陣 獲得的結果就和上面不一樣,所以應該是物體旋轉以後,相應的縮放軸也跟着旋轉了,所以縮放 不是沿着世界軸進行的,而是沿着物體自己的本地座標軸進行的,這樣物體不會邊形。
    接着考慮縮放左乘 平移矩陣 , 結果中的縮放部分沒有變化,可是平移部分會被改變,結果就是 物體仍是按照原來的比例縮放,可是 新的平移位移的時候相對於 原來的平移位移會產生必定比例的縮放。
    若是是 平移 左乘 縮放矩陣 結果中平移部分 和 縮放部分都不會發生改變, 結果就是 物體在世界座標空間中 按照原來的比例 縮放 , 接着平移正常的位移。
    能夠總結出來 平移 左乘 另外的矩陣 不過影響原來矩陣的結果, 而別的兩種矩陣左乘平移矩陣 會影響平移的結果。縮放 左乘 旋轉 會產生物體的邊形, 而旋轉左乘縮放 會保持物體的形狀和單純的進行縮放的物體形狀是一致的。
    所以若是你的目標是保證世界空間中平移不變則用平移矩陣左乘其它矩陣,若是是要保證物體的縮放形狀不變則 用 旋轉矩陣左乘 縮放矩陣。
    若是要保持這兩個不變性的話 矩陣乘法的順序就是 平移 * 旋轉 * 縮放
    http://gamedev.stackexchange.com/questions/16719/what-is-the-correct-order-to-multiply-scale-rotation-and-translation-matrices-f
    固然要根據自身想要的結果來調整矩陣的乘法順序,而且能夠經過增長父子變換的關係來控制矩陣乘法順序。
    通常狀況是 父親矩陣 左乘於 孩子矩陣 則結果就是 父親在世界空間的平移 獲得保持, 父親縮放會致使旋轉的孩子發生變形,父親的旋轉 會影響孩子自身的平移方向。
    按照專業的說法叫作 孩子的變換矩陣做用在孩子節點自身的局部空間 而 父親矩陣 會對孩子局部空間進行變換。dom

  3. 骨骼動畫
    本質上骨骼只是一個矩陣變換,若是要查看一個骨骼則觀察其對應的矩陣便可。可是這種方式很是不直觀,如何經過圖像直觀表現這種矩陣變換呢?
    這裏首先要明確表現和本質之間的區別,矩陣變換及其對應的3d骨骼對象不能等價。骨骼的做用只是施展一種變換到一個對象身上,至於這個對象當前的狀態是什麼並不關心,所以須要手動的對對象設定一個初始化的狀態,然後續的狀態經過這種骨骼矩陣變換來生成。
    所以問題分紅兩個部分,如何描述這種初始化狀態,如何描述這個矩陣變換。
    骨骼分紅兩個端點 頭和 尾部,之間有必定長度鏈接,而且這兩個點之間有必定的旋轉方向。
    矩陣變換比較簡單,能夠經過一個四元式和一個3維向量, 以及一個骨骼長度來描述。
    將骨骼的一端作爲原點,這裏我設定骨骼沿着x 軸方向,而骨骼長度就是lenght,offset表示孩子骨骼相對於父親骨骼的 結束端點的 位置偏移,一般這個偏移量爲0.
    這樣矩陣變換的計算方法就是
    外部矩陣 * 父親骨骼平移矩陣 * 父親骨骼旋轉矩陣 * x軸方向 length長度 平移矩陣 * 孩子骨骼的平移矩陣 * 孩子骨骼旋轉矩陣
    上面就能計算到 一個孩子骨骼的變換矩陣了。抽取其中的元素,能夠獲得每根骨骼的變換矩陣的計算方法是
    外部矩陣 * 平移矩陣 * 旋轉矩陣
    而傳入給孩子骨骼的 矩陣就是 外部矩陣 * 平移矩陣 * 旋轉矩陣 * x軸方向長度length 平移矩陣
    這裏的length存在的主要目的是爲了方便的描述旋轉,由於對於長度0的骨骼來說 就沒辦法指定其旋轉方向了。
    解決了矩陣變換的描述方法 接着須要描述骨骼初始狀態以及和mesh綁定時的初始狀態
    首先建模的時候會把骨骼的父子關係肯定每一個骨骼初始的旋轉 長度 平移這些參數肯定, 這裏咱們假設骨骼動畫只有旋轉, 這樣的話 長度能夠存儲到上面提到的length裏面。
    這時候如何存儲初始的旋轉矩陣呢? 咱們爲每個骨骼分配了一個額外的矩陣,這個矩陣裏面存放 骨骼初始 骨骼的初始平移矩陣 左乘 旋轉矩陣 的逆 矩陣。
    這樣在對一個骨骼上面的定點進行變換的時候,若是骨骼在初始狀態,那麼對定點的變換就是 單位矩陣,經過上面計算的逆矩陣 * 骨骼當前的變換矩陣 就會獲得一個單位矩陣 而這個單位矩陣 再做用到 定點上 定點就不會運動了。這樣就保證了 在骨骼的初始狀態下 骨骼上綁定的 頂點 也是在初始狀態, 不會運動。
    上面計算的骨骼逆矩陣是骨骼局部空間的逆矩陣 所以是不夠用的,對於子骨骼來說 其變換矩陣是通過父親層層傳遞的, 所以一個子骨骼的逆矩陣實際的逆向矩陣是 子局部逆向矩陣 * 父親逆向矩陣
    這時候 對於 計算孩子骨骼的實際變換矩陣就是 子局部逆向矩陣 * 父親逆向矩陣 * 父親傳到的變換矩陣 * 子局部變化矩陣
    這樣若是 父親 孩子骨骼都在bind位置時候,孩子上面的mesh 定點也是在bind位置的。
    所以對於一個骨骼描述的數據就包括
    rotate 四元式骨骼局部旋轉
    offset 3維度向量 骨骼局部偏移
    length 長度 骨骼長度
    reverse kmMat4 局部逆矩陣
    mat 計算的實際變換矩陣 用於給mesh定點使用
    child 骨骼的孩子骨骼
    parent 骨骼的父親
    id 骨骼的編號
    name 骨骼的名字測試

  4. blender中的骨骼動畫導出 並在cocos2dx 中導入
    blender 支持python腳本有比較好的擴展性 所以嘗試導出blender中的模型和動畫數據 在遊戲引擎中使用
    須要導出的數據包括
    定點數據 包括 定點位置 定點綁定的骨骼編號 以及權重
    面數據 每一個三角面 由哪幾個編號的定點構成
    骨骼數據 骨骼在bind姿式下面 每一個骨骼的旋轉值, 偏移值, 長度信息, 骨骼的父親信息
    動畫信息 不一樣frame下 每一個骨骼的 旋轉 長度 偏移 信息動畫

相關文章
相關標籤/搜索