Coverage Report

Created: 2025-12-05 06:25

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-2025, 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
282
#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
0
inline unsigned int ComponentTypeSize(ComponentType t) {
198
0
    switch (t) {
199
0
    case ComponentType_SHORT:
200
0
    case ComponentType_UNSIGNED_SHORT:
201
0
        return 2;
202
203
0
    case ComponentType_UNSIGNED_INT:
204
0
    case ComponentType_FLOAT:
205
0
        return 4;
206
207
0
    case ComponentType_BYTE:
208
0
    case ComponentType_UNSIGNED_BYTE:
209
0
        return 1;
210
0
    default:
211
0
        throw DeadlyImportError("GLTF: Unsupported Component Type ", ai_to_string(t));
212
0
    }
213
0
}
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
0
    inline static Value FromString(const char *str) {
309
0
        for (size_t i = 0; i < NUM_VALUES; ++i) {
310
0
            if (strcmp(data<0>::infos[i].name, str) == 0) {
311
0
                return static_cast<Value>(i);
312
0
            }
313
0
        }
314
0
        return SCALAR;
315
0
    }
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
0
    inline static unsigned int GetNumComponents(Value type) {
322
0
        return data<0>::infos[static_cast<size_t>(type)].numComponents;
323
0
    }
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
0
    operator bool() const {
354
0
        return Size() != 0;
355
0
    }
356
357
0
    size_t Size() const {
358
0
        if (mValues.isPresent) {
359
0
            return mValues.value.size();
360
0
        } else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent || mBoolValue.isPresent) {
361
0
            return 1;
362
0
        }
363
0
        return 0;
364
0
    }
365
366
0
    CustomExtension() = default;
367
368
0
    ~CustomExtension() = default;
369
370
0
    CustomExtension(const CustomExtension &other) = default;
371
372
0
    CustomExtension& operator=(const CustomExtension&) = default;
373
};
374
375
//! Represents metadata in an glTF2 object
376
struct Extras {
377
    std::vector<CustomExtension> mValues;
378
379
0
    inline bool HasExtras() const {
380
0
        return !mValues.empty();
381
0
    }
382
};
383
384
//! Base class for all glTF top-level objects
385
struct Object {
386
    int index; //!< The index of this object within its property container
387
    int oIndex; //!< The original index of this object defined in the JSON
388
    std::string id; //!< The globally unique ID used to reference this object
389
    std::string name; //!< The user-defined name of this object
390
391
    CustomExtension customExtensions;
392
    Extras extras;
393
394
    //! Objects marked as special are not exported (used to emulate the binary body buffer)
395
0
    virtual bool IsSpecial() const { return false; }
396
397
0
    virtual ~Object() = default;
398
399
    //! Maps special IDs to another ID, where needed. Subclasses may override it (statically)
400
0
    static const char *TranslateId(Asset & /*r*/, const char *id) { return id; }
401
402
    inline Value *FindString(Value &val, const char *id);
403
    inline Value *FindNumber(Value &val, const char *id);
404
    inline Value *FindUInt(Value &val, const char *id);
405
    inline Value *FindArray(Value &val, const char *id);
406
    inline Value *FindObject(Value &val, const char *id);
407
    inline Value *FindExtension(Value &val, const char *extensionId);
408
409
    inline void ReadExtensions(Value &val);
410
    inline void ReadExtras(Value &val);
411
};
412
413
//
414
// Classes for each glTF top-level object type
415
//
416
417
//! A buffer points to binary geometry, animation, or skins.
418
struct Buffer : public Object {
419
    /********************* Types *********************/
420
public:
421
    enum Type {
422
        Type_arraybuffer,
423
        Type_text
424
    };
425
426
    /// \struct SEncodedRegion
427
    /// Descriptor of encoded region in "bufferView".
428
    struct SEncodedRegion {
429
        const size_t Offset; ///< Offset from begin of "bufferView" to encoded region, in bytes.
430
        const size_t EncodedData_Length; ///< Size of encoded region, in bytes.
431
        uint8_t *const DecodedData; ///< Cached encoded data.
432
        const size_t DecodedData_Length; ///< Size of decoded region, in bytes.
433
        const std::string ID; ///< ID of the region.
434
435
        /// \fn SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID)
436
        /// Constructor.
437
        /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
438
        /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
439
        /// \param [in] pDecodedData - pointer to decoded data array.
440
        /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
441
        /// \param [in] pID - ID of the region.
442
        SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID) :
443
                Offset(pOffset),
444
                EncodedData_Length(pEncodedData_Length),
445
                DecodedData(pDecodedData),
446
                DecodedData_Length(pDecodedData_Length),
447
0
                ID(pID) {}
448
449
        /// \fn ~SEncodedRegion()
450
        /// Destructor.
451
0
        ~SEncodedRegion() { delete[] DecodedData; }
452
    };
453
454
    /******************* Variables *******************/
455
456
    //std::string uri; //!< The uri of the buffer. Can be a filepath, a data uri, etc. (required)
457
    size_t byteLength; //!< The length of the buffer in bytes. (default: 0)
458
    //std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer")
459
    size_t capacity = 0; //!< The capacity of the buffer in bytes. (default: 0)
460
461
    Type type;
462
463
    /// \var EncodedRegion_Current
464
    /// Pointer to currently active encoded region.
465
    /// Why not decoding all regions at once and not to set one buffer with decoded data?
466
    /// Yes, why not? Even "accessor" point to decoded data. I mean that fields "byteOffset", "byteStride" and "count" has values which describes decoded
467
    /// data array. But only in range of mesh while is active parameters from "compressedData". For another mesh accessors point to decoded data too. But
468
    /// offset is counted for another regions is encoded.
469
    /// 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:
470
    /// M1_E0, M1_E1, M2_E0, M2_E1.
471
    /// After decoding you'll get:
472
    /// M1_D0, M1_D1, M1_D2, M1_D3, M2_D0, M2_D1, M2_D2, M2_D3.
473
    /// "accessors" must to use values that point to decoded data - obviously. So, you'll expect "accessors" like
474
    /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 4, byteLength: 4}
475
    /// but in real life you'll get:
476
    /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 2, byteLength: 4}
477
    /// Yes, accessor of next mesh has offset and length which mean: current mesh data is decoded, all other data is encoded.
478
    /// 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
479
    /// delete encoding mark. And after that you can repeat process: decode data of mesh, read, delete decoded data.
480
    ///
481
    /// 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
482
    /// exporter and importer. And, thanks to such way, there is no need to load whole file into memory.
483
    SEncodedRegion *EncodedRegion_Current;
484
485
private:
486
    shared_ptr<uint8_t> mData; //!< Pointer to the data
487
    bool mIsSpecial; //!< Set to true for special cases (e.g. the body buffer)
488
489
    /// \var EncodedRegion_List
490
    /// List of encoded regions.
491
    std::list<SEncodedRegion *> EncodedRegion_List;
492
493
    /******************* Functions *******************/
494
495
public:
496
    Buffer();
497
    ~Buffer() override;
498
499
    void Read(Value &obj, Asset &r);
500
501
    bool LoadFromStream(IOStream &stream, size_t length = 0, size_t baseOffset = 0);
502
503
    /// \fn void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID)
504
    /// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data.
505
    /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
506
    /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
507
    /// \param [in] pDecodedData - pointer to decoded data array.
508
    /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
509
    /// \param [in] pID - ID of the region.
510
    void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID);
511
512
    /// \fn void EncodedRegion_SetCurrent(const std::string& pID)
513
    /// Select current encoded region by ID. \sa EncodedRegion_Current.
514
    /// \param [in] pID - ID of the region.
515
    void EncodedRegion_SetCurrent(const std::string &pID);
516
517
    /// \fn bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count)
518
    /// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions.
519
    /// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed.
520
    /// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced.
521
    /// \param [in] pReplace_Data - pointer to array with new data for buffer.
522
    /// \param [in] pReplace_Count - count of bytes in new data.
523
    /// \return true - if successfully replaced, false if input arguments is out of range.
524
    bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count);
525
    bool ReplaceData_joint(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count);
526
527
    size_t AppendData(uint8_t *data, size_t length);
528
    void Grow(size_t amount);
529
530
0
    uint8_t *GetPointer() { return mData.get(); }
531
532
0
    void MarkAsSpecial() { mIsSpecial = true; }
533
534
0
    bool IsSpecial() const override { return mIsSpecial; }
535
536
0
    std::string GetURI() { return std::string(this->id) + ".bin"; }
537
538
    static const char *TranslateId(Asset &r, const char *id);
539
};
540
541
//! A view into a buffer generally representing a subset of the buffer.
542
struct BufferView : public Object {
543
    Ref<Buffer> buffer; //! The ID of the buffer. (required)
544
    size_t byteOffset; //! The offset into the buffer in bytes. (required)
545
    size_t byteLength; //! The length of the bufferView in bytes. (default: 0)
546
    unsigned int byteStride; //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0)
547
548
    BufferViewTarget target; //! The target that the WebGL buffer should be bound to.
549
550
    void Read(Value &obj, Asset &r);
551
    uint8_t *GetPointerAndTailSize(size_t accOffset, size_t& outTailSize);
552
};
553
554
//! A typed view into a BufferView. A BufferView contains raw binary data.
555
//! An accessor provides a typed view into a BufferView or a subset of a BufferView
556
//! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer.
557
struct Accessor : public Object {
558
    struct Sparse;
559
560
    Ref<BufferView> bufferView; //!< The ID of the bufferView. (required)
561
    size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required)
562
    ComponentType componentType; //!< The datatype of components in the attribute. (required)
563
    size_t count; //!< The number of attributes referenced by this accessor. (required)
564
    AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
565
    std::vector<double> max; //!< Maximum value of each component in this attribute.
566
    std::vector<double> min; //!< Minimum value of each component in this attribute.
567
    std::unique_ptr<Sparse> sparse;
568
    std::unique_ptr<Buffer> decodedBuffer; // Packed decoded data, returned instead of original bufferView if present
569
570
    unsigned int GetNumComponents();
571
    unsigned int GetBytesPerComponent();
572
    unsigned int GetElementSize();
573
574
    inline uint8_t *GetPointer();
575
    inline size_t GetStride();
576
    inline size_t GetMaxByteSize();
577
578
    template <class T>
579
    size_t ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices = nullptr);
580
581
    void WriteData(size_t count, const void *src_buffer, size_t src_stride);
582
    void WriteSparseValues(size_t count, const void *src_data, size_t src_dataStride);
583
    void WriteSparseIndices(size_t count, const void *src_idx, size_t src_idxStride);
584
585
    //! Helper class to iterate the data
586
    class Indexer {
587
        friend struct Accessor;
588
589
        // 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:
590
        // ../code/glTF2/glTF2Asset.h:392:19: error: private field 'accessor' is not used [-Werror,-Wunused-private-field]
591
    protected:
592
        Accessor &accessor;
593
594
    private:
595
        uint8_t *data;
596
        size_t elemSize, stride;
597
598
        Indexer(Accessor &acc);
599
600
    public:
601
        //! Accesses the i-th value as defined by the accessor
602
        template <class T>
603
        T GetValue(int i);
604
605
        //! Accesses the i-th value as defined by the accessor
606
0
        inline unsigned int GetUInt(int i) {
607
0
            return GetValue<unsigned int>(i);
608
0
        }
609
610
0
        inline bool IsValid() const {
611
0
            return data != nullptr;
612
0
        }
613
    };
614
615
0
    inline Indexer GetIndexer() {
616
0
        return Indexer(*this);
617
0
    }
618
619
0
    Accessor() = default;
620
    void Read(Value &obj, Asset &r);
621
622
    //sparse
623
    struct Sparse {
624
        size_t count;
625
        ComponentType indicesType;
626
        Ref<BufferView> indices;
627
        size_t indicesByteOffset;
628
        Ref<BufferView> values;
629
        size_t valuesByteOffset;
630
631
        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.
632
633
        void PopulateData(size_t numBytes, const uint8_t *bytes);
634
        void PatchData(unsigned int elementSize);
635
    };
636
};
637
638
struct Camera : public Object {
639
    enum Type {
640
        Perspective,
641
        Orthographic
642
    };
643
644
    Type type;
645
646
    union {
647
        struct {
648
            float aspectRatio; //!<The floating - point aspect ratio of the field of view. (0 = undefined = use the canvas one)
649
            float yfov; //!<The floating - point vertical field of view in radians. (required)
650
            float zfar; //!<The floating - point distance to the far clipping plane. (required)
651
            float znear; //!< The floating - point distance to the near clipping plane. (required)
652
        } perspective;
653
654
        struct {
655
            float xmag; //! The floating-point horizontal magnification of the view. (required)
656
            float ymag; //! The floating-point vertical magnification of the view. (required)
657
            float zfar; //! The floating-point distance to the far clipping plane. (required)
658
            float znear; //! The floating-point distance to the near clipping plane. (required)
659
        } ortographic;
660
    } cameraProperties;
661
662
    Camera() :
663
0
            type(Perspective),
664
0
            cameraProperties() {
665
        // empty
666
0
    }
667
    void Read(Value &obj, Asset &r);
668
};
669
670
//! A light (from KHR_lights_punctual extension)
671
struct Light : public Object {
672
    enum Type {
673
        Directional,
674
        Point,
675
        Spot
676
    };
677
678
    Type type;
679
680
    vec3 color;
681
    float intensity;
682
    Nullable<float> range;
683
684
    float innerConeAngle;
685
    float outerConeAngle;
686
687
0
    Light() = default;
688
    void Read(Value &obj, Asset &r);
689
};
690
691
//! Image data used to create a texture.
692
struct Image : public Object {
693
    std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required)
694
695
    Ref<BufferView> bufferView;
696
697
    std::string mimeType;
698
699
    int width, height;
700
701
private:
702
    std::unique_ptr<uint8_t[]> mData;
703
    size_t mDataLength;
704
705
public:
706
    Image();
707
    void Read(Value &obj, Asset &r);
708
709
0
    inline bool HasData() const { return mDataLength > 0; }
710
711
0
    inline size_t GetDataLength() const { return mDataLength; }
712
713
0
    inline const uint8_t *GetData() const { return mData.get(); }
714
715
    inline uint8_t *StealData();
716
717
    inline void SetData(uint8_t *data, size_t length, Asset &r);
718
};
719
720
const vec4 defaultBaseColor = { 1, 1, 1, 1 };
721
const vec3 defaultEmissiveFactor = { 0, 0, 0 };
722
const vec4 defaultDiffuseFactor = { 1, 1, 1, 1 };
723
const vec3 defaultSpecularFactor = { 1, 1, 1 };
724
const vec3 defaultSpecularColorFactor = { 1, 1, 1 };
725
const vec3 defaultSheenFactor = { 0, 0, 0 };
726
const vec3 defaultAttenuationColor = { 1, 1, 1 };
727
728
struct TextureInfo {
729
    Ref<Texture> texture;
730
    unsigned int index;
731
    unsigned int texCoord = 0;
732
733
    bool textureTransformSupported = false;
734
    struct TextureTransformExt {
735
        float offset[2];
736
        float rotation;
737
        float scale[2];
738
    } TextureTransformExt_t;
739
};
740
741
struct NormalTextureInfo : TextureInfo {
742
    float scale = 1;
743
};
744
745
struct OcclusionTextureInfo : TextureInfo {
746
    float strength = 1;
747
};
748
749
struct PbrMetallicRoughness {
750
    vec4 baseColorFactor;
751
    TextureInfo baseColorTexture;
752
    TextureInfo metallicRoughnessTexture;
753
    float metallicFactor;
754
    float roughnessFactor;
755
};
756
757
struct PbrSpecularGlossiness {
758
    vec4 diffuseFactor;
759
    vec3 specularFactor;
760
    float glossinessFactor;
761
    TextureInfo diffuseTexture;
762
    TextureInfo specularGlossinessTexture;
763
764
0
    PbrSpecularGlossiness() { SetDefaults(); }
765
    void SetDefaults();
766
};
767
768
struct MaterialSpecular {
769
    float specularFactor;
770
    vec3 specularColorFactor;
771
    TextureInfo specularTexture;
772
    TextureInfo specularColorTexture;
773
774
0
    MaterialSpecular() { SetDefaults(); }
775
    void SetDefaults();
776
};
777
778
struct MaterialSheen {
779
    vec3 sheenColorFactor;
780
    float sheenRoughnessFactor;
781
    TextureInfo sheenColorTexture;
782
    TextureInfo sheenRoughnessTexture;
783
784
0
    MaterialSheen() { SetDefaults(); }
785
    void SetDefaults();
786
};
787
788
struct MaterialClearcoat {
789
    float clearcoatFactor = 0.f;
790
    float clearcoatRoughnessFactor = 0.f;
791
    TextureInfo clearcoatTexture;
792
    TextureInfo clearcoatRoughnessTexture;
793
    NormalTextureInfo clearcoatNormalTexture;
794
};
795
796
struct MaterialTransmission {
797
    TextureInfo transmissionTexture;
798
    float transmissionFactor = 0.f;
799
};
800
801
struct MaterialVolume {
802
    float thicknessFactor = 0.f;
803
    TextureInfo thicknessTexture;
804
    float attenuationDistance = 0.f;
805
    vec3 attenuationColor;
806
807
0
    MaterialVolume() { SetDefaults(); }
808
    void SetDefaults();
809
};
810
811
struct MaterialIOR {
812
    float ior = 0.f;
813
814
0
    MaterialIOR() { SetDefaults(); }
815
    void SetDefaults();
816
};
817
818
struct MaterialEmissiveStrength {
819
    float emissiveStrength = 0.f;
820
821
0
    MaterialEmissiveStrength() { SetDefaults(); }
822
    void SetDefaults();
823
};
824
825
struct MaterialAnisotropy {
826
    float anisotropyStrength = 0.f;
827
    float anisotropyRotation = 0.f;
828
    TextureInfo anisotropyTexture;
829
830
0
    MaterialAnisotropy() { SetDefaults(); }
831
    void SetDefaults();
832
};
833
834
//! The material appearance of a primitive.
835
struct Material : public Object {
836
    //PBR metallic roughness properties
837
    PbrMetallicRoughness pbrMetallicRoughness;
838
839
    //other basic material properties
840
    NormalTextureInfo normalTexture;
841
    OcclusionTextureInfo occlusionTexture;
842
    TextureInfo emissiveTexture;
843
    vec3 emissiveFactor;
844
    std::string alphaMode;
845
    float alphaCutoff;
846
    bool doubleSided;
847
848
    //extension: KHR_materials_pbrSpecularGlossiness
849
    Nullable<PbrSpecularGlossiness> pbrSpecularGlossiness;
850
851
    //extension: KHR_materials_specular
852
    Nullable<MaterialSpecular> materialSpecular;
853
854
    //extension: KHR_materials_sheen
855
    Nullable<MaterialSheen> materialSheen;
856
857
    //extension: KHR_materials_clearcoat
858
    Nullable<MaterialClearcoat> materialClearcoat;
859
860
    //extension: KHR_materials_transmission
861
    Nullable<MaterialTransmission> materialTransmission;
862
863
    //extension: KHR_materials_volume
864
    Nullable<MaterialVolume> materialVolume;
865
866
    //extension: KHR_materials_ior
867
    Nullable<MaterialIOR> materialIOR;
868
869
    //extension: KHR_materials_emissive_strength
870
    Nullable<MaterialEmissiveStrength> materialEmissiveStrength;
871
872
    //extension: KHR_materials_anisotropy
873
    Nullable<MaterialAnisotropy> materialAnisotropy;
874
875
    //extension: KHR_materials_unlit
876
    bool unlit;
877
878
0
    Material() { SetDefaults(); }
879
    void Read(Value &obj, Asset &r);
880
    void SetDefaults();
881
882
    inline void SetTextureProperties(Asset &r, Value *prop, TextureInfo &out);
883
    inline void ReadTextureProperty(Asset &r, Value &vals, const char *propName, TextureInfo &out);
884
    inline void ReadTextureProperty(Asset &r, Value &vals, const char *propName, NormalTextureInfo &out);
885
    inline void ReadTextureProperty(Asset &r, Value &vals, const char *propName, OcclusionTextureInfo &out);
886
};
887
888
//! 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.
889
struct Mesh : public Object {
890
    using AccessorList = std::vector<Ref<Accessor>>;
891
892
    struct Primitive {
893
        PrimitiveMode mode;
894
895
        struct Attributes {
896
            AccessorList position, normal, tangent, texcoord, color, joint, jointmatrix, weight;
897
        } attributes;
898
899
        Ref<Accessor> indices;
900
901
        Ref<Material> material;
902
903
        struct Target {
904
            AccessorList position, normal, tangent;
905
        };
906
        std::vector<Target> targets;
907
908
        // extension: FB_ngon_encoding
909
        bool ngonEncoded;
910
911
0
        Primitive(): ngonEncoded(false) {}
912
    };
913
914
    std::vector<Primitive> primitives;
915
916
    std::vector<float> weights;
917
    std::vector<std::string> targetNames;
918
919
0
    Mesh() = default;
920
921
    /// Get mesh data from JSON-object and place them to root asset.
922
    /// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
923
    /// \param [out] pAsset_Root - reference to root asset where data will be stored.
924
    void Read(Value &pJSON_Object, Asset &pAsset_Root);
925
};
926
927
struct Node : public Object {
928
    std::vector<Ref<Node>> children;
929
    std::vector<Ref<Mesh>> meshes;
930
931
    Nullable<mat4> matrix;
932
    Nullable<vec3> translation;
933
    Nullable<vec4> rotation;
934
    Nullable<vec3> scale;
935
936
    Ref<Camera> camera;
937
    Ref<Light> light;
938
939
    std::vector<Ref<Node>> skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy.
940
    Ref<Skin> skin; //!< The ID of the skin referenced by this node.
941
    std::string jointName; //!< Name used when this node is a joint in a skin.
942
943
    Ref<Node> parent; //!< This is not part of the glTF specification. Used as a helper.
944
945
0
    Node() = default;
946
    void Read(Value &obj, Asset &r);
947
};
948
949
struct Program : public Object {
950
    Program() = default;
951
    void Read(Value &obj, Asset &r);
952
};
953
954
struct Sampler : public Object {
955
    SamplerMagFilter magFilter; //!< The texture magnification filter.
956
    SamplerMinFilter minFilter; //!< The texture minification filter.
957
    SamplerWrap wrapS; //!< The texture wrapping in the S direction.
958
    SamplerWrap wrapT; //!< The texture wrapping in the T direction.
959
960
0
    Sampler() { SetDefaults(); }
961
    void Read(Value &obj, Asset &r);
962
    void SetDefaults();
963
};
964
965
struct Scene : public Object {
966
    std::string name;
967
    std::vector<Ref<Node>> nodes;
968
969
0
    Scene() = default;
970
    void Read(Value &obj, Asset &r);
971
};
972
973
struct Shader : public Object {
974
    Shader() = default;
975
    void Read(Value &obj, Asset &r);
976
};
977
978
struct Skin : public Object {
979
    Nullable<mat4> bindShapeMatrix; //!< Floating-point 4x4 transformation matrix stored in column-major order.
980
    Ref<Accessor> inverseBindMatrices; //!< The ID of the accessor containing the floating-point 4x4 inverse-bind matrices.
981
    std::vector<Ref<Node>> jointNames; //!< Joint names of the joints (nodes with a jointName property) in this skin.
982
    std::string name; //!< The user-defined name of this object.
983
984
0
    Skin() = default;
985
    void Read(Value &obj, Asset &r);
986
};
987
988
//! A texture and its sampler.
989
struct Texture : public Object {
990
    Ref<Sampler> sampler; //!< The ID of the sampler used by this texture. (required)
991
    Ref<Image> source; //!< The ID of the image used by this texture. (required)
992
993
    //TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA)
994
    //TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
995
996
    //TextureTarget target; //!< The target that the WebGL texture should be bound to. (default: TextureTarget_TEXTURE_2D)
997
    //TextureType type; //!< Texel datatype. (default: TextureType_UNSIGNED_BYTE)
998
999
0
    Texture() = default;
1000
    void Read(Value &obj, Asset &r);
1001
};
1002
1003
struct Animation : public Object {
1004
    struct Sampler {
1005
        Sampler() :
1006
0
                interpolation(Interpolation_LINEAR) {}
1007
1008
        Ref<Accessor> input; //!< Accessor reference to the buffer storing the key-frame times.
1009
        Ref<Accessor> output; //!< Accessor reference to the buffer storing the key-frame values.
1010
        Interpolation interpolation; //!< Type of interpolation algorithm to use between key-frames.
1011
    };
1012
1013
    struct Target {
1014
        Target() :
1015
0
                path(AnimationPath_TRANSLATION) {}
1016
1017
        Ref<Node> node; //!< The node to animate.
1018
        AnimationPath path; //!< The property of the node to animate.
1019
    };
1020
1021
    struct Channel {
1022
        Channel() :
1023
0
                sampler(-1) {}
1024
1025
        int sampler; //!< The sampler index containing the animation data.
1026
        Target target; //!< The node and property to animate.
1027
    };
1028
1029
    std::vector<Sampler> samplers; //!< All the key-frame data for this animation.
1030
    std::vector<Channel> channels; //!< Data to connect nodes to key-frames.
1031
1032
0
    Animation() = default;
1033
    void Read(Value &obj, Asset &r);
1034
};
1035
1036
//! Base class for LazyDict that acts as an interface
1037
class LazyDictBase {
1038
public:
1039
1.97k
    virtual ~LazyDictBase() = default;
1040
1041
    virtual void AttachToDocument(Document &doc) = 0;
1042
    virtual void DetachFromDocument() = 0;
1043
1044
#if !defined(ASSIMP_BUILD_NO_EXPORT)
1045
    virtual void WriteObjects(AssetWriter &writer) = 0;
1046
#endif
1047
};
1048
1049
template <class T>
1050
class LazyDict;
1051
1052
//! (Implemented in glTFAssetWriter.h)
1053
template <class T>
1054
void WriteLazyDict(LazyDict<T> &d, AssetWriter &w);
1055
1056
//! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID
1057
//! It is the owner the loaded objects, so when it is destroyed it also deletes them
1058
template <class T>
1059
class LazyDict : public LazyDictBase {
1060
    friend class Asset;
1061
    friend class AssetWriter;
1062
1063
    using Dict = typename std::gltf_unordered_map<unsigned int, unsigned int>;
1064
    using IdDict = typename std::gltf_unordered_map<std::string, unsigned int>;
1065
1066
    std::vector<T *> mObjs; //! The read objects
1067
    Dict mObjsByOIndex; //! The read objects accessible by original index
1068
    IdDict mObjsById; //! The read objects accessible by id
1069
    const char *mDictId; //! ID of the dictionary object
1070
    const char *mExtId; //! ID of the extension defining the dictionary
1071
    Value *mDict; //! JSON dictionary object
1072
    Asset &mAsset; //! The asset instance
1073
1074
    std::gltf_unordered_set<unsigned int> mRecursiveReferenceCheck; //! Used by Retrieve to prevent recursive lookups
1075
1076
    void AttachToDocument(Document &doc);
1077
    void DetachFromDocument();
1078
1079
#if !defined(ASSIMP_BUILD_NO_EXPORT)
1080
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&)
1081
#endif
1082
1083
    Ref<T> Add(T *obj);
1084
1085
public:
1086
    LazyDict(Asset &asset, const char *dictId, const char *extId = nullptr);
1087
    ~LazyDict();
1088
1089
    Ref<T> Retrieve(unsigned int i);
1090
1091
    Ref<T> Get(unsigned int i);
1092
    Ref<T> Get(const char *id);
1093
1094
    Ref<T> Create(const char *id);
1095
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&)
1096
1097
    unsigned int Remove(const char *id);
1098
1099
0
    inline unsigned int Size() const { return unsigned(mObjs.size()); }
Unexecuted instantiation: glTF2::LazyDict<glTF2::Buffer>::Size() const
Unexecuted instantiation: glTF2::LazyDict<glTF2::Mesh>::Size() const
Unexecuted instantiation: glTF2::LazyDict<glTF2::Node>::Size() const
Unexecuted instantiation: glTF2::LazyDict<glTF2::Material>::Size() const
Unexecuted instantiation: glTF2::LazyDict<glTF2::Camera>::Size() const
Unexecuted instantiation: glTF2::LazyDict<glTF2::Light>::Size() const
Unexecuted instantiation: glTF2::LazyDict<glTF2::Animation>::Size() const
Unexecuted instantiation: glTF2::LazyDict<glTF2::Image>::Size() const
1100
1101
0
    inline T &operator[](size_t i) { return *mObjs[i]; }
Unexecuted instantiation: glTF2::LazyDict<glTF2::Material>::operator[](unsigned long)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Mesh>::operator[](unsigned long)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Camera>::operator[](unsigned long)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Light>::operator[](unsigned long)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Animation>::operator[](unsigned long)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Node>::operator[](unsigned long)
Unexecuted instantiation: glTF2::LazyDict<glTF2::Image>::operator[](unsigned long)
1102
};
1103
1104
struct AssetMetadata {
1105
    std::string copyright; //!< A copyright message suitable for display to credit the content creator.
1106
    std::string generator; //!< Tool that generated this glTF model.Useful for debugging.
1107
1108
    struct {
1109
        std::string api; //!< Specifies the target rendering API (default: "WebGL")
1110
        std::string version; //!< Specifies the target rendering API (default: "1.0.3")
1111
    } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {})
1112
1113
    std::string version; //!< The glTF format version
1114
1115
    void Read(Document &doc);
1116
1117
141
    AssetMetadata() = default;
1118
};
1119
1120
//
1121
// glTF Asset class
1122
//
1123
1124
//! Root object for a glTF asset
1125
class Asset {
1126
    using IdMap = std::gltf_unordered_map<std::string, int>;
1127
1128
    template <class T>
1129
    friend class LazyDict;
1130
    friend struct Buffer; // To access OpenFile
1131
    friend class AssetWriter;
1132
1133
    std::vector<LazyDictBase *> mDicts;
1134
1135
public:
1136
    //! Keeps info about the enabled extensions
1137
    struct Extensions {
1138
        bool KHR_materials_pbrSpecularGlossiness;
1139
        bool KHR_materials_specular;
1140
        bool KHR_materials_unlit;
1141
        bool KHR_lights_punctual;
1142
        bool KHR_texture_transform;
1143
        bool KHR_materials_sheen;
1144
        bool KHR_materials_clearcoat;
1145
        bool KHR_materials_transmission;
1146
        bool KHR_materials_volume;
1147
        bool KHR_materials_ior;
1148
        bool KHR_materials_emissive_strength;
1149
        bool KHR_materials_anisotropy;
1150
        bool KHR_draco_mesh_compression;
1151
        bool FB_ngon_encoding;
1152
        bool KHR_texture_basisu;
1153
1154
        Extensions() :
1155
141
                KHR_materials_pbrSpecularGlossiness(false),
1156
141
                KHR_materials_specular(false),
1157
141
                KHR_materials_unlit(false),
1158
141
                KHR_lights_punctual(false),
1159
141
                KHR_texture_transform(false),
1160
141
                KHR_materials_sheen(false),
1161
141
                KHR_materials_clearcoat(false),
1162
141
                KHR_materials_transmission(false),
1163
141
                KHR_materials_volume(false),
1164
141
                KHR_materials_ior(false),
1165
141
                KHR_materials_emissive_strength(false),
1166
141
                KHR_materials_anisotropy(false),
1167
141
                KHR_draco_mesh_compression(false),
1168
141
                FB_ngon_encoding(false),
1169
141
                KHR_texture_basisu(false) {
1170
            // empty
1171
141
        }
1172
    } extensionsUsed;
1173
1174
    //! Keeps info about the required extensions
1175
    struct RequiredExtensions {
1176
        bool KHR_draco_mesh_compression;
1177
        bool KHR_texture_basisu;
1178
1179
141
        RequiredExtensions() : KHR_draco_mesh_compression(false), KHR_texture_basisu(false) {
1180
            // empty
1181
141
        }
1182
    } extensionsRequired;
1183
1184
    AssetMetadata asset;
1185
    Value *extras;
1186
1187
    // Dictionaries for each type of object
1188
1189
    LazyDict<Accessor> accessors;
1190
    LazyDict<Animation> animations;
1191
    LazyDict<Buffer> buffers;
1192
    LazyDict<BufferView> bufferViews;
1193
    LazyDict<Camera> cameras;
1194
    LazyDict<Light> lights;
1195
    LazyDict<Image> images;
1196
    LazyDict<Material> materials;
1197
    LazyDict<Mesh> meshes;
1198
    LazyDict<Node> nodes;
1199
    LazyDict<Sampler> samplers;
1200
    LazyDict<Scene> scenes;
1201
    LazyDict<Skin> skins;
1202
    LazyDict<Texture> textures;
1203
1204
    Ref<Scene> scene;
1205
1206
public:
1207
    Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) :
1208
141
            mDicts(),
1209
141
            extensionsUsed(),
1210
141
            extensionsRequired(),
1211
141
            asset(),
1212
141
            extras(nullptr),
1213
141
            accessors(*this, "accessors"),
1214
141
            animations(*this, "animations"),
1215
141
            buffers(*this, "buffers"),
1216
141
            bufferViews(*this, "bufferViews"),
1217
141
            cameras(*this, "cameras"),
1218
141
            lights(*this, "lights", "KHR_lights_punctual"),
1219
141
            images(*this, "images"),
1220
141
            materials(*this, "materials"),
1221
141
            meshes(*this, "meshes"),
1222
141
            nodes(*this, "nodes"),
1223
141
            samplers(*this, "samplers"),
1224
141
            scenes(*this, "scenes"),
1225
141
            skins(*this, "skins"),
1226
141
            textures(*this, "textures") ,
1227
141
            mIOSystem(io),
1228
141
            mSchemaDocumentProvider(schemaDocumentProvider) {
1229
        // empty
1230
141
    }
1231
1232
    //! Main function
1233
    void Load(const std::string &file, bool isBinary = false);
1234
1235
    //! Parse the AssetMetadata and check that the version is 2.
1236
    bool CanRead(const std::string &pFile, bool isBinary = false);
1237
1238
    //! Enables binary encoding on the asset
1239
    void SetAsBinary();
1240
1241
    //! Search for an available name, starting from the given strings
1242
    std::string FindUniqueID(const std::string &str, const char *suffix);
1243
1244
0
    Ref<Buffer> GetBodyBuffer() { return mBodyBuffer; }
1245
1246
    Asset(Asset &) = delete;
1247
    Asset &operator=(const Asset &) = delete;
1248
1249
private:
1250
    void ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneData);
1251
1252
    /// Obtain a JSON document from the stream.
1253
    /// \param second argument is a buffer used by the document. It must be kept
1254
    /// alive while the document is in use.
1255
    Document ReadDocument(IOStream& stream, bool isBinary, std::vector<char>& sceneData);
1256
1257
    void ReadExtensionsUsed(Document &doc);
1258
    void ReadExtensionsRequired(Document &doc);
1259
1260
    IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false);
1261
1262
private:
1263
    IOSystem *mIOSystem;
1264
    rapidjson::IRemoteSchemaDocumentProvider *mSchemaDocumentProvider;
1265
    std::string mCurrentAssetDir;
1266
    size_t mSceneLength;
1267
    size_t mBodyOffset;
1268
    size_t mBodyLength;
1269
    Ref<Buffer> mBodyBuffer;
1270
    std::unordered_map<std::string, int> lastUsedID;
1271
};
1272
1273
0
inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {
1274
0
    std::string context = id;
1275
0
    if (!name.empty()) {
1276
0
        context += " (\"" + name + "\")";
1277
0
    }
1278
0
    return context;
1279
0
}
1280
1281
} // namespace glTF2
1282
1283
// Include the implementation of the methods
1284
#include "glTF2Asset.inl"
1285
1286
//#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
1287
1288
#endif // GLTF2ASSET_H_INC