### Install fastgltf Components Source: https://github.com/spnda/fastgltf/blob/main/CMakeLists.txt This section handles the installation of fastgltf components when `FASTGLTF_ENABLE_INSTALL` is true. It installs headers, the package configuration files, and the main library targets. ```cmake if (FASTGLTF_ENABLE_INSTALL) install( FILES ${FASTGLTF_HEADERS} DESTINATION include/fastgltf ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/fastgltfConfigVersion.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fastgltf ) install( TARGETS fastgltf EXPORT fastgltf-targets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) install( EXPORT fastgltf-targets FILE fastgltfConfig.cmake NAMESPACE fastgltf:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fastgltf ) endif () ``` -------------------------------- ### Enable Subdirectories for Examples, Tests, and Docs Source: https://github.com/spnda/fastgltf/blob/main/CMakeLists.txt This snippet conditionally includes subdirectories for examples, tests, and documentation based on CMake variables. If the respective `FASTGLTF_ENABLE_` variables are set to true, the corresponding subdirectories are added to the build. ```cmake if (FASTGLTF_ENABLE_EXAMPLES) add_subdirectory(examples) endif () if (FASTGLTF_ENABLE_TESTS) add_subdirectory(tests) endif () if (FASTGLTF_ENABLE_DOCS) add_subdirectory(docs) endif () ``` -------------------------------- ### Load Primitive Indices with Accessor Tools Source: https://github.com/spnda/fastgltf/blob/main/docs/overview.rst Loads the indices of a glTF primitive using fastgltf's accessor utilities. This example demonstrates how to extract index data, supporting sparse accessors. Ensure the asset and primitive are valid. ```cpp fastgltf::Primitive& primitive = ...; std::vector indices; if (primitive.indicesAccessor.has_value()) { auto& accessor = asset->accessors[primitive.indicesAccessor.value()]; indices.resize(accessor.count); fastgltf::iterateAccessorWithIndex( asset.get(), accessor, [&](std::uint32_t index, std::size_t idx) { indices[idx] = index; }); } ``` -------------------------------- ### Export glTF with Extras Write Callback Source: https://github.com/spnda/fastgltf/blob/main/docs/guides.rst Use a custom callback to write 'extras' data when exporting a glTF asset. This example writes node names. ```c++ auto extrasWriteCallback = [](std::size_t objectIndex, fastgltf::Category category, void *userPointer) -> std::optional { if (category != fastgltf::Category::Nodes) return std::nullopt; auto *nodeNames = static_cast*>(userPointer); if (objectIndex >= nodeNames->size()) return std::nullopt; // TODO: Error? return {std::string(R"({\"name\":")") + (*nodeNames)[objectIndex] + "\"}"}; }; std::vector nodeNames; fastgltf::Exporter exporter; exporter.setUserPointer(&nodeNames); exporter.setExtrasWriteCallback(extrasWriteCallback); auto exported = exporter.writeGltfJson(asset, fastgltf::ExportOptions::None); ``` -------------------------------- ### Define fastgltf_gl_viewer Executable Source: https://github.com/spnda/fastgltf/blob/main/examples/gl_viewer/CMakeLists.txt Defines the 'fastgltf_gl_viewer' executable and excludes it from default build targets. This is typically used for specific tools or examples. ```cmake add_executable(fastgltf_gl_viewer EXCLUDE_FROM_ALL) ``` -------------------------------- ### Load Primitive Positions into OpenGL Buffer Source: https://github.com/spnda/fastgltf/blob/main/docs/tools.rst This example demonstrates loading vertex positions for a glTF primitive into an OpenGL vertex buffer. It uses fastgltf's accessor tools to iterate over the position data and copy it directly into a mapped OpenGL buffer. Ensure that the glTF asset and primitive are valid, and that the 'POSITION' attribute exists. ```c++ fastgltf::Primitive* primitive = ...; // findAttribute returns a iterator into the underlying vector of primitive attributes. // Note that the glTF spec requires every primitive to have a POSITION, // so it's perfectly valid to assert that positionIt is never nullptr. auto* positionIt = primitive->findAttribute("POSITION"); auto& positionAccessor = asset.accessors[positionIt->second]; if (!positionAccessor.bufferViewIndex.has_value()) continue; // Create the vertex buffer for this primitive, // and use the accessor tools to copy directly into the mapped buffer. glCreateBuffers(1, &primitive.vertexBuffer); glNamedBufferData(primitive.vertexBuffer, positionAccessor.count * sizeof(Vertex), nullptr, GL_STATIC_DRAW); auto* vertices = static_cast(glMapNamedBuffer(primitive.vertexBuffer, GL_WRITE_ONLY)); // Iterates over the accessor (potentially handling any sparse accessors), // and gives each vertex UV a default value, which need to be loaded separately. fastgltf::iterateAccessorWithIndex( asset, positionAccessor, [&](fastgltf::math::fvec3 pos, std::size_t idx) { vertices[idx].position = pos; vertices[idx].uv = fastgltf::math::fvec2(); }); ``` -------------------------------- ### Parse glTF JSON with Extras Callback Source: https://github.com/spnda/fastgltf/blob/main/docs/guides.rst Use a custom callback to parse 'extras' data during glTF JSON loading. This example specifically extracts node names. ```c++ auto extrasCallback = [](simdjson::dom::object* extras, std::size_t objectIndex, fastgltf::Category category, void* userPointer) { if (category != fastgltf::Category::Nodes) return; auto* nodeNames = static_cast*>(userPointer); nodeNames->resize(fastgltf::max(nodeNames->size(), objectIndex + 1)); std::string_view nodeName; if ((*extras)("name").get_string().get(nodeName) == simdjson::SUCCESS) { (*nodeNames)[objectIndex] = std::string(nodeName); } }; std::vector nodeNames; fastgltf::Parser parser; parser.setExtrasParseCallback(extrasCallback); parser.setUserPointer(&nodeNames); auto asset = parser.loadGltfJson(&jsonData, materialVariants); ``` -------------------------------- ### Iterate Accessor using Ranges in C++ Source: https://context7.com/spnda/fastgltf/llms.txt Use `iterateAccessor` to get an `IterableAccessor` that works with range-based for loops and standard algorithms. Requires `fastgltf/tools.hpp`. ```cpp #include #include #include const auto& posAcc = asset.accessors[posAttr->second]; // Range-based for loop std::size_t idx = 0; for (auto pos : fastgltf::iterateAccessor(asset, posAcc)) { gpuBuffer[idx++] = pos; } // Compatible with std:: algorithms auto range = fastgltf::iterateAccessor(asset, scalarAcc); float sum = std::accumulate(range.begin(), range.end(), 0.0f); auto it = std::find_if(range.begin(), range.end(), [](float v) { return v > 1.0f; }); ``` -------------------------------- ### Iterate Accessor with Index in C++ Source: https://context7.com/spnda/fastgltf/llms.txt Use `iterateAccessorWithIndex` to iterate over accessor data and get the element index. This is useful for writing directly into a pre-sized destination buffer, such as a mapped GPU vertex buffer. Requires `fastgltf/tools.hpp`. ```cpp #include // Write positions & default UVs directly into a mapped GPU vertex buffer struct Vertex { fastgltf::math::fvec3 position; fastgltf::math::fvec2 uv; }; glCreateBuffers(1, &vbo); glNamedBufferData(vbo, posAcc.count * sizeof(Vertex), nullptr, GL_STATIC_DRAW); auto* vertices = static_cast(glMapNamedBuffer(vbo, GL_WRITE_ONLY)); fastgltf::iterateAccessorWithIndex( asset, posAcc, [&](fastgltf::math::fvec3 pos, std::size_t idx) { vertices[idx].position = pos; vertices[idx].uv = fastgltf::math::fvec2(); }); // Fill UV channel separately auto* uvAttr = prim.findAttribute("TEXCOORD_0"); if (uvAttr) { fastgltf::iterateAccessorWithIndex( asset, asset.accessors[uvAttr->second], [&](fastgltf::math::fvec2 uv, std::size_t idx) { vertices[idx].uv = uv; }); } glUnmapNamedBuffer(vbo); ``` -------------------------------- ### Load glTF File with fastgltf Source: https://github.com/spnda/fastgltf/blob/main/docs/overview.rst Demonstrates the basic usage of fastgltf to load a glTF file. It shows how to create a parser instance and hints at buffer handling. The parser should ideally be reused across loads but not across threads. Extensions can be enabled via the parser's constructor. ```c++ #include #include bool load(std::filesystem::path path) { // Creates a Parser instance. Optimally, you should reuse this across loads, but don't use it // across threads. To enable extensions, you have to pass them into the parser's constructor. fastgltf::Parser parser; // The GltfDataBuffer class contains static factories which create a buffer for holding the // glTF data. These return Expected, which can be checked if an error occurs. ``` -------------------------------- ### Configure fastgltf::Parser with extensions Source: https://context7.com/spnda/fastgltf/llms.txt Instantiate the Parser class, optionally enabling specific glTF extensions using a bitwise OR combination. Reusing a Parser instance is recommended for performance, but it should not be used concurrently from multiple threads. ```cpp #include // Parser with no extensions (fastest, parses only core glTF 2.0) fastgltf::Parser parser; // Parser with multiple extensions enabled via bitwise OR fastgltf::Parser parserExt( fastgltf::Extensions::KHR_lights_punctual | fastgltf::Extensions::KHR_materials_unlit | fastgltf::Extensions::KHR_texture_transform | fastgltf::Extensions::EXT_meshopt_compression | fastgltf::Extensions::KHR_draco_mesh_compression ); ``` -------------------------------- ### Get local node transform matrix Source: https://github.com/spnda/fastgltf/blob/main/docs/guides.rst Retrieve the local transform matrix for a given glTF node. This is useful for implementing custom iteration logic. ```c++ auto mat4 = fastgltf::getTranformMatrix(node); ``` -------------------------------- ### Link Libraries for fastgltf_gl_viewer Source: https://github.com/spnda/fastgltf/blob/main/examples/gl_viewer/CMakeLists.txt Links the necessary libraries for the 'fastgltf_gl_viewer' executable. This includes the fastgltf library itself, OpenGL loader (glad), GLFW for windowing, and ImGui for UI. ```cmake target_link_libraries(fastgltf_gl_viewer PRIVATE fastgltf::fastgltf fg_glad_gl46) ``` ```cmake target_link_libraries(fastgltf_gl_viewer PRIVATE glfw::glfw stb imgui::imgui) ``` -------------------------------- ### Build fastgltf Tests with CMake Source: https://github.com/spnda/fastgltf/blob/main/tests/README.md Use this command to build the fastgltf test target. Ensure FASTGLTF_ENABLE_TESTS is set to ON during CMake configuration. ```bash cmake --build . --target fastgltf_tests ``` -------------------------------- ### Add Source Directory for fastgltf_gl_viewer Source: https://github.com/spnda/fastgltf/blob/main/examples/gl_viewer/CMakeLists.txt Includes all source files from the current directory into the 'fastgltf_gl_viewer' target. This is a convenient way to add multiple source files. ```cmake fastgltf_add_source_directory(TARGET fastgltf_gl_viewer FOLDER ".") ``` -------------------------------- ### Get Single Typed Element from Accessor Source: https://context7.com/spnda/fastgltf/llms.txt Retrieve a specific typed element from a glTF accessor by index using `getAccessorElement`. This function handles sparse accessors, normalization, and component type conversion automatically. Requires `fastgltf/tools.hpp`. ```cpp #include #include // Get the position of the 42nd vertex const auto& posAcc = asset.accessors[posAttr->second]; fastgltf::math::fvec3 pos = fastgltf::getAccessorElement( asset, posAcc, 42); // Works with any type that has an ElementTraits specialisation: // built-in: int8/16/32, uint8/16/32, float, double, fvec2/3/4, dvec2/3/4, // fquat, fmat2x2/3x3/4x4, and their glm / DXMath equivalents. std::uint32_t index = fastgltf::getAccessorElement( asset, idxAcc, 0); ``` -------------------------------- ### Build fastgltf Tests on Visual Studio with CMake Source: https://github.com/spnda/fastgltf/blob/main/tests/README.md If using Visual Studio, this command builds the test target. Ensure FASTGLTF_ENABLE_TESTS is set to ON during CMake configuration. ```bash cmake --build . --target tests/fastgltf_tests ``` -------------------------------- ### Run fastgltf Tests with Catch2 Source: https://github.com/spnda/fastgltf/blob/main/tests/README.md Execute all tests using the Catch2 test runner. This command runs tests excluding those tagged with 'gltf-benchmark'. ```bash tests/fastgltf_tests -d yes --order lex ~[gltf-benchmark] ``` -------------------------------- ### Load glTF Asset from Path Source: https://github.com/spnda/fastgltf/blob/main/docs/overview.rst Loads a glTF file from a given path and parses its JSON content. It automatically detects binary or JSON formats. Ensure the path is valid and the file is accessible. Errors during loading or parsing are returned. ```cpp auto data = fastgltf::GltfDataBuffer::FromPath(path); if (data.error() != fastgltf::Error::None) { // The file couldn't be loaded, or the buffer could not be allocated. return false; } // This loads the glTF file into the gltf object and parses the JSON. // It automatically detects whether this is a JSON-based or binary glTF. // If you know the type, you can also use loadGltfJson or loadGltfBinary. auto asset = parser.loadGltf(data.get(), path.parent_path(), fastgltf::Options::None); if (auto error = asset.error(); error != fastgltf::Error::None) { // Some error occurred while reading the buffer, parsing the JSON, or validating the data. return false; } // The glTF 2.0 asset is now ready to be used. Simply call asset.get(), asset.get_if() or // asset-> to get a direct reference to the Asset class. You can then access the glTF data // structures, like, for example, with buffers: for (auto& buffer : asset->buffers) { // Process the buffers. } // Optionally, you can now also call the fastgltf::validate method. This will more strictly // enforce the glTF spec and is not needed most of the time, though I would certainly // recommend it in a development environment or when debugging to avoid mishaps. // fastgltf::validate(asset.get()); return true; ``` -------------------------------- ### Error Handling with fastgltf::Expected Source: https://context7.com/spnda/fastgltf/llms.txt All parser and buffer-factory operations return `Expected`, a lightweight result type that bundles a value with a `fastgltf::Error` enum. Never call `get()` or `operator->()` without first verifying `error() == Error::None`. ```cpp #include auto data = fastgltf::GltfDataBuffer::FromPath("./missing.gltf"); auto asset = fastgltf::Parser{}.loadGltf(data.get(), "./"); // Method 1 – check error code if (asset.error() != fastgltf::Error::None) { std::cerr << "[" << fastgltf::getErrorName(asset.error()) << "] " << fastgltf::getErrorMessage(asset.error()) << '\n'; return; } // Method 2 – bool conversion if (!asset) { /* same as checking error() != None */ } // Method 3 – get_if (returns nullptr on error) if (auto* a = asset.get_if()) { std::cout << "Loaded " << a->meshes.size() << " meshes.\n"; } // Method 4 – structured bindings (C++17) auto [err, value] = std::move(asset); if (err != fastgltf::Error::None) { /* ... */ } ``` -------------------------------- ### Load glTF Asset with Options Source: https://context7.com/spnda/fastgltf/llms.txt Loads a glTF asset from a file path, automatically detecting JSON or GLB format. Supports options for loading external buffers and images, decomposing node matrices, and generating mesh indices. Handles file reading errors and parsing errors. ```cpp #include #include bool loadScene(const std::filesystem::path& path) { fastgltf::Parser parser( fastgltf::Extensions::KHR_lights_punctual | fastgltf::Extensions::KHR_materials_unlit ); auto data = fastgltf::GltfDataBuffer::FromPath(path); if (data.error() != fastgltf::Error::None) { std::cerr << "Failed to read file: " << fastgltf::getErrorMessage(data.error()) << '\n'; return false; } // Options::LoadExternalBuffers – read external .bin files into CPU memory // Options::LoadExternalImages – read external image files into CPU memory // Options::DecomposeNodeMatrices – convert matrix transforms to TRS on load // Options::GenerateMeshIndices – auto-generate indices for un-indexed primitives auto options = fastgltf::Options::LoadExternalBuffers | fastgltf::Options::DecomposeNodeMatrices; auto asset = parser.loadGltf(data.get(), path.parent_path(), options); if (auto err = asset.error(); err != fastgltf::Error::None) { std::cerr << "glTF parse error: " << fastgltf::getErrorMessage(err) << '\n'; return false; } // Access parsed data std::cout << "Meshes : " << asset->meshes.size() << '\n'; std::cout << "Nodes : " << asset->nodes.size() << '\n'; std::cout << "Scenes : " << asset->scenes.size() << '\n'; std::cout << "Images : " << asset->images.size() << '\n'; std::cout << "Lights : " << asset->lights.size() << '\n'; // Selective category parsing (skip animations for a render-only path) auto assetRenderOnly = parser.loadGltf( data.get(), path.parent_path(), options, fastgltf::Category::OnlyRenderable ); return true; } ``` -------------------------------- ### Error Handling - fastgltf::Expected Source: https://context7.com/spnda/fastgltf/llms.txt All parser and buffer-factory operations return `Expected`, a lightweight result type that bundles a value with a `fastgltf::Error` enum. Never call `get()` or `operator->()` without first verifying `error() == Error::None`. ```APIDOC ## Error Handling — `fastgltf::Expected`, `getErrorName`, `getErrorMessage` All parser and buffer-factory operations return `Expected`, a lightweight result type that bundles a value with a `fastgltf::Error` enum. Never call `get()` or `operator->()` without first verifying `error() == Error::None`. ```cpp #include auto data = fastgltf::GltfDataBuffer::FromPath("./missing.gltf"); auto asset = fastgltf::Parser{}.loadGltf(data.get(), "./"); // Method 1 – check error code if (asset.error() != fastgltf::Error::None) { std::cerr << "[" << fastgltf::getErrorName(asset.error()) << "] " << fastgltf::getErrorMessage(asset.error()) << '\n'; return; } // Method 2 – bool conversion if (!asset) { /* same as checking error() != None */ } // Method 3 – get_if (returns nullptr on error) if (auto* a = asset.get_if()) { std::cout << "Loaded " << a->meshes.size() << " meshes.\n"; } // Method 4 – structured bindings (C++17) auto [err, value] = std::move(asset); if (err != fastgltf::Error::None) { /* ... */ } ``` ``` -------------------------------- ### Integrate fastgltf with CMake Source: https://context7.com/spnda/fastgltf/llms.txt Add fastgltf to your CMake project using FetchContent. simdjson is automatically downloaded. Ensure you link against the fastgltf::fastgltf target. ```cmake cmake_minimum_required(VERSION 3.13) project(MyApp) # Option A – FetchContent include(FetchContent) FetchContent_Declare(fastgltf GIT_REPOSITORY https://github.com/spnda/fastgltf.git GIT_TAG v0.9.0 ) FetchContent_MakeAvailable(fastgltf) # Option B – vcpkg / conan (package name: fastgltf) # find_package(fastgltf CONFIG REQUIRED) add_executable(my_app main.cpp) target_link_libraries(my_app PRIVATE fastgltf::fastgltf) # Optional CMake flags # -DFASTGLTF_USE_64BIT_FLOAT=ON – use double instead of float for glTF num types # -DFASTGLTF_DISABLE_CUSTOM_MEMORY_POOL=ON – disable PMR-based allocator # -DFASTGLTF_COMPILE_AS_CPP20=ON – compile as C++20 # -DFASTGLTF_ENABLE_CPP_MODULES=ON – expose fastgltf::module C++20 named module target ``` -------------------------------- ### Configure Filesystem Library Source: https://github.com/spnda/fastgltf/blob/main/CMakeLists.txt This snippet configures the filesystem library based on the compiler and its version. It sets the FILESYSTEM_LIB variable to link the appropriate library for C++17 filesystem support, particularly for older GCC and Clang versions. ```cmake set(FILESYSTEM_LIB "") if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.1) set(FILESYSTEM_LIB stdc++fs) elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0) set(FILESYSTEM_LIB c++fs) endif() if(FILESYSTEM_LIB) target_link_libraries(fastgltf PRIVATE ${FILESYSTEM_LIB}) endif() ``` -------------------------------- ### Generate Package Configuration File Source: https://github.com/spnda/fastgltf/blob/main/CMakeLists.txt This snippet generates a basic package version file for CMake's package management system. It uses the `write_basic_package_version_file` command to create `fastgltfConfigVersion.cmake`. ```cmake include(GNUInstallDirs) include(CMakePackageConfigHelpers) write_basic_package_version_file( "${PROJECT_BINARY_DIR}/fastgltfConfigVersion.cmake" VERSION ${PACKAGE_VERSION} COMPATIBILITY SameMajorVersion ) ``` -------------------------------- ### Load glTF file from path or bytes Source: https://github.com/spnda/fastgltf/blob/main/docs/guides.rst Use GltfDataBuffer factory constructors to load glTF file contents from a file path or a byte array. Always check the returned Expected for errors. ```c++ auto gltfFile = fastgltf::GltfDataBuffer::FromPath("./asset.gltf"); auto gltfData = fastgltf::GltfDataBuffer::FromBytes(bytes.data(), bytes.size()); ``` -------------------------------- ### Custom Buffer Data Adapter with Lambda Source: https://github.com/spnda/fastgltf/blob/main/docs/tools.rst Use a lambda function as a custom buffer data adapter to provide binary data for accessors. This is useful when external buffers are loaded as sources::URI and the DefaultBufferDataAdapter cannot be used directly. Ensure the lambda correctly returns a span to the required byte range. ```c++ std::vector fileBytes; std::vector accessorData(accessor.count); fastgltf::copyFromAccessor(asset.get(), accessor, accessorData.data(), [&](const Asset& asset, const std::size_t bufferViewIdx) const { const auto& bufferView = asset.bufferViews[bufferViewIdx]; return span(fileBytes).subspan(bufferView.byteOffset, bufferView.byteLength); }); ``` -------------------------------- ### Export Asset to JSON or Binary (In-Memory) Source: https://context7.com/spnda/fastgltf/llms.txt Serialize a `fastgltf::Asset` to an in-memory JSON string or binary GLB blob. Does not write to disk. Use `fastgltf::FileExporter` for automatic disk writing. Configure relative paths for buffer and image URIs using `setBufferPath` and `setImagePath`. ```cpp #include fastgltf::Asset asset; // constructed or previously parsed // ... populate asset ... fastgltf::Exporter exporter; exporter.setBufferPath("buffers/"); // relative path for buffer URIs exporter.setImagePath("images/"); // relative path for image URIs // Export as JSON glTF auto jsonResult = exporter.writeGltfJson( asset, fastgltf::ExportOptions::PrettyPrintJson); if (jsonResult) { const std::string& jsonStr = jsonResult->output; // jsonResult->bufferPaths – optional filesystem paths for each buffer // jsonResult->imagePaths – optional filesystem paths for each image std::ofstream("out/scene.gltf") << jsonStr; } // Export as binary GLB (first buffer ≤ 4 GB is embedded automatically) auto glbResult = exporter.writeGltfBinary(asset); if (glbResult) { const std::vector& blob = glbResult->output; std::ofstream("out/scene.glb", std::ios::binary) .write(reinterpret_cast(blob.data()), blob.size()); } ``` -------------------------------- ### Iterate Scene Nodes Source: https://context7.com/spnda/fastgltf/llms.txt Recursively walk every node in a scene in depth-first order, providing each node and its accumulated world-space transform matrix. Requires `fastgltf/tools.hpp`. ```APIDOC ## `fastgltf::iterateSceneNodes` Recursively walk every node in a scene in depth-first order, providing each node and its accumulated world-space transform matrix. Requires `fastgltf/tools.hpp`. ```cpp #include std::size_t sceneIdx = asset.defaultScene.value_or(0); fastgltf::iterateSceneNodes(asset, sceneIdx, fastgltf::math::fmat4x4(1.f), // identity as initial transform [&](fastgltf::Node& node, const fastgltf::math::fmat4x4& worldMatrix) { if (node.meshIndex.has_value()) { const auto& mesh = asset.meshes[*node.meshIndex]; for (const auto& prim : mesh.primitives) { drawPrimitive(prim, worldMatrix); } } if (node.cameraIndex.has_value()) { setupCamera(asset.cameras[*node.cameraIndex], worldMatrix); } if (node.lightIndex.has_value()) { setupLight(asset.lights[*node.lightIndex], worldMatrix); } }); ``` ``` -------------------------------- ### Redirect Buffer Allocation with Callbacks Source: https://context7.com/spnda/fastgltf/llms.txt Use custom callbacks to manage buffer memory, allowing direct allocation into application-managed memory like GPU buffers to avoid CPU copies. The mapCallback is invoked for storage needs, and unmapCallback signals completion. ```cpp #include struct AppState { // e.g. a Vulkan/DX12 staging buffer pool std::vector stagingBuffers; }; fastgltf::BufferInfo mapBuffer(std::uint64_t bufferSize, void* userPointer) { auto* app = static_cast(userPointer); // Allocate / map a GPU-visible staging buffer void* mappedPtr = /* vkMapMemory(...) */ nullptr; CustomBufferId id = /* buffer index */ 0; return { mappedPtr, id }; } void unmapBuffer(fastgltf::BufferInfo* info, void* userPointer) { // vkUnmapMemory(...); } AppState appState; fastgltf::Parser parser; parser.setBufferAllocationCallback(mapBuffer, unmapBuffer); parser.setUserPointer(&appState); auto data = fastgltf::GltfDataBuffer::FromPath("./scene.glb"); auto asset = parser.loadGltfBinary(data.get(), "./", fastgltf::Options::None); ``` -------------------------------- ### Copy Accessor Data in C++ Source: https://context7.com/spnda/fastgltf/llms.txt Use `copyFromAccessor` for bulk copying accessor data to a destination buffer, handling type conversions and normalization. It uses `memcpy` for exact type matches and supports custom strides. Requires `fastgltf/tools.hpp`. ```cpp #include // Simple copy — positions into a contiguous float3 array const auto& posAcc = asset.accessors[posAttr->second]; std::vector positions(posAcc.count); fastgltf::copyFromAccessor( asset, posAcc, positions.data()); // Copy with a custom stride (e.g., interleaved vertex buffer) struct Vertex { fastgltf::math::fvec3 pos; fastgltf::math::fvec2 uv; std::uint8_t _pad[2]; }; std::vector verts(posAcc.count); fastgltf::copyFromAccessor fileBytes = /* read entire .bin file */; std::vector out(posAcc.count * 3); fastgltf::copyFromAccessor( asset, posAcc, out.data(), [&](const fastgltf::Asset& a, std::size_t bvIdx) { const auto& bv = a.bufferViews[bvIdx]; return fastgltf::span(fileBytes).subspan(bv.byteOffset, bv.byteLength); }); ``` -------------------------------- ### Export Asset to Disk (File Exporter) Source: https://context7.com/spnda/fastgltf/llms.txt Higher-level exporter that writes the glTF JSON (or GLB) plus all referenced buffers and images to disk automatically. Inherits all `setBufferPath`/`setImagePath` configuration from `Exporter`. Use `fastgltf::ExportOptions::ValidateAsset` for validation. ```cpp #include fastgltf::Asset asset; // previously loaded/constructed fastgltf::FileExporter fileExporter; fileExporter.setBufferPath("buffers/"); // Write JSON + external buffer files fastgltf::Error err = fileExporter.writeGltfJson( asset, "export/scene.gltf", fastgltf::ExportOptions::PrettyPrintJson | fastgltf::ExportOptions::ValidateAsset ); if (err != fastgltf::Error::None) { std::cerr << "Export failed: " << fastgltf::getErrorMessage(err) << '\n'; } // Write GLB (single-file, first buffer embedded) fastgltf::Error err2 = fileExporter.writeGltfBinary(asset, "export/scene.glb"); ``` -------------------------------- ### Load glTF data into memory Source: https://context7.com/spnda/fastgltf/llms.txt Load glTF file data using GltfDataBuffer::FromPath or GltfDataBuffer::FromBytes. MappedGltfFile offers memory-mapped loading for potentially faster access on supported platforms. Always check the returned Expected for errors. ```cpp #include // Load from filesystem path (copies file into heap buffer) auto data = fastgltf::GltfDataBuffer::FromPath("./scene.glb"); if (data.error() != fastgltf::Error::None) { std::cerr << fastgltf::getErrorMessage(data.error()) << '\n'; return false; } // Load from raw bytes already in memory std::vector fileBytes = readFileSomehow("scene.gltf"); auto data2 = fastgltf::GltfDataBuffer::FromBytes(fileBytes.data(), fileBytes.size()); // Memory-mapped file (Linux/macOS/Windows desktop only) #ifdef FASTGLTF_HAS_MEMORY_MAPPED_FILE auto mapped = fastgltf::MappedGltfFile::FromPath("./large_scene.glb"); if (!mapped) { std::cerr << "mmap failed: " << std::strerror(errno) << '\n'; return false; } #endif // Stream-based (wraps std::ifstream, lowest memory overhead) fastgltf::GltfFileStream stream("./scene.gltf"); if (!stream.isOpen()) { return false; } ``` -------------------------------- ### Open glTF file stream Source: https://github.com/spnda/fastgltf/blob/main/docs/guides.rst Use GltfFileStream to wrap std::ifstream for loading glTF files. Ensure the stream is open before proceeding. ```c++ fastgltf::GltfFileStream fileStream("./asset.gltf"); if (!fileStream.isOpen()) return false; ``` -------------------------------- ### Configure C++ Modules Support Source: https://github.com/spnda/fastgltf/blob/main/CMakeLists.txt This snippet enables and configures C++ modules support for fastgltf. It checks for compiler support and CMake version compatibility, then defines a library for modules and sets the necessary compile features and sources. ```cmake fastgltf_check_modules_support() if (FASTGLTF_ENABLE_CPP_MODULES AND FASTGLTF_SUPPORTS_MODULES AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.28") message(STATUS "fastgltf: Found compiler support for CXX modules") # 3.29.20240416 is what the CMake blog used for talking about import std, so this should roughly be the first # version to support the feature. if (FASTGLTF_USE_STD_MODULE AND CMAKE_VERSION VERSION_LESS "3.29.20240416") message(AUTHOR_WARNING "fastgltf: Using the std module is only natively supported with CMake 3.30 or newer. This might cause compilation errors.") endif () add_library(fastgltf_module) add_library(fastgltf::module ALIAS fastgltf_module) if (FASTGLTF_USE_STD_MODULE) target_compile_features(fastgltf_module PRIVATE cxx_std_23 INTERFACE cxx_std_20) else () target_compile_features(fastgltf_module PUBLIC cxx_std_20) endif () target_sources(fastgltf_module PUBLIC FILE_SET CXX_MODULES BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/fastgltf.ixx ) target_link_libraries(fastgltf_module PRIVATE fastgltf::fastgltf) target_compile_definitions(fastgltf_module PUBLIC "FASTGLTF_USE_STD_MODULE=$" elseif (FASTGLTF_ENABLE_CPP_MODULES) message(WARNING "FASTGLTF_ENABLE_CPP_MODULES is ON but compiler does not support them") endif () ``` -------------------------------- ### Math Library Source: https://github.com/spnda/fastgltf/blob/main/docs/api.rst fastgltf provides a math library for vector, quaternion, and matrix operations relevant to glTF. ```APIDOC ## Math Library fastgltf includes a math library for common operations: * **Vector**: Represents a mathematical vector. * `fastgltf::math::vec`: Class for vector operations. * `fastgltf::math::dot`: Computes the dot product of two vectors. * `fastgltf::math::cross`: Computes the cross product of two vectors. * `fastgltf::math::length`: Computes the length of a vector. * `fastgltf::math::normalize`: Normalizes a vector. * **Quaternion**: Represents a mathematical quaternion. * `fastgltf::math::quat`: Class for quaternion operations. * `fastgltf::math::asMatrix`: Converts a quaternion to a rotation matrix. * **Matrix**: Represents a mathematical matrix. ``` -------------------------------- ### Custom Extras Write Callback for Export Source: https://context7.com/spnda/fastgltf/llms.txt Supply custom `extras` JSON for each exported glTF object using a callback. The callback returns `std::optional` — return `std::nullopt` to omit extras for that object. Requires `fastgltf/core.hpp`. ```cpp #include std::vector nodeNames = { "RootNode", "Mesh_0", "Camera" }; auto extrasWriter = [](std::size_t objectIndex, fastgltf::Category category, void* userPointer) -> std::optional { if (category != fastgltf::Category::Nodes) return std::nullopt; auto* names = static_cast*>(userPointer); if (objectIndex >= names->size()) return std::nullopt; return std::string(R"({\"name\":")") + (*names)[objectIndex] + "\"}"; }; fastgltf::Exporter exporter; exporter.setUserPointer(&nodeNames); exporter.setExtrasWriteCallback(extrasWriter); auto result = exporter.writeGltfJson(asset, fastgltf::ExportOptions::PrettyPrintJson); ``` -------------------------------- ### Custom Extras Write Callback Source: https://context7.com/spnda/fastgltf/llms.txt Supply custom `extras` JSON for each exported glTF object using a callback. The callback returns `std::optional` — return `std::nullopt` to omit extras for that object. ```APIDOC ## Extras Write Callback (`Exporter::setExtrasWriteCallback`) Supply custom `extras` JSON for each exported glTF object using a callback. The callback returns `std::optional` — return `std::nullopt` to omit extras for that object. ```cpp #include std::vector nodeNames = { "RootNode", "Mesh_0", "Camera" }; auto extrasWriter = [](std::size_t objectIndex, fastgltf::Category category, void* userPointer) -> std::optional { if (category != fastgltf::Category::Nodes) return std::nullopt; auto* names = static_cast*>(userPointer); if (objectIndex >= names->size()) return std::nullopt; return std::string(R"({\"name\":")") + (*names)[objectIndex] + ""}"; }; fastgltf::Exporter exporter; exporter.setUserPointer(&nodeNames); exporter.setExtrasWriteCallback(extrasWriter); auto result = exporter.writeGltfJson(asset, fastgltf::ExportOptions::PrettyPrintJson); ``` ``` -------------------------------- ### File Exporter for Disk Writing Source: https://context7.com/spnda/fastgltf/llms.txt Higher-level exporter that writes the glTF JSON (or GLB) plus all referenced buffers and images to disk automatically. Inherits all `setBufferPath`/`setImagePath` configuration from `Exporter`. ```APIDOC ## `fastgltf::FileExporter::writeGltfJson` / `writeGltfBinary` Higher-level exporter that writes the glTF JSON (or GLB) plus all referenced buffers and images to disk automatically. Inherits all `setBufferPath`/`setImagePath` configuration from `Exporter`. ```cpp #include fastgltf::Asset asset; // previously loaded/constructed fastgltf::FileExporter fileExporter; fileExporter.setBufferPath("buffers/"); // Write JSON + external buffer files fastgltf::Error err = fileExporter.writeGltfJson( asset, "export/scene.gltf", fastgltf::ExportOptions::PrettyPrintJson | fastgltf::ExportOptions::ValidateAsset ); if (err != fastgltf::Error::None) { std::cerr << "Export failed: " << fastgltf::getErrorMessage(err) << '\n'; } // Write GLB (single-file, first buffer embedded) fastgltf::Error err2 = fileExporter.writeGltfBinary(asset, "export/scene.glb"); ``` ``` -------------------------------- ### Parser::loadGltfBinary Source: https://context7.com/spnda/fastgltf/llms.txt Loads a glTF asset specifically from binary (GLB) data. This is a specialized version of `loadGltf` for GLB files. ```APIDOC ## `Parser::loadGltfBinary` ### Description Loads a glTF asset specifically from binary (GLB) data. This is a specialized version of `loadGltf` for GLB files. ### Parameters #### `GltfDataGetter` data - The source data for the GLB file. #### `std::filesystem::path` basePath - The base path to resolve relative file paths (e.g., for external buffers or images). #### `fastgltf::Options` options - Options to control the loading process, such as `LoadExternalBuffers`, `LoadExternalImages`, `DecomposeNodeMatrices`, and `GenerateMeshIndices`. #### `fastgltf::Category` category (Optional) - Specifies which categories of glTF data to parse. Defaults to parsing all categories. ### Returns - `Expected`: Contains the parsed `fastgltf::Asset` on success, or a `fastgltf::Error` on failure. ### Example ```cpp // Usage is similar to loadGltf, but ensures binary (GLB) parsing. // auto asset = parser.loadGltfBinary(glbDataGetter, basePath, options); ``` ``` -------------------------------- ### Export Asset to JSON or Binary Source: https://context7.com/spnda/fastgltf/llms.txt Serialize a `fastgltf::Asset` to an in-memory JSON string or binary GLB blob. Does not write to disk. Use `fastgltf::FileExporter` for automatic disk writing. ```APIDOC ## `fastgltf::Exporter::writeGltfJson` / `writeGltfBinary` Serialize a `fastgltf::Asset` to an in-memory JSON string or binary GLB blob. Does not write to disk. Use `fastgltf::FileExporter` for automatic disk writing. ```cpp #include fastgltf::Asset asset; // constructed or previously parsed // ... populate asset ... fastgltf::Exporter exporter; exporter.setBufferPath("buffers/"); // relative path for buffer URIs exporter.setImagePath("images/"); // relative path for image URIs // Export as JSON glTF auto jsonResult = exporter.writeGltfJson(asset, fastgltf::ExportOptions::PrettyPrintJson); if (jsonResult) { const std::string& jsonStr = jsonResult->output; // jsonResult->bufferPaths – optional filesystem paths for each buffer // jsonResult->imagePaths – optional filesystem paths for each image std::ofstream("out/scene.gltf") << jsonStr; } // Export as binary GLB (first buffer ≤ 4 GB is embedded automatically) auto glbResult = exporter.writeGltfBinary(asset); if (glbResult) { const std::vector& blob = glbResult->output; std::ofstream("out/scene.glb", std::ios::binary) .write(reinterpret_cast(blob.data()), blob.size()); } ``` ``` -------------------------------- ### Set C++ Standard to C++17 Source: https://github.com/spnda/fastgltf/blob/main/examples/gl_viewer/CMakeLists.txt Specifies that the 'fastgltf_gl_viewer' target requires C++17 features. This ensures modern C++ constructs can be used. ```cmake target_compile_features(fastgltf_gl_viewer PUBLIC cxx_std_17) ``` -------------------------------- ### Set Compile Definitions Source: https://github.com/spnda/fastgltf/blob/main/CMakeLists.txt This section sets various compile definitions for the fastgltf target. These definitions control optional features and configurations of the library, such as custom small vectors, memory pools, 64-bit float usage, and specific KHR extensions. ```cmake target_compile_definitions(fastgltf PUBLIC "FASTGLTF_USE_CUSTOM_SMALLVECTOR=$" FASTGLTF_DISABLE_CUSTOM_MEMORY_POOL=$" FASTGLTF_USE_64BIT_FLOAT=$" FASTGLTF_ENABLE_KHR_IMPLICIT_SHAPES=$" FASTGLTF_ENABLE_KHR_PHYSICS_RIGID_BODIES=$" ) ```