1

我正在尝试实现一个“raypicker”来选择我的项目中的对象。我不完全理解如何实现这一点,但我从概念上理解它应该如何工作。我一直在尝试学习如何做到这一点,但是我发现的大多数教程都超出了我的想象。我当前的代码基于我发现的最新教程之一,here。

经过几个小时的修改,我相信我的光线选择器遇到的问题实际上首先是光线的创建。如果我用无可争议地位于三角形区域内的坐标替换/硬编码我的近/远平面,则选择器会正确识别它。

我的问题是:我的光线创建似乎没有完全考虑到我当前的“相机”或视角,因此相机旋转不会影响我的鼠标所在的位置。我相信要解决这个问题,我需要使用 gluUnProject() 之类的东西,但是每当我使用它时,返回的 x、y、z 坐标都会非常小,

我目前的光线创作是一团糟。我尝试使用其他人最初提出的方法,但似乎我尝试的任何方法都不适用于我的选择器/交叉点功能。

这是我的光线创建的代码:

void oglWidget::mousePressEvent(QMouseEvent *event)
{   

    QVector3D nearP = QVector3D(event->x()+camX, -event->y()-camY, -1.0);
    QVector3D farP = QVector3D(event->x()+camX, -event->y()-camY, 1.0);

    int i = -1;
    for (int x = 0; x < tileCount; x++)
    {
        bool rayInter = intersect(nearP, farP, tiles[x]->vertices);
        if (rayInter == true)
            i = x;
    }
    if (i != -1)
    {
        tiles[i]->showSelection();
    }
    else
    {
        for (int x = 0; x < tileCount; x++)
            tiles[x]->hideSelection();
    }
    //tiles[0]->showSelection();
}

重复一遍,我曾经加载视口、模型和投影矩阵,并取消投影鼠标坐标,但在 1920x1080 窗口中,我得到的只是每个鼠标事件的 xy 和 z 范围为 -2 到 2 的值,这就是我尝试这种方法的原因,但这种方法不适用于相机旋转和缩放。

我不想做像素颜色拾取,因为谁知道我以后可能需要这种技术,而且我宁愿在我到目前为止付出的努力之后不放弃

4

3 回答 3

1

看一眼

http://www.realtimerendering.com/intersections.html

在确定各种几何形状之间的交点方面有很多帮助

http://geomalgorithms.com/code.html也有一些 c++ 函数,其中之一服务于您的目的

于 2015-02-06T20:31:49.607 回答
1

由于您似乎在构建光线时遇到问题,这就是我的做法。这还没有直接测试。你可以这样做,确保所有向量都在同一个空间中。如果您使用多个模型矩阵(或其堆栈),则需要分别对每个模型矩阵重复计算。

  1. 用于pos = gluUnproject(winx, winy, near, ...)获取鼠标在模型空间近平面上的坐标位置;near是赋予glFrustum()或的值gluPerspective()
  2. 射线的原点是模型空间中的相机位置:rayorig = inv(modelmat) * camera_in_worldspace
  3. 射线的方向是从位置 1. 到射线原点的归一化向量:raydir = normalize(pos - rayorig)

在链接的网站上,他们使用两个点来表示光线,并且他们似乎没有对光线方向矢量进行归一化,所以这是可选的。

于 2015-02-07T23:11:21.487 回答
1

好的,这就是我的面包屑之旅的开始。

我在某种程度上遇到了矩阵的 QT 数据类型以及与矩阵转换有关的逻辑问题。

这个问题中的这个特殊问题是由于实际上没有执行任何转换造成的。

解决这个问题的步骤是:

  • 将鼠标坐标转换为 NDC 空间(-1 到 1 范围内:x/屏幕宽度 * 2 - 1,y - 高度/高度 * 2 - 1)
  • 为我的视图矩阵抓取 4x4 矩阵(可以是渲染时使用的矩阵,或重新计算)
  • 在一个新向量中,让它等于逆视图矩阵乘以逆投影矩阵。

为了构建射线,我必须执行以下操作:

  • 为相乘的矩阵取先前计算的值。这将乘以向量 4(4 个点的数组),其中将保存先前计算的 x 和 y 坐标,以及-1和 +1。
  • 然后这个向量将除以整个向量的最后一个点值
  • 创建另一个向量 4,它就像最后一个一样,但不是 -1,而是放"1"
  • 再次将其除以其最后一个现货值。

现在,射线的坐标已在远近平面创建,因此它可以与场景中沿它的任何物体相交。

我提出了一系列问题(因为我的一系列问题存在很大的不确定性),所以我的部分问题也重叠在其中。

  • 在这里,我了解到我需要考虑屏幕高度来切换笛卡尔系统的 y 轴原点,因为 windows 的 y 轴从左上角开始。此外,矩阵的检索是多余的,但也是错误的,因为它们从未被声明为“正确”。
  • 在这里,我了解到 unProject 不起作用,因为我试图使用 OpenGL 函数提取模型和视图矩阵,但我从未真正设置它们,因为我手动构建了矩阵。我用 2 倍解决了这个问题:我手动进行了数学计算,并制作了相同数据类型的所有矩阵(它们之前是混合数据类型,也会导致问题)。
  • 最后,在这里,我了解到我的操作顺序略有偏差(需要将矩阵乘以向量,而不是相反),我的近平面需要为 -1,而不是 0,并且最后一个值与矩阵相乘的向量(值“w”)需要为 1。

感谢那些帮助我解决这些问题的人:

于 2015-02-15T15:47:14.623 回答