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