Zoom where move cursor is in orthographic mode

Hi, I currently have a arcRotateCamera setup in orthographic mode that zooms by manually setting the orthoLeft, orthoRight, orthoTop and orthoBottom properties on the camera object. This works fine, however I’d like it to zoom where the camera is rather than the centre of the screen. I’m pretty new to the 3D programming world and hence not 100% sure how I would even start to go about accomplishing that so any direction would be great.

For reference, this is roughly the code I wrote to zoom(actually broken up into multiple functions):

const delta = (Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)))) * 1.5;
const zoomingOut = delta < 0;
// limit zooming in to no less than 3 units.
if (!zoomingOut && Math.abs(camera.orthoLeft) <= 3)
    return;
camera.orthoLeft += delta;
camera.orthoRight -= delta;

const ratio = canvas.height / canvas.width;
camera.orthoTop = camera.orthoRight * ratio;
camera.orthoBottom = camera.orthoLeft * ratio;

// decrease pan sensitivity the closer the zoom level.
camera.panningSensibility = 6250 / Math.abs(camera.orthoLeft);

Hey!
can you share a repro in the playground so we can hack your code? :slight_smile:

Sure, hack away!

https://playground.babylonjs.com/#EBPQH9#1

Thanks!

Hum it seems pretty cool already :slight_smile: what are you looking to change?

I’d like the zoom to zoom in on where the mouse cursor is rather than the centre of the screen. Like most CAD programs.

well… Then you first need to offset the position and then zoom right?

So something like this?

camera.setPosition(new BABYLON.Vector3(scene.pointerX, scene.pointerY, camera.position.z));

Although I need to convert scene.pointerX and scene.pointerY to local coordinates.

right :slight_smile:
You can move from 2d to 3d with something like that:

var target = BABYLON.Vector3.Unproject(
            new BABYLON.Vector3(scene.pointerX, scene.pointerY, 0),
            screenwidth,
            screenheight,
            new BABYLON.Matrix.Identity(),
            cam.getViewMatrix(),
            cam.getProjectionMatrix()
        );
1 Like

Thanks @Deltakosh for the code sample. It seems to give me the correct x & y coordinate however when I try to use those coordinates to set the position of the camera, or set the target of the camera, or both, strange things happen:

https://playground.babylonjs.com/#EBPQH9#9

I fixed the screenwidth and height which are not the one of the window but the one of the engine: https://playground.babylonjs.com/#EBPQH9#11

What do you find wrong ?

I’m looking to have the zoom act like the following video:

I’ve got it pretty close! But it doesn’t feel very smooth right now:

https://playground.babylonjs.com/#EBPQH9#14

Also I had to switch to using Z instead of Y for the Y offset from BABYLON.Unproject which I don’t understand why.

1 Like

Z instead of Y is because your camera is looking down Y axis so this is expected.

For smoothness, you just need to reduce the delta value

2 Likes

@davidworkman9

camera.panningSensibility = 6250 / Math.abs(camera.orthoLeft);

Why did you use the number 6250 ? I am trying to understand your code.

@constantinos I brought that in from the project I’m working on. It’s the constant that I found for my use case felt the best at the various zoom levels I allow.

For anyone that’s curious, I ended up changing the orthoLeft/Top/Right/Bottom to get it to zoom the way I wanted rather than changing the target and position of the camera. It works really well.

https://playground.babylonjs.com/#EBPQH9#19

2 Likes

Thanks for sharing this. I’ve been a bit stumped by the default zooming behavior by the orthographic camera mode.

I still can’t seem to get this to work on Firefox (v73.0, Linux). Any idea what might be missing?
I have no issues on Chrome…

Can you share a repro of what does not work in firefox using our Playground?

Looks like it’s related to event.wheelDelta being undefined. There’s a topic about this here:

With the solution being to used event.deltaY instead. Here’s a playground with that change. I tried it in Firefox on Mac and it’s working:

1 Like

Well so it works now? :slight_smile:

https://playground.babylonjs.com/#EBPQH9#23
In the above PG, it’s working for 2D view.
How to apply the same for 3D view?