Centerpoint correction on loaded model

Hello,
i am trying to load a model and then create an environment like in the babylon sandbox.
Since I am not using a file input but rather the BABYLON.SceneLoader.Append method, it seems that some things are working differently to the BABYLON.FilesInput loading.
My main concern is that the loaded model in the sandbox example gets its centerpoint nicely corrected.
In the SceneLoader.Append version my model rotates slightly off-center.
Any idea what could cause this?
Here is what I do:

	 var canvas = document.getElementById("renderCanvas"); // Get the canvas element 
 var engine = new BABYLON.Engine(canvas, true, { premultipliedAlpha: false, preserveDrawingBuffer: true });
 engine.loadingUIBackgroundColor = "#000000";
 BABYLON.Engine.ShadersRepository = "/src/Shaders/";
 BABYLON.Animation.AllowMatricesInterpolation = true;
 BABYLON.GLTFFileLoader.IncrementalLoading = false;
 BABYLON.SceneLoader.OnPluginActivatedObservable.add(function(plugin) {
     currentPluginName = plugin.name;
     console.info(currentPluginName);
 });	
 window.addEventListener("resize", function() {
     engine.resize();
 });
 
 var scene = new BABYLON.Scene(engine);
 var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2, Math.PI / 2, 12, BABYLON.Vector3.Zero(), scene);
 camera.attachControl(canvas, true);

 var sceneLoaded = function (sceneFile) {
	 
	 scene.skipFrustumClipping = true;
 	 engine.clearInternalTexturesCache();
     scene.createDefaultCamera(true);
	 
     if (currentPluginName === "gltf") {
         // glTF assets use a +Z forward convention while the default camera faces +Z. Rotate the camera to look at the front of the asset.
         scene.activeCamera.alpha += Math.PI;
     }

     // Enable camera's behaviors
     scene.activeCamera.useFramingBehavior = true;

     var framingBehavior = scene.activeCamera.getBehaviorByName("Framing");
     framingBehavior.framingTime = 0;
     framingBehavior.elevationReturnTime = -1;

     if (scene.meshes.length) {
         var worldExtends = scene.getWorldExtends();
		 console.info(worldExtends);
         scene.activeCamera.lowerRadiusLimit = null;
         framingBehavior.zoomOnBoundingInfo(worldExtends.min, worldExtends.max);
     }
	
     scene.activeCamera.pinchPrecision = 200 / scene.activeCamera.radius;
     scene.activeCamera.upperRadiusLimit = 5 * scene.activeCamera.radius;
	 
     scene.activeCamera.wheelDeltaPercentage = 0.01;
     scene.activeCamera.pinchDeltaPercentage = 0.01;
	 scene.activeCamera.attachControl(canvas);
	 scene.createDefaultLight();
	
 }
 BABYLON.SceneLoader.Append("models/", "model.glb", scene, sceneLoaded);

This should work :slight_smile:
can you repro in the PG so we can see what is going wrong?

Hello,
i tried to recreate it in the playground, however i am not allowed to show the model i am actually using because of an nda.
So i used a different model i found ( “https://bjs-playground.s3.amazonaws.com/”, “astro.glb”)
With this model I am not experiencing the issue described in the original topic.
See the playground here: https://www.babylonjs-playground.com/#ZFPAHV#1
However also I do not get the Zoom limitations I am getting in my local version.

What I am basically trying to achieve is to load a glb / gltf model, center it and place it on the stage with zoom limitations like in the sandbox example.
Thanks !

Yeah but it works in your example :smiley: So it comes from your model and you cannot share it…

Can you make sure the model you are loading has is pivot at its center?

I believe there are two primary options here,

  1. The model has a pivotPoint which is not (0,0,0)
    Check output of; mesh.getPivotPoint()
    Attempt to fix; mesh.setPivotPoint( BABYLON.Vector3.Zero() )

  2. The “offset” is baked into the model’s geometry
    In this case, either manually (mesh.position…)
    or using the inspector, position the mesh correctly,
    then; mesh.bakeCurrentTransformIntoVertices()
    -Note that this bakes and resets position / rotation (0,0,0), scaling (1,1,1)

I bet i forgot something, somewhere :slight_smile:
In a perfect world this should be returned to the 3D editor who made it, for fixing, then they’ll also learn something new :smiley:
I hope you get it sorted.

2 Likes

Ok, so I updated the code and uploaded the model without a texture.
https://www.babylonjs-playground.com/#ZFPAHV#3
you can download the model under https://dl.dropbox.com/s/q72q7ha10wxknxc/pot.glb
and try it in the sandbox, then you will see the difference.
I basically copied all the relevant code from the sandbox source but I neither get the corrected centerpoint, nor the zoom restrictions that the sandbox applies.

Hi EvilTwinsNiceBrother,

Does this have the behavior you’re looking for?

https://www.babylonjs-playground.com/#ZFPAHV#4

The only lines I added were lines 46, 47, and 48. (I also removed a line that was creating an engine, which was causing an error for me as there was already an engine created.) As aWeirdo pointed out above, the reason the model appeared off-center was because its pivot is off-center, which can’t really be automatically corrected by the engine because it’s impossible to know whether it was intentional or not. However, if you want to rotate around the model’s geometric centroid and not the built-in pivot, you can just tell the ArcRotateCamera to target the center of the model’s bounding volume, which is computed at runtime. Hope this helps!

1 Like

Seems i was too slow :smiley:

Either way, here’s a prototype to re-center a mesh.

https://www.babylonjs-playground.com/#ZFPAHV#5

Thanks a lot.
that does indeed deal with the issue!
The only thing I need as well is to prohibit the zoom “through” the outer wall of the object.
Is this possible?

Without starting to mess around with collisions and stuff like that,
you can use the boundingInfo again here,
upside is performance & simplicity,
downside is that radiusWorld is the furthest point of the mesh from it’s center,
thus having a tall mesh like you do, you can zoom very close to the top/bottom, but less close to the sides.

scene.activeCamera.lowerRadiusLimit = scene.meshes[1].getBoundingInfo().boundingSphere.radiusWorld;

(Line #57)
https://www.babylonjs-playground.com/#ZFPAHV#6

2 Likes

Thank you. This did help a lot.

One hopefully last question i have:
in the sandbox example the camera is not zoomed in completely on load.
https://sandbox.babylonjs.com/index.html?assetUrl=https://dl.dropbox.com/s/q72q7ha10wxknxc/pot.glb
In the current example https://www.babylonjs-playground.com/#ZFPAHV#7
the zoom is much higher.
Is this behaviour defined with the creation of the camera?
I could not fnd any line that would do that.

I just tried a different, more complex model to see about performance and here the zooming does not work
https://www.babylonjs-playground.com/#ZFPAHV#9
I presume it has might have to with the fact that there are multiple meshes, so I guess

scene.meshes[0]

wont work as a limit to the full model.
I guess I’d need to compare all the bounding boxes of the meshes?

Hi @EvilTwinsNiceBrother
The radius is indeed defined at camera creation,

Here it is set to 12;
…new BABYLON.ArcRotateCamera(“Camera”, Math.PI/2, Math.PI / 2, 12, BAB…

As for multi-mesh support,
In this case, i suggest finding the center of worldExtends / all meshes.
See lines #34 - #46 Here
That’s how i would do it when dealing with more complex mesh hierarchies.
This should work in all (or at least most) cases.

I hope it helps :slight_smile:

Hi @aWeirdo
Thanks a lot.
Well this evaluation of the meshes surely doe help, however now with other, simpler models ( as in https://www.babylonjs-playground.com/#ZFPAHV#11 )
The initial zoom is again to large.
Somehow the original sandbox code does seem to be able to handle all of these models.
I cannot seem to find where and how though. :thinking:

Hi @EvilTwinsNiceBrother

See line #48
https://www.babylonjs-playground.com/#ZFPAHV#12

It will update the camera radius based on lowerRadiusLimit, which in turn is based on the mesh’s size.
The initial “zoom” you’re seeing is because the radius was static at 12 units, so a large mesh would look “zoomed” compared to a small mesh.

Great!
Thanks so much!
I was looking at the original sandbox code for clues but could not find any.
I guess there must be some other “magic” involved elsewhere.

Hello,
needed to revisit this topic since i tried to load the BoomBox.glb from ( https://raw.githubusercontent.com/BabylonJS/Babylon.js/master/Playground/scenes/BoomBox.glb )
This does not work correctly:
https://www.babylonjs-playground.com/#ZFPAHV#14
The model shows up nicely in the sandbox however.
Babylon.js Sandbox - View glTF, glb, obj and babylon files

Any ideas?
thanks!

The coordinates of the 3D model are very small, you need to put your camera nearer of it:

https://www.babylonjs-playground.com/#ZFPAHV#15

1 Like

ah, thank you!