【GAMES101]图形学学习记录——几何

在现实生活中,物体有各种各样的形状,在这一节中,我们将学习如何在图形学中表示这些不同的形状。

隐式和显式几何表示

隐式几何表示

只包含构成几何形状的点满足的关系,不包含这些点的具体位置,通常为一个函数。例如一个球的隐式表示:

通常用以下方式表示:

隐式表示很容易判断一个点在不在几何平面上,但很难找出几何平面上有哪些点。

显式几何表示

直接将几何形状上的所有的点都表示出来,或者通过参数映射的方法定义的表面。参数映射的解释如下:

image-20241228181255365

显式表示很容易判断哪些点在平面上,但很难判断一个点在平面上,平面内还是平面外。

不同的隐式表示

之前所说函数形式的隐式表示虽然能表示出一个几何图形,但我们很难直观地通过一个复杂的函数知道这个几何图形的形状。以下是一些其他的隐式表示方法。

  • CSG(Constructive Solid Geometry):通过对基础的几何体做一些简单的布尔运算来表示复杂的几何体。如图所示:

CSG

  • Distance Functions(距离函数):对于任何一个几何图形,不直接描述它的表面,而是描述如何一个点到这个表面的最近距离。求出两个物体的距离函数,并进行融合,就可以得到新的物体。(怎么感觉更不直观了

Distance Functions

不同的显式表示

  • 点云:不考虑物体是一个表面,而是表面上的一些点,当足够精细时就和平面相差无几。

  • 多边形面:大多数是三角形和四边形。用多边形的组合来描述几何图形。在图形学中的应用最为广泛。

    .obj文件:一种文本文件,分别记录了一堆点,一堆法线和一堆纹理坐标,再将它们组织起来来描述图形。

曲线(Curves)

贝塞尔曲线

用一系列控制点去定义某一个曲线。

算法

假设在时间0-1内,时间0在起始点,时间1在结束点,我们要算出在任意时间0-1中任意时刻点在空间中的位置。对于n个控制点(n>2),我们在每两个相邻的点之间连一条线段,并在这个线段上找到使其比例为t的点。当进行一轮这样的操作后,我们得到了n-1个点。重复以上操作,直到最终只剩下一个点,这个点就是时间t所在的点。当我们枚举时间t,得到的点连成的就是贝塞尔曲线。图解如下:

贝塞尔曲线

性质

  • 贝塞尔曲线的起点是第一个控制点,终点是最后一个控制点。
  • 起点处切线的方向一定为b2-b1,终点处的方向一定为bn-b(n-1)。
  • 控制点经过仿射变换后,生成的贝塞尔曲线形状不会改变。
  • 控制点得到的曲线一定在控制点形成的凸包内。

逐段控制的贝塞尔曲线

当控制点过多时,计算成本会增加,同时控制的效果会变差。因此,更高效的做法是逐段用少量控制点(通常是四个)来逐段控制曲线。

B-splines(B样条)

样条是一种完全可控的曲线,而B样条是贝塞尔曲线的延伸,它具有局部性,在改动控制点时影响的范围有限。

曲面

贝塞尔曲面

贝塞尔曲面是由贝塞尔曲线得到的。原理和双线性插值基本相同,我们在两个方向上分别应用贝塞尔曲线即可。

三角形的细分和简化

三角形的细分

有的时候,三角形数量不足会导致模型不够精细,这时候,我们希望能增加三角形的数量来提升模型的精细度。细分通常分为两步:将一个三角形分成多个三角形,之后调整这些三角形的位置使其符合模型。

Loop细分(Loop Subdivision)

将三角形三边的中点连起来,就得到了四个小的三角形。以前的顶点称为旧的顶点,中点称为新的顶点。

对于新的顶点,如果它被两个三角形共享,则它的位置由这两个三角形的旧的顶点加权得出。和它在同一条线段上的两个顶点的权值是3/8,另外两个顶点的权值是1/8。如图所示:

New Vertex

对于旧的顶点,定义n为顶点的度,定义u为和n有关的数,当n=3时,u=3/16,否则u=3/(8n)。旧的顶点的位置有自己和周围的点加权得出,如图所示:

Old Vertex

Catmull-Clark细分

Loop细分只能对三角形做细分,而Catmull-Clark细分在一般的情况下也能进行操作。

定义非四边形为所有边数不为4的多边形,奇异点为度不等于4的点。对所有的边都取中点,所有的面也取中心点,将中点和中心点连起来就产生了更多的多边形。当进行这样一次操作后,奇异点的数量增加了非四边形的数量,所有非四边形都消失,并且之后不会再有奇异点的增加和非四边形的出现。效果如下:

Catmull-Clark

每个点位置的更新方式如下图所示:

Catmull-Clark Vertex Update Rules

三角形的简化

有的时候(例如当物体离摄像机很远的时候),物体的精细程度并不十分重要,在这种情况下,我们希望用更少的三角形来表示物体,以达到减少性能消耗的目的。

边坍缩(Edge Collapse)

想象有一条边,当我们捏住它的两个顶点并重叠到一起,这条边就不复存在了。这就是边坍缩的概念。但是对于一个物体来说,我们怎么知道哪些边不重要,可以进行坍缩,哪些不能呢?这里需要用到二次误差度量的概念。二次误差度量是指顶点到到和它相邻的所有平面的距离的平方和

在进行边坍缩时,优先坍缩二次误差度量最小的边即可。但是,当我们对一条边进行坍缩后,和它相邻的边会受到影响,导致二次误差度量受到影响,这使得我们无法先计算所有边的二次误差度量,再依次进行坍缩。在这里,我们可以用最小堆的数据结构进行计算。