OpenGL基礎變換

第四章 OpenGL基礎變換 向量和矩陣

???????在第三章趾代,我們討論了如何繪制3D點绘搞、線和三角形晌纫。為了將一系列圖形轉(zhuǎn)換到連續(xù)的場景,我們必須將它們相對于其他圖形和觀察者進行排列淤翔。在本章,我們開始學習在坐標系中移動圖形佩谷。

本章內(nèi)容:

  • 什么是向量旁壮,以及為什么要了解它
  • 什么是矩陣,以及為什么要更認真地了解它
  • 我們?nèi)绾问褂镁仃嚭拖蛄縼硪苿訋缀螆D形
  • OpenGL對于模型視圖和投影矩陣的約定
  • 什么是照相機谐檀,以及如何應用它轉(zhuǎn)換
  • 如何將一個點光源位置轉(zhuǎn)換到視點坐標系

一抡谐、3D圖形數(shù)學

???????GLTools庫中有一個組建叫做Math3d,其中包含了大量好用的與OpenGL一致的3D數(shù)學例程和數(shù)據(jù)結(jié)構。
向量:
???????一個頂點是XYZ坐標空間上的一個位置桐猬,同時也是一個向量麦撵。
???????向量指出方向;同時也代表數(shù)量溃肪,一個向量的數(shù)量就是這個向量的長度厦坛。
Math3d庫有兩種數(shù)據(jù)類型:M3DVector3f表示一個三維向量(X,Y乍惊,Z)杜秸;
M3DVector4f表示一個四維向量(X, Y, Z, W)。
???????點乘:兩個單位向量之間的點乘運算將得到一個標量润绎。它表示兩個向量之間的夾角撬碟。要進行這種運算诞挨,兩個向量必須為單位長度。而返回的結(jié)果將在-1和+1之間呢蛤,實際是兩個向量之間夾角的余弦值惶傻。

//返回余弦值
float m3dDotProduct3(const M3DVector3f u, M3DVector3f v);
//返回弧度值
float m3dGetAngleBetweenVetors3(const M3DVector3f u, M3DVector3f v);

???????叉乘:兩個向量之間叉乘所得的結(jié)果是另外一個向量,這個新的向量與原來兩個向量定義的平面垂直其障。叉乘的兩個向量都不必為單位向量银室。兩個向量位置交換叉乘值不同,即叉乘不滿足交換律励翼。

//返回結(jié)果向量
float m3dCrossProduct3(M3DVector3f result, const M3DVector3f u, M3DVector3f v);

矩陣:
???????如果空間中有一點蜈敢,有X,Y汽抚,Z坐標定義抓狭,將它圍繞任意點沿任意方向旋轉(zhuǎn)一定角度后,我們需要知道這個點現(xiàn)在的位置造烁,就要用到矩陣否过。數(shù)學上,矩陣為一組排列在統(tǒng)一的行和列中的數(shù)字惭蟋,用程序設計語言來說就是一個二維數(shù)組苗桂。
3D程序設計中用到的幾乎全是兩種維度的矩陣,即3×3和4×4告组;在math3d庫中有兩種維度的矩陣類型:
???????typedef float M3DMatrix33f[9];
???????typedef float M3DMatrix44f[16];

二誉察、理解變換

視覺坐標:
???????視覺坐標是相對于觀察者的視角而言的,無論可能進行何種變換惹谐,我們都可以將它們視為“絕對的”屏幕坐標持偏。
視圖變換:
???????視圖變換是應用到場景中的第一種變換。對于視覺坐標系而言氨肌,視圖變換移動了當前的工作坐標系鸿秆。所有后續(xù)變換隨后都會基于新調(diào)整的坐標系進行。然后怎囚,在實際開始考慮如何進行這些變換時卿叽,就會更容易地看到這些變換是如何實現(xiàn)的了。
模型變換:
???????模型變換用于操縱模型和其中的特定對象恳守。這些變換將對象移動到需要的位置考婴,然后再對它們進行旋轉(zhuǎn)和縮放。
模型視圖的二元性:
???????實際上催烘,視圖和模型變換按照它們內(nèi)部效果和對場景的最終外觀來說是一樣的沥阱。將這兩者分開純粹是為了程序員的方便。將對象象后移動和將參考系坐標向前移動在視覺上沒有區(qū)別伊群,效果是相同的考杉。視圖變換和模型變換一樣策精,都應用在整個場景中,在場景中的對象常常在進行視圖變換后單獨進行模型變換崇棠。術語“模型視圖”是指這兩種變換在變換管線中進行組合咽袜,成為一個單獨的矩陣,即模型視圖矩陣枕稀。
投影變換:
???????投影變換將在模型視圖變換之后應用到頂點上询刹,這種投影實際上定義了視景體并創(chuàng)建了裁剪平面。投影變換指定一個完成的場景(所有模型變換都已完成)是如何投影到屏幕上的最終圖形萎坷。
???????在正投影中凹联,所有多邊形都是精確地按照指定的相對大小來在屏幕上繪制的。線和多邊形使用平行線來直接映射到2D屏幕上食铐,無論物體位置遠近,都按照相同大小來進行繪制僧鲁。典型情況下虐呻,這個投影用于渲染如屏幕菜單等二維圖像。
???????透視投影所顯示的場景與現(xiàn)實生活中更接近寞秃,透視投影的特點就是透視縮短斟叼,這種特性使得遠處的物體看起來比近處同樣大小的物體更小一些。
視口變換:
???????當上述變換完成時春寿,就得到了一個場景的二維投影朗涩,它將被映射到屏幕上某處的窗口上,這種到物理窗口坐標的映射是我們最后要做的變換绑改,成為視口變換谢床。

矩陣變換:

 /*
 mView: 平移
 mModel: 旋轉(zhuǎn)
 mModelView: 模型視圖
 mModelViewProjection: 模型視圖投影MVP
 */
M3DMatrix44f mView, mModel, mModelView, mModelViewProjection;

//mModel旋轉(zhuǎn)矩陣,繞y軸旋轉(zhuǎn)yRot度
m3dRotationMatrix44(mModel, m3dDegToRad(yRot), 0.0f, 1.0f, 0.0f);

//mView平移矩陣厘线,沿z軸移動-2.5
m3dTranslationMatrix44(mView, 0.0f, 0.0f, -2.5f);

//mModelview = mView * mModel
m3dMatrixMultiply44(mModelview, mView, mModel);

//mModelViewProjection = ProjectionMatrix * mView * mModel
 m3dMatrixMultiply44(mModelViewProjection,
                     viewFrustum.GetProjectionMatrix(),
                     mModelview);

更多對象:
???????GLBatch類识腿,這個類的目的是為了解決容納一個頂點列表并將它們作為一個特定類型的圖元批次來進行渲染。而GLTriangleBatch造壮,這個類是專門作為三角形的容器的渡讼,每個頂點都可以有一個表面法線,已進行光照計算和紋理坐標耳璧。
變換管線:

使用矩陣堆棧:
???????我們在矩陣儲存時可能用到以下實例:

GLMatrixStack       modelViewMatrix;
GLMatrixStack       projectionMatrix;
GLFrame             cameraFrame;
GLFrame             objectFrame;
//其中成箫,cameraFrame用于存儲觀察者矩陣,objectFrame用于存儲模型矩陣旨枯。projectionMatrix只用于存儲投影矩陣蹬昌,我們操作最多的是modelViewMatrix。

//模型矩陣繞世界坐標系y軸旋轉(zhuǎn)-5.0度
objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
//觀察者矩陣向后退15.0,GLFrame中默認的朝向是z軸的負方向;即(0.0, 0.0, -1.0);向前走-15.0攀隔,即(0.0, 0.0, -1.0 * -15.0) = (0.0, 0.0, 15.0)
cameraFrame.MoveForward(-15.0f);渲染過程中矩陣棧操作凳厢,獲取MVP矩陣的計算結(jié)果
//壓棧
modelViewMatrix.PushMatrix();
//獲取觀察者矩陣
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
//棧頂矩陣乘以傳入矩陣账胧,相乘的結(jié)果簡存儲在棧頂
modelViewMatrix.MultMatrix(mCamera);
//獲取模型矩陣
M3DMatrix44f mObjectFrame;
objectFrame.GetMatrix(mObjectFrame);
//由于先乘的觀察者矩陣,現(xiàn)在再乘以模型矩陣
//棧頂 = M_view * M_model
modelViewMatrix.MultMatrix(mObjectFrame);
...
//由于初始化時傳入了先紫,modelViewMatrix和projectionMatrix的引用
//transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
//下面的代碼會計算projectionMatrix * modelViewMatrix
//結(jié)合上面的代碼治泥,等價于M_projection * M_view * M_model
transformPipeline.GetModelViewProjectionMatrix()
...
//出棧
modelViewMatrix.PopMatrix();

???????其中,入棧遮精,是為了保存當前的矩陣棧狀態(tài)居夹;出棧,是為了恢復入棧前的矩陣棧狀態(tài)本冲。這個操作類似于iOS的Core Graphic中context的保存與恢復准脂。
???????//保存
???????void CGContextSaveGState(CGContextRef c);
???????//恢復
???????void CGContextRestoreGState(CGContextRef c);

優(yōu)化矩陣棧操作:
???????不同的實現(xiàn)方式,之前我們用cameraFrame和objectFrame來記錄相機和模型的變化檬洞,用到了兩個對象狸膏。但我們可以固定一個對象,變化另一個對象添怔。例如湾戳,之前的做法需要觀察者向后退,同時物體旋轉(zhuǎn)广料,把變化作用到了兩個物體上砾脑,所以用到了兩個矩陣分別記錄兩個物體的變化,最后再使用矩陣相乘把兩個變化合并起來艾杏。
如果固定一個物體韧衣,那么根據(jù)相對運動,就是把之前兩個物體的變化购桑,相對地作用到另一個物體上畅铭,就可以少用一個矩陣了。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末勃蜘,一起剝皮案震驚了整個濱河市顶瞒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌元旬,老刑警劉巖榴徐,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異匀归,居然都是意外死亡坑资,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門穆端,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袱贮,“玉大人,你說我怎么就攤上這事体啰≡芪。” “怎么了嗽仪?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長柒莉。 經(jīng)常有香客問我闻坚,道長,這世上最難降的妖魔是什么兢孝? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任窿凤,我火速辦了婚禮,結(jié)果婚禮上跨蟹,老公的妹妹穿的比我還像新娘雳殊。我一直安慰自己,他們只是感情好窗轩,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布夯秃。 她就那樣靜靜地躺著,像睡著了一般痢艺。 火紅的嫁衣襯著肌膚如雪仓洼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天腹备,我揣著相機與錄音衬潦,去河邊找鬼斤蔓。 笑死植酥,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的弦牡。 我是一名探鬼主播友驮,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼驾锰!你這毒婦竟也來了卸留?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤椭豫,失蹤者是張志新(化名)和其女友劉穎耻瑟,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赏酥,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡喳整,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了裸扶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片框都。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖呵晨,靈堂內(nèi)的尸體忽然破棺而出魏保,到底是詐尸還是另有隱情熬尺,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布谓罗,位于F島的核電站粱哼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏妥衣。R本人自食惡果不足惜皂吮,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望税手。 院中可真熱鬧蜂筹,春花似錦、人聲如沸芦倒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兵扬。三九已至麻裳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間器钟,已是汗流浹背津坑。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留傲霸,地道東北人疆瑰。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像昙啄,于是被迫代替她去往敵國和親穆役。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容