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