I have several models (geometries) And they are all of different size and format

var geometry = new THREE.BoxGeometry( 1, 1, 1 ); var materials = new THREE.MeshBasicMaterial({ color: "red"}) ; var cube = new THREE.Mesh(geometry, materials); scene.add(cube); var topy = 'models/JSON/111.json'; var loader = new THREE.ObjectLoader(); loader.load( topy, function ( obj ) { scene.add( obj ); }); var loader = new THREE.TextureLoader(); var normal = loader.load( 'models/3ds/portalgun/textures/normal.jpg' ); var loader = new THREE.TDSLoader( ); loader.setResourcePath( 'models/3ds/portalgun/textures/' ); loader.load( 'models/3ds/portalgun/portalgun.3ds', function ( object ) { object.traverse( function ( child ) { if ( child instanceof THREE.Mesh ) { child.material.normalMap = normal; } } ); scene.add( object ); } ); var loader = new THREE.ThreeMFLoader(); loader.load( 'models/3MF/Mi-24.3mf', function ( object ) { scene.add( object ); } ); 

I need all models to be the same size and in the same place.

as I have a floor on which in the center models should be displayed

 var floor_gam = new THREE.PlaneBufferGeometry( 2000, 2000 ) ; var floor_rotat = - Math.PI / 2; var mat_standart = new THREE.MeshStandardMaterial( { color: 0x808080, roughness: 0, metalness: 0 } ) ; var object_floor_standart = new THREE.Mesh( floor_gam, mat_standart ); object_floor_standart.rotation.x = floor_rotat ; object_floor_standart.receiveShadow = true; scene.add( object_floor_standart ); 

Who does not know how to do this? I tried

  var center = obj.geometry.boundingSphere.center; controls.target.set( center.x, center.y, center.z ); 

But this does not work with all models and simply fits the camera to the model, but vice versa.

  • Meaning the same height? - prisoner849
  • @ prisoner849 Yes you can and height. Ideally, something like a width: 300px; height: 300px; object-fit: contain; width: 300px; height: 300px; object-fit: contain; only for three.js - zeni1agent 1:19 pm

1 answer 1

Here is the function to fit an object at a given size ( scaleToFit() ). In this case, the maximum size of the duckling on the x axis.

 var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000); camera.position.set(0, 3, 8); var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); var controls = new THREE.OrbitControls(camera, renderer.domElement); scene.add(new THREE.AmbientLight(0xffffff, 1.0)); var sizeBound = new THREE.Vector3(4, 4, 4); var b = new THREE.Mesh(new THREE.BoxBufferGeometry(sizeBound.x, sizeBound.y, sizeBound.z), new THREE.MeshBasicMaterial()); var boxHelper = new THREE.BoxHelper(b); scene.add(boxHelper); var loader = new THREE.GLTFLoader(); loader.load("https://threejs.org/examples/models/gltf/Duck/glTF/Duck.gltf", (gltf) => { scaleToFit(gltf.scene, sizeBound); // умещаем в заданные размеры let b = new THREE.Box3().setFromObject(gltf.scene); gltf.scene.position.sub(b.getCenter()); // центрируем gltf.scene.position.y -= (sizeBound.y - b.getSize().y) * 0.5; // опускаем к "полу" scene.add(gltf.scene); // добавляем в сцену }); function scaleToFit(obj, bound) { let box = new THREE.Box3().setFromObject(obj); let size = new THREE.Vector3(); box.getSize(size); let vScale = new THREE.Vector3().copy(bound).divide(size); let scale = Math.min(vScale.x, Math.min(vScale.y, vScale.z)); obj.scale.setScalar(scale); } renderer.setAnimationLoop(() => { renderer.render(scene, camera) }); 
 body { overflow: hidden; margin: 0; } 
 <script src="https://threejs.org/build/three.min.js"></script> <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script> <script src="https://threejs.org/examples/js/loaders/GLTFLoader.js"></script> 

  • scaleToFit() only works with the GLTF format for me; I tried to adapt it for different formats but failed var loader = new THREE.AWDLoader();loader.load("./models/AWD/simple.awd", (gltf) =>{ scaleToFit(gltf.scene, sizeBound); gltf.scene.position.sub(new THREE.Box3().setFromObject(gltf.scene).getCenter());scene.add(gltf.scene); }); var loader = new THREE.AWDLoader(); loader.load( 'models/AWD/simple.awd', function (trunk ) { scaleToFit(trunk.scene, sizeBound); trunk.scene.position.sub(new THREE.Box3().setFromObject(trunk.scene).getCenter()); scene.add(trunk.scene); }); var loader = new THREE.AWDLoader();loader.load("./models/AWD/simple.awd", (gltf) =>{ scaleToFit(gltf.scene, sizeBound); gltf.scene.position.sub(new THREE.Box3().setFromObject(gltf.scene).getCenter());scene.add(gltf.scene); }); var loader = new THREE.AWDLoader(); loader.load( 'models/AWD/simple.awd', function (trunk ) { scaleToFit(trunk.scene, sizeBound); trunk.scene.position.sub(new THREE.Box3().setFromObject(trunk.scene).getCenter()); scene.add(trunk.scene); }); - zeni1agent 2:49 pm
  • error ncaught TypeError: Cannot read property 'updateMatrixWorld' of undefined - zeni1agent 2:53 pm
  • one
    Different loaders return different objects. The function takes in the first parameter an object inherited from THREE.Object3D() . Therefore, we must look at what you pass to a function — you can pass the mesh, or the entire scene, but you cannot transfer the geometry. - prisoner849
  • one
    Everything seems to have figured out `var loader = new THREE.AWDLoader (); loader.load ('models / AWD / simple.awd', function (trunk) {scaleToFit (trunk, sizeBound); // fit in the given dimensions trunk.position.sub (new THREE.Box3 (). setFromObject (trunk). getCenter ()); // center scene.add (trunk);}); ` - zeni1agent pm
  • one
    @ zeni1agent updated the snippet in response :) - prisoner849