該接觸PV3D這個引擎,而且對3D的編程也是一種半解,所以Mark兩篇文章,以備自己學習PV3D用..
人類最初用9個值的矩陣(Matrix),來表示一個三維物體的旋轉位置。它的缺陷是數據大,和無法自動在兩個角度間產生過度的角度。
由於矩陣描述角度過於抽象,人類又發明了3個值的優拉角(Euler)。可優拉角是個很不負責任的傢伙,旋轉圈數和旋轉順序完全不做區分。三維動畫師最厭
惡的情況之一‘萬向鎖(Gimbal
Lock)’就是這個傢伙的問題。按不同軸以優拉角旋轉幾次後,出現x,y,z三個軸完全變成同向的情況,也就是說,優拉角很容易出現旋轉到最後只剩一個
方向可以旋轉的情況,這就是恐怖的‘萬向鎖’。
後來,聰明的愛爾蘭數學家發明了我們今天要研究的四元數(Quaternion),這就是迄今爲止描述三維空間旋轉相對完美的方案。
四元數和矩陣一樣,不滿足乘法交換率,也就是說,A*B不等於B*A。四元數之所以可以明確地表述三維旋轉,是因爲他實際上是一種‘四維’的算法。這裏的‘四維’是數學上的使用,不需要去想象什麼是四維的世界=_=,只是多一條軸,多一個參數而已。
我們主要介紹PV3d裏Quaternion常用的幾個方法和其用法,不會涉及過深的數學知識,所以不用擔心。Quaternion類位置在org-papervision-core-math包裏。
//構造四元數需要4個值(人家名字就叫4元嘛=_=),x,y,z是個三維向量,表示‘任意軸’,w是個標量,表示旋轉度數。這就是幾乎完美的角度旋轉。
四元數之所以不是‘絕對完美’,是因爲插值的時候過渡速率不恆定,且很難解決。不過這比起‘恐怖萬向鎖’已經是很小的問題。
public function Quaternion( x:Number = 0, y:Number = 0, z:Number = 0, w:Number = 1 )
//下面兩個個分別是‘從優拉角換算出四元數’和‘從矩陣換算出四元數’。這是兩個非常常用的方法,只要已知一個物體的優拉角或矩陣,即可生成對應的四元數。
Pv3d裏任何DisplayObject3D的tranform這個屬性就是變換他的矩陣,由這個矩陣就能得到目前旋轉的四元數。(我們研究所的Flab攝像機旋轉就用到了這些方法)
public static function createFromEuler( ax:Number, ay:Number, az:Number, useDegrees:Boolean = false )
public static function createFromMatrix( matrix:Matrix3D )
//和上面的剛好反向,分別是‘得到已知四元數的優拉角’和‘得到已知四元數的矩陣’
public function toEuler()
public function get matrix()
//插值是四元數最重要的用處之一,slerp方法的參數中,qa爲開始的旋轉位置的四元數,qb爲結束的旋轉位置四元數,apha可以看成一個插值的位置的比例,數值在0-1之間。
public static function slerp( qa:Quaternion, qb:Quaternion, alpha:Number )
完美旋轉的思路
是這樣的:
我們必須要首先知道我們的開始位置和結束位置,結束位置很多情況用一個DisplayObject3D虛擬,我們可以用它的.tranform(是個矩陣值),變換成一個四元數
知道兩頭的四元數,我們只需要每禎增加alpha值(從0-1),即可在這兩個四元數之間插入任意多的過渡幀的四元數。
然後將每禎的這個四元數反向爲矩陣,在通過矩陣相乘目前物體的位置,即可得到物體每禎的新位置。
下面這些都是四元數的基本運算(一般使用沒必要掌握),維基詞典可以瞭解‘四元數’更專業的解釋。
維基詞典-四元數
(會打開新窗口)
//求模,四元數到原點的距離,簡單的說就是長度
public function get modulo()
//共軌
//點乘
//叉稱
public static function multiply( a:Quaternion, b:Quaternion )
//求差
public static function sub(a:Quaternion, b:Quaternion)
//求和
public static function add(a:Quaternion, b:Quaternion)