Coverage Report

Created: 2026-01-25 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/assimp/code/AssetLib/glTF2/glTF2Asset.h
Line
Count
Source
1
/*
2
Open Asset Import Library (assimp)
3
----------------------------------------------------------------------
4
5
Copyright (c) 2006-2026, assimp team
6
7
All rights reserved.
8
9
Redistribution and use of this software in source and binary forms,
10
with or without modification, are permitted provided that the
11
following conditions are met:
12
13
* Redistributions of source code must retain the above
14
copyright notice, this list of conditions and the
15
following disclaimer.
16
17
* Redistributions in binary form must reproduce the above
18
copyright notice, this list of conditions and the
19
following disclaimer in the documentation and/or other
20
materials provided with the distribution.
21
22
* Neither the name of the assimp team, nor the names of its
23
contributors may be used to endorse or promote products
24
derived from this software without specific prior
25
written permission of the assimp team.
26
27
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39
----------------------------------------------------------------------
40
*/
41
42
/** @file glTFAsset.h
43
 * Declares a glTF class to handle gltf/glb files
44
 *
45
 * glTF Extensions Support:
46
 *   KHR_materials_pbrSpecularGlossiness full
47
 *   KHR_materials_specular full
48
 *   KHR_materials_unlit full
49
 *   KHR_lights_punctual full
50
 *   KHR_materials_sheen full
51
 *   KHR_materials_clearcoat full
52
 *   KHR_materials_transmission full
53
 *   KHR_materials_volume full
54
 *   KHR_materials_ior full
55
 *   KHR_materials_emissive_strength full
56
 *   KHR_materials_anisotropy full
57
 */
58
#ifndef GLTF2ASSET_H_INC
59
#define GLTF2ASSET_H_INC
60
61
//#if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF2_IMPORTER)
62
63
#include <assimp/Exceptional.h>
64
65
#include <algorithm>
66
#include <list>
67
#include <unordered_map>
68
#include <set>
69
#include <stdexcept>
70
#include <string>
71
#include <vector>
72
73
// clang-format off
74
#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0)
75
#pragma GCC diagnostic push
76
#pragma GCC diagnostic ignored "-Wclass-memaccess"
77
#endif
78
79
#include <rapidjson/document.h>
80
#include <rapidjson/error/en.h>
81
#include <rapidjson/rapidjson.h>
82
#include <rapidjson/schema.h>
83
84
#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0)
85
#   pragma GCC diagnostic pop
86
#endif
87
88
#ifdef ASSIMP_API
89
#   include <assimp/ByteSwapper.h>
90
#   include <assimp/DefaultIOSystem.h>
91
#   include <memory>
92
#else
93
#   include <memory>
94
#   define AI_SWAP4(p)
95
#   define ai_assert
96
#endif
97
98
#if _MSC_VER > 1500 || (defined __GNUC__)
99
#   define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
100
#else
101
#   define gltf_unordered_map map
102
#   define gltf_unordered_set set
103
#endif
104
105
#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
106
#   include <unordered_map>
107
#   include <unordered_set>
108
#   if defined(_MSC_VER) && _MSC_VER <= 1600
109
#       define gltf_unordered_map tr1::unordered_map
110
#       define gltf_unordered_set tr1::unordered_set
111
#   else
112
#       define gltf_unordered_map unordered_map
113
#       define gltf_unordered_set unordered_set
114
#   endif
115
#endif
116
// clang-format on
117
118
#include <assimp/StringUtils.h>
119
#include <assimp/material.h>
120
#include <assimp/GltfMaterial.h>
121
122
#include "AssetLib/glTFCommon/glTFCommon.h"
123
124
namespace glTF2 {
125
126
using glTFCommon::Nullable;
127
using glTFCommon::Ref;
128
using glTFCommon::IOStream;
129
using glTFCommon::IOSystem;
130
using glTFCommon::shared_ptr;
131
132
using rapidjson::Document;
133
using rapidjson::Value;
134
135
class Asset;
136
class AssetWriter;
137
138
struct BufferView; // here due to cross-reference
139
struct Texture;
140
struct Skin;
141
142
using glTFCommon::mat4;
143
using glTFCommon::vec3;
144
using glTFCommon::vec4;
145
146
//! Magic number for GLB files
147
35.0k
#define AI_GLB_MAGIC_NUMBER "glTF"
148
149
#ifdef ASSIMP_API
150
#include <assimp/Compiler/pushpack1.h>
151
#endif
152
153
//! For binary .glb files
154
//! 12-byte header (+ the JSON + a "body" data section)
155
struct GLB_Header {
156
    uint8_t magic[4]; //!< Magic number: "glTF"
157
    uint32_t version; //!< Version number (always 2 as of the last update)
158
    uint32_t length; //!< Total length of the Binary glTF, including header, scene, and body, in bytes
159
} PACK_STRUCT;
160
161
struct GLB_Chunk {
162
    uint32_t chunkLength;
163
    uint32_t chunkType;
164
} PACK_STRUCT;
165
166
#ifdef ASSIMP_API
167
#include <assimp/Compiler/poppack1.h>
168
#endif
169
170
//! Values for the GLB_Chunk::chunkType field
171
enum ChunkType {
172
    ChunkType_JSON = 0x4E4F534A,
173
    ChunkType_BIN = 0x004E4942
174
};
175
176
//! Values for the mesh primitive modes
177
enum PrimitiveMode {
178
    PrimitiveMode_POINTS = 0,
179
    PrimitiveMode_LINES = 1,
180
    PrimitiveMode_LINE_LOOP = 2,
181
    PrimitiveMode_LINE_STRIP = 3,
182
    PrimitiveMode_TRIANGLES = 4,
183
    PrimitiveMode_TRIANGLE_STRIP = 5,
184
    PrimitiveMode_TRIANGLE_FAN = 6
185
};
186
187
//! Values for the Accessor::componentType field
188
enum ComponentType {
189
    ComponentType_BYTE = 5120,
190
    ComponentType_UNSIGNED_BYTE = 5121,
191
    ComponentType_SHORT = 5122,
192
    ComponentType_UNSIGNED_SHORT = 5123,
193
    ComponentType_UNSIGNED_INT = 5125,
194
    ComponentType_FLOAT = 5126
195
};
196
197
26.8k
inline unsigned int ComponentTypeSize(ComponentType t) {
198
26.8k
    switch (t) {
199
46
    case ComponentType_SHORT:
200
4.81k
    case ComponentType_UNSIGNED_SHORT:
201
4.81k
        return 2;
202
203
3.32k
    case ComponentType_UNSIGNED_INT:
204
19.2k
    case ComponentType_FLOAT:
205
19.2k
        return 4;
206
207
2.57k
    case ComponentType_BYTE:
208
2.67k
    case ComponentType_UNSIGNED_BYTE:
209
2.67k
        return 1;
210
24
    default:
211
24
        throw DeadlyImportError("GLTF: Unsupported Component Type ", ai_to_string(t));
212
26.8k
    }
213
26.8k
}
214
215
//! Values for the BufferView::target field
216
enum BufferViewTarget {
217
    BufferViewTarget_NONE = 0,
218
    BufferViewTarget_ARRAY_BUFFER = 34962,
219
    BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
220
};
221
222
//! Values for the Sampler::magFilter field
223
enum class SamplerMagFilter : unsigned int {
224
    UNSET = 0,
225
    SamplerMagFilter_Nearest = 9728,
226
    SamplerMagFilter_Linear = 9729
227
};
228
229
//! Values for the Sampler::minFilter field
230
enum class SamplerMinFilter : unsigned int {
231
    UNSET = 0,
232
    SamplerMinFilter_Nearest = 9728,
233
    SamplerMinFilter_Linear = 9729,
234
    SamplerMinFilter_Nearest_Mipmap_Nearest = 9984,
235
    SamplerMinFilter_Linear_Mipmap_Nearest = 9985,
236
    SamplerMinFilter_Nearest_Mipmap_Linear = 9986,
237
    SamplerMinFilter_Linear_Mipmap_Linear = 9987
238
};
239
240
//! Values for the Sampler::wrapS and Sampler::wrapT field
241
enum class SamplerWrap : unsigned int {
242
    UNSET = 0,
243
    Clamp_To_Edge = 33071,
244
    Mirrored_Repeat = 33648,
245
    Repeat = 10497
246
};
247
248
//! Values for the Texture::format and Texture::internalFormat fields
249
enum TextureFormat {
250
    TextureFormat_ALPHA = 6406,
251
    TextureFormat_RGB = 6407,
252
    TextureFormat_RGBA = 6408,
253
    TextureFormat_LUMINANCE = 6409,
254
    TextureFormat_LUMINANCE_ALPHA = 6410
255
};
256
257
//! Values for the Texture::target field
258
enum TextureTarget {
259
    TextureTarget_TEXTURE_2D = 3553
260
};
261
262
//! Values for the Texture::type field
263
enum TextureType {
264
    TextureType_UNSIGNED_BYTE = 5121,
265
    TextureType_UNSIGNED_SHORT_5_6_5 = 33635,
266
    TextureType_UNSIGNED_SHORT_4_4_4_4 = 32819,
267
    TextureType_UNSIGNED_SHORT_5_5_5_1 = 32820
268
};
269
270
//! Values for the Animation::Target::path field
271
enum AnimationPath {
272
    AnimationPath_TRANSLATION,
273
    AnimationPath_ROTATION,
274
    AnimationPath_SCALE,
275
    AnimationPath_WEIGHTS,
276
};
277
278
//! Values for the Animation::Sampler::interpolation field
279
enum Interpolation {
280
    Interpolation_LINEAR,
281
    Interpolation_STEP,
282
    Interpolation_CUBICSPLINE,
283
};
284
285
//! Values for the Accessor::type field (helper class)
286
class AttribType {
287
public:
288
    enum Value { SCALAR,
289
        VEC2,
290
        VEC3,
291
        VEC4,
292
        MAT2,
293
        MAT3,
294
        MAT4 };
295
296
private:
297
    static const size_t NUM_VALUES = static_cast<size_t>(MAT4) + 1;
298
299
    struct Info {
300
        const char *name;
301
        unsigned int numComponents;
302
    };
303
304
    template <int N>
305
    struct data { static const Info infos[NUM_VALUES]; };
306
307
public:
308
12.1k
    inline static Value FromString(const char *str) {
309
37.7k
        for (size_t i = 0; i < NUM_VALUES; ++i) {
310
37.5k
            if (strcmp(data<0>::infos[i].name, str) == 0) {
311
11.9k
                return static_cast<Value>(i);
312
11.9k
            }
313
37.5k
        }
314
240
        return SCALAR;
315
12.1k
    }
316
317
0
    inline static const char *ToString(Value type) {
318
0
        return data<0>::infos[static_cast<size_t>(type)].name;
319
0
    }
320
321
16.3k
    inline static unsigned int GetNumComponents(Value type) {
322
16.3k
        return data<0>::infos[static_cast<size_t>(type)].numComponents;
323
16.3k
    }
324
};
325
326
// must match the order of the AttribTypeTraits::Value enum!
327
template <int N>
328
const AttribType::Info
329
        AttribType::data<N>::infos[AttribType::NUM_VALUES] = {
330
            { "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 }
331
        };
332
333
334
struct CustomExtension {
335
336
    //
337
    // A struct containing custom extension data added to a glTF2 file
338
    // Has to contain Object, Array, String, Double, Uint64, and Int64 at a minimum
339
    // String, Double, Uint64, and Int64 are stored in the Nullables
340
    // Object and Array are stored in the std::vector
341
    //
342
    std::string name;
343
344
    Nullable<std::string> mStringValue;
345
    Nullable<double> mDoubleValue;
346
    Nullable<uint64_t> mUint64Value;
347
    Nullable<int64_t> mInt64Value;
348
    Nullable<bool> mBoolValue;
349
350
    // std::vector<CustomExtension> handles both Object and Array
351
    Nullable<std::vector<CustomExtension>> mValues;
352
353
21.3k
    operator bool() const {
354
21.3k
        return Size() != 0;
355
21.3k
    }
356
357
21.3k
    size_t Size() const {
358
21.3k
        if (mValues.isPresent) {
359
0
            return mValues.value.size();
360
21.3k
        } else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent || mBoolValue.isPresent) {
361
0
            return 1;
362
0
        }
363
21.3k
        return 0;
364
21.3k
    }
365
366
107k
    CustomExtension() = default;
367
150k
    ~CustomExtension() = default;
368
43.7k
    CustomExtension(const CustomExtension &other) = default;
369
2.39k
    CustomExtension& operator=(const CustomExtension&) = default;
370
};
371
372
//! Represents metadata in an glTF2 object
373
struct Extras {
374
    std::vector<CustomExtension> mValues;
375
376
21.3k
    inline bool HasExtras() const {
377
21.3k
        return !mValues.empty();
378
21.3k
    }
379
};
380
381
//! Base class for all glTF top-level objects
382
struct Object {
383
    int index; //!< The index of this object within its property container
384
    int oIndex; //!< The original index of this object defined in the JSON
385
    std::string id; //!< The globally unique ID used to reference this object
386
    std::string name; //!< The user-defined name of this object
387
388
    CustomExtension customExtensions;
389
    Extras extras;
390
391
    //! Objects marked as special are not exported (used to emulate the binary body buffer)
392
0
    virtual bool IsSpecial() const { return false; }
393
394
60.6k
    virtual ~Object() = default;
395
396
    //! Maps special IDs to another ID, where needed. Subclasses may override it (statically)
397
0
    static const char *TranslateId(Asset & /*r*/, const char *id) { return id; }
398
399
    inline Value *FindString(Value &val, const char *id);
400
    inline Value *FindNumber(Value &val, const char *id);
401
    inline Value *FindUInt(Value &val, const char *id);
402
    inline Value *FindArray(Value &val, const char *id);
403
    inline Value *FindObject(Value &val, const char *id);
404
    inline Value *FindExtension(Value &val, const char *extensionId);
405
406
    inline void ReadExtensions(Value &val);
407
    inline void ReadExtras(Value &val);
408
};
409
410
//
411
// Classes for each glTF top-level object type
412
//
413
414
//! A buffer points to binary geometry, animation, or skins.
415
struct Buffer : public Object {
416
    /********************* Types *********************/
417
public:
418
    enum Type {
419
        Type_arraybuffer,
420
        Type_text
421
    };
422
423
    /// Descriptor of encoded region in "bufferView".
424
    struct SEncodedRegion {
425
        const size_t Offset; ///< Offset from begin of "bufferView" to encoded region, in bytes.
426
        const size_t EncodedData_Length; ///< Size of encoded region, in bytes.
427
        uint8_t *const DecodedData; ///< Cached encoded data.
428
        const size_t DecodedData_Length; ///< Size of decoded region, in bytes.
429
        const std::string ID; ///< ID of the region.
430
431
        /// Constructor.
432
        /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
433
        /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
434
        /// \param [in] pDecodedData - pointer to decoded data array.
435
        /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
436
        /// \param [in] pID - ID of the region.
437
        SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID) :
438
                Offset(pOffset),
439
                EncodedData_Length(pEncodedData_Length),
440
                DecodedData(pDecodedData),
441
                DecodedData_Length(pDecodedData_Length),
442
0
                ID(pID) {}
443
444
        /// Destructor.
445
0
        ~SEncodedRegion() { delete[] DecodedData; }
446
    };
447
448
    /******************* Variables *******************/
449
450
    //std::string uri; //!< The uri of the buffer. Can be a filepath, a data uri, etc. (required)
451
    size_t byteLength; //!< The length of the buffer in bytes. (default: 0)
452
    //std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer")
453
    size_t capacity = 0; //!< The capacity of the buffer in bytes. (default: 0)
454
455
    Type type;
456
457
    /// Pointer to currently active encoded region.
458
    /// Why not decoding all regions at once and not to set one buffer with decoded data?
459
    /// Yes, why not? Even "accessor" point to decoded data. I mean that fields "byteOffset", "byteStride" and "count" has values which describes decoded
460
    /// data array. But only in range of mesh while is active parameters from "compressedData". For another mesh accessors point to decoded data too. But
461
    /// offset is counted for another regions is encoded.
462
    /// Example. You have two meshes. For every of it you have 4 bytes of data. That data compressed to 2 bytes. So, you have buffer with encoded data:
463
    /// M1_E0, M1_E1, M2_E0, M2_E1.
464
    /// After decoding you'll get:
465
    /// M1_D0, M1_D1, M1_D2, M1_D3, M2_D0, M2_D1, M2_D2, M2_D3.
466
    /// "accessors" must to use values that point to decoded data - obviously. So, you'll expect "accessors" like
467
    /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 4, byteLength: 4}
468
    /// but in real life you'll get:
469
    /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 2, byteLength: 4}
470
    /// Yes, accessor of next mesh has offset and length which mean: current mesh data is decoded, all other data is encoded.
471
    /// And when before you start to read data of current mesh (with encoded data of course) you must decode region of "bufferView", after read finished
472
    /// delete encoding mark. And after that you can repeat process: decode data of mesh, read, delete decoded data.
473
    ///
474
    /// Remark. Encoding all data at once is good in world with computers which do not has RAM limitation. So, you must use step by step encoding in
475
    /// exporter and importer. And, thanks to such way, there is no need to load whole file into memory.
476
    SEncodedRegion *EncodedRegion_Current;
477
478
private:
479
    shared_ptr<uint8_t> mData; //!< Pointer to the data
480
    bool mIsSpecial; //!< Set to true for special cases (e.g. the body buffer)
481
482
    /// \var EncodedRegion_List
483
    /// List of encoded regions.
484
    std::list<SEncodedRegion *> EncodedRegion_List;
485
486
    /******************* Functions *******************/
487
488
public:
489
    Buffer();
490
    ~Buffer() override;
491
492
    void Read(Value &obj, Asset &r);
493
494
    bool LoadFromStream(IOStream &stream, size_t length = 0, size_t baseOffset = 0);
495
496
    /// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data.
497
    /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
498
    /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
499
    /// \param [in] pDecodedData - pointer to decoded data array.
500
    /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
501
    /// \param [in] pID - ID of the region.
502
    void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID);
503
504
    /// Select current encoded region by ID. \sa EncodedRegion_Current.
505
    /// \param [in] pID - ID of the region.
506
    void EncodedRegion_SetCurrent(const std::string &pID);
507
508
    /// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions.
509
    /// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed.
510
    /// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced.
511
    /// \param [in] pReplace_Data - pointer to array with new data for buffer.
512
    /// \param [in] pReplace_Count - count of bytes in new data.
513
    /// \return true - if successfully replaced, false if input arguments is out of range.
514
    bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count);
515
    bool ReplaceData_joint(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count);
516
517
    size_t AppendData(uint8_t *data, size_t length);
518
    void Grow(size_t amount);
519
520
9.48k
    uint8_t *GetPointer() { return mData.get(); }
521
522
6.36k
    void MarkAsSpecial() { mIsSpecial = true; }
523
524
0
    bool IsSpecial() const override { return mIsSpecial; }
525
526
0
    std::string GetURI() { return std::string(this->id) + ".bin"; }
527
528
    static const char *TranslateId(Asset &r, const char *id);
529
};
530
531
//! A view into a buffer generally representing a subset of the buffer.
532
struct BufferView : public Object {
533
    Ref<Buffer> buffer; //! The ID of the buffer. (required)
534
    size_t byteOffset; //! The offset into the buffer in bytes. (required)
535
    size_t byteLength; //! The length of the bufferView in bytes. (default: 0)
536
    unsigned int byteStride; //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0)
537
538
    BufferViewTarget target; //! The target that the WebGL buffer should be bound to.
539
540
    void Read(Value &obj, Asset &r);
541
    uint8_t *GetPointerAndTailSize(size_t accOffset, size_t& outTailSize);
542
};
543
544
//! A typed view into a BufferView. A BufferView contains raw binary data.
545
//! An accessor provides a typed view into a BufferView or a subset of a BufferView
546
//! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer.
547
struct Accessor : public Object {
548
    struct Sparse;
549
550
    Ref<BufferView> bufferView; //!< The ID of the bufferView. (required)
551
    size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required)
552
    ComponentType componentType; //!< The datatype of components in the attribute. (required)
553
    size_t count; //!< The number of attributes referenced by this accessor. (required)
554
    AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
555
    std::vector<double> max; //!< Maximum value of each component in this attribute.
556
    std::vector<double> min; //!< Minimum value of each component in this attribute.
557
    std::unique_ptr<Sparse> sparse;
558
    std::unique_ptr<Buffer> decodedBuffer; // Packed decoded data, returned instead of original bufferView if present
559
560
    unsigned int GetNumComponents();
561
    unsigned int GetBytesPerComponent();
562
    unsigned int GetElementSize();
563
564
    inline uint8_t *GetPointer();
565
    inline size_t GetStride();
566
    inline size_t GetMaxByteSize();
567
568
    template <class T>
569
    size_t ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices = nullptr);
570
571
    void WriteData(size_t count, const void *src_buffer, size_t src_stride);
572
    void WriteSparseValues(size_t count, const void *src_data, size_t src_dataStride);
573
    void WriteSparseIndices(size_t count, const void *src_idx, size_t src_idxStride);
574
575
    //! Helper class to iterate the data
576
    class Indexer {
577
        friend struct Accessor;
578
579
        // This field is reported as not used, making it protectd is the easiest way to work around it without going to the bottom of what the problem is:
580
        // ../code/glTF2/glTF2Asset.h:392:19: error: private field 'accessor' is not used [-Werror,-Wunused-private-field]
581
    protected:
582
        Accessor &accessor;
583
584
    private:
585
        uint8_t *data;
586
        size_t elemSize, stride;
587
588
        Indexer(Accessor &acc);
589
590
    public:
591
        //! Accesses the i-th value as defined by the accessor
592
        template <class T>
593
        T GetValue(int i);
594
595
        //! Accesses the i-th value as defined by the accessor
596
44.9k
        inline unsigned int GetUInt(int i) {
597
44.9k
            return GetValue<unsigned int>(i);
598
44.9k
        }
599
600
1.61k
        inline bool IsValid() const {
601
1.61k
            return data != nullptr;
602
1.61k
        }
603
    };
604
605
1.61k
    inline Indexer GetIndexer() {
606
1.61k
        return Indexer(*this);
607
1.61k
    }
608
609
12.7k
    Accessor() = default;
610
    void Read(Value &obj, Asset &r);
611
612
    //sparse
613
    struct Sparse {
614
        size_t count;
615
        ComponentType indicesType;
616
        Ref<BufferView> indices;
617
        size_t indicesByteOffset;
618
        Ref<BufferView> values;
619
        size_t valuesByteOffset;
620
621
        std::vector<uint8_t> data; //!< Actual data, which may be defaulted to an array of zeros or the original data, with the sparse buffer view applied on top of it.
622
623
        void PopulateData(size_t numBytes, const uint8_t *bytes);
624
        void PatchData(unsigned int elementSize);
625
    };
626
};
627
628
struct Camera : public Object {
629
    enum Type {
630
        Perspective,
631
        Orthographic
632
    };
633
634
    Type type;
635
636
    union {
637
        struct {
638
            float aspectRatio; //!<The floating - point aspect ratio of the field of view. (0 = undefined = use the canvas one)
639
            float yfov; //!<The floating - point vertical field of view in radians. (required)
640
            float zfar; //!<The floating - point distance to the far clipping plane. (required)
641
            float znear; //!< The floating - point distance to the near clipping plane. (required)
642
        } perspective;
643
644
        struct {
645
            float xmag; //! The floating-point horizontal magnification of the view. (required)
646
            float ymag; //! The floating-point vertical magnification of the view. (required)
647
            float zfar; //! The floating-point distance to the far clipping plane. (required)
648
            float znear; //! The floating-point distance to the near clipping plane. (required)
649
        } ortographic;
650
    } cameraProperties;
651
652
    Camera() :
653
31
            type(Perspective),
654
31
            cameraProperties() {
655
        // empty
656
31
    }
657
    void Read(Value &obj, Asset &r);
658
};
659
660
//! A light (from KHR_lights_punctual extension)
661
struct Light : public Object {
662
    enum Type {
663
        Directional,
664
        Point,
665
        Spot
666
    };
667
668
    Type type;
669
670
    vec3 color;
671
    float intensity;
672
    Nullable<float> range;
673
674
    float innerConeAngle;
675
    float outerConeAngle;
676
677
0
    Light() = default;
678
    void Read(Value &obj, Asset &r);
679
};
680
681
//! Image data used to create a texture.
682
struct Image : public Object {
683
    std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required)
684
685
    Ref<BufferView> bufferView;
686
687
    std::string mimeType;
688
689
    int width, height;
690
691
private:
692
    std::unique_ptr<uint8_t[]> mData;
693
    size_t mDataLength;
694
695
public:
696
    Image();
697
    void Read(Value &obj, Asset &r);
698
699
631
    inline bool HasData() const { return mDataLength > 0; }
700
701
305
    inline size_t GetDataLength() const { return mDataLength; }
702
703
0
    inline const uint8_t *GetData() const { return mData.get(); }
704
705
    inline uint8_t *StealData();
706
707
    inline void SetData(uint8_t *data, size_t length, Asset &r);
708
};
709
710
const vec4 defaultBaseColor = { 1, 1, 1, 1 };
711
const vec3 defaultEmissiveFactor = { 0, 0, 0 };
712
const vec4 defaultDiffuseFactor = { 1, 1, 1, 1 };
713
const vec3 defaultSpecularFactor = { 1, 1, 1 };
714
const vec3 defaultSpecularColorFactor = { 1, 1, 1 };
715
const vec3 defaultSheenFactor = { 0, 0, 0 };
716
const vec3 defaultAttenuationColor = { 1, 1, 1 };
717
718
struct TextureInfo {
719
    Ref<Texture> texture;
720
    unsigned int index;
721
    unsigned int texCoord = 0;
722
723
    bool textureTransformSupported = false;
724
    struct TextureTransformExt {
725
        float offset[2];
726
        float rotation;
727
        float scale[2];
728
    } TextureTransformExt_t;
729
};
730
731
struct NormalTextureInfo : TextureInfo {
732
    float scale = 1;
733
};
734
735
struct OcclusionTextureInfo : TextureInfo {
736
    float strength = 1;
737
};
738
739
struct PbrMetallicRoughness {
740
    vec4 baseColorFactor;
741
    TextureInfo baseColorTexture;
742
    TextureInfo metallicRoughnessTexture;
743
    float metallicFactor;
744
    float roughnessFactor;
745
};
746
747
struct PbrSpecularGlossiness {
748
    vec4 diffuseFactor;
749
    vec3 specularFactor;
750
    float glossinessFactor;
751
    TextureInfo diffuseTexture;
752
    TextureInfo specularGlossinessTexture;
753
754
4.81k
    PbrSpecularGlossiness() { SetDefaults(); }
755
    void SetDefaults();
756
};
757
758
struct MaterialSpecular {
759
    float specularFactor;
760
    vec3 specularColorFactor;
761
    TextureInfo specularTexture;
762
    TextureInfo specularColorTexture;
763
764
4.81k
    MaterialSpecular() { SetDefaults(); }
765
    void SetDefaults();
766
};
767
768
struct MaterialSheen {
769
    vec3 sheenColorFactor;
770
    float sheenRoughnessFactor;
771
    TextureInfo sheenColorTexture;
772
    TextureInfo sheenRoughnessTexture;
773
774
4.81k
    MaterialSheen() { SetDefaults(); }
775
    void SetDefaults();
776
};
777
778
struct MaterialClearcoat {
779
    float clearcoatFactor = 0.f;
780
    float clearcoatRoughnessFactor = 0.f;
781
    TextureInfo clearcoatTexture;
782
    TextureInfo clearcoatRoughnessTexture;
783
    NormalTextureInfo clearcoatNormalTexture;
784
};
785
786
struct MaterialTransmission {
787
    TextureInfo transmissionTexture;
788
    float transmissionFactor = 0.f;
789
};
790
791
struct MaterialVolume {
792
    float thicknessFactor = 0.f;
793
    TextureInfo thicknessTexture;
794
    float attenuationDistance = 0.f;
795
    vec3 attenuationColor;
796
797
4.81k
    MaterialVolume() { SetDefaults(); }
798
    void SetDefaults();
799
};
800
801
struct MaterialIOR {
802
    float ior = 0.f;
803
804
4.81k
    MaterialIOR() { SetDefaults(); }
805
    void SetDefaults();
806
};
807
808
struct MaterialEmissiveStrength {
809
    float emissiveStrength = 0.f;
810
811
4.81k
    MaterialEmissiveStrength() { SetDefaults(); }
812
    void SetDefaults();
813
};
814
815
struct MaterialAnisotropy {
816
    float anisotropyStrength = 0.f;
817
    float anisotropyRotation = 0.f;
818
    TextureInfo anisotropyTexture;
819
820
4.81k
    MaterialAnisotropy() { SetDefaults(); }
821
    void SetDefaults();
822
};
823
824
//! The material appearance of a primitive.
825
struct Material : public Object {
826
    //PBR metallic roughness properties
827
    PbrMetallicRoughness pbrMetallicRoughness;
828
829
    //other basic material properties
830
    NormalTextureInfo normalTexture;
831
    OcclusionTextureInfo occlusionTexture;
832
    TextureInfo emissiveTexture;
833
    vec3 emissiveFactor;
834
    std::string alphaMode;
835
    float alphaCutoff;
836
    bool doubleSided;
837
838
    //extension: KHR_materials_pbrSpecularGlossiness
839
    Nullable<PbrSpecularGlossiness> pbrSpecularGlossiness;
840
841
    //extension: KHR_materials_specular
842
    Nullable<MaterialSpecular> materialSpecular;
843
844
    //extension: KHR_materials_sheen
845
    Nullable<MaterialSheen> materialSheen;
846
847
    //extension: KHR_materials_clearcoat
848
    Nullable<MaterialClearcoat> materialClearcoat;
849
850
    //extension: KHR_materials_transmission
851
    Nullable<MaterialTransmission> materialTransmission;
852
853
    //extension: KHR_materials_volume
854
    Nullable<MaterialVolume> materialVolume;
855
856
    //extension: KHR_materials_ior
857
    Nullable<MaterialIOR> materialIOR;
858
859
    //extension: KHR_materials_emissive_strength
860
    Nullable<MaterialEmissiveStrength> materialEmissiveStrength;
861
862
    //extension: KHR_materials_anisotropy
863
    Nullable<MaterialAnisotropy> materialAnisotropy;
864
865
    //extension: KHR_materials_unlit
866
    bool unlit;
867
868
4.81k
    Material() { SetDefaults(); }
869
    void Read(Value &obj, Asset &r);
870
    void SetDefaults();
871
872
    inline void SetTextureProperties(Asset &r, Value *prop, TextureInfo &out);
873
    inline void ReadTextureProperty(Asset &r, Value &vals, const char *propName, TextureInfo &out);
874
    inline void ReadTextureProperty(Asset &r, Value &vals, const char *propName, NormalTextureInfo &out);
875
    inline void ReadTextureProperty(Asset &r, Value &vals, const char *propName, OcclusionTextureInfo &out);
876
};
877
878
//! A set of primitives to be rendered. A node can contain one or more meshes. A node's transform places the mesh in the scene.
879
struct Mesh : public Object {
880
    using AccessorList = std::vector<Ref<Accessor>>;
881
882
    struct Primitive {
883
        PrimitiveMode mode;
884
885
        struct Attributes {
886
            AccessorList position, normal, tangent, texcoord, color, joint, jointmatrix, weight;
887
        } attributes;
888
889
        Ref<Accessor> indices;
890
891
        Ref<Material> material;
892
893
        struct Target {
894
            AccessorList position, normal, tangent;
895
        };
896
        std::vector<Target> targets;
897
898
        // extension: FB_ngon_encoding
899
        bool ngonEncoded;
900
901
3.03k
        Primitive(): ngonEncoded(false) {}
902
    };
903
904
    std::vector<Primitive> primitives;
905
906
    std::vector<float> weights;
907
    std::vector<std::string> targetNames;
908
909
3.04k
    Mesh() = default;
910
911
    /// Get mesh data from JSON-object and place them to root asset.
912
    /// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
913
    /// \param [out] pAsset_Root - reference to root asset where data will be stored.
914
    void Read(Value &pJSON_Object, Asset &pAsset_Root);
915
};
916
917
struct Node : public Object {
918
    std::vector<Ref<Node>> children;
919
    std::vector<Ref<Mesh>> meshes;
920
921
    Nullable<mat4> matrix;
922
    Nullable<vec3> translation;
923
    Nullable<vec4> rotation;
924
    Nullable<vec3> scale;
925
926
    Ref<Camera> camera;
927
    Ref<Light> light;
928
929
    std::vector<Ref<Node>> skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy.
930
    Ref<Skin> skin; //!< The ID of the skin referenced by this node.
931
    std::string jointName; //!< Name used when this node is a joint in a skin.
932
933
    Ref<Node> parent; //!< This is not part of the glTF specification. Used as a helper.
934
935
17.2k
    Node() = default;
936
    void Read(Value &obj, Asset &r);
937
};
938
939
struct Program : public Object {
940
    Program() = default;
941
    void Read(Value &obj, Asset &r);
942
};
943
944
struct Sampler : public Object {
945
    SamplerMagFilter magFilter; //!< The texture magnification filter.
946
    SamplerMinFilter minFilter; //!< The texture minification filter.
947
    SamplerWrap wrapS; //!< The texture wrapping in the S direction.
948
    SamplerWrap wrapT; //!< The texture wrapping in the T direction.
949
950
351
    Sampler() { SetDefaults(); }
951
    void Read(Value &obj, Asset &r);
952
    void SetDefaults();
953
};
954
955
struct Scene : public Object {
956
    std::string name;
957
    std::vector<Ref<Node>> nodes;
958
959
2.85k
    Scene() = default;
960
    void Read(Value &obj, Asset &r);
961
};
962
963
struct Shader : public Object {
964
    Shader() = default;
965
    void Read(Value &obj, Asset &r);
966
};
967
968
struct Skin : public Object {
969
    Nullable<mat4> bindShapeMatrix; //!< Floating-point 4x4 transformation matrix stored in column-major order.
970
    Ref<Accessor> inverseBindMatrices; //!< The ID of the accessor containing the floating-point 4x4 inverse-bind matrices.
971
    std::vector<Ref<Node>> jointNames; //!< Joint names of the joints (nodes with a jointName property) in this skin.
972
    std::string name; //!< The user-defined name of this object.
973
974
616
    Skin() = default;
975
    void Read(Value &obj, Asset &r);
976
};
977
978
//! A texture and its sampler.
979
struct Texture : public Object {
980
    Ref<Sampler> sampler; //!< The ID of the sampler used by this texture. (required)
981
    Ref<Image> source; //!< The ID of the image used by this texture. (required)
982
983
    //TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA)
984
    //TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
985
986
    //TextureTarget target; //!< The target that the WebGL texture should be bound to. (default: TextureTarget_TEXTURE_2D)
987
    //TextureType type; //!< Texel datatype. (default: TextureType_UNSIGNED_BYTE)
988
989
382
    Texture() = default;
990
    void Read(Value &obj, Asset &r);
991
};
992
993
struct Animation : public Object {
994
    struct Sampler {
995
126
        Sampler() = default;
996
997
        Ref<Accessor> input; //!< Accessor reference to the buffer storing the key-frame times.
998
        Ref<Accessor> output; //!< Accessor reference to the buffer storing the key-frame values.
999
        Interpolation interpolation{Interpolation_LINEAR}; //!< Type of interpolation algorithm to use between key-frames.
1000
    };
1001
1002
    struct Target {
1003
119
        Target() = default;
1004
1005
        Ref<Node> node; //!< The node to animate.
1006
        AnimationPath path{AnimationPath_TRANSLATION}; //!< The property of the node to animate.
1007
    };
1008
1009
    struct Channel {
1010
119
        Channel() = default;
1011
1012
        int sampler{-1}; //!< The sampler index containing the animation data.
1013
        Target target; //!< The node and property to animate.
1014
    };
1015
1016
    std::vector<Sampler> samplers; //!< All the key-frame data for this animation.
1017
    std::vector<Channel> channels; //!< Data to connect nodes to key-frames.
1018
1019
153
    Animation() = default;
1020
    void Read(Value &obj, Asset &r);
1021
};
1022
1023
//! Base class for LazyDict that acts as an interface
1024
class LazyDictBase {
1025
public:
1026
200k
    virtual ~LazyDictBase() = default;
1027
1028
    virtual void AttachToDocument(Document &doc) = 0;
1029
    virtual void DetachFromDocument() = 0;
1030
1031
#if !defined(ASSIMP_BUILD_NO_EXPORT)
1032
    virtual void WriteObjects(AssetWriter &writer) = 0;
1033
#endif
1034
};
1035
1036
template <class T>
1037
class LazyDict;
1038
1039
//! (Implemented in glTFAssetWriter.h)
1040
template <class T>
1041
void WriteLazyDict(LazyDict<T> &d, AssetWriter &w);
1042
1043
//! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID
1044
//! It is the owner the loaded objects, so when it is destroyed it also deletes them
1045
template <class T>
1046
class LazyDict : public LazyDictBase {
1047
    friend class Asset;
1048
    friend class AssetWriter;
1049
1050
    using Dict = typename std::gltf_unordered_map<unsigned int, unsigned int>;
1051
    using IdDict = typename std::gltf_unordered_map<std::string, unsigned int>;
1052
1053
    std::vector<T *> mObjs; //! The read objects
1054
    Dict mObjsByOIndex; //! The read objects accessible by original index
1055
    IdDict mObjsById; //! The read objects accessible by id
1056
    const char *mDictId; //! ID of the dictionary object
1057
    const char *mExtId; //! ID of the extension defining the dictionary
1058
    Value *mDict; //! JSON dictionary object
1059
    Asset &mAsset; //! The asset instance
1060
1061
    std::gltf_unordered_set<unsigned int> mRecursiveReferenceCheck; //! Used by Retrieve to prevent recursive lookups
1062
1063
    void AttachToDocument(Document &doc);
1064
    void DetachFromDocument();
1065
1066
#if !defined(ASSIMP_BUILD_NO_EXPORT)
1067
0
    void WriteObjects(AssetWriter &writer) { WriteLazyDict<T>(*this, writer); }
Unexecuted instantiation: glTF2::LazyDict<glTF2::Accessor>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Animation>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Buffer>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::BufferView>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Camera>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Light>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Image>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Material>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Mesh>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Node>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Sampler>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Scene>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Skin>::WriteObjects(glTF2::AssetWriter&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Texture>::WriteObjects(glTF2::AssetWriter&)
1068
#endif
1069
1070
    Ref<T> Add(T *obj);
1071
1072
public:
1073
    LazyDict(Asset &asset, const char *dictId, const char *extId = nullptr);
1074
    ~LazyDict();
1075
1076
    Ref<T> Retrieve(unsigned int i);
1077
1078
    Ref<T> Get(unsigned int i);
1079
    Ref<T> Get(const char *id);
1080
1081
    Ref<T> Create(const char *id);
1082
0
    Ref<T> Create(const std::string &id) { return Create(id.c_str()); }
Unexecuted instantiation: glTF2::LazyDict<glTF2::BufferView>::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Accessor>::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Texture>::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Image>::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Material>::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Buffer>::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Skin>::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Mesh>::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Node>::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Scene>::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Animation>::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
1083
1084
    unsigned int Remove(const char *id);
1085
1086
27.6k
    inline unsigned int Size() const { return unsigned(mObjs.size()); }
glTF2::LazyDict<glTF2::Material>::Size() const
Line
Count
Source
1086
2.34k
    inline unsigned int Size() const { return unsigned(mObjs.size()); }
glTF2::LazyDict<glTF2::Mesh>::Size() const
Line
Count
Source
1086
13.7k
    inline unsigned int Size() const { return unsigned(mObjs.size()); }
glTF2::LazyDict<glTF2::Camera>::Size() const
Line
Count
Source
1086
2.02k
    inline unsigned int Size() const { return unsigned(mObjs.size()); }
glTF2::LazyDict<glTF2::Light>::Size() const
Line
Count
Source
1086
2.00k
    inline unsigned int Size() const { return unsigned(mObjs.size()); }
glTF2::LazyDict<glTF2::Animation>::Size() const
Line
Count
Source
1086
1.90k
    inline unsigned int Size() const { return unsigned(mObjs.size()); }
glTF2::LazyDict<glTF2::Image>::Size() const
Line
Count
Source
1086
5.62k
    inline unsigned int Size() const { return unsigned(mObjs.size()); }
Unexecuted instantiation: glTF2::LazyDict<glTF2::Buffer>::Size() const
Unexecuted instantiation: glTF2::LazyDict<glTF2::Node>::Size() const
1087
1088
7.74k
    inline T &operator[](size_t i) { return *mObjs[i]; }
glTF2::LazyDict<glTF2::Material>::operator[](unsigned long)
Line
Count
Source
1088
2.17k
    inline T &operator[](size_t i) { return *mObjs[i]; }
glTF2::LazyDict<glTF2::Mesh>::operator[](unsigned long)
Line
Count
Source
1088
4.75k
    inline T &operator[](size_t i) { return *mObjs[i]; }
glTF2::LazyDict<glTF2::Camera>::operator[](unsigned long)
Line
Count
Source
1088
21
    inline T &operator[](size_t i) { return *mObjs[i]; }
Unexecuted instantiation: glTF2::LazyDict<glTF2::Light>::operator[](unsigned long)
glTF2::LazyDict<glTF2::Animation>::operator[](unsigned long)
Line
Count
Source
1088
97
    inline T &operator[](size_t i) { return *mObjs[i]; }
glTF2::LazyDict<glTF2::Node>::operator[](unsigned long)
Line
Count
Source
1088
72
    inline T &operator[](size_t i) { return *mObjs[i]; }
glTF2::LazyDict<glTF2::Image>::operator[](unsigned long)
Line
Count
Source
1088
631
    inline T &operator[](size_t i) { return *mObjs[i]; }
1089
};
1090
1091
struct AssetMetadata {
1092
    std::string copyright; //!< A copyright message suitable for display to credit the content creator.
1093
    std::string generator; //!< Tool that generated this glTF model.Useful for debugging.
1094
1095
    struct {
1096
        std::string api; //!< Specifies the target rendering API (default: "WebGL")
1097
        std::string version; //!< Specifies the target rendering API (default: "1.0.3")
1098
    } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {})
1099
1100
    std::string version; //!< The glTF format version
1101
1102
    void Read(Document &doc);
1103
1104
14.3k
    AssetMetadata() = default;
1105
};
1106
1107
//
1108
// glTF Asset class
1109
//
1110
1111
//! Root object for a glTF asset
1112
class Asset {
1113
    using IdMap = std::gltf_unordered_map<std::string, int>;
1114
1115
    template <class T>
1116
    friend class LazyDict;
1117
    friend struct Buffer; // To access OpenFile
1118
    friend class AssetWriter;
1119
1120
    std::vector<LazyDictBase *> mDicts;
1121
1122
public:
1123
    //! Keeps info about the enabled extensions
1124
    struct Extensions {
1125
        bool KHR_materials_pbrSpecularGlossiness{false};
1126
        bool KHR_materials_specular{false};
1127
        bool KHR_materials_unlit{false};
1128
        bool KHR_lights_punctual{false};
1129
        bool KHR_texture_transform{false};
1130
        bool KHR_materials_sheen{false};
1131
        bool KHR_materials_clearcoat{false};
1132
        bool KHR_materials_transmission{false};
1133
        bool KHR_materials_volume{false};
1134
        bool KHR_materials_ior{false};
1135
        bool KHR_materials_emissive_strength{false};
1136
        bool KHR_materials_anisotropy{false};
1137
        bool KHR_draco_mesh_compression{false};
1138
        bool FB_ngon_encoding{false};
1139
        bool KHR_texture_basisu{false};
1140
        bool EXT_texture_webp{false};
1141
1142
14.3k
        Extensions() = default;
1143
        ~Extensions() = default;
1144
    } extensionsUsed;
1145
1146
    //! Keeps info about the required extensions
1147
    struct RequiredExtensions {
1148
        bool KHR_draco_mesh_compression{false};
1149
        bool KHR_texture_basisu{false};
1150
        bool EXT_texture_webp{false};
1151
1152
14.3k
        RequiredExtensions() = default;
1153
    } extensionsRequired;
1154
1155
    AssetMetadata asset;
1156
    Value *extras;
1157
1158
    // Dictionaries for each type of object
1159
1160
    LazyDict<Accessor> accessors;
1161
    LazyDict<Animation> animations;
1162
    LazyDict<Buffer> buffers;
1163
    LazyDict<BufferView> bufferViews;
1164
    LazyDict<Camera> cameras;
1165
    LazyDict<Light> lights;
1166
    LazyDict<Image> images;
1167
    LazyDict<Material> materials;
1168
    LazyDict<Mesh> meshes;
1169
    LazyDict<Node> nodes;
1170
    LazyDict<Sampler> samplers;
1171
    LazyDict<Scene> scenes;
1172
    LazyDict<Skin> skins;
1173
    LazyDict<Texture> textures;
1174
1175
    Ref<Scene> scene;
1176
1177
public:
1178
    Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) :
1179
14.3k
            mDicts(),
1180
14.3k
            extensionsUsed(),
1181
14.3k
            extensionsRequired(),
1182
14.3k
            asset(),
1183
14.3k
            extras(nullptr),
1184
14.3k
            accessors(*this, "accessors"),
1185
14.3k
            animations(*this, "animations"),
1186
14.3k
            buffers(*this, "buffers"),
1187
14.3k
            bufferViews(*this, "bufferViews"),
1188
14.3k
            cameras(*this, "cameras"),
1189
14.3k
            lights(*this, "lights", "KHR_lights_punctual"),
1190
14.3k
            images(*this, "images"),
1191
14.3k
            materials(*this, "materials"),
1192
14.3k
            meshes(*this, "meshes"),
1193
14.3k
            nodes(*this, "nodes"),
1194
14.3k
            samplers(*this, "samplers"),
1195
14.3k
            scenes(*this, "scenes"),
1196
14.3k
            skins(*this, "skins"),
1197
14.3k
            textures(*this, "textures") ,
1198
14.3k
            mIOSystem(io),
1199
14.3k
            mSchemaDocumentProvider(schemaDocumentProvider) {
1200
        // empty
1201
14.3k
    }
1202
1203
    //! Main function
1204
    void Load(const std::string &file, bool isBinary = false);
1205
1206
    //! Parse the AssetMetadata and check that the version is 2.
1207
    bool CanRead(const std::string &pFile, bool isBinary = false);
1208
1209
    //! Enables binary encoding on the asset
1210
    void SetAsBinary();
1211
1212
    //! Search for an available name, starting from the given strings
1213
    std::string FindUniqueID(const std::string &str, const char *suffix);
1214
1215
0
    Ref<Buffer> GetBodyBuffer() { return mBodyBuffer; }
1216
1217
    Asset(Asset &) = delete;
1218
    Asset &operator=(const Asset &) = delete;
1219
1220
private:
1221
    void ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneData);
1222
1223
    /// Obtain a JSON document from the stream.
1224
    /// \param second argument is a buffer used by the document. It must be kept
1225
    /// alive while the document is in use.
1226
    Document ReadDocument(IOStream& stream, bool isBinary, std::vector<char>& sceneData);
1227
1228
    void ReadExtensionsUsed(Document &doc);
1229
    void ReadExtensionsRequired(Document &doc);
1230
1231
    IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false);
1232
1233
private:
1234
    IOSystem *mIOSystem;
1235
    rapidjson::IRemoteSchemaDocumentProvider *mSchemaDocumentProvider;
1236
    std::string mCurrentAssetDir;
1237
    size_t mSceneLength;
1238
    size_t mBodyOffset;
1239
    size_t mBodyLength;
1240
    Ref<Buffer> mBodyBuffer;
1241
    std::unordered_map<std::string, int> lastUsedID;
1242
};
1243
1244
183
inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {
1245
183
    std::string context = id;
1246
183
    if (!name.empty()) {
1247
25
        context += " (\"" + name + "\")";
1248
25
    }
1249
183
    return context;
1250
183
}
1251
1252
} // namespace glTF2
1253
1254
// Include the implementation of the methods
1255
#include "glTF2Asset.inl"
1256
1257
//#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
1258
1259
#endif // GLTF2ASSET_H_INC