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
JavaScript
x
70
70
1
function loadModels(points) {
2
// loader
3
const loader = new GLTFLoader();
4
5
const dl = new DRACOLoader();
6
dl.setDecoderPath("/scripts/decoder/");
7
loader.setDRACOLoader(dl);
8
9
let lengthRatios;
10
const meshes = [];
11
12
for (let i = 0; i < store.length; i++) {
13
loader.load(
14
store[i].model,
15
(gltf) => {
16
const mesh = gltf.scene;
17
const meshBounds = new THREE.Box3().setFromObject(mesh);
18
19
// Calculate side lengths of model1
20
const lengthMeshBounds = {
21
x: Math.abs(meshBounds.max.x - meshBounds.min.x),
22
y: Math.abs(meshBounds.max.y - meshBounds.min.y),
23
z: Math.abs(meshBounds.max.z - meshBounds.min.z),
24
};
25
26
if (lengthRatios) {
27
lengthRatios = [
28
lengthRatios[0] / lengthMeshBounds.x,
29
lengthRatios[1] / lengthMeshBounds.y,
30
lengthRatios[2] / lengthMeshBounds.z,
31
];
32
} else {
33
lengthRatios = [
34
lengthMeshBounds.x,
35
lengthMeshBounds.y,
36
lengthMeshBounds.z,
37
];
38
}
39
40
meshes.push(mesh);
41
if (meshes.length == store.length) {
42
addModels();
43
}
44
},
45
(xhr) => {
46
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
47
},
48
(error) => {
49
console.log("An error happened");
50
}
51
);
52
}
53
54
function addModels() {
55
// Select smallest ratio in order to contain the models within the scene
56
const minRation = Math.min(lengthRatios);
57
58
for (let i = 0; i < meshes.length; i++) {
59
// Use smallest ratio to scale the model
60
meshes[i].scale.set(minRation, minRation, minRation);
61
62
// position the model/mesh
63
meshes[i].position.set(points[i]);
64
65
// add it to the scene
66
scene.add(meshes[i]);
67
}
68
}
69
}
70
Advertisement
Answer
You should create a bounding box around each model.
JavaScript
1
31
31
1
//Creating the actual bounding boxes
2
mesh1Bounds = new THREE.Box3().setFromObject( model1 );
3
mesh2Bounds = new THREE.Box3().setFromObject( model2 );
4
5
// Calculate side lengths of model1
6
let lengthMesh1Bounds = {
7
x: Math.abs(mesh1Bounds.max.x - mesh1Bounds.min.x),
8
y: Math.abs(mesh1Bounds.max.y - mesh1Bounds.min.y),
9
z: Math.abs(mesh1Bounds.max.z - mesh1Bounds.min.z),
10
};
11
12
// Calculate side lengths of model2
13
let lengthMesh2Bounds = {
14
x: Math.abs(mesh2Bounds.max.x - mesh2Bounds.min.x),
15
y: Math.abs(mesh2Bounds.max.y - mesh2Bounds.min.y),
16
z: Math.abs(mesh2Bounds.max.z - mesh2Bounds.min.z),
17
};
18
19
// Calculate length ratios
20
let lengthRatios = [
21
(lengthMesh1Bounds.x / lengthMesh2Bounds.x),
22
(lengthMesh1Bounds.y / lengthMesh2Bounds.y),
23
(lengthMesh1Bounds.z / lengthMesh2Bounds.z),
24
];
25
26
// Select smallest ratio in order to contain the models within the scene
27
let minRatio = Math.min(lengthRatios);
28
29
// Use smallest ratio to scale the model
30
model.scale.set(minRatio, minRatio, minRatio);
31