人物10457 項目5215 室內592 家居及產品164 文章2393 方案1386 攝影788 視頻225 圖書201 讀者來稿 最新評論21,730 所有作品11439 所有圖片156,207
變換矩陣與投影
這篇《變換矩陣與投影》是編者對文章后面所列的參考文章,以編者的理解能力的匯總及解讀,帶著大家進入一個計算機圖形學如何把3D物體展示在2D屏幕上的旅程。
來源:馬海東

The engines don’t move the ship at all. The ship stays where it is and the engines move the universe around it.

– Futurama

 

編輯: 馬海東

編者按: 這篇《變換矩陣與投影》是編者對文章后面所列的參考文章,以編者的理解能力的匯總及解讀.帶著大家進入一個計算機圖形學如何把3D物體展示在2D屏幕上的旅程.

在展開整個旅程之前,我先講一個簡單的案例來通俗的說明矩陣相乘意味著什么意思?

 

一個簡單的矩陣相乘的例子

當地商店賣3種餡餅。當地商店賣三種餡餅。

● 蘋果派每塊3元

●?櫻桃派每塊4元

●?藍莓派每塊2元

而這是他們3天賣出的數量。

 

 

現在想想……周一的銷售價值是這樣計算的。

蘋果派的價值+櫻桃派的價值+藍莓派的價值= $3×13 + $4×8 + $2×6 = $83

我們把價格和賣出的數量進行匹配,分別乘以每一個價格,然后將結果相加。

●?周一: 3×13+4×8+2×6=83元。

●?周二:3×9+4×7+2×4 =63元。

●?周三:3×7+4×4+2×0 =37元。

其中每一個價格與每一個數量的匹配很重要。

而這里是矩陣形式的完整結果。

 

 

向量空間、齊次坐標與矩陣

向量空間: 或者坐標體系, 一種數學結構,它是由給定數量的線性獨立向量定義的,也稱為基向量;線性獨立向量的數量決定了向量空間的大小,因此一個3D空間有三個基向量(圖1),而一個2D空間有兩個。這些基向量可以被縮放和相加來獲得空間中的所有其他向量。

 

圖1:標準右手三維坐標系統

 

todo: 圖片, 空間中其他向量的表示

齊次坐標: 通常在計算機圖形學中我們為了可以同時描述歐式空間及投影空間,我們還會引入齊次坐標(x,y,z,w), 來表示3維向量空間:

如果 w == 1, 那么向量 (x,y,z,1) 是3維空間中的一個位置.

如果 w == 0,那么向量(x,y,z,0)是3維空間中一個方向。

 

 

w等于或不等于0有什么不同嗎?對于旋轉來說,它沒有任何改變。當你旋轉一個點或一個方向時,你會得到同樣的結果。然而,對于平移(當你把點向某個方向移動時),事情就不同了。平移一個方向是什么意思? 沒有任何意義。

4×4矩陣: 此外為了能在各種向量空間之間進行變換, 我們會使用(x,y,z,w)齊次坐標與4X4矩陣相乘進行變換。

[Matrix] x [Vertex] = [TransformedVertex]

通過以上這些數學元素,我們就可以把3D幾何體展示在2D顯示器上了.

它們依次經過從模型空間到世界空間的變換, 再從世界空間到視圖空間的變換, 再從視圖空間到投影空間的變換. 最終從投影空間變換顯示到2D的顯示器上.

 

 

模型空間->世界空間

我們將3D模型存在的向量空間叫做模型空間(Model Space),它用標準的右手三維坐標系來表示(圖1)。

當一個設計師創作一個3D模型時,他創建的所有頂點和面都是相對于他所使用的三維坐標系(模型空間)。 如我們說一個點的坐標是(1,1,1),其中的數值是相對于其坐標系的原點而言的(圖2).

場景中每一個模型在創建的時候都有自己的模型空間,如果你想讓它們存在于任何空間關系中(比如你想把一個茶壺放在桌子上),你需要把它們轉化為一個共同的空間體系(這就是通常指的世界空間)。

 

圖2:茶壺的頂點在位置(1,1,1)。

 

現在,如果我們想把模型放到場景中,我們需要移動它和/或旋轉它到所需的位置。移動、旋轉或縮放一個模型,這就是我們所說的變換。當所有的對象都被轉化為世界空間時,它們的頂點將相對于世界空間。

 

空間變換

我們可以把向量空間的變換簡單地看成是從一個空間到另一個空間的轉換。

我們可以把三維中的向量空間想象成三個正交軸(如圖1), 也就是我們用來作為其他一切物體(無論是幾何體還是其他空間)的參考空間。

重點來了:

現在假設我們從一個”參照”空間開始,稱它為空間A,其中包含一個茶壺?,F在我們想應用一個變換,將空間A中的所有東西移動到一個新的位置;但如果我們移動空間A,我們就需要定義一個新的”參照”空間來表示變換后的空間A,讓我們稱這個新的參照空間為空間B(圖3)。在變換之前,空間A中描述的任何點,都是相對于該空間的原點而言的(如左圖3所述)。在我們應用了變換之后,現在所有的點都是相對于新的參照空間空間B(圖3右)。

任何將空間A相對于空間B重新定義的操作都是一種變換。 請注意,在變換之后,空間A現在”消失”了,變成了空間B,或者更準確地說,它被重新映射到了空間B,所以我們沒有辦法對它進行任何其他的變換。

當我們應用變換時,我們將空間A向空間B移動,同時空間A中的任何東西也會隨之移動。一旦我們移動了所有的頂點,這意味著所有的頂點表示為相對于空間B,我們就完成了變換。

如果我們需要再次在空間A中進行操作,可以對空間B進行逆向變換,這樣做的話, 空間B將再次被重新映射到空間A中(此時,我們”舍棄”空間B)。如果我們知道這兩個變換和它們的逆,我們總是可以將兩個空間一一重新映射。

 

圖3:空間變換

 

我們可以在向量空間中使用的變換通常有縮放、平移和旋轉。

需要注意的是,每一次變換總是相對于原點的,這使得我們使用變換本身的順序非常重要。如果我們先向左旋轉90°,然后再平移,我們得到的東西與先平移再旋轉90°的結果非常不同(圖4)。

 

圖4:同樣的變換應用于不同順序的不同結果。

 

變換矩陣

現在我們明白了變換是從一個空間到另一個空間的變化.

為了應用變換,我們必須將所有要變換的向量(齊次坐標)與變換矩陣相乘。如果向量在空間A中,而變換是描述空間A相對于空間B的新位置,那么在乘法后,所有的向量就會被描述在空間B中。

現在,讓我們看看如何用矩陣形式來表示一個通用的變換。

 

 

●?其中Transform_XAxis是新空間中的XAxis方向

●?Transform_YAxis是新空間中的YAxis方向

●?Transform_ZAxis是新空間中的ZAxis方向

●?Translation是描述新空間相對于活動空間的位置。

有時我們想做簡單的變換,比如平移或旋轉;在這些情況下,我們可以使用以下矩陣,它們是我們剛才介紹的通用形式的特殊情況。

平移矩陣:

 

 

其中translation是一個3D向量,代表我們要移動空間的位置。

一個平移矩陣的xyz軸與之前的參照空間完全相同。

縮放矩陣:

 

 

其中scale是一個3D向量,代表每個軸的比例。如果你讀了第一列,你可以看到新的X軸它仍然朝向同一個方向,但它被scale.x縮放了。同樣的情況也發生在所有其他軸上。另外,請注意平移列全部被設置為零,這意味著不需要平移。

圍繞X軸的旋轉矩陣:

 

 

其中θ是我們想要用來旋轉的角度。請注意第一列將永遠不會改變,這是我們所期望的,因為我們是圍繞X軸旋轉的。另外,請注意將θ改為90°后,Y軸將重構為Z軸,Z軸將重構為-Y軸。

圍繞Y軸的旋轉矩陣:

 

 

圍繞Z軸的旋轉矩陣

 

 

Z軸和Y軸的旋轉矩陣與X軸矩陣的行為方式相同。

我剛才向你介紹的矩陣是最常用的矩陣。您可以通過將矩陣一個接一個地相乘,將幾個變換連接在一起。其結果將是一個包含了所有變換的單一矩陣。

正如我們在變換部分所看到的,我們用來應用變換的順序是非常重要的。在數學中,矩陣乘法不能互換的事實也反映了這一點。因此在一般情況下,Translate x Rotate與Rotate x Translate 是不同的。

變換矩陣相乘的次序是從右到左,所以如果我們想圍繞Y軸向左旋轉90°,然后沿著Z軸平移10個單位,其結果是:

[沿Z平移10]x[RotateY 90°]=[ComposedTransformation]。

 

一個變換矩陣的例子

讓我們把一些數值放入矩陣其中,看看它是如何工作的。

假設我們想變換圖5中的球體。為了簡單起見,我們將只對球體的頂部頂點進行變換,它在模型空間中的位置是(0,1,0)。我們將計算它在世界空間中的位置。首先我們定義變換矩陣。假設我們要將球體放置在世界空間中,它將圍繞 Y 軸順時針旋轉 90°,然后圍繞 X 軸旋轉 180°,然后平移(1.5,1,1.5)。

這意味著變換矩陣將是:

 

 

請注意,結果矩陣完全符合我們所介紹的通用變換公式。在世界空間中,X軸現在的方向是該空間的Z軸,因此現在是(0,0,1)。Y軸現在是倒置的,因此是(0,-1,0)。Z軸現在作為X軸的方向,(1,0,0)。最后,平移向量(1.5,1,1.5)。

一旦我們有了結果,我們可以乘以球體的任何頂點,將其從模型空間變為世界空間。讓我們對頂點(0,1,0)進行變換。

 

 

圖5:從模型空間轉換到世界空間的球體

 

世界空間->視圖空間

當所有的物體都在正確位置的位置之后,我們現在要考慮如何將它們投影到屏幕上。這通常分兩步完成。

●?第一步將所有對象變換到另一個空間,稱為”視圖空間”或者”相機空間”。

●?第二步是使用投影矩陣進行實際的投影。

為什么我們需要一個視圖空間?視圖空間是一個輔助空間,我們用它來簡化數學運算,讓一切都保持優雅,并簡化為矩陣。

視圖空間的定義: 默認狀態下的攝影機設定為以相機原點為中心,負Z軸與相機的目標對齊。

 

圖8:左邊是世界空間中的兩個茶壺和一個攝像頭;右邊是所有的東西都被轉化到視圖空間中(世界空間的標識只是為了可視化空間轉換)

 

 

視圖空間->投影空間

現在場景已經在我們的視線范圍之內,要做的就是把它投影到攝像機的2D屏幕上。在扁平化圖像之前,我們還需要變換到投影空間。

投影空間: 這個空間是一個立方體,每個軸的尺寸都在-1和1之間。這個空間對于計算機圖形學上對圖像顯示的剪裁來說非常方便( 1,-1范圍外的任何東西都在攝像機的視圖區域之外, 可以不用被顯示),并且簡化了扁平化操作(我們只需要舍棄z值就可以得到2D圖像)。

要從視圖空間變換到投影空間,我們需要另一個矩陣,即視圖到投影矩陣,這個矩陣的值取決于我們要執行的投影類型。最常用的兩種投影是正交投影和透視投影。

要進行正交投影,我們必須定義攝像機能看到的區域大小。這通常用x軸和y軸的寬度和高度值,以及z軸的遠近z值來定義(圖9)。

 

圖9:正交投影

 

給定了這些值之后,我們可以創建變換矩陣,將箱體區域重映射到立方體中。下面的矩陣是將View Space中的向量轉換為Ortho Projected Space。

 

 

圖10:從圖9中的茶壺得到的投影空間。

 

另一種投影是透視投影。其思想與正交投影類似,但這次的視圖區域是一個frustum.

 

 

 

圖11:透視投影

 

投影空間->屏幕空間

最后一步, 將所有從-1到1的范圍重新映射到0到1的范圍,然后將其縮放到視口寬度和高度,并將三角形柵格化到屏幕。

公式: [View To Projection]x[World To View]x[Model to World]=[ModelViewProjectionMatrix]。

reference

●?http://www.opengl-tutorial.org

●?http://www.codinglabs.net/article_world_view_projection_matrix.aspx

●?http://ogldev.org/index.html

●?https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/projection-matrix-introduction

●?https://www.mathsisfun.com/algebra/matrix-multiplying.html

●?https://jsantell.com/model-view-projection

 

相關文章

●?建筑師為什么要會python編程?

●?Caad4Rhino:建筑繪圖工具插件

●?Rhino及Bob McNeel的故事(轉載)

●?計算機曲線spline簡史(轉載)

●?漫談算法設計(computational design)與腳本語言(grasshopper, python)

●?算法: 平面圖自動生成(轉載)

●?什么是齊次坐標?

 

建筑師編程課推廣

ikuku精選課 Python4Rhino 建筑師編程課 2020.11.15開始線上直播!講師:馬海東

 

Lenka maurizio 等2人贊過
2020.10.10
請帖個標簽,寫個點評吧!
標簽(多個標簽用逗號隔開) 登錄可保存標簽
綁定新浪微博可評論

小貼士


標簽收藏可以有利于您以后的內容分類管理
->進入收藏管理頁。


blog comments powered by Disqus
娱网棋牌游戏大厅下载 0422公牛vs小牛 棋牌开发公司的套路 广东快乐十分是正规彩票嘛 青海快3下载 安徽麻将浪牌怎么打 十大正规游戏平台排行榜 浙江体彩6 1开奖 上海11选五开奖遗漏 一肖中特王中王选 东北麻将下载安卓下载 移动棋牌验证码 单机福州麻将下载 上期开特下期必开16码 山东十一选五走走势图 海王捕鱼手机版 三国名人单机麻将