【图形学】网格简化及边坍缩( Edge Collapse )算法
本文参考论文: Surface Simplification Using Quadric Error Metrics
本文参考书籍:Real-Time Rendering 第四版
目录
1. 网格简化
1.1 网格简化的意义
1.2 网格简化的分类
2. 边坍缩(Edge Collapse)算法
2.1 边坍缩算法的特性
2.2 基于二次度量误差的边坍缩算法
2.2.1 代价函数
2.2.2 坍缩代价和最佳坍缩位置计算
2.2.3 算法流程
2.3 边坍缩过程中需要注意到的问题
本文简要介绍了网格简化的基础及意义,重点介绍了边坍缩(Edge Collapse)算法的好处以及具体实现细节。
1. 网格简化
网格简化本身非常好理解,就是将复杂的网格模型通过一些操作之后缩减成较为简单的模型,如下图所示:
1.1 网格简化的意义
网格简化的主要使用于实时工作的场景,网格简化能够减少存储和渲染三角形的数量。此外,网格简化在游戏中使用的非常频繁,比如在渲染大型场景的时候,人物通常只能看见非常有限范围的场景,对于非常远的物体通常是仅能看看一个大概的轮廓。这个时候如果远处的物体具有大量的三角面片,这势必会消耗大量的渲染资源,然而人物却感知不强,通俗的说就是性价比不高。此时通常的解决方案是对于远处的物体使用一个简化了的模型进行渲染,这样就能够保证用户感知的同时提高了程序性能。
1.2 网格简化的分类
网格简化可以分为 静态、动态 以及 基于视点的方法。(参考自Real-Time Rendering 第四版 第16.5节)
静态简化的方法是在渲染之前创建好不同层级的Lod模型,在渲染的时候通过事先设定好的条件选择一个模型用于渲染。
动态简化提供了LOD模型的连续谱,而不是静态LOD的离散模型,这种方法称为连续细节层次(continuous level of detail)。
View-Dependent 技术适用于模型中细节层级不同的地方,比如在地形渲染中,近处需要渲染的非常细致,而远处渲染的比较粗糙就足够了。
今天的主角是动态简化中的使用的一种重要的方法——Edge collapse 算法。
2. 边坍缩(Edge Collapse)算法
边坍缩算法是一个迭代算法,通过不断迭代进行边坍缩操作达到简化模型的目的。
边坍缩操作是移动一条边的两个使它们重合,以消除一条边。上图展示了一次边坍缩的操作,只是简单的将u点坍缩到v点,但是这样的到的网格质量往往不够好,因此一般会将u和v坍缩到一个新的点,在u和v连接的线段上,比如中点,也有一些优化策略讲述坍缩到u和v上的哪一个位置。(下面会介绍基于二次误差度量的边坍缩算法)
2.1 边坍缩算法的特性
a. 边坍缩具有一个非常好的性质——边坍缩的过程是可逆的。因此,可以通过将坍缩边按照顺序存储,从简化的模型开始,重构出复杂的模型。这对模型的网络传输非常有用,可以先传输比较粗糙的模型,然后持续的传送折叠边的信息,并逐步的构建出原始的复杂模型。这种方式通常被归于view-independent progressive meshing(视点无关的渐进式网格划分)。
b. 边坍缩操作以及代价计算都是局部的,一条边的折叠代价只取决于几个相邻的局部变量(边长度,靠近边的面法线的影响),很容易计算,同时,每次折叠边仅影响它的几个临边的代价函数。比如说一个模型需要坍缩3000个边,首先坍缩的边肯定是坍缩代价最小的边,由于坍缩这个边仅仅影响相邻的三角形以及边,所以只需要重新计算这些边的代价函数(假如有十个),每次坍缩的计算量就很小,额外的代价仅仅是对新的边进行重排,维护这个代价列表的很好的数据结构是堆和优先级队列。
2.2 基于二次度量误差的边坍缩算法
该方法的本质目的是每次坍缩让网格变化最小的那条边,这就需要引入一个代价函数,使网格变化较小的坍缩边具有较小的代价。本方法的代价通过坍缩之后的点到原始网格中相邻的面的距离衡量。
2.2.1 代价函数
设网格中一个顶点v具有n个相邻的面,原始的每一个面的平面方程为 pi = [ai,bi,ci,di])(平面法向量为单位向量),则可以将顶点v(v_x,v_y,v_z)相对于该网络的误差定义为,点到每个平面的距离的平方和(在初始网格的状态下,所有点的误差均为0,因为都在面上),如下表示:
其中Kp是一个矩阵,用来求空间中任意一点到平面p的距离平方和 :
用矩阵Q表示与点v相邻的平面集合的Kp之和,则: △(v) = v^T * Q * v
则每一个点都维护一个自己的代价矩阵Q,就能够很简单的计算坍缩一条边的代价。
2.2.2 坍缩代价和最佳坍缩位置计算
1. 坍缩代价计算
假设一个边的两个点v1和v2坍缩到一个新的点v_new,则v_new的代价矩阵是:Q_new = Q1+Q2。
坍缩代价为: △(v_new)= v_new^T * Q_new * v_new, 其中v_new的位置能够使得坍缩代价△(v_new)最小。
可以注意到我们在计算新的顶点的代价矩阵时,只是简单的使用了一个加法运算,而不是根据相邻面的Kp矩阵计算,这很明显会引入一个误差,因为这个近似仅在Q1和Q2中表示的平面集合没有交集的时候成立,但是网格中一般都是有所交集的(有相同的相邻面)。虽然引入了一些误差,但是这样做的好处在于跟踪平面集所需要的空间仅仅需要一个4*4的矩阵,而且在计算新的顶点的Q的时候也仅仅是两个矩阵相加的计算量。
2. 最佳坍缩位置计算
Q_new是我们确定了坍缩了哪一个边之后能够直接确定的,此时如何找到最佳的v_new的位置是非常重要的,这能够有效的保证网格变化最小。
具体而言,对代价 △(v_new)= v_new^T * Q_new * v_new = q11x^2 + 2q12xy + 2q13xz + 2q14x + q22 y^2 + 2q23 yz + 2q24 y + q33z^2 + 2q34z + q44 (展开形式)
分别对x,y,z求偏导,通过 ∂△/∂x = ∂△/∂y = ∂△/∂z = 0确定v_new的位置 ,最终这等价于求解:
如果左侧矩阵是可逆的,则v_new的坐标 可以直接求出:
如果矩阵不可逆,则沿着v1->v2 分段寻找最优的位置,如果这也找不到则直接取v1和v2的中点即可。
2.2.3 算法流程
在了解前面描述的内容之后,边坍缩算法就非常简单了,下面放上算法的整体流程:
- 计算初始点的Q矩阵
- 选择所有的有效点对,即可以坍缩的边
- 计算每个有效对坍缩之后的代价,代价 = v_new^T * (Q1 +Q2) * v_new
- 将所有有效对放置在一个以代价为键值的堆中,最小代价放在顶部
- 迭代的从堆中删除代价最小的对,坍缩每个边,并更新涉及v1的所有有效对的代价
2.3 边坍缩过程中需要注意到的问题
1. 有时对于地形这种网格,则需要保留边界,这通过增加初始误差的惩罚项。
2. 在坍缩一条边之后,有可能造成相邻面折叠的情况,即坍缩边之后,相邻面的法线方向变成反方向。如下图:
在网格简化的过程中应禁止这种情况的发生,可以通过检测相邻面的法线方向判断。
【图形学】网格简化及边坍缩( Edge Collapse )算法相关推荐
- 12、计算机图形学——几何(网格细分与网格简化)
一.网格细分 1.1.概念 网格细分指的是将原有模型上的网格分成更多个网格,从而将模型变得更加精细,提高渲染出来的效果,让画面更加漂亮 下图就是一个网格细分的示意,左图是细分前的效果,右图是细分后的效 ...
- 实现边坍塌的网格简化方法
一.算法介绍 关于边塌陷的网格简化方法,SIGGRAPH 有一篇97年的论文Surface Simplification Using Quadric Error Metrics(Michael& ...
- 视相关细节层次网格简化方法(VDPM-LOD)
基于视相关技术的 LOD 允许使用复杂度可变的三角形网格面来渲染同一个对象, 可以根据对象和视点的相关位置来动态调整网格的复杂性 .当对象接近视点时细化三角形网格 , 当对象远离视点时粗化三角形网格 ...
- Unity使用波函数坍缩 (Wave Collapse Function)算法生成随机地图
在游戏领域和人工智能领域有一个随机生成地图用的比较多的算法叫做波函数坍缩 (Wave Collapse Function)算法,这个算法可以根据自己定制的规则生成随机地图. 根据波函数坍缩算法的源码 ...
- line划线计算机图像学,【计算机图形学】根本图形元素:直线的生成算法
[计算机图形学]基本图形元素:直线的生成算法 08年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大学生活.此系列是对四年专业课程学习的回顾,索引参见:http://blog.csdn.net ...
- c语言计算机图形来画八分画圆,【计算机图形学】基本图形元素:圆的生成算法...
08年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大学生活.此系列是对四年专业课程学习的回顾,索引参见:http://blog.csdn.net/xiaowei_cqu/article/de ...
- 图形学笔记(十)几何2 —— 曲面细分(Loop细分、Catmull-Clark细分)、曲面简化(边坍缩、二次度量误差)、曲面正则化
图形学笔记(九)几何 --几何表示方法(CSG.距离函数.水平集 .点云.网格(obj格式)).贝塞尔曲线(面) 图形学笔记(十一)光线追踪--Shadow Mapping.光线追踪.光线投射.软硬阴 ...
- Unity使用Mesh Simplify 减面(网格简化)
基于性能的考虑,有些模型需要减面,然而做独立游戏的我,又找不到美术去做.只能想办法用程序减.然后,发现了Mesh Simplify这个插件: 导入模型,进行试验: 如下图,默认场景默认光,10.7k ...
- 图形学基础笔记II:多边形光栅化算法和显卡三角形光栅算法
为什么三角形就够了 实际对于 3D 来说肯定全是基于三角形的 geometry - OpenGL: Is it more efficient to use GL_QUADS or GL_TRIANGL ...
最新文章
- 用C编写的诙谐幽默的关机程序。
- jira 8.2.1 安装 及一些常见的坑
- 【ARM】Tiny4412裸板编程之异常
- OO第四单元博客作业
- mysql中使用BETWEEN AND
- go语言学习笔记(5)数组与切片
- 【转】Asp.Net TreeView with CheckBox
- android picasso 圆形,Andorid开发之Picasso通过URL获取用户头像的圆形显示
- Matlab2018破解方法
- 李秋豪计算机系统,CS:APP3e 深入理解计算机系统_3e Y86-64模拟器指南
- 开心电视助手v3.8最新绿色版,安卓设备远程管理工具神器
- mysql设置59分59秒会自动加一秒
- C#对数据库的各种操作
- vue 全局/局部组件
- UE4在Android平台调试
- 如何将EasyCVR平台RTSP接入的设备数据迁移到EasyNVR中?
- 边界外推和边界处理--cv::copyMakeBorder()和cv::borderInterpolate()
- 集体备课模板_集体备课模板
- 中小型企业有没有实施ERP的必要
- 一款可以实现淘宝拼多多虚拟店商品自动发货的百度网盘机器人软件助手