Three.js: complex animations
On three.js you can use complex animations regulating weights. In this code example I show a character with 3 animations: one for walking, one for moving the head and one for moving the arms.1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Test Three.js</title> 6 <style> 7 body { 8 background-color: #888; 9 } 10 </style> 11 </head> 12 <body> 13 <script type="importmap"> 14 { 15 "imports": { 16 "three": "./three.module.js", 17 "three/addons/": "./addons/" 18 } 19 } 20 </script> 21 <script type="module"> 22 import * as THREE from './three.module.js'; 23 import { GLTFLoader } from './addons/GLTFLoader.js'; 24 import { OrbitControls } from './addons/OrbitControls.js'; 25 import Stats from './libs/stats.module.js'; 26 import { GUI } from './libs/lil-gui.module.min.js'; 27 28 let stats = new Stats(); 29 document.body.appendChild(stats.dom); 30 31 const panel = new GUI({ width: 300 }); 32 const panelc1 = panel.addFolder("Character"); 33 let panelsettings = { 34 'walking_loop': 1.0, 35 'look_loop': 1.0, 36 'moveArms_loop': 1.0 37 } 38 39 function setWeight(animName) { 40 clips.forEach((clip) => { if (clip.name === animName) { mixer.clipAction(clip).setEffectiveWeight(panelsettings[animName]); } }); 41 } 42 43 panelc1.add(panelsettings, "walking_loop", 0.0, 1.0, 0.01).onChange(function () { setWeight('walking_loop'); }); 44 panelc1.add(panelsettings, "look_loop", 0.0, 1.0, 0.01).onChange(function () { setWeight('look_loop'); }); 45 panelc1.add(panelsettings, "moveArms_loop", 0.0, 1.0, 0.01).onChange(function () { setWeight('moveArms_loop'); }); 46 47 const renderer = new THREE.WebGLRenderer(); 48 renderer.setPixelRatio(window.devicePixelRatio); 49 renderer.setSize(window.innerWidth, window.innerHeight); 50 document.body.appendChild(renderer.domElement); 51 52 const scene = new THREE.Scene(); 53 scene.background = new THREE.Color(0x888888); 54 55 const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); 56 camera.position.set(0, 0, 1); 57 camera.lookAt(0, 0, 0); 58 scene.add(camera); 59 60 const light = new THREE.PointLight(0xffffff, 10.0); 61 camera.add(light); 62 63 const controls = new OrbitControls(camera, renderer.domElement); 64 controls.target.set(0, 0.5, 0); 65 controls.update(); 66 controls.enablePan = false; 67 controls.enableDamping = true; 68 69 const loader = new GLTFLoader(); 70 let mixer = null; 71 let clips = []; 72 loader.load( 73 "omino-01.en.gltf", 74 function (gltf) { 75 // Resource has been loaded. 76 77 mixer = new THREE.AnimationMixer(gltf.scene); 78 gltf.animations.forEach((clip) => { 79 clips.push(clip); 80 console.log("Clip name: " + clip.name); 81 mixer.clipAction(clip).play(); 82 }); 83 84 scene.add(gltf.scene); 85 }, 86 function (xhr) { 87 // Resource is loading 88 console.log("Loading... " + (xhr.loaded / xhr.total * 100) + "%"); 89 }, 90 function (error) { 91 // Error during loading 92 console.error("Error during the asset loading: " + error); 93 } 94 ); 95 96 let clock = new THREE.Clock(); 97 98 function animate() { 99 const delta = clock.getDelta(); 100 requestAnimationFrame(animate); 101 if (stats) 102 stats.update(); 103 controls.update(); 104 if (mixer) 105 mixer.update(delta); 106 renderer.render(scene, camera); 107 } 108 animate(); 109 </script> 110 </body> 111 </html>
Click here to see the running script.
At line 40 a
setEffectiveWeight()
function is used to indicate how much weight needs to be used to
the current animations. Weights are regulated acting on the configuration panel's sliders.
2023
Dec, 26
Dec, 26