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