Reputation: 59
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
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