前言
本篇是使用three.js 提供的加载器加载 glTF 模型展示,并进行动作控制。直接使用three.js编程建模比较麻烦,实际开发时的模型会借助一些3D建模工具进行建模,如Blender、C4D、3Dmax。导出的文件再加载到three.js 场景中展示。
实现
添加基本代码
import * as THREE from 'three';
let camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight,1, 10000);
camera.position.y = 300;
let scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0f0 );
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio( window.devicePixelRatio );
renderer.outputEncoding = THREE.sRGBEncoding;
document.body.appendChild(renderer.domElement);
const light1 = new THREE.DirectionalLight( 0xefefff, 1.5 );
light1.position.set( 1, 1, 1 ).normalize();
scene.add( light1 );
const light2 = new THREE.DirectionalLight( 0xFFFFFF, 1.5 );
light2.position.set( - 1, - 1, - 1 ).normalize();
scene.add( light2 );
基本结构和灯光。
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
const loader = new GLTFLoader();
let mixer: THREE.AnimationMixer;
loader.load( 'models/Horse.glb', function ( gltf ) {
mesh = gltf.scene.children[ 0 ];
mesh.scale.set( 1.5, 1.5, 1.5 );
scene.add( mesh );
mixer = new THREE.AnimationMixer( mesh );
mixer.clipAction( gltf.animations[ 0 ] ).setDuration( 1 ).play();
} );
GLTFLoader 是用于 glTF 2.0 资源的加载器。该类文件以JSON(.gltf)格式或二进制(.glb)格式提供数据。一个 glTF 文件可以包含一个或多个场景。包括网格、材质、贴图、动画等等。
AnimationMixer 动画混合器。用于控制场景内对象动画运动。
将 glTF 上的动画(animations) 使用clipAction() 方法生成一个可调用的动画对象(AnimationAction),setDuration 方法为设置单次循环的时间,play() 即播放。
加载的 glTF 模型文件的数据结构如下
function animate() {
requestAnimationFrame( animate );
render();
}
let prevTime = Date.now();
const radius = 600;
let theta = 0;
function render() {
theta += 0.1;
camera.position.x = radius * Math.sin( THREE.MathUtils.degToRad( theta ) );
camera.position.z = radius * Math.cos( THREE.MathUtils.degToRad( theta ) );
camera.lookAt( 0, 150, 0 );
if ( mixer ) {
const time = Date.now();
mixer.update( ( time - prevTime ) * 0.001 );
prevTime = time;
}
renderer.render( scene, camera );
}
animate();
添加旋转动画,camera 在X-Z面上以radius = 600 进行旋转,mixer.update 推进混合器时间并更新动画,这个传入的时间大小会影响动画的播放速率。
添加与模型交互
官网示例没有添加控制器,没法交互,我们修改一下代码,变得可以通过键盘控制模型马的奔跑。
let animation;
loader.load('models/Horse.glb',(model) => {
......
//mixer.clipAction( gltf.animations[ 0 ] ).setDuration( 1 ).play();
animation = mixer.clipAction( gltf.animations[0] );
});
将动画混合器得到的动画调度存到变量中。
const consorl = new OrbitControls(camera, renderer.domElement);
// EVENTS
document.addEventListener( 'keydown', onKeyDown );
document.addEventListener( 'keyup', onKeyUp );
let walk = false;
function onKeyDown(e) {
if (e.code === 'KeyW') {
animation.play();
walk = true;
}
}
function onKeyUp(e) {
if (e.code === 'KeyW') {
walk = false;
}
}
添加轨道控制器和事件监听。
function animate() {
......
// 修改mixer 执行条件
if ( mixer && walk) {
const time = Date.now();
mixer.update( ( time - prevTime ) * 0.001);
prevTime = time;
} else if (mixer) {
mixer.stopAllAction();
}
}
修改动画混合器的执行条件。这样就可以通过按键 W 来控制模型奔跑的动作。
关于glTF 模型
glTF 是一个非常全面的格式,几乎支持所有的常见功能,支持颜色、动画、CSG、细节网格工作、纹理、相机、光线、相对定位等重要功能。
借用 juejin.cn/post/701692… 一张表格来描述glTF 格式的模型在3D 模型格式中的优点:
- glTF的目标是作为一个中转格式,而不是另一个新的3D数据格式.
- 使用JSON来描述场景结构,可以方便地被应用程序分析处理。
- glTF导出格式有两种后缀格式:.gltf 和 .glb。 .gltf 格式为JSON 数据储存,.glb 是压缩为二进制文件进行储存,占比空间会更小。
结语
通过本篇示例我们可以了解到three.js 是如何加载glTF 模型,将模型展示在3D场景中并通过交互播放模型中的动画。
参考官网示例:threejs.org/examples/#w…
本篇以上代码也已放到了github上:github.com/wenxuan12/3… ,可供做印证参考。