Loading... # Lec 10 ~ 12:Geometry 几何 几何可以分为 **隐式几何** 和 **显式几何**。  - **隐式几何**不会告诉具体的点的位置,只会告诉点与点之间的关系。比如球面的公式:$x^2+y^2+z^2-r^2=0$ 或者广义地说,定义某个函数f,满足:$f(x,y,z)=0$ 隐式几何难以描述物体的具体形状,但是方便判断点是否在物体内外,比如球面:$x^2+y^2+z^2 - r^2<0$ 表示在球内。 - **显式几何**会直接给出所有的点,或者提供一个参数的映射。比如下图中的马鞍面,遍历每一个$(u,v)$,将其映射为三维中的点,即可得到完整的几何形状。  亦或如下图圆环,其中的$f(u,v)$即为一个映射:  显然,这个不方便判断点是否在内外。 没有最好的表示方式,必须根据实际需求做出改变。 ## 1. 隐式几何 ### 1.1 代数曲面  ### 1.2 Constructive Solid Geometry(CSG)  可以通过交并补等布尔操作计算出各种形状的几何体  ### 1.3 距离函数 对于任意一个几何,不直接描述表面,而是描述空间中任何一个点到几何体的最小距离。 当然这一距离是可以有符号的,符号为负表示在曲面内部,符号为正表示在外部,被称为 **带符号的距离函数(Signed Distance Function,简称SDF)**。 使用距离函数可以得到如下的 **融合** 效果:  以下摘自:https://blog.csdn.net/qq_38065509/article/details/106105000 首先对于符号距离函数来说本质上就是一种定义距离的函数。对于空间任意一点,已知其到各个几何物体表面的距离,对这些距离做各种各样的运算操作最后得到的一个函数就是最终的距离函数了,举一个简单的例子:  对于这样一个二维平面的例子,定义空间中每一个点的SDF为该点到阴影区域右边界的垂直距离,在阴影内部为负,外部为正,因此对于A和B两种阴影来说的SDF分别如上图下半部分所示。有了SDF(A),SDF(B)之后对这两个距离函数选择性的做一些运算得到最终的距离函数,这里采用最简单的SDF = SDF(A)+SDF(B)来举例,最终得到的SDF为零的点的集合即为blend之后曲面,对该例子来说,就是两道阴影之间中点的一条线:  因此对于一开始的那个例子来说,只需合理定义空间中任意一个点的SDF,再令SDF为0即可得到混合的效果了。 (tips:对于几何体混合效果自然不可能像这里简单的两个距离相加就可以得到了,该效果具体实现是找出任一个点到两个几何体表面距离中的最短距离再减去一个变量作为该点最终的SDF,有兴趣的读者可以取油管搜索Coding Adventure:Ray Marching,该视频的讲解很不错) ### 1.4 水平集 水平集和上述距离函数的思想很像,定义空间中的每一个点的距离值(可正可负),找出一条近似的值为零的曲面。与距离函数不同的是,水平集并没有一个严格的数学定义。 比如下图,是一个二维面上的水平集。对该面内的每一个点利用已经定义好的格子值进行双线性插值就可以得到任意一点的函数值,找出所有=0的点作为曲面。  这一方法与地理上的等高线十分相似。相较于距离函数,它可以**显式地**勾勒出曲面的形状。  ### 1.5 分形几何  分型几何是指许许多多自相似的形体最终所组成的几何形状。 如雪花是一个六边形,放大之后会发现每一个边上又是一个六边形,再放大六边形边上的六边形边上又是六边形,就这样无限套娃,有点递归的意思。 隐式曲面具有形式简单,轻易判断点与曲面关系等优点,但难以采样曲面点和模拟过于复杂的形状。 ## 2. 显式曲面 ### 2.1 点云 很多很多的点构成的曲面,直接有着所有点的信息。用大量的点集可以简单地描述出任何形状。但是显然,在欠采样的区域效果会很差。  ### 2.2 多边形网格  这是计算机图形学中使用最广泛的表达方式。通过定义各个顶点,以及顶点之间的连接关系,构成多个三角形/四边形面,再由这些面构成一个完整的几何体模型。 常见的.obj格式文件就是这样的表达方式:  这是一个立方体的模型数据例子。 - 3 - 10行 v(vertice) 定义了立方体的8个顶点信息。 - 12-25行 vt(vertice texture)定义了这些顶点的纹理坐标信息(每个面4个点,共6个面所以最多有24种不同的纹理坐标信息,这里有一些纹理对于不同面上的点是公用的)。 - 27-34行 vn (vertice norm)定义了6个面的法线信息,为什么有8个是因为建模软件输出的精度问题不必在意,其中有两个是重复的。 - 36-47行,f(face) 代表一个面,其中x/x/x的第一位表示是哪个顶点,第二位表示该顶点纹理坐标是第几个,第三位表示法线信息是第几个。 3个 x/x/x表示3个顶点的信息构成一个面。 ## 3. 贝塞尔曲线 贝塞尔曲线是需要一系列的**控制点**去定义某一个曲线  其中 $p_0,p_1,p_2,p_3$ 为控制点。可以看出蓝色的曲线经过始末控制点(0/3),而且与始末向量(01/23)相切。 下面详细讲解贝塞尔曲线的形成过程: 首先是简单的三个点的情况  - 我们选定一个参数 $t \in [0,1]$,在$b_0b_1$线段上利用 $t$ 进行线性插值,即选定划分比例为 $t$ 的地方  - 然后在 $b_1b_2$ 线段上进行同样的操作  - 将两次所得的 $b_0^1/b_1^1$ 点连接成线段,在这个线段上再进行一次线性插值。如此一来便得到了一个曲线将会经过的点 $b_0^2$ . 如果对所有的$t\in[0,1]$都进行一次这样的操作,就可以得到一些列曲线上的点,最后得到最终的结果(图中的蓝色曲线)  **其核心所在就是多次的线性插值,并在生成的新的顶点所连接构成的线段之上递归的执行这个过程,直到得到最后一个顶点** 如下图这样一个4个控制顶点的例子,步骤完全类似:  **贝塞尔曲线的代数公式** 求贝塞尔曲线的一个点的过程,是每次都在相邻两个同级点之间所取,其过程可以表示成如下图:  根据线性插值的公式,将四个控制点的贝塞尔曲线展开:  可以发现,形成了一个参数为 $t$ 的一元二次方程(n个控制点形成n-1阶贝塞尔曲线)。可以将这个情况推广到任意级的贝塞尔曲线,即可得到 **Bernstein形式的贝塞尔曲线公式**:  其中 $b_j$ 是贝塞尔控制点, $B_j^n(t)$ 是Bernstein多项式,为: $$ B_j^n(t) = C_n^i t^i(1-t)^{n-i} $$ 贝塞尔曲线有如下的特点: 1. 必定经过起始与终止控制点 2. 必定经与起始与终止线段相切 3. 具有仿射变换性质,可以通过移动控制点移动整条曲线 4. 凸包性质,曲线一定不会超出所有控制点构成的多边形范围 但是高阶的贝塞尔曲线有一个很大的缺陷:如下图所示,一个11个控制点所形成的10阶贝塞尔曲线,它的形状很难控制。  为此,有人提出了分段贝塞尔曲线的方法。比如下图便是由三段贝赛尔曲线所拼接组成的。  ## 4. 贝赛尔曲面  画出四条贝塞尔曲线后,在这四个线上再取四个点,认为是一个新的贝塞尔曲线的控制点。在不断扫的过程中,形成了曲面:  可以将任意二维坐标 $(u,v)$ ∈ (0, 1) 映射成贝塞尔曲面上一点。以4×4为例 - 先根据u值,在四个列上获取四个贝塞尔曲线(灰色曲线)上的四个点(上图蓝色点) - 将这四个蓝点当做控制点,再根据v值获取到指定的一个点 - 遍历每一个u、v,就可以得到一个完整的曲面 由此可以看出,贝塞尔曲面是一种 **显式表示**(利用映射) 下图为4×4的控制点计算贝塞尔曲面的流程图:  ## 5. 曲面细分/简化 **曲面细分 Mesh Subdivision** 是指将一个模型的面合理的分成更多小的面,从而提升模型精度,提高渲染效果 **曲面简化 Mesh Simplication** 是指将一个模型的面合理的合成更少的面,从而降低模型精度,为特定情形下提供使用   ### 5.1 曲面细分 细分的过程基本分为2步:**新增顶点(新增面)**、**调整顶点位置** #### 5.1.1 Loop细分 Loop是一个人名。Loop细分是一种专门针对三角形面的细分方法。 **1. 新增顶点,生成更多三角形**  如图所示,在三角形的三个边上各选一个位置新增点,就可以将三角形划分成更多的子三角形。 **2. 调整新增顶点的位置** 接下来我们根据每个点周围的顶点的权重进行位置的调整(新增的点与原有的点的调整方法不同) - **对新增点**  如上图,中央的白色点是一个新增的点。我们要修改它的位置(向量),设为**与其邻接的三角形的每个顶点的位置(向量)加权**,类似一个种加权平均的操作。新增点所在边的顶点权重为3/8,其余点权重为1/8. - **对原有点**  如上图,中央的白色点是一个原有的点。我们要修改它的位置,设为**与其邻接的每个原有点的位置,再加上自身位置的加权平均**。 如果相邻结点数量n为3,那么相邻结点权重为 3/16, 否则为3/(8n),而自身的权值为(1-相邻结点权值和)  #### 5.1.2 Catmull-Clark细分 **Catmull-Clark细分**适用于存在四边形面的模型。有些模型是四边形面与三角形面的混合。  如上图所示,我们定义每个顶点的邻接的面数为这个 **顶点的度数**,对于度数不为4的点称为 **奇异点** 一次细分的过程: - **每个边上取中点,以及每个面上取一个点(重心或者其他的),把这些点连起来**  在这个过程中,因为两个三角形面内的点要与三个顶点相连,相当于引入了两个度为3的奇异点,所以一共有4个奇异点。同时在这个过程中,所有的面都变成了四边形面。 - **再进行一次细分**  可以发现,这次并没有再引入新的奇异点(紫色的是奇异点,都是前一次细分之后都有的)。也就是说,在进行一次细分之后,就不会再产生新的奇异点了。 - 以上是**新增顶点**的过程,接下来需要**调整顶点位置**:   ### 5.2. 曲面简化  曲面简化所用的方法叫做**坍缩**(collapse),即将一个边的两个顶点连成一个。 为了保证模型原本的形状,我们需要考虑一个问题:选取哪一条边优先进行坍缩,可以让模型的形状变化最小? 为此引入一个度量,即**二次误差度量**(Quadric Error Metrics)  如图所示,将中间两个黑点坍缩成一条边之后,形成了新的顶点蓝点。**新顶点所在的位置与原来各个平面的垂直距离之和**即为二次误差度量。如果能够使得这个误差最小那么对整个模型样貌修改一定程度上也会较小。 所以曲面简化的流程为: 1. **为模型每条边赋值,其值为坍缩这条边之后能得到的最小二次误差值** 2. **选取权值最小的边做坍缩,新顶点位置为原来计算得出使得二次误差最小的位置** 3. **坍缩完之后,与之相连其他的边的位置会改动,更新这些边的权值** 4. **重复上述步骤,直到到达终止条件** 因为需要求最小值,同时又要动态更新,所以以上过程可以用**优先队列**(堆) 这是一个标准的贪心算法,并不能达到全局最优解,但是仍然有不错的效果  最后修改:2021 年 11 月 10 日 02 : 23 AM © 允许规范转载