一 引入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 模型文件
模型文件内容如图所示:
textures文件(模型材质)内容如图所示:
将模型文件整体(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);
},