Problem when using lookAt() on an imported mesh

I have created a simple sphere that moves from bottom to top and then called :

scar1.lookAt(sphere.position);

Where scar1 is the model of a weapon I imported and I’m trying to make the weapon point to the sphere when it moves, but it is positionned side way and it thus, it is not the canon that follow the sphere but the sides of the weapon…
here is the code:

var canvas = document.getElementById(“renderCanvas”); // Get the canvas element
var engine = new BABYLON.Engine(canvas, true); // Generate the BABYLON 3D engine

/******* Add the create scene function ******/
var createScene = function() {

// Create the scene space
var scene = new BABYLON.Scene(engine);

// Add a camera to the scene and attach it to the canvas
var camera = new BABYLON.UniversalCamera("Camera", new BABYLON.Vector3(-6.5, 0, 0), scene);
camera.attachControl(canvas, true);
var light = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(-1, -2, -1), scene);
light.position = new BABYLON.Vector3(5, 5, 5);
var ground = BABYLON.MeshBuilder.CreateGround("ground", {
    width: 40,
    height: 40,
    subdivisions: 4
}, scene);
ground.position.y = -2.05;
ground.receiveShadows = true;
var scar1;
var scar2;
var scar3;
var sphere = BABYLON.MeshBuilder.CreateSphere("mySphere", {
    diameter: 1,
    diameterX: 1
}, scene);
sphere.position.x = 20;
camera.setTarget(sphere.position);
var assetsManager = new BABYLON.AssetsManager(scene);
var meshTask = assetsManager.addMeshTask("scar task", "", "static/models/fn_scar-l/", "scene.gltf");
meshTask.onSuccess = function(task) {
    console.log("success");
    scar1 = task.loadedMeshes[0];
    task.loadedMeshes[0].position = BABYLON.Vector3.Zero();
    var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
    shadowGenerator.addShadowCaster(scar1);
    camera.position.y += 2;
    //scar1.rotationQuaternion = new BABYLON.Quaternion.RotationAxis(new BABYLON.Vector3(0, 0, 1), Math.PI/2);

    let t = 0;
    scene.registerBeforeRender(function() {
        let py = 25.0 * Math.cos(t / 3.5);
        sphere.position.y = py;
        t += 0.1;
        //scar1.rotationQuaternion = new BABYLON.Quaternion.RotationAxis(sphere.position, Math.PI/2);
        scar1.lookAt(sphere.position);

    });
    window.addEventListener("mousemove", function() {
        // We try to pick an object
        // var pickResult = scene.pick(scene.pointerX, scene.pointerY);
        // if (pickResult.hit) {
        // 	var targetPoint = pickResult.pickedPoint;
        // 	scar1.lookAt(new BABYLON.Vector3(targetPoint.x, targetPoint.y, targetPoint.z));
        //     scar1.rotationQuaternion = new BABYLON.Quaternion.RotationAxis(new BABYLON.Vector3(targetPoint.x, targetPoint.y, targetPoint.z), Math.PI/2);
        // }
    });
}
assetsManager.load();
var gizmoManager = new BABYLON.GizmoManager(scene);
gizmoManager.positionGizmoEnabled = true;
gizmoManager.rotationGizmoEnabled = true;
// Toggle gizmos with keyboard buttons
document.onkeydown = (e) => {
    if (e.key == 'w') {
        gizmoManager.positionGizmoEnabled = !gizmoManager.positionGizmoEnabled
    }
    if (e.key == 'e') {
        gizmoManager.rotationGizmoEnabled = !gizmoManager.rotationGizmoEnabled
    }
    if (e.key == 'r') {
        gizmoManager.scaleGizmoEnabled = !gizmoManager.scaleGizmoEnabled
    }
    if (e.key == 'q') {
        gizmoManager.boundingBoxGizmoEnabled = !gizmoManager.boundingBoxGizmoEnabled
    }
}

showWorldAxis(3);
return scene;

};
/******* End of the create scene function ******/

var scene = createScene(); //Call the createScene function

// Register a render loop to repeatedly render the scene
engine.runRenderLoop(function() {
scene.render();
});

// Watch for browser/canvas resize events
window.addEventListener(“resize”, function() {
engine.resize();
});

Thank you in advance for your help.

Hello!, you can probably call something like:

scar1.bakeTransformIntoVertices(BABYLON.Matrix.RotationY(Math.PI / 2);


Thanks for your answer.
I tried to add the line, but the problem seems to remain, here is a screeshot of the scene.
With my code becoming :

meshTask.onSuccess = function(task) {
console.log(“success”);
scar1 = task.loadedMeshes[0];
scar1.bakeTransformIntoVertices(BABYLON.Matrix.RotationY(Math.PI / 2));
task.loadedMeshes[0].position = BABYLON.Vector3.Zero();
var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
shadowGenerator.addShadowCaster(scar1);
camera.position.y += 5;
camera.position.z += 5;
camera.setTarget(scar1.position);
sphere.position.y = 15;
scar1.lookAt(sphere.position);
// let t = 0;
// scene.registerBeforeRender(function() {
// let py = 25.0 * Math.cos(t / 3.5);
// sphere.position.y = py;
// t += 0.1;
// scar1.lookAt(sphere.position);
//
// });
window.addEventListener(“mousemove”, function() {
// We try to pick an object
// var pickResult = scene.pick(scene.pointerX, scene.pointerY);
// if (pickResult.hit) {
// var targetPoint = pickResult.pickedPoint;
// scar1.lookAt(new BABYLON.Vector3(targetPoint.x, targetPoint.y, targetPoint.z));
// scar1.rotationQuaternion = new BABYLON.Quaternion.RotationAxis(new BABYLON.Vector3(targetPoint.x, targetPoint.y, targetPoint.z), Math.PI/2);
// }
});
}

are you sure that scar1 is the right mesh (maybe it is one of its children)
You can get a view of your scene tree by calling scene.debugtLayer.show()


I’m quite new to this so I could not tell you if if is one of its children, but here is a screen of the debugging layer.

yep so from what I’m seeing, the gun is not the first child so scar1 = task.loadedMeshes[0] will not point to the right one

Damn it =D Am I doing this assetManager thing wrong ?
When I modify the rotation, position, and so forth, it does work, what am I missing here ?

it works because of inheritance but to bake a transform you need to do it on the actual mesh.
Does it make sense?

Oh ok, it does make sense but then, is it a problem with the .gltf file in itself ?

nope this is totally fine to have a hierarchical structure. Perhaps you may want to better name your nodes so you can easily find them by name with scene.getMeshByName()

Thanks for your answer.
Am I giving a name when doing :

var meshTask = assetsManager.addMeshTask(“scar task”, “scar”, “static/models/fn_scar-l/”,
“scene.gltf”);

Because when doing so, the gun does not appear anymore. However in the doc, it says “meshesName” for this parameter.
Sorry for being such a noob, I started learning babylone yesterday.

No worries. I didn’t mean to change the way you load it but more the way you reference it :slight_smile:

Use scene.getMeshByName instead of scar1 = task.loadedMeshes[0]

I retrieved the name by doing :

alert(task.loadedMeshes[0].name);

The displayed name is “__root__”, so I wrote :

scar1 = scene.getMeshByName("__root__");

But the gun is still turned sideways and

scar1.bakeTransformIntoVertices(BABYLON.Matrix.RotationY(Math.PI / 2));

doesn’t seem to work.
Here is the code :

meshTask.onSuccess = function(task) {
scar1 = scene.getMeshByName("__root__");
scar1.bakeTransformIntoVertices(BABYLON.Matrix.RotationY(Math.PI / 2));
scar1.position = BABYLON.Vector3.Zero();
camera.setTarget(scar1.position);
scar1.lookAt(sphere.position);
var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
shadowGenerator.addShadowCaster(scar1);
});

Yes but this is what I try to say. The mesh ( the real one with geometry) is not root but one of the children (deep down your hierarchy)

So let try something else. Keep all the code you where doing before. Remove the call to bake Transform and instead just add this line:

scene.getMeshByName("Root").rotation.y = Math. PI/2

Oh I see.
I added the line but it didn’t work, and turns out :

console.log(scene.getMeshByName(“Root”));

prints null. This is weird.

my bad it is not a mesh but a transformNode :slight_smile:
console.log(scene.getTransformNodeByName(“Root”));

After adding the line of code, it does not work.
Here is the code:


Is this way even the advised one ? Or is it better to import a .babylone file and not have these kind of problem ? I must say that it is quite frustrating.

You will get it, sometimes it just takes a bit of tinkering with model files.
For example, look at this one I threw together.
https://www.babylonjs-playground.com/#8LFTCH#28

I am having to multiply the direction of the ball by -1, since the normal lookAt uses the tail of the bird.
There is no problem with gltf vs babylon.

Also you are not helping us to help you…We need a repro in the playground. With a repro this could be fix in 10 minutes

Yeah I wanted to make a playground but how can I put the gun model in it so you can see the problem?