简体   繁体   English

在OpenGL中绘制一个凹多边形

[英]Drawing a concave polygon in OpenGL

I have a concave polygon I need to draw in OpenGL.我有一个需要在 OpenGL 中绘制的凹多边形。
The polygon is defined as a list of points which form its exterior ring, and a list of lists-of-points that define its interior rings (exclusion zones).多边形被定义为形成其外环的点列表,以及定义其内环(禁区)的点列表。

I can already deal with the exclusion zones, so a solution for how to draw a polygon without interior rings will be good too.我已经可以处理禁区,因此如何绘制没有内环的多边形的解决方案也很好。

A solution with Boost.Geometry will be good, as I already use it heavily in my application. Boost.Geometry的解决方案会很好,因为我已经在我的应用程序中大量使用它。

I need this to work on the iPhone, namely OpenGL ES (the older version with fixed pipeline).我需要它才能在 iPhone 上工作,即 OpenGL ES(具有固定管道的旧版本)。

How can I do that?我怎样才能做到这一点?

Try OpenGL's tessellation facilities .试试 OpenGL 的曲面细分工具 You can use it to convert a complex polygon into a set of triangles, which you can render directly.您可以使用它将复杂的多边形转换为一组可以直接渲染的三角形。

EDIT (in response to comment): OpenGL ES doesn't support tessellation functions.编辑(回应评论):OpenGL ES 不支持曲面细分功能。 In this case, and if the polygon is static data, you could generate the tessellation offline using OpenGL on your desktop or notebook computer.在这种情况下,如果多边形是静态数据,您可以在台式机或笔记本电脑上使用 OpenGL 离线生成细分。

If the shape is dynamic, then you are out of luck with OpenGL ES.如果形状是动态的,那么您对 ​​OpenGL ES 不走运。 However, there are numerous libraries (eg, CGAL ) that will perform the same function.但是,有许多库(例如CGAL )将执行相同的功能。

It's a bit complicated, and resource-costly method, but any concave polygon can be drawn with the following steps (note this methos works surely on flat polygons, but I also assume you try to draw on flat surface, or in 2D orthogonal mode):这有点复杂,而且资源成本很高,但是任何凹多边形都可以通过以下步骤绘制(注意这个方法肯定适用于平面多边形,但我也假设你尝试在平面上绘制,或者在 2D 正交模式下绘制) :

  • enable stencil test, use glStencilFunc(GL_ALWAYS,1,0xFFFF)启用模板测试,使用glStencilFunc(GL_ALWAYS,1,0xFFFF)
  • disable color mask to oprevent unwanted draws: glColorMask(0,0,0,0)禁用颜色蒙版以防止不必要的绘制: glColorMask(0,0,0,0)
  • I think you have the vertices in an array of double, or in other form (strongly recommended as this method draws the same polygon multiple times, but using glList or glBegin-glEnd can be used as well)我认为您的顶点是双精度数组或其他形式(强烈推荐,因为此方法多次绘制相同的多边形,但也可以使用 glList 或 glBegin-glEnd)
  • set glStencilOp(GL_KEEP,GL_KEEP,GL_INCR)设置glStencilOp(GL_KEEP,GL_KEEP,GL_INCR)
  • draw the polygon as GL_TRIANGLE_FAN将多边形绘制为 GL_TRIANGLE_FAN

Now on the stencil layer, you have bits set >0 where triangles of polygon were drawn.现在在模板层上,您将位设置为 >0,其中绘制了多边形的三角形。 The trick is, that all the valid polygon area is filled with values having mod2=1, this is because the triangle fan drawing sweeps along polygon surface, and if the selected triangle has area outside the polygon, it will be drawn twice (once at the current sequence, then on next drawings when valid areas are drawn) This can happens many times, but in all cases, pixels outside the polygon are drawn even times, pixels inside are drawn odd times.诀窍是,所有有效的多边形区域都用 mod2=1 的值填充,这是因为三角形扇形图沿着多边形表面扫过,如果所选三角形有多边形之外的区域,它将被绘制两次(一次在当前序列,然后在绘制有效区域时在下一个绘图上)这可能会发生很多次,但在所有情况下,多边形外部的像素被绘制偶数次,内部像素被绘制奇数次。 Some exceptions can happen, when order of pixels cause outside areas not to be drawn again.当像素顺序导致外部区域不再被绘制时,可能会发生一些例外情况。 To filter these cases, the reverse directioned vertex array must be drawn (all these cases work properly when order is switched): - set glStencilFunc(GL.GL_EQUAL,1,1) to prevent these errors happen in reverse direction (Can draw only areas inside the polygon drawn at first time, so errors happening in the other direction won't apperar, logically this generates the intersectoin of the two half-solution) - draw polygon in reverse order, keeping glStencilFunc to increase sweeped pixel values Now we have a correct stencil layer with pixel_value%2=1 where the pixel is truly inside the polygon.要过滤这些情况,必须绘制反向顶点数组(所有这些情况在切换顺序时都能正常工作): - 设置 glStencilFunc(GL.GL_EQUAL,1,1) 以防止这些错误发生在反向(只能绘制区域在第一次绘制的多边形内,因此不会出现在另一个方向上发生的错误,从逻辑上讲,这会产生两个半解的相交) - 以相反的顺序绘制多边形,保持 glStencilFunc 增加扫描像素值现在我们有一个使用 pixel_value%2=1 的正确模板层,其中像素真正位于多边形内。 The last step is to draw the polygon itself: - set glColorMask(1,1,1,1) to draw visible polygon - keep glStencilFunc(GL_EQUAL,1,1) to draw the correct pixels - draw polygon in the same mode (vertex arrays etc.), or if you draw without lighting/texturing, a single whole-screen-rectangle can be also drawn (faster than drawing all the vertices, and only the valid polygon pixels will be set)最后一步是绘制多边形本身: - 设置glColorMask(1,1,1,1)以绘制可见多边形 - 保持 glStencilFunc(GL_EQUAL,1,1) 以绘制正确的像素 - 以相同的模式绘制多边形(顶点数组等),或者如果您在没有照明/纹理的情况下进行绘制,也可以绘制单个全屏矩形(比绘制所有顶点更快,并且只会设置有效的多边形像素)

If everything goes well, the polygon is correctly drawn, make sure that after this function you reset the stencil usage (stencil test) and/or clear stencil buffer if you also use it for another purpose.如果一切顺利,多边形绘制正确,请确保在此功能后重置模板使用(模板测试)和/或清除模板缓冲区(如果您还将其用于其他目的)。

I wrote a java classe for a small graphical library that do exacly what you are looking for, you can check it here :我为一个小型图形库编写了一个 java 类,它完全符合您的要求,您可以在此处查看:

https://github.com/DzzD/TiGL/blob/main/android/src/fr/dzzd/tigl/PolygonTriangulate.java https://github.com/DzzD/TiGL/blob/main/android/src/fr/dzzd/tigl/PolygonTriangulate.java

It receive as input two float arrays (vertices & uvs) and return the same vertices and uvs reordered and ready to be drawn as a list of triangles.它接收两个浮点数组(顶点和 uvs)作为输入,并返回相同的顶点和 uvs 重新排序并准备绘制为三角形列表。

If you want to exclude a zone (or many) you can simply connect your two polygones (the main one + the hole) in one by connecting them by a vertex, you will end with only one polygone that can be triangulate like any other with the same function.如果你想排除一个(或多个)区域,你可以简单地将你的两个多边形(主要的一个 + 孔)通过一个顶点连接起来,你将只得到一个可以像任何其他多边形一样三角剖分的多边形相同的功能。

Like this :像这样 : 在此处输入图像描述

To better understand zoomed it will look like :为了更好地理解缩放它看起来像: 在此处输入图像描述

Finally it is just a single polygon.最后它只是一个多边形。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM