Lecture 12 Geometry 3
Mesh Operations: Geometry Processing
- Mesh subdivision
- Mesh simplification
- Mesh regularization
![image-20210120211945364](https://i-blog.csdnimg.cn/blog_migrate/48cc76cc1e30affb6e05b756661d55fb.png)
①、Mesh Subdivision (upsampling)
![image-20210121193949137](https://i-blog.csdnimg.cn/blog_migrate/313e0a8d46365a391911f6b709f632d3.png)
Increase resolution
网格细分。通过增加三角形面数来得到更加平滑的效果。
②、Mesh Simplification (downsampling)
![image-20210121193924987](https://i-blog.csdnimg.cn/blog_migrate/a8e2d4643097ce49619d0fa5880b2d5b.png)
Decrease resolution; try to preserve shape/appearance
网格简化。当一个模型很复杂,但是我看这个模型的时候距离相距很远,那么看到的细节其实没有那么多,这时候就需要对网格进行简化,去掉一些边、三角形等,但是依然要维持原来的相互连接关系,不能破坏基本结构。
③、Mesh Regularization (same #triangles)
![image-20210121194244584](https://i-blog.csdnimg.cn/blog_migrate/191e2e8283dce1535b4930d7c817400c.png)
Modify sample distribution to improve quality
三角形大小不一,长短各不相同的模型,在渲染上可能会造成很多不便。这里做一个正则化,将原来的三角形正则成大小相同的正三角形,但是同时不能丢失细节。
(一)、Subdivision
1、Loop Subdivision
Common subdivision rule for triangle meshes
First, create more triangles (vertices)
Second, tune their positions
![image-20210121202218689](https://i-blog.csdnimg.cn/blog_migrate/ba032a96fadd47cba80f58af68290479.png)
整个Loop细分分为两步,首先引入更多的三角形,然后再通过改变这些三角形顶点的位置来让整个模型看上去更光滑。
- Split each triangle into four
![image-20210121202311398](https://i-blog.csdnimg.cn/blog_migrate/6cb8dd0e53d2df58ea38e7cd5e260ca4.png)
取三角形三边的中点并相互连接,就将一个三角形分成了四个三角形
-
Assign new vertex positions according to weights
--New / old vertices updated differently
![image-20210121202424571](https://i-blog.csdnimg.cn/blog_migrate/e50d9ca99857c1f362f396bae18bed5e.png)
调整三角形顶点的位置。
将三角形的顶点区分为新的顶点和老的顶点,新的顶点即为新生成的顶点(上一步中取到的边的中点),老的顶点即为原来三角形的顶点。Loop细分将这两种不同类型的顶点,分别以不同的规则来改变他们的位置。
(Loop Subdivision并不是叫循环细分,发明这个细分方法的人的family name就叫Loop,所以就有了这个名字)
For new vertices:
![image-20210121202851436](https://i-blog.csdnimg.cn/blog_migrate/dd5dd0f1f3b8da7e795edb889dd8aacf.png)
Update to: 3/8 * (A + B) + 1/8 * (C + D).
对于新的顶点(如上图白色点),会被两个三角形所共享,将共享顶点所在的这条公共边两端的两个公共顶点分别定义为A、B,然后把这两个三角形非公共的两个顶点分别定义为C、D,然后将共享顶点(上图白色点)的位置调整为3/8 * (A + B) + 1/8 * (C + D)即可(这个式子其实就是一个简单的加权平均,A和B离共享顶点近一些,所以占的比例相对较大,而C和D离共享顶点远一些,所以占的比例相对较小)。
For old vertices (e.g. degree 6 vertices here):
![image-20210121203428690](https://i-blog.csdnimg.cn/blog_migrate/a0860d7493bd3337fc2db5e453e16d1c.png)
Update to: (1 - n*u) * original_position + u * neighbor_position_sum
n:vertex degree
u:3/16 if n=3,3/(8n) otherwise
对于老的顶点(如上图白色点),周围的老顶点会对这个顶点有一定的影响。Loop细分规定这个要计算的老顶点(上图白色点)一部分受周围老顶点的影响,一部分保持自己的位置属性。在这里我们定义一个n,为顶点的度(这个顶点连接的边的数量),再定义一个u,这个u仅仅是一个与顶点的度有关的数。得到以下公式:(1 - n*u) * original_position + u * neighbor_position_sum。从这个式子可以看到,当顶点的度很大(连了好多三角形),那么这个顶点基本就可以由周围的老顶点决定位置,当顶点的度很小(连接的三角形很少),那么这个顶点由自己原来位置决定更新后位置的比重就会增大。
2、Catmull-Clark Subdivision (General Mesh)
刚刚的Loop Subdivision仅仅可以针对全部都是三角面的网格。而Catmull-Clark Subdivision适用于更普遍的情况,无论是四边面还是三角面都可以很好地进行细分处理。
![image-20210121204507690](https://i-blog.csdnimg.cn/blog_migrate/0d7f74f30b24f2b00bfdef4e341239b3.png)
首先我们定义Non-quad face,所有不是四边面的网格形状都被称作非四边形面。
其次我们再定义奇异点(极点),所有度不为4的点都被称为奇异点。
Each subdivision step:
①、Add vertex in each face
②、Add midpoint on each edge
③、Connect all new vertices
对于每一个面,首先取这个面中心的点,然后取这个面的各个边的中点,最后把边上的中点和面中心的点连起来。
![image-20210121204831690](https://i-blog.csdnimg.cn/blog_migrate/56160337467dfb17c22affb361aa6929.png)
如上图,即为经过Catmull-Clark细分后的样子。
After one subdivision:
How many extraordinary vertices? 共有4个奇异点
What are their degrees? 原来是度是5的奇异点现在的度还是5,新引入的奇异点由于要与三角面上的每一条边的中点相连,因此度为3
How many non-quad faces? 没有非四边形面了,全部都为四边形面(细分的过程中每一个非四边形面都会引入一个奇异点,然后非四边形面就消失了)
再次细分后,面会越来越光滑。
FYI: Catmull-Clark Vertex Update Rules (Quad Mesh)
![image-20210121210701366](https://i-blog.csdnimg.cn/blog_migrate/97410615428d723d42cf39761d8cef73.png)
Catmull-Clark细分后对点的位置的更新分三种:
第一种是对于面的中心点f的更新,第二种是对于边的中心点e的更新,第三种是对于老的顶点v的更新。公式如上图所示。
Convergence: Overall Shape and Creases
![image-20210121211240085](https://i-blog.csdnimg.cn/blog_migrate/d9ec79f02e8d32180addb6d719528079.png)
Loop Subdivision仅能用于三角形面的网格,Catmull-Clark Subdivision可以用于任何形状组成的网格。
(二)、Mesh Simplification
Goal: reduce number of mesh elements while maintaining the overall shape
![image-20210121211425073](https://i-blog.csdnimg.cn/blog_migrate/fd72b26e187e9c6b38519174a9858f49.png)
How to compute?
不同情况下要用不同面数的模型,那么如何去计算对网格的简化?
Collapsing An Edge
- Suppose we simplify a mesh using edge collapsing
![image-20210121211548366](https://i-blog.csdnimg.cn/blog_migrate/3357f4de47774c3b6c339a5d728cdd4e.png)
这里提供边坍缩的方法。
边坍缩:形象的说明的话,即为一条边两端连着两个顶点,将这两个顶点往中间一捏,变成一个点,这个操作即为边坍缩。
Quadric Error Metrics(⼆次误差度量)
- How much geometric error is introduced by simplification?
- Not a good idea to perform local averaging of vertices
- Quadric error: new vertex should minimize its sum of square distance (L2 distance) to previously related triangle planes!
![image-20210121211842407](https://i-blog.csdnimg.cn/blog_migrate/955cbf27ab5c204fb910ec81a2fd77cf.png)
如上图左图,假设要简化上面三个顶点,变成一个顶点,该把这个顶点放在哪里,才能保证简化后的蓝色三角形与原本灰色多边形基本保持轮廓的一致?这里引入二次误差度量概念:我们希望把这个顶点放某个位置上,可以最小化二次误差。在此处的意思就是:把这个顶点放置在某个位置上,使得这个顶点到各个面(如上图右图,在这里看上去像是边)的距离的平方和达到最小。
Quadric Error of Edge Collapse
-
How much does it cost to collapse an edge?
-
Idea: compute edge midpoint, measure quadric error
-
Better idea: choose point that minimizes quadric error
-
More details: Garland & Heckbert 1997
对于整个模型有很多条边,假设如果坍缩一条边,并且算出把这个坍缩后的点放在最佳的位置上会得到一个多大的二次度量误差。对于整个模型而言,每次肯定都是要坍缩二次度量误差最小的边。
Simplification via Quadric Error
Iteratively collapse edges
Which edges? Assign score with quadric error metric*
- approximate distance to surface as sum of distances to planes containing triangles
- iteratively collapse edge with smallest score
- greedy algorithm… great results!
先给每个边打上一个分数,这个分数就是这个边的二次度量误差,从小的开始一个个进行坍缩。
但是问题是,如果坍缩了一条边,有一些其他的边的位置要跟着这条坍缩的边变化,那么这些边的二次度量误差就会随之发生变化。
因此这里我们要通过一种数据结构,既可以每次取到二次度量误差的最小值的边,又可以动态地以最小的代价去更新其他的受影响的元素。那么这里要使用的数据结构就是堆(优先队列)。