《3D Math Primer for Graphics and Game Development》读书笔记1

时间:2023-03-09 04:42:12
《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章 笛卡尔坐标系统

左手坐标系的记忆方法

伸出左手,手指依次是())))))Z轴。他们分别对应起来,用左手摆成下图的样子(不错的pose啊),就是左手坐标系。

《3D Math Primer for Graphics and Game Development》读书笔记1

右手坐标系的记忆方法

同上,用右手就行了。

《3D Math Primer for Graphics and Game Development》读书笔记1

约定俗成和习惯

传统的计算机图形学使用左手坐标系,线性代数则倾向于右手坐标系。

两种坐标系没有优劣之分,只是使用习惯不同。

本书使用左手坐标系。

第3章 多坐标系

摄像机坐标系

本书约定的摄像机坐标系,摄像机在原点,X轴向右,Z轴向前,Y轴向上,如下图所示。

《3D Math Primer for Graphics and Game Development》读书笔记1

许多图形学书中习惯使用右手系,Z轴向外,即从屏幕指向读者。

坐标系变换

坐标系变换的意思:知道某一点P在坐标系A中的坐标,如何获取P在另一坐标系B中的坐标?

只需在坐标系A中定位坐标系B(描述B的原点和轴在A中的值)。后文会详述。

包围盒

向量轴对齐包围盒是axially aligned bounding box(AABB)的翻译。我就是觉得包围盒这个翻译很不错。

《3D Math Primer for Graphics and Game Development》读书笔记1

第4章 向量

相对位置

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

向量能描述的是相对位置。相对位置的想法是很直接的:某个物体的位置,能通过描述它与已知点之间的相对关系来指明。

由此引出一个问题,这些"已知"点在哪儿?什么是"绝对"位置?令人吃惊的是不存在这样的东西。因为在描述一个点的位置时,总要描述它和其它一些点的关系。这就没完没了了。

既然"已知"点不存在,那么如何通过所谓的"已知"点来描述位置呢?我的思路是:假设存在一个已知点的位置。假设已经找到了一个已知点,这样就不必无限地去追溯"已知"点了。

相对论的一个重要观点就是不存在绝对参考系。

第5章 向量运算

向量和点的关系

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

向量和点在概念上不同,而在数学上等价。

等价是什么意思?等价就是两者存在一一对应的关系。一一对应是什么意思?就是即使你和我毫不相干,但是你有一个什么东西,我就有一个相应的什么东西;反过来也一样。比如你在照镜子,你看到镜子里的人脸上粘个米粒,就知道自己什么情况了。

向量投影

给定两个向量vn,可以把v分成两部分:v||v。它们分别平行和垂直于n, 并满足v = v|| + v。我们把平行分量v||称作vn上的投影。

《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》读书笔记1

后文会有很多地方用到这两个公式。总之你知道有这两个公式存在就行了,需要的时候拿来用。毕竟不需要做数学家。

第6章 3D向量类

类接口

好的类设计首先要回答下列问题:"这个类将提供什么操作?"、"在哪些数据上执行这些操作?"

《3D Math Primer for Graphics and Game Development》读书笔记1

《3D Math Primer for Graphics and Game Development》读书笔记1

从这些代码和设计思路中就可以感受到作者的认真态度和深厚功底。

设计决策

如果世界不超过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如下:

《3D Math Primer for Graphics and Game Development》读书笔记1

矩阵乘法设计成这样,是因为有实际意义,数学上也有研究价值。或者说,正是因为它反映了现实世界的某些东西,才会有数学意义。

本书给了一种非常好的记忆方法:

《3D Math Primer for Graphics and Game Development》读书笔记1

我扩展了一下,可以将A的各个列拆开,同时将B的各个行拆开:

《3D Math Primer for Graphics and Game Development》读书笔记1

变成下图所示的样子:

《3D Math Primer for Graphics and Game Development》读书笔记1

可以看到,矩阵的乘法运算,可以把A的各列拆开,B的各行拆开,分别运算,最后相加。拆分时,只要A的列和B的行的拆分方式相同即可。

还有另一种拆法:把A的各行拆开,B的各列拆开,分别运算,最后拼起来。

《3D Math Primer for Graphics and Game Development》读书笔记1

而且,还可以同时进行这两种拆分。这时,你可以看做先进行第一种拆分,然后进行第二种拆分,这样(对我来说)比较容易理解。这样就能理解矩阵分块计算的原理。

约定和习惯

本书默认使用行向量进行与矩阵的运算。

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构造矩阵。没什么理由,就这么做了。

《3D Math Primer for Graphics and Game Development》读书笔记1

来看看向量v=(x, y, z)乘以矩阵会出现什么?

《3D Math Primer for Graphics and Game Development》读书笔记1

从左边到第一个等号右边,说明这个乘法运算给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)经过转换,得到的新坐标值是?

《3D Math Primer for Graphics and Game Development》读书笔记1

观察这三个式子,你会发现新的基向量恰好组成了我们需要的转换矩阵。

一般情况下,我们是不能预先得到转换矩阵的。而三个式子就给出了获取转换矩阵的方法。就是说,只要我们能先用别的什么方法求出新的基向量的坐标值,就能拼出转换矩阵,然后就可以从任意一个向量/点的初始坐标值得到其新的坐标值!

总之,矩阵等价于变换后的基向量。

2D示例

比如这个矩阵:

《3D Math Primer for Graphics and Game Development》读书笔记1

这个矩阵代表的变换是什么?

首先,从矩阵中抽出基向量p和q:

《3D Math Primer for Graphics and Game Development》读书笔记1

下图展示了p0=(1, 0), q0=(0, 1)转换到p,q后的样子:

《3D Math Primer for Graphics and Game Development》读书笔记1

加个图片会看起来更直观:

《3D Math Primer for Graphics and Game Development》读书笔记1

“不幸的是,没有人能告诉您矩阵像什么——您必须自己去感受。”