几何
教程:B站闰老师的计算机图形学入门
隐式几何
并不会直接定义xyz的坐标,而是阐述xyz之间的关系
函数式
x 2 + y 2 + z 2 = 1 x^2+y^2+z^2=1 x2+y2+z2=1
上方的函数就表示了一个单位球
特点:
- 不直观
- 很难描述复杂的形状
- 容易判断一个点是否在面上
布尔运算
使用简单的几何体,通过进行交集、差集、并集形成复杂的几何体
距离函数
如上图,直接混合AB只会得到1/3的灰色
而使用距离函数之后,AB分别根据右边界生成两个距离函数,越右边越大
将两者混合之后,两个距离函数相加为0的地方为中线,为想要的效果
这样子就能融合一些形状
距离函数另一种表述:水平集
函数本身通过图表来表示
可以通过双线性插值获得f(x)为某一数的地方,就像等高线一样
分形:特殊的描述法
物体的一部分和自己的整体相似
因为变化十分剧烈所以很难采样
显示几何
参数映射
定义二维的变量uv,有如下函数
f ( u , v ) = f ( x , y , z ) f(u,v)=f(x,y,z) f(u,v)=f(x,y,z)
使用uv两个参数来映射空间中实际的点的位置,xyz都是根据uv直接决定的
点云
将点连成线、面,当点足够多时,可以看作一个面
一般在3D扫描中存储物体的形状
多边形面
一般由三角形、四边形的面组成
obj文件存储:
//每个顶点,按序号排
v x y z
//每个法线
vn x y z
//纹理坐标
vt x y z
//定义点之间的连接关系,比如 3/4/5表示使用第三个顶点,第4个纹理坐标,第5个法线
//定义三个连接成三角形
f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3
贝塞尔曲线
以三个点为例,设 t ∈ ( 0 , 1 ) t\in(0,1) t∈(0,1)
找到 b 0 1 b^1_0 b01,使 b 0 b 0 1 = t b 0 b 1 , b 0 1 b 1 = ( 1 − t ) b 0 b 1 b_0b_0^1=tb_0b_1,b_0^1b_1=(1-t)b_0b_1 b0b01=tb0b1,b01b1=(1−t)b0b1
同理找到 b 1 1 b_1^1 b11,连接 b 0 1 b 1 1 b_0^1b_1^1 b01b11,并找到这个线段上的 b 0 2 b_0^2 b02
当t在(0,1)上滑动时,
b
0
2
b_0^2
b02的移动就会形成一条曲线,这个曲线就是以b0为头,b2为尾,b1为控制点的贝塞尔曲线
再看四个点,这时原本会有三个线段,我们就可以找出 b 0 1 , b 1 1 , b 2 1 b_0^1,b_1^1,b_2^1 b01,b11,b21,这三个点连接形成三个线段,问题就转化为3个点的情况,使用了递归思想
我们计算贝塞尔曲线最后那个点所形成曲线的表达式,以三个点为例
b
0
1
(
t
)
=
(
1
−
t
)
b
0
+
t
b
1
b
1
1
(
t
)
=
(
1
−
t
)
b
1
+
t
b
2
b
0
2
(
t
)
=
(
1
−
t
)
b
0
1
+
t
b
1
1
b
0
2
(
t
)
=
(
1
−
t
)
2
b
0
+
2
t
(
1
−
t
)
b
1
+
t
2
b
2
b_0^1(t)=(1-t)b_0+tb_1\\ b_1^1(t)=(1-t)b_1+tb_2\\ b_0^2(t)=(1-t)b_0^1+tb_1^1\\ b_0^2(t)=(1-t)^2b_0+2t(1-t)b_1+t^2b_2
b01(t)=(1−t)b0+tb1b11(t)=(1−t)b1+tb2b02(t)=(1−t)b01+tb11b02(t)=(1−t)2b0+2t(1−t)b1+t2b2
易法线其满足二项式定律
归纳得有n+1个点时
b
0
n
(
t
)
=
∑
j
=
0
n
(
n
j
)
t
j
(
1
−
t
)
n
−
j
b
j
b^n_0(t)=\sum\limits_{j=0}^n\left(\begin{matrix} n\\j\end{matrix}\right) t^j(1-t)^{n-j}b_j
b0n(t)=j=0∑n(nj)tj(1−t)n−jbj
贝塞尔曲线的性质:
- 在仿射变化下,贝塞尔曲线不会变化,但投影变化这种是会发生变化的
- 凸包性质:任何时候贝塞尔曲线都会在贝塞尔控制点所形成的凸包里面
逐段贝塞尔曲线
当贝塞尔曲线控制点过多时,会导致贝塞尔曲线趋向于过于平滑,
一般以四个点为一段,形成多段的贝塞尔曲线
B样条、NURBS
比贝塞尔曲线更复杂的曲线,具有局部性,改变一个点不会造成全局改变
贝塞尔曲面
上图是用16个控制点所形成的贝塞尔曲面
上图中灰色的四条线为四条贝塞尔曲线
将四条曲线在不同t下所在的四个点再次作为贝塞尔曲线的四个控制点在t’下进行绘制
就可以得到贝塞尔曲面,如果将t,t’看作uv,则可以得到参数映射的定义
曲面细分
将一个三角形转化成多个小三角形
loop subdivision
取一个三角形三边的三个中点,相连后就形成了四个三角形
对于一个新增的顶点,找到他相邻的两个三角面,他的坐标为3/8*(A+B)+1/8*(C+D)
对于一个老的顶点,我们计算顶点的度n,再计算一个权值u, u = { 3 16 n = 3 3 8 n n > 3 u=\left\{ \begin{aligned} \frac{3}{16} & & n=3\\ \frac{3}{8n} & & n>3 \end{aligned} \right. u=⎩⎪⎨⎪⎧1638n3n=3n>3
其新的位置为原位置*(1-nu),相邻的顶点的位置*(u)之和
Catmull-CLARK Subdivision
上一种方法只能用在三角面上,这个方法可以应用在四边形上
定义四边形的面为quad face
,非四边形面为non-quad face
定义度不为4的顶点为extraordinary vertex
(奇异点)
对于每一个三角形/四边形,取他们边上的中点和面上的中点O,并将点O和边上的点相连
从上图可以观察到,非四边形面在进行一次细分后,都变成了四边形面,并且每个非四边形面会增加一个奇异点,我们可以得出以下结论
- 在第一次细分时,每个非四边形面变成四边形面,并且增加一个奇异点
- 之后再次细分时,不会产生新的奇异点,所有面都是四边形面
我们将点更新的方式分为三类,更新方式如下图
- 面上的新点
- 边上新点
- 老的顶点
曲面简化
Edge Collapsing-边坍缩
将两个点合并成一个点,从而让两个边坍缩成一个边,关键在于尽量让简化后的面和原面相似
二次误差度量:我们将合并后的点看作是可以任意移动的,计算在某个位置下这个点到所有被简化的面上的距离的平方,寻找当这个值为最小的位置
如上图所示,两个点被捏成一个点其实可以 看作一个边坍缩成了一个点(也就是在二次误差度量上的*的点)
因此我们这样简化:
- 计算每条边坍缩后形成的点的最优的二次度量误差,并存入小顶堆中。
- 取出堆顶,优化边
- 更新这个边的相邻的边的最优二次度量误差,重新入堆
- 再次进行操作2
可以看出,这是一种用局部最优求全局最优的解法,是一种贪心算法