[OpenGL] 网格细分算法 Loop Subdivision - 附我的实现结果
【更新】 我的新博客:www.ryuzhihao.cc,当然这个****也会更新。
本文在新博客的链接:点击打开链接
时间:2017年8月25日
一、写在前面
这篇blog可能算是大三结束之前写完的最后一篇博客了,哈哈哈。还有几天就开学成为大四,想到将要结束的大学生活,和即将到来的硕士生涯,真的充满了期待。最近开学提前返校,做了一些自己的研究工作,其中有一个步骤,就是对模型网格的细分(subdivision)。
本文采用Loop Subdivision算法实现网格细分。但是相关中文资料实在太少……,而且内容含糊,因此非常建议阅读Charles Loop在1987年提出Loop细分算法时的那篇论文原文:《Smooth subdivision surfaces based on triangles》。Notice that this paper is the master's thesis writen by C.Loop. 论文链接在博客的第三章节
在文章开始之前,还是先贴一下我的实现结果。
二、我的实现结果:
平台:C++、OpenGL 4.3+
【测试结果1】 对立方体的细分
以下四张图片分别是立方体的原始模型、细分1次、细分2次、细分5次的结果。
【测试结果2】对Stanford Bunny的细分
下图分别为Bunny的原始模型、细分2次的结果。
三、Loop细分算法原理及实现步骤
1、关于Loop Subdivision
wiki中提到Loop细分算法的一个简单定义:“In computer graphics, Loop Subdivision Surface is an approximating subdivision scheme for triangular meshes.”
Loop算法是一种面向三角网格的细分策略。细分过程包括2步:生成边点、移动原有顶点,最终生成切平面连续的光滑表面。在生成边点的过程中,将1个三角形划分为4个三角形,如下图所示:
2、Loop算法的细分过程
[1] 生成边点(E-顶点):按照下述的策略在原有三角形的边上新增一个点(即边点,E-顶点),将原有三角形1分为4。
[1.1] 生成网格内部E-顶点:
网格内部某条边的两个端点为v0、v1,共享这条边的两个三角形的面是(v0,v1,v2)和(v0,v1,v3),那么新生成的边点为:
[1.2] 生成网格边界E-顶点
网格边界E-顶点和网格内部E-顶点的区别就是,这条边位于模型的边界,只属于一个三角形,没有第二个三角形共享这条边。设这条边的两个端点为v0,v1,则新增加的顶点位置v为:
v = 1/2*(v0+v1);
[2] 移动原有顶点(V-顶点):
[2.1] 移动网格内部V-顶点:
假设原有的内部顶点为v0,相邻顶点为v1,v2,v3,v4.......vn,那么移动后的v0的坐标v为:
本质是顶点本身与相邻顶点的加权和,它本身的权值为(1-nβ),其邻接点的权值为β。这里权值β通过下式计算得到:
[2.2] 移动网格边界V-顶点:
设网格边界顶点v0的两个相邻点为v1,v2,则更新后的顶点位置为: v=3/4*v0+1/8*v1+1/8+v2。
网格化的效果如下所示:
四、参考文献:
[1] Smooth subdivision surfaces based on triangles Charles Loop' master paper
[2] Exact Evaluation of Subdivision Surfaces ACM SIGGRAPH 1998 Jos Stam