Search code examples
javascriptthree.jsscale

ThreeJS Match GLTF Model To Size Of Bounding Box


I want to scale the imported GLB Model to the same size a cube in my scene. It is needed to make sure that the model stays inside the shadow casting areas and is big enough to make the shadows visible.

I 've calculated the bounding Boxes of both objects already:

// shadowcasting area 
var sceneExtent = new THREE.BoxGeometry( 4, 4, 4 );
var cube = new THREE.Mesh( sceneExtent, material );
var sceneBounds = sceneExtent.computeBoundingBox()

and

// imported mesh
model.traverse( function ( child ) {
    if ( child.isMesh ) {
        child.geometry.computeBoundingBox()
        meshBounds = child.geometry.boundingBox
    }
} );

but now I do not know what to do with them to modify the scale of the GLTF Model

// meshBounds = child.geometry.boundingBox
// sceneBounds = sceneExtent.computeBoundingBox()

// how to resize model scale to match size of sceneBounds

model.scale.set(1,1,1)

I've already researched quite a bit but I do not seem to understand the solutions I've found so far.

How can I modify the model scale to match the sceneBounds with the information I have?

UPDATE: To get the bounding box use .setFromObject() instead:

sceneBounds = new THREE.Box3().setFromObject( cube );
meshBounds = new THREE.Box3().setFromObject( model );

Solution

  • For example like this:

    // Calculate side lengths of scene (cube) bounding box
    let lengthSceneBounds = {
      x: Math.abs(sceneBounds.max.x - sceneBounds.min.x),
      y: Math.abs(sceneBounds.max.y - sceneBounds.min.y),
      z: Math.abs(sceneBounds.max.z - sceneBounds.min.z),
    };
    
    // Calculate side lengths of glb-model bounding box
    let lengthMeshBounds = {
      x: Math.abs(meshBounds.max.x - meshBounds.min.x),
      y: Math.abs(meshBounds.max.y - meshBounds.min.y),
      z: Math.abs(meshBounds.max.z - meshBounds.min.z),
    };
    
    // Calculate length ratios
    let lengthRatios = [
      (lengthSceneBounds.x / lengthMeshBounds.x),
      (lengthSceneBounds.y / lengthMeshBounds.y),
      (lengthSceneBounds.z / lengthMeshBounds.z),
    ];
    
    // Select smallest ratio in order to contain the model within the scene
    let minRatio = Math.min(...lengthRatios);
    
    // If you need some padding on the sides
    let padding = 0;
    minRatio -= padding;
    
    // Use smallest ratio to scale the model
    model.scale.set(minRatio, minRatio, minRatio);