首页 > 建站教程 > 前端框架 >  threejs 自适应obj模型正文

threejs 自适应obj模型

我爱模板网在做一个模型展示的站点时,客户上传的模型太大了,导致显示出了问题:

threejs


通过图片可以看到两个问题:

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);


最终效果

threejs


全部代码:

// 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文件解释

2、Three.js加载.obj模型文件