【问题标题】:get mouse in world coordinates with 2 gluUnproject calls to create ray通过 2 个 gluUnproject 调用在世界坐标中获取鼠标以创建射线
【发布时间】:2014-11-14 08:15:20
【问题描述】:

我尝试使用许多人似乎找到的好方法,我用不同的 z 值调用 gluUnproject 2 次,然后尝试从这两个向量计算射线的方向向量。

我阅读了this question 并尝试将那里的结构用于我自己的代码:

        glGetFloat(GL_MODELVIEW_MATRIX, modelBuffer);
        glGetFloat(GL_PROJECTION_MATRIX, projBuffer);
        glGetInteger(GL_VIEWPORT, viewBuffer);

        gluUnProject(mouseX, mouseY, 0.0f, modelBuffer, projBuffer, viewBuffer, startBuffer);
        gluUnProject(mouseX, mouseY, 1.0f, modelBuffer, projBuffer, viewBuffer, endBuffer);

        start = vecmath.vector(startBuffer.get(0), startBuffer.get(1), startBuffer.get(2));
        end = vecmath.vector(endBuffer.get(0), endBuffer.get(1), endBuffer.get(2));

        direction = vecmath.vector(end.x()-start.x(), end.y()-start.y(), end.z()-start.z());

但这只会返回同质剪辑坐标(我相信),因为它们在每个轴上的范围仅从 -1 到 1。

如何实际获取可以创建射线的坐标?

编辑:这就是我构造矩阵的方式:

Matrix projectionMatrix = vecmath.perspectiveMatrix(60f, aspect, 0.1f,
            100f);
//The matrix of the camera = viewMatrix
setTransformation(vecmath.lookatMatrix(eye, center, up));
//And every object sets a ModelMatrix in it's display method  
Matrix modelMatrix = parentMatrix.mult(vecmath
                    .translationMatrix(translation));
modelMatrix = modelMatrix.mult(vecmath.rotationMatrix(1, 0, 1, angle));

编辑 2:

这是函数现在的样子:

private void calcMouseInWorldPosition(float mouseX, float mouseY, Matrix proj, Matrix view) {
    Vector start = vecmath.vector(0, 0, 0);
    Vector end = vecmath.vector(0, 0, 0);

    FloatBuffer modelBuffer = BufferUtils.createFloatBuffer(16);
    modelBuffer.put(view.asArray());
    modelBuffer.rewind();
    FloatBuffer projBuffer = BufferUtils.createFloatBuffer(16);
    projBuffer.put(proj.asArray());
    projBuffer.rewind();

    FloatBuffer startBuffer = BufferUtils.createFloatBuffer(16);
    FloatBuffer endBuffer = BufferUtils.createFloatBuffer(16);
    IntBuffer viewBuffer = BufferUtils.createIntBuffer(16);

     //The two calls for projection and modelView matrix are disabled here,   
       as I use my own matrices in this case
//  glGetFloat(GL_MODELVIEW_MATRIX, modelBuffer);
//  glGetFloat(GL_PROJECTION_MATRIX, projBuffer);
    glGetInteger(GL_VIEWPORT, viewBuffer);

    //I know this is really ugly and bad, but I know that the height and width is always 600  
    // and this is just for testing purposes 
    mouseY = 600 - mouseY;

    gluUnProject(mouseX, mouseY, 0.0f, modelBuffer, projBuffer, viewBuffer, startBuffer);
    gluUnProject(mouseX, mouseY, 1.0f, modelBuffer, projBuffer, viewBuffer, endBuffer);

    start = vecmath.vector(startBuffer.get(0), startBuffer.get(1), startBuffer.get(2));
    end = vecmath.vector(endBuffer.get(0), endBuffer.get(1), endBuffer.get(2));

    direction = vecmath.vector(end.x()-start.x(), end.y()-start.y(), end.z()-start.z());

}

我正在尝试使用自己的投影和视图矩阵,但这似乎只会给出更奇怪的结果。
使用 GlGet... 的东西,我可以在右上角单击一下:
开始:(0.97333336, -0.98, -1.0)
结束: (0.97333336, -0.98, 1.0)

当我使用自己的东西时,我会得到相同的位置:
开始:(-2.4399707,-0.55425626,-14.202201)
结束:(-2.4399707,-0.55425626,-16.198204)

现在我实际上需要一个 modelView 矩阵而不仅仅是视图矩阵,但我不知道我应该如何获得它,因为它在每个对象的每次显示调用中都被更改并重新创建。
但这真的是问题吗?在this 教程中,他说“通常,要从眼睛空间进入剪辑空间,我们将向量乘以投影矩阵。我们可以通过乘以该矩阵的逆矩阵来向后退。”下一步他再次乘以视图矩阵的倒数,所以我认为这就是我应该做的吗?

编辑 3:
在这里,我尝试了 user42813 的建议:

    Matrix view = cam.getTransformation();
    view = view.invertRigid();

    mouseY = height - mouseY - 1;

    //Here I only these values, because the Z and W values would be 0  
    //following your suggestion, so no use adding them here
    float tempX = view.get(0, 0) * mouseX + view.get(1, 0) * mouseY;
    float tempY = view.get(0, 1) * mouseX + view.get(1, 1) * mouseY;
    float tempZ = view.get(0, 2) * mouseX + view.get(1, 2) * mouseY;

    origin = vecmath.vector(tempX, tempY, tempZ);
    direction = cam.getDirection();

但现在方向和原点值始终相同:
来源:(-0.04557252,-0.0020000197,-0.9989586)
方向:(-0.04557252,-0.0020000197,-0.9989586)

【问题讨论】:

  • gluUnProject 应该回到对象空间坐标。您很可能有一个身份模型视图/投影矩阵。你的目标是什么版本的GL?例如,如果您使用 GL 3.2 内核,我可以很容易地看到 glGetFloat (...) 返回未初始化的矩阵。在这种情况下,只会定义视口,这就解释了为什么你只返回剪辑空间。
  • @AndonM.Coleman 我的版本是 3.1.0。
  • GL_ARB_compatibility 是您的扩展字符串中的扩展之一吗?此外,如果您使用单独的库构建矩阵,为什么要尝试从 OpenGL 中查询它们?
  • @AndonM.Coleman 抱歉,我不知道扩展字符串是什么意思。而且我不知道我应该如何获得 gluUnproject 方法所需的矩阵,尤其是 modelMatrix,因为它随每个对象而改变。我可以以某种方式获得视图和投影矩阵,但我仍然需要 ModelView 矩阵,我应该如何创建/获取它?
  • 不幸的是,您将不得不更清楚地解释您的情况(在您的问题中,因为这些 cmets 变得一团糟)。我什至不确定此时您使用的是固定功能还是着色器管道。但是如果你有视图矩阵,你应该能够将它乘以你的对象的模型矩阵来得到模型视图矩阵。在任何情况下,如果 很多东西实际上都在工作(sans 模型矩阵),那么它将像你一样在世界空间而不是剪辑空间正在描述:-\

标签: opengl lwjgl glu ray-picking mouse-picking


【解决方案1】:

好的,我终于设法解决了这个问题,也许这会对某人有所帮助。
我为此找到了一些公式,并使用我得到的坐标进行了此操作,范围从 -1 到 1:

    float tempX = (float) (start.x() * 0.1f * Math.tan(Math.PI * 60f / 360));
    float tempY = (float) (start.y() * 0.1f * Math.tan(Math.PI * 60f / 360) * height / width);
    float tempZ = -0.1f;

    direction = vecmath.vector(tempX, tempY, tempZ); //create new vector with these x,y,z
    direction = view.transformDirection(direction); 
    //multiply this new vector with the INVERSED viewMatrix
    origin = view.getPosition(); //set the origin to the position values of the matrix (the right column)

【讨论】:

    【解决方案2】:

    我并没有真正使用过时的 opengl,但我会分享我的想法, 首先,如果您向我们展示如何构建视图矩阵,将会很有帮助, 其次,您拥有的 View 矩阵位于相机的本地空间中, 现在通常你会将你的 mouseX 和 (ScreenHeight - mouseY - 1) 乘以 View 矩阵(我认为该矩阵的倒数对不起,不确定!)然后你将在相机空间中拥有鼠标坐标,然后你将添加 Forward向量到鼠标创建的那个向量,然后你就会得到它,它看起来像这样:

    float mouseCoord[] = { mouseX, screen_heihgt - mouseY - 1, 0, 0 }; /* 0, 0 because we multipling by a matrix 4.*/
    mouseCoord = multiply( ViewMatrix /*Or: inverse(ViewMatrix)*/, mouseCoord );
    float ray[] = add( mouseCoord, forwardVector );
    

    【讨论】:

    • 我的哪些代码已被弃用? glGetxxx() 方法?获得它的现代方法是什么?
    • gluPerspective(..)、gluUnProject(...)、glMatrixMode(..)、glTranslateX(..)、glRotateX(..)、...,嗯,现代的方式会正在创建自己的数学库,或者使用已经定义的数学库,例如 glm 如果您使用的是 C/C++ 或查看 LibGDX 数学库,这是一个很棒的库,您还必须使用没有 gl_ModelViewMatrix/gl_NormalMatrix/gl_Vertex 的着色器...,清单就是一个,你可以在这里 link 有一些很棒的 tuts,还请注意,如果我提供的代码有效,那么光线将在相机空间中。
    • 关于您提供的代码,请注意每帧创建直接缓冲区是一个好主意,您应该做的是创建静态引用并重用它们。
    • 还有一件事,如果你是用鼠标来控制相机旋转,那么代码就简化为(ray = cameraForward)。
    • 我编辑了我的问题并尝试了您的建议。但它并没有真正起作用:/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 2014-11-13
    • 1970-01-01
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多