為 了回答這個問題,先來看看一般關于旋轉(面向)的描述方法-歐拉描述法。它使用最簡單的x,y,z值來分別表示在x,y,z軸上的旋轉角度,其取值為 0-360(或者0-2pi),一般使用roll,pitch,yaw來表示這些分量的旋轉值。需要注意的是,這里的旋轉是針對世界坐標系說的,這意味著 第一次的旋轉不會影響第二、三次的轉軸,簡單的說,三角度系統無法表現任意軸的旋轉,只要一開始旋轉,物體本身就失去了任意軸的自主性,這也就導致了萬向 軸鎖(Gimbal Lock)的問題。鑒于歐拉角插值動畫時有錯誤,因此不能使用歐拉角的方式來進行球面方式插值,相應地,就可以采用四元數的方式來解決這個問題。如果系統還是使用歐拉角表示,要先轉換為四元數,然后再進行插值,再轉換回來歐拉角表示。
四元數的應用范圍很廣泛,它的定義如下:
四元數是簡單的超復數。 復數是由實數加上虛數單位 i 組成,其中i^2 = -1。 相似地,四元數都是由實數加上三個虛數單位 i、j、k 組成,而且它們有如下的關系: i^2 = j^2 = k^2 = -1, i^0 = j^0 = k^0 = 1 , 每個四元數都是 1、i、j 和 k 的線性組合,即是四元數一般可表示為a + bk+ cj + di,其中a、b、c 、d是實數。對于i、j、k本身的幾何意義可以理解為一種旋轉,其中i旋轉代表X軸與Y軸相交平面中X軸正向向Y軸正向的旋轉,j旋轉代表Z軸與X軸相交平面中Z軸正向向X軸正向的旋轉,k旋轉代表Y軸與Z軸相交平面中Y軸正向向Z軸正向的旋轉,-i、-j、-k分別代表i、j、k旋轉的反向旋轉。
ij = k, ji = -k, jk = i, kj = -i, ki =j, ik = -j
四元數的虛部可以使用qv, 實部使用qw,那么就可表示為(qv, qw)的形式。

1.四元數和軸-角對 繞軸n旋轉θ角:n是一個向量,根據左手或右手法則定義旋轉的正方向, θ角表示旋轉的量。 那么表示這個旋轉的四元數為:

2. 四元數的模

代入軸-角對的公式求模。 n為單位向量,最后可以得到四元數的模為1.稱為單位四元數。
3. 四元數的共軛

四元數和它的共軛代表相反的角位移,因為相當于旋轉軸反向。
4. 四元數乘法(叉乘)

5. 優點
通俗的講,一個四元數(Quaternion)描述了一個旋轉軸和一個旋轉角度。這個旋轉軸和這個角度可以通過 Quaternion::ToAngleAxis轉換得到。當然也可以隨意指定一個角度一個旋轉軸來構造一個Quaternion。這個角度是相對于單位四元數而言的,也可以說是相對于物體的初始方向而言的。當用一個四元數乘以一個向量時,實際上就是讓該向量圍繞著這個四元數所描述的旋轉軸,轉動這個四元數所描述的角度而得到的向量。有多種方式可表示旋轉,如 axis/angle、歐拉角(Euler angles)、矩陣(matrix)、四元組等。 相對于其它方法,四元組有其本身的優點: 四元數不會有歐拉角存在的 gimbal lock 問題 四元數由4個數組成,旋轉矩陣需要9個數 兩個四元數之間更容易插值 四元數、矩陣在多次運算后會積攢誤差,需要分別對其做規范化(normalize)和正交化(orthogonalize),對四元數規范化更容易 與旋轉矩陣類似,兩個四元組相乘可表示兩次旋轉
6. 四元數轉換為矩陣

7. 四元數插值



代碼:
quat slerp(quat qa, quat qb, double t) { // quaternion to return quat qm = new quat(); // Calculate angle between them. double cosHalfTheta = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z; // if qa=qb or qa=-qb then theta = 0 and we can return qa if (abs(cosHalfTheta) >= 1.0){ qm.w = qa.w;qm.x = qa.x;qm.y = qa.y;qm.z = qa.z; return qm; } // Calculate temporary values. double halfTheta = acos(cosHalfTheta); double sinHalfTheta = sqrt(1.0 - cosHalfTheta*cosHalfTheta); // if theta = 180 degrees then result is not fully defined // we could rotate around any axis normal to qa or qb if (fabs(sinHalfTheta) < 0.001){ // fabs is floating point absolute qm.w = (qa.w * 0.5 + qb.w * 0.5); qm.x = (qa.x * 0.5 + qb.x * 0.5); qm.y = (qa.y * 0.5 + qb.y * 0.5); qm.z = (qa.z * 0.5 + qb.z * 0.5); return qm; } double ratioA = sin((1 - t) * halfTheta) / sinHalfTheta; double ratioB = sin(t * halfTheta) / sinHalfTheta; //calculate Quaternion. qm.w = (qa.w * ratioA + qb.w * ratioB); qm.x = (qa.x * ratioA + qb.x * ratioB); qm.y = (qa.y * ratioA + qb.y * ratioB); qm.z = (qa.z * ratioA + qb.z * ratioB); return qm;}更多,請參考:http://www.cnblogs.com/mengdd/archive/2013/08/05/3238223.htmlhttp://blog.csdn.net/candycat1992/article/details/41254799http://blog.csdn.net/jin_syuct/article/details/49785541
1. C++標準模板庫從入門到精通
http://edu.csdn.net/course/detail/3324
2.跟老菜鳥學C++
http://edu.csdn.net/course/detail/29013. 跟老菜鳥學python
http://edu.csdn.net/course/detail/25924. 在VC2015里學會使用tinyxml庫
http://edu.csdn.net/course/detail/25905. 在Windows下SVN的版本管理與實戰
http://edu.csdn.net/course/detail/2579
6.Visual Studio 2015開發C++程序的基本使用
http://edu.csdn.net/course/detail/2570
7.在VC2015里使用PRotobuf協議
http://edu.csdn.net/course/detail/25828.在VC2015里學會使用MySQL數據庫
http://edu.csdn.net/course/detail/2672
新聞熱點
疑難解答