ActionManager with AssetManager and Camera pivot points

Delta was so kind to post for me: https://www.babylonjs-playground.com/#PFKSUJ#1

Originally I had 5 boxes and I was trying to get the camera to change targets on double-click. Each time I changed target, the camera would then rotate around the newly selected mesh. Great! So, I changed some things and this time around I used AssetManager to load up a model I have. Only now I’ve noticed that, while the double-clicks are catching the correct meshes, the camera doesn’t focus on the selected mesh or change its pivot point to the selected mesh’s position. Why and how do I fix this?

Again, I apologize for the lack of a playground. I can’t get one to save today for the life of me. Here’s the code.

var createScene = function() {
    var scene = new BABYLON.Scene(engine);
    scene.clearColor = new BABYLON.Color3(0.8, 0.8, 0.8);
    scene.checkCollisions = true;
    scene.collisionsEnabled = true;
    var camera = new BABYLON.ArcRotateCamera("camera1", 0, 0, 10, new BABYLON.Vector3(0, 0, 0), scene);
    camera.attachControl(canvas, true);
    camera.checkCollisions = true;
    camera.applyGravity = true;
    camera.speed = 1;
    camera.layerMask = 2;

    var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 1), scene);
    light.intensity = .5;

    var assetsManager = new BABYLON.AssetsManager(scene);

    var meshTask = assetsManager.addMeshTask("mtask", "", "https://raw.githubusercontent.com/carlos-mendieta/models/master/", "AH-64.obj");

    assetsManager.load();
    meshTask.onSuccess = function (task) {
        let ms = task.loadedMeshes.filter(function (mesh) {
            return mesh.geometry._totalVertices > 0;
        });
        var meshes = ms;  

        meshes.forEach(function (mesh) {
             mesh.checkCollisions = true;
        mesh.ellipsoid = new BABYLON.Vector3(1, 1, 1);
        mesh.ellipsoidOffset = new BABYLON.Vector3(0, 0, 0);
        mesh.scaling.x = mesh.scaling.y = mesh.scaling.z = 1;
        mesh.isPickable = true;            
        mesh.renderOutline = true;
        mesh.outlineColor = new BABYLON.Color3(0, 0, 0);
        mesh.outlineWidth = .3;

        mesh.actionManager = new BABYLON.ActionManager(scene);            
        mesh.actionManager.registerAction(
            new BABYLON.ExecuteCodeAction(
                {
                    trigger: BABYLON.ActionManager.OnDoublePickTrigger,
                },
                function () {  
                    camera.setTarget(mesh.position);
                    console.log("selected " + mesh.id);
                }
            )
        );
    });
};

return scene;

};

Here is your PG: Babylon.js Playground (try to clear your cache to fix your PG saving issue)

1 Like

I’ve checked your PG. You are always picking the same object (UniqueID === 526). You should make sure to flag only meshes that you want (by flagging others as isPickable = false)

1 Like

Ok, so after thinking about it for a while, I started realizing I was overcomplicating things. To make it easier, I just grabbed the point I wanted the camera to rotate around with scene.pick. I don’t know what I was thinking before, but this works great now.

the playground

Now I have a different problem. I put the code into a project and its not working. It doesn’t appear to detect my double-clicks. Here’s my code

        meshes.forEach(function (mesh) {                
            mesh.ellipsoid = new BABYLON.Vector3(1, 1, 1);
            mesh.ellipsoidOffset = new BABYLON.Vector3(0, 0, 0);
            mesh.scaling.x = mesh.scaling.y = mesh.scaling.z = 1; //0.3;

            mesh.material = new BABYLON.StandardMaterial("modelTexture", scene);
            mesh.material.diffuseTexture = modelTexture;
            mesh.material.bumpTexture = new BABYLON.Texture(modeltexture, scene);               
            mesh.material.specularTexture = new BABYLON.Texture(modeltexture, scene);
            mesh.material.emissiveTexture = new BABYLON.Texture(modeltexture, scene);

            mesh.isPickable = true;
            
            camera.setTarget(mesh, true, true);

            mesh.renderOutline = true;
            mesh.outlineColor = new BABYLON.Color3(0, 0, 0);
            mesh.outlineWidth = .3;

            setMeshActions(mesh);   // Also tried to set the code directly here, 
                                    //  without the function but no joy.
        });

        var setMeshActions = function (mesh) {
        mesh.actionManager = new BABYLON.ActionManager(scene);            
        mesh.actionManager.registerAction(
            new BABYLON.ExecuteCodeAction(
                {
                    trigger: BABYLON.ActionManager.OnDoublePickTrigger,
                },
                function () {
                    console.log("Got inside the action!");   // doesn't even get here
                    var dpic = scene.pick(scene.pointerX, scene.pointerY);

                    if (dpic.hit) {
                        var pickresult = scene.pick(scene.pointerX, scene.pointerY);
                    }

                    camera.setTarget(pickresult.pickedPoint);                        
            }
        )

The logging at the start of the setMeshActions method doesn’t even fire off. I’m not sure what to think, as I moved the code from playground to project over in the same place.

Can you create a new question and provide a PG? (Easier for others to search later :))

1 Like

Hi CM! Ok, this is a difficult issue.

All 74 mesh in this heli… have a .getAbsolutePosition() of 0,0,0. That makes it VERY difficult to animate arcCam.lockedTarget… to ANY of those mesh positions.

Every mesh is at position 0,0,0… because of the WAY the heli was created.

Also, it is very difficult to PICK a mesh that is blocked by another isPickable mesh. We could only pick a FEW “outer skin” mesh, and never anything “inside”. And even when we DID pick the outer mesh, it had a position of 0,0,0, so it was impossible to animate the camera.lockedTarget to THAT position. 0,0,0 would be the WRONG position.

These 74 mesh are positioned via “transformed vertices” and not via .position property values.

The best you can do with moving arcCam.lockedTarget to various positions… is to use “clickZone mesh”.

Take a look… https://www.babylonjs-playground.com/#STX192#9

(lots of “debris” outputted to console during the model loading. I’m not sure why)

Click on some clickZones. Working okay?

Later, ALL clickZone mesh and the camera.lockedTarget mesh… will be set .visibility = 0… so user cannot see them. It took a LONG TIME for me to build the six clickZone mesh for this model, but they work pretty well.

An animation utility add-on is placed onto ALL mesh (including camera.lockedTarget)… in lines 1-5.

SetActions function is not called at all, because no actionManagers are put onto the 74 mesh. ONLY put onto the 6 clickZone mesh. Each of the clickZone mesh DOES have a non-0,0,0 .position… so we can use the animator… to animate arcCam.lockedTarget… to THOSE clickZone positions.

Add as many clickZones as you wish, using the same format as I have used. The more clickZones you have, the more precise your clicking/lockedTarget “resolution” can be.

It’s not the same as being able to click all 74 mesh, and have the .lockedTarget animate to each. BUT… it’s not too bad, and it works for transformed-vertex models like this helicopter.

Wha-da-ya-think? Would THIS method of moving camera.lockedTarget… work ok for your project?

With models like this helicopter, there are not many target-moving choices available.

I hope I have been helpful. Ask questions, make comments, we’re here to help. Click on some clickZone mesh… have some fun.

PS: I changed the double-click… to single-click. You might wish to change that back-to double-click, as wanted.

3 Likes

Sweet answer and PG @Wingnut!

2 Likes

Uh oh, I started thinking about the helicopter, and about “transformed vertices”… and and and…

… I decided to try another non-clickzone version. (instead, putting an actionManager on all 74 mesh).

https://www.babylonjs-playground.com/#STX192#16

I started wondering WHERE are boundingBoxes… located… when mesh are using transformed-verts and their .position is always 0,0,0. SO… I turned on the boundingBoxes for all 74 mesh.

Hey, look at that. They are all in proper place. SO… I can use pickedMesh.getBoundingInfo().boundingBox.center… as the moveTo target for cam.lockedTarget. (line 79)

In other words, I CAN find the center of all 74 mesh, and use it as a location to aim the camera (when picked). Hunh. (I didn’t think I could do that, when I yapped earlier).

This means I said some foolish and incorrect things… in a previous post. Sorry.

Anyway, this new test version… allows us to click on SOME of the 74 mesh… and cam target will gladly make the trip. I think @Carlos.Mendieta knew this… LONG AGO. He probably removed those clickZones and used boundingBox centers… MONTHS ago. I finally caught-up. :slight_smile:

1 Like