Vai al contenuto
animorio
EN
Tutti gli oggetti 3D

La nuvola col bastone

NuovoGLBThree.js1 ottobre 2026

Una nuvola bianca con gli occhi incassati, le gambe sottili e un bastone di legno. Respira, si guarda intorno, sorride e saluta, batte il bastone; e la faccia la guidi tu, con dieci pose.

Cosa c’è dentro

Mesh
80.027 vertici, 159.988 triangoli
Scheletro
16 ossa
Animazione
vita, 10 secondi, in loop. Respira (le palle della nuvola si gonfiano a onda), batte le ciglia, guarda il bastone e poi dall’altra parte, sorride e saluta saltellando, batte due colpi col bastone, alza gli occhi al cielo. Si chiude su sé stessa.
Pose della faccia
  • occhi_sinistra guarda a sinistra
  • occhi_destra guarda a destra
  • occhi_su guarda in alto
  • occhi_giu guarda in basso
  • chiudi chiude gli occhi
  • sorriso occhi ad arco, felici
  • stupore occhi più grandi
  • respiro_alto si gonfia la palla in alto
  • respiro_spalle si gonfiano le spalle
  • respiro_basso si gonfiano le palle in basso
Materiali
Nuvola (bianco opaco, appena caldo), Occhi (marrone scuro lucido), Riflesso (bianco che si accende da solo), Arti (cioccolato satinato), Legno (noce chiaro)
Peso
1,4 MB

Come si usa

Carica il GLB, fai partire l’animazione e, se vuoi, guida tu le pose della faccia: ogni chiave di forma ha un nome e un peso da 0 a 1.

three.js
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';

// il modello: compresso con meshopt, serve il suo decoder
const loader = new GLTFLoader().setMeshoptDecoder(MeshoptDecoder);
const gltf = await loader.loadAsync('nuvola-col-bastone.glb');
scene.add(gltf.scene);

// l'animazione "vita": 10 secondi, in loop
const mixer = new THREE.AnimationMixer(gltf.scene);
mixer.clipAction(gltf.animations[0]).play();

// le pose della faccia: un peso da 0 a 1 per ogni chiave di forma
const faccia = [];
gltf.scene.traverse((m) => {
  if (m.morphTargetDictionary && 'sorriso' in m.morphTargetDictionary) faccia.push(m);
});
const posa = (nome, peso) => faccia.forEach((m) => {
  m.morphTargetInfluences[m.morphTargetDictionary[nome]] = peso;
});

// la luce: uno studio bianco, e il bianco resta bianco
renderer.toneMapping = THREE.NoToneMapping;
scene.environment = new THREE.PMREMGenerator(renderer)
  .fromScene(new RoomEnvironment(), 0.04).texture;

const clock = new THREE.Clock();
renderer.setAnimationLoop(() => {
  mixer.update(clock.getDelta());
  posa('occhi_destra', 0.6);   // dopo il mixer: vince sulla clip
  renderer.render(scene, camera);
});

Com’è fatto

  • Dal disegno alla forma

    Il contorno dell’illustrazione è fatto di sette archi: ognuno è stato misurato al decimo di pixel e diventa una sfera. Le sfere si uniscono con un raccordo che cambia con la profondità: vivo sul bordo, così le punte fra una palla e l’altra restano nette, e sempre più morbido verso la faccia, dove le pieghe svaniscono come nel disegno.

  • Liscia davvero

    Ogni parte è una superficie matematica: la mesh nasce su una griglia fitta e poi ogni vertice viene riportato esattamente sulla superficie, con la normale presa dalla superficie stessa. Per il web la mesh è stata ridotta dove è piatta e tenuta fitta dove curva, poi riportata di nuovo sulla superficie: 80 mila vertici, e nessuna faccetta.

  • La faccia

    Gli occhi stanno in un incavo con il bordo svasato, che prende la luce sotto e l’ombra sopra. Per le pose l’incavo si sposta insieme all’occhio tenendo la sua profondità rispetto alla pelle, così la nuvola resta esatta anche mentre guarda, chiude gli occhi o sorride.

  • Lo scheletro

    Sedici ossa: il corpo, le gambe con i piedi piantati a terra (cinematica inversa, già cotta nell’animazione), il braccio che saluta, il bastone con la mano agganciata. La coreografia è scritta come funzioni del tempo e campionata a 24 fotogrammi al secondo.

LibreriaLe animazioni, con il codice