vue中使用three.js——加载显示模型

4,806 阅读2分钟

一 引入three.js

npm install --save three
npm install --save three-obj-mtl-loader
npm install --save three-orbit-controls

二 使用加载显示模型

1 在组件中引入

import * as THREE from 'three'
import {sRGBEncoding} from 'three'
//此处加载gltf模型,故使用GLFTLoader
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
//其他模型加载器
import {OBJLoader,MTLLoader} from 'three-obj-mtl-loader'

2 定义一个div

<div id="container"></div>

3 模型文件

模型文件内容如图所示:

image.png

textures文件(模型材质)内容如图所示:

image.png

将模型文件整体(scene.bin、scene.gltf、textures文件夹)放置到public文件夹中

4 加载模型(此处模型名为scene.gltf)

定义加载方法loadObj

loadObj(){
  let loader = new GLTFLoader();
  loader.load("./scene.gltf", (gltf)=>{
    let mesh = gltf.scene.children[0];
    mesh.scale.set(300,300,300);
    // 获得包围盒得min和max
    const box = new THREE.Box3().setFromObject(gltf.scene.children[0]);
    // 返回包围盒的中心点
    const center = box.getCenter(new THREE.Vector3());
    //调整模型位置(使其尽量居中显示)
    mesh.position.x += mesh.position.x - center.x;
    mesh.position.y += mesh.position.y - center.y;
    mesh.position.z += mesh.position.z - center.z;
    // 将模型引入three
    this.scene.add(mesh);
  });
  this.scene.add(loader);
},

5 初始化

定义初始化方法init

init(){
  let container = document.getElementById('container');
  // 创建场景
  this.scene = new THREE.Scene();
  //环境光
  let ambient = new THREE.AmbientLight(0xFFFFFF,0.3);
  this.scene.add(ambient);
  //半球光源
  let light = new THREE.HemisphereLight();
  this.scene.add(light);
  // //平行光
  let  directionLight = new THREE.DirectionalLight(0xFFFFFF,0.8 * Math.PI);
  directionLight.position.set(2,2,2);
  this.scene.add(directionLight);
  // // 创建相机
  let width = window.innerWidth; //窗口宽度
  let height = window.innerHeight; //窗口高度
  //创建相机对象
  this.camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 4000 );
  this.camera.position.set(400,300,0); //设置相机位置
  //创建渲染器
  this.renderer = new THREE.WebGLRenderer({antialias: true});
  //是否使用物理上正确的光照模式
  this.renderer.physicallyCorrectLights = true;
  //three.js色彩空间转换
  this.renderer.outputEncoding = sRGBEncoding;
  this.renderer.setPixelRatio( window.devicePixelRatio );
  this.renderer.setSize(width, height);//设置渲染区域尺寸
  this.renderer.setClearColor(0xccccccc);
  //创建控制器,可根据实际情况选择合适的控制器
  this.controls=new MapControls(this.camera,this.renderer.domElement);
  // true为启动阻尼(惯性) 需要进行update
  // an animation loop is required when either damping or auto-rotation are enabled
  // this.controls.enableDamping = true; 
  //阻尼(惯性)参数
  // this.controls.dampingFactor = 0.05;
  //true,摄像机将在屏幕空间内平移。 否则,摄像机将在与摄像机向上方向垂直的平面中平移。默认值为false。
  this.controls.screenSpacePanning = false;
  //能够将相机向内移动多少
  this.controls.minDistance = 100;
  //能够将相机向外移动多少
  this.controls.maxDistance = 1000;
  //能垂直旋转的角度下限
  this.controls.maxPolarAngle = Math.PI / 2;
  this.controls.update();
  let childs = container.childNodes;
  if (container.childNodes.length > 0) {
    container.removeChild(childs[0]);
    container.appendChild(this.renderer.domElement);
  } else {
    container.appendChild(this.renderer.domElement);
  }
  //官方提供的快速搭建three.js的交互UI,使用时需要引入
  //引入:import { GUI } from 'three/examples/jsm/libs/dat.gui.module.js';
  // const gui = new GUI();
  // gui.add( this.controls, 'screenSpacePanning' );
  //添加窗口监听事件(resize-onresize即窗口或框架被重新调整大小)
  window.addEventListener('resize', this.onWindowResize);
  },
//窗口监听函数
onWindowResize() {
  this.camera.aspect = window.innerWidth / window.innerHeight;
  this.camera.updateProjectionMatrix();
  this.renderer.setSize(window.innerWidth, window.innerHeight);
},

6 渲染(动画循环/渲染循环)

animate () {
  //再次调用animate方法实现刷新
  requestAnimationFrame(this.animate);
  //开启阻尼时需要update
  // this.controls.update();
  this.render();
},
render(){
  this.renderer.render(this.scene, this.camera);
},

三 效果预览

image.png