How to manipulate isometric / orthographic camera to keep content onscreen and optimally scaled?

Hey sorry no playground but you can see from the above video we have an isometric world using an orthographic camera.

We would like it so that the board always stays visible on the screen at all times (with a little padding around the outside) but also optimally takes up the optimal amount of space on the screen it can.

I have already tinkered with it quite a bit to get it to where it is able to always keep it visible and is optimal in the vertical dimension but as you can see when the window shrinks horizontally it grows a bunch of padding on the left and right hand side which should not be needed.

Code is really messy but here is the method im currently using (cobbled together from various sources)

export interface OrthographicCameraSettings {
  minHeight: number;
  maxHeight: number;
  scaleFactor: number;
  aspectMultiplier: number;
}

export class OrthographicCamera {
  constructor(private scene: Scene, public settings: OrthographicCameraSettings) {}

  calculateZoom() {
    const rect = ensure(this.scene.getEngine().getRenderingCanvasClientRect());
    const aspect = rect.height / rect.width;

    const zoom =
      ((rect.width * 0.001) /
        clamp(rect.height, this.settings.minHeight, this.settings.maxHeight)) *
      this.settings.scaleFactor;

    const constrained = clamp(zoom, aspect * this.settings.aspectMultiplier, 20);

    return constrained;
  }

  updateCamera(camera: ArcRotateCamera) {
    const zoom = this.calculateZoom();

    const rect = ensure(this.scene.getEngine().getRenderingCanvasClientRect());
    const aspect = rect.height / rect.width;

    camera.orthoLeft = -camera.radius * zoom;
    camera.orthoRight = camera.radius * zoom;
    camera.orthoBottom = -camera.radius * aspect * zoom;
    camera.orthoTop = camera.radius * aspect * zoom;
  }
}

Here’s how I would do it:

It tries to use the maximum space in the X dimension by keeping the right aspect ratio and same thing for the Y dimension. It needs the scene X and Y world extents and is computed in computeSceneBounds in the PG. Note that it needs the extents as seen by the camera, so the world extents of the meshes are transformed by the camera view matrix.

If you move (rotate) the camera in the PG, hit “Enter” to recompute the new extents and to fit the display in the screen.

6 Likes

Wow!!! This is absolutely perfect! Thankyou so much :smiley:

i tried using the same code structure, but it wouldn’t work for me. I want to be able to use it for ArcRotateCamera.

The PG already uses an arc rotate camera. It is created by the scene.createDefaultCamera(true, true, true); call, the camera created line 6 is not used.