@certe/atmos-assets
v0.8.8
Published
glTF 2.0 / GLB asset pipeline for the Atmos Engine
Maintainers
Readme
📦 @certe/atmos-assets
glTF 2.0 / GLB asset pipeline for the Atmos Engine. Parses binary glTF into a CPU-only ModelAsset, then instantiates it as a live GameObject hierarchy with GPU resources — meshes, materials, textures, skeletal skins, and animation clips.
🔑 Two-Stage Pipeline
ArrayBuffer → parseGltfModel() → ModelAsset (CPU-only)
↓
instantiateModel() → GameObject (GPU-ready)Stage 1 is thread-safe (no GPU access). Stage 2 uploads to the GPU and creates engine components.
🚀 Quick Start
import { parseGltfModel, instantiateModel } from '@certe/atmos-assets';
// Load a .glb file
const buffer = await fetch('/models/character.glb').then(r => r.arrayBuffer());
// Parse (CPU-only, no GPU needed)
const asset = parseGltfModel(buffer, 'Character');
// Instantiate into the scene
const root = await instantiateModel(asset, { renderSystem });
scene.add(root);For skinned meshes, instantiateModel automatically creates SkinnedMeshRenderer and AnimationMixer components, and auto-plays the first animation clip.
📖 API Overview
Core Functions
| Function | Description |
|---|---|
| parseGltfModel(buffer, name?) | Parse GLB → ModelAsset |
| instantiateModel(asset, options) | Create GameObject tree with GPU resources |
ModelAsset Contents
| Field | Description |
|---|---|
| meshes: ModelMesh[] | Geometry data (32B standard or 52B skinned stride) |
| materials: ModelMaterial[] | PBR params + texture indices |
| textures: ModelTexture[] | CPU-side image bytes |
| rootNodes: ModelNode[] | Scene hierarchy with TRS |
| skins: ModelSkin[] | Joint hierarchies + inverse bind matrices |
| animations: ModelAnimation[] | Keyframe tracks per joint |
Skinned Mesh Support
When a mesh has JOINTS_0 and WEIGHTS_0 attributes:
- Vertices are interleaved into a 52-byte format: position(3) + normal(3) + uv(2) + joints(u8×4) + weights(f32×4)
ModelMesh.skinned = trueandskinIndexlinks to the skin datainstantiateModel()creates aSkinnedMeshRendererwith a bone buffer, and anAnimationMixerpre-loaded with all clips
Low-Level Parser API
For advanced use cases:
import { parseGlb, readAccessor, readBufferView } from '@certe/atmos-assets';
const doc = parseGlb(buffer); // { json, buffers }
const positions = readAccessor(doc, 0); // Float32Array
const imageBytes = readBufferView(doc, 2); // Uint8Array| Function | Description |
|---|---|
| parseGlb(buffer) | Parse GLB container |
| parseGltfJson(json, buffers?) | Wrap standalone .gltf |
| readAccessor(doc, index) | Read typed array from accessor |
| readBufferView(doc, index) | Read raw bytes from buffer view |
| extractSkins(doc) | Extract skin data (joints, IBM, rest pose) |
| extractAnimations(doc) | Extract animation clips |
🧠 Design Notes
- Custom parser (~350 lines) — no external glTF dependencies
- Interleaves vertex attributes into engine-native stride formats
- Supports indexed meshes with both
Uint16ArrayandUint32Arrayindices - PBR metallic-roughness workflow with embedded texture extraction
- Node hierarchy preserved with TRS decomposition
📁 Structure
packages/assets/src/
index.ts # Public API
types.ts # ModelAsset, ModelMesh, ModelSkin, etc.
gltf-parser.ts # GLB/glTF binary parser
gltf-mesh.ts # Mesh extraction + vertex interleaving
gltf-material.ts # Material extraction
gltf-scene.ts # Scene graph assembly
gltf-skin.ts # Skin extraction (joints, IBM, rest pose)
gltf-animation.ts # Animation channel extraction
model-instantiate.ts # GPU instantiation + component creation🔗 Dependencies
@certe/atmos-core— GameObject, Component, Transform@certe/atmos-math— Vec3, Mat4, Quat@certe/atmos-renderer— Mesh, Material, MeshRenderer, SkinnedMeshRenderer, textures@certe/atmos-animation— Skeleton, AnimationClip, AnimationMixer
