Search code examples
babylonjs

On mesh click, ArcRotateCamera focus on


I'm using ArcRotateCamera, when I click on mesh, I have to focus camera on

var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2, Math.PI / 2, 300, BABYLON.Vector3.Zero(), scene);
camera.setTarget(BABYLON.Vector3.Zero());



// on mesh click, focus in
var i = 2;
var pickInfo = scene.pick(scene.pointerX, scene.pointerY);
        if (pickInfo.hit) {
            pickInfo.pickedMesh.actionManager = new BABYLON.ActionManager(scene);
            pickInfo.pickedMesh.actionManager.registerAction(
                new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger,
                    function (event) {
                        camera.position = (new BABYLON.Vector3(pickInfo.pickedPoint.x, pickInfo.pickedPoint.y, camera.position.z + i));
                        i += 2;
                    })
            );
        }

this code changes mesh's z position but don't makes it in the center of screen


Solution

  • There are a few things that can be changed in your code.

    1st - what you are doing is executing a code action after a click, instead of simply running the code in the callback after a pick has occurred. You are registering a pick action (technically user click) on right on the first frame, but only if the mouse was found in the right location at the right moment. My guess is that it didn't work every time (unless you scene is covered with meshes :-) )

    2nd - you are changing the camera's position, instead of change the position to which it is looking. Changing the camera's position won't result in what you want (to see the selected mesh), it will move the camera to a new position while still focusing on the old position.

    There are a few ways to solve this. The first is this:

    scene.onPointerDown = function(evt, pickInfo) {
            if(pickInfo.hit) {
                camera.focusOn([pickInfo.pickedMesh], true);
            }
        }
    

    The ArcRotate camera provides focusOn function that focuses on a group of meshes, while fixing the orientation of the camera. this is very helpful. You can see a demo here:

    https://playground.babylonjs.com/#A1210C#51

    Another solution would be to use the setTarget function:

    https://playground.babylonjs.com/#A1210C#52

    Which works a bit differently (notice the orientation change of the camera).

    Another thing - use the pointer events integrated in Babylon, as they are saving you the extra call for a scene pick. pointer down is executed with the pickinfo integrated in the function, so you can get the picking info of the current pointer down / up / move each frame.

    **** EDIT ****

    After a new comment - since you want to animate the values, all you need to do is store the current values, calculate the new ones, and animate the values using the internal animation system (documentation here - https://doc.babylonjs.com/babylon101/animations#basic-animation) . There are many ways to achieve this, I took an old function and modernized it :-)

    Here is the demo - https://playground.babylonjs.com/#A1210C#53