Aseed Kid
Aseed Kid

Reputation: 59

How do I get world coordinates from mouse coordinates in OpenGL with Camera class?

I am trying to convert mouse coordinates to world coordinates in OpenGL and I am using the camera class from learnOpenGL.com, which is this. And I'm using this function for converting cursor space to world space:

glm::vec3 ConvertMouseToWorldSpace(GLFWwindow* window, Camera& camera, glm::mat4 projection) {
    // Get the window size
    int width, height;
    glfwGetFramebufferSize(window, &width, &height);

    double mouseX, mouseY;
    glfwGetCursorPos(window, &mouseX, &mouseY);

    float x = (2.0f * mouseX) / width - 1.0f;
    float y = 1.0f - (2.0f * mouseY) / height;
    float z = 1.0f; 

    glm::vec4 clipCoords(x, y, -1.0f, 1.0f);

    glm::mat4 inverseProjection = glm::inverse(projection);
    glm::vec4 viewCoords = inverseProjection * clipCoords;
    viewCoords = glm::vec4(viewCoords.x, viewCoords.y, -1.0f, 0.0f); 

    glm::mat4 inverseView = glm::inverse(camera.GetViewMatrix());
    glm::vec4 worldCoords = inverseView * viewCoords;

    glm::vec3 rayWorld = glm::normalize(glm::vec3(worldCoords));

    return rayWorld;
}

But it doesn't change the coordinates when I move the camera, and it's very inaccurate, what is the correct way to implement this?

Upvotes: -2

Views: 77

Answers (1)

Aseed Kid
Aseed Kid

Reputation: 59

I fixed this problem by watching a youtube video on dragging objects in OpenGL and came up with this code:

glm::vec3 Camera::screenToWorldSpace(const glm::vec2& screenCoords) {

    glm::vec2 viewportSize(getWindowSizeX(), getWindowSizeY());

    float zDepth = Position.z * 1.9f;

    glm::mat4 projection = glm::perspective(glm::radians(GetZoom()), getAspectRatio(), 0.1f, 100.0f);
    glm::mat projInverse = glm::inverse(projection);

    float mouse_x = screenCoords.x;
    float mouse_y = screenCoords.y;

    float ndc_x = (2.0f * mouse_x) / getWindowSizeX() - 1.0f;
    float ndc_y = 1.0f - (2.0f * mouse_y) / getWindowSizeY();

    float focal_length = 1.0f / glm::tan(glm::radians(45.0f / 2.0f));
    float ar = (float)getWindowSizeY() / (float)getWindowSizeX();
    glm::vec3 ray_view(ndc_x / focal_length, (ndc_y * ar) / focal_length, 1.0f);

    glm::vec4 ray_ndc_4d(ndc_x, ndc_y, 1.0f, 1.0f);
    glm::vec4 ray_view_4d = projInverse * ray_ndc_4d;

    glm::vec4 view_space_intersect = glm::vec4(ray_view * zDepth, 1.0f);

    glm::mat4 view = GetViewMatrix();
    glm::mat4 viewInverse = glm::inverse(view);

    glm::vec4 point_world = viewInverse * view_space_intersect;
    
    return glm::vec3(point_world);
}

Upvotes: -2

Related Questions