ellipticaldoor
ellipticaldoor

Reputation: 1272

How I can map the position in real pixels of the mouse to a normalized one when using glm::perspective?

I'm drawing a 2D tilemap using OpenGL and I will like to be able to know where the position of the mouse corresponds into my scene. This is what I currently have:

The 2D tilemap I'm drawing

To draw this screen this projection is used

glm::mat4 projection = glm::perspective(
  glm::radians(45.0f),
  (float)screenWidth / (float)screenHeight,
  1.0f,
  100.0f
);

Then this camera is used to move and zoom the tilemap

glm::vec3 camera(0.0f, 0.0f, -1.00f);

Which then translates into a camera view

glm::mat4 cameraView = glm::translate(state.projection, camera);

That finally gets passed through a uniform to the vertex shader

#version 330 core

layout(location = 0) in vec2 aPosition;

uniform mat4 uCameraView;

void main() {
  gl_Position = uCameraView * vec4(aPosition.x, aPosition.y, 0.0f, 1.0f);
}

This shader receives a normalized vertex, which it means that I never know how much in pixels a tile is in my screen.

Now I'm trying to somehow calculate where the mouse will be inside of my scene if it was projected like a ray into the tilemap and then hit it. If I managed to get the position of that collision I will be able to know which tile the mouse is hovering.

What will be the best approach to find this coordinate?

Upvotes: 1

Views: 211

Answers (1)

ellipticaldoor
ellipticaldoor

Reputation: 1272

In the end I found this solution to map the mouse pixel coordinates to the perspective:

glm::vec4 tile = glm::translate(projection, glm::vec3(0.0f, 0.0f, camera.z)) *
  glm::vec4(size.tile.regular, size.tile.regular, camera.z, 1.0f);
glm::vec3 ndcTile =
  glm::vec3(tile.x / tile.w, tile.y / tile.w, tile.z / tile.w);

float pixelUnit = windowWidth * ndcTile.x;

float pixelCameraX = (camera.x / size.tile.regular) * pixelUnit;
float pixelCameraY = (camera.y / size.tile.regular) * pixelUnit;

float originX = (windowWidth / 2.0f) + pixelCameraX;
float originY = (windowHeight / 2.0f) - pixelCameraY;

float tileX = (state.input.pixelCursorX - originX) / pixelUnit;
float tileY = (state.input.pixelCursorY - originY) / pixelUnit;

selectedTileX = tileX > 0 ? tileX : tileX - 1;
selectedTileY = tileY > 0 ? tileY : tileY - 1;

Upvotes: 1

Related Questions