轉 D3D中的四元數

2022-05-20 02:57:01 字數 4337 閱讀 3985

在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 ...