I'm trying to cast a ray so I can implement mouse picking. My game uses 2:1 isometric with a 3D world sim that uses AABBs. Positive X points to the bottom right, positive Y points to the bottom left, positive Z is up.
I currently have a screen -> world conversion function that will tell me where a mouse click intersects with Z==0:
// Offset the screen point to include the camera position.
float x{screenPoint.x + camera.extent.x};
float y{screenPoint.y + camera.extent.y};
// Calc the scaling factor going from screen tiles to world tiles.
float TILE_WIDTH_SCALE{TILE_WORLD_WIDTH / TILE_SCREEN_WIDTH};
float TILE_HEIGHT_SCALE{TILE_WORLD_WIDTH / TILE_SCREEN_HEIGHT};
// Calc the world position.
float worldX{((2.f * y) + x) * TILE_WIDTH_SCALE};
float worldY{((2.f * y) - x) * TILE_HEIGHT_SCALE / 2.f};
Is there maybe an alternate form of this conversion that will get me a ray? I don't have a set of matrices to unproject, I'm just using these iso conversions.
Another thought I had is: the direction vector out of the camera is constant, so I could just calculate that and use it for my ray. The issue is, I don't know my camera's position so I don't know the ray's origin. My camera is very simple, it's just centered on a world-space position using the following steps:
- Set the world-space floor (Z==0) position that you want to center the camera on.
- Convert the world position to a point in isometric screen space.
- Render anything within (point.x - screenWidth/2, point.y - screenHeight/2, screenWidth, screenHeight).
Edit: As requested, here's my world -> screen conversion:
// Calc the scaling factor going from world tiles to screen tiles.
float TILE_WIDTH_SCALE{TILE_SCREEN_WIDTH / TILE_WORLD_WIDTH};
float TILE_HEIGHT_SCALE{TILE_SCREEN_HEIGHT / TILE_WORLD_WIDTH};
// Convert cartesian world point to isometric screen point.
float screenX{(position.x - position.y) * (TILE_WIDTH_SCALE / 2.f)};
float screenY{(position.x + position.y) * (TILE_HEIGHT_SCALE / 2.f)};
// The Z coordinate contribution is independent of X/Y and only affects the
// screen's Y axis. Scale and apply it.
screenY -= (position.z * Z_SCREEN_SCALE);