1 /*
2 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
4 
5 Copyright (c) 2006-2019, assimp team
6 
7 
8 All rights reserved.
9 
10 Redistribution and use of this software in source and binary forms,
11 with or without modification, are permitted provided that the
12 following conditions are met:
13 
14 * Redistributions of source code must retain the above
15 copyright notice, this list of conditions and the
16 following disclaimer.
17 
18 * Redistributions in binary form must reproduce the above
19 copyright notice, this list of conditions and the
20 following disclaimer in the documentation and/or other
21 materials provided with the distribution.
22 
23 * Neither the name of the assimp team, nor the names of its
24 contributors may be used to endorse or promote products
25 derived from this software without specific prior
26 written permission of the assimp team.
27 
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 
40 ----------------------------------------------------------------------
41 */
42 
43 /** @file glTFAsset.h
44  * Declares a glTF class to handle gltf/glb files
45  *
46  * glTF Extensions Support:
47  *   KHR_binary_glTF: full
48  *   KHR_materials_common: full
49  */
50 #ifndef GLTFASSET_H_INC
51 #define GLTFASSET_H_INC
52 
53 #ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
54 
55 #include <assimp/Exceptional.h>
56 
57 #include <map>
58 #include <string>
59 #include <list>
60 #include <vector>
61 #include <algorithm>
62 #include <stdexcept>
63 
64 #define RAPIDJSON_HAS_STDSTRING 1
65 #include <rapidjson/rapidjson.h>
66 #include <rapidjson/document.h>
67 #include <rapidjson/error/en.h>
68 
69 #ifdef ASSIMP_API
70 #   include <memory>
71 #   include <assimp/DefaultIOSystem.h>
72 #   include <assimp/ByteSwapper.h>
73 #else
74 #   include <memory>
75 #   define AI_SWAP4(p)
76 #   define ai_assert
77 #endif
78 
79 
80 #if _MSC_VER > 1500 || (defined __GNUC___)
81 #       define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
82 #   else
83 #       define gltf_unordered_map map
84 #endif
85 
86 #ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
87 #   include <unordered_map>
88 #   if _MSC_VER > 1600
89 #       define gltf_unordered_map unordered_map
90 #   else
91 #       define gltf_unordered_map tr1::unordered_map
92 #   endif
93 #endif
94 
95 #include "glTF/glTFCommon.h"
96 
97 namespace glTF
98 {
99     using glTFCommon::shared_ptr;
100     using glTFCommon::IOSystem;
101     using glTFCommon::IOStream;
102 
103     using rapidjson::Value;
104     using rapidjson::Document;
105 
106     class Asset;
107     class AssetWriter;
108 
109     struct BufferView; // here due to cross-reference
110     struct Texture;
111     struct Light;
112     struct Skin;
113 
114     using glTFCommon::vec3;
115     using glTFCommon::vec4;
116     using glTFCommon::mat4;
117 
118     //! Magic number for GLB files
119     #define AI_GLB_MAGIC_NUMBER "glTF"
120 
121     #ifdef ASSIMP_API
122         #include <assimp/Compiler/pushpack1.h>
123     #endif
124 
125     //! For the KHR_binary_glTF extension (binary .glb file)
126     //! 20-byte header (+ the JSON + a "body" data section)
127     struct GLB_Header
128     {
129         uint8_t magic[4];     //!< Magic number: "glTF"
130         uint32_t version;     //!< Version number (always 1 as of the last update)
131         uint32_t length;      //!< Total length of the Binary glTF, including header, scene, and body, in bytes
132         uint32_t sceneLength; //!< Length, in bytes, of the glTF scene
133         uint32_t sceneFormat; //!< Specifies the format of the glTF scene (see the SceneFormat enum)
134     } PACK_STRUCT;
135 
136     #ifdef ASSIMP_API
137         #include <assimp/Compiler/poppack1.h>
138     #endif
139 
140 
141     //! Values for the GLB_Header::sceneFormat field
142     enum SceneFormat
143     {
144         SceneFormat_JSON = 0
145     };
146 
147     //! Values for the mesh primitive modes
148     enum PrimitiveMode
149     {
150         PrimitiveMode_POINTS = 0,
151         PrimitiveMode_LINES = 1,
152         PrimitiveMode_LINE_LOOP = 2,
153         PrimitiveMode_LINE_STRIP = 3,
154         PrimitiveMode_TRIANGLES = 4,
155         PrimitiveMode_TRIANGLE_STRIP = 5,
156         PrimitiveMode_TRIANGLE_FAN = 6
157     };
158 
159     //! Values for the Accessor::componentType field
160     enum ComponentType
161     {
162         ComponentType_BYTE = 5120,
163         ComponentType_UNSIGNED_BYTE = 5121,
164         ComponentType_SHORT = 5122,
165         ComponentType_UNSIGNED_SHORT = 5123,
166         ComponentType_UNSIGNED_INT = 5125,
167         ComponentType_FLOAT = 5126
168     };
169 
ComponentTypeSize(ComponentType t)170     inline unsigned int ComponentTypeSize(ComponentType t)
171     {
172         switch (t) {
173             case ComponentType_SHORT:
174             case ComponentType_UNSIGNED_SHORT:
175                 return 2;
176 
177             case ComponentType_UNSIGNED_INT:
178             case ComponentType_FLOAT:
179                 return 4;
180 
181             case ComponentType_BYTE:
182             case ComponentType_UNSIGNED_BYTE:
183                 return 1;
184             default:
185                 std::string err = "GLTF: Unsupported Component Type ";
186                 err += t;
187                 throw DeadlyImportError(err);
188         }
189     }
190 
191     //! Values for the BufferView::target field
192     enum BufferViewTarget
193     {
194         BufferViewTarget_ARRAY_BUFFER = 34962,
195         BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
196     };
197 
198     //! Values for the Sampler::magFilter field
199     enum SamplerMagFilter
200     {
201         SamplerMagFilter_Nearest = 9728,
202         SamplerMagFilter_Linear = 9729
203     };
204 
205     //! Values for the Sampler::minFilter field
206     enum SamplerMinFilter
207     {
208         SamplerMinFilter_Nearest = 9728,
209         SamplerMinFilter_Linear = 9729,
210         SamplerMinFilter_Nearest_Mipmap_Nearest = 9984,
211         SamplerMinFilter_Linear_Mipmap_Nearest = 9985,
212         SamplerMinFilter_Nearest_Mipmap_Linear = 9986,
213         SamplerMinFilter_Linear_Mipmap_Linear = 9987
214     };
215 
216     //! Values for the Sampler::wrapS and Sampler::wrapT field
217     enum SamplerWrap
218     {
219         SamplerWrap_Clamp_To_Edge = 33071,
220         SamplerWrap_Mirrored_Repeat = 33648,
221         SamplerWrap_Repeat = 10497
222     };
223 
224     //! Values for the Texture::format and Texture::internalFormat fields
225     enum TextureFormat
226     {
227         TextureFormat_ALPHA = 6406,
228         TextureFormat_RGB = 6407,
229         TextureFormat_RGBA = 6408,
230         TextureFormat_LUMINANCE = 6409,
231         TextureFormat_LUMINANCE_ALPHA = 6410
232     };
233 
234     //! Values for the Texture::target field
235     enum TextureTarget
236     {
237         TextureTarget_TEXTURE_2D = 3553
238     };
239 
240     //! Values for the Texture::type field
241     enum TextureType
242     {
243         TextureType_UNSIGNED_BYTE = 5121,
244         TextureType_UNSIGNED_SHORT_5_6_5 = 33635,
245         TextureType_UNSIGNED_SHORT_4_4_4_4 = 32819,
246         TextureType_UNSIGNED_SHORT_5_5_5_1 = 32820
247     };
248 
249 
250     //! Values for the Accessor::type field (helper class)
251     class AttribType
252     {
253     public:
254         enum Value
255             { SCALAR, VEC2, VEC3, VEC4, MAT2, MAT3, MAT4 };
256 
257     private:
258         static const size_t NUM_VALUES = static_cast<size_t>(MAT4)+1;
259 
260         struct Info
261             { const char* name; unsigned int numComponents; };
262 
263         template<int N> struct data
264             { static const Info infos[NUM_VALUES]; };
265 
266     public:
FromString(const char * str)267         inline static Value FromString(const char* str)
268         {
269             for (size_t i = 0; i < NUM_VALUES; ++i) {
270                 if (strcmp(data<0>::infos[i].name, str) == 0) {
271                     return static_cast<Value>(i);
272                 }
273             }
274             return SCALAR;
275         }
276 
ToString(Value type)277         inline static const char* ToString(Value type)
278         {
279             return data<0>::infos[static_cast<size_t>(type)].name;
280         }
281 
GetNumComponents(Value type)282         inline static unsigned int GetNumComponents(Value type)
283         {
284             return data<0>::infos[static_cast<size_t>(type)].numComponents;
285         }
286     };
287 
288     // must match the order of the AttribTypeTraits::Value enum!
289     template<int N> const AttribType::Info
290     AttribType::data<N>::infos[AttribType::NUM_VALUES] = {
291         { "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 }
292     };
293 
294 
295 
296     //! A reference to one top-level object, which is valid
297     //! until the Asset instance is destroyed
298     template<class T>
299     class Ref
300     {
301         std::vector<T*>* vector;
302         unsigned int index;
303 
304     public:
Ref()305         Ref() : vector(0), index(0) {}
Ref(std::vector<T * > & vec,unsigned int idx)306         Ref(std::vector<T*>& vec, unsigned int idx) : vector(&vec), index(idx) {}
307 
GetIndex()308         inline unsigned int GetIndex() const
309             { return index; }
310 
311         operator bool() const
312             { return vector != 0; }
313 
314         T* operator->()
315             { return (*vector)[index]; }
316 
317         T& operator*()
318             { return *((*vector)[index]); }
319     };
320 
321     //! Helper struct to represent values that might not be present
322     template<class T>
323     struct Nullable
324     {
325         T value;
326         bool isPresent;
327 
NullableNullable328         Nullable() : isPresent(false) {}
NullableNullable329         Nullable(T& val) : value(val), isPresent(true) {}
330     };
331 
332 
333     //! Base class for all glTF top-level objects
334     struct Object
335     {
336         std::string id;   //!< The globally unique ID used to reference this object
337         std::string name; //!< The user-defined name of this object
338 
339         //! Objects marked as special are not exported (used to emulate the binary body buffer)
IsSpecialObject340         virtual bool IsSpecial() const
341             { return false; }
342 
~ObjectObject343         virtual ~Object() {}
344 
345         //! Maps special IDs to another ID, where needed. Subclasses may override it (statically)
TranslateIdObject346         static const char* TranslateId(Asset& /*r*/, const char* id)
347             { return id; }
348     };
349 
350     //
351     // Classes for each glTF top-level object type
352     //
353 
354     //! A typed view into a BufferView. A BufferView contains raw binary data.
355     //! An accessor provides a typed view into a BufferView or a subset of a BufferView
356     //! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer.
357     struct Accessor : public Object
358     {
359         Ref<BufferView> bufferView;  //!< The ID of the bufferView. (required)
360         unsigned int byteOffset;     //!< The offset relative to the start of the bufferView in bytes. (required)
361         unsigned int byteStride;     //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0)
362         ComponentType componentType; //!< The datatype of components in the attribute. (required)
363         unsigned int count;          //!< The number of attributes referenced by this accessor. (required)
364         AttribType::Value type;      //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
365         std::vector<double> max;     //!< Maximum value of each component in this attribute.
366         std::vector<double> min;     //!< Minimum value of each component in this attribute.
367 
368         unsigned int GetNumComponents();
369         unsigned int GetBytesPerComponent();
370         unsigned int GetElementSize();
371 
372         inline uint8_t* GetPointer();
373 
374         template<class T>
375         bool ExtractData(T*& outData);
376 
377         void WriteData(size_t count, const void* src_buffer, size_t src_stride);
378 
379         //! Helper class to iterate the data
380         class Indexer
381         {
382             friend struct Accessor;
383 
384             Accessor& accessor;
385             uint8_t* data;
386             size_t elemSize, stride;
387 
388             Indexer(Accessor& acc);
389 
390         public:
391 
392             //! Accesses the i-th value as defined by the accessor
393             template<class T>
394             T GetValue(int i);
395 
396             //! Accesses the i-th value as defined by the accessor
GetUIntAccessor397             inline unsigned int GetUInt(int i)
398             {
399                 return GetValue<unsigned int>(i);
400             }
401 
IsValidAccessor402             inline bool IsValid() const
403             {
404                 return data != 0;
405             }
406         };
407 
GetIndexerAccessor408         inline Indexer GetIndexer()
409         {
410             return Indexer(*this);
411         }
412 
AccessorAccessor413         Accessor() {}
414         void Read(Value& obj, Asset& r);
415     };
416 
417     //! A buffer points to binary geometry, animation, or skins.
418     struct Buffer : public Object
419 	{
420 		/********************* Types *********************/
421 	public:
422 
423 		enum Type
424 		{
425 			Type_arraybuffer,
426 			Type_text
427 		};
428 
429 		/// \struct SEncodedRegion
430 		/// Descriptor of encoded region in "bufferView".
431 		struct SEncodedRegion
432 		{
433 			const size_t Offset;///< Offset from begin of "bufferView" to encoded region, in bytes.
434 			const size_t EncodedData_Length;///< Size of encoded region, in bytes.
435 			uint8_t* const DecodedData;///< Cached encoded data.
436 			const size_t DecodedData_Length;///< Size of decoded region, in bytes.
437 			const std::string ID;///< ID of the region.
438 
439 			/// \fn SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID)
440 			/// Constructor.
441 			/// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
442 			/// \param [in] pEncodedData_Length - size of encoded region, in bytes.
443 			/// \param [in] pDecodedData - pointer to decoded data array.
444 			/// \param [in] pDecodedData_Length - size of encoded region, in bytes.
445 			/// \param [in] pID - ID of the region.
SEncodedRegionBuffer::SEncodedRegion446 			SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID)
447 				: Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID)
448 			{}
449 
450 			/// \fn ~SEncodedRegion()
451 			/// Destructor.
~SEncodedRegionBuffer::SEncodedRegion452 			~SEncodedRegion() { delete [] DecodedData; }
453 		};
454 
455 		/******************* Variables *******************/
456 
457 		//std::string uri; //!< The uri of the buffer. Can be a filepath, a data uri, etc. (required)
458 		size_t byteLength; //!< The length of the buffer in bytes. (default: 0)
459 		//std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer")
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 ofcourse) 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 
487 		shared_ptr<uint8_t> mData; //!< Pointer to the data
488 		bool mIsSpecial; //!< Set to true for special cases (e.g. the body buffer)
489         size_t capacity = 0; //!< The capacity of the buffer in bytes. (default: 0)
490 		/// \var EncodedRegion_List
491 		/// List of encoded regions.
492 		std::list<SEncodedRegion*> EncodedRegion_List;
493 
494 		/******************* Functions *******************/
495 
496 	public:
497 
498 		Buffer();
499 		~Buffer();
500 
501 		void Read(Value& obj, Asset& r);
502 
503         bool LoadFromStream(IOStream& stream, size_t length = 0, size_t baseOffset = 0);
504 
505 		/// \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)
506 		/// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data.
507 		/// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
508 		/// \param [in] pEncodedData_Length - size of encoded region, in bytes.
509 		/// \param [in] pDecodedData - pointer to decoded data array.
510 		/// \param [in] pDecodedData_Length - size of encoded region, in bytes.
511 		/// \param [in] pID - ID of the region.
512 		void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID);
513 
514 		/// \fn void EncodedRegion_SetCurrent(const std::string& pID)
515 		/// Select current encoded region by ID. \sa EncodedRegion_Current.
516 		/// \param [in] pID - ID of the region.
517 		void EncodedRegion_SetCurrent(const std::string& pID);
518 
519 		/// \fn bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count)
520 		/// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions.
521 		/// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed.
522 		/// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced.
523 		/// \param [in] pReplace_Data - pointer to array with new data for buffer.
524 		/// \param [in] pReplace_Count - count of bytes in new data.
525 		/// \return true - if successfully replaced, false if input arguments is out of range.
526 		bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count);
527 
528         size_t AppendData(uint8_t* data, size_t length);
529         void Grow(size_t amount);
530 
GetPointerBuffer531         uint8_t* GetPointer()
532             { return mData.get(); }
533 
MarkAsSpecialBuffer534         void MarkAsSpecial()
535             { mIsSpecial = true; }
536 
IsSpecialBuffer537         bool IsSpecial() const
538             { return mIsSpecial; }
539 
GetURIBuffer540         std::string GetURI()
541             { return std::string(this->id) + ".bin"; }
542 
543         static const char* TranslateId(Asset& r, const char* id);
544     };
545 
546     //! A view into a buffer generally representing a subset of the buffer.
547     struct BufferView : public Object
548     {
549         Ref<Buffer> buffer; //! The ID of the buffer. (required)
550         size_t byteOffset; //! The offset into the buffer in bytes. (required)
551         size_t byteLength; //! The length of the bufferView in bytes. (default: 0)
552 
553         BufferViewTarget target; //! The target that the WebGL buffer should be bound to.
554 
555         void Read(Value& obj, Asset& r);
556     };
557 
558     struct Camera : public Object
559     {
560         enum Type
561         {
562             Perspective,
563             Orthographic
564         };
565 
566         Type type;
567 
568         union
569         {
570             struct {
571                 float aspectRatio; //!<The floating - point aspect ratio of the field of view. (0 = undefined = use the canvas one)
572                 float yfov;  //!<The floating - point vertical field of view in radians. (required)
573                 float zfar;  //!<The floating - point distance to the far clipping plane. (required)
574                 float znear; //!< The floating - point distance to the near clipping plane. (required)
575             } perspective;
576 
577             struct {
578                 float xmag;  //! The floating-point horizontal magnification of the view. (required)
579                 float ymag;  //! The floating-point vertical magnification of the view. (required)
580                 float zfar;  //! The floating-point distance to the far clipping plane. (required)
581                 float znear; //! The floating-point distance to the near clipping plane. (required)
582             } ortographic;
583         };
584 
CameraCamera585         Camera() {}
586         void Read(Value& obj, Asset& r);
587     };
588 
589 
590     //! Image data used to create a texture.
591     struct Image : public Object
592     {
593         std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required)
594 
595         Ref<BufferView> bufferView;
596 
597         std::string mimeType;
598 
599         int width, height;
600 
601     private:
602         std::unique_ptr<uint8_t[]> mData;
603         size_t mDataLength;
604 
605     public:
606 
607         Image();
608         void Read(Value& obj, Asset& r);
609 
HasDataImage610         inline bool HasData() const
611             { return mDataLength > 0; }
612 
GetDataLengthImage613         inline size_t GetDataLength() const
614             { return mDataLength; }
615 
GetDataImage616         inline const uint8_t* GetData() const
617             { return mData.get(); }
618 
619         inline uint8_t* StealData();
620 
621         inline void SetData(uint8_t* data, size_t length, Asset& r);
622     };
623 
624     //! Holds a material property that can be a texture or a color
625     struct TexProperty
626     {
627         Ref<Texture> texture;
628         vec4 color;
629     };
630 
631     //! The material appearance of a primitive.
632     struct Material : public Object
633     {
634         //Ref<Sampler> source; //!< The ID of the technique.
635         //std::gltf_unordered_map<std::string, std::string> values; //!< A dictionary object of parameter values.
636 
637         //! Techniques defined by KHR_materials_common
638         enum Technique
639         {
640             Technique_undefined = 0,
641             Technique_BLINN,
642             Technique_PHONG,
643             Technique_LAMBERT,
644             Technique_CONSTANT
645         };
646 
647         TexProperty ambient;
648         TexProperty diffuse;
649         TexProperty specular;
650         TexProperty emission;
651 
652         bool doubleSided;
653         bool transparent;
654         float transparency;
655         float shininess;
656 
657         Technique technique;
658 
MaterialMaterial659         Material() { SetDefaults(); }
660         void Read(Value& obj, Asset& r);
661         void SetDefaults();
662     };
663 
664     //! 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.
665     struct Mesh : public Object
666     {
667         typedef std::vector< Ref<Accessor> > AccessorList;
668 
669         struct Primitive
670         {
671             PrimitiveMode mode;
672 
673             struct Attributes {
674                 AccessorList position, normal, texcoord, color, joint, jointmatrix, weight;
675             } attributes;
676 
677             Ref<Accessor> indices;
678 
679             Ref<Material> material;
680         };
681 
682 		/// \struct SExtension
683 		/// Extension used for mesh.
684 		struct SExtension
685 		{
686 			/// \enum EType
687 			/// Type of extension.
688 			enum EType
689 			{
690 				#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
691 					Compression_Open3DGC,///< Compression of mesh data using Open3DGC algorithm.
692 				#endif
693 
694 				Unknown
695 			};
696 
697 			EType Type;///< Type of extension.
698 
699 			/// \fn SExtension
700 			/// Constructor.
701 			/// \param [in] pType - type of extension.
SExtensionMesh::SExtension702 			SExtension(const EType pType)
703 				: Type(pType)
704 			{}
705 
~SExtensionMesh::SExtension706             virtual ~SExtension() {
707                 // empty
708             }
709 		};
710 
711 		#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
712 			/// \struct SCompression_Open3DGC
713 			/// Compression of mesh data using Open3DGC algorithm.
714 			struct SCompression_Open3DGC : public SExtension
715 			{
716 				using SExtension::Type;
717 
718 				std::string Buffer;///< ID of "buffer" used for storing compressed data.
719 				size_t Offset;///< Offset in "bufferView" where compressed data are stored.
720 				size_t Count;///< Count of elements in compressed data. Is always equivalent to size in bytes: look comments for "Type" and "Component_Type".
721 				bool Binary;///< If true then "binary" mode is used for coding, if false - "ascii" mode.
722 				size_t IndicesCount;///< Count of indices in mesh.
723 				size_t VerticesCount;///< Count of vertices in mesh.
724 				// AttribType::Value Type;///< Is always "SCALAR".
725 				// ComponentType Component_Type;///< Is always "ComponentType_UNSIGNED_BYTE" (5121).
726 
727 				/// \fn SCompression_Open3DGC
728 				/// Constructor.
SCompression_Open3DGCMesh::SCompression_Open3DGC729 				SCompression_Open3DGC()
730 				: SExtension(Compression_Open3DGC) {
731                     // empty
732                 }
733 
~SCompression_Open3DGCMesh::SCompression_Open3DGC734                 virtual ~SCompression_Open3DGC() {
735                     // empty
736                 }
737 			};
738 		#endif
739 
740         std::vector<Primitive> primitives;
741 		std::list<SExtension*> Extension;///< List of extensions used in mesh.
742 
MeshMesh743         Mesh() {}
744 
745 		/// \fn ~Mesh()
746 		/// Destructor.
~MeshMesh747 		~Mesh() { for(std::list<SExtension*>::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) { delete *it; }; }
748 
749 		/// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root)
750 		/// Get mesh data from JSON-object and place them to root asset.
751 		/// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
752 		/// \param [out] pAsset_Root - reference to root asset where data will be stored.
753 		void Read(Value& pJSON_Object, Asset& pAsset_Root);
754 
755 		#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
756 			/// \fn void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root)
757 			/// Decode part of "buffer" which encoded with Open3DGC algorithm.
758 			/// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region.
759 			/// \param [out] pAsset_Root - reference to root assed where data will be stored.
760 			void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root);
761 		#endif
762     };
763 
764     struct Node : public Object
765     {
766         std::vector< Ref<Node> > children;
767         std::vector< Ref<Mesh> > meshes;
768 
769         Nullable<mat4> matrix;
770         Nullable<vec3> translation;
771         Nullable<vec4> rotation;
772         Nullable<vec3> scale;
773 
774         Ref<Camera> camera;
775         Ref<Light>  light;
776 
777         std::vector< Ref<Node> > skeletons;       //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy.
778         Ref<Skin>  skin;                          //!< The ID of the skin referenced by this node.
779         std::string jointName;                    //!< Name used when this node is a joint in a skin.
780 
781         Ref<Node> parent;                         //!< This is not part of the glTF specification. Used as a helper.
782 
NodeNode783         Node() {}
784         void Read(Value& obj, Asset& r);
785     };
786 
787     struct Program : public Object
788     {
ProgramProgram789         Program() {}
790         void Read(Value& obj, Asset& r);
791     };
792 
793 
794     struct Sampler : public Object
795     {
796         SamplerMagFilter magFilter; //!< The texture magnification filter. (required)
797         SamplerMinFilter minFilter; //!< The texture minification filter. (required)
798         SamplerWrap wrapS;          //!< The texture wrapping in the S direction. (required)
799         SamplerWrap wrapT;          //!< The texture wrapping in the T direction. (required)
800 
SamplerSampler801         Sampler() {}
802         void Read(Value& obj, Asset& r);
803         void SetDefaults();
804     };
805 
806     struct Scene : public Object
807     {
808         std::vector< Ref<Node> > nodes;
809 
SceneScene810         Scene() {}
811         void Read(Value& obj, Asset& r);
812     };
813 
814     struct Shader : public Object
815     {
ShaderShader816         Shader() {}
817         void Read(Value& obj, Asset& r);
818     };
819 
820     struct Skin : public Object
821     {
822         Nullable<mat4> bindShapeMatrix;       //!< Floating-point 4x4 transformation matrix stored in column-major order.
823         Ref<Accessor> inverseBindMatrices;    //!< The ID of the accessor containing the floating-point 4x4 inverse-bind matrices.
824         std::vector<Ref<Node>> jointNames;    //!< Joint names of the joints (nodes with a jointName property) in this skin.
825         std::string name;                     //!< The user-defined name of this object.
826 
SkinSkin827         Skin() {}
828         void Read(Value& obj, Asset& r);
829     };
830 
831     struct Technique : public Object
832     {
833         struct Parameters
834         {
835 
836         };
837 
838         struct States
839         {
840 
841         };
842 
843         struct Functions
844         {
845 
846         };
847 
TechniqueTechnique848         Technique() {}
849         void Read(Value& obj, Asset& r);
850     };
851 
852     //! A texture and its sampler.
853     struct Texture : public Object
854     {
855         Ref<Sampler> sampler; //!< The ID of the sampler used by this texture. (required)
856         Ref<Image> source;    //!< The ID of the image used by this texture. (required)
857 
858         //TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA)
859         //TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
860 
861         //TextureTarget target; //!< The target that the WebGL texture should be bound to. (default: TextureTarget_TEXTURE_2D)
862         //TextureType type; //!< Texel datatype. (default: TextureType_UNSIGNED_BYTE)
863 
TextureTexture864         Texture() {}
865         void Read(Value& obj, Asset& r);
866     };
867 
868 
869     //! A light (from KHR_materials_common extension)
870     struct Light : public Object
871     {
872         enum Type
873         {
874             Type_undefined,
875             Type_ambient,
876             Type_directional,
877             Type_point,
878             Type_spot
879         };
880 
881         Type type;
882 
883         vec4 color;
884         float distance;
885         float constantAttenuation;
886         float linearAttenuation;
887         float quadraticAttenuation;
888         float falloffAngle;
889         float falloffExponent;
890 
LightLight891         Light() {}
892         void Read(Value& obj, Asset& r);
893 
894         void SetDefaults();
895     };
896 
897     struct Animation : public Object
898     {
899         struct AnimSampler {
900             std::string id;               //!< The ID of this sampler.
901             std::string input;            //!< The ID of a parameter in this animation to use as key-frame input.
902             std::string interpolation;    //!< Type of interpolation algorithm to use between key-frames.
903             std::string output;           //!< The ID of a parameter in this animation to use as key-frame output.
904         };
905 
906         struct AnimChannel {
907             std::string sampler;         //!< The ID of one sampler present in the containing animation's samplers property.
908 
909             struct AnimTarget {
910                 Ref<Node> id;            //!< The ID of the node to animate.
911                 std::string path;        //!< The name of property of the node to animate ("translation", "rotation", or "scale").
912             } target;
913         };
914 
915         struct AnimParameters {
916             Ref<Accessor> TIME;           //!< Accessor reference to a buffer storing a array of floating point scalar values.
917             Ref<Accessor> rotation;       //!< Accessor reference to a buffer storing a array of four-component floating-point vectors.
918             Ref<Accessor> scale;          //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
919             Ref<Accessor> translation;    //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
920         };
921 
922         // AnimChannel Channels[3];            //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
923         // AnimParameters Parameters;          //!< The samplers that interpolate between the key-frames.
924         // AnimSampler Samplers[3];            //!< The parameterized inputs representing the key-frame data.
925 
926         std::vector<AnimChannel> Channels;            //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
927         AnimParameters Parameters;                    //!< The samplers that interpolate between the key-frames.
928         std::vector<AnimSampler> Samplers;         //!< The parameterized inputs representing the key-frame data.
929 
AnimationAnimation930         Animation() {}
931         void Read(Value& obj, Asset& r);
932     };
933 
934 
935     //! Base class for LazyDict that acts as an interface
936     class LazyDictBase
937     {
938     public:
~LazyDictBase()939         virtual ~LazyDictBase() {}
940 
941         virtual void AttachToDocument(Document& doc) = 0;
942         virtual void DetachFromDocument() = 0;
943 
944         virtual void WriteObjects(AssetWriter& writer) = 0;
945     };
946 
947 
948     template<class T>
949     class LazyDict;
950 
951     //! (Implemented in glTFAssetWriter.h)
952     template<class T>
953     void WriteLazyDict(LazyDict<T>& d, AssetWriter& w);
954 
955 
956     //! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID
957     //! It is the owner the loaded objects, so when it is destroyed it also deletes them
958     template<class T>
959     class LazyDict : public LazyDictBase
960     {
961         friend class Asset;
962         friend class AssetWriter;
963 
964         typedef typename std::gltf_unordered_map< std::string, unsigned int > Dict;
965 
966         std::vector<T*>  mObjs;      //! The read objects
967         Dict             mObjsById;  //! The read objects accessible by id
968         const char*      mDictId;    //! ID of the dictionary object
969         const char*      mExtId;     //! ID of the extension defining the dictionary
970         Value*           mDict;      //! JSON dictionary object
971         Asset&           mAsset;     //! The asset instance
972 
973         void AttachToDocument(Document& doc);
974         void DetachFromDocument();
975 
WriteObjects(AssetWriter & writer)976         void WriteObjects(AssetWriter& writer)
977             { WriteLazyDict<T>(*this, writer); }
978 
979         Ref<T> Add(T* obj);
980 
981     public:
982         LazyDict(Asset& asset, const char* dictId, const char* extId = 0);
983         ~LazyDict();
984 
985         Ref<T> Get(const char* id);
986         Ref<T> Get(unsigned int i);
Get(const std::string & pID)987         Ref<T> Get(const std::string& pID) { return Get(pID.c_str()); }
988 
989         Ref<T> Create(const char* id);
Create(const std::string & id)990         Ref<T> Create(const std::string& id)
991             { return Create(id.c_str()); }
992 
Size()993         inline unsigned int Size() const
994             { return unsigned(mObjs.size()); }
995 
996         inline T& operator[](size_t i)
997             { return *mObjs[i]; }
998 
999     };
1000 
1001 
1002     struct AssetMetadata
1003     {
1004         std::string copyright; //!< A copyright message suitable for display to credit the content creator.
1005         std::string generator; //!< Tool that generated this glTF model.Useful for debugging.
1006         bool premultipliedAlpha; //!< Specifies if the shaders were generated with premultiplied alpha. (default: false)
1007 
1008         struct {
1009             std::string api;     //!< Specifies the target rendering API (default: "WebGL")
1010             std::string version; //!< Specifies the target rendering API (default: "1.0.3")
1011         } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {})
1012 
1013         std::string version; //!< The glTF format version (should be 1.0)
1014 
1015         void Read(Document& doc);
1016 
AssetMetadataAssetMetadata1017         AssetMetadata()
1018             : premultipliedAlpha(false)
1019             , version("")
1020         {
1021         }
1022     };
1023 
1024     //
1025     // glTF Asset class
1026     //
1027 
1028     //! Root object for a glTF asset
1029     class Asset
1030     {
1031         typedef std::gltf_unordered_map<std::string, int> IdMap;
1032 
1033         template<class T>
1034         friend class LazyDict;
1035 
1036         friend struct Buffer; // To access OpenFile
1037 
1038         friend class AssetWriter;
1039 
1040     private:
1041         IOSystem* mIOSystem;
1042 
1043         std::string mCurrentAssetDir;
1044 
1045         size_t mSceneLength;
1046         size_t mBodyOffset, mBodyLength;
1047 
1048         std::vector<LazyDictBase*> mDicts;
1049 
1050         IdMap mUsedIds;
1051 
1052         Ref<Buffer> mBodyBuffer;
1053 
1054         Asset(Asset&);
1055         Asset& operator=(const Asset&);
1056 
1057     public:
1058 
1059         //! Keeps info about the enabled extensions
1060         struct Extensions
1061         {
1062             bool KHR_binary_glTF;
1063             bool KHR_materials_common;
1064 
1065         } extensionsUsed;
1066 
1067         AssetMetadata asset;
1068 
1069 
1070         // Dictionaries for each type of object
1071 
1072         LazyDict<Accessor>    accessors;
1073         LazyDict<Animation>   animations;
1074         LazyDict<Buffer>      buffers;
1075         LazyDict<BufferView>  bufferViews;
1076         LazyDict<Camera>      cameras;
1077         LazyDict<Image>       images;
1078         LazyDict<Material>    materials;
1079         LazyDict<Mesh>        meshes;
1080         LazyDict<Node>        nodes;
1081         //LazyDict<Program>   programs;
1082         LazyDict<Sampler>     samplers;
1083         LazyDict<Scene>       scenes;
1084         //LazyDict<Shader>    shaders;
1085         LazyDict<Skin>      skins;
1086         //LazyDict<Technique> techniques;
1087         LazyDict<Texture>     textures;
1088 
1089         LazyDict<Light>       lights; // KHR_materials_common ext
1090 
1091         Ref<Scene> scene;
1092 
1093     public:
1094         Asset(IOSystem* io = 0)
mIOSystem(io)1095             : mIOSystem(io)
1096             , asset()
1097             , accessors     (*this, "accessors")
1098             , animations    (*this, "animations")
1099             , buffers       (*this, "buffers")
1100             , bufferViews   (*this, "bufferViews")
1101             , cameras       (*this, "cameras")
1102             , images        (*this, "images")
1103             , materials     (*this, "materials")
1104             , meshes        (*this, "meshes")
1105             , nodes         (*this, "nodes")
1106             //, programs    (*this, "programs")
1107             , samplers      (*this, "samplers")
1108             , scenes        (*this, "scenes")
1109             //, shaders     (*this, "shaders")
1110             , skins       (*this, "skins")
1111             //, techniques  (*this, "techniques")
1112             , textures      (*this, "textures")
1113             , lights        (*this, "lights", "KHR_materials_common")
1114         {
1115             memset(&extensionsUsed, 0, sizeof(extensionsUsed));
1116         }
1117 
1118         //! Main function
1119         void Load(const std::string& file, bool isBinary = false);
1120 
1121         //! Enables the "KHR_binary_glTF" extension on the asset
1122         void SetAsBinary();
1123 
1124         //! Search for an available name, starting from the given strings
1125         std::string FindUniqueID(const std::string& str, const char* suffix);
1126 
GetBodyBuffer()1127         Ref<Buffer> GetBodyBuffer()
1128             { return mBodyBuffer; }
1129 
1130     private:
1131         void ReadBinaryHeader(IOStream& stream);
1132 
1133         void ReadExtensionsUsed(Document& doc);
1134 
1135 
1136         IOStream* OpenFile(std::string path, const char* mode, bool absolute = false);
1137     };
1138 
1139 }
1140 
1141 // Include the implementation of the methods
1142 #include "glTFAsset.inl"
1143 
1144 #endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
1145 
1146 #endif // GLTFASSET_H_INC
1147