《3D Math Primer for Graphics and Game Development》讀書筆記1


《3D Math Primer for Graphics and Game Development》讀書筆記1

本文是《3D Math Primer for Graphics and Game Development》第一版的讀書筆記。第二版貌似還沒有中文版。

本書網站gamemath.com。中文版居然給了翻譯公司的網址,而且里面還什么有用的都沒有,囧。

第2章 笛卡爾坐標系統

左手坐標系的記憶方法

伸出左手,手指依次是(1大拇指、(2食指、(3中指;坐標軸按字母表依次是(1X軸、(2Y軸、(3Z軸。他們分別對應起來,用左手擺成下圖的樣子(不錯的pose啊),就是左手坐標系。

右手坐標系的記憶方法

同上,用右手就行了。

約定俗成和習慣

傳統的計算機圖形學使用左手坐標系,線性代數則傾向於右手坐標系。

兩種坐標系沒有優劣之分,只是使用習慣不同。

本書使用左手坐標系。

第3章 多坐標系

攝像機坐標系

本書約定的攝像機坐標系,攝像機在原點,X軸向右,Z軸向前,Y軸向上,如下圖所示。

許多圖形學書中習慣使用右手系,Z軸向外,即從屏幕指向讀者。

坐標系變換

坐標系變換的意思:知道某一點P在坐標系A中的坐標,如何獲取P在另一坐標系B中的坐標?

只需在坐標系A中定位坐標系B(描述B的原點和軸在A中的值)。后文會詳述。

包圍盒

向量軸對齊包圍盒是axially aligned bounding box(AABB)的翻譯。我就是覺得包圍盒這個翻譯很不錯。

第4章 向量

相對位置

"50英里每小時的速度向北"能用向量表示。

向量能描述的是相對位置。相對位置的想法是很直接的:某個物體的位置,能通過描述它與已知點之間的相對關系來指明。

由此引出一個問題,這些"已知"點在哪兒?什么是"絕對"位置?令人吃驚的是不存在這樣的東西。因為在描述一個點的位置時,總要描述它和其它一些點的關系。這就沒完沒了了。

既然"已知"點不存在,那么如何通過所謂的"已知"點來描述位置呢?我的思路是:假設存在一個已知點的位置。假設已經找到了一個已知點,這樣就不必無限地去追溯"已知"點了。

相對論的一個重要觀點就是不存在絕對參考系。

第5章 向量運算

向量和點的關系

向量[x, y]描述了原點到點(x, y)的位移量。

向量和點在概念上不同,而在數學上等價

等價是什么意思?等價就是兩者存在一一對應的關系。一一對應是什么意思?就是即使你和我毫不相干,但是你有一個什么東西,我就有一個相應的什么東西;反過來也一樣。比如你在照鏡子,你看到鏡子里的人臉上粘個米粒,就知道自己什么情況了。

向量投影

給定兩個向量vn,可以把v分成兩部分:v||v。它們分別平行和垂直於n, 並滿足v = v|| + v。我們把平行分量v||稱作vn上的投影。

投影的計算公式:

垂直分量的公式:

后文會有很多地方用到這兩個公式。總之你知道有這兩個公式存在就行了,需要的時候拿來用。畢竟不需要做數學家。

第6章 3D向量類

類接口

好的類設計首先要回答下列問題:"這個類將提供什么操作?"、"在哪些數據上執行這些操作?"

從這些代碼和設計思路中就可以感受到作者的認真態度和深厚功底。

設計決策

如果世界不超過1英里,那么32位的float類型就足夠,因為24位尾數能提供1/250英寸的精度。

如果世界超過200英里(321.8688千米),比如整個江蘇省,那么32位float就不夠了。

不存在Point3類

有了Vector3類,就不需要Point3類。避免重復代碼以及滿世界的向量與點的轉換。

關於優化

過早的優化是一切罪惡的根源。優化那些非瓶頸的代碼,使代碼復雜化,卻沒有得到相應的回報。

在過去,定點數是一種優化技術。當今的處理器已經可以快速處理浮點數,這個技術就不需要了。

不要為了2%的優化付出100%的代碼復雜性。

簡單點說,就是別優化,我的技術水平沒那么高。

第7章 矩陣

矩陣用來描述兩個坐標系間的關系,通過定義一種運算來將一個坐標系中的向量/點轉換到另一個坐標系中。換句話說,就是已知一個向量/點在坐標系A中的坐標,又知坐標系A和坐標系B的關系,求其在坐標系B中的坐標。

向量是標量的數組,矩陣是向量的數組。

矩陣的下標從1開始。

矩陣乘法

記r×n矩陣A與n×c矩陣B的乘積為CC的任意元素Cij如下:

矩陣乘法設計成這樣,是因為有實際意義,數學上也有研究價值。或者說,正是因為它反映了現實世界的某些東西,才會有數學意義。

本書給了一種非常好的記憶方法:

我擴展了一下,可以將A的各個列拆開,同時將B的各個行拆開:

變成下圖所示的樣子:

可以看到,矩陣的乘法運算,可以把A的各列拆開,B的各行拆開,分別運算,最后相加。拆分時,只要A的列和B的行的拆分方式相同即可。

還有另一種拆法:把A的各行拆開,B的各列拆開,分別運算,最后拼起來。

而且,還可以同時進行這兩種拆分。這時,你可以看做先進行第一種拆分,然后進行第二種拆分,這樣(對我來說)比較容易理解。這樣就能理解矩陣分塊計算的原理。

約定和習慣

本書默認使用行向量進行與矩陣的運算。

DirectX使用的是行向量。

OpenGL使用的是列向量。

線性變換

線性變換保留了模型中原有的直線和平行線,原點也保持不動。長度、角度、體積可能會改變。從非技術意義上說,線性變換可能"拉伸"坐標系,但不會"彎曲"或"卷折"坐標系。

旋轉、縮放、投影、鏡像是線性變換。

仿射(線性變換后平移)不是線性變換。

方陣能描述線性變換。

矩陣運算和3D變換

設有一組基向量p0=(1, 0, 0),q0=(0, 1, 0),r0=(0, 0, 1),此時向量v=(x, y, z)就是vp0=(1, 0, 0),q0=(0, 1, 0),r0=(0, 0, 1)這個坐標系里的坐標,即有v = xp0 + yq0 + zr0

pqr為任意一組基向量。例如p=(1, 0, 0),q=(0, 1, 0),r=(0, 0, 1)(互相垂直);或p=(0.8, 0.6, 0),q=(-0.6, 0.8, 0),r=(0, 0, 1) (互相垂直);或p=(1/√5)(2,-1,0)q= (1/√45)(2,4,5)r= (1/3)(1,2,-2) (互相垂直)或p=(1, 1, 1-√2 ),q=(1-√2, 1, 1),r=(1, 1-√2, 1)(並非互相垂直)……

然后,我們用pqr構造矩陣。沒什么理由,就這么做了。

來看看向量v=(x, y, z)乘以矩陣會出現什么?

從左邊到第一個等號右邊,說明這個乘法運算給v賦予了新的坐標值。廢話。

從第一個等號右邊到第二個等號右邊,說明這個新的坐標值與基向量pqr的關系等同於v與原始基向量p0=(1, 0, 0),q0=(0, 1, 0),r0=(0, 0, 1)的關系,這就是新坐標值的意義所在。

這也是矩陣乘法設計成這樣的價值所在。

所以,把3×3矩陣M的3行看做轉換后的3個基向量,那么任意一個1×3的行向量v乘以M,就得到了v轉換后的坐標。這就是說,乘以該矩陣就相當於執行了一次坐標轉換。若有aM=b,我們就可以說,Ma轉換到b

如何建立需要的矩陣?

上一節說明了,3×3矩陣的每一行都能解釋為轉換后的基向量。初始坐標系中的向量/點經過轉換,得到了各自新的坐標值。那么,初始坐標系中的基向量p0=(1, 0, 0),q0=(0, 1, 0),r0=(0, 0, 1)經過轉換,得到的新坐標值是?

觀察這三個式子,你會發現新的基向量恰好組成了我們需要的轉換矩陣。

一般情況下,我們是不能預先得到轉換矩陣的。而三個式子就給出了獲取轉換矩陣的方法。就是說,只要我們能先用別的什么方法求出新的基向量的坐標值,就能拼出轉換矩陣,然后就可以從任意一個向量/點的初始坐標值得到其新的坐標值!

總之,矩陣等價於變換后的基向量。

2D示例

比如這個矩陣:

這個矩陣代表的變換是什么?

首先,從矩陣中抽出基向量p和q:

下圖展示了p0=(1, 0), q0=(0, 1)轉換到p,q后的樣子:

加個圖片會看起來更直觀:

“不幸的是,沒有人能告訴您矩陣像什么——您必須自己去感受。”


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM