CommunityProgramación y desarrollogithub.com

threejs-gltf-loading

Carga modelos glTF/GLB en three.js r187 y reproduce sus animaciones: GLTFLoader, decodificadores DRACO, Meshopt y KTX2, transiciones de AnimationMixer y clones de SkeletonUtils. Útil cuando un modelo es invisible o pequeño, los archivos del decodificador devuelven 404, las animaciones nunca se reproducen o los clones comparten un mismo esqueleto. No aplica para configuración de escena (`threejs-scene-setup`) ni iluminación (`threejs-materials-lighting`).

¿Qué es threejs-gltf-loading?

Este skill especializado en three.js permite cargar modelos `.gltf` / `.glb` en la versión r187, incluyendo geometría comprimida (DRACO, Meshopt) y texturas KTX2, además de reproducir y mezclar clips de animación. Es ideal cuando un modelo no se muestra visible, aparece muy pequeño, los archivos del decodificador generan errores 404, las animaciones no se ejecutan o se necesitan múltiples clones de un personaje animado sin conflictos de esqueleto. La habilidad proporciona patrones claros para inspeccionar el archivo antes de escribir código de carga (usando `@gltf-transform/cli`), adjuntar los decodificadores adecuados según las extensiones detectadas, y gestionar animaciones con transiciones suaves (cross-fade). También incluye una sección de verificación con pasos para validar el modelo, la compilación y el comportamiento en tiempo de ejecución, así como una lista detallada de problemas comunes y sus soluciones. Está pensada para entornos web con three.js y puede aplicarse junto con otras habilidades como `threejs-scene-setup` para el bucle de renderizado, `threejs-materials-lighting` para iluminación PBR, y `create-game-assets` para la creación de activos 3D. Es compatible con las herramientas de línea de comandos `gltf-transform` y se ha verificado contra three.js r187 y `@gltf-transform/cli` 4.5.1.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mext-ai/elearning-agent-skills/tree/HEAD/third-party/gamedev/threejs-gltf-loading

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Carga de glTF en three.js

Carga modelos .gltf / .glb, incluyendo geometría comprimida (DRACO, Meshopt) y texturas (KTX2), y reproduce sus clips de animación. Los patrones están orientados a r187; un proyecto existente mantiene su versión fija a menos que el usuario solicite una actualización. glTF es el formato de ejecución por defecto: OBJ no tiene grafo de escena ni animación, y FBX es pesado de analizar en un navegador.

Cuándo usar

  • Importar un modelo o personaje, inspeccionar su jerarquía de nodos, reproducir o mezclar clips, generar muchas copias de un enemigo animado, o corregir un modelo que no aparece.
  • Los archivos son .gltf / .glb, o el código importa GLTFLoader, DRACOLoader o KTX2Loader desde three/addons/loaders/....
  • No aplica para el renderizador, cámara y bucle (threejs-scene-setup), la iluminación y materiales del modelo (threejs-materials-lighting), ni para ajustes de modelado y exportación en una herramienta DCC.

Flujo de trabajo

  1. Inspecciona el archivo antes de escribir código de carga cuando gltf-transform esté disponible: npx @gltf-transform/cli inspect model.glb lista mallas, extensiones (por ejemplo KHR_draco_mesh_compression, EXT_meshopt_compression, KHR_texture_basisu), clips y tamaños de textura. Cada extensión de compresión listada necesita su decodificador adjunto.
  2. Carga con GLTFLoader (loadAsync en código asíncrono). El resultado tiene gltf.scene, la raíz Object3D, y gltf.animations, un AnimationClip[].
  3. Añade gltf.scene y encuádralo. Las unidades de glTF son metros; registra nombres y límites para encontrar las partes que el código controlará.
  4. Un AnimationMixer por raíz animada, acciones desde mixer.clipAction(clip), y mixer.update(segundos) en cada fotograma.
  5. Adjunta decodificadores para las extensiones encontradas en el paso 1. Desde r185, DRACOLoader y KTX2Loader encuentran sus archivos de decodificador incluidos sin necesidad de una ruta.
  6. Verifica con Verificar.

Patrones

1. Cargar y encuadrar un modelo

import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const gltf = await new GLTFLoader().loadAsync('assets/robot.glb');
const root = gltf.scene;
scene.add(root);

const box = new THREE.Box3().setFromObject(root);
console.log('tamaño (m):', box.getSize(new THREE.Vector3()).toArray());
console.log('clips:', gltf.animations.map((c) => c.name));

2. Reproducir un clip

const timer = new THREE.Timer();            // THREE.Clock está obsoleto desde r183
const mixer = new THREE.AnimationMixer(gltf.scene);
const run = THREE.AnimationClip.findByName(gltf.animations, 'Run') ?? gltf.animations[0];
mixer.clipAction(run).play();

renderer.setAnimationLoop(() => {
  timer.update();
  mixer.update(timer.getDelta());           // segundos, no milisegundos
  renderer.render(scene, camera);
});

3. Transición suave entre clips

const actions = Object.fromEntries(gltf.animations.map((c) => [c.name, mixer.clipAction(c)]));
let current = actions.Idle;
current.play();

function transitionTo(name, duration = 0.3) {
  const next = actions[name];
  if (!next || next === current) return;
  next.reset().play();                      // rebobina y limpia una transición anterior
  current.crossFadeTo(next, duration, false);
  current = next;
}

4. Geometría y texturas comprimidas

import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader, DRACO_GLTF_CONFIG } from 'three/addons/loaders/DRACOLoader.js';
import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';
import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';

const loader = new GLTFLoader()
  .setDRACOLoader(new DRACOLoader().setDecoderPath(DRACO_GLTF_CONFIG)) // compilación WASM solo para glTF (r185+)
  .setKTX2Loader(new KTX2Loader().detectSupport(renderer))             // necesita el renderizador
  .setMeshoptDecoder(MeshoptDecoder);
// Comparte este único loader para todos los modelos para que los decodificadores y workers se creen una vez.

En versiones anteriores a r185, o cuando el servidor no sirve los archivos incluidos, copia examples/jsm/libs/draco/ y libs/basis/ del paquete three instalado y pasa esas carpetas a setDecoderPath / setTranscoderPath.

5. Encontrar una parte nombrada

const wheels = [];
gltf.scene.traverse((node) => {
  if (node.name.startsWith('Wheel')) wheels.push(node);
});
// En el bucle: for (const w of wheels) w.rotation.x += dt * 4;

6. Reducir un modelo sin perder las partes que el código necesita

# Compresión Meshopt, texturas WebP de máximo 1024 px, conserva nodos nombrados y la jerarquía.
npx @gltf-transform/cli optimize in.glb out.glb \
  --compress meshopt --texture-compress webp --texture-size 1024 \
  --flatten false --join-named false
npx @gltf-transform/cli validate out.glb

optimize aplana la jerarquía y une mallas, incluidas las nombradas, por defecto. Eso reduce las llamadas de dibujo, pero el código que busca Wheel_FL o anima un nodo de puerta entonces no encuentra nada. Mantén las dos banderas anteriores para cualquier modelo al que el código acceda. La salida necesita setMeshoptDecoder (Patrón 4).

Verificar

  1. Verificación de archivo: npx @gltf-transform/cli validate model.glb para cada archivo nuevo o modificado; corrige los errores reportados antes de depurar el código de carga.
  2. Compilación: npm run build (o npx tsc --noEmit) pasa.
  3. Prueba en tiempo de ejecución: expón scene y el mixer en window (Object.assign(window, { scene, mixer })). Pasa esta expresión a page.evaluate de Playwright como una cadena, para que se ejecute en la página y no en Node (el script de prueba rápida en threejs-scene-setup funciona), o pide al usuario que la pegue en la consola del navegador con await al inicio y que reporte la salida:
(async () => {
  const before = window.mixer?.time ?? null;
  await new Promise((r) => setTimeout(r, 500));
  const meshes = [];
  window.scene.traverse((o) => { if (o.isMesh) meshes.push(o.name || o.type); });
  return { meshes: meshes.length, mixerAdvanced: before !== null && window.mixer.time > before };
})();

Espera un conteo de mallas distinto de cero y mixerAdvanced: true, luego verifica una captura de pantalla para la escala y orientación.

Problemas comunes

  • El modelo se carga pero no se muestra → Materiales PBR sin luz ni entorno (consulta threejs-materials-lighting), o la escala está desviada por 100 (exportación en centímetros). Registra la caja delimitadora del Patrón 1.
  • gltf no está definido fuera del callback → load es asíncrono. Usa loadAsync, o asigna referencias compartidas dentro del callback.
  • La animación nunca se mueve → mixer.update no se llama en cada fotograma, se le pasan milisegundos, o nunca se llamó a play().
  • Error 404 para archivos draco_* o basis_*, o un error de decodificación → los archivos del decodificador no se sirven, o provienen de otra versión de three.js. Sirve las copias desde el paquete three instalado y apunta el loader hacia ellas.
  • setKTX2Loader must be called before loading KTX2 textures o setMeshoptDecoder must be called before loading compressed files → el archivo usa KHR_texture_basisu o compresión meshopt; adjunta el decodificador (Patrón 4).
  • .hasFeature() called before the backend is initialized → KTX2Loader.detectSupport se ejecutó en un WebGPURenderer antes de que await renderer.init() terminara.
  • Agregar el mismo modelo dos veces lo mueve → un Object3D tiene un solo padre. Clónalo, y usa SkeletonUtils.clone para mallas con esqueleto (consulta la referencia).
  • Los clones se animan juntos, o solo uno se mueve → un .clone() simple comparte el esqueleto; usa SkeletonUtils.clone y un mixer separado por cada clon.
  • Las partes nombradas desaparecen después de gltf-transform optimize → el aplanamiento y unión por defecto las fusionaron. Vuelve a ejecutar con --flatten false --join-named false.
  • Los offsets incorporados entran en conflicto con el control en tiempo de ejecución → los exportadores pueden incorporar escala o rotación en nodos hijos. Primero vuelca nombres y transformaciones locales; re-parenta una parte bajo un nuevo Object3D para un pivote limpio, o pide una reexportación con transformaciones aplicadas.

Referencias

  • Lee references/loaders-and-animation.md para una barra de progreso con LoadingManager a través de múltiples loaders, generación de muchos enemigos animados con SkeletonUtils.clone, detalles de bucle y mezcla de AnimationAction, notas sobre alojamiento de decodificadores, y listas de verificación para exportadores que puedas entregar a un artista.

Habilidades relacionadas

  • threejs-scene-setup: renderizador, cámara y bucle.
  • threejs-materials-lighting: iluminación y entorno para que los modelos PBR luzcan correctamente.
  • create-game-assets: briefing, obtención y verificación de los propios activos 3D.
  • fps-shooter: un género 3D que se basa en estas habilidades.

Notas de versión

Última verificación: 2026-11-11 contra three r187 (npm [email protected], publicado 2026-10-30) y @gltf-transform/cli 4.5.1.

  • r185: DRACOLoader y KTX2Loader usan por defecto sus carpetas de decodificador incluidas; se añadió DRACO_GLTF_CONFIG; DRACOLoader.setDecoderConfig() obsoleto (eliminación prevista para r194). r183: Se soporta KHR_meshopt_compression junto con EXT_meshopt_compression. r181: KTX2Loader.detectSupportAsync() obsoleto.
  • gltf-transform 4.5.1 valores por defecto de optimize: --compress meshopt, --flatten true, --join true, --join-named true, --simplify true, --texture-compress auto. --texture-compress ktx2 necesita el comando ktx de KTX-Software 4.4.0 o más reciente en PATH.
  • Fuentes: Notas de la versión r187, r187 DRACOLoader.js, r187 GLTFLoader.js, CLI de glTF Transform, npx @gltf-transform/cli optimize --help.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills relacionados