I’m using threejs to render some models (gltf/glb). All of them are of different sizes, some are big and some are small. Now I want scale all of them to the same size.
if i use mesh.scale() that would scale the object relative to it’s own size. Is there any way to achieve this without manually calculating each model’s scale?
UPDATE:
Here’s my code
function loadModels(points) { // loader const loader = new GLTFLoader(); const dl = new DRACOLoader(); dl.setDecoderPath("/scripts/decoder/"); loader.setDRACOLoader(dl); let lengthRatios; const meshes = []; for (let i = 0; i < store.length; i++) { loader.load( store[i].model, (gltf) => { const mesh = gltf.scene; const meshBounds = new THREE.Box3().setFromObject(mesh); // Calculate side lengths of model1 const 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), }; if (lengthRatios) { lengthRatios = [ lengthRatios[0] / lengthMeshBounds.x, lengthRatios[1] / lengthMeshBounds.y, lengthRatios[2] / lengthMeshBounds.z, ]; } else { lengthRatios = [ lengthMeshBounds.x, lengthMeshBounds.y, lengthMeshBounds.z, ]; } meshes.push(mesh); if (meshes.length == store.length) { addModels(); } }, (xhr) => { console.log((xhr.loaded / xhr.total) * 100 + "% loaded"); }, (error) => { console.log("An error happened"); } ); } function addModels() { // Select smallest ratio in order to contain the models within the scene const minRation = Math.min(...lengthRatios); for (let i = 0; i < meshes.length; i++) { // Use smallest ratio to scale the model meshes[i].scale.set(minRation, minRation, minRation); // position the model/mesh meshes[i].position.set(...points[i]); // add it to the scene scene.add(meshes[i]); } } }
Advertisement
Answer
You should create a bounding box around each model.
//Creating the actual bounding boxes mesh1Bounds = new THREE.Box3().setFromObject( model1 ); mesh2Bounds = new THREE.Box3().setFromObject( model2 ); // Calculate side lengths of model1 let lengthMesh1Bounds = { x: Math.abs(mesh1Bounds.max.x - mesh1Bounds.min.x), y: Math.abs(mesh1Bounds.max.y - mesh1Bounds.min.y), z: Math.abs(mesh1Bounds.max.z - mesh1Bounds.min.z), }; // Calculate side lengths of model2 let lengthMesh2Bounds = { x: Math.abs(mesh2Bounds.max.x - mesh2Bounds.min.x), y: Math.abs(mesh2Bounds.max.y - mesh2Bounds.min.y), z: Math.abs(mesh2Bounds.max.z - mesh2Bounds.min.z), }; // Calculate length ratios let lengthRatios = [ (lengthMesh1Bounds.x / lengthMesh2Bounds.x), (lengthMesh1Bounds.y / lengthMesh2Bounds.y), (lengthMesh1Bounds.z / lengthMesh2Bounds.z), ]; // Select smallest ratio in order to contain the models within the scene let minRatio = Math.min(...lengthRatios); // Use smallest ratio to scale the model model.scale.set(minRatio, minRatio, minRatio);