three.js 引入3D模型
一、依赖安装
依赖安装只需要这一个
# three.js
npm install --save three
或者cnd导入
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@<version>/build/three.module.js",
"three/addons/": "https://unpkg.com/three@<version>/examples/jsm/"
}
}
</script>
addons为附加组件,按需引入
二、封装
准备一个js文件进行各个所需内容的封装,如下
import * as THREE from 'three'//导入three.js核心库
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' //导入轨道控制器
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'//导入GLTF模型加载器
class MODEL3D {
constructor(selector) {
this.container = document.querySelector(selector)//获取容器
this.scene
this.camera
this.renderer
this.controls
this.init() //初始化
this.animate()//循环函数
}
init() {
// 初始化场景
this.initScene()
// 初始化辅助轴
// this.initAxesHelper()
// 初始化网格辅助线
// this.initGridHelper()
// 初始化灯光
this.initLight()
// 初始化相机
this.initCamera()
// 初始化渲染器
this.initRender()
// 初始化轨道控制器
this.initMesh()
this.initControls()
// 监听场景大小改变,重新渲染尺寸
window.addEventListener('resize', this.onWindowResize.bind(this))
}
initMesh() {
this.addGLTFModel()
}
initScene() {
this.scene = new THREE.Scene()
this.scene.background = new THREE.Color(0xa0a0a0)
}
initAxesHelper() {
const axesHelper = new THREE.AxesHelper(1)
this.scene.add(axesHelper)
}
initGridHelper() {
const size = 10;
const divisions = 10;
const gridHelper = new THREE.GridHelper(size, divisions);
const radius = 10;
const jsectors = 16;
const jrings = 8;
const jringsdivisions = 64;
const jhelper = new THREE.PolarGridHelper(radius, jsectors, jrings, jringsdivisions);
this.scene.add(jhelper);
this.scene.add(gridHelper);
}
initLight() {
const light = new THREE.AmbientLight(0x404040); // 柔和的白光
this.scene.add(light);
}
initCamera() {
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100)
this.camera.position.set(1, 0, 1)
}
initRender() {
this.renderer = new THREE.WebGLRenderer({ antialias: true })//设置抗锯齿
//设置屏幕像素比
this.renderer.setPixelRatio(window.devicePixelRatio)
//渲染的尺寸大小
this.renderer.setSize(window.innerWidth, window.innerHeight)
// 添加到容器
this.container.appendChild(this.renderer.domElement)
}
render() {
this.renderer.outputColorSpace = THREE.SRGBColorSpace
this.renderer.shadowMap.enabled = true;
this.renderer.hadowMapEnabled = true;
this.renderer.render(this.scene, this.camera)
}
animate() {
this.renderer.setAnimationLoop(this.render.bind(this))
}
initControls() {
this.controls = new OrbitControls(this.camera, this.renderer.domElement)
this.controls.enablePan = false
this.controls.minPolarAngle = Math.PI/2
this.controls.maxPolarAngle = Math.PI/2
}
onWindowResize() {
//页面大小变化时重渲染
this.camera.aspect = window.innerWidth / window.innerHeight
this.camera.updateProjectionMatrix() //更新矩阵,将3d内容投射到2d画面上转换
this.renderer.setSize(window.innerWidth, window.innerHeight)
}
addGLTFModel() {
return new Promise((resolve, reject) => {
const loader = new GLTFLoader()
loader.load('/pikaqu.glb', (gltf) => {
console.log(gltf); //模型对象
gltf.scene.castShadow = true;
gltf.scene.rotation.set(0, -Math.PI / 4, 0)
gltf.scene.position.set(0, -Math.PI/4, 0)
//模型纯黑问题处理
gltf.scene.traverse(function (child) {
if (child.isMesh) {
child.frustumCulled = true;
//模型阴影
child.castShadow = true;
//模型自发光
child.material.emissive = child.material.color;
child.material.emissiveMap = child.material.map;
}
})
this.scene.add(gltf.scene)
// 模型自转
var that = this
function animate() {
requestAnimationFrame( animate );
gltf.scene.rotation.y += 0.01;
that.renderer.render(that.scene, that.camera)
}
animate();
})
})
}
}
export default MODEL3D
仅需要注意模型格式问题,有两点
- 模型加载器不同:不同的模型加载器用于加载不同格式的模型,并不是通用的;Addons中有多种不同格式的模型加载器,选取合适的用;
- 模型不受光影响:注意确认模型材质,有些格式模型如gltf、glb不会反射光,并且没有自发光,加载出来的模型很黑,可以给他做一个自发光的处理;
三、使用封装
<template>
<div id="scene">
</div>
</template>
<script setup>
import {onMounted } from 'vue'
import motor3d from './motor3d';
onMounted(()=>{
new motor3d('#scene')
})
</script>
<style scoped></style>
id选择器直接挂上就可以