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

source code of qt3d/src/3rdparty/assimp/src/code/Blender/BlenderDNA.h