glTF Loading
SafiEngine provides two glTF loading paths built on cgltf and stb_image:
SafiModel (recommended)
SafiModel is a self-contained renderable that holds merged geometry, per-primitive draw ranges, and per-material textures for an entire glTF file.
Types
Functions
safi_model_load
The loader:
- Parses all meshes and primitives in the glTF file
- Merges vertices and indices into a single shared VBO/IBO
- Deduplicates materials — each unique
cgltf_materialgets one texture slot - Loads base-color textures (embedded or external URI); falls back to a solid color from
baseColorFactoror a 1x1 white texture - Computes an axis-aligned bounding box across all vertices
- Creates a shared unlit pipeline and sampler
Returns false on parse/load/upload error.
safi_model_draw
Must be called inside an active render pass. Binds the shared VBO/IBO once, then loops over primitives — binding the correct material texture and issuing an indexed draw call for each.
safi_model_destroy
Releases all GPU resources (VBO, IBO, pipeline, sampler, textures) and zeroes the struct.
Example
safi_gltf_load (low-level)
Minimal single-primitive loader. Loads only the first mesh's first primitive into a SafiMesh + SafiMaterial pair.
Limitations
- Only the first primitive of the first mesh
- No node graph / transforms
- No skeletal animation or morph targets
- Missing normals are replaced with
(0, 1, 0) - Indices are always converted to
uint32_t
For multi-primitive or multi-material models, use safi_model_load instead.
Example
Supported attributes
Both loaders extract the same vertex attributes from glTF accessors:
See also
SafiMesh— vertex/index buffer pairSafiMaterial— graphics pipeline + textureSafiRenderer— frame lifecycle