几何2 - 曲线和曲面(Geometry 2 - Curves and Surface)
上一节提到,要表现一些复杂的几何模型有两种方法:
- 隐式几何
- 显式几何
本节课讲的为显式几何
显式几何(Explicit Representations)
显式几何有两种方式:
- 一种是像三角形直接定义出来
- 另一种是通过参数映射的方法定义表面
显式几何有许多的方法,如:
下面介绍几种方法:
点云(Point Cloud)
点云是最简单的一种方法,点云是将每一个点就当作一个点,并不像三角形那样把点链接起来,而是只是单纯的用点来形成面。当点十分密集时,每个点和点之间都是相邻并且十分接近,密集的点就能形成一个面。如下所示:
上面部分的点十分密集,形成了一个铜像,而下面的点比较稀疏,则无法构成一个面,只能看见一些离散的点。
这种方法有以下特点:
- 能够十分简单的表示任何几何形体
- 对于大量数据的点集合很有用
- 通常被转换为多边形的面
- 在采样不足的区域很难绘制出图形,如上图下面
多边形面(Polygon Mesh)
多边形面是目前应用最广泛的一种方式。具有以下特点:
- 存储顶点和面的信息,面通常是三角形或者矩形
- 更容易处理和采样
- 这种方法使用的数据结构更加复杂
下图的几何体就是用多边形面所组成的。
存储几何体的文件 .obj文件
一般用.obj文件来存储一个模型,如果使用blender建模然后导出就可以得到一个.obj文件,文件的内容如下:
v代表几何体的每个顶点的位置信息,vt代表纹理坐标,vn代表顶点对应的法向量,f代表将三角形连接成顶点的索引顺序。
如第一行f表示,将第5个,第1个和第4个顶点连接成三角形。f代表的是:顶点号/纹理号/法向量号。
曲线(Curves)
贝塞尔曲线(Bézier Curves)
贝塞尔曲线定义一个曲线的方法,如下图:
p0,p1,p2,p3为控制点,其中p0,p3为起点和终点。定义一个曲线的条件:
- 知道起点p0和终点p3
- 起点和终点的切线方向分别在p0p1和p2p3上
有以上两个条件,就可以定义一个控制方向。即控制点+属性就可以定义一条曲线。
注:曲线并不一定经过控制点,但一定经过起点和终点。
画一条贝塞尔曲线
先考虑只有三个顶点两条线段的情况下如何画一条曲线:
b0,b2为起点和终点,b0,b1,b2为控制点。
贝塞尔画曲线的方法就是:假设有一个时间t属于[0,1],只要找出所有 在任意时间t上所对应的曲线的点,就可以画出这条曲线。
也就是说,给一个时间t属于[0,1],找出曲线上这个点在哪。如下图所示:
注:上图bo到中间点b(01)为(1-t),而b(01)到b1为t,图画反了。
要在两条线段上都找到这样一个中点:
然后在两个中点的连线上再找到一个时间t对应的中点。
得到的b(02)就是曲线上的点。只要我们枚举所有的时间t所对应的点,就能够画出这条曲线。
如果有四个点三条线段时:
如上所示,现在三条线段上各找一个中点,然后将三个中点连接成两条线段,然后再在两条线段上找两个中点,然后再连接成一个线段,再找到这一个线段上的中点即可。简化一下:
四个点,三条线 - > 三个点,两条线 - > 两个点,一条线 -> 一个点,这个点就是曲线上的点。
贝塞尔曲线用代数表示
先把b(01)和b(11)用控制点表示出来,然后再对b(02)用上面获得的两个中点表示。将b(01)和b(11)带入b(02),就能够得到最下面的那个式子。可以看到,b(02)是所有控制点的一个线性组合所表示的,是否可以认为,曲线上的点都是所有控制点的一个线性组合?
实际上是这样,所有曲线上的点都是所有控制点的一个线性组合,公式如下:
上图表示当有n+1个控制点时,曲线上t所对应的点可以由所有的控制点的线性组合表示,其中:
可以看出,其实
为[t + (1-t)]^n的二项展开的一个通项。
一个例子:
贝塞尔曲线的属性
-
第一个和最后一个控制点为起始点,一定要经过,其他控制点不一定经过
- 最开始的两个点和最后的两个点决定起点和终点的切线方向,比如有4个点b0,b1,b2,b3,切线如下
其中3并不是固定的,当控制点的数量改变时,3可能变为其他的系数 -
先用控制点画的贝塞尔曲线,和经过仿射变换(affine transformation)的控制点画出来的曲线是一样的。注:旋转变换+缩放变换 = 线性变换, 线性变换 + 平移变换 = 仿射变换。
-
凸包性质(Convex hull property):给出一系列的控制点画曲线,画出来的曲线一定在一个能够包围所有控制点的范围内。如下图所示:
其中蓝色的框就是凸包,这些控制点画出来的曲线一定在这个蓝色框内。更通俗的理解就是说:比如在一个木板上,钉了许多钉子,这些黑点就是一个一个钉子,然后用一个环形的橡皮筋来包围住这些所有的钉子,这个橡皮筋一定会被最外围的一圈钉子支撑形成一个环,这个环就是凸包。
分段贝塞尔曲线(Piecewise Bézier Curves)
先看下面一个例子:
上图中,用十个控制点来画贝塞尔曲线,可以看到划出了一条曲线。但是这存在了一些问题,在一些偏移较大的控制点的位置,其画出来的曲线偏移十分的小,比如在靠近上面的一段曲线甚至接近一条直线,但是可以看到控制点歪曲的方向非常大,这就是为题所在。
当控制点十分多的时候再用贝塞尔曲线,得到的曲线就难以达到我们想要的标准,于是我们想:为什么要用许多的控制点定义一个贝塞尔曲线,而不是用几个控制点定义一段贝塞尔曲线,最终把这些曲线连接起来?于是,分段贝塞尔曲线就诞生了。
分段贝塞尔曲线通常用四个控制点定义一段曲线,然后将这些曲线最终连起来。如下:
以最左面的一段曲线举例,四个控制点定义了这一段曲线:
图中四个蓝色的点为控制点,然后后面的依次类推,每次用四个控制点画一段贝塞尔曲线,最后连起来就能够得到一条我们希望的曲线。
分段贝塞尔曲线的连续性
分段贝塞尔的连续性有两种,分别是:
- C0连续,即上一段曲线的终点是下一段曲线的起点,仅仅满足这种物理上的连续,并不要求在连续点的切线方向不变(或者说可导),能够满足下面这种情况都可以。an为上一段曲线的终点,b0为下一段曲线的起点。
- C1连续,除了满足C0连续的条件外,还要满足在连接点的两端切线的方向相同,切长度相等。如下面红线所示,中间点为终点,左右两个点分别为两段曲线的控制点。
C1连续要满足的代数条件:
样条曲线(Spline)
定义:一个连续的曲线由一系列的控制点控制,并且在曲线上的任意一点都满足连续性。
解决问题:在之前10个控制点的例子中,对于这种控制点很多的曲线,当我们想修改其中的一小部分的时候,如果用贝塞尔曲线,当我们想修改一个控制点,就会导致整个曲线发生改变,这个是我们不希望看到的。我们希望改变一个控制点只会改变局部的曲线,希望曲线能够具有这种局部性。样条就是解决这个问题。分段贝塞尔也可以解决这个问题,但是样条能够控制更加方便,不需要分段。
曲面(surfaces)
贝塞尔曲面(Bézier Surfaces)
贝塞尔的曲面构建如下图所示:
- 有一个时间t属于[0,1],根据控制点和时间t画出纵向的曲线。
- 有一个时间v属于[0,1],在对应的时间v上找出四条曲线上对应的四个点,将这四个点作为控制点就可以画出横向的曲线。