
使用Three.js加载FBX模型,并播放动画
概述
Three.js是一个JavaScript库,主要用于创建和显示3D图形。它基于WebGL,一个在浏览器中实现3D效果的API。通过使用Three.js,开发者可以在网页上创建和展示3D场景、模型和动画。它提供了丰富的3D显示功能,包括场景管理、几何体、光照、材质、纹理映射等。使用Three.js可以简化3D程序的实现过程,使得在浏览器中创建和展示3D内容更加容易。
场景构建
使用Three.js构建3D场景的过程可以分为以下几个步骤:
创建场景:首先需要创建一个场景对象,这个对象将包含所有的3D对象。可以使用Three.js提供的Scene类来创建一个场景。
创建相机:相机用于定义观察场景的视角。Three.js提供了多种类型的相机,如PerspectiveCamera和OrthographicCamera。根据需要选择适合的相机类型,并将其添加到场景中。
创建渲染器:渲染器负责将场景渲染到屏幕上。使用Three.js提供的WebGLRenderer类创建一个渲染器实例,并将其添加到HTML页面中。
添加光源:光源影响物体表面的光照效果。使用Three.js提供的光源类创建光源对象,并将其添加到场景中。
渲染循环:最后,需要创建一个渲染循环,不断更新场景、相机和光源的状态,并调用渲染器进行绘制。在渲染循环中,可以监听用户输入、处理动画和物理计算等。
以上是使用Three.js构建3D场景的基本过程。通过不断调整和优化场景中的对象、材质、光源等属性,可以创建出丰富多彩的3D效果。
基本代码示例
// 创建场景
scene = new THREE.Scene();
scene.background = new THREE.Color(0xa0a0a0);
// 创建相机
camera = new THREE.PerspectiveCamera(angle, SCREEN_WIDTH / SCREEN_HEIGHT, nearest, farthest);
camera.position.set(20, 20, 30);
// 环境光
scene.add(new THREE.AmbientLight(4210752, 3));
// 平行光
var light = new THREE.DirectionalLight(16777215, 1);
light.position.set(0, 50, 50);
scene.add(light);
// 创建渲染器
var renderer = new THREE.WebGLRenderer({
antialias: true, // 平滑效果
alpha: true, // canvas背景透明
});
renderer.render(scene, camera);
加载FBX模型
FBX模型是一种3D通用模型文件格式,最早并非由Autodesk开发,但后来被其收购。它支持所有主要的三维数据元素以及二维、音频和视频媒体元素,因此被众多标准建模软件所支持,如3ds Max、Maya、Softimage等。FBX格式可以用于在各种软件间进行模型、材质、动作和摄影机信息的互导,从而发挥这些软件的优势。例如,在3D Studio Max、Maya、Softimage等软件间进行模型、材质、动作和摄影机信息的互导,这样可以方便地在不同的软件中进行协同工作。
要在Three.js中加载FBX模型,你可以使用three.js的FBXLoader类。以下是一个简单的示例代码:
var loader = new THREE.FBXLoader();
loader.load('model.fbx', function (object) {
// 在回调函数中处理加载完成的模型
scene.add(object);
}, undefined, function (error) {
// 处理加载错误
console.error(error);
});
在上面的代码中,首先创建了一个FBXLoader实例,然后使用其load方法加载FBX模型文件。在回调函数中,你可以获取到加载完成的模型对象,并将其添加到场景中。如果加载过程中出现错误,可以在回调函数的错误处理部分输出错误信息。
需要注意的是,FBXLoader支持多种版本的FBX格式,因此在使用时需要确保你的FBX模型文件与加载器版本兼容。另外,加载大型FBX模型可能需要较长时间,因此最好在加载完成后添加适当的加载提示或进度条。
播放动画
在加载模型后,使用AnimationMixer和AnimationAction来控制动画的播放。以下是一个简单的示例代码:
var loader = new THREE.FBXLoader();
loader.load('path/to/model.fbx', function (object) {
// 将模型添加到场景中
scene.add(object);
// 获取模型的动画控制器
var mixer = new THREE.AnimationMixer(object);
var action = mixer.clipAction(object.animations[0]); // 假设模型只有一个动画
// 播放动画
action.play();
}, undefined, function (error) {
// 处理加载错误
console.error(error);
});
除此之外,还要不断更新mixers:
function render() {
window.requestAnimationFrame(()=>{
render()
});
var delta = clock.getDelta();
mixer.update(delta);
controls.update();
renderer.render(scene, camera);
}
暂停、重置动画
要停止Three.js中的动画,你可以使用AnimationMixer的timeScale属性。将timeScale属性设置为0可以暂停动画的播放。如果你想重新开始动画,可以将timeScale属性设置为1。可以使用stopAllAction
方法停止Three.js中的所有动画。这个方法会停止所有与特定AnimationMixer对象关联的动画。
// 停止动画
stop(){
mixer.stopAllAction();
},
// 暂停动画
suspended() {
mixer.timeScale = 0;
},
// 继续播放
continueAnimation() {
mixer.timeScale = 1
}
在VUE中完成这些操作
首先使用NPM或Yarn安装three.js
npm i three
<template>
<div class="three-container">
<div ref="dom" class="three-dom"></div>
</div>
</template>
<style scoped>
* {
margin: 0;
padding: 0;
}
.three-container {
width: 100%;
height: 100%;
overflow: hidden;
}
.three-dom {
width: 100%;
height: 100%;
}
</style>
<script>
import * as THREE from 'three'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
export default {
name: 'ThreeContainer',
data() {
return {
scene: null,
renderer: null,
camera: null,
controls: null,
group: null,
mixers: [],
clock:null
}
},
mounted() {
this.clock = new THREE.Clock();
this.initScene()
},
methods: {
initScene() {
this.scene = new THREE.Scene()
this.scene.background = new THREE.Color(0xa0a0a0);
this.camera = new THREE.PerspectiveCamera(
90,
window.innerWidth / window.innerHeight,
1,
1000
);
this.camera.position.set(20, 20, 30);
// this.scene.add(this.camera)
// 环境光
this.scene.add(new THREE.AmbientLight(4210752, 3));
// 平行光
var light = new THREE.DirectionalLight(16777215, 1);
light.position.set(0, 50, 50);
this.scene.add(light);
// 加载模型
const loader = new FBXLoader()
loader.load('/1.fbx', (fbxObj) => {
fbxObj.scale.set(0.15, 0.15, 0.15)
console.log(fbxObj);
fbxObj.mixer = new THREE.AnimationMixer(fbxObj);
this.mixers.push(fbxObj.mixer)
var AnimationAction = fbxObj.mixer.clipAction(fbxObj.animations[0]);
AnimationAction.play(); //播放动画
this.scene.add(fbxObj)
})
// 添加渲染器
this.renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true, // canvas背景透明
})
this.renderer.setPixelRatio(window.devicePixelRatio)
this.renderer.setSize(window.innerWidth, window.innerHeight)
// this.renderer.setClearColor(0x132c3e)
this.$refs.dom.appendChild(this.renderer.domElement)
// OrbitControls
this.controls = new OrbitControls(this.camera, this.renderer.domElement)
this.controls.target.set(0, 0, 0);
this.animate();
// 监听窗口大小变化
window.addEventListener('resize', this.handleResize)
},
animate() {
requestAnimationFrame(() => {
this.animate()
});
// 创建一个时钟对象Clock
var delta = this.clock.getDelta();
if (this.mixers.length > 0) {
// 更新混合器相关的时间
for (let i = 0; i < this.mixers.length; i++) {
this.mixers[i].update(delta);
}
}
this.controls.update()
this.renderer.render(this.scene, this.camera)
},
handleResize() {
this.camera.aspect = window.innerWidth / window.innerHeight
this.camera.updateProjectionMatrix()
this.renderer.setSize(window.innerWidth, window.innerHeight)
}
}
}
</script>
更好的方案
FBX、 OBJ (Wavefront)和 DAE (Collada)格式仍然是其中最受欢迎的格式,尽管它们都存在阻碍其广泛采用的问题。比如OBJ不支持动画,FBX是属于Autodesk的封闭格式,Collada规范过于复杂,导致大文件难以加载。
然而,最近,一个名为glTF的新成员已成为在网络上交换3D资源的事实上的标准格式。 glTF(GL传输格式),有时被称为 3D中的JPEG,由 Kronos Group创建,他们负责WebGL、OpenGL和一大堆其他图形API。glTF最初于2017年发布,现在是在网络和许多其他领域交换3D资源的最佳格式。它专为在网络上共享模型而设计,因此文件大小尽可能小,并且您的模型将快速加载。
但是,由于glTF相对较新,您最喜欢的应用程序可能还没有导出器。在这种情况下,您可以在使用模型之前将它们转换为glTF。