第十一章
用d3dxmatrixlookatlh函式計算觀察矩陣(即取景變換矩陣),當在某一固定地點固定攝像機方位,該函式十分有用,但其使用者對於乙個能夠根據使用者輸入做出響應的移動攝像機來說,就顯得力不從心,
用4個攝像機向量:右向量(right vector),上向量(up vector),觀察向量(look vector)以及位置向量(position vector)來定義攝像機相對於世界座標系的位置和朝向.這些向量實質上為相對世界座標系描述的攝像機定義了乙個區域性座標系,由於右向量,上向量和觀察向量定義了攝像機在世界座標系中的朝向,有時也將這三個向量統稱為方向向量(orientation vector)方向向量必須是標準正交的,如果乙個向量集中的向量都彼此正交,且模均為1,則稱該向量時標準正交的,引入這些約束的原因是在後面要將這些向量插入到乙個矩陣的某些行中,以使該矩陣成為標準正交矩陣(如果乙個矩陣的行向量是標準正交的),標準正交矩陣的乙個重要性質是其逆矩陣與其轉置矩陣相等
用4個向量來描述攝像機,就可對攝像機實施6種變換
#繞向量right的旋轉(俯仰,pitch)
#繞向量up的旋轉(偏航,yaw)
#繞向量look的旋轉(滾動,roll)
#沿向量right方向的掃視(strafe)
#沿向量up的方向的公升降(fly)
#沿向量look的平動
通過上述6種運算,攝像機可沿3個軸平動已經繞3個軸轉動,即攝像機具有6個自由度
class camera
;camera();
camera(cameratype cameratype) ;
~camera();
void strafe(flaot units);
void fly(float units);
void walk(float units);
void pitch(float angle);
void yaw(float angle);
void roll(float angle);
void getviewmatrix(d3dxmatrix* v);
void setcameratype(cameratype cameratype);
void getposition(d3dxvector3* pos);
void setposition(d3dxvector3* pos);
void getright(d3dxvector3* right);
void getup(d3dxvector3* up);
void getlook(d3dxvector3* look);
private:
cameratype _cameratype;
d3dxvector3 _right;
d3dxvector3 _up;
d3dxvector3 _look;
d3dxvector3 _pos;
};計算取景變換矩陣,令向量 p = (px,py,pz),r = (rx,ry,rz),u = (ux,uy,uz),d = (dx,dy,dz)分別表示position,right,up和 look這4個向量
取景變換所解決的問題其實就是世界座標系中的物體在以攝像機為中心的座標系中如果進行描述,等價於將世界座標系中的物體隨攝像機一起進行變換,以使攝像機座標系與世界座標系完全重合
所以希望變換矩陣v能夠實現:
#pv = (0,0,0) 矩陣v將攝像機移至世界座標系的原點
#rv = (1,0,0) 矩陣v將攝像機的right向量與世界座標系的x軸重合
#uv = (0,1,0) 矩陣v將攝像機的up向量與世界座標系的y軸重合
#dv = (0,0,1) 矩形v使攝像機的look向量與世界座標系的z軸重合
這樣就可將計算這種矩陣的任務分為兩步:首先將攝像機平移到世界座標系的原點,然後通過旋轉變換使攝像機各向量與世界座標系對應各軸重合
平移:攝像機的位置向量p平移到原點可通過將其與向量-p做向量加法輕鬆實現,因為p-p = 0
旋轉攝像機各向量與世界座標系各軸重合的工作量稍大一些,需要乙個3x3的旋轉矩陣a以使向量right,up和look分別與世界座標系的x,y,z軸重合
使用3x3矩陣,因為不需要用齊次座標來表示旋轉,在後面的部分中,再將其擴充套件為4x4矩陣
使攝像機各軸與世界座標系各軸重合的變換可用如下矩陣表示:
a = rx ux dx
[ry uy dy ]
rz uz dz
前兩步的整合
將a擴充套件為4x4矩陣,並將取景變換的前兩步整合,得到完整的觀察矩陣 v
rx ux dx 0
ry uy dy 0
v =[ rz uz dz 0 ]
-pr -pu -pd 1
在camera類中,用camera::getviematrix方法來計算觀察矩陣
void camera::getviewmatrix(d3dxmatrix * v)
由於浮點數運算的誤差,攝像機的各向量可能不再是標準正交,所以,每次呼叫該函式時,必須重新根據向量look計算向量up,right以保證三者相互正交,新的正交向量up可由up=look * right得到;新的正交向量right可由right =up * look 計算得到
實現攝像機的旋轉方法時,應使得能夠繞任意軸進行旋轉,
d3dxmatrix *d3dxmatrixrotationaxis(
d3dxmatrix *pout,// returns rotation matrix
const d3dxvector3 *pv,// axis to rotate around
float angle // angle ,in radians to rotate
);例:繞由向量(0.707f,0.707f,0.0f)所確定的軸旋轉∏/2
d3dxmatrix r;
d3dxvector3 axis(0.707f,0.707f,0.0f);
d3dxmatrixrotationaxis(&r,&axis,&d3dx_pi / 2.0f);
由於方向向量描述了攝像機在世界座標系中的朝向,所以當攝像機發生俯仰,偏航或滾動時,必須指定方向向量應如何更新
攝像機發生俯仰時,需要將向量up和look繞著向量right轉動指定的角度,類似地,發生偏航時,需要將向量look和right繞向量up轉動指定的角度,發生翻滾時,需要將向量right和up繞著向量look轉動指定的角度
使用函式d3dxmatrixrotationaxis的必要性,因為確定了旋轉軸的這3個方向在世界座標系中可能會沿著任意方向
方法pitch,yaw和roll的實現也應遵循上述討論中提到的原則,但是還需要對landobjet型別的攝像機增加一些約束
尤其是當乙個地面物體俯仰之後又發生了偏航或滾動,這看起來總有些問題,所以,對於landobject型別的攝像機,應使其繞世界座標系的y軸旋轉而非yaw方法中的up向量,而且完全禁止地面物體,有一點必須清楚,我們可以改變camera類來適應應用程式的不同要求
方法pitch,yaw和roll的實現:
//俯仰
void camera::pitch(float angle)
//偏航
void camera::yaw(float angle)
//滾動
void camera::roll(float angle)
"行走"是指沿著攝像機的觀察方向(即沿著向量look的方向)的平動
'掃視(strafing)'是指保持觀察方向不變,沿向量right方向從一邊平移到另一邊
"公升降(flying)"是指沿著向量up方向的平動
為了能夠沿這些軸中的任意乙個進行平動,只需將攝像機當前位置向量和乙個與該軸方向相同的向量相加即可
像旋轉一樣,也必須給地面物體的運動增加一些約束,例landobject型別的攝像機不應在觀察方向朝下時沿著其up向量公升降或平動,也不應在乙個斜面上進行掃視,所以應將攝像機的運動限制在xz平面上,然後,由於landobject型別的攝像機可以改變其高度(爬樓或爬山),我們提供了camera::setposition方法,使可手工將攝像機指定在乙個合適的高度和位置上
//行走
void camera::walk(float units)
//掃視
void camera::strafe(float units)
//公升降
void camera::fly(float units)
遊戲開發基礎
任何遊戲都需要一些基本框架,用於實現抽象化,並減輕與底層作業系統互動的痛苦。通常這一框架分成幾個模組 用於建立乙個視窗和處理一些操作,如關閉視窗 暫停或恢復android應用程式等。與視窗管理模組相關聯,用於跟蹤使用者的輸入,如觸控事件 按鍵事件 加速計讀取等。android系統中,這些輸入會被排程...
遊戲開發基礎 四
第四章 rgb資料可用兩種不同的結構來儲存,d3dcolor dword型別相同 要指定每個顏色分量值d3dcolor argb d3dcolor xrgb define d3dcolor xrgb r,g,b d3dcolor argb 0xff,r,g,b d3dcolorvalue 結構 該結...
遊戲開發框架基礎
比如,開發第乙個軟體lol killer的思路 第一步 學習c winform程式設計基礎 理解事件驅動的程式設計模型,delegate event,begininovke的用法,圖書館隨便借一本c 教程書應該都有相關的教程。第二步 通過msdn查閱c 獲取系統程序的api,關鍵字搜尋 msdn c...