绘制相交圆的轮廓

时间:2011-09-20 18:41:17

标签: opengl geometry intersection

我有一组点,每个点都有一个“影响”或基本上是半径的区域。我希望能够将所有点的这些影响圆中的每一个绘制为一个简单的圆形线。

它们会重叠,但我希望画出形状的外部。我知道这可能需要我在他们相交的地方锻炼,并以某种方式形成一个完整的形状来绘制。问题是某些点可能甚至没有触及其他点!所以我也需要能够解决这个问题。

我试图说明我的意思:

enter image description here

请注意,我希望简单地画出黑线,没有填充。这是因为我希望透过背景图像和其他几何图形。

我会在openGL中这样做,所以圈子可能是用GL_LINES或其他一些形成曲线的顶点制作的,但我真的不知道如何计算出这个边界。

如果有人有任何建议或者可以指出我如何解决这个问题,我们将不胜感激!

这可能更像是一个数学问题,我不是在寻找一些代码但实际上是如何去研究这些形状。我只是想不出怎么做!

*****编辑:根据我提出的解决方案,希望可以帮助别人!

所以我使用了建议的想法,并且基本上决定了使用模板缓冲区绘制的最佳方法。这现在意味着我循环我的点3次,但我需要仔细排序它们,无论如何只能找到可见的。

所以代码明智我现在有这个:

private void stencilCircleAroundStars()
{
    //Lets try and draw something here using stencil
    glColorMask(false, false, false, false); //Disable colour mask
    glEnable(GL_STENCIL_TEST); // Enable Stencil Buffer For "marking" the outer circle
    glDisable(GL_DEPTH_TEST);// Disable Depth Testing

    for (Object value : stars.values())
    {
        Star star = (Star)value;

        glStencilFunc(GL_ALWAYS, 1, 1); // Always Passes, 1 Bit Plane, 1 As Mask
        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // We Set The Stencil Buffer To 1 Where We Draw Any Polygon

        //Draw the large circle
        starOb.location.copy(star.location);
        starOb.setScale(2000);
        starOb.draw();
    }

    for (Object value : stars.values())
    {
        Star star = (Star)value;
        //Now we change the functions and remove a slightly smaller circle from buffer.
        glStencilFunc(GL_ALWAYS, 0, 0); // Always passes, 0 bit plane, 0 as mask;
        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // We Set The Stencil Buffer To 0 Where We Draw Any Polygon
        starOb.location.copy(star.location);
        starOb.setScale(1900);
        starOb.draw();
    }

    //Now we enable the colour
    glColorMask(true, true, true, true);
    glStencilFunc(GL_EQUAL, 1, 1); // We Draw Only Where The Stencil Is 1
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // Don't Change The Stencil Buffer

    glColor4f(0.5f, 1.0f, 0.5f, 0.5f);
    for (Object value : stars.values())
    {
        Star star = (Star)value;
        starOb.location.copy(star.location);
        starOb.setScale(2000);
        starOb.draw();
    }

    //Now we are done .. disable
    glDisable(GL_STENCIL_TEST);  
}

我的点实质上是为了我的程序而被称为“星星”的实体,而StarOb是我从文件加载的四边形的集合,形成一个漂亮的光滑圆圈。

我禁用了颜色遮罩,我循环了一次,将最大的圆圈绘制到模板缓冲区并设置值1.然后再循环将较小的缩放圆圈绘制到模板缓冲区中,但这次设置一个值这应该在任何不接触其他恒星的恒星周围留下边界,并有效地去除它们重叠的位置。

我终于重新启用了颜色遮罩并实际绘制了彩色圆圈。模板缓冲区阻止内部渲染,我得到了我想要的东西!然后我禁用了模板缓冲区。

如果你真的想看到它,这里有一个产生几个不断增加的点数的视频:Video of it running

以下是它的低质量版本(测试时未绘制背景):

Overlapping circles with centre not drawn due to stencil

2 个答案:

答案 0 :(得分:6)

首先,想象一下背景不存在。我很确定你会知道怎么做,绘制每个圆圈然后绘制它们的内部(如在一个实心圆圈中)来移除内部的弧线。

现在要对图像执行相同操作,您可以执行以下任一操作。您可以做的一件事是禁用在颜色缓冲区上的写入,执行该过程并更改模板缓冲区。然后启用在颜色缓冲区上的写入并绘制一个整个屏幕矩形,从而填充您在模板缓冲区中标记的像素。

模板缓冲区可能无法使用,但原因有两个,例如您将其用于其他原因。在这种情况下,另一种方法是做同样的事情,但不是在模板缓冲区中渲染,而是在纹理中渲染。然后绑定该纹理并在屏幕上绘制一个矩形。

我很确定你也可以通过累积缓冲区实现这一点,但我从未使用它,所以我无法真正告诉(如果有人知道,请编辑我的答案并告诉我们如何)

答案 1 :(得分:3)

两遍:

  1. 通过GL_LINESGL_LINE_LOOP绘制所有圈子轮廓。确保将glLineWidth()设置为3或更高。
  2. 使用“背景”颜色和与步骤1中的圆圈相同的半径绘制实心圆圈(GL_TRIANGLE_STRIP可能很有用)。
  3. 步骤2中的实心圆圈将覆盖步骤1中的所有轮廓像素,但仅覆盖它们重叠的位置。这样就可以保持完整的非重叠轮廓。

    如果您想要更宽范围的轮廓宽度(即大于大多数OpenGL实现允许的约10个glLineWidth()),您应该重复使用步骤1中步骤2中的实心圆渲染器,除了半径更大