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

发布于 2024-07-06 06:21:10 字数 271 浏览 10 评论 0原文

我正在尝试使用 c# 和 directx 绘制多边形,

我得到的只是文件中点的有序列表,我需要在 3d 世界中绘制平面多边形。

我可以加载点并使用三角形扇和绘制用户基元绘制凸形状。

当多边形非常凹时(可能是这样),这显然会导致不正确的结果。

我无法想象我是唯一一个解决这个问题的人(尽管我是 gfx/directx 新手 - 我的背景是 gui\windows 应用程序开发)。

谁能给我指出一个简单易懂的资源\教程\算法来帮助我?

I'm trying to draw a polygon using c# and 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.

I can load the points and draw a convex shape using a trianglefan and 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).

Can anyone point me towards a simple to follow resource\tutorial\algorithm which may assist me?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

別甾虛僞 2024-07-13 06:21:10

Direct3D 只能绘制三角形(当然,它也可以绘制直线和点,但这不是重点)。 因此,如果您想绘制任何比三角形更复杂的形状,则必须绘制一堆等于该形状的相接三角形。

就您而言,这是一个凹多边形三角剖分问题。 给定一堆顶点,您可以保持它们不变,您只需要计算“索引缓冲区”(在最简单的情况下,每个三角形的三个索引表示三角形使用哪些顶点)。 然后通过放入顶点/索引缓冲区或使用 DrawUserPrimitives 来绘制它。

用于对简单(凸或凹,但没有自相交或孔)多边形进行三角测量的一些算法位于 VTerrain 网站

我过去曾使用过 Ratcliff 的代码; 非常简单并且效果很好。 VTerrain 有一个死链接; 代码可以在此处找到。 它是 C++,但将其移植到 C# 应该很简单。

哦,不要使用三角扇。 它们的用途非常有限、效率低下并且很快就会消失(例如 Direct3D 10 不再支持它们)。 只需使用三角形列表即可。

Direct3D can only draw triangles (well, it can draw lines and points as well, but that's besides the point). 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.

Some algorithms for triangulating simple (convex or concave, but without self-intersections or holes) polygons are at VTerrain site.

I have used Ratcliff's code in the past; very simple and works well. VTerrain has a dead link to it; the code can be found here. It's C++, but porting that over to C# should be straightforward.

Oh, and don't use triangle fans. They are of very limited use, inefficient and are going away soon (e.g. Direct3D 10 does not support them anymore). Just use triangle lists.

苯莒 2024-07-13 06:21:10

如果您能够使用模板缓冲区,那应该不难做到。 这是一个通用算法:

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 v0, v[i], v[i+1] that adds 1 to the stencil buffer
    else
        draw a triangle defined by v0, 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.

“s 的右侧”是指从站在 v[i] 并面向 v[i+1] 的人的角度来看。 这可以通过使用叉积来测试:

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

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 v0, v[i], v[i+1] that adds 1 to the stencil buffer
    else
        draw a triangle defined by v0, 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]. This can be tested by using a cross product:

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

锦欢 2024-07-13 06:21:10

三角测量是显而易见的答案,但很难编写一个可靠的三角测量器。 除非你有两个月的时间可以浪费,否则不要尝试。

有一些代码可以帮助您:

GPC 库。 非常容易使用,但您可能不喜欢它的许可证:

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

还有一个三角形:

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

和 FIST:

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

另一个(也是我更喜欢的)选项是使用 GLU tesselator。 您可以从 DirectX 程序加载和使用 GLU 库。 它不需要 OpenGL 上下文来使用它,并且它已预安装在所有 Windows 计算机上。 如果您想要源代码,可以从 SGI 参考实现中提取三角测量代码。 我这样做过一次,只花了几个小时。

到目前为止,三角测量。 还有一种不同的方法:您可以使用模板技巧。

一般算法如下:

  1. 禁用颜色和深度写入。 启用模板写入并设置模板缓冲区,它将反转当前的模板值。 一点模板就足够了。 哦 - 你的模板缓冲区也应该被清除。

  2. 在屏幕上随机选择一个点。 任何都可以。 将此点称为您的锚点。

  3. 对于多边形的每条边,从构建边和锚点的两个顶点构建一个三角形。 画出那个三角形。

  4. 绘制完所有这些三角形后,关闭模板写入,打开模板测试和颜色写入,并以您选择的颜色绘制全屏四边形。 这将仅填充凸多边形内的像素。

最好将锚点放置在多边形的中间,然后绘制一个与多边形边界框一样大的矩形。 这节省了一点填充率。

顺便说一句 - 模板技术也适用于自相交的多边形。

希望能帮助到你,
尼尔斯

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. Very easy to use, but you may not like it's license:

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

There is also triangle:

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

And FIST:

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

Another (and my prefered) option would be to use the GLU tesselator. You can load and use the GLU library from DirectX programs just fine. It does not need an OpenGL context to use it and it's pre-installed on all windows machines. If you want source you can lift off the triangulation code from the SGI reference implementation. 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

我是男神闪亮亮 2024-07-13 06:21:10

我只需要为一个项目这样做。 我发现的最简单的算法称为“Ear Clipping”。 关于它的一篇很棒的论文在这里: TriangulationByEarClipping.pdf

我花了大约 250 行C++ 代码和 4 小时来实现它的暴力版本。 其他算法具有更好的性能,但这很容易实现和理解。

I just had to do this for a project. The simplest algorithm I found is called "Ear Clipping". A great paper on it is here: TriangulationByEarClipping.pdf

I took me about 250 lines of c++ code and 4 hours to implement the brute force version of it. Other algorithms have better performance, but this was simple to implement and understand.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文