《Fundamentals of Computer Graphics》第五版 第二章 各种数学

287 阅读3分钟

很多时候,图形学就是将数学翻译成代码。数学越简洁,代码就越简洁。本章将回顾各种数学工具,涵盖高中和大学,但不做严格处理,而是强调几何直觉。线性代数的内容到第六章再做介绍。

集合与映射

映射,或函数,是数学和编程的基础。数学中的映射,接收一个某种类型的参数,然后将它映为某种类型的对象。程序中的类型在数学中用集合表示

集合、映射、逆映射、区间(intervals)、对数(logarithms)等相关内容可参考高中数学教材。

二次(quadratic)方程求解

二次方程:

Ax2+Bx+C=0Ax^{2} + Bx + C = 0

求根公式如下:

x=B±B24AC2Ax = \frac{-B\pm\sqrt{B^{2} - 4AC}}{2A}

程序中可先计算判别式(discriminant),再根据判别式的正负决定是否需要开方。求根公式还有另一种更健壮的形式:

x=2CBB24ACx = \frac{2C}{-B\mp\sqrt{B^2 - 4AC}}

使用该公式,可根据一次项系数的正负计算出其中一个根,而无需考虑二次项系数是否为 00

三角学(trigonometry)

角(angles)

来自同一源点的两条射线构成一个角,角的大小由射线在单位圆上所截弧长决定。这种度量方式称为弧度(radians),它可以和角度(degrees)互相转换。由于两条射线将平面分割成了两个部分,因此需要约定哪一部分才是所定义的角。一种常见的约定是,取较小的那段弧长作为角的大小,射线的声明顺序决定角的正负。这种约定下,所有的角都在区间 [π,π][-\pi, \pi] 上。

三角函数

函数 atan2(s,c)\mathrm{atan2}(s, c) 在图形学中很常用,它的返回值是坐标为 (c,s)(c, s) 的点的辐角主值。

逆时针为角的正方向。

三角函数相关内容可参考中学数学教材。

立体角(solid angles)和球面三角学(spherical trigonometry)

三角形可以定义在曲面上,如球面。球面三角形(spherical triangles)以大圆(great circles)弧为边,对这种三角形的研究称为球面三角学

对于计算机图形学,更重要的是立体角(solid angles)。物体相对于原点所占据的视场范围就是它的立体角。立体角在单位球面上所围成的面积就是它的球面度(steradians)。

向量(vector)

向量是一种具有大小和方向的量。有时在程序中,向量需要用数字表示,但即便如此,它们也应该被当做对象来使用,只有底层的向量操作才需要知道相关的数值表示。

向量可以存储偏移(offset)——也称位移(displacement),也可以存储位置(location/position/point)。位置可以用另一个位置加上一个位移来表示。通常约定一个原点,所有位置可以存储为相对于原点的偏移。位置不是向量,也不是偏移,它只是可以用向量或偏移来存储;偏移也不是位置。

常用的向量间乘法有点乘(dot product)、叉乘(cross product)。

  1. 点乘常用于计算两向量夹角余弦,也可用于计算一个向量对另一个向量的投影;
  2. 叉乘通常仅用于三维向量。

向量叉乘通常不满足结合律 a×(b×c)(a×b)×c\vec{a} \times (\vec{b} \times \vec{c}) \neq (\vec{a} \times \vec{b}) \times \vec{c}

向量相关的数学知识可参考高中数学教材。

正交基(orthonormal bases)与坐标系(coordinate frames)

管理坐标系是图形程序的核心任务之一,其中的关键在于管理正交基。图形学中定义了两种坐标系:规范坐标系(canonical coordinate system)和参照标架(frame of reference)——也称坐标标架(coordinate frame)。

这里将 canonical 翻译为规范,原因是书中曾提到 “The word 'canonical' crops up again——it means something arbitrarily chosen for convenience.”。

规范坐标系最特殊,它的原点和正交基不予存储,程序中用它做底层表示。由于全局模型通常存储在规范坐标系中,因此规范坐标系也称为全局坐标系(global coordinate system)或世界坐标系(world coordinate system)。

除规范坐标系以外,其它的坐标系均称为参照标架,它们的原点和正交基必须显式存储。坐标系可以固连到某一物体上,这样的参照标架也称为局部坐标系(local coordinate system)。

规范坐标系、参照标架和局部坐标系就是理论力学中的定系、动系和固系。

规范坐标系和参照标架中的坐标可以利用以下两点进行转换:

  1. 两坐标系的正交基之间的关系
  2. 坐标就是矢量对正交基的投影

构造正交基

根据单个向量构造正交基

根据单个向量 a\vec{a} 构造一组正交基 u\vec{u}v\vec{v}w\vec{w},使得 w\vec{w}a\vec{a} 平行。这种情形下,我们并不关心 u\vec{u}v\vec{v} 的方向,一个典型的应用场景是表面着色,在这一场景中,我们只关注法向量。下面是构造正交基的具体步骤:

  1. 首先,构造单位向量 w=a/a\vec{w} = \vec{a} / \|\vec{a}\|
  2. 然后,选取与 w\vec{w} 不共线的向量 t\vec{t},构造与 w\vec{w} 垂直的单位向量 u=t×w/t×w\vec{u} = \vec{t} \times \vec{w} / \|\vec{t} \times \vec{w}\|
  3. 构造 v=w×u\vec{v} = \vec{w} \times \vec{u}

上面第二步中,如果向量 t\vec{t}w\vec{w} 近平行,则会出现精度问题。解决该问题的一个简单方法是,将 w\vec{w} 中绝对值最小的分量改为 11,其余分量保持不变从而构成向量 t\vec{t}。易知,这种方法所得到的 t×w\|\vec{t} \times \vec{w}\| 取值范围:[2(31)/3,33/4][0.345,1.299][\sqrt{2}(\sqrt{3}-1) / 3, 3\sqrt{3}/4] \approx [0.345, 1.299]

根据两个向量构造正交基

有时候,我们关心正交基 u\vec{u}v\vec{v} 的取向,如:为相机(camera)建立一个标架。确定一个标架的常用方法是提供两个向量 a\vec{a}b\vec{b}。这种情况下,上面处理单向量的方法也是可取的:

{w=aau=b×wb×wv=w×u\left\{ \begin{aligned} \vec{w} &= \frac{\vec{a}}{\|\vec{a}\|} \\ \vec{u} &= \frac{\vec{b} \times \vec{w}}{\|\vec{b} \times \vec{w}\|} \\ \vec{v} &= \vec{w} \times \vec{u} \\ \end{aligned} \right.

上述公式适用于一般情形,只要 a\vec{a}b\vec{b} 不平行。对于 a\vec{a}b\vec{b} 不垂直的情形,所得出的 v\vec{v} 是所有与 a\vec{a} 垂直的向量中离 b\vec{b} 最近的。

摆正(squaring up)正交基

有时候,计算机的舍入误差(rounding error)或正交基存储的精度过低可能会引起一些问题。为了解决这些问题,可以使用上面的方法把原始向量基中的 w\vec{w}v\vec{v} 分别当作 a\vec{a}b\vec{b} 重新生成一组新的正交基。然而,这种正交化方法是不对称的,w\vec{w} 优先级高于 v\vec{v}v\vec{v} 优先级高于 u\vec{u}。也可以使用 SVD(Singular Value Decomposition,奇异值分解)对原始向量基正交化。

积分(integration)

图形学中大多数积分都无法解析求解,因此需要数值积分。真正需要的不是手算积分,而是明白积分的含义以便于数值求解。积分可能有多种形式,但它们都有:

  1. 被积函数
  2. 积分区域

这两部分通常作为参数传入 integrate 函数中:

float area = integrate(cos(), unit-sphere)

图形学中的积分常用于计算平均(average)以及加权平均(weighted average)。有时也会涉及对立体角积分,比如,物体表面的颜色通常与入射光颜色(incident colors)的加权平均有关。

float averageElevation = integrate(elevation(), country) / integrate(1, country)
float shade = integrate(cos() * f(), unit-hemisphere) / integrate(cos(), unit-hemisphere)

积分相关内容可参考高等数学教材。

密度函数(density function)

图形学中经常出现密度函数。密度是一种强度量(intensive quantity),而非广延量(extensive quantity)。一般意义上,密度是单位度量下的广延量。图形学中使用的度量不仅限于空间,还可以是时间、立体角等。也就是说,在图形学中,物理量的速率——单位时间内的物理量,如功率,也可以作为密度。

热力学统计物理中,广延量是与物质数量成正比的物理量,这里的广延量和强度量可以看作是相关概念的推广。

密度函数具有以下两点特征:

  1. 密度是某种比值,即单位 Y 内 X 的量
  2. 密度函数是一种返回值为密度的函数

密度函数的用处:

  1. 比较不同位置的浓度
  2. 计算一个区域内的总量

图形学中很多积分都涉及密度函数。

曲线(curves)与曲面(surfaces)

曲线和曲面在图形学中占据核心地位。

下面将 2D 空间中的曲线简称为 2D 曲线,3D 曲面、3D 曲线等术语的含义类似。

梯度(gradient)

以二元函数为例,高度场 f(x,y)f(x, y)梯度定义如下:

f=(fx,fy)\nabla f = \left(\frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}\right)

梯度方向是增速最快的方向,梯度大小是该方向的增速。梯度在隐式曲线 f(x,y)=0f(x, y) = 0 上的取值,就是曲线上该点的法向量(normal vector),与曲线上该点的切向量(tangent vector)垂直,方向指向 f>0f > 0 的区域。

梯度、偏导的具体内容可参考高等数学教材。

隐式方程(implicit equation)

隐式方程是一种常用的描述曲线的方式。

2D 曲线

2D 曲线的隐式方程具有如下形式:

f(x,y)=0f(x, y) = 0

该方程可以看作高度场(height field)z=f(x,y)z = f(x, y)xoyxoy 平面上的截线。之所以称为“隐式”,是因为曲线上的点没有在方程中直接表示出来,必须解方程才能得到。

2D 曲线把整个平面分成三个区域:f>0f > 0f<0f < 0f=0f = 0。因此,通过计算 ff 可以知道点和曲线间的方位关系,如内外、上下等。这一关系通过高度场可以更加明显地看出来。

曲线的隐式方程也可以用向量来表示,比如圆的方程:

pcr=0\| \vec{p} - \vec{c} \| - r = 0

一个方程的向量形式通常蕴含着更加丰富的几何直觉。而面向向量(vector-oriented)的方程在代码实现上也更少出错,比如:涉及 xxyyzz 复制粘贴的错误直接消失了。

2D 直线的斜截式(slope-intercept):

y=mx+by = mx + b

一般式

Ax+By+C=0Ax + By + C = 0

给定直线上两点 (x0,y0)(x_{0}, y_{0})(x1,y1)(x_{1}, y_{1}),直线的一般式:

(y0y1)x+(x1x0)y+x0y1x1y0=0(y_{0} - y_{1})x + (x_{1} - x_{0})y + x_{0}y_{1} - x_{1}y_{0} = 0

(a,b)(a, b) 到直线 f(x,y)=Ax+By+C=0f(x, y) = Ax + By + C = 0有符号距离(signed distance)为:

f(a,b)A2+B2\frac{f(a, b)}{\sqrt{A^{2} + B^{2}}}

2D 隐式二次曲线(implicit quadric curves)方程如下:

Ax2+Bxy+Cy2+Dx+Ey+F=0Ax^{2} + Bxy + Cy^{2} + Dx + Ey + F = 0

上式可以描述的曲线有:椭圆(ellipses)、双曲线(hyperbolas)、抛物线(parabolas)、圆(circles)、直线(lines)。

其它形式的直线方程、二次曲线相关内容可参考高中数学教材。

3D 曲面与 3D 曲线

3D 曲面的隐式方程及其向量形式:

f(p)=f(x,y,z)=0f(\vec{p}) = f(x, y, z) = 0

其中,p=(x,y,z)\vec{p} = (x, y, z)。计算 f(x,y,z)f(x, y, z) 可以知道点 p\vec{p} 是否在曲面上,或者根据符号判断在曲面的哪一侧。

曲面上任一点法向量可以通过隐函数的梯度来得到:

n=f(p)=(fx,fy,fz)\vec{n} = \nabla f(\vec{p}) = \left(\frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}, \frac{\partial f}{\partial z}\right)

该向量指向 f(p)>0f(\vec{p}) > 0 的区域,该区域和曲面之间的方位关系(如内外、上下等)需结合具体情况来分析。

3D 平面的点法式方程如下:

(pa)n=0(\vec{p} - \vec{a})\cdot\vec{n} = 0

其中,n\vec{n} 是法向量,a\vec{a} 是平面上给定的一个点。

a\vec{a}b\vec{b}c\vec{c} 三点的平面隐式方程如下:

(pa)((ba)×(ca))=0(\vec{p} - \vec{a})\cdot((\vec{b} - \vec{a}) \times (\vec{c} - \vec{a})) = 0

上式的几何意义是,由 pa\vec{p} - \vec{a}ba\vec{b} - \vec{a}ca\vec{c} - \vec{a} 所构成的平行六面体(parallelepiped)体积为 00,或者说三个向量共面(coplanar)。该式也等价于下面的行列式:

xxayyazzaxbxaybyazbzaxcxaycyazcza=0\begin{vmatrix} x - x_{a} & y - y_{a} & z - z_{a} \\ x_{b} - x_{a} & y_{b} - y_{a} & z_{b} - z_{a} \\ x_{c} - x_{a} & y_{c} - y_{a} & z_{c} - z_{a} \\ \end{vmatrix} = 0

其中,p=(x,y,z)\vec{p} = (x, y, z)。若存在封装完好的关于向量的 determinant(a,b,c)\mathrm{determinant}(\vec{a}, \vec{b}, \vec{c}) 函数(或命名为 volume\mathrm{volume}),使用上式也可以避免笔误。唯独使用 xxyyzz 的展开式编程是最不可取的。数学的简洁性决定了代码的简洁性

与 2D 情形类似,关于 xxyyzz 的二次多项式定义了 3D 二次曲面。如球面:

f(p)=(pc)2r2=0f(\vec{p}) = (\vec{p} - \vec{c})^{2} - r^{2} = 0

形式 f(p)=0f(\vec{p}) = 0 的方程能产生的 3D 曲线都只是退化曲面(degenerate surfaces),实践中很少使用。3D 曲线一般表示为两个 3D 曲面的交线:

{f(p)=0g(p)=0\left\{ \begin{aligned} f(\vec{p}) = 0 \\ g(\vec{p}) = 0 \end{aligned} \right.

参数方程

2D 曲线

2D 参数曲线(parametric curves)方程如下:

[xy]=[g(t)h(t)]\begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} g(t) \\ h(t) \end{bmatrix}

其中,tt 是决定整条曲线的参数,(x,y)(x, y) 是曲线上的点。参数方程的向量形式如下:

p=f(t)\vec{p} = \vec{f}(t)

其中,f:RR2\vec{f}: \mathbb{R}\mapsto\mathbb{R}^{2} 是向量值函数。对 f(t)\vec{f}(t) 求导可以得到曲线的切向量。讨论参数曲线时,通常会把 tt 看作时间,把曲线看作轨迹。

过点 p0=(x0,y0)\vec{p_{0}} = (x_{0}, y_{0})p1=(x1,y1)\vec{p_{1}} = (x_{1}, y_{1}) 的 2D 直线参数方程:

[xy]=[x0+t(x1x0)y0+t(y1y0)]\begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} x_{0} + t(x_{1} - x_{0}) \\ y_{0} + t(y_{1} - y_{0}) \end{bmatrix}

等价的向量形式为:

p(t)=p0+t(p1p0)\vec{p}(t) = \vec{p_{0}} + t(\vec{p_{1}} - \vec{p_{0}})

其中,p=(x,y)\vec{p} = (x, y)。参数 tt 的取值决定了点 p\vec{p} 的位置:

t<0p0 以外0<t<1p0 与 p1 之间t>1p1 以外\begin{aligned} t < 0 &\Leftrightarrow \vec{p_{0}}\ 以外 \\ 0 < t < 1 &\Leftrightarrow \vec{p_{0}}\ 与\ \vec{p_{1}}\ 之间 \\ t > 1 &\Leftrightarrow \vec{p_{1}}\ 以外 \end{aligned}

参数直线也可以由一个点 o\vec{o} 和一个向量 d\vec{d} 来描述:

p(t)=o+td\vec{p}(t) = \vec{o} + t\vec{d}

d\vec{d} 的长度为 11 时,直线是弧长参数化的(arc-length parameterized)。此时,tt 就是直线上的精确距离。

圆心 (xc,yc)(x_{c}, y_{c})、半径为 rr 的圆的参数方程:

[xy]=[xc+rcosϕyc+rsinϕ]\begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} x_{c} + r\cos\phi \\ y_{c} + r\sin\phi \end{bmatrix}

为了保证点的参数唯一,可限制 ϕ\phi 的取值范围。

齐轴椭圆(axis-aligned ellipse)参数方程:

[xy]=[xc+acosϕyc+bsinϕ]\begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} x_{c} + a\cos\phi \\ y_{c} + b\sin\phi \end{bmatrix}

3D 曲面和 3D 曲线

曲面需要两个参数来确定所占据的区域,3D 曲面的参数方程及其向量形式如下:

[xyz]=p(u,v)=[f(u,v)g(u,v)h(u,v)]\begin{bmatrix} x \\ y \\ z \end{bmatrix} = \vec{p}(u, v) = \begin{bmatrix} f(u, v) \\ g(u, v) \\ h(u, v) \end{bmatrix}

曲面就是函数 p:R2R3\vec{p}: \mathbb{R}^{2}\mapsto\mathbb{R}^{3} 的取值范围。例如:球面可以经度(longitude)和纬度(latitude)作为参数,也可以球坐标系中的天顶角 θ\theta方位角 ϕ\phi 作为参数。

曲线 q(t)=p(t,v0)\vec{q}(t) = \vec{p}(t, v_{0}) 称为等参数曲线(isoparametric curve)。它的导数 pu\vec{p}_{u} 给出了曲面的一个切向量。同理,可以构造出曲面的法向量:

n=pu×pv\vec{n} = \vec{p}_{u} \times \vec{p}_{v}

一般约定该法向量指向曲面外部。

3D 曲线参数方程及其向量形式:

[xyz]=p(t)=[f(t)g(t)h(t)]\begin{bmatrix} x \\ y \\ z \end{bmatrix} = \vec{p}(t) = \begin{bmatrix} f(t) \\ g(t) \\ h(t) \end{bmatrix}

通过限制定义域可以控制曲线的起点和终点。

3D 直线参数方程的向量形式:

p=o+td\vec{p} = \vec{o} + t\vec{d}

其中,o\vec{o} 是直线上的点,d\vec{d} 是直线方向向量。将参数范围限制为 [ta,tb][t_{a}, t_{b}][0,)[0, \infty),可以得到线段(line segment)、射线(ray, half-line)。点 a\vec{a}b\vec{b} 间的线段可以表示为:

p(t)=a+t(ba),t[0,1]\vec{p}(t) = \vec{a} + t(\vec{b} - \vec{a}), t \in [0, 1]

线性插值(linear interpolation)

线性插值是图形学中最常用的数学操作。线性插值就是用一个变量 t[0,1]t\in[0, 1],使数据 AA 线性过渡到数据 BB,中间值为:

I(t)=(1t)A+tBI(t) = (1 - t)A + tB

由于 I(0)=AI(0) = AI(1)=BI(1) = B,所以称为插值;又因为权重项 1t1 - ttt 是关于 tt 的线性多项式,所以称为线性插值。

三角形(triangles)

2D、3D 三角形是许多图形程序中的基础模型。图形学中通常希望把一个属性(如颜色)分配到三角形顶点(vertices)上,然后平滑地插值到三角形内部。而重心坐标(barycentric coordinates)让这种插值变得更加简单直接。理解 2D 三角形有助于在 2D 屏幕上绘制图形。

2D 三角形

由点 a=(xa,ya)\vec{a}=(x_{a}, y_{a})b=(xb,yb)\vec{b}=(x_{b}, y_{b})c=(xc,yc)\vec{c}=(x_{c}, y_{c}) 所构成的 2D 三角形的有向面积(signed area):

Area=12xbxaxcxaybyaycya\mathrm{Area} = \frac{1}{2} \begin{vmatrix} x_{b} - x_{a} & x_{c} - x_{a} \\ y_{b} - y_{a} & y_{c} - y_{a} \end{vmatrix}

其中,a\vec{a}b\vec{b}c\vec{c} 的顺序决定了 Area\mathrm{Area} 的正负:

  1. 逆时针,Area>0\mathrm{Area} > 0
  2. 顺时针,Area<0\mathrm{Area} < 0

任选 abc\triangle abc 的一个顶点以及相关联的两条边建立一个标架,再根据线性代数的基础知识可以知道,平面上任一点 p\vec{p} 均可以唯一分解为:

p=αa+βb+γc,α+β+γ=1\vec{p} = \alpha\vec{a} + \beta\vec{b} + \gamma\vec{c},\quad \alpha + \beta + \gamma = 1

其中,(α,β,γ)(\alpha, \beta, \gamma) 就是点 p\vec{p} 的重心坐标。

重心坐标具有以下性质:

  1. p\vec{p}abc\triangle abc 内部 \Leftrightarrow 0<α,β,γ<10 < \alpha, \beta, \gamma < 1
  2. p\vec{p}abc\triangle abc 边上(不包括顶点)\Leftrightarrow α\alphaβ\betaγ\gamma 中有一个为 00,另外两个位于开区间 (0,1)(0, 1)
  3. p\vec{p}abc\triangle abc 顶点上 \Leftrightarrow α\alphaβ\betaγ\gamma 中有两个为 00

重心坐标 (α,β,γ)(\alpha, \beta, \gamma) 可作为系数混合其它属性,如颜色。

如何计算重心坐标

计算重心坐标可以使用代数方法,也可以使用几何方法。代数方法可以是求解线性方程组:

[baca][βγ]=[pa]\begin{bmatrix} \vec{b} - \vec{a} & \vec{c} - \vec{a} \end{bmatrix} \begin{bmatrix} \beta \\ \gamma \end{bmatrix} = \begin{bmatrix} \vec{p} - \vec{a} \end{bmatrix}

一种几何方法是,先考虑以下事实:

  1. fac(x,y)f_{ac}(x, y)β(x,y)\beta(x, y) 均正比于点 (x,y)(x, y) 到直线 fac(x,y)=0f_{ac}(x, y) = 0 的有符号距离
  2. β(xb,yb)=1\beta(x_{b}, y_{b}) = 1

其中,fac(x,y)=0f_{ac}(x, y) = 0 是过点 a\vec{a}c\vec{c} 的直线。将这两条事实结合起来可以得到:

β(x,y)=fac(x,y)fac(xb,yb)\beta(x, y) = \frac{f_{ac}(x, y)}{f_{ac}(x_{b}, y_{b})}

根据过两点直线方程的一般式可得:

{γ=(yayb)x+(xbxa)y+xaybxbya(yayb)xc+(xbxa)yc+xaybxbyaβ=(yayc)x+(xcxa)y+xaycxcya(yayc)xb+(xcxa)yb+xaycxcyaα=1βγ\left\{ \begin{aligned} \gamma &= \frac{(y_{a} - y_{b})x + (x_{b} - x_{a})y + x_{a}y_{b} - x_{b}y_{a}}{(y_{a} - y_{b})x_{c} + (x_{b} - x_{a})y_{c} + x_{a}y_{b} - x_{b}y_{a}} \\ \beta &= \frac{(y_{a} - y_{c})x + (x_{c} - x_{a})y + x_{a}y_{c} - x_{c}y_{a}}{(y_{a} - y_{c})x_{b} + (x_{c} - x_{a})y_{b} + x_{a}y_{c} - x_{c}y_{a}} \\ \alpha &= 1 - \beta - \gamma \end{aligned} \right.

还有一种几何方法是,通过计算面积来得到重心坐标:

{α=Aa/Aβ=Ab/Aγ=Ac/A\left\{ \begin{aligned} \alpha &= A_{a}/A \\ \beta &= A_{b}/A \\ \gamma &= A_{c}/A \end{aligned} \right.

其中,A=Aa+Ab+AcA = A_{a} + A_{b} + A_{c}abc\triangle abc 的面积;AaA_{a}AbA_{b}AcA_{c} 分别是 bcp\triangle bcpcap\triangle capabp\triangle abp 的有向面积,它们(如 AbA_{b})的正负取决于相应的顶点(如 b\vec{b})和点 p\vec{p} 是否在对边(如 acac)的同侧。

3D 三角形

重心坐标可以直接推广到 3D 情形。此时,点 p\vec{p} 位于 abc\triangle abc 所确定的平面上:

p=(1βγ)a+βb+γc\vec{p} = (1 - \beta - \gamma)\vec{a} + \beta\vec{b} + \gamma\vec{c}

由于 3D 隐式直线使用联立方程组表示,相比较而言,通过面积来计算重心坐标更加方便:

{α=nnan2β=nnbn2γ=nncn2\left\{ \begin{aligned} \alpha &= \frac{\vec{n}\cdot\vec{n}_{a}}{\|\vec{n}\|^{2}} \\ \beta &= \frac{\vec{n}\cdot\vec{n}_{b}}{\|\vec{n}\|^{2}} \\ \gamma &= \frac{\vec{n}\cdot\vec{n}_{c}}{\|\vec{n}\|^{2}} \end{aligned} \right.

其中,向量 n\vec{n}na\vec{n}_{a}nb\vec{n}_{b}nc\vec{n}_{c} 分别用于表征 abc\triangle abcbcp\triangle bcpcap\triangle capabp\triangle abp 的有向面积,面积的正负反映在向量方向上:

{n=(ba)×(ca)na=(cb)×(pb)nb=(ac)×(pc)nc=(ba)×(pa)\left\{ \begin{aligned} &\vec{n} = (\vec{b} - \vec{a}) \times (\vec{c} - \vec{a}) \\ &\vec{n}_{a} = (\vec{c} - \vec{b}) \times (\vec{p} - \vec{b}) \\ &\vec{n}_{b} = (\vec{a} - \vec{c}) \times (\vec{p} - \vec{c}) \\ &\vec{n}_{c} = (\vec{b} - \vec{a}) \times (\vec{p} - \vec{a}) \end{aligned} \right.

概率

原文中关于离散概率的说法 “discrete probability refers to when there is a finite number of random outcomes” 有问题。离散型随机变量的取值不一定只有有限多个,也可以是无穷多个,比如所有整数。

随机变量 XX(random variable)、离散概率、连续型随机变量、期望 E(X)E(X)(expectation)、方差 V(X)V(X)(variance)、标准差 σ(X)\sigma(X)(standard deviation)等内容可参考高中数学教材或大学概率论教材。

蒙特卡洛积分(Monte Carlo Integration)

图形学中实现积分的最常用的方法就是蒙特卡洛。蒙特卡洛方法通常把一个积分表示为一个平均值与常数的乘积:

integrate(f(), domain) = average(f(), domain) * integrate(1, domain)

根据大数定理,通过选取一系列服从 domain 上均匀分布的随机数 v{v},并对 f(v)f(v) 求平均可以得到 average(f(), domain) 的近似值。而生成随机数 vv 的最简单的方法就是舍选法(rejection method):先在简单区域中生成随机数,然后舍弃那些不在目标区域的,留下的就是所需要的随机数。

重要性采样(importance sampling)

如果随机变量 f(v)f(v) 涨落较大,那么最好集中在某些区域采样,并用权重来修正 ff 的不均匀性。这种依照对积分贡献大小来决定采样权重的方法叫做重要性采样

integrate = average_of_nonuniform_samples(f() / p(), domain)

蒙特卡洛重要性采样一般按以下步骤进行:

  1. 确定被积函数 f(x)f(x) 和积分区域;
  2. 找一个方法生成积分区域上满足概率密度函数(probability density function,简称为 PDF)p(x)p(x) 的随机数 xx
  3. 生成一系列随机数 xix_{i},计算 f(xi)/p(xi)f(x_{i})/p(x_{i}) 的平均值。

任何概率密度函数 p(x)p(x) 都可以得到正确结果,只要保证 f(x)f(x) 非零的区域,p(x)p(x) 也非零。p(x)p(x) 的选取只影响蒙特卡洛积分的收敛速度