二维空间内的三角剖分 -- (给出边缘顶点的例子)

  三角剖分的种类很多, 根据不同需求有各种各样的算法, 这里讲的是按顺序给出边缘顶点之后, 如何对这个顶点集合进行三角剖分.

比如下面的图示:

图一

  给出了边缘点并按顺序排列, 将它剖分成三角形, 虽然有多种方法, 不过我们只需要获得正确的三角形就行了, 不用关心它剖成怎么样.

对于凸多边形(Convex Polygon), 只需要像图中一样, 找一个起始点, 然后按顺序取点跟起始点组成三角形就行了, 非常简单. 代码都懒得写了.

  而对于凹多边形(Concave Polygon)就不能简单划分三角形了, 因为会超出原有多边形的范围 :

图二

  ACD组成的三角形明显超出了边界, 不能简单剖分.

  PS: 不要把这个和 delaunay triangulation 搞混了, delaunay做的是离散点的三角剖分, 获得的是这些离散点组成的凸多边形.

  我是最近才有这个功能要做, 所以找了一下相关的实现方法, 发现很多人的实现基于很早以前的某篇论文<<三维模型重建中的凹多边形三角剖分>> : 解放军测绘学院学报 1999年9月刊.

而且看了下基本都是抄来抄去, 代码不少, 错误不少, 基本都没有实现这个剖分逻辑...... 论文也是很有问题, 给出了几个定义, 几个性质, 然后就给出了算法, 至于算法的正确性证明也没有, 我就

直接相信它吧.

  把论文的算法精简出来就有那么几步 ( 比如顶点列表为 List<Vector3> points, 排列顺序就是在List中的顺序 ) :

  一. 寻找出一个凸顶点

    1.1 定义: 临时从列表中去掉某个顶点, 然后列表剩下的顶点构成新的的多边形, 这个被去掉的顶点不在新多边形内部, 就是凸顶点 ( 比如图二中的 A, B, C, D, E 点都是凸顶点, F点被AE组成的多边形包在里面, 所以不是凸顶点 )

    1.2 功能 : 如果不是凸顶点, 把这个顶点插回列表原来位置. 找下一个顶点, 如果是凸顶点, 测试是否可划分顶点.

  二. 确定该凸顶点是可划分顶点

    2.1 定义 : 被去除掉的点和原列表中左右相邻的点组成的三角形, 如果不包含列表中的其它顶点, 就是可划分点 ( 比如图二中的 ABC 里面没有其它点, B点就是可划分点. ACD 中有F点C点就不可划分 )

    2.2 功能 : 如果不是可划分顶点, 把这个顶点插回列表原来位置. 找下一个顶点

  三. 可划分就把顶点从列表中删除

    3.1 功能 : 把之前该点组成的三角形记录到返回值列表中, 它就是一个剖分出来的三角形. 不插回去就等于删除了.

  四. 一直重复直到只剩最后3个顶点, 最后3个顶点就是最后一个三角形.

    4.1 功能 : 把最后三个顶点作为一个三角形加到返回值列表中, 剖分就完成了.

  

  说明一下我用的是Unity3D, 原始顶点列表作为输入, 返回值输出的是剖分后的三角形顶点, 而不是组成三角形的Index, 因为Mesh需要normal的数量跟顶点数量一致, 如果Mesh使用原始顶点列表作为顶点的话(比如正方体只有8个顶点),

然后通过Mesh.triangles 来设置三角形的话, 它自动计算出来的normal也是只有8个, 也就是说它把各个共享顶点的向量进行了插值, 光照会出错的.

  下来就是代码实现了

猜你喜欢

转载自www.cnblogs.com/tiancaiwrk/p/11052699.html