今天继续学习Three.js,完成一个小案例,目标:学会导入GLTF(3D模型)
废话不多说,几行代码,现在开始!
初始化环境
新建html文件,并添加相机、场景、轨道控制器、渲染器,这个不会添加的,可以看看我前面的文章,很简单的。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>案例-小火车</title>
<script type="importmap">
{
"imports":{
"three":"./node_modules/three/build/three.module.js",
"three/addons/":"./node_modules/three/examples/jsm/"
}
}
</script>
</head>
<body>
<style>
* {
margin: 0;
padding: 0;
}
</style>
<script type="module">
import * as THREE from 'three';
// 引入轨道控制器
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
// 创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xbfe3dd);
// 相机
const camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 100);
// 相机位置
camera.position.set(5, 2, 8);
// 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true }); //抗锯齿
// 设置渲染画布大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染画布插入到body中
document.body.appendChild(renderer.domElement); //renderer.domElement为渲染画布元素
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0.5, 0);
controls.update();
// 添加阻尼效果(惯性)
controls.enableDamping = true;
// 渲染
function animate() {
renderer.render(scene, camera);
controls.update();
requestAnimationFrame(animate)
}
animate();
</script>
</body>
</html>
添加3D模型
html
const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('./node_modules/three/examples/jsm/libs/draco/')
loader.setDRACOLoader(dracoLoader)
loader.load('./static/img/LittlestTokyo.glb', function (gltf) {
const model = gltf.scene;
model.position.set(1, 1, 0);
model.scale.set(0.01, 0.01, 0.01);
scene.add(model);
animate();
});
此时的效果:
为什么会是一坨黑色的呢,因为我们没有给场景加上光源,就像是日常没有太阳,我们加上一个环境光:
html
//创建光源
// 环境光
const light = new THREE.AmbientLight(0xffffff);
scene.add(light);
此时,这个3D模型已经可以被看见了:
使用 AnimationMixer动画混合器
使用 AnimationMixer动画混合器,让3D模型的小火车动起来,这里小火车运动,是模型上已经有的,所以说three.js很大部分,还是要靠建模的!建模太耗费精力,还是让专业的建模师去做吧。
model是3D模型,gltf.animations[0]
是模型的组件(小火车),每个模型都可以由很多的组件。
html
let mixer;
const clock = new THREE.Clock();
loader.load('./static/img/LittlestTokyo.glb', function (gltf) {
...
mixer = new THREE.AnimationMixer(model);
mixer.clipAction(gltf.animations[0]).play();
...
});
// 渲染
function animate() {
...
const delta = clock.getDelta();
mixer.update(delta);
...
}
效果:
其实除了场景、相机外,也就几行代码。
完整代码
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>案例-小火车</title>
<script type="importmap">
{
"imports":{
"three":"./node_modules/three/build/three.module.js",
"three/addons/":"./node_modules/three/examples/jsm/"
}
}
</script>
</head>
<body>
<style>
* {
margin: 0;
padding: 0;
}
</style>
<script type="module">
import * as THREE from 'three';
// 引入轨道控制器
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
// 创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xbfe3dd);
//创建光源
// 环境光
const light = new THREE.AmbientLight(0xffffff);
scene.add(light);
// 相机
const camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 100);
// 相机位置
camera.position.set(5, 2, 8);
// 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true }); //抗锯齿
// 设置渲染画布大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染画布插入到body中
document.body.appendChild(renderer.domElement); //renderer.domElement为渲染画布元素
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0.5, 0);
controls.update();
// 添加阻尼效果(惯性)
controls.enableDamping = true;
// GLTFLoader 加载GLB模型
const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('./node_modules/three/examples/jsm/libs/draco/')
loader.setDRACOLoader(dracoLoader)
loader.load('./static/img/LittlestTokyo.glb', function (gltf) {
const model = gltf.scene;
model.position.set(1, 1, 0);
model.scale.set(0.01, 0.01, 0.01);
scene.add(model);
mixer = new THREE.AnimationMixer(model);
mixer.clipAction(gltf.animations[0]).play();
animate();
});
// 让小火车动起来
let mixer;
const clock = new THREE.Clock();
// 渲染
function animate() {
renderer.render(scene, camera);
controls.update();
const delta = clock.getDelta();
mixer.update(delta);
requestAnimationFrame(animate)
}
// animate();
</script>
</body>
</html>