Camera Panning Limit

Hello all,

I have been working on a Babylon project that works similarly to Google-maps/Google earth. Basically I have a 3D map with a camera that allows the user to move around using the map.

I have iterated on how to handle the movement but settled on using the ArcRotateCamera’s base panning behaviour.

I toggled map panning to true to keep transforms limited to the X axis. I added a limit to stop the user from ‘escaping’ the map.

However, when near the edges the camera gets ‘stuck’ and you can’t move around near the edges as smooth.

I have tried increasing the limit which allows the user to better move around the map, however this meant the user could end up seeing the edge of the map. I want to keep the camera contained but want the camera to move around smoothly even when on the edges.

Does anyone have an idea of how this might be done?

I have attached a basic playground with my camera setup. The plane is the map and if you use RMB to pan around to the edges you can see the skippyness/stuckness.

Thanks!

cc @PolygonalSun

With cameraPanningLimit, your camera shouldn’t be able to pan outside of the defined radius. If you’re going for something like keeping your camera on a map or in a box, this may not be the best approach. Depending on how you have things set up, you could set up a bounds check to happen as a part of the beforeRender callback:

    // Our built-in 'ground' shape.
    var width = 12;
    var height = 12;
    var ground = BABYLON.MeshBuilder.CreateGround("ground", {width: width, height: height}, scene);

    // Before each rendered frame, if the target's current value exceeds the limit, move it back.
    scene.beforeRender = () => {
        const xLimit = width / 2;
        const yLimit = height / 2;

        if (camera.target.x < -xLimit) {
            camera.target.x = -xLimit;
        }
        else if (camera.target.x > xLimit) {
            camera.target.x = xLimit;
        }

        if (camera.target.z < -yLimit) {
            camera.target.z = -yLimit;
        }
        else if (camera.target.z > yLimit) {
            camera.target.z = yLimit;
        }
    };

In this example, we have the ground acting as a sort of limit and we’re checking that the camera’s target remains in that limit. For more complex boundaries, this may not be the best solution but this way should also ensure smoother movement at the boundaries.

1 Like

Hey man, thanks for coming back to me on this.

This was actually one of the avenues I explored when iterating on the camera movement. I will give this a shot and report back with any more questions.

Thanks again

Just a follow up after trying it on my actual scene.

The functionality works great. I can set the limit bounds for the camera target and have removed the panning limit from the camera. Now when you reach the X bound or Y bound in either direction the camera just stops movement in that direction but can still ‘slide’ along on the other axis.

Before I had used a similar function but instead of the putting the check before the render, I had it where when you dragged to move the camera, a movement vector is generated which is used to move the camera. I would then check where the camera ends up and then if it is out of the limits, then don’t move it. This resulted in a weird situations where big swipes would not move you (since the result would put you out of bounds) but small swipes would slowly get you to the edge and it just didn’t feel great.

This new functionality is exactly what I wanted, so thanks again @PolygonalSun and @sebavan.

I have added it to the playground here just in case anyone wants an example of it: https://playground.babylonjs.com/#82G302#3

3 Likes