在3d程式中,通常用quaternion來計算3d物體的旋轉角度,與matrix相比,quaternion更加高效,占用的儲存空間更小,此外也更便於插值。在數學上,quaternion表示複數w+xi+yj+zk,其中i,j,k都是虛數單位:
i*i = j*j = k*k= -1
i*j = k, j*i = -k
可以把quaternion看做乙個標量和乙個3d向量的組合。實部w表示標量,虛部表示向量標記為v,或三個單獨的分量(x,y,z)。所以quaternion可以記為[ w,v]或[ w,(x,y,x)]。對quaternion最大的誤解在於認為w表示旋轉角度,v表示旋轉軸。正確的理解應該是w與旋轉角度有關,v與旋轉軸有關。例如,要表示以向量n為軸,軸旋α度,相對的quaternion應該是:
q = [ cos(α/ 2) , sin(α/ 2)n]
=[ cos(α/ 2) , ( sina(α/ 2)nx, sin(α/ 2)ny, sin(α/ 2)nz ) ]
為了計算方便,一般要求n為單位向量。對quaternion來說使用四個值就能記錄旋轉,而不是matrix所需的十六個值。為什麼用quaternion來計算旋轉很方便呢?先說過quaternion是乙個複數,如果你還記得一點點複數的知識,那麼應該知道複數乘法(叉乘)的幾何意義實際上就是對複數進行旋轉。對最簡單的複數p= x + yi來說,和另乙個複數q = ( conα,sinα)相乘,則表示把p沿逆時針方向旋轉α:
p』 = pq
當然,x+yi的形式只能表示2d變換,對3d變換來說就需要使用 quaternion了,而且計算也要複雜一點。為了對3d空間中的乙個點p(x,y,z)進行旋轉,需要先把它轉換為quaternion形式p = [0, ( x, y, z)],接下來前面討論的內容,定義q = cos(α/ 2) , sin(α/ 2)n為旋轉quaternion,這裡n為單位向量長度的旋轉軸,α為旋轉角度。那麼旋轉之後的點p』則為:
p』 = qpq-1
1. 數學分析
1) 四元數是什麼東西?
這個東西算盤、矩陣、複數是一類東西,即數學工具,數學家們創造了這個東西來解決一些數學問題。其實四元數是一種超複數,他不是只有乙個虛數的複數,而是有三個虛數的複數。我們先回顧一下複數吧。
2) 虛數的**
實數集中沒有-1的平方根,因為沒有哪個實數的平方等於-1,所以數學家們就創造它——虛數i,並且定義了i * i = -1。
所以我們可以計算sqrt(-4)了,sqrt(-4) = 2*i
3) 複數
定義:乙個實數與乙個虛數的和。 z = a + bi。
a叫實部,b叫虛部。
其中(a,b)為復平面上的點。這也是為什麼3d圖形運算能和四元數掛上關係了。
運算法則:
z1 = a + b*i
z2 = c + d*i
與標量相乘 k*z1 = k*a + k*b*i
複數相加 z1 + z2 = a + c + (b + d) * i
複數相乘 z1 * z2 = (a + b * i) * (c + d * i) = a * c + a * d * i + c * b * i - b * d = a*c - b*d + (a*d+b*c) * i
複數相除 z1 / z2 = (a + b*i) / (c + d*i)
z1的共軛z1* = a - b*i,作用是z×z*為實數
所以複數相除 z1 / z2 = (a + b*i)*(c - d*i) / (c2+d2) = ... = (a*c + b*d)/(a2+b2) + (b*c-a*d)*i)/(a2+b2)
z1的倒數 1/z = 1 / (a+b*i),同樣可以轉化為:a/(a2+b2) + b*i/(a2+b2)
z1的範數 |z| = sqrt(a2+b2) = sqrt(z×z*)
4) 超複數
q = q0 + q1*i + q2*j + q3*k
上面就是四元數的表示,其中q0為實部,而虛部1,q2,q3>正好組成了3d復平面中的向量。
簡寫就是q = q0 + qv,其中qv是向量1, q2 ,q3>。
超複數的運算法則與複數相同,這裡就不再重複了,但要特別說明四元數的倒數q-1。
q×q-1 = 1
兩邊同時乘以q*:
q×q-1×q* = q*
因為:q×q* = |q|2
所以q-1=q* / |q|2
可以注意到,如果q是乙個單位四元數的話,那麼q的倒數就等於q的共軛。
這個特性非常重要,因為在四元數旋轉中要使用。
5) 四元數旋轉
對於乙個3d向量,我們把他表現為四元數形式,則是:vq= <0, x, y, z>。
以及給定乙個表示旋轉軸和旋轉角度的單位四元數q,那麼向量vq繞指定軸旋轉指定角度的結果四元數vq'滿足如下:
右手座標系:
順時針旋**vq' = q*×vq×q
逆時針旋**vq' = q×vq×q*
左手座標系:
順時針旋**vq' = q×vq×q*
逆時針旋**vq' = q*×vq×q
其中,對於那個用於儲存旋轉軸和旋轉角度的單位四元數q,他與旋轉軸v = 和角度theta關係如下:
q = cos(theta/2) + sin(theta/2) × v
2. **實現
1) 四元數結構體定義
[cpp]view plain
copy
typedef
struct
quat_type
// 四元數
; struct
; };
} quat, *quat_ptr;
2) 四元數常用操作函式實現
[cpp]view plain
copy
void
_cppyin_math::quatcreate(quat_ptr q, vector3d_ptr v,
double
theta)
// 建立用於旋轉的四元數q, v必須為單位向量
void
_cppyin_math::quatgetvectorandtheta(quat_ptr q, vector3d_ptr v,
double
*theta)
void
_cppyin_math::quatadd(quat_ptr q1, quat_ptr q2, quat_ptr qsum)
void
_cppyin_math::quatsub(quat_ptr q1, quat_ptr q2, quat_ptr qdiff)
void
_cppyin_math::quatconjugate(quat_ptr q, quat_ptr qconj)
// 求共軛
void
_cppyin_math::quatscale(quat_ptr q,
double
scale, quat_ptr qs)
double
_cppyin_math::quatnorm(quat_ptr q)
double
_cppyin_math::quatnorm2(quat_ptr q)
void
_cppyin_math::quatnormalize(quat_ptr q, quat_ptr qn)
void
_cppyin_math::quatunitinverse(quat_ptr q, quat_ptr qi)
// 單位四元數的逆,等於求共軛
void
_cppyin_math::quatinverse(quat_ptr q, quat_ptr qi)
// 非單位四元數的逆
void
_cppyin_math::quatmul(quat_ptr q1, quat_ptr q2, quat_ptr qprod)
void
_cppyin_math::quatmul3(quat_ptr q1, quat_ptr q2, quat_ptr q3, quat_ptr qprod)
// 三個四元數相乘,用於做旋轉變換
D3D學習筆記(四)
光照 光照可分為環境光,漫射光,鏡面光三種 三種顏色的光均可用d3decolorvalue或d3dxcolor來表示,描述光線的顏色時,d3dxcolor中的alpha值將被忽略 材質 材質可用結構d3dmaterial9來表示 typedef struct d3dmaterial9d3dmater...
D3D中的渲染
虛擬世界中渲染幾何體一般來說有三種途徑 自定義座標渲染 d3dx內建模型渲染和外部模型資料渲染。第一步 定義頂點資料結構體 d3d提供了自定義頂點結構的機制,通過自定乙個結構體,來儲存我們所希望具有的頂點資料,例如 stuct colorvertex 頂點結構體定義好之後,需要用靈活頂點格式標記的組...
關於D3D中的顏色
1.當模型自帶顏色時,使用白色光照即可顯示出模型的本色,如果禁用光照,那麼模型就是黑色 2.當模型自帶顏色時,要通過設定material來設定模型的顏色,然後用白色光照之即可 1for dword i 0 i m dwnummtrls i 213m pmesh drawsubset i 14 15 ...