我是靠谱客的博主 简单鸡,最近开发中收集的这篇文章主要介绍【笔记】Loop曲面细分算法c++实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、概述
二、思路
       1、Loop算法简述
       2、更新策略
       3、三角面细分操作
       4、操作流程
三、数据结构
四、参考资料


一、概述

上课作业。基于半边数据结构实现了Loop曲面细分算法。

 

二、思路

1、Loop算法简述

Loop细分是一种三角网络的细分法则。算法本身挺简单的,主要就是把1个旧三角面片分成4个新三角面片,涉及到半边数据结构操作的部分有点麻烦。具体:每次细分,每条边上计算插入一个新顶点,同时每个原始顶点更新位置。边界边/点和非边界边/点按不同策略插入/更新坐标。

 

2、更新策略

每条边上新插入的点计算坐标后暂时存储在边结构的newPos变量中,每个旧顶点计算完更新后顶点位置后暂时存储在顶点结构的newPos变量中。

更新策略如下图所示,图上为非边界情况的更新策略,图下为边界情况的更新策略。

顶点更新策略

 

3、三角面细分操作

采用如下策略进行三角面的划分:(更详细说明见参考资料链接第二条)

  • Split:对每一条旧边执行split操作,可按任意顺序执行。具体操作为:按照该边中存储的前一步已计算好的新顶点的坐标将该边断成两条边,并插入2条边连接新顶点与所处三角形的对角顶点(如果该边是边界,则新插入的边为1条)。
  • Flip:对连接新旧顶点的新插入的边(新插入——不是由断裂原有边形成)进行flip操作。

 

4、操作流程

  • 标记原始mesh的所有顶点和边。
  • 按策略计算每条边上新插入的顶点坐标,数据暂存在边结构中。
  • 按策略计算每个旧顶点更新后的位置,数据暂存在顶点结构中。
  • 对每条旧边执行split操作。PS:要避免split新插入的边
  • 对特定边执行flip操作。PS:注意特定边的要求
  • 将暂存在顶点结构中的顶点更新后坐标,替换到顶点坐标中去。

 

三、数据结构

这部分主要是半边数据结构。之前实现欧拉操作的时候已经写过一遍,这次写起来还算顺手。区别于实现miniCAD的欧拉操作中用到的半边数据结构,本次用到的半边在层级结构上去掉了Loop那一层(此Loop非彼Loop,欧拉操作中为Solid--Face--Loop--Halfedge--Vertex + Edge--Halfedge)。

因为半边数据结构中各种面、边、点结构指来指去,为了防止内存泄漏用了智能指针。但基本都是自己瞎瘠薄用,总觉得自己用得不伦不类的,所以仅供参考。

  • 顶点结构
class Vertex
{
public:
	Point3d pos;			// 顶点坐标
	Point3d newPos;			// 更新后顶点坐标
	bool ifCalNewPos = false;		// 用于区分新旧顶点
	bool isOnBoundary = false;	// 用于判断是否位于边界
	Index idxForSave;		// 用于新mesh写出

public:
	Vertex(Point3d& p) : pos(p) {}
};
  • 半边结构
class Halfedge
{
public:
	shared_ptr<Vertex> v;
	weak_ptr<Halfedge> twin;
	weak_ptr<Halfedge> next;
	weak_ptr<Halfedge> prev;
	weak_ptr<Edge> e;
	weak_ptr<Face> f;
	
public:
	Halfedge() {}
	Halfedge(shared_ptr<Vertex>&  _v) {
		v = _v;
	}
};
  • 边结构
class Edge
{
public:
	Index ID;
	shared_ptr<Halfedge> he1;
	shared_ptr<Halfedge> he2;
	Point3d newPos;			// 用于存储新顶点的坐标
	bool ifCalNewPos = false;		// 用于判断是否计算了新顶点
	bool ifNew = false;		// 用于判断是否为新插入的边
	bool isBoundary = false;		// 用于判断是否为边界

public:
	Edge() {
		static Index id = 0;
		ID = id++;
	}
};
  • 面结构
class Face
{
public:
	shared_ptr<Halfedge> he;
	Point3d normal;
	bool ifNeedDelete = false;

public:
	Face(){}
	Face(shared_ptr<Halfedge>& _he) {
		he = _he;
	}
};

 

四、参考资料

  • 博客:http://www.cnblogs.com/shushen/p/5251070.html
  • cmu462/Scotty3D:https://github.com/cmu462/Scotty3D/wiki/Loop-Subdivision

强烈推荐链接2里的Scotty3D项目,虽然Scotty3D本身是个空项目,但是整个系统都搭建起来了,代码里有大量的TODO注释,还有wiki里各种生动形象且详细到令人发指的知识点介绍。半边数据结构也有介绍(虽然我是按照自己的理解瞎瘠薄写的)。看着cmu462/Scotty3D这个项目,心里满满都是羡慕qaq

最后

以上就是简单鸡为你收集整理的【笔记】Loop曲面细分算法c++实现的全部内容,希望文章能够帮你解决【笔记】Loop曲面细分算法c++实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部