15.6. glTF 2.0 loader (dasGLTF): GLB/.gltf parse, accessor decode, node hierarchy, skinning and keyframe animation into a backend-neutral scene
dasGLTF loads glTF 2.0 models — .glb (binary),
.gltf (JSON), external or base64-embedded buffers — into a backend-neutral scene,
with no new native code (it builds on json_boost, base64, fio, stbimage and
math).
The backend-neutral core parses, decodes accessors, builds the node hierarchy, and evaluates skinning and keyframe animation with no OpenGL or Vulkan dependency — usable headless for tooling or a future renderer. Require it with:
require gltf/gltf_boost
An opt-in OpenGL adapter (gltf/gltf_gl + gltf/gltf_pbr, requiring dasOpenGL /
dasGlsl) maps a loaded scene to GL buffers and renders it with a Cook-Torrance
metallic-roughness PBR shader; it is documented with the OpenGL examples, not here.
15.6.1. The scene model
load_gltf returns a
GltfScene, which aggregates the meshes, materials,
textures, images, samplers, nodes, skins and animations of the default scene. Geometry is
decoded to a fixed GltfVertex layout (position, normal,
tangent, two UV sets, color, and joints/weights decoded to float4), so interleaved,
normalized and integer-lane attributes need no downstream handling.
require gltf/gltf_boost
var scene <- load_gltf("model.glb")
update_world_transforms(scene) // fill GltfNode.world from the hierarchy
let (mn, mx) = gltf_scene_bounds(scene) // world-space AABB for auto-framing
15.6.2. Animation and skinning
evaluate_animation samples
one animation at a time t (STEP / LINEAR / CUBICSPLINE), writes the result into each target
node’s TRS, and refreshes the world transforms.
gltf_joint_matrix returns the
per-joint skinning matrix (jointNode.world * inverseBind[j]) that deforms skinned geometry.
Morph targets and saving/export are out of scope.
15.6.2.1. Enumerations
- GltfAlphaMode
enum GltfAlphaMode
- GltfInterp
enum GltfInterp
- GltfPath
enum GltfPath
- GltfPrimitiveMode
enum GltfPrimitiveMode
15.6.2.2. Structures
- GltfVertex
struct GltfVertex
- GltfPrimitive
struct GltfPrimitive
- GltfMesh
struct GltfMesh
- GltfMaterial
struct GltfMaterial
- GltfImage
struct GltfImage
- GltfSampler
struct GltfSampler
- GltfTexture
struct GltfTexture
- GltfNode
struct GltfNode
- GltfSkin
struct GltfSkin
- GltfAnimSampler
struct GltfAnimSampler
- GltfAnimChannel
struct GltfAnimChannel
- GltfAnimation
struct GltfAnimation
- GltfScene
struct GltfScene
15.6.2.3. Loading
- load_gltf(path: string ): GltfScene
Load a glTF 2.0 file (.gltf, .glb, or base64-embedded .gltf) into a backend-agnostic GltfScene. Returns an empty scene on failure.
- Arguments:
path : string
- load_gltf_from_memory(bytes: array<uint8>; baseDir: string = "" ): GltfScene
Load a glTF 2.0 document (.gltf JSON, .glb binary, or base64-embedded .gltf) from an in-memory byte buffer. baseDir resolves external buffer/image URIs (pass “” for a self-contained .glb). Returns an empty scene on failure.
- Arguments:
bytes : array<uint8>
baseDir : string
15.6.2.4. Scene, skinning and animation
- evaluate_animation(scene: GltfScene; animation: int; t: float )
Evaluate animation animation at time t (seconds): sample each channel and write the result into its target node’s TRS, then recompose those nodes’ local matrices and refresh every world transform. Nodes given by an explicit matrix are never animation targets (glTF forbids it), so only touched (hence TRS-defined) nodes are recomposed — matrix-defined nodes keep their parsed local.
- Arguments:
scene : GltfScene
animation : int
t : float
- gltf_joint_matrix(scene: GltfScene; skinIndex: int; j: int ): float4x4
Skinning matrix for joint slot j of skin skinIndex: jointNode.world * inverseBind[j]. This is the palette the GPU multiplies each skinned vertex by; the mesh node’s own transform is intentionally omitted (glTF renders skinned geometry directly in skin space). Returns identity for an invalid index.
- Arguments:
scene : GltfScene
skinIndex : int
j : int
- gltf_scene_bounds(scene: GltfScene ): tuple<float3;float3>
World-space axis-aligned bounds (min, max) over every mesh vertex, using each node’s world transform. Returns (0, 0) for a scene with no drawable vertices. Handy for auto-framing a camera.
- Arguments:
scene : GltfScene
- update_world_transforms(scene: GltfScene )
Recompute every node’s world transform by walking the hierarchy from the scene roots (world = parent.world * local).
- Arguments:
scene : GltfScene
15.6.2.5. Accessor byte readers
- gltf_comp_size(compType: int ): int64
Byte size of one accessor component for the given glTF componentType.
- Arguments:
compType : int
- gltf_rd_f32(b: array<uint8>|array<uint8>#; o: int64 ): float
def gltf_rd_f32 (b: array<uint8>|array<uint8>#; o: int64) : float
- Arguments:
b : option<array<uint8>| array<uint8>#>
o : int64
- gltf_rd_i16(b: array<uint8>|array<uint8>#; o: int64 ): int
def gltf_rd_i16 (b: array<uint8>|array<uint8>#; o: int64) : int
- Arguments:
b : option<array<uint8>| array<uint8>#>
o : int64
- gltf_rd_i8(b: array<uint8>|array<uint8>#; o: int64 ): int
def gltf_rd_i8 (b: array<uint8>|array<uint8>#; o: int64) : int
- Arguments:
b : option<array<uint8>| array<uint8>#>
o : int64
- gltf_rd_u16(b: array<uint8>|array<uint8>#; o: int64 ): uint
def gltf_rd_u16 (b: array<uint8>|array<uint8>#; o: int64) : uint
- Arguments:
b : option<array<uint8>| array<uint8>#>
o : int64
- gltf_rd_u32(b: array<uint8>|array<uint8>#; o: int64 ): uint
def gltf_rd_u32 (b: array<uint8>|array<uint8>#; o: int64) : uint
- Arguments:
b : option<array<uint8>| array<uint8>#>
o : int64
- gltf_rd_u8(b: array<uint8>|array<uint8>#; o: int64 ): uint
def gltf_rd_u8 (b: array<uint8>|array<uint8>#; o: int64) : uint
- Arguments:
b : option<array<uint8>| array<uint8>#>
o : int64
- gltf_read_comp_float(b: array<uint8>|array<uint8>#; o: int64; compType: int; normalized: bool ): float
Read one component at byte offset o as float, applying glTF normalized integer→float conversion (unsigned: /max; signed: max(v/max, -1)).
- Arguments:
b : option<array<uint8>| array<uint8>#>
o : int64
compType : int
normalized : bool
- gltf_read_comp_uint(b: array<uint8>|array<uint8>#; o: int64; compType: int ): uint
Read one component at byte offset o as uint (index accessors: u8/u16/u32).
- Arguments:
b : option<array<uint8>| array<uint8>#>
o : int64
compType : int
- gltf_type_ncomp(t: string ): int
Number of components for a glTF accessor type string (SCALAR/VECn/MATn).
- Arguments:
t : string