cocos2dx blender 骨骼動畫實現

2022-07-18 20:03:22 字數 4251 閱讀 3156

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

參考一 簡單3d 模型支援

第一步實現對3d 模型的簡單支援,完成乙個ccsprite3d 類

參考ccsprite 類 以及 ccglprogram ** 主要修改 draw 方法。

新增了定點陣列pos  繪製索引陣列index. 以及若干 3d 變換相關的成員方法 平移 旋轉 縮放。

對draw方法的改造,首先增加對opengl 矩陣進行計算的stdtransform, 將3d空間中的變換 矩陣乘到 mv 矩陣上面。

注意cocos2d 使用了兩種投影方式,一種是 平行投影,一種是3d 透視投影,預設使用的3d 投影, 這種方式下mv矩陣也被修改,將座標原點移動到了螢幕的右下角。

3d繪製需要 開啟depth_test 深度測試。

之後只需要將頂點陣列傳入vertexattribpointer 中 將索引陣列傳給gldrawelements 中即可.

測試時可以手動寫乙個 正方體的 頂點陣列資料。

注意要對模型進行一定的縮放,否則螢幕上面會看不到。

使用 畫 line 以及 畫頂點 方式 繪製 可以用來除錯。

二 3d 模型 基本變換支援

cocos2dx 中使用kazmath 這個數學庫,這個庫中的矩陣kmmat4使用列優先的方式儲存,即0 1 2 3 儲存的是 矩陣第一列資料。

對應平移變換只需要修改 最後一列的 前3行資料即可,分別對應x y z 平移。

對於旋轉,一般使用四元式進行計算,因此對於旋轉可以先按照四元式進行計算,最後轉化成乙個矩陣即可。

四元式 通過對旋轉軸和相對於軸的旋轉角度來表示(通過一些sin cos計算),兩個四元式之間的插值使用圓插值(slerp).

基本的 x y z 軸的旋轉矩陣 可以參考2維度旋轉矩陣的構造方法。

對於縮放直接修改矩陣主對角線上面的值即可。

下面這些矩陣對頂點的計算 都是按照 行優先矩陣 左乘以 頂點列向量, 相當於列優先矩陣 右乘以 頂點行向量 來計算結果的。在給opengl 傳入矩陣的時候 是以 列優先的方式傳入資料的。  

在kazmath 這個庫裡面 矩陣是以列優先方式儲存,矩陣相乘的時候第乙個矩陣的第一行 乘以 第二個矩陣的第一列 得到第乙個元素,即是第乙個矩陣左乘第二個矩陣。 

貌似在direct3d中傳入的矩陣資料是按照行優先的順序的,因此在direct中如果要做兩個矩陣的乘法,第乙個矩陣左乘第二個矩陣,則選取的矩陣元素和opengl是不同的。

當然這裡使用的左乘 是數學上面的左乘的概念,即用乙個矩陣的 第一行 乘以 第二個矩陣的第一列 得到第乙個元素。

注意矩陣乘法是不可以交換了,因此對於這三種變換,不同的乘順序會產生不同的結果。舉例如下:

旋轉矩陣 左乘 平移矩陣,則旋轉矩陣中的值將會影響到平移的值,而平移的數值不會影響結果中的旋轉部分的值,結果就是在世界空間中 物件是旋轉一定角度之後,沿著這個角度進行平移的。

如果平移矩陣 左乘 旋轉矩陣, 平移的值不會影響結果中的旋轉部分, 旋轉也不會影響平移。結果就是物體現在本地旋轉,但是之後 還是沿著世界座標中原來的軸進行平移。

先考慮 縮放矩陣 左乘 旋轉矩陣 結果就是 相當於在原來的旋轉矩陣上面 同一行 乘以乙個相同的係數, 這個矩陣在作用到頂點的時候  這個 係數可以提取出來,則相當於 對頂點先進行了旋轉 接著 還是按照原來的 世界座標的方向 進行縮放, 這樣得到的是乙個 切拉伸的效果,這樣物體會變形。

那麼 旋轉矩陣 左乘 縮放 矩陣 得到的結果就和上面不同,因此應該是物體旋轉之後,相應的縮放軸也跟著旋轉了,因此縮放 不是沿著世界軸進行的,而是沿著物體本身的本地座標軸進行的,這樣物體不會邊形。

接著考慮縮放左乘 平移矩陣 , 結果中的縮放部分沒有變化,但是平移部分會被改變,結果就是 物體還是按照原來的比例縮放,但是 新的平移位移的時候相對於 原來的平移位移會產生一定比例的縮放。

如果是 平移 左乘 縮放矩陣  結果中平移部分 和 縮放部分都不會發生改變, 結果就是 物體在世界座標空間中 按照原來的比例 縮放 , 接著平移正常的位移。

可以總結出來 平移 左乘 另外的矩陣 不過影響原來矩陣的結果, 而別的兩種矩陣左乘平移矩陣 會影響平移的結果。縮放 左乘 旋轉 會產生物體的邊形, 而旋轉左乘縮放 會保持物體的形狀和單純的進行縮放的物體形狀是一致的。

因此如果你的目標是保證世界空間中平移不變則用平移矩陣左乘其它矩陣,如果是要保證物體的縮放形狀不變則 用 旋轉矩陣左乘 縮放矩陣。

如果要保持這兩個不變性的話 矩陣乘法的順序就是 平移 * 旋轉 * 縮放

當然要根據自身想要的結果來調整矩陣的乘法順序,並且可以通過增加父子變換的關係來控制矩陣乘法順序。

一般情況是 父親矩陣 左乘於 孩子矩陣 則結果就是 父親在世界空間的平移 得到保持, 父親縮放會導致旋轉的孩子發生變形,父親的旋轉 會影響孩子自身的平移方向。

按照專業的說法叫做 孩子的變換矩陣作用在孩子節點自身的區域性空間 而 父親矩陣 會對孩子區域性空間進行變換。

三 骨骼動畫

本質上骨骼只是乙個矩陣變換,如果要檢視乙個骨骼則觀察其對應的矩陣即可。但是這種方式非常不直觀,如何通過影象直觀表現這種矩陣變換呢?

這裡首先要明確表現和本質之間的區別,矩陣變換及其對應的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 骨骼的名字

四:blender中的骨骼動畫匯出 並在cocos2dx 中匯入 

blender 支援python指令碼有比較好的擴充套件性 因此嘗試匯出blender中的模型和動畫資料 在遊戲引擎中使用

需要匯出的資料報括

定點資料 包括 定點位置 定點繫結的骨骼編號 以及權重

面資料 每個三角面 由哪幾個編號的定點構成

骨骼資料 骨骼在bind姿勢下面 每個骨骼的旋轉值, 偏移值, 長度資訊, 骨骼的父親資訊

動畫資訊 不同frame下 每個骨骼的 旋轉 長度 偏移 資訊

cocos2dx CCScrollView使用示例

總的來說,就是有乙個容器container 錨點 0,0 大小 為全部內容的大小 scrollview 大小,錨點,setdelegate 視窗大小 setviewsize 設定容器 setcontainer 方向 ccnode m pmedalcontainer ccscrollview m ps...

cocos2d實現語音 Cocos2d 聲音API

param url 聲音路徑 cc.audioengine.playmusic url loop 停止背景 param releasedata 是否釋放聲音資料,預設為false cc.audioengine.stopmusic releasedata 暫停背景 cc.audioengine.pau...

Cocos2d x教程第 14 講 Cocos2d

cocos2d x 2.2.0之前的版本常用的json解析的三方庫一般是 jsoncpp 2.2.x的版本中已經包含了jsoncpp的庫,但是卻把名字給換了,導致引入jsoncpp庫的同志們發生各種衝突.完成上述操作後就可以盡情發揮了.下面讓我們來認識一下幾個主要的類 value value 類建立...