我爱模板网在做一个模型展示的站点时,客户上传的模型太大了,导致显示出了问题:
通过图片可以看到两个问题:
1、PerspectiveCamera第四个参数即far设置的小了,导致穿模了:
camera = new THREE.PerspectiveCamera(60, threeDom.clientWidth/threeDom.clientHeight, 0.1, 1000)
改成
camera = new THREE.PerspectiveCamera(60, threeDom.clientWidth/threeDom.clientHeight, 0.1, 10000)
2、此时模型不穿模了,但是还是太大了,虽然可以通过缩放来查看全部,但是用户体验太差,如果可以计算出模型的实际大小,根据实际大小,设置相机的z轴,让obj物体原点,还好,找到了方法:
// 根据模型尺寸设置相机的 const bBox = new THREE.Box3().setFromObject(obj); const size = bBox.getSize(new THREE.Vector3()); const height = size.y; const dist = height / (2 * Math.tan(camera.fov * Math.PI / 360)); const pos = scene.position; // fudge factor so the object doesn't take up the whole view camera.position.set(pos.x, pos.y, dist * 1.5); camera.lookAt(pos);
最终效果
全部代码:
// objUrl是obj的地址,mtlUrl是材质的地址 function init(objUrl, mtlUrl) { if(!objUrl && !mtlUrl) return // threeDom 为div的id const threeDom = document.getElementById('threeDom') scene = new THREE.Scene() // 创建相机 camera = new THREE.PerspectiveCamera(60, threeDom.clientWidth/threeDom.clientHeight, 0.1, 10000) camera.position.set(100,100,100) // 添加环境光 ambientLight = new THREE.AmbientLight(0xffffff, .9) scene.add(ambientLight) // 添加点光源 directionLight = new THREE.DirectionalLight(0xffffff, .8) directionLight.position.set(400, 200, 300) scene.add(directionLight) // 创建渲染器 renderer = new THREE.WebGLRenderer({antialias: true}) renderer.setClearColor(new THREE.Color('#000000')) renderer.setClearAlpha(0.0) renderer.setSize(threeDom.clientWidth, threeDom.clientHeight) renderer.domElement.addEventListener('click', onClick, false) threeDom.appendChild(renderer.domElement) // 控制器 controls = new OrbitControls(camera, renderer.domElement) controls.enableDamping = true controls.enablePan = true controls.enableZoom = true controls.autoRotate = true controls.autoRotateSpeed = 9 controls.update() // 加载材质和模型 const mtlLoader = new MTLLoader() width.value = 0 // mtlLoader.setPath( path + '/' ); mtlLoader.load(mtlUrl, (materials) => { materials.preload() const objLoader = new OBJLoader() objLoader.setMaterials(materials) // objLoader.setPath( path + '/' ) objLoader.load(objUrl, // 加载成功回调 (obj) => { width.value = 100 scene.add(obj); // 加载后的一些编辑操作 obj.children[0].scale.set(1,1,1) // 网格模型缩放 obj.children[0].geometry.center() // 网格模型的几何体居中 // obj.children[0].material.color.set(0xff0000);//设置材质颜色 setTimeout(() =>{ showLoading.value = false }, 500) // 根据模型尺寸设置相机的 const bBox = new THREE.Box3().setFromObject(obj); const size = bBox.getSize(new THREE.Vector3()); const height = size.y; const dist = height / (2 * Math.tan(camera.fov * Math.PI / 360)); const pos = scene.position; // fudge factor so the object doesn't take up the whole view camera.position.set(pos.x, pos.y, dist * 1.5); camera.lookAt(pos); }, // 加载过程中回调 (xhr) => { width.value = (xhr.loaded/xhr.total)*100 console.log((xhr.loaded/xhr.total)*100 + '% loaded') }, // 加载失败回调 (error) => { width.value = 100 console.log('加载失败:', error) } ) }) // 渲染场景 const render = () => { renderer.render(scene, camera) controls.update() requestAnimationFrame(render) } render() }
更多:
1、mtl文件解释