简体   繁体   English

是否有一种有效的\简单方法在Direct3d中绘制凹多边形

[英]Is there an efficient\easy way to draw a concave polygon in Direct3d

I'm trying to draw a polygon using c# and directx 我正在尝试使用c#和directx绘制多边形

All I get is an ordered list of points from a file and I need to draw the flat polygon in a 3d world. 我得到的是文件中有序的点列表,我需要在3d世界中绘制平面多边形。

I can load the points and draw a convex shape using a trianglefan and drawuserprimitives. 我可以使用trianglefan和drawuserprimitives加载点并绘制凸形。

This obviously leads to incorrect results when the polygon is very concave (which it may be). 当多边形非常凹陷时(这可能是),这显然会导致不正确的结果。

I can't imagine I'm the only person to grapple with this problem (tho I'm a gfx/directx neophyte - my background is in gui\\windows application development). 我无法想象我是唯一一个要解决这个问题的人(因为我是一个gfx / directx新手 - 我的背景是gui \\ windows应用程序开发)。

Can anyone point me towards a simple to follow resource\\tutorial\\algorithm which may assist me? 任何人都可以指向一个简单的资源\\ tutorial \\算法可以帮助我吗?

Direct3D can only draw triangles (well, it can draw lines and points as well, but that's besides the point). Direct3D只能绘制三角形(嗯,它也可以绘制线条和点,但除此之外)。 So if you want to draw any shape that is more complex than a triangle, you have to draw a bunch of touching triangles that equal to that shape. 因此,如果要绘制比三角形更复杂的任何形状,则必须绘制一组等于该形状的触摸三角形。

In your case, it's a concave polygon triangulation problem. 在你的情况下,它是一个凹多边形三角剖分问题。 Given a bunch of vertices, you can keep them as is, you just need to compute the "index buffer" (in simplest case, three indices per triangle that say which vertices the triangle uses). 给定一堆顶点,你可以按原样保存它们,你只需要计算“索引缓冲区”(在最简单的情况下,每个三角形有三个索引,说明三角形使用哪个顶点)。 Then draw that by putting into vertex/index buffers or using DrawUserPrimitives. 然后通过放入顶点/索引缓冲区或使用DrawUserPrimitives来绘制它。

Some algorithms for triangulating simple (convex or concave, but without self-intersections or holes) polygons are at VTerrain site . 用于三角测量简单(凸或凹,但没有自交叉或孔)多边形的一些算法在VTerrain站点

I have used Ratcliff's code in the past; 我过去曾使用过Ratcliff的代码; very simple and works well. 非常简单,效果很好。 VTerrain has a dead link to it; VTerrain有一个死链接; the code can be found here . 代码可以在这里找到。 It's C++, but porting that over to C# should be straightforward. 它是C ++,但将其移植到C#应该是直截了当的。

Oh, and don't use triangle fans. 哦,不要使用三角扇。 They are of very limited use, inefficient and are going away soon (eg Direct3D 10 does not support them anymore). 它们使用非常有限,效率低下并且很快就会消失(例如Direct3D 10不再支持它们)。 Just use triangle lists. 只需使用三角形列表。

If you are able to use the stencil buffer, it should not be hard to do. 如果你能够使用模板缓冲区,那应该不难。 Here's a general algorithm: 这是一个通用算法:

Clear the stencil buffer to 1.
Pick an arbitrary vertex v0, probably somewhere near the polygon to reduce floating-point errors.
For each vertex v[i] of the polygon in clockwise order:
    let s be the segment v[i]->v[i+1] (where i+1 will wrap to 0 when the last vertex is reached)
    if v0 is to the "right" of s:
        draw a triangle defined by s, v[i], v[i+1] that adds 1 to the stencil buffer
    else
        draw a triangle defined by s, v[i], v[i+1] that subtracts 1 from the stencil buffer
end for
fill the screen with the desired color/texture, testing for stencil buffer values >= 2.

By "right of s" I mean from the perspective of someone standing on v[i] and facing v[i+1]. “s的权利”是指站在v [i]并面对v [i + 1]的人的角度。 This can be tested by using a cross product: 这可以通过使用交叉产品来测试:

cross(v0 - v[i], v[i+1] - v[i]) > 0 交叉(v0 - v [i],v [i + 1] - v [i])> 0

Triangulation is he obvious answer, but it's hard to write a solid triangulator. 三角测量是他明显的答案,但很难写出一个可靠的三角测量仪。 Unless you have two month time to waste don't even try it. 除非你有两个月的时间浪费甚至不尝试。

There are a couple of codes that may help you: 有几个代码可以帮助您:

The GPC Library. GPC图书馆。 Very easy to use, but you may not like it's license: 非常容易使用,但您可能不喜欢它的许可证:

http://www.cs.man.ac.uk/~toby/alan/software/gpc.html http://www.cs.man.ac.uk/~toby/alan/software/gpc.html

There is also triangle: 还有三角形:

http://www.cs.cmu.edu/~quake/triangle.html http://www.cs.cmu.edu/~quake/triangle.html

And FIST: 和FIST:

http://www.cosy.sbg.ac.at/~held/projects/triang/triang.html http://www.cosy.sbg.ac.at/~held/projects/triang/triang.html

Another (and my prefered) option would be to use the GLU tesselator. 另一个(和我最喜欢的)选项是使用GLU tesselator。 You can load and use the GLU library from DirectX programs just fine. 您可以正常加载和使用DirectX程序中的GLU库。 It does not need an OpenGL context to use it and it's pre-installed on all windows machines. 它不需要OpenGL上下文来使用它,并且它已预先安装在所有Windows机器上。 If you want source you can lift off the triangulation code from the SGI reference implementation. 如果您需要源,可以从SGI参考实现中取消三角测量代码。 I did that once and it took me just a couple of hours. 我这样做了一次,花了我几个小时。

So far for triangulation. 到目前为止进行三角测量。 There is a different way as well: You can use stencil tricks. 还有一种不同的方式:你可以使用模板技巧。

The general algorithm goes like this: 一般算法如下:

  1. Disable color- and depth writes. 禁用颜色和深度写入。 Enable stencil writes and setup your stencil buffer that it will invert the current stencil value. 启用模板写入并设置模板缓冲区,它将反转当前的模板值。 One bit of stencil is sufficient. 一点模板就足够了。 Oh - your stencil buffer should be cleared as well. 哦 - 你的模板缓冲区也应该被清除。

  2. Pick a random point on the screen. 在屏幕上选择一个随机点。 Any will do. 任何会做的。 Call this point your Anchor. 把这一点称为你的主持人。

  3. For each edge of your polygon build a triangle from the two vertices that build the edge and your anchor. 对于多边形的每个边,从构建边和锚的两个顶点构建三角形。 Draw that triangle. 绘制那个三角形。

  4. Once you've drawn all these triangles, turn off stencil write, turn on stencil test and color-write and draw a fullscreen quad in your color of choice. 绘制完所有这些三角形后,关闭模板写入,打开模板测试和颜色写入,并以您选择的颜色绘制全屏四边形。 This will fill just the pixels inside your convex polygon. 这将仅填充凸多边形内的像素。

It's a good idea to place the anchor into the middle of the polygon and just draw a rectangle as large as the boundary box of your polygon. 最好将锚点放在多边形的中间,然后绘制一个与多边形边界框一样大的矩形。 That saves a bit of fillrate. 这节省了一点填充。

Btw - the stencil technique works for self-intersecting polygons as well. 顺便说一句 - 模板技术也适用于自相交多边形。

Hope it helps, Nils 希望它有所帮助,尼尔斯

I just had to do this for a project. 我只需要为一个项目做这个。 The simplest algorithm I found is called "Ear Clipping". 我发现的最简单的算法叫做“Ear Clipping”。 A great paper on it is here: TriangulationByEarClipping.pdf 关于它的一篇很好的论文在这里: TriangulationByEarClipping.pdf

I took me about 250 lines of c++ code and 4 hours to implement the brute force version of it. 我带了大约250行c ++代码和4小时来实现它的强力版本。 Other algorithms have better performance, but this was simple to implement and understand. 其他算法具有更好的性能,但这很容易实现和理解。

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

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