get mouse in world coordinates with 2 gluUnproject calls to create ray

£可爱£侵袭症+ 提交于 2019-12-13 01:23:15

问题


I try to use what many people seem to find a good way, I call gluUnproject 2 times with different z-values and then try to calculate the direction vector for the ray from these 2 vectors.

I read this question and tried to use the structure there for my own code:

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

But this only returns the Homogeneous Clip Coordinates (I believe), since they only range from -1 to 1 on every axis.

How to actually get coordinates from which I can create a ray?

EDIT: This is how I construct the matrices:

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

EDIT 2:

This is how the function looks right now:

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

}

I'm trying to use my own projection and view matrix, but this only seems to give weirder results.
With the GlGet... stuff I get this for a click in the upper right corner:
start: (0.97333336, -0.98, -1.0)
end: (0.97333336, -0.98, 1.0)

When I use my own stuff I get this for the same position:
start: (-2.4399707, -0.55425626, -14.202201)
end: (-2.4399707, -0.55425626, -16.198204)

Now I actually need a modelView matrix instead of just the view matrix, but I don't know how I am supposed to get it, since it is altered and created anew in every display call of every object.
But is this really the problem? In this tutorial he says "Normally, to get into clip space from eye space we multiply the vector by a projection matrix. We can go backwards by multiplying by the inverse of this matrix." and in the next step he multiplies again by the inverse of the view matrix, so I thought this is what I should actually do?

EDIT 3:
Here I tried what user42813 suggested:

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

But now the direction and origin values are always the same:
origin: (-0.04557252, -0.0020000197, -0.9989586)
direction: (-0.04557252, -0.0020000197, -0.9989586)


回答1:


Ok I finally managed to work this out, maybe this will help someone.
I found some formula for this and did this with the coordinates that I was getting, which ranged from -1 to 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:


I dont really use deprecated opengl but i would share my thought, First it would be helpfull if you show us how you build your View matrix, Second the View matrix you have is in the local space of the camera, now typically you would multiply your mouseX and (ScreenHeight - mouseY - 1) by the View matrix (i think the inverse of that matrix sorry, not sure!) then you will have the mouse coordinates in camera space, then you will add the Forward vector to that vector created by the mouse, then you will have it, it would look something like that:

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


来源:https://stackoverflow.com/questions/25938924/get-mouse-in-world-coordinates-with-2-gluunproject-calls-to-create-ray

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!