What it does
await game.modelFiles.load(key, url) fetches a file through the engine's loader, so the loading screen, progress and
retries work as usual, and registers its meshes. game.modelFiles.spawn(key, …) then places a copy with a position, a
size, a yaw, pitch and roll, and a tint, and every copy is another instance in the same draw call. An OBJ's MTL is
fetched from beside it, and a missing one leaves the model grey rather than failing the load.
Every model is fitted to the unit box the other meshes use, so size is its largest dimension in world units, just
as for a primitive; model.size reports the file's own dimensions if you want real-world scale back. A static model is
merged to one mesh per material, so it costs as many draws as it has materials rather than nodes. Each part's vertices
are available too, so a model can feed anything that needs geometry, such as a wireframe outline.
Animated .glb files play straight off the spawned handle. play takes a clip by name or index, loops or plays once
and holds the last frame, scales speed, and crossfades from the current clip over a time you choose, so idle to walk
reads as a transition. play(clip, { at }) starts part-way in, which stops a crowd of the same model marching in
lockstep. Node animation (doors, wheels, mechanical rigs) is applied as ordinary transforms, and skinned characters
are skinned on the CPU, both from one mixer so they stay in step.
Features
- Two formats —
.glband.objwith.mtl, from a URL, a buffer or text you already have. - Instanced copies — load once, spawn many, all in the same draw call.
- A common scale — every model fitted to the unit box, with its own dimensions still reported.
- Materials and textures — base colour, metallic and roughness, normal maps and emissive colour, with embedded textures decoded into the atlas.
- Animation mixer — clips by name or index, looping or one-shot, speed, scrubbing and crossfades.
- Offset starts —
atto start a clip part-way in, for crowds. - Node and skinned animation — skins with up to four joints a vertex, in step with node animation.
- Honest refusals — compressed, quantized, sparse or split files fail with a message naming what was found.
- A pure reader —
parseGlband the animation maths work on their own, for tools or a worker.
Good for
- 3D games with artist-made assets — characters, props and environments from a modelling program.
- Animated characters that walk, idle and run with crossfades between clips.
- Crowds of the same model, staggered so they do not move as one.
- Vehicles and machines whose wheels, doors and turrets are animated nodes in the file.
- Mixing styles, with loaded hero models beside procedural primitives in the same scene.
Make it yours
The pack has no options; each spawn takes its own position, size, rotation and tint, and each handle its own clip,
speed, fade and start time. Two different uses: a racing game that loads one car .glb and spawns a dozen tinted
copies, each playing the file's own wheel animation; and a town scene where eight copies of a walker play the same
Walk clip, each started a fraction of a second later than the last.
A quick look
Load an animated model, then spawn it and crossfade into a walk:
await game.modelFiles.load('robot', 'models/robot.glb');
const h = game.modelFiles.spawn('robot', { size: 3 });
h.play('Walk', { loop: true, fade: 0.25 });
for (let i = 0; i < 8; i++) game.modelFiles.spawn('walker', { x: i * 2, y: 1, size: 2 }).play('Walk', { loop: true, at: i * 0.17 });
Works with
world-3dandrender-3d— the world it spawns into and the renderer that draws its materials.model-3d— models built from data instead of files; the two work side by side.hull-3d— a convex collider for a loaded model underphysics-3d.vector-3d— draws any loaded model as outline edges from its parts' vertices.
Good to know
- Compressed files (Draco or meshopt), quantized attributes, sparse accessors, KTX2 or WebP textures and data outside
the
.glb's own chunk are refused with a clear message; export without them. - Textures are capped at 512 pixels on their longer side in the shared atlas, and an OBJ's texture maps are not loaded, so it wears its diffuse colours.
- Morph targets, a second uv set, occlusion and emissive maps, cameras and lights are ignored.
- Skinning runs on the CPU and re-uploads each frame: correct, but a large crowd of skinned characters will be costly.
- A model is fitted round its centre, so spawn it at half its size above the ground to stand it on the floor.






