Finding the 3D position of a point on an isometric view?

Started by
3 comments, last by Alberth 11 months ago

I have a 2:1 isometric 3D world where all of the world objects have AABBs, and I'm trying to add mouse selection of those objects. Positive X points to the bottom right, and positive Y points to the bottom left.

Where I'm at so far:

  • From my rendering logic, I already have a list of all of the objects and their AABBs, sorted by their draw order.
  • I can add this sorted list of objects to a spatial acceleration structure, to reduce the number of checks needed.
  • I'm able to click a point on the screen and get the floor position (z == 0) that was clicked.
  • I have some idea of how I could calculate the direction vector for this camera (rotate 60 around X, rotate -45 around Z).
  • I think I could use the floor position + inverted direction vector to cast a ray from the floor, towards the camera. I could then ask the acceleration structure for the objects in the intersected tiles, then reverse-iterate them and check for intersections with the ray.

This seems like it would work, but I was wondering: is there a way to know the 3D position of a point on the screen, so I can just cast a ray from it instead of from the ground?

The reason why this is difficult is that my camera is very simple, and isn't already set up to itself have a position. Here's how it currently works:

  • Set the world floor position that you want to center the camera on.
  • Convert the world position to a point in isometric screen space.
  • Use the point as the center of the camera, render anything within (point.x - w/2, point.y - h/2, w, h).

Since I'm just centering on a world position and doing the rest in screen space, I don't have any intuition about where the camera is actually located in the world.

Is there a straightforward way to do this? Should I forget it and just cast the ray from the floor? Is there a simpler overall approach that I should know about? Any help is appreciated!

Advertisement

Hello if you are using matrices then you can maybe use this post: https://gamedev.stackexchange.com/questions/34787/how-to-convert-mouse-coordinates-to-isometric-indexes

There are multiple explanations and examples for the inverse matrix. hope this helps ?.

This also should save you a ray cast if I understand correctly, since you are directly calculating the position instead of doing the ray cast^^.

“It's a cruel and random world, but the chaos is all so beautiful.”
― Hiromu Arakawa

Ultraporing said:

Hello if you are using matrices then you can maybe use this post: https://gamedev.stackexchange.com/questions/34787/how-to-convert-mouse-coordinates-to-isometric-indexes

There are multiple explanations and examples for the inverse matrix. hope this helps ?.

This also should save you a ray cast if I understand correctly, since you are directly calculating the position instead of doing the ray cast^^.

Thanks for the link ? Unfortunately I don't think I can use that approach, since I'm not using a 3D camera with matrices. I'm just using the standard iso transforms:

    // World -> Screen
    // 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);
    // Screen -> World
    // 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};

I'm also specifically looking to do the ray cast, since I want to test the ray against the AABBs of my world objects (I already have tile picking working).

I solved this problem by (virtual) painting a 1x1 pixels display window at the mouse coordinates, and then process the given elements that need to be painted.

This topic is closed to new replies.

Advertisement