【问题标题】:Java OpenGL - Mouse position from window to world spaceJava OpenGL - 从窗口到世界空间的鼠标位置
【发布时间】:2015-12-27 17:31:36
【问题描述】:

我尝试将窗口鼠标坐标(0/0 为左上角)转换为世界空间坐标。我只是试图通过this描述来解决它。这是我的代码:

public void showMousePosition(float mx, float my){
    Matrix4f projectionMatrix = camera.getProjectionMatrix();
    Matrix4f viewMatrix = camera.getViewMatrix();
    Matrix4f projMulView = projectionMatrix.mul(viewMatrix);
    projMulView.invert();
    float px = ((2*mx)/650)-1;
    float py = ((2*my)/650)-1;
    Vector4f vec4 = new Vector4f(px, py*(-1), 0.0f, 1.0f);
    vec4.mul(projMulView);
    vec4.w = 1.0f / vec4.w;
    vec4.x *= vec4.w;
    vec4.y *= vec4.w;
    vec4.z *= vec4.w;

    System.out.println(vec4.x + ", " + vec4.y);
}

但这不是 100% 正确的。我在世界空间的 0/-11 上有一个对象,当我将鼠标移动到这一点时,我的函数说 0/9,8。当我转到窗口的左侧时,x 值为 5,6,但它应该是 28 之类的东西。

有人知道我的代码有什么问题吗?

【问题讨论】:

    标签: java opengl mouseevent


    【解决方案1】:

    首先,您的代码表明您的窗口大小始终为 width=650, height=650。

    那么当 z=0 时你就得到了这个位置。但是这个 z 在屏幕空间中,因此它会随着您更改相机位置和方向而改变。通常,您使用 glReadPixel 从深度缓冲区中获取此信息。在这种情况下你应该这样做。

    但是,还有另一种方法可以做到这一点。在我将分享的代码中,我正在寻找射线(从鼠标位置生成)和平面(0,0,0)与法线(0,1,0)之间的交点,我希望这会有所帮助。

    /*Given the inverse PV (projection*view) matrix, the position of the mouse on screen and the size of the screen, transforms the screen coordinates to world coordinates*/
    glm::vec3 Picking::OnWorld(glm::mat4 const& m_inv, glm::vec2 const & spos,size_t width, size_t height) {
    float x = spos.x;
    float y = spos.y;
    
    y = height - y;
    
    //InputOrigin, start of the ray for intersection with plane 
    glm::vec4 inputO = glm::vec4(x / width*2.0f - 1.0f, y / height*2.0f - 1.0f, -1.0f, 1.0f);   //transforms screen position to the unit cube range
    glm::vec4 resO = m_inv*inputO;      //transforms to world space
    if (resO.w == 0.0f)  
        return glm::vec3(-1); //return an invalid value to show a problem during a calculation, normally this means that the m_inv matrix was incorrect
    
    resO /= resO.w;     //homogeneous division
    
    glm::vec4 inputE = inputO;      //inputEnd, the end of the ray
    inputE.z = 1.0;
    
    //End of ray to world space
    glm::vec4 resE = m_inv*inputE;
    
    //checks that the coordinates are correct
    if (resE.w == 0.0f)
        return glm::vec3(-1); //return an invalid value to show a problem during a calculation, normally this means that the m_inv matrix was incorrect
    
    resE /= resE.w;
    
    //ray for intersection
    glm::vec3 ray = glm::vec3(resE - resO);     //vector between z=-1 and z=1
    
    glm::vec3 normalRay = glm::normalize(ray);
    glm::vec3 normalPlane = glm::vec3(0, 1, 0);     //detects collision with plane 0, normal 1
    float denominator = glm::dot(normalRay, normalPlane);       
    if (denominator == 0)
        return glm::vec3(-1);   //return an invalid value to show a problem during a calculation, normally this means that the m_inv matrix was incorrect
    
    float numerator = glm::dot(glm::vec3(resO), normalPlane);
    
    //intersection between ray and plane
    glm::vec3 result = glm::vec3(resO) - normalRay*(numerator / denominator);
    
    return result;
    }
    

    可以从此链接读取交叉点的数学运算: https://www.cs.princeton.edu/courses/archive/fall00/cs426/lectures/raycast/sld017.htm

    【讨论】:

      猜你喜欢
      • 2011-03-06
      • 1970-01-01
      • 2012-12-11
      • 2011-04-17
      • 1970-01-01
      • 2020-03-14
      • 1970-01-01
      • 2019-02-07
      • 1970-01-01
      相关资源
      最近更新 更多