通过2次gluUnproject调用获取鼠标在世界坐标中以创建光线

时间:2014-09-19 16:58:07

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

我尝试使用许多人似乎找到一个好方法,我用不同的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());

但这仅返回Homogeneous Clip Coordinates(我相信),因为它们在每个轴上的范围仅为-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)

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分:0)

我真的不使用弃用的opengl,但我会分享我的想法, 首先,如果您向我们展示如何构建View矩阵,将会有所帮助, 其次,你拥有的View矩阵位于相机的局部空间, 现在通常你会将你的mouseX和(ScreenHeight - mouseY - 1)乘以View矩阵(我认为该矩阵的反转对不起,不确定!)然后你将在相机空间中有鼠标坐标,然后你将添加前进矢量到鼠标创建的矢量,然后你会有它,它看起来像这样:

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 );