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