Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl 使用选择框选择三维曲面(以两种不同的方式)_Opengl_3d_Mouse Picking - Fatal编程技术网

Opengl 使用选择框选择三维曲面(以两种不同的方式)

Opengl 使用选择框选择三维曲面(以两种不同的方式),opengl,3d,mouse-picking,Opengl,3d,Mouse Picking,我正在创建一个建模软件。我的模型都是由平面多边形组成的,这些多边形只是我用OpenGL显示的一组有序的顶点。我已经做了相当多的搜索,但令我惊讶的是,我还没有找到很多关于我正在寻找的应用程序的信息 我试图使用一个矩形框来选择曲面。这听起来很简单,但我希望它的工作方式与此方法在许多程序中的工作方式相同。以下是我正在寻找的要求: 我想要一个从左边开始到右边的矩形,只选择那些完全包含在框中的对象 从右开始向左的矩形应选择任何接触的曲面(不必完全封闭) 应选择矩形中/与矩形接触的所有对象。换句话说,我希望

我正在创建一个建模软件。我的模型都是由平面多边形组成的,这些多边形只是我用OpenGL显示的一组有序的顶点。我已经做了相当多的搜索,但令我惊讶的是,我还没有找到很多关于我正在寻找的应用程序的信息

我试图使用一个矩形框来选择曲面。这听起来很简单,但我希望它的工作方式与此方法在许多程序中的工作方式相同。以下是我正在寻找的要求:

  • 我想要一个从左边开始到右边的矩形,只选择那些完全包含在框中的对象
  • 从右开始向左的矩形应选择任何接触的曲面(不必完全封闭)
  • 应选择矩形中/与矩形接触的所有对象。换句话说,我希望选择对象,无论它们是否可见。适合长方体内部的所有对象,即使被另一个曲面覆盖,仍应选择
  • 清单上的第三个是最重要的。选择1和2都是首选,但如果证明实现它们太困难,我只能接受其中一个

    我看过其他关于3D拾取的帖子,似乎大多数都建议使用颜色拾取或光线投射。我使用颜色拾取进行普通单击选择,但因为我希望框选择包括不可见的曲面,所以这不是一个选项。光线投射似乎只适用于单个单击点,而不是框。那么,有没有其他方法可以相当直接地实现我的目标呢?我认为这将是一项相当常见的任务,因为它似乎存在于许多建模软件中,但不幸的是,我还没有找到一种适合我需要的方法


    算法的伪代码将受到赞赏,但不是必需的。至少我正在寻找一种方法,我可以自己研究并找到一些示例;我只是不知道应该在哪里查找。

    我可以直截了当地告诉您,颜色拾取将不起作用;您必须对每个对象执行一次才能满足要求要求(3),因为只有一个像素进入帧缓冲区

    至于光线投射,它确实只测试一个点,但实际上可以通过取消投影选择矩形的四个角来创建测试体积。可以在世界空间中的近平面(
    Win_Z=0
    )和远平面(
    Win_Z=1
    )找到坐标并使用此选项从二维选择区域构造三维体积

    从中得到的体积称为平截体(假设透视投影),它看起来像一个顶部被切掉的金字塔。平截体相交测试有很好的文档记录,任何讨论“平截体剔除”的内容应该为您提供足够的背景来实现这一点。如果您可以使用轴对齐的边界框和/或球体来近似这些对象的边界,您的生活会轻松得多

    下面的示例很好地说明了此测试卷:


    在CPU上执行自己的交点计算当然是一种选择。但基于我对您的需求的理解,我认为您也可以让OpenGL来完成这项工作,这应该会更简单、更高效

    方法概述 想到的机制是遮挡查询。它们允许您计算已渲染的像素数。如果您将此与使用剪刀测试相结合,则可以计算在选择矩形内渲染的像素数

    用例的应用 用例2是这种方法中比较简单的一个。您将选择矩形设置为剪刀形矩形,并使用每个曲面的遮挡查询渲染所有曲面。然后检查查询结果,查询结果大于0的所有曲面在选择矩形内都有像素

    用例1有点棘手。要知道曲面是否完全包含在矩形中,需要两次过程。在启用剪刀测试的情况下,使用遮挡查询进行渲染,如上一次。然后在禁用剪刀测试的情况下第二次执行相同的操作。如果曲面对这两次都具有相同的查询结果通过时,它完全位于矩形内

    实施 我不打算为此提供完整的代码。这应该非常简单。但这里有一些指针和代码片段。这些调用是用C绑定显示的。我希望很明显,Python绑定的情况也是如此

    首先,由于要在选择中包括隐藏曲面,因此需要禁用深度测试:

    glDisable(GL_DEPTH_TEST);
    
    由于您实际上不需要生成输出,并且可能不想干扰视觉渲染输出,因此您可能还需要禁用颜色输出:

    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    
    如果启用了背面剔除,则可能还需要禁用该选项:

    glDisable(GL_CULL_FACE);
    
    然后,对于上面提到的只想计算选择矩形内像素数的过程,设置剪刀矩形并启用剪刀测试:

    glScissor(selectionLeft, selectionBottom, selectionWidth, selectionHeight);
    glEnable(GL_SCISSOR_TEST);
    
    对于使用遮挡查询的渲染,每个曲面都需要一个查询对象:

    GLuint queryIds[surfaceCount];
    glGenQueries(surfaceCount, queryIds);
    
    然后,对于每个曲面,使用
    k
    作为循环索引:

    glBeginQuery(GL_SAMPLES_PASSED, queryIds[k]);
    // render surface k
    glEndQuery(GL_SAMPLES_PASSED);
    
    渲染所有曲面后,可以获得查询结果:

    GLint pixelCounts[surfaceCount];
    // for all surfaces k
    glGetQueryObjectiv(queryIds[k], GL_QUERY_RESULT, &pixelCounts[k]);
    
    然后评估像素计数,以决定应选择哪些曲面,如前一节中针对每个用例所述


    完成后,不要忘记重置所有状态以准备再次渲染。深度测试、颜色遮罩、剪刀测试等。

    我知道我迟到了,但实际上颜色拾取可以用于选择深层对象,同时通过解决方法执行:按下shift+鼠标滚动时进行选择剥离

    或者换句话说,当你做第一个矩形t时