threejs-gltf-loading

Carrega modelos glTF/GLB no three.js r187 e executa suas animações: GLTFLoader, decodificadores DRACO, Meshopt e KTX2, transições suaves do AnimationMixer e clones do SkeletonUtils. Use quando um modelo está invisível ou minúsculo, arquivos de decodificação retornam 404, animações nunca são reproduzidas ou clones compartilham um único esqueleto. Não é para configuração de cena (`threejs-scene-setup`) ou iluminação (`threejs-materials-lighting`).

O que é threejs-gltf-loading?

Este skill do three.js lida com o carregamento de modelos `.gltf` / `.glb`, incluindo geometria comprimida (DRACO, Meshopt) e texturas (KTX2), além de reproduzir clipes de animação. Ele é focado na versão **r187** e fornece padrões robustos para inspecionar, carregar, animar e depurar modelos 3D. O skill é essencial quando um modelo não aparece, está muito pequeno, arquivos de decodificação retornam 404 ou animações não funcionam. As plataformas suportadas incluem o ecossistema three.js. O fluxo de trabalho começa com a inspeção do arquivo usando `gltf-transform`, seguida pelo carregamento com `GLTFLoader`, anexação de decodificadores apropriados e uso de `AnimationMixer` para animações. Ele também lida com problemas comuns como clones que compartilham o mesmo esqueleto (usando `SkeletonUtils.clone`) e escala incorreta. Para projetos existentes, o skill mantém a versão fixa do three.js, a menos que o usuário solicite uma atualização. O skill não substitui habilidades de configuração de cena ou iluminação, sendo específico para carregamento e animação de modelos glTF.

Funciona com~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 Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Carregamento glTF no three.js

Carrega modelos .gltf / .glb, incluindo geometria comprimida (DRACO, Meshopt) e texturas (KTX2), e reproduz seus clipes de animação. Os padrões são direcionados à r187; um projeto existente mantém sua versão fixa, a menos que o usuário solicite uma atualização. glTF é o formato padrão de tempo de execução: OBJ não tem grafo de cena nem animação, e FBX é pesado de analisar em um navegador.

Quando usar

  • Importar um modelo ou personagem, inspecionar sua hierarquia de nós, reproduzir ou fazer transição entre clipes, gerar várias cópias de um inimigo animado, ou corrigir um modelo que não aparece.
  • Os arquivos são .gltf / .glb, ou o código importa GLTFLoader, DRACOLoader ou KTX2Loader de three/addons/loaders/....
  • Não é para o renderizador, câmera e loop (threejs-scene-setup), iluminação e materiais do modelo (threejs-materials-lighting), ou configurações de modelagem e exportação em uma ferramenta DCC.

Fluxo de trabalho

  1. Inspecione o arquivo antes de escrever o código do carregador quando gltf-transform estiver disponível: npx @gltf-transform/cli inspect model.glb lista malhas, extensões (por exemplo KHR_draco_mesh_compression, EXT_meshopt_compression, KHR_texture_basisu), clipes e tamanhos de textura. Cada extensão de compressão listada precisa que seu decodificador seja anexado.
  2. Carregue com GLTFLoader (loadAsync em código assíncrono). O resultado tem gltf.scene, a raiz Object3D, e gltf.animations, um AnimationClip[].
  3. Adicione gltf.scene e enquadre-o. Unidades glTF são metros; registre nomes e limites para encontrar as partes que o código irá controlar.
  4. Um AnimationMixer por raiz animada, ações a partir de mixer.clipAction(clip), e mixer.update(segundos) a cada quadro.
  5. Anexe decodificadores para as extensões encontradas no passo 1. Desde a r185, DRACOLoader e KTX2Loader encontram seus arquivos de decodificação incluídos sem a necessidade de um caminho.
  6. Verifique com Verificar.

Padrões

1. Carregar e enquadrar um 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('tamanho (m):', box.getSize(new THREE.Vector3()).toArray());
console.log('clipes:', gltf.animations.map((c) => c.name));

2. Reproduzir um clipe

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, não milissegundos
  renderer.render(scene, camera);
});

3. Transição suave entre clipes

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 e limpa uma transição antiga
  current.crossFadeTo(next, duration, false);
  current = next;
}

4. Geometria e 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)) // compilação WASM apenas para glTF (r185+)
  .setKTX2Loader(new KTX2Loader().detectSupport(renderer))             // precisa do renderizador
  .setMeshoptDecoder(MeshoptDecoder);
// Compartilhe este único carregador para todos os modelos para que decodificadores e workers sejam criados uma vez.

Em versões anteriores à r185, ou quando o host não serve os arquivos incluídos, copie examples/jsm/libs/draco/ e libs/basis/ do three instalado e passe essas pastas para setDecoderPath / setTranscoderPath.

5. Encontrar uma parte nomeada

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

6. Reduzir um modelo sem perder as partes que o código precisa

# Compressão Meshopt, texturas WebP com no máximo 1024 px, manter nós nomeados e a hierarquia.
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 achata a hierarquia e une malhas, incluindo as nomeadas, por padrão. Isso reduz chamadas de desenho, mas o código que procura por Wheel_FL ou anima um nó de porta então não encontra nada. Mantenha as duas flags acima para qualquer modelo que o código acesse. A saída precisa de setMeshoptDecoder (Padrão 4).

Verificar

  1. Verificação do arquivo: npx @gltf-transform/cli validate model.glb para cada arquivo novo ou alterado; corrija os erros relatados antes de depurar o código do carregador.
  2. Compilação: npm run build (ou npx tsc --noEmit) passa.
  3. Sonda em tempo de execução: exponha scene e o mixer em window (Object.assign(window, { scene, mixer })). Passe esta expressão para page.evaluate do Playwright como uma string, para que ela seja executada na página e não no Node (o script de teste em threejs-scene-setup funciona), ou peça ao usuário para colá-la no console do navegador com await na frente e relatar a saída:
(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 };
})();

Espere uma contagem de malhas diferente de zero e mixerAdvanced: true, depois verifique uma captura de tela para escala e orientação.

Armadilhas

  • Modelo carrega mas nada aparece → Materiais PBR sem luz ou ambiente (veja threejs-materials-lighting), ou a escala está errada por 100 (exportação em centímetros). Registre a caixa delimitadora do Padrão 1.
  • gltf é indefinido fora do callback → load é assíncrono. Use loadAsync, ou atribua referências compartilhadas dentro do callback.
  • Animação nunca se move → mixer.update não é chamado a cada quadro, recebe milissegundos, ou play() nunca foi chamado.
  • Erro 404 para arquivos draco_* ou basis_*, ou um erro de decodificação → os arquivos do decodificador não estão sendo servidos, ou vêm de outra versão do three.js. Sirva as cópias do three instalado e aponte o carregador para elas.
  • setKTX2Loader deve ser chamado antes de carregar texturas KTX2 ou setMeshoptDecoder deve ser chamado antes de carregar arquivos comprimidos → o arquivo usa KHR_texture_basisu ou compressão meshopt; anexe o decodificador (Padrão 4).
  • .hasFeature() foi chamado antes do backend ser inicializado → KTX2Loader.detectSupport foi executado em um WebGPURenderer antes de await renderer.init() terminar.
  • Adicionar o mesmo modelo duas vezes o move → um Object3D tem um único pai. Clone-o e use SkeletonUtils.clone para malhas com skin (veja a referência).
  • Clones animam juntos, ou apenas um se move → uma .clone() simples compartilha o esqueleto; use SkeletonUtils.clone e um mixer separado para cada clone.
  • Partes nomeadas desaparecem após gltf-transform optimize → o achatamento e junção padrão as mesclaram. Execute novamente com --flatten false --join-named false.
  • Deslocamentos enrijecidos competem com o controle em tempo de execução → exportadores podem enrijecer escala ou rotação em nós filhos. Primeiro, despeje nomes e transformações locais; re-parente uma parte sob um novo Object3D para um pivô limpo, ou peça uma reexportação com transformações aplicadas.

Referências

  • Leia references/loaders-and-animation.md para uma barra de progresso do LoadingManager entre vários carregadores, gerando muitos inimigos animados com SkeletonUtils.clone, detalhes de looping e mesclagem do AnimationAction, notas sobre hospedagem de decodificadores e listas de verificação para exportadores para entregar a um artista.

Habilidades relacionadas

  • threejs-scene-setup: renderizador, câmera e loop.
  • threejs-materials-lighting: iluminação e ambiente para que modelos PBR pareçam corretos.
  • create-game-assets: briefing, obtenção e verificação dos próprios ativos 3D.
  • fps-shooter: um gênero 3D que se baseia nestas habilidades.

Notas de versão

Última verificação: 2026-11-11 contra three r187 (npm [email protected], publicado em 2026-10-30) e @gltf-transform/cli 4.5.1.

  • r185: DRACOLoader e KTX2Loader usam por padrão suas pastas de decodificação incluídas; DRACO_GLTF_CONFIG adicionado; DRACOLoader.setDecoderConfig() obsoleto (remoção planejada para r194). r183: suporte a KHR_meshopt_compression ao lado de EXT_meshopt_compression. r181: KTX2Loader.detectSupportAsync() obsoleto.
  • Otimização optimize do gltf-transform 4.5.1: valores padrão: --compress meshopt, --flatten true, --join true, --join-named true, --simplify true, --texture-compress auto. --texture-compress ktx2 precisa do comando ktx do KTX-Software 4.4.0 ou mais recente no PATH.
  • Fontes: Notas de lançamento da r187, r187 DRACOLoader.js, r187 GLTFLoader.js, CLI 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.

Habilidades Relacionadas