Chapter 2
Internal Architecture of TinyGltf
Beneath the simplicity of TinyGltf's interface lies a rigorously engineered core designed for reliability, speed, and extensibility. This chapter draws back the curtain on TinyGltf's data representations, memory strategies, and parsing algorithms, revealing the architectural choices that allow it to efficiently process complex glTF scenes with minimal overhead. Readers are invited to navigate the intricate machinery of TinyGltf, gaining practical fluency in debugging, customizing, and optimizing the library for high-performance and demanding production use cases.
2.1 Core Classes and Data Models
The TinyGLTF library encapsulates the glTF 2.0 file format's abstract hierarchical schema through a set of carefully crafted C++ classes and data structures. These core classes mirror glTF's JSON-based specification, enabling efficient data parsing, manipulation, and serialization with minimal overhead. This section delves into the principal classes, enumerations, and models that form the backbone of TinyGLTF, highlighting key design choices related to data ownership, lifetime management, and type conversion.
At the highest level, the Model class represents a fully parsed glTF asset and acts as a container for all associated components, such as buffers, meshes, nodes, materials, and scenes. It is defined roughly as follows:
struct Model { std::vector<Scene> scenes; int defaultScene = -1; std::vector<Node> nodes; std::vector<Mesh> meshes; std::vector<Buffer> buffers; std::vector<BufferView> bufferViews; std::vector<Accessor> accessors; std::vector<Material> materials; std::vector<Image> images; std::vector<Texture> textures; std::vector<Skin> skins; std::vector<Animation> animations; // Additional glTF components... }; Every field within Model is a collection of sub-objects corresponding to glTF entities, preserving the canonical hierarchy. Note that indices rather than direct pointers are employed for cross-references to maintain compactness and simplify serialization.
Data Ownership and Lifetime
TinyGLTF opts for clear ownership semantics: the Model maintains full ownership of all nested data structures. For example, all Buffer objects-representing raw binary blob data potentially loaded from external files-are stored internally within the Model and not duplicated unnecessarily. This approach avoids issues such as dangling references or double frees.
Individuals accessing buffer data via BufferView or Accessor objects do so through integer offsets and lengths, not through owning pointers. Along these lines, BufferView encapsulates a contiguous byte range within a Buffer:
struct BufferView { int buffer = -1; // Index into Model.buffers size_t byteOffset = 0; size_t byteLength = 0; size_t byteStride = 0; // Optional stride in bytes ...