Skip to content

rusoleal/gltf

Repository files navigation

C++ glTF 2.0 helper library

A c++ package that allows loading .gltf and .glb (glTF binary format) files according to the glTF 2.0 specification.

Public API

// Parse a JSON .gltf string with external resource loading via callback.
// The callback receives a URI and returns a future with the loaded data.
// After loading, Draco/meshopt extensions are automatically decompressed.
static std::shared_ptr<GLTF> GLTF::loadGLTF(
    const std::string &data,
    std::function<std::future<std::vector<uint8_t>>(const std::string &uri)> loadCallback);

// Parse a binary .glb file given a raw byte buffer and its size in bytes.
// Draco/meshopt extensions are automatically decompressed.
static std::shared_ptr<GLTF> GLTF::loadGLB(uint8_t *data, uint64_t size);

// Returns which buffers and images are required to render a scene.
// Returns nullptr if sceneIndex is out of range.
std::shared_ptr<RuntimeInfo> GLTF::getRuntimeInfo(uint64_t sceneIndex);

Loading external resources

When loading a .gltf file that references external buffers or images by URI, provide a callback:

auto gltf = GLTF::loadGLTF(jsonString, [](const std::string& uri) {
    return std::async(std::launch::deferred, [&uri]() {
        return loadFile(uri);  // your file loading function
    });
});

For self-contained glTF with embedded data URIs (no external files):

auto gltf = GLTF::loadGLTF(jsonString, [](const std::string&) {
    return std::async(std::launch::deferred, []() {
        return std::vector<uint8_t>{};  // no external resources
    });
});

Error handling

Both loadGLTF and loadGLB throw std::invalid_argument on malformed or unsupported input. This includes missing required fields (e.g. asset.version, TextureInfo.index), unsupported required extensions, array size limits exceeded, and invalid cross-references detected at parse time (skin joint indices, animation channel sampler indices, sparse accessor count).

getRuntimeInfo also throws std::invalid_argument when traversing the scene graph if it encounters out-of-range indices for: scene nodes, node children, node mesh, node light (KHR_lights_punctual), primitive material, primitive accessors, accessor buffer views, material textures, KHR_materials_variants material and variant indices, and KHR_xmp_json_ld packet indices (asset, material, mesh, node). It also throws on cycles in the node hierarchy. It returns nullptr for an out-of-range scene index.

Indices that are not traversed by getRuntimeInfo (e.g. animation targets, skin references, camera indices) are not validated at runtime — the caller is responsible for bounds-checking those before use.

External buffers and images

The callback-based loadGLTF automatically handles external resource loading. The callback is invoked for each unique external URI found in buffers and images. The library waits for all futures to complete, assigns the loaded data, and then automatically decompresses any Draco or meshopt extensions. No manual decompression is required.

Thread safety

loadGLTF and loadGLB are stateless and safe to call concurrently. A single GLTF instance is not thread-safe for concurrent mutation; concurrent reads are safe.

Features

  • Load .gltf format with external buffers/images.
  • Load .gltf format with embedded buffers/images.
  • Load .glb format (glTF binary format).
  • Dynamic asset info via GLTF::getRuntimeInfo() method
  • Sparse accessor support (accessor.sparse).
  • Morph targets (primitive.targets[]).
  • Skeletal skin data (skin.joints, skin.inverseBindMatrices, skin.skeleton).

Known Limitations

  • Sparse accessors — the Accessor::sparse field is parsed and exposed, but the library does not automatically apply sparse overrides to the base buffer data. The caller must do this manually if needed.
  • Morph targetsPrimitive::targets is parsed and exposed as a vector of attribute maps (attribute name → accessor index). Computing the final morphed geometry is left to the caller.
  • Skin matrices — joint indices and inverseBindMatrices are parsed and stored in Skin. Computing the final joint transform matrices is left to the caller.
  • Camera downcastingGLTF::cameras holds std::shared_ptr<Camera>. To access PerspectiveCamera-specific fields (aspectRatio, zFar) use std::dynamic_pointer_cast<PerspectiveCamera>(gltf->cameras->at(i)).
  • Input size limits — by default the library rejects assets with more than 65 536 elements in any top-level array (buffers, bufferViews, accessors, meshes, nodes, materials) and buffers larger than 2 GB.

Extensions

Ratified glTF 2.0 extensions:

Status Reference
KHR_animation_pointer Ok Spec.
KHR_draco_mesh_compression Ok Spec.
KHR_lights_punctual Ok Spec.
KHR_materials_anisotropy Ok Spec.
KHR_materials_clearcoat Ok Spec.
KHR_materials_dispersion Ok Spec.
KHR_materials_emissive_strength Ok Spec.
KHR_materials_ior Ok Spec.
KHR_materials_iridescence Ok Spec.
KHR_materials_sheen Ok Spec.
KHR_materials_specular Ok Spec.
KHR_materials_transmission Ok Spec.
KHR_materials_unlit Ok Spec.
KHR_materials_variants Ok Spec.
KHR_materials_volume Ok Spec.
KHR_mesh_quantization Ok Spec.
KHR_texture_basisu Ok Spec.
KHR_texture_transform Ok Spec.
KHR_xmp_json_ld Ok Spec.
EXT_mesh_gpu_instancing Ok Spec.
EXT_meshopt_compression Ok Spec.
KHR_meshopt_compression Ok Same decompression logic as EXT_meshopt_compression (Khronos-ratified name)
EXT_texture_webp Ok Spec.

Dependencies

Licenses

This library is licensed under MIT license.

gltf library uses the following third party libraries.

  • json.hpp : Copyright (c) 2013-2025 Niels Lohmann Link
  • base64 : Copyright (C) 2004-2017, 2020-2022 René Nyffenegger Link

About

C++ glTF 2.0 helper

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages