Geometry¶
约 1567 个字 94 行代码 1 张图片 预计阅读时间 9 分钟
Introduction¶
隐式几何: \(f(x,y,z)=0\)
使用隐式表示,可能难以想想图形长什么样;但是很方便判断某一点是否在图形上
显式几何:直接给出或通过参数映射给出各个点(或小三角形)的坐标
对于同样一个几何形体(y和z调换一下):
Implicit¶
Constructive Solid Geometry¶
Distance Functions¶
对每个点维护它们离几何图形最近的距离,当两个图形需要 Blend 时,将 Signed Distance Function 相加以更新:
当我们对两个几何形体进行 Blend 时,面上某个点的距离函数更新为其对分别两个图形的距离函数的相加,则融合后的几何形体的边界为新的距离函数等于0的点。
Level Set Methods¶
与距离函数类似,但是是每个格子维护一个相对高度。
即等高线
Fractals¶
即分形,可以类比算法中的递归,用来描述自相似的几何图形,但是较难控制形状。
比如雪花。
Explicit¶
Point Cloud¶
用一组点表示几何图形,点云密度足够大才能表示一个较为复杂的模型。
在实际应用中通常需要转换为三角形面。
Polygon Mesh¶
多边形面表示是图形学中使用最广泛的显式几何,非常方便进行处理、仿真、采样等操作。
在 Wavefront Object File (.obj
) 中,多边形面的格式如下:
Bezier Curves¶
贝塞尔曲线使用一系列控制点来定义一段曲线。
先考虑只有三个控制点的二阶贝塞尔曲线(quadratic Bezier):
其中 \(\frac{b_0 b_0^1}{ b_0 b_1} = \frac{b_1 b_1^1}{b _1 b_2} = \frac{b_0^1 b_0^2 }{b_0^1 b_1^1} = t\)
数学上,易证明得到(上标表示层数,不是平方):
同样适用于更多点数:
那么有 Bernstein Form of order n:
其中 \(B_j^n(t)\) 称为 Bernstein polynomial。
最常用的是有四个控制点的四阶贝塞尔曲线 Cubic Bezier
贝塞尔曲线有如下性质:
- 起点和终点满足:\(b(0)= b_0, b(1)=b_n\)
- 起点和终点的切线满足:\(b'(0)=n(b_1 -b_0), b'(1)= n(b_n -b_{n-1})\)
- 对控制点先做仿射变换再画贝塞尔曲线得到的结果与对控制点先画贝塞尔曲线再对曲线仿射变换一样(几何不变性)
- 贝塞尔曲线一定位于控制点形成的凸包内
Convex Hull
即能包围给定点的最小凸多边形
通常使用 Piecewise cubic Bezier curve (分段,每四个点,贝塞尔曲线)作为曲线描述。例如 PS 中给出的钢笔工具就是采用四个点作为控制点来画出贝塞尔曲线。
You can try in Bezier curve edit
连续性
若只是方向相同,定义为该处 C0 Continuity;若方向和距离都相同,定义为该处 C1 Continuity
用 Unity
写的一个贝塞尔曲线实现:
使用C++ openCV
的 de Casteljau's algorithm 实现方式:
虽然递归形式慢,但是方便支持更多点的贝塞尔曲线
Bezier Surfaces¶
For bi-cubic Bezier surface patch,
- Input: 4 * 4 Control Points
- Output: 2D surface parameterized by \((u,v)\) in \([0,1]^2\)
具体做法是对每四个点都画出对应的贝塞尔曲线,再对每四个贝塞尔曲线上 \(t\) 时刻运动的四个点画出画出一个 moving curve。
Mesh Operation¶
- Subdivision 细分
- Simplification 简化
Loop Subdivision¶
Loop 细分和循环没关系,是因为算法的发明人姓 Loop
- <1> Split each triangle into four
- 连接三角形每条边的中点,将其拆分为四个小三角形
-
<2> Assign new vertex positions according to weights
- 根据权重更新顶点的位置
-
对于新顶点(中点),它与两个顶点直接连接,与两个顶点不直接连接但在同一个三角形内,那么对其加权平均更新:
- 对于旧顶点,根据连接的旧定点数(该节点的度)选择不同的权重加权平均:
Catmull-Clark Subdivision¶
上述 Loop 细分只能应用于网格呈三角形的模型,而 Catmull-Clark 细分适用于更 General 的网格。
定义非四边形面为 Non-quad face
,定义度不为四的点为 Extraordinary vertex
:
对每一个面取中心点,对每一条边取中点,并把这些新的点全部连接起来。那么细分之后,在 Non-quad face
中会增加一个奇异点,而所有的非四边形面均消失:
所以在之后的细分中,奇异点的个数不会增加。
坐标更新的加权平均算法如下:
Collapsing An Edge Simplification¶
在保留整体形状的前提下减少网格面数,从而降低性能需求。
在 Games101 课程中介绍的简化算法为边坍缩。
为了实现这个算法,我们引入二次误差(Quadric Error)的概念,其定义为一个新顶点到原本相关的三角形平面的距离的平方和。
类似机器学习中的 L2 Distance
对于整个模型,计算每一条边坍缩后造成的二次误差,而选择误差最小的边坍缩。坍缩后更新与这两个点相连的所有边的误差值,然后继续坍缩。
数据结构
该算法的一般操作为取最小值以及修改键值,所以用来存储二次误差值的数据结构应该选择优先队列。
这实际上是一种贪心算法,并不保证结果的最优性