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

时间:2008-09-18 09:29:05

标签: c# directx polygon concave

我正在尝试使用c#和directx

绘制多边形

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

我可以使用trianglefan和drawuserprimitives加载点并绘制凸形。

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

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

任何人都可以指向一个简单的资源\ tutorial \ algorithm来帮助我吗?

4 个答案:

答案 0 :(得分:3)

Direct3D只能绘制三角形(嗯,它也可以绘制线条和点,但除此之外)。因此,如果您想要绘制比三角形更复杂的任何形状,您必须绘制一组等于该形状的触摸三角形。

在您的情况下,这是一个凹多边形三角剖分问题。给定一堆顶点,你可以按原样保存它们,你只需要计算“索引缓冲区”(在最简单的情况下,每个三角形有三个索引,说明三角形使用哪个顶点)。然后通过放入顶点/索引缓冲区或使用DrawUserPrimitives来绘制它。

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

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

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

答案 1 :(得分:2)

三角测量是他明显的答案,但很难写出一个可靠的三角测量仪。除非你有两个月的时间浪费,否则不要尝试。

有几个代码可以帮助您:

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. 一旦绘制了所有这些三角形,请关闭模板写入,打开模板测试并进行颜色写入,并以您选择的颜色绘制全屏四边形。这将仅填充凸多边形内的像素。

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

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

    希望它有所帮助,   尼尔斯

答案 2 :(得分:2)

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

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.

“s的权利”是指站在v [i]并面对v [i + 1]的人的角度。这可以通过使用交叉产品进行测试:

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

答案 3 :(得分:0)

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

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