用于切割网格的算法或软件

时间:2012-03-14 20:41:36

标签: c++ graphics visualization computational-geometry mesh

切片3D网格的正确方法是什么?网格都是闭合曲面,切片需要是网格内部的二进制图像。因此,例如,表示球体和切片图像的网格是实心圆的网格。

我正在寻找可以集成到我当前的C ++项目中的软件库或算法。

5 个答案:

答案 0 :(得分:20)

我的开源游戏库包含网格切片的实现。它适用于Irrlicht api,但可以通过适度的努力重写为使用不同的API。您可以使用BSD许可条款下的代码,或从中学习您自己的工具。

请参阅this file for an implementation of mesh slicing中的MeshTools :: splitMeshZ。

如果你只是想知道算法,这里是对我所做事情的高级描述:

我最初想过使用轴对齐的边界框来指定切割网格的位置。这是有问题的,因为它引入了许多特殊情况。例如,穿过盒子角落的边缘可以分成三块而不是两块。

使用平面将网格切割成左侧网格和右侧网格可减少特殊情况的数量,因为边缘位于平面的一侧或另一侧,或者它与平面交叉,因此被切断分成两部分。

任何所需的切割配置都可以简单地通过切割一次,取出一个所得到的网格并在另一个位置再次切割,等等。特别是在您在该部分中描述的情况下,可以通过将球体的一半切掉,将平面移动少量并切掉另一半而仅留下一个薄带来从球体切割圆圈。 (你不能用我编写的代码将网格切割到几乎没有深度,但你可以将网格切割到你设置浮点平等阈值的任何东西。我想我在我的代码中任意选择了0.001 。)

使用类似的逻辑,可以使用固定平面实现切割平面的任何所需角度;您只需要转换网格以相对于固定切割平面旋转它,然后将结果转换回来。 (对于我的游戏,我只需要垂直于XY平面的切割,所以为了简单起见,我只允许设置切割的Z值,并假设切割位于Z位置。)

好的,既然我们已经简化了问题,那么算法并不是那么糟糕:

开始条件:你有一个切割平面。你有一组源三角形。您有两个目标集多边形(不是三角形;可以通过切割三角形生成四边形)。两个目标集称为左和右。

过程:迭代三角形的三个点。计算小于切割平面的点数。我会称那些小于切割平面左侧的那些和那些大于切割平面右侧的那些。只有少数案例:

  • 所有三角形点都在左侧:将三角形放在左侧集合
  • 所有点都在右边:将三角形放在右边的集合中
  • 一点是左,另一点是右:如果你在两条边上切一个三角形,并且你拿着一个点,你最终会拿一个较小的三角形。在由左点组成的左侧集合中放置一个三角形,在边缘与平面交叉的两个点上放置一个三角形。在右侧设置一个四边形(见下一个案例)。
  • 两点是左,一点是右。如果你握住一个三角形的边缘并将其切割到另外两个边缘,那么你将保持一个梯形。将一个四边形放在由手中的两个点组成的左侧组中,加上两个穿过切口的点。在右侧设置一个三角形(上面的镜像图像)。

  • 完成后,通过在最短的部分添加链接将四边形转换为三角形。

那就是它。这是基本算法。实际代码处理一些更多的情况,例如,如果边缘与切割完全相等,如果三角形恰好位于边缘,不添加退化多边形(例如,没有主体的点),等等。

混杂。问题(所有内容都包含在链接代码中):

  • 不要为LERP的数学过度复杂化,即边缘穿过切割平面的地方。它不需要完整的线性插值,它实际上只是Highschool代数II:超越运行,倍数比率

  • 缓存生成的(LERP' ed)点是有利的,这样在未切割网格中共享顶点的三角形将共享切割网格中相应的新顶点。

  • 如果您要保留顶点共享,并且您正在使用三角形索引缓冲区,那么当您第一次生成要放入左侧和右侧集合的形状时,遗憾的是您还不知道索引。我使用了一个名为" PossibleVertex"表示未来的三角形指数。

  • 如果要显示网格,缠绕顺序很重要。仔细考虑如何对其进行编码可以确保生成的多边形使用与它们来自的三角形相同的绕线顺序。在对四边形进行三角测量时,这尤其棘手。我无法记住详细信息,但它们都是在链接代码中处理的。

  • 对于我的游戏,我想制作一个连接两个切割网格的扁平色带。这就是为什么splitMeshZ会产生3个网格而不仅仅是两个网格的原因。您可以使用中间网格,或者只是忽略它。

答案 1 :(得分:3)

3D网格切片中的项目(使用C ++中的源代码):

http://www.dainf.ct.utfpr.edu.br/~rminetto/projects/slicing/

答案 2 :(得分:2)

我已经概述了在this answer中计算平面体积交点的算法。提供了Java实现。

答案 3 :(得分:1)

我假设你在谈论三角网格?

什么是“正确”的方法很大程度上取决于您的用例的具体情况。

Jerry建议的OpenGL方法可能适合你。

另一种方法是明确计算削减。您可以使用CGAL进行此操作。更具体地说,它的3D内核。它具有function,可以计算各种基元之间的交叉点,包括平面和三角形。使用此功能,您可以准确计算交叉点轮廓并将其渲染为图像。 - 这样你就不会依赖OpenGL而是依靠CGAL了。

答案 4 :(得分:0)

如果你自己实现它会更快(对你自己而不是运行时):这些是你需要做的简单步骤:

1 - 提取网格的所有三角形

2 - 对于每个三角形,

2-1-检查切片平面上是否有任何三角形点,

2-2-如果不是,那么对于它的三个边缘中的每一个,找到与切片平面的交点(如果有的话)。你必须要么有2个与飞机相交或没有。

2-2-1如果2条边与平面相交,则在平面上的这2个点之间添加一条线。