Geometry 几何
在计算机图形学无论是人物,风景,建筑,都离不开几何,如何表示好各种各样的模型是几何部分的主要研究内容之一。
比如:
Ways to Represent Geometry 几何的表示方法
表示方法主要有两种:
一是:隐式曲面
二是:显式曲面
Implicit Surpace 隐式曲面
隐式曲面的特点
隐式曲面指的是并不会告诉你任何点的信息,只会告诉你该曲面上所有点满足的关系。
比如:在三维空间中表示一个球面
f ( x , y , z ) = x 2 + y 2 + z 2 − 1 f(x, y, z)=x^{2}+y^{2}+z^{2}-1 f(x,y,z)=x2+y2+z2−1
上面就是三维空间中的球面的隐式曲面代数方程,仅仅表示的是该曲面上所有的点满足的 f ( x , y , z ) = 0 f(x, y, z)=0 f(x,y,z)=0的关系。
再比如:
f ( x , y , z ) = ( 2 − x 2 + y 2 ) 2 + z 2 − 1 f(x, y, z)=\left(2-\sqrt{x^{2}+y^{2}}\right)^{2}+z^{2}-1 f(x,y,z)=(2−x2+y2)2+z2−1
表示的是空间之中的一个圆环曲面
隐式曲面的优缺点
- 优点:隐式曲面的表示方法比较简单,只需要知道曲面的代数方程即可。同时,可以很容易的判断点与曲面的位置关系,比如:判断一个点是在曲面内还是在曲面之外
- 缺点:表示比较抽象,无法直观的想象出曲面的形状
隐式曲面举例
利用代数方程表示一个♥️的隐式曲面已经很不具规律了,那么如何表示一个更为复杂的曲面呢?
表示复杂隐式曲面的方法 Constructive Solid Geometry(CSG)
大致思路就是,将几个简单的曲面来进行最基本的并集和交集操作,然后再将这些曲面进行组合,最后得到一个更为复杂的曲面。
实现几何体逐渐混合的效果:符号距离函数(Signed Distance Function)
符号距离函数 Signed Q Q Q Distance Function是某度量空间X中的一个集合 Ω \Omega Ω 的函数,决定X中任一点到 Ω \Omega Ω 边界 ∂ Ω \partial \Omega ∂Ω 的距离,并且由x是在 Ω \Omega Ω 内还是 Ω \Omega Ω 外确定其SDF的正负号:当x在 Ω \Omega Ω 内时,SDF为正;当x在 Ω \Omega Ω 外时,SDF为负。假设 d d d 是空间 X X X 的一种度量,那么SDF用数学公式表达:
f ( x ) = { d ( x , ∂ Ω ) if x ∈ Ω − d ( x , ∂ Ω ) if x ∈ Ω c f(x)= \begin{cases}d(x, \partial \Omega) & \text { if } x \in \Omega \\ -d(x, \partial \Omega) & \text { if } x \in \Omega^{c}\end{cases} f(x)={d(x,∂Ω)−d(x,∂Ω) if x∈Ω if x∈Ωc
个人理解:就是通过正负来做成渐变的这种效果,比如,两个正数相加就会得到比以前更大的数,而一个正数和一个负数相加所取得的结果值取决于两者之间绝对值的大小,但结果的绝对值一定比两者都要小,这样就会起到一定的渐变效果
定义空间中每一个点的SDF为该点到阴影区域右边界的垂直距离,在阴影内部为负,外部为正,因此对于A和B两种阴影来说的SDF分别如上图下半部分所示。最终正正负负可以相互增加,相互抵消,从而有了渐变的效果,也就是从最小的负值逐渐变换到最大的正值
Level Set Method(LSM)水平集
水平集(LevelSet)是一种图像分割方法,就像阈值法(threshold),分水岭(watershed),图割算法(GraphCut)一样,只不过它主要用于医学图像分割。
首先,回顾一个概念:就是等高线
看下面的曲面,红色的虚线就是一条等高线。
那么水平集算法的核心思想是什么?
那就是将要研究的问题,看做是更高一维空间的函数(也就是水平集函数)的零水平集。
因此,当我们要追踪某一曲线(曲面)的演化过程,实际上就等价于追踪更高一维曲面的演化过程。
比如:
如上图1至2的演化过程,如果对红色曲线建立一个随时间而变化的模型,是很困难的,因为发生了拓扑结构变化(一条曲线变成了两条),但是如果只是对蓝色的曲面建立随时间变化的过程,则是可行的,而红色曲线就是取其Z=0的水平集。
分型几何 Fractals
分型几何是指许许多多自相似的形体最终所组成的几何形状。
比如:
总的来说隐式曲面具有形式简单,轻易判断点与曲面关系等优点,但难以采样曲面点和模拟过于复杂的形状
Explicit Surface 显式曲面
显式曲面特点
对于显式曲面来说是与隐式曲面相对应的,所有曲面的点被直接给出,或者可以通过映射关系直接得到
All points are given directly or via parameter mapping
区别隐式曲面与显示曲面的关键: 就在于是否可以直接表示出所有的点
隐式曲面难以采样曲面上的点,但是可以轻易判断点与曲面的关系,
对于显式曲面来说恰恰相反,我们可以很轻易的采样到所有的点,但是给予你任意一点却很难判断它与曲面的关系!
显式曲面举例
点云
顾名思义,就是很多很多的点构成的曲面,直接有着所有点的信息,多过点多模型细节就多,点少模型细节就少。
例如:
多边形网格 Polygon Mesh
对于多边形网格来说,该方法广泛应用在计算机图形当中,简单来说通过定义各个多边形面的顶点以及顶点之间的连接关系以及各个所形成的面的特点,就可以得到许许多多的三角形面或是四边形面,再通过这些面来近似表现出我们想要的模型效果。
贝塞尔 Bezier (important)
贝塞尔曲线 Bezier Curve
其中 p 0 , p 1 , p 2 , p 3 p_0,p_1,p_2,p_3 p0,p1,p2,p3为控制点,蓝色所表示曲线正是贝塞尔曲线
画出贝塞尔曲线的过程:
从三个控制点来推导二次贝塞尔曲线
-
给出三个控制点的坐标
-
给定一个时间 t t t( [ 0 , 1 ] [0,1] [0,1]),利用线性插值的原理计算出 b 0 b 1 , b 1 b 2 b_0b_1,b_1b_2 b0b1,b1b2上的在t时点的坐标
b 0 1 = b 0 + t ∗ ( b 1 − b 0 ) b_{0}^{1}=b_{0}+t *\left(b_{1}-b_{0}\right) b01=b0+t∗(b1−b0)
-
将其点的坐标再进行连线然后再找到点的坐标,直到新产生的点仅有一个
-
将时间进行不断从0到1的变化,直到得到一条曲线
其核心所在就是多次的线性插值,并在生成的新的顶点所连接构成的线段之上递归的执行这个过程,直到得到最后一个顶点
同样的,利用上述方法,也可以将控制点数增多,从而再画出一条曲线
将曲线的点转变为统一代数形式
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 \begin{aligned}&\mathbf{b}_{0}^{1}(t)=(1-t) \mathbf{b}_{0}+t \mathbf{b}_{1} \\&\mathbf{b}_{1}^{1}(t)=(1-t) \mathbf{b}_{1}+t \mathbf{b}_{2} \\&\mathbf{b}_{0}^{2}(t)=(1-t) \mathbf{b}_{0}^{1}+t \mathbf{b}_{1}^{1}\end{aligned} b01(t)=(1−t)b0+tb1b11(t)=(1−t)b1+tb2b02(t)=(1−t)b01+tb11
b 0 2 ( t ) = ( 1 − t ) 2 b 0 + 2 t ( 1 − t ) b 1 + t 2 b 2 \mathbf{b}_{0}^{2}(t)=(1-t)^{2} \mathbf{b}_{0}+2 t(1-t) \mathbf{b}_{1}+t^{2} \mathbf{b}_{2} b02(t)=(1−t)2b0+2t(1−t)b1+t2b2
由此,我们可以得到一般性公式:
b n ( t ) = b 0 n ( t ) = ∑ j = 0 n b j B j n ( t ) {\mathbf{b}^{n}}(t)=\mathbf{b}_{0}^{n}(t)=\sum_{j=0}^{n} \mathbf{b}_{j} B_{j}^{n}(t) bn(t)=b0n(t)=j=0∑nbjBjn(t)
其中:
B i n ( t ) = ( n i ) t i ( 1 − t ) n − i B_{i}^{n}(t)=\left(\begin{array}{c}n \\i\end{array}\right) t^{i}(1-t)^{n-i} Bin(t)=(ni)ti(1−t)n−i
贝塞尔曲线特点
-
必定经过起始与终止控制点
-
必定经与起始与终止线段相切
-
具有仿射变换性质,可以通过移动控制点移动整条曲线
-
凸包性质,曲线一定不会超出所有控制点构成的多边形范围
对于上图所示的由11个控制点所得到的10次贝塞尔曲线,由于控制点众多,很难控制局部的贝塞尔曲线形状,因此为了解决该问题,有人提出了分段贝塞尔曲线,即将一条高次曲线分成多条低次曲线的拼接,其中用的最多的便是用很多的3次曲线来拼接,如下图:
如果想要使得拼接的点看起来较为光滑的话,就要满足一些函数光滑连续条件如:一阶光滑连续(连接点导数存在),但是,我们还不想让这个曲线在连接处局部发生特别大的变化,所以,可以让两侧导数的极限在这一点相等,从而实现更加平滑的过渡
贝塞尔曲面 Bezier surface
曲线到曲面就是将空间升一维度的问题,也就是,之前的一个t来找到空间中的点形成的无数条曲线,然后,再引入一个v,来找这些形成的曲线上的点,再将这些点,随着v的变化而形成曲线,这样两个方向上的无数条线就会构成一个曲面
Mesh Subdivision 曲面细分
Loop 细分
loop细分是专门针对三角形的细分方法
具体步骤如下:
-
生成更多的三角形或顶点
-
调整这些三角形或者顶点的位置(纹理等)
我们将所有的顶点分为两类,一类是新生成的顶点,一类是老的原来就有的顶点,对于新生成的顶点做如下处理:- new vertices
这里新的顶点就是白色的那个顶点,其位置为周围4个顶点的权重之和,各顶点权重如图所示,其余边上的新顶点处理类似。
- old vertices
其实旧每个顶点的处理也十分类似,这里以图中一个白色旧顶点为例,也是其自身以及邻接顶点的权重和,但权重的设置与该旧顶点度数有关,具体如图中右下部分所示。
最后效果
Catmull-Clark细分(Catmull-Clark Subdivision)
针对于有四边形和三角形混合的曲面细分
方法的部分定义:
对于所有不是四边形的面,称之为Non-quad face
所有度不为4的顶点称之为奇异点
步骤:
-
在不是四边形的面里面添加一个点,这个点可以是自己选定的任意一个点,然后在围成这个面的边的中点上引出一条线,来连接这个点:
-
特点:
有几个非四边形面,就会多出几个奇异点,所以现在一共有2+2 = 4个
新多出来的奇异点的度数与原来所在面的边数相等,如这里就是3度
第一次细分之后所有面都会变成四边形,且往后奇异点数目不再增加 -
各个点坐标计算
Vertex point 顶点
效果:
Mesh Smplication 曲面简化
其实曲面简化所利用的一个方法叫做边坍缩,如上图所示就是将一条边的两个顶点合成为一个顶点。但随之而来的问题就是,曲面简化需要尽量保持原本模型的shape,如何坍缩一条边,或者说坍缩哪一条边能够使得原模型样貌被改变的程度最小,这就是曲面简化的关键所在。
为此,科学家引入了一个度量:二次误差度量,这个度量可以衡量曲面简化的效果。
表述为:坍缩之后蓝色新顶点所在的位置与原来各个平面的垂直距离之和。
如果能够使得这个误差最小那么对整个模型样貌修改一定程度上也会较小。
步骤:
- 为模型每条边赋值,其值为坍缩这条边之后,代替两个老顶点的新顶点所能得到的最小二次误差度量
- 选取权值最小的边做坍缩,新顶点位置为原来计算得出使得二次误差最小的位置
- 坍缩完之后,与之相连其他的边的位置会改动,更新这些边的权值 (这里有个动态更新的数据结构,使得每次更新放在前面的值始终都是最小的结果—优先队列)
- 重复上述步骤,直到到达终止条件
效果: