【问题标题】:Drawing outline of intersecting circles绘制相交圆的轮廓
【发布时间】:2011-09-20 18:41:16
【问题描述】:

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

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

我试图简单地说明我的意思:

请注意,我只想画黑线,没有填充。这是因为我希望背景图像和其他几何图形能够显示出来。

我将在 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。然后我再次循环将较小的缩放圆圈绘制到模板缓冲区中,但这次设置了一个值0。这应该在任何不接触其他星星的星星周围留下一个边框,并将有效地去除它们重叠的地方。

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

如果你真的想看,这里有一个产生几个越来越多的点的视频:Video of it running

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

【问题讨论】:

    标签: opengl geometry intersection


    【解决方案1】:

    首先,假设背景不存在。我很确定你知道怎么做,画出每个圆圈,然后画出它们的内部(如实心圆圈)以移除内部的弧线。

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

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

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

    【讨论】:

    • 感谢您的建议,我已经设法使用模板缓冲区来解决问题,并用我的解决方案更新我的问题,这有点像您的建议。不知道我现在应该给谁打勾!
    • 也许给我们俩一个+1? :D
    • 完成 :D 我已经更新了我的问题以显示我最终得到的结果。那是你想的那种方式吗?我有点缺乏opengl知识..
    • OpenGL 有很多很棒的功能。我已经断断续续地编写 OpenGL 代码 4 到 5 年了,仍然看到让我想知道的东西(我的意思是它们很棒)!
    • 我刚刚意识到它也可能会更好,而不是激活颜色蒙版并循环最后一次并再次绘制单个圆圈我可以只绘制一个全屏矩形,因为模板缓冲区只会让它通过在正确的地方?它可能会更快..不确定。
    【解决方案2】:

    两遍:

    1. 通过GL_LINESGL_LINE_LOOP 绘制所有圆形轮廓。确保将 glLineWidth() 设置为 3 或更高版本。
    2. 使用您的“背景”颜色和与第 1 步中的圆相同的半径绘制实心圆(GL_TRIANGLE_STRIP 可能很有用)。

    第 2 步中的实心圆圈将覆盖第 1 步中的所有轮廓像素,但仅覆盖它们重叠的位置。这样一来,您就可以得到完整的非重叠轮廓。

    如果您想要更宽范围的轮廓宽度(即大于大多数 OpenGL 实现允许 glLineWidth() 的 ~10),您应该在第 1 步中重用第 2 步中的实心圆渲染器,但半径较大。

    【讨论】:

    • 我只想绘制轮廓的原因是为了让背景图像(以及各种图层/先前绘制的实体)显示出来。如果我放弃了,那么这将是我会做出的第一选择!
    • 我会使用上面的过程,但将圆圈绘制到模板缓冲区,并在绘制其余几何图形时启用模板缓冲区测试。
    • 啊,老实说我没有想到这一点。我对它不是很熟悉,所以我会做一些阅读。我假设您会做类似的事情,将较大的圆圈以某种颜色/值绘制到模板中,将较小的圆圈绘制到不同的模板中。如果模板测试时的值是 largeValue,则为片段着色,如果不是,则不执行任何操作?
    • 无法编辑我的评论,但我已经编辑了我的问题以显示我的最终结果!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    相关资源
    最近更新 更多