1 /* 2 Open Asset Import Library (assimp) 3 ---------------------------------------------------------------------- 4 5 Copyright (c) 2006-2015, assimp team 6 All rights reserved. 7 8 Redistribution and use of this software in source and binary forms, 9 with or without modification, are permitted provided that the 10 following conditions are met: 11 12 * Redistributions of source code must retain the above 13 copyright notice, this list of conditions and the 14 following disclaimer. 15 16 * Redistributions in binary form must reproduce the above 17 copyright notice, this list of conditions and the 18 following disclaimer in the documentation and/or other 19 materials provided with the distribution. 20 21 * Neither the name of the assimp team, nor the names of its 22 contributors may be used to endorse or promote products 23 derived from this software without specific prior 24 written permission of the assimp team. 25 26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 38 ---------------------------------------------------------------------- 39 */ 40 41 // Modified by Lasse Oorni for Urho3D 42 43 /** @file BlenderDNA.h 44 * @brief Blender `DNA` (file format specification embedded in 45 * blend file itself) loader. 46 */ 47 #ifndef INCLUDED_AI_BLEND_DNA_H 48 #define INCLUDED_AI_BLEND_DNA_H 49 50 #include "BaseImporter.h" 51 #include "TinyFormatter.h" 52 #include "StreamReader.h" 53 #include "../include/assimp/DefaultLogger.hpp" 54 // Urho3D: VS2008 compatibility 55 #if !defined(_MSC_VER) || (_MSC_VER >= 1600) 56 #include <stdint.h> 57 #else 58 #include "../include/assimp/Compiler/pstdint.h" 59 #endif 60 #include <boost/shared_ptr.hpp> 61 62 63 // enable verbose log output. really verbose, so be careful. 64 #ifdef ASSIMP_BUILD_DEBUG 65 # define ASSIMP_BUILD_BLENDER_DEBUG 66 #endif 67 68 // #define ASSIMP_BUILD_BLENDER_NO_STATS 69 70 namespace Assimp { 71 template <bool,bool> class StreamReader; 72 typedef StreamReader<true,true> StreamReaderAny; 73 74 namespace Blender { 75 class FileDatabase; 76 struct FileBlockHead; 77 78 template <template <typename> class TOUT> 79 class ObjectCache; 80 81 // ------------------------------------------------------------------------------- 82 /** Exception class used by the blender loader to selectively catch exceptions 83 * thrown in its own code (DeadlyImportErrors thrown in general utility 84 * functions are untouched then). If such an exception is not caught by 85 * the loader itself, it will still be caught by Assimp due to its 86 * ancestry. */ 87 // ------------------------------------------------------------------------------- 88 struct Error : DeadlyImportError 89 { ErrorError90 Error (const std::string& s) 91 : DeadlyImportError(s) 92 {} 93 }; 94 95 // ------------------------------------------------------------------------------- 96 /** The only purpose of this structure is to feed a virtual dtor into its 97 * descendents. It serves as base class for all data structure fields. */ 98 // ------------------------------------------------------------------------------- 99 struct ElemBase 100 { ~ElemBaseElemBase101 virtual ~ElemBase() {} 102 103 /** Type name of the element. The type 104 * string points is the `c_str` of the `name` attribute of the 105 * corresponding `Structure`, that is, it is only valid as long 106 * as the DNA is not modified. The dna_type is only set if the 107 * data type is not static, i.e. a boost::shared_ptr<ElemBase> 108 * in the scene description would have its type resolved 109 * at runtime, so this member is always set. */ 110 const char* dna_type; 111 }; 112 113 114 // ------------------------------------------------------------------------------- 115 /** Represents a generic pointer to a memory location, which can be either 32 116 * or 64 bits. These pointers are loaded from the BLEND file and finally 117 * fixed to point to the real, converted representation of the objects 118 * they used to point to.*/ 119 // ------------------------------------------------------------------------------- 120 struct Pointer 121 { PointerPointer122 Pointer() : val() {} 123 uint64_t val; 124 }; 125 126 // ------------------------------------------------------------------------------- 127 /** Represents a generic offset within a BLEND file */ 128 // ------------------------------------------------------------------------------- 129 struct FileOffset 130 { FileOffsetFileOffset131 FileOffset() : val() {} 132 uint64_t val; 133 }; 134 135 // ------------------------------------------------------------------------------- 136 /** Dummy derivate of std::vector to be able to use it in templates simultaenously 137 * with boost::shared_ptr, which takes only one template argument 138 * while std::vector takes three. Also we need to provide some special member 139 * functions of shared_ptr */ 140 // ------------------------------------------------------------------------------- 141 template <typename T> 142 class vector : public std::vector<T> 143 { 144 public: 145 using std::vector<T>::resize; 146 using std::vector<T>::empty; 147 reset()148 void reset() { 149 resize(0); 150 } 151 152 operator bool () const { 153 return !empty(); 154 } 155 }; 156 157 // ------------------------------------------------------------------------------- 158 /** Mixed flags for use in #Field */ 159 // ------------------------------------------------------------------------------- 160 enum FieldFlags 161 { 162 FieldFlag_Pointer = 0x1, 163 FieldFlag_Array = 0x2 164 }; 165 166 // ------------------------------------------------------------------------------- 167 /** Represents a single member of a data structure in a BLEND file */ 168 // ------------------------------------------------------------------------------- 169 struct Field 170 { 171 std::string name; 172 std::string type; 173 174 size_t size; 175 size_t offset; 176 177 /** Size of each array dimension. For flat arrays, 178 * the second dimension is set to 1. */ 179 size_t array_sizes[2]; 180 181 /** Any of the #FieldFlags enumerated values */ 182 unsigned int flags; 183 }; 184 185 // ------------------------------------------------------------------------------- 186 /** Range of possible behaviours for fields absend in the input file. Some are 187 * mission critical so we need them, while others can silently be default 188 * initialized and no animations are harmed. */ 189 // ------------------------------------------------------------------------------- 190 enum ErrorPolicy 191 { 192 /** Substitute default value and ignore */ 193 ErrorPolicy_Igno, 194 /** Substitute default value and write to log */ 195 ErrorPolicy_Warn, 196 /** Substitute a massive error message and crash the whole matrix. Its time for another zion */ 197 ErrorPolicy_Fail 198 }; 199 200 #ifdef ASSIMP_BUILD_BLENDER_DEBUG 201 # define ErrorPolicy_Igno ErrorPolicy_Warn 202 #endif 203 204 // ------------------------------------------------------------------------------- 205 /** Represents a data structure in a BLEND file. A Structure defines n fields 206 * and their locatios and encodings the input stream. Usually, every 207 * Structure instance pertains to one equally-named data structure in the 208 * BlenderScene.h header. This class defines various utilities to map a 209 * binary `blob` read from the file to such a structure instance with 210 * meaningful contents. */ 211 // ------------------------------------------------------------------------------- 212 class Structure 213 { 214 template <template <typename> class> friend class ObjectCache; 215 216 public: 217 Structure()218 Structure() 219 : cache_idx(-1) 220 {} 221 222 public: 223 224 // publicly accessible members 225 std::string name; 226 vector< Field > fields; 227 std::map<std::string, size_t> indices; 228 229 size_t size; 230 231 public: 232 233 // -------------------------------------------------------- 234 /** Access a field of the structure by its canonical name. The pointer version 235 * returns NULL on failure while the reference version raises an import error. */ 236 inline const Field& operator [] (const std::string& ss) const; 237 inline const Field* Get (const std::string& ss) const; 238 239 // -------------------------------------------------------- 240 /** Access a field of the structure by its index */ 241 inline const Field& operator [] (const size_t i) const; 242 243 // -------------------------------------------------------- 244 inline bool operator== (const Structure& other) const { 245 return name == other.name; // name is meant to be an unique identifier 246 } 247 248 // -------------------------------------------------------- 249 inline bool operator!= (const Structure& other) const { 250 return name != other.name; 251 } 252 253 public: 254 255 // -------------------------------------------------------- 256 /** Try to read an instance of the structure from the stream 257 * and attempt to convert to `T`. This is done by 258 * an appropriate specialization. If none is available, 259 * a compiler complain is the result. 260 * @param dest Destination value to be written 261 * @param db File database, including input stream. */ 262 template <typename T> inline void Convert (T& dest, 263 const FileDatabase& db) const; 264 265 266 267 // -------------------------------------------------------- 268 // generic converter 269 template <typename T> 270 void Convert(boost::shared_ptr<ElemBase> in,const FileDatabase& db) const; 271 272 // -------------------------------------------------------- 273 // generic allocator 274 template <typename T> boost::shared_ptr<ElemBase> Allocate() const; 275 276 277 278 // -------------------------------------------------------- 279 // field parsing for 1d arrays 280 template <int error_policy, typename T, size_t M> 281 void ReadFieldArray(T (& out)[M], const char* name, 282 const FileDatabase& db) const; 283 284 // -------------------------------------------------------- 285 // field parsing for 2d arrays 286 template <int error_policy, typename T, size_t M, size_t N> 287 void ReadFieldArray2(T (& out)[M][N], const char* name, 288 const FileDatabase& db) const; 289 290 // -------------------------------------------------------- 291 // field parsing for pointer or dynamic array types 292 // (boost::shared_ptr or boost::shared_array) 293 // The return value indicates whether the data was already cached. 294 template <int error_policy, template <typename> class TOUT, typename T> 295 bool ReadFieldPtr(TOUT<T>& out, const char* name, 296 const FileDatabase& db, 297 bool non_recursive = false) const; 298 299 // -------------------------------------------------------- 300 // field parsing for static arrays of pointer or dynamic 301 // array types (boost::shared_ptr[] or boost::shared_array[]) 302 // The return value indicates whether the data was already cached. 303 template <int error_policy, template <typename> class TOUT, typename T, size_t N> 304 bool ReadFieldPtr(TOUT<T> (&out)[N], const char* name, 305 const FileDatabase& db) const; 306 307 // -------------------------------------------------------- 308 // field parsing for `normal` values 309 // The return value indicates whether the data was already cached. 310 template <int error_policy, typename T> 311 void ReadField(T& out, const char* name, 312 const FileDatabase& db) const; 313 314 private: 315 316 // -------------------------------------------------------- 317 template <template <typename> class TOUT, typename T> 318 bool ResolvePointer(TOUT<T>& out, const Pointer & ptrval, 319 const FileDatabase& db, const Field& f, 320 bool non_recursive = false) const; 321 322 // -------------------------------------------------------- 323 template <template <typename> class TOUT, typename T> 324 bool ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, 325 const FileDatabase& db, const Field& f, bool) const; 326 327 // -------------------------------------------------------- 328 bool ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, 329 const FileDatabase& db, const Field& f, bool) const; 330 331 // -------------------------------------------------------- 332 inline const FileBlockHead* LocateFileBlockForAddress( 333 const Pointer & ptrval, 334 const FileDatabase& db) const; 335 336 private: 337 338 // ------------------------------------------------------------------------------ _allocate(boost::shared_ptr<T> & out,size_t & s)339 template <typename T> T* _allocate(boost::shared_ptr<T>& out, size_t& s) const { 340 out = boost::shared_ptr<T>(new T()); 341 s = 1; 342 return out.get(); 343 } 344 _allocate(vector<T> & out,size_t & s)345 template <typename T> T* _allocate(vector<T>& out, size_t& s) const { 346 out.resize(s); 347 return s ? &out.front() : NULL; 348 } 349 350 // -------------------------------------------------------- 351 template <int error_policy> 352 struct _defaultInitializer { 353 354 template <typename T, unsigned int N> operator_defaultInitializer355 void operator ()(T (& out)[N], const char* = NULL) { 356 for (unsigned int i = 0; i < N; ++i) { 357 out[i] = T(); 358 } 359 } 360 361 template <typename T, unsigned int N, unsigned int M> operator_defaultInitializer362 void operator ()(T (& out)[N][M], const char* = NULL) { 363 for (unsigned int i = 0; i < N; ++i) { 364 for (unsigned int j = 0; j < M; ++j) { 365 out[i][j] = T(); 366 } 367 } 368 } 369 370 template <typename T> operator_defaultInitializer371 void operator ()(T& out, const char* = NULL) { 372 out = T(); 373 } 374 }; 375 376 private: 377 378 mutable size_t cache_idx; 379 }; 380 381 // -------------------------------------------------------- 382 template <> struct Structure :: _defaultInitializer<ErrorPolicy_Warn> { 383 384 template <typename T> 385 void operator ()(T& out, const char* reason = "<add reason>") { 386 DefaultLogger::get()->warn(reason); 387 388 // ... and let the show go on 389 _defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out); 390 } 391 }; 392 393 template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> { 394 395 template <typename T> 396 void operator ()(T& /*out*/,const char* = "") { 397 // obviously, it is crucial that _DefaultInitializer is used 398 // only from within a catch clause. 399 throw; 400 } 401 }; 402 403 // ------------------------------------------------------------------------------------------------------- 404 template <> inline bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, 405 const Pointer & ptrval, 406 const FileDatabase& db, 407 const Field& f, 408 bool 409 ) const; 410 411 412 // ------------------------------------------------------------------------------- 413 /** Represents the full data structure information for a single BLEND file. 414 * This data is extracted from the DNA1 chunk in the file. 415 * #DNAParser does the reading and represents currently the only place where 416 * DNA is altered.*/ 417 // ------------------------------------------------------------------------------- 418 class DNA 419 { 420 public: 421 422 typedef void (Structure::*ConvertProcPtr) ( 423 boost::shared_ptr<ElemBase> in, 424 const FileDatabase& 425 ) const; 426 427 typedef boost::shared_ptr<ElemBase> ( 428 Structure::*AllocProcPtr) () const; 429 430 typedef std::pair< AllocProcPtr, ConvertProcPtr > FactoryPair; 431 432 public: 433 434 std::map<std::string, FactoryPair > converters; 435 vector<Structure > structures; 436 std::map<std::string, size_t> indices; 437 438 public: 439 440 // -------------------------------------------------------- 441 /** Access a structure by its canonical name, the pointer version returns NULL on failure 442 * while the reference version raises an error. */ 443 inline const Structure& operator [] (const std::string& ss) const; 444 inline const Structure* Get (const std::string& ss) const; 445 446 // -------------------------------------------------------- 447 /** Access a structure by its index */ 448 inline const Structure& operator [] (const size_t i) const; 449 450 public: 451 452 // -------------------------------------------------------- 453 /** Add structure definitions for all the primitive types, 454 * i.e. integer, short, char, float */ 455 void AddPrimitiveStructures(); 456 457 // -------------------------------------------------------- 458 /** Fill the @c converters member with converters for all 459 * known data types. The implementation of this method is 460 * in BlenderScene.cpp and is machine-generated. 461 * Converters are used to quickly handle objects whose 462 * exact data type is a runtime-property and not yet 463 * known at compile time (consier Object::data).*/ 464 void RegisterConverters(); 465 466 467 // -------------------------------------------------------- 468 /** Take an input blob from the stream, interpret it according to 469 * a its structure name and convert it to the intermediate 470 * representation. 471 * @param structure Destination structure definition 472 * @param db File database. 473 * @return A null pointer if no appropriate converter is available.*/ 474 boost::shared_ptr< ElemBase > ConvertBlobToStructure( 475 const Structure& structure, 476 const FileDatabase& db 477 ) const; 478 479 // -------------------------------------------------------- 480 /** Find a suitable conversion function for a given Structure. 481 * Such a converter function takes a blob from the input 482 * stream, reads as much as it needs, and builds up a 483 * complete object in intermediate representation. 484 * @param structure Destination structure definition 485 * @param db File database. 486 * @return A null pointer in .first if no appropriate converter is available.*/ 487 FactoryPair GetBlobToStructureConverter( 488 const Structure& structure, 489 const FileDatabase& db 490 ) const; 491 492 493 #ifdef ASSIMP_BUILD_BLENDER_DEBUG 494 // -------------------------------------------------------- 495 /** Dump the DNA to a text file. This is for debugging purposes. 496 * The output file is `dna.txt` in the current working folder*/ 497 void DumpToFile(); 498 #endif 499 500 // -------------------------------------------------------- 501 /** Extract array dimensions from a C array declaration, such 502 * as `...[4][6]`. Returned string would be `...[][]`. 503 * @param out 504 * @param array_sizes Receive maximally two array dimensions, 505 * the second element is set to 1 if the array is flat. 506 * Both are set to 1 if the input is not an array. 507 * @throw DeadlyImportError if more than 2 dimensions are 508 * encountered. */ 509 static void ExtractArraySize( 510 const std::string& out, 511 size_t array_sizes[2] 512 ); 513 }; 514 515 // special converters for primitive types 516 template <> inline void Structure :: Convert<int> (int& dest,const FileDatabase& db) const; 517 template <> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const; 518 template <> inline void Structure :: Convert<char> (char& dest,const FileDatabase& db) const; 519 template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const; 520 template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const; 521 template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const; 522 523 // ------------------------------------------------------------------------------- 524 /** Describes a master file block header. Each master file sections holds n 525 * elements of a certain SDNA structure (or otherwise unspecified data). */ 526 // ------------------------------------------------------------------------------- 527 struct FileBlockHead 528 { 529 // points right after the header of the file block 530 StreamReaderAny::pos start; 531 532 std::string id; 533 size_t size; 534 535 // original memory address of the data 536 Pointer address; 537 538 // index into DNA 539 unsigned int dna_index; 540 541 // number of structure instances to follow 542 size_t num; 543 544 545 546 // file blocks are sorted by address to quickly locate specific memory addresses 547 bool operator < (const FileBlockHead& o) const { 548 return address.val < o.address.val; 549 } 550 551 // for std::upper_bound 552 operator const Pointer& () const { 553 return address; 554 } 555 }; 556 557 // for std::upper_bound 558 inline bool operator< (const Pointer& a, const Pointer& b) { 559 return a.val < b.val; 560 } 561 562 // ------------------------------------------------------------------------------- 563 /** Utility to read all master file blocks in turn. */ 564 // ------------------------------------------------------------------------------- 565 class SectionParser 566 { 567 public: 568 569 // -------------------------------------------------------- 570 /** @param stream Inout stream, must point to the 571 * first section in the file. Call Next() once 572 * to have it read. 573 * @param ptr64 Pointer size in file is 64 bits? */ 574 SectionParser(StreamReaderAny& stream,bool ptr64) 575 : stream(stream) 576 , ptr64(ptr64) 577 { 578 current.size = current.start = 0; 579 } 580 581 public: 582 583 // -------------------------------------------------------- 584 const FileBlockHead& GetCurrent() const { 585 return current; 586 } 587 588 589 public: 590 591 // -------------------------------------------------------- 592 /** Advance to the next section. 593 * @throw DeadlyImportError if the last chunk was passed. */ 594 void Next(); 595 596 public: 597 598 FileBlockHead current; 599 StreamReaderAny& stream; 600 bool ptr64; 601 }; 602 603 604 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS 605 // ------------------------------------------------------------------------------- 606 /** Import statistics, i.e. number of file blocks read*/ 607 // ------------------------------------------------------------------------------- 608 class Statistics { 609 610 public: 611 612 Statistics () 613 : fields_read () 614 , pointers_resolved () 615 , cache_hits () 616 // , blocks_read () 617 , cached_objects () 618 {} 619 620 public: 621 622 /** total number of fields we read */ 623 unsigned int fields_read; 624 625 /** total number of resolved pointers */ 626 unsigned int pointers_resolved; 627 628 /** number of pointers resolved from the cache */ 629 unsigned int cache_hits; 630 631 /** number of blocks (from FileDatabase::entries) 632 we did actually read from. */ 633 // unsigned int blocks_read; 634 635 /** objects in FileData::cache */ 636 unsigned int cached_objects; 637 }; 638 #endif 639 640 // ------------------------------------------------------------------------------- 641 /** The object cache - all objects addressed by pointers are added here. This 642 * avoids circular references and avoids object duplication. */ 643 // ------------------------------------------------------------------------------- 644 template <template <typename> class TOUT> 645 class ObjectCache 646 { 647 public: 648 649 typedef std::map< Pointer, TOUT<ElemBase> > StructureCache; 650 651 public: 652 653 ObjectCache(const FileDatabase& db) 654 : db(db) 655 { 656 // currently there are only ~400 structure records per blend file. 657 // we read only a small part of them and don't cache objects 658 // which we don't need, so this should suffice. 659 caches.reserve(64); 660 } 661 662 public: 663 664 // -------------------------------------------------------- 665 /** Check whether a specific item is in the cache. 666 * @param s Data type of the item 667 * @param out Output pointer. Unchanged if the 668 * cache doens't know the item yet. 669 * @param ptr Item address to look for. */ 670 template <typename T> void get ( 671 const Structure& s, 672 TOUT<T>& out, 673 const Pointer& ptr) const; 674 675 // -------------------------------------------------------- 676 /** Add an item to the cache after the item has 677 * been fully read. Do not insert anything that 678 * may be faulty or might cause the loading 679 * to abort. 680 * @param s Data type of the item 681 * @param out Item to insert into the cache 682 * @param ptr address (cache key) of the item. */ 683 template <typename T> void set 684 (const Structure& s, 685 const TOUT<T>& out, 686 const Pointer& ptr); 687 688 private: 689 690 mutable vector<StructureCache> caches; 691 const FileDatabase& db; 692 }; 693 694 // ------------------------------------------------------------------------------- 695 // ------------------------------------------------------------------------------- 696 template <> class ObjectCache<Blender::vector> 697 { 698 public: 699 700 ObjectCache(const FileDatabase&) {} 701 702 template <typename T> void get(const Structure&, vector<T>&, const Pointer&) {} 703 template <typename T> void set(const Structure&, const vector<T>&, const Pointer&) {} 704 }; 705 706 #ifdef _MSC_VER 707 # pragma warning(disable:4355) 708 #endif 709 710 // ------------------------------------------------------------------------------- 711 /** Memory representation of a full BLEND file and all its dependencies. The 712 * output aiScene is constructed from an instance of this data structure. */ 713 // ------------------------------------------------------------------------------- 714 class FileDatabase 715 { 716 template <template <typename> class TOUT> friend class ObjectCache; 717 718 public: 719 720 721 FileDatabase() 722 : _cacheArrays(*this) 723 , _cache(*this) 724 , next_cache_idx() 725 {} 726 727 public: 728 729 // publicly accessible fields 730 bool i64bit; 731 bool little; 732 733 DNA dna; 734 boost::shared_ptr< StreamReaderAny > reader; 735 vector< FileBlockHead > entries; 736 737 public: 738 739 Statistics& stats() const { 740 return _stats; 741 } 742 743 // For all our templates to work on both shared_ptr's and vector's 744 // using the same code, a dummy cache for arrays is provided. Actually, 745 // arrays of objects are never cached because we can't easily 746 // ensure their proper destruction. 747 template <typename T> 748 ObjectCache<boost::shared_ptr>& cache(boost::shared_ptr<T>& /*in*/) const { 749 return _cache; 750 } 751 752 template <typename T> 753 ObjectCache<vector>& cache(vector<T>& /*in*/) const { 754 return _cacheArrays; 755 } 756 757 private: 758 759 760 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS 761 mutable Statistics _stats; 762 #endif 763 764 mutable ObjectCache<vector> _cacheArrays; 765 mutable ObjectCache<boost::shared_ptr> _cache; 766 767 mutable size_t next_cache_idx; 768 }; 769 770 #ifdef _MSC_VER 771 # pragma warning(default:4355) 772 #endif 773 774 // ------------------------------------------------------------------------------- 775 /** Factory to extract a #DNA from the DNA1 file block in a BLEND file. */ 776 // ------------------------------------------------------------------------------- 777 class DNAParser 778 { 779 780 public: 781 782 /** Bind the parser to a empty DNA and an input stream */ 783 DNAParser(FileDatabase& db) 784 : db(db) 785 {} 786 787 public: 788 789 // -------------------------------------------------------- 790 /** Locate the DNA in the file and parse it. The input 791 * stream is expected to point to the beginning of the DN1 792 * chunk at the time this method is called and is 793 * undefined afterwards. 794 * @throw DeadlyImportError if the DNA cannot be read. 795 * @note The position of the stream pointer is undefined 796 * afterwards.*/ 797 void Parse (); 798 799 public: 800 801 /** Obtain a reference to the extracted DNA information */ 802 const Blender::DNA& GetDNA() const { 803 return db.dna; 804 } 805 806 private: 807 808 FileDatabase& db; 809 }; 810 811 } // end Blend 812 } // end Assimp 813 814 #include "BlenderDNA.inl" 815 816 #endif 817