github spnda/fastgltf v1.0.0

4 hours ago

This is a major release with many breaking API changes. Most importantly, the library now requires C++20. Please read the entries marked "Change" below when upgrading.

As a quick overview, the most important changes are:

  • Rewritten the Exporter using simdjson's new string_builder API. It is now roughly 4x faster.
  • Significant memory optimizations reducing the average asset (measured on the glTF-Sample-Assets repository) by 37% and reducing the average allocation count by 59%.
    • For example, on Intel's NewSponza the Asset is 31.4% smaller (581KB vs 846KB) with 51.5% less allocations (812 vs 1674) compared to v0.9.1 (on arm64 macOS with Clang 23).
  • Switched to simdutf for base64 decoding for a ~30% performance improvement as well as better error detection & handling.
  • Added a box and boxed_optional type for better ergonomics working with optional glTF data.
  • Rewritten all supporting containers such as small_vector, optional, and static_vector, fixing a lot of unexpected behavior and memory and exception safety issues.
  • Implemented fuzzing for the parser, exporter, and URI parser, fixing an incredible amount of issues and edge cases.
  • Updated the library to C++20

This is a major milestone as fastgltf has now hit v1.0. However, I want to be clear that there's still a lot of things that I plan on changing in the future. v1.0 was more focused on fixing as many existing issues as possible while laying the groundwork in terms of API changes and supporting functionality to have a better base to expand upon.

I also wanted to finally ditch the 0-based versioning and stick to proper semantic versioning. Previous version numbers were always loosely based on "how much has changed" (see v0.8 vs v0.9, there's no actual reason to bump the minor version since they're completely compatible).

Also, this is the first major version of fastgltf to require C++20 instead of C++17. This was done because I think nearing the end of 2026 there should be enough support for C++20 and the amount of things I had to workaround or implement myself which are features of the language or standard library with C++20 was surprisingly large.

With this release the library recognizes glTF 2.1 assets. This does not mean that it can load all of them: assets requiring 2.1 through minVersion and GLB version 3 files are rejected, while 2.1 assets compatible with 2.0 load as usual.

  • Add: Support for more extensions
    • KHR_accessor_float16
    • EXT_texture_avif
  • Add: Support for 16-bit floats and 64-bit integers in accessors
    • ComponentType now has HalfFloat, Int64, and UnsignedInt64.
    • std::float16_t is also supported on supporting compilers. Otherwise fastgltf::HalfFloat can be used as a storage type. See the documentation for more details.
  • Add: GltfDataString to easily pass strings or literals to the parser
  • Add: validateAccessorBounds to validate a single accessor against its buffer view and buffer
  • Add: box (a conformant implementation of std::indirect (C++26)) and boxed_optional containers
    • This type is essentially a fancy wrapper around a std::unique_ptr but with value-like semantics
    • boxed_optional provides the std::optional interface but uses a box internally with nullptr being the valueless state.
    • Members data such as Accessor::sparse, Material::clearcoat and BufferView::meshoptCompression are now a boxed_optional instead of a std::unique_ptr for a better usage API
  • Add: Fuzzing targets, which can be enabled with the FASTGLTF_ENABLE_FUZZING CMake option (#158)
    • Fix #160: Guard against invalid accessor indices when generating mesh indices
    • Fix: Integer underflow when generating mesh indices causing large allocations
    • Fix: Malformed data URIs could read out of bounds or overflow the output (@tim-tim707)
    • Fix: GLB JSON chunk total length check
    • Fix: Always reset the GLB buffer when reusing a parser
    • Fix: Avoid NaNs when decomposing a matrix with zero scale
    • Fix: Catch out-of-range and non-finite numbers, and use num in all remaining types
    • Fix: Guard against large and out-of-bounds material variants
    • Fix: Check glTF indices against the sentinel values used by flagged_optional
    • Fix: Check invalid sparse accessor buffer views and animation channel accessors in validate
    • Change: Reject duplicated root JSON objects, meshes with no primitives, non-finite node transforms, accessor bounds that don't fit into 2^63, and unknown enumeration values
  • Add: CMake options FASTGLTF_DOWNLOAD_SIMDJSON and FASTGLTF_DOWNLOAD_SIMDUTF
    • Downloaded dependencies are now checked against their SHA256, and are installed alongside fastgltf.
    • Disabling these options makes fastgltf fail if find_package cannot resolve either library.
  • Add: std::ostream overload and std::formatter specialization for Error
  • Change: Completely rewrite fastgltf::small_vector, fastgltf::static_vector, and add fastgltf::inplace_vector
    • fastgltf::small_vector is now completely compatible with std::vector
    • The containers now all offer the same exception guarantees that comparable std containers do.
    • The containers are now completely allocator compliant
    • Fixed a significant amount of memory and exception safety issues
    • Renamed the containers and all of their member functions to snake_case to match the C++ standard containers
    • Support for C++23's std::from_range, assign_range, and append_range
  • Change: Rename Optional to optional and OptionalWithFlagValue to flagged_optional
    • Flag traits now also allow complex types in flagged_optional.
    • flagged_optional and boxed_optional now share a generic basic_optional interface
  • Change: Replace the custom base64 implementations with simdutf (#159)
    • fastgltf now depends on simdutf, which is downloaded by default.
    • base64::decode now returns an Expected, and base64::decode_inplace returns a bool. Both now report malformed input.
    • The custom NEON/SSE/AVX decode functions have been removed in favor of the simdutf functions since benchmarks showed them to be more performant while being stricter.
    • Parser::setBase64DecodeCallback and Base64DecodeCallback were removed.
  • Change: Rewrite Expected as a tagged union, which also allows any error type
    • Using Expected as a tuple with structured bindings is not possible anymore since it has become a union.
    • New errors: InvalidVersion, ValueOutOfRange, UnexpectedJsonType, MissingExternalFile, and Unknown.
    • Error::MissingExternalBuffer and Error::InvalidOrMissingAssetField are now deprecated aliases for Error::MissingExternalFile and Error::InvalidGltf.
  • Change: Harden version parsing and checks (#165)
    • This was done to reject assets that advertise minVersion as 2.1.
    • AssetInfo::gltfVersion is now AssetInfo::version and uses the new Version type. AssetInfo::minVersion is now an optional<Version>.
    • Asset::assetInfo is no longer optional, and Options::DontRequireValidAssetMember was removed.
    • Version strings are now parsed using the stricter syntax defined by glTF 2.1.
  • Change: Remove all usage of polymorphic allocators and the custom memory pool
    • Nearly all strings and vectors in the glTF types are now std::string and std::vector.
    • Primitive::findAttribute and similar functions now return std::vector iterators instead of pointers.
    • The CMake options FASTGLTF_DISABLE_CUSTOM_MEMORY_POOL and FASTGLTF_USE_CUSTOM_SMALLVECTOR were removed.
    • Removed MaybeSmallVector.
  • Change: sources::URI::uri is now boxed to reduce the size of DataSource
  • Change: Shape is now a struct holding the variant in Shape::data, and also has a name for better future compatibility with glTF 2.1
  • Change: KHR_implicit_shapes and KHR_physics_rigid_bodies are now always available
    • The CMake options FASTGLTF_ENABLE_KHR_IMPLICIT_SHAPES and FASTGLTF_ENABLE_KHR_PHYSICS_RIGID_BODIES were removed. Enable the extensions through the Parser like any other extension.
  • Change: Split core.hpp into parser.hpp and exporter.hpp
    • core.hpp continues to exist and holds the validation functionality
  • Change: Deprecate fastgltf::span and fastgltf::dynamic_extent. Use the std types instead.
  • Change: Removed math::pi in favor of std::numbers::pi.
  • Removed macros: FASTGLTF_CPP_17, FASTGLTF_CPP_20, FASTGLTF_HAS_BIT, FASTGLTF_HAS_CONCEPTS, FASTGLTF_CONSTEXPR_BITCAST, FASTGLTF_LIKELY / FASTGLTF_UNLIKELY
  • Removed CMake option: FASTGLTF_COMPILE_AS_CPP20.
  • Various fixes and improvements to the URI parser
    • The parser was rewritten.
    • URI::decodePercents is now the free function decodePercents, which returns the decoded string.
    • Fix: A % without two hex digits read out of bounds (@tim-tim707)
    • Fix: Treat ? after # as part of the URI fragment (@Shaisolaris, #161)
  • Various fixes and improvements to the Exporter interface
    • Fix: Percent-encode file paths written as URIs (@khiner)
    • Fix: Add missing Color meshopt compression filter
  • Fix #86: Move ordinary includes before the module purview
  • Fix: Keep scenes that omit nodes (@khiner)
  • Fix: GenerateMeshIndices now generates correct indices for strip, fan, and loop topologies
  • Fix: copyComponentsFromAccessor used the wrong destination address when converting components
  • Fix: Wrong accessor element trait type for signed 32-bit vectors
  • Fix: Don't throw an error when visible, selectable, or hoverable is missing
  • Fix #164: Check the correct error for a missing KHR_lights_punctual object
  • Fix: Check errors returned from parsing material extensions
  • Fix: Skip the directory check in loadGltfBinary on Android to match loadGltfJson (@1runeberg, #155)
  • Fix: Don't leak the file descriptor in MappedGltfFile when fstat fails
  • Fix: Compile with more warnings enabled and /W4 on MSVC, and fix all of them accordingly
  • Docs: Clarify the external buffer and image loading options (@snowyukitty, #162)
  • Bump builtin simdjson version from 4.6.0 to 5.1.0

... and a significant amount of various minor improvements and fixes!

Don't miss a new fastgltf release

NewReleases is sending notifications on new releases.