quaternion(四元數)
quaternion 的定義
四元數一般定義如下:
q=w+xi+yj+zk
其中 w,x,y,z是實數。同時,有:
i*i=-1
j*j=-1
k*k=-1
四元數也可以表示為:
q=[w,v]
其中v=(x,y,z)是向量,w是標量,雖然v是向量,但不能簡單的理解為3d空間的向量,它是4維空間中的的向量,也是非常不容易想像的。
通俗的講,乙個四元數(quaternion)描述了乙個旋轉軸和乙個旋轉角度。這個旋轉軸和這個角度可以通過 quaternion::toangleaxis轉換得到。當然也可以隨意指定乙個角度乙個旋轉軸來構造乙個quaternion。這個角度是相對於單位四元數而言的,也可以說是相對於物體的初始方向而言的。
當用乙個四元數乘以乙個向量時,實際上就是讓該向量圍繞著這個四元數所描述的旋轉軸,轉動這個四元數所描述的角度而得到的向量。
四元組的優點
有多種方式可表示旋轉,如 axis/angle、尤拉角(euler angles)、矩陣(matrix)、四元組等。 相對於其它方法,四元組有其本身的優點:
四元數不會有尤拉角存在的 gimbal lock 問題
四元數由4個數組成,旋轉矩陣需要9個數
兩個四元數之間更容易插值
四元數、矩陣在多次運算後會積攢誤差,需要分別對其做規範化(normalize)和正交化(orthogonalize),對四元數規範化更容易
與旋轉矩陣類似,兩個四元組相乘可表示兩次旋轉
quaternion 的基本運算
normalizing a quaternion
// normalising a quaternion works similar to a vector. this method will not do anything
// if the quaternion is close enough to being unit-length. define tolerance as something
// small like 0.00001f to get accurate results
void quaternion::normalise()
}vector3 quaternion::operator* (const vector3 &vec) const
how to convert to/from quaternions1
quaternion from axis-angle
// convert from axis angle
void quaternion::fromaxis(const vector3 &v, float angle)
quaternion from euler angles
// convert from euler angles
void quaternion::fromeuler(float pitch, float yaw, float roll)
quaternion to matrix
// convert to matrix
matrix4 quaternion::getmatrix() const
quaternion to axis-angle
// convert to axis/angles
void quaternion::getaxisangle(vector3 *axis, float *angle)
quaternion 插值
線性插值
最簡單的插值演算法就是線性插值,公式如:
q(t)=(1-t)q1 + t q2
但這個結果是需要規格化的,否則q(t)的單位長度會發生變化,所以
q(t)=(1-t)q1+t q2 / || (1-t)q1+t q2 ||
球形線性插值
儘管線性插值很有效,但不能以恆定的速率描述q1到q2之間的曲線,這也是其弊端,我們需要找到一種插值方法使得q1->q(t)之間的夾角θ是線性的,即θ(t)=(1-t)θ1+t*θ2,這樣我們得到了球形線性插值函式q(t),如下:
q(t)=q1 * sinθ(1-t)/sinθ + q2 * sinθt/sineθ
如果使用d3d,可以直接使用 d3dxquaternionslerp 函式就可以完成這個插值過程。
用 quaternion 實現 camera 旋轉
總體來講,camera 的操作可分為如下幾類:
沿直線移動
圍繞某軸自轉
圍繞某軸公轉
下面是乙個使用了 quaternion 的 camera 類:
class camera ;
void camera::rotate(const quaternion& q)
void camera::rotate(const vector3& axis, const radian& angle)
void camera::roll (const glfloat angle) //in radian
void camera::yaw (const glfloat angle) //in degree
rotate(yaxis, angleinradian);
}void camera::pitch (const glfloat angle) //in radian
void camera::glulookat()
用 quaternion 實現 trackball
用滑鼠拖動物體在三維空間裡旋轉,一般設計乙個 trackball,其內部實現也常用四元數。
class trackball
;void trackball::move(const qpointf& p)
每乙個單位四元數都可以對應到乙個旋轉矩陣
單位四元數q=(s,v)的共軛為q*=(s,-v)
單位四元數的模為||q||=1;
四元數q=(s,v)的逆q^(-1)=q*/(||q||)=q*
乙個向量r,沿著向量n旋轉a角度之後的向量是哪個(假設為v),這個用四元數可以輕鬆搞定
構造兩個四元數q=(cos(a/2),sin(a/2)*n),p=(0,r)
p`=q * p * q^(-1) 這個可以保證求出來的p`也是(0,r`)形式的,求出的r`就是r旋轉後的向量
另外其實對p做q * p * q^(-1)操作就是相當於對p乘了乙個旋轉矩陣,這裡先假設 q=(cos(a/2),sin(a/2)*n)=(s,(x, y, z))
兩個四元數相乘也表示乙個旋轉
q1 * q2 表示先以q2旋轉,再以q1旋轉
則這個矩陣為
同理乙個旋轉矩陣也可以轉換為乙個四元數,即給你乙個旋轉矩陣可以求出(s,x,y,z)這個四元數,
方法是:
旋轉矩陣 尤拉角 四元數比較
旋轉矩陣 尤拉角 四元數主要用於 向量的旋轉 座標系之間的轉換 角位移計算 方位的平滑插值計算。旋轉矩陣 尤拉角 四元數比較 不同的方位表示方法適用於不同的情況。下面是我們對合理選擇格式的一些建議 1.尤拉角最容易使用。當需要為世界中的物體指定方位時,尤拉角能大大的簡化人機互動,包括直接的鍵盤輸入方...
Eigen 四元數 尤拉角 旋轉矩陣 旋轉向量
一 旋轉向量 1.0 初始化旋轉向量 旋轉角為alpha,旋轉軸為 x,y,z eigen angleaxisd rotation vector alpha,vector3d x,y,z 1.1 旋轉向量轉旋轉矩陣 eigen matrix3d rotation matrix rotation ma...
unity3d四元數和旋轉矩陣
quaternion中存放了x,y,z,w四個資料成員,可以用下標來進行訪問,對應的下標分別是0,1,2,3。主要介紹幾個函式 1 根據兩個向量計算出旋轉量,計算出來的旋轉量為從fromdirection旋轉到todirection的旋轉量 static quaternion fromtorotat...