在OpenGL中绘制凹多边形
我有一个凹多边形,需要在 OpenGL 中绘制。
多边形被定义为形成其外环的点列表,以及定义其内环(排除区域)的点列表。
我已经可以处理禁区,因此如何绘制没有内环的多边形的解决方案也很好。
使用 Boost.Geometry 的解决方案将很好,因为我已经在我的应用程序中大量使用它了。
我需要它在 iPhone 上工作,即 OpenGL ES(具有固定管道的旧版本)。
我怎样才能做到这一点?
I have a concave polygon I need to draw in 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.
I need this to work on the iPhone, namely OpenGL ES (the older version with fixed pipeline).
How can I do that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
尝试 OpenGL 的曲面细分工具。您可以使用它将复杂的多边形转换为一组三角形,然后可以直接渲染。
编辑(回应评论):OpenGL ES不支持曲面细分函数。在这种情况下,如果多边形是静态数据,您可以在台式机或笔记本电脑上使用 OpenGL 离线生成曲面细分。
如果形状是动态的,那么 OpenGL ES 就不那么幸运了。然而,有许多库(例如,CGAL)可以执行相同的功能。
Try OpenGL's tessellation facilities. 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. In this case, and if the polygon is static data, you could generate the tessellation offline using OpenGL on your desktop or notebook computer.
If the shape is dynamic, then you are out of luck with OpenGL ES. However, there are numerous libraries (e.g., CGAL) that will perform the same function.
这是有点复杂且资源昂贵的方法,但可以通过以下步骤绘制任何凹多边形(请注意,此方法肯定适用于平面多边形,但我也假设您尝试在平面上或以 2D 正交模式绘制) :
glStencilFunc(GL_ALWAYS,1,0xFFFF)
glColorMask(0,0,0,0)
glStencilOp(GL_KEEP,GL_KEEP,GL_INCR)
现在在模板层,您的位设置为> 0,其中绘制了多边形的三角形。技巧是,所有有效的多边形区域都填充有 mod2=1 的值,这是因为三角形扇形图沿着多边形表面扫描,如果所选三角形有多边形之外的区域,则会绘制两次(一次在当前序列,然后在绘制有效区域时在下一个绘图上)这种情况可能会发生很多次,但在所有情况下,多边形外部的像素都会绘制偶数次,内部像素会绘制奇数次。
当像素顺序导致外部区域无法再次绘制时,可能会发生一些异常。要过滤这些情况,必须绘制反向顶点数组(切换顺序时所有这些情况都可以正常工作):
- 设置glStencilFunc(GL.GL_EQUAL,1,1)以防止这些错误在相反方向发生(只能绘制第一次绘制的多边形内部的区域,因此不会出现在另一个方向发生的错误,逻辑上这会生成相交)两个半解)
- 以相反的顺序绘制多边形,保持 glStencilFunc 增加扫描像素值
现在我们有了一个正确的模板层,其中pixel_value%2=1,其中像素真正位于多边形内部。最后一步是绘制多边形本身:
- 设置
glColorMask(1,1,1,1)
来绘制可见多边形- 保持 glStencilFunc(GL_EQUAL,1,1) 绘制正确的像素
- 以相同的模式(顶点数组等)绘制多边形,或者如果您在没有照明/纹理的情况下绘制,也可以绘制单个全屏矩形(比绘制所有顶点更快,并且只有有效的多边形像素才会被绘制) 如果一切顺利,多边形
已正确绘制,请确保在此函数之后重置模板使用(模板测试)和/或清除模板缓冲区(如果您还将其用于其他目的)。
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):
glStencilFunc(GL_ALWAYS,1,0xFFFF)
glColorMask(0,0,0,0)
glStencilOp(GL_KEEP,GL_KEEP,GL_INCR)
Now on the stencil layer, you have bits set >0 where triangles of polygon were drawn. 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.
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. 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)
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.
查看glues,它具有可以处理凹多边形的曲面细分函数。
Check out glues, which has tessellation functions that can handle concave polygons.
我为一个小型图形库编写了一个 java 类,它完全可以满足您的需求,您可以在这里查看:
https://github.com/DzzD/TiGL/blob/main/android/src/fr/dzzd/tigl/PolygonTriangulate.java
它接收两个浮点数组(顶点和 uvs)作为输入,返回相同的顶点和 uv 重新排序并准备好绘制为三角形列表。
如果您想排除一个区域(或多个区域),您可以简单地将两个多边形(主多边形+孔)通过一个顶点连接起来,将它们连接到一个区域中,最后您将只得到一个可以像其他任何多边形一样进行三角剖分的多边形相同的功能。
像这样 :
为了更好地理解缩放,它看起来像:
最后它只是一个多边形。
I wrote a java classe for a small graphical library that do exacly what you are looking for, you can check it here :
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.
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.