vue2使用three加载obj模型及其材质

第一次搞three.js,网上找的加载obj的方法都试了一下,发现总是报错,不报错就是模型看不到,后来老老实实去官网读文档,原来是大多文章没有提及模型太大或者偏移的情况,建模的师傅给的模型中心位置可能和原点偏移过大,就像相对定位和绝对定位,相机看着相对的位置,模型其实“远在天边”,因此便有了这篇文章,以供参考。

<template>
  <div class="app-container">
    <el-row :gutter="20" align="middle">
      <div style="margin-bottom:10px">
        <el-button @click="cameraResert()">复位</el-button>
      </div>
      <div id="objContaier" ref="objContaier" class="objContaier"></div>
    </el-row>
  </div>
</template>

<style scoped>
.objContaier{width: 100%;height: calc(100vh - 200px);background-color: black;}
</style>

<script>
import * as THREE from 'three';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
import {OBJLoader} from 'three/examples/jsm/loaders/OBJLoader';
import {MTLLoader} from 'three/examples/jsm/loaders/MTLLoader'
export default {
  data() {
    return {
      scene:undefined,
      light:undefined,
      camera:undefined,
      controls:undefined,
      renderer:undefined,
      dragControls:undefined,
      object:[],

      conWidth:undefined,
      conHeight:undefined,
    }
  },
  mounted() {
    this.conWidth = this.$refs.objContaier.offsetWidth
    this.conHeight = this.$refs.objContaier.offsetHeight
    this.init()
    this.animate()
  },
  methods:{
    init() {
      // 创建场景
      this.scene = new THREE.Scene()
      this.scene.background = new THREE.Color('#202124')
      // 渲染
      const container = document.getElementById('objContaier')
      this.renderer = new THREE.WebGLRenderer({antialias: true, alpha: true})
      this.renderer.outputEncoding = THREE.sRGBEncoding;
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setSize(this.conWidth, this.conHeight);
      container.appendChild(this.renderer.domElement)
      // 相机
      this.camera = new THREE.PerspectiveCamera(45, this.conWidth / this.conHeight, 0.1, 1000)
      this.camera.position.set(0, 10, 20)
      this.camera.lookAt(new THREE.Vector3(0, 0, 0))
      // 轨道控制
      this.controls = new OrbitControls(this.camera, this.renderer.domElement)
      this.controls.target.set(0, 5, 0);
      this.controls.update();
      // 光源
      const skyColor = 0xFFFFFF;
      const groundColor = 0xB97A20; 
      const intensity = 1;
      const light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
      this.scene.add(light);
      // 直射光
      const dcolor = 0xFFFFFF;
      const dintensity = 1;
      const dlight = new THREE.DirectionalLight(dcolor, dintensity);
      dlight.position.set(0, 10, 0);
      dlight.target.position.set(-5, 0, 0);
      this.scene.add(dlight);
      this.scene.add(dlight.target);
      // 环境光
      const ambient = new THREE.AmbientLight(0x404040, 3)
      this.scene.add(ambient)
      // 材质模型加载器,模型在服务器上
      const mtlLoader = new MTLLoader()
      const objLoader = new OBJLoader();
      mtlLoader.load('/模型链接.mtl', (mtl) => {
        mtl.preload()
        for (const material of Object.values(mtl.materials)) {
          material.side = THREE.DoubleSide;
        }
        objLoader.setMaterials(mtl)
        objLoader.load('/模型链接.obj', (root) => {
          this.root = root
          const box = new THREE.Box3().setFromObject(root);
          const boxSize = box.getSize(new THREE.Vector3()).length();
          const boxCenter = box.getCenter(new THREE.Vector3());
          this.objBoxSize = boxSize
          this.objBoxCenter = boxCenter
          this.cameraResert()
          // 辅助坐标线
          // var axesHelper = new THREE.AxesHelper(15);
          // this.scene.add(axesHelper);
        });
      })
    },
    // 刷新渲染
    animate() {
      this.renderer.render(this.scene, this.camera);
      this.requestId = requestAnimationFrame(this.animate);
    },
    // 相机位置调整
    frameArea(sizeToFitOnScreen, boxSize, boxCenter) {
      const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
      const halfFovY = THREE.MathUtils.degToRad(this.camera.fov * .5);
      const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
      const direction = (new THREE.Vector3())
        .subVectors(this.camera.position, boxCenter)
        .multiply(new THREE.Vector3(1, 0, 1))
        .normalize();
      this.camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
      this.camera.near = boxSize / 100;
      this.camera.far = boxSize * 100;
      this.camera.updateProjectionMatrix();
      this.camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);

    },
    // 相机位置重置
    cameraResert(){
      if(this.objBoxCenter){
        this.frameArea(this.objBoxSize * 1.2, this.objBoxSize, this.objBoxCenter)
        this.controls.maxDistance = this.objBoxSize * 10;
        this.controls.target.copy(this.objBoxCenter);
        this.controls.update();
        this.scene.add(this.root);
        this.renderer.render(this.scene, this.camera);
      }
    }
  }
}
</script>

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值