games101_几何2
主要内容
- 显式表现(Explicit Representations)
- 曲线(Curces)
- Bezier curves
- De Casteljau’s algorithm
- B-splines,etc.
- 表面(Surfaces)
- Bezier surfaces
- Triangles & quads
- subdivision,simplification,regularization
显式几何(Explicit Representations)
点云(Point Cloud(Explicit))
最简单的表现方式:一连串的点(x,y,z).
点云是最简单的一种方法,点云是将每一个点就当作一个点,并不像三角形那样把点链接起来,而是只是单纯的用大量的点来形成面。当点十分密集时,每个点和点之间都是相邻并且十分接近,密集的点就能形成一个面。如下所示:
- 能够十分简单的表示任何几何形体
- 对于大量数据的点集合很有用
- 通常被转换为多边形的面
- 在采样不足的区域很难绘制出图形,如雕塑下面
多边形网格(Polygon Mesh(Expicit))
- 在图形学中最广泛应用的一种显示方法。
- 存储顶点和面的信息(面通常是三角形或者矩形)。
- 更容易处理、模拟和采样。
- 这种方法使用的数据结构更加复杂。
存储几何体的文件 .obj文件
一般用.obj文件来存储一个模型,如果使用blender建模然后导出就可以得到一个.obj文件,文件的内容如下:
把空间中的一堆点,法线和纹理坐标在文件中分开表示,并且也在文件中表示了他们之间的关系。
- 左图上面的v,表示的是空间中的立方体坐标,即每个顶点的(x,y,z)的坐标。一个立方体有八个点,所以有八行数据。
- 右图上面的vn,表示的是立方体有八个顶点六个面,每个面都有一个法向量,一共六种不同的法线。有八行的原因是因为自动的建模有可能会产生冗余的地方,比如29行和30行其实是一样的。
- 左图下面的vt,表示的是12个纹理坐标,当然里面也有冗余。每个面都要定义一个四个点不同的纹理坐标(最多24个纹理坐标,中间可能有公用的,不需要那么多)。
- 右图下方的f(face),表示的是点之间的连接关系,顺序是[f v1/vt1/vn v2/vt2/vn v3/vt3/vn]表示的是一个面由v1,v2,v3三个点组成,分别使用vt1,vt2,vt3三个纹理坐标,使用vn法线。
简化解释就是: - v代表几何体的每个顶点的位置信息
- vt代表纹理坐标
- vn代表顶点对应的法向量
- f代表将三角形连接成顶点的索引顺序。
- f代表的是:顶点号/纹理号/法向量号。
如第一行f表示,将第5个,第1个和第4个顶点连接成三角形。
曲线(Curves)
Maya中的曲线应用
字体中的曲线应用
贝塞尔曲线(Bezier Curves)
使用一系列的控制点,去定义某个曲线:
然后这些控制点会去满足这个曲线的某些性质,比如说:
p0,p1,p2,p3为控制点,其中p0,p3为起点和终点。定义一个曲线的条件:
- 知道起点p0和终点p3
- 起点和终点的切线方向分别在p0、p1和p2、p3上
有以上两个条件,就可以定义一个控制方向。即控制点+属性就可以定义一条曲线。
但这不意味着曲线一定要经过我们的控制点,只要经过起始点和终止点就可以。
画贝塞尔曲线(直观表达形式)
给出一系列任意多的控制点,怎么画出一条贝塞尔曲线?
比如说目前只有三个点,两条线段:
-
先考虑只有三个顶点两条线段的情况下如何画一条曲线:
首先这条线一定要从b0开始,到b2结束。b1决定了整条线要向哪个方向弯曲。 -
给定一个时间t,从0开始到1结束。在这里我们用图下方的线段表示出来。
- 三个输入的点b0、b1、b2确定了两条线段b0b1、b1b2
- 在b0b1上认为,b0是0,b1是1
- 那么在b0b1线段上,找一个点t(t=1/3),这个点记为b10。
-
同样的,在b1b2上:
- 认为b1是0,b2是1
- 也找这样一个点t=1/3,这个点记为b11。
到此我们通过三个点b0、b1、b2得到了两个点b10、b11。
-
把刚刚得到的两个点b10、b11连起来
- 再认为线段b10b11又是从0到1,b10是0,b11是1
- 再取同样的t=1/3,这时我们找到了1个点b20
b20这个点即为由b0、b1、b2三点确定的一条贝塞尔曲线在时间t=1/3上的点。
- t的取值从0到1,每取一个值都重复上述步骤,然后得到了一系列点,将所有的点连起来就得到了一条贝塞尔曲线。
再比如说目前有四个点,三条线段:
根据上面三个点,两条线段的例子,可以推出一下过程:
-
找出相对于三条线段,t(t=0.5)点的位置,如下图所示:
可以得到b10,b11,b12三个点。 -
然后将这三个点连起来,这样又得到两条线段,然后又在这两条线段上取t点,得到两个点b20、b21:
-
再由上面得到的两个点连成一条线段,然后取点t,得到点b30:
-
连接线段。 t的取值从0到1,每取一个值都重复上述步骤,然后得到了一系列点,将所有的点连起来就得到了一条贝塞尔曲线。将其连接起来就会得到最后的贝塞尔曲线。
动画绘制,回视频观看的话在1:02:20。
画贝塞尔曲线(代数表达形式)
最后会得到下图的关系式,算数式使用的是 线性插值 计算方法(线性插值知识博客):
将上面三个式子融合就可以得到下面这个式子:
b0、b1、b2前的系数可以看成是1的平方的展开,1的平方可以写成{(1-t)+t}²,展开后也就是上面的系数了。
总结规律后可以得到下面这个关系式:
给 n+1 个控制点(分别是0,1,2…,n),可以得到一个n阶的贝塞尔曲线,这个贝塞尔曲线在任意时间t都是给定的控制点的线性组合,而组合的系数就是一个多项式(伯恩斯坦多项式):
伯恩斯坦多项式是跟时间有关的一个多项式:
i对应从0到n(竖着的n i应该是组合数,对应排列组合中的C(n,i))
最后简化一下,不考虑有多少层了,任意阶数的贝塞尔曲线,任意时间t的点的位置就由伯恩斯坦多项式作为系数对给定的控制点的加权。
例:不用将控制点限制在平面内,在空间中仍然可以得到一个贝塞尔曲线,只要将不同的控制点输入成三维坐标,同样用伯恩斯坦多项式对其插值
因为伯恩斯坦多项式相当于对1自己的n阶展开,所以这个多项式:
- 如下图,三阶,有四个不同的多项式,分别对应i等于0、1、2、3
- 在同一阶上把相同时间t的几个多项式的值加起来肯定等于1
贝塞尔曲线的性质(Properties of Bezier Curves)
-
贝塞尔曲线规定了必须过起点和终点,所以在t=0时在起点,t=1时在终点
-
特别的,对于4个控制点,起始的切线一定是3(b1-b0),结束的切线为3(b3-b2)。在这里的三倍是根据我们这个举例有4个控制点来的,如果有其他不同的控制点,这里需要变化。
-
求贝塞尔曲线两种不同的方式,但结果一样。
- 可以直接对不同的顶点做仿射变换,再重新对变换之后的顶点画一条贝塞尔曲线。
- 直接对原始的控制点做贝塞尔曲线,然后根据这条贝塞尔曲线的每一个点做仿射变换。
- 上面两个方式得出的贝塞尔曲线是一模一样的。
- 注意,比如某个平面有一条贝塞尔曲线在投影后,对投影后的贝塞尔曲线做仿射变换。那么这两条贝塞尔曲线就不是同一条了
-
凸包性质(Convex hull property)
画出来的贝塞尔曲线一定得在所有控制点形成的凸包内。- 凸包:能够包围一系列给定的几何形体的最小的凸多边形。
- 更直观来讲,如下图,在一个板子上打好多钉子,用一个橡皮筋拉大包住所有钉子后放手,让橡皮筋自然收缩,被卡住的一圈钉子组成的多边形即为凸包。也就是,任何一个贝塞尔曲线在被画出来之后,这个贝塞尔曲线上的任何一个点,在任何时间t里,一定都在这几个给定的控制点形成的凸包范围内。
逐段的贝塞尔曲线(Piecewise Bezier Curves)
为什么要逐段考虑?
当碰到下面这种高阶贝塞尔曲线时:
- n=10,也就是给了11个点,得到上面蓝色的曲线,虽然没有问题,但并不直观,在中间部分变成很平缓的线了。
- 所以这条曲线不好控制,不利于用中间的控制点得到你想要的形状。
- 所以需要分段进行考虑。
一般每四个控制点控制一条贝塞尔曲线,也就是Piecewise cubic Bézier
如下图,是由不同的贝塞尔曲线连接的,可以看发生剧烈拐弯处的点,显然不是通过原始的点求出来的贝塞尔曲线。而每一段贝塞尔曲线由四个点控制,如第一条由曲线起始点、下面蓝色线段的左端点、上面蓝色线段的左右端点
下图就分段贝塞尔曲线的例子,黑色的点和蓝色的方块都是某一条贝塞尔曲线的控制点。
分段贝塞尔曲线的连续性
分段贝塞尔的连续性有两种,分别是:
-
C0连续。即上一段曲线的终点是下一段曲线的起点,仅仅满足这种物理上的连续,并不管这两段相连的地方会形成多大的锐角,只要他们两段挨在一块。
-
C1连续。C1连续是在满足C0连续的条件外,还要满足在连接点的两端切线的方向相同,切长度相等。如下面红线所示,中间点为终点,左右两个点分别为两段曲线的控制点。
-
C0连续是两个函数在值上连续,C1连续是导数连续,C2连续是二阶导数连续。
其他类型的曲线
样条曲线(Spline)
定义:一个连续的曲线是由一系列的控制点控制的,并能够满足一定的连续性。简单来说就是一个可控的曲线
早期人们通过提前固定好点,然后使用树枝穿过这些点,从而得到自然弯曲的曲,如上图所示。
B样条(B-Splines)
是basis splines的缩写,就是基函数样条。
基函数: 可以理解成用伯恩斯坦多项式在时间t对几个控制点做加权平均,也可以理解为用控制点的位置对伯恩斯坦多项式进行加权求和。那伯恩斯坦多项式就是可以理解成一个基函数,就相当于由不同的函数通过不同的方式组合起来形成别的函数,这个函数就叫基函数。
B样条: 是贝塞尔曲线的扩展,能力要更强(像之前n=10的情况下,我动一个点,整个一条曲线在任何位置都会发生变化,而这在设计上并不是一个很好的性质,当我们觉得这条曲线其他的地方都很好,就想改一个点,如果贝塞尔曲线就要动所有的点,很不方便),具有局部性(我改变一个点,我知道这个控制点至多影响到这条曲线的哪些范围内)。同样对于局部性,分段贝塞尔也可以实现。
如果想更加深入了解B样条可以看下面的内容。
曲面(Surfaces)
贝塞尔曲面(Bezier Surfaces)
将曲线扩展到曲面。
通过贝塞尔曲线得到贝塞尔曲面(概念实现)
下图可以理解为一个曲面,有一种力将它拉了上去。但其实下图是通过16(4x4)个控制点得到的。
相当于双线性插值的理解,在两个方向上分别应用贝塞尔曲线
具体表示为以下过程:
首先,我们在平面上定义4x4个点:
我们认为他有4行,每一行用四个控制点得到一条曲线
每一条曲线在不同时间t上,会在不同的位置上,我们先将其相连成一条线,在所有时间t上重复这个过程,可以绘制出一个面。
然后这个线在不同时间t来不断扫空间的过程中会得到一个曲面。也可以任意的改变贝塞尔曲面控制点的位置
图表表示过程:
通过上面那个方式我们可以得到非常复杂的曲面。
贝塞尔曲面计算方法
要找到贝塞尔曲面上任何一个点,通过上面的过程看,是需要两个不同的时间t(在水平方向上找同一个时间t,找到4个点后,这4个点要连成一条曲线,还需要一个时间t),所以需要一个二维的控制,我们管它叫uv。
完全可以找到某一个u沿着得到的4条曲线上,找到时间u在哪,这样可以得到4个蓝色的点,再给任何一个时间v,在这4个蓝色的点形成的曲线上找时间v,就找到了最后的点的位置(也就是曲面在uv参数下的位置)
这也说明了为什么贝塞尔曲线是显式的表示的,因为是通过参数uv映射过去的
网格操作:几何处理(Mesh Operations: Geometry Processing)
- Mesh subdivision(网格细分)
用更多的三角形得到更光滑的表面(见下图牛2到牛3) - Mesh simplification(网格简化)
用更少的面可以节省很多存储(见下图牛3) - Mesh regularization(网格正规化)
让三角形不至于出现特别尖特别长的情况,都变成一个和正三角形相似的比较规则的三角形(见下图牛5)