npx skills add ...
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill threejs-gltf-loading
Load glTF/GLB models in three.js with GLTFLoader and play their skinned animations with AnimationMixer, including DRACO/Meshopt-compressed meshes and KTX2 textures. Use when importing 3D models into three.js — when the user mentions glTF, GLB, GLTFLoader, AnimationMixer, animation clips, DRACOLoader, or "load a 3D model". For scene/camera/renderer setup use threejs-scene-setup; for materials and lights use threejs-materials-lighting.
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill threejs-gltf-loading
Load .gltf/.glb models and play their animations in three.js, including
compressed geometry (DRACO/Meshopt) and textures (KTX2). Patterns target
r184; preserve an existing project's pinned release unless migration is requested.
AnimationMixer..gltf/.glb, or code imports GLTFLoader /
DRACOLoader / KTX2Loader from three/addons/loaders/....When not to use: creating the renderer/camera/loop → threejs-scene-setup.
Tuning surface look, lights, or shadows on the loaded model →
threejs-materials-lighting. Authoring/exporting the model itself (Blender) is out
of scope; prefer glTF over OBJ/FBX for runtime.
GLTFLoader. loader.load(url, onLoad, onProgress, onError). The
result gltf has gltf.scene (the Object3D root), gltf.animations
(AnimationClip[]), gltf.cameras, and gltf.asset.gltf.scene to your scene and frame it. Inspect the hierarchy with
traverse / getObjectByName to find the parts you'll control.AnimationMixer. One mixer per animated root;
mixer.clipAction(clip).play(); advance with mixer.update(delta) every frame.DRACOLoader (and/or KTX2Loader +
Meshopt) so DRACO meshes and KTX2 textures load; point the decoders at their
files.gltf.animations, and confirm
the model is visible (right scale, lit) and the clip actually plays.scene.environment (see
threejs-materials-lighting), and check scale — glTF is in metres, so a 0.01-scaled
asset is tiny.load is async → gltf only exists inside the callback; declare mixer/refs
outside and assign them in the callback, or use await loader.loadAsync(url).mixer.update(delta) each frame, or you
passed milliseconds instead of seconds (use clock.getDelta()), or you forgot
action.play().setDecoderPath/setTranscoderPath must point at files matching your
three.js version.AnimationMixer per animated root and
create all actions from it; don't make a new mixer per clip.Object3D to give it a clean
pivot rather than fighting baked offsets.loadAsync
LoadingManager progress bar, reusing models with SkeletonUtils.clone, and
exporter guidance (apply transforms, one clean root), read
references/loaders-and-animation.md.threejs-scene-setup — the renderer, camera, and loop this model renders into.threejs-materials-lighting — lighting/environment so PBR models look right.fps-shooter — a 3D genre that composes three.js skills.