Three.js: animazioni complesse
Su three.js si possono usare delle animazioni complesse regolando i pesi. In questo mio esempio di codice mostro un personaggio che ha 3 animazioni: una per camminare, una per muovere la testa e una per muovere le braccia.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 pannello = new GUI({ width: 300 }); 32 const pannelloc1 = pannello.addFolder("Personaggio"); 33 let impostazioniPannello = { 34 'camminata_loop': 1.0, 35 'guardaInAlto1_loop': 1.0, 36 'muoviLeBraccia1_loop': 1.0 37 } 38 39 function settaPeso(nomeAnim) { 40 clips.forEach((clip) => { if (clip.name === nomeAnim) { mixer.clipAction(clip).setEffectiveWeight(impostazioniPannello[nomeAnim]); } }); 41 } 42 43 pannelloc1.add(impostazioniPannello, "camminata_loop", 0.0, 1.0, 0.01).onChange(function () { settaPeso('camminata_loop'); }); 44 pannelloc1.add(impostazioniPannello, "guardaInAlto1_loop", 0.0, 1.0, 0.01).onChange(function () { settaPeso('guardaInAlto1_loop'); }); 45 pannelloc1.add(impostazioniPannello, "muoviLeBraccia1_loop", 0.0, 1.0, 0.01).onChange(function () { settaPeso('muoviLeBraccia1_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 luce = new THREE.PointLight(0xffffff, 10.0); 61 camera.add(luce); 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.gltf", 74 function (gltf) { 75 // La risorsa e' stata caricata. 76 77 mixer = new THREE.AnimationMixer(gltf.scene); 78 gltf.animations.forEach((clip) => { 79 clips.push(clip); 80 console.log("Nome clip: " + clip.name); 81 mixer.clipAction(clip).play(); 82 }); 83 84 scene.add(gltf.scene); 85 }, 86 function (xhr) { 87 // La risorsa e' in fase di caricamento. 88 console.log("Caricamento in corso... " + (xhr.loaded / xhr.total * 100) + "%"); 89 }, 90 function (errore) { 91 // Errore durante il caricamento della risorsa. 92 console.error("Errore durante il caricamento dell'omino: " + errore); 93 } 94 ); 95 96 let clock = new THREE.Clock(); 97 98 function anima() { 99 const delta = clock.getDelta(); 100 requestAnimationFrame(anima); 101 if (stats) 102 stats.update(); 103 controls.update(); 104 if (mixer) 105 mixer.update(delta); 106 renderer.render(scene, camera); 107 } 108 anima(); 109 </script> 110 </body> 111 </html>
Clicca qui per vedere lo script in esecuzione.
Alla riga n.40 viene utilizzata la funzione
setEffectiveWeight()
che indica a three.js quanto peso
dare alle animazioni correnti. I pesi vengono dati agendo sugli slider del pannello di configurazione.
2023
26 dic
26 dic