如何将粗2D线渲染为多边形?

时间:2009-03-26 19:18:45

标签: opengl path geometry line miter

我有一条由2D点列表组成的路径。我想将它们变成一条三角形,以渲染具有指定厚度的纹理线条(和其他类似的东西)。因此,2D点的列表基本上需要成为顶点列表,指定多边形的轮廓,如果渲染将呈现该线。问题是处理角落连接,斜角,帽子等。所产生的多边形在没有透支,干净连接等意义上需要是“完美的”,以便它可以被挤压或以其他方式玩弄。

是否有任何简单的资源可以提供算法洞察,代码或有效执行此操作的更多信息?

我绝对不想要一个完整的2D矢量库(cairo,antigrain,OpenVG等),包括曲线,弧线,破折号以及所有的铃声和​​口哨声。我一直在为OpenVG实现和其他事情挖掘多个源代码树以找到一些见解,但这一切都非常令人费解。

我绝对愿意自己编写代码,但有许多退化情况(小段+粗宽+尖角)会产生各种连接问题。即使是一点帮助也可以节省我数小时的时间来处理它们。

编辑:这是一个例子,如果你只是从顶点到顶点,那些导致丑陋的退化情况。红色是原始路径。橙色块是以指定宽度绘制的矩形,对齐并以每个段为中心。

9 个答案:

答案 0 :(得分:4)

哦好吧 - 我自己试图解决这个问题。我浪费了两个月试图解决零透支问题的解决方案。正如你已经发现的那样,你无法处理所有堕落的案件,并且同时没有透支。

然而,您可以使用混合方法:

给自己写一个例程,检查连接是否可以从简单的几何体构造而没有问题。为此,您必须检查连接角度,线条的宽度和连接线段的长度(短于宽度的线段是PITA)。通过一些启发式方法,您应该能够解决所有琐碎的案例。

我不知道您的平均线数据是怎样的,但在我的情况下,超过90%的宽线没有退化的情况。

对于所有其他行:

你很可能已经发现,如果你容忍透支,那么生成几何体就容易多了。这样做,让多边形CSG算法和tesselation算法完成艰苦的工作。

我已经评估了大部分可用的tesselation软件包,最后我得到了GLU tesselator。它快速,强大,永不崩溃(与大多数其他算法不同)。这是免费的,许可证允许我将其包含在商业计划中。细分的质量和速度是可以的。你不会得到delaunay三角测量质量,但是因为你只需要三角形来渲染这不是问题。

由于我不喜欢tesselator API,我从免费的SGI OpenGL参考实现中提取了tesselation代码,重写了整个前端并添加了内存池以减少分配数量。花了两天的时间才做到这一点,但这非常值得(比如因子五的性能提升)。最终解决方案是商业OpenVG实施btw: - )

如果您在PC上使用OpenGL进行渲染,则可能需要将tesselation / CSG作业从CPU移动到GPU并使用模板缓冲区或z缓冲区技巧来移除透支。这比CPU细分更容易,甚至可能更快。

答案 1 :(得分:2)

一种简单的方法。

将每个2d顶点的角度平分,这将创建一个漂亮的斜接线。然后沿着那条线向内和向外移动你的“厚度”(或厚度除以2?),你现在有了你的内部和外部多边形点。移动到下一个点,重复相同的过程,沿途构建新的多边形点。然后应用三角形来获得渲染就绪的顶点。

答案 2 :(得分:2)

我刚刚发现了这项惊人的工作:

http://www.codeproject.com/Articles/226569/Drawing-polylines-by-tessellation

它似乎完全符合您的要求,其许可证甚至可以在商业应用程序中使用它。此外,作者在详细描述他的方法方面做得非常出色。我可能会在某些时候试图取代我自己的不那么完美的实现。

答案 3 :(得分:1)

我最后不得不弄脏手写一个小的绷带来解决类似的问题。

对我来说,问题是我想在OpenGL中使用胖线,而这些线条没有我在iPhone上使用OpenGL看到的各种工件。看了各种解决方案后;贝塞尔曲线之类的东西 - 我认为最简单的就是制作自己的曲线。有几种不同的方法。

一种方法是找到两个线段之间的交叉角,然后沿着该交点线移动一段距离表面并将其视为带状顶点。我试过了,看起来并不直观;色带宽度会有所不同。

另一种方法是实际计算线段表面的法线,并使用它来计算该线段的理想色带边缘,并在带段之间进行实际的相交测试。这种方法效果很好,但对于尖角,带状线段的交叉点距离太远(如果段间角度接近180°)。

我用两种方法解决了尖角问题。 Paul Bourke线交叉算法(我以未经优化的方式使用)建议检测交叉点是否在段内。由于两个段都相同,我只需要测试其中一个段以进行交叉。然后我可以仲裁如何解决这个问题;无论是通过捏造两端之间的最佳点还是戴上一个端帽 - 两种方法看起来都很好 - 端帽方法可能会抛弃面向opengl的多边形正面/背面排序。

请参阅http://paulbourke.net/geometry/lineline2d/

请在此处查看我的源代码:https://gist.github.com/1474156

答案 4 :(得分:0)

我想我会找到一个曲面细分算法。确实,在大多数情况下使用它们的目的是减少顶点的数量以优化渲染,但在您的情况下,您可以参数化以保留所有细节 - 并且优化的可能性可能会有用。

网上有许多曲面细分算法和代码 - 几年前我在一个DLL中包含一个纯C,用于Delphi横向渲染器,它们不是高级图形编码教程的常见主题,之类的。

答案 5 :(得分:0)

我也对此感兴趣,因为我想完善我的地图应用程序(Kosmos)绘制道路。我使用的一种解决方法是绘制折线两次,一次使用较粗的线,一次使用较薄的颜色,使用不同的颜色。但这不是一个真正的多边形,它只是模拟一个多边形的快速方法。请在此处查看一些示例:http://wiki.openstreetmap.org/wiki/Kosmos_Rendering_Help#Rendering_Options

我不确定这是否是你需要的。

答案 6 :(得分:0)

查看Delaunay triangulation是否有帮助。

答案 7 :(得分:0)

在我的情况下,我可以负担得起。我只是以每个折线顶点为中心的半径=宽度/ 2的圆圈投影。

伪影以这种方式被掩盖,如果你可以忍受“圆角”和一些透支,它很容易实现。

答案 8 :(得分:0)

从您的图像看起来,您正在使用FILL打开并使用橙色颜色的线段周围绘制框。这样做肯定会造成糟糕的透支。所以首先要做的不是渲染黑色边框和填充颜色可能是不透明的。

为什么不能使用GL_LINES原语来做你想做的事情?您可以指定宽度,过滤,平滑度,纹理任何东西。您可以使用glDrawArrays()渲染所有顶点。我知道这不是你想到的,但是当你专注于2D绘图时,这可能是更容易的方法。 (搜索纹理线等)