vrshoot
diff libs/assimp/BlenderDNA.h @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/BlenderDNA.h Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,798 @@ 1.4 +/* 1.5 +Open Asset Import Library (assimp) 1.6 +---------------------------------------------------------------------- 1.7 + 1.8 +Copyright (c) 2006-2012, assimp team 1.9 +All rights reserved. 1.10 + 1.11 +Redistribution and use of this software in source and binary forms, 1.12 +with or without modification, are permitted provided that the 1.13 +following conditions are met: 1.14 + 1.15 +* Redistributions of source code must retain the above 1.16 + copyright notice, this list of conditions and the 1.17 + following disclaimer. 1.18 + 1.19 +* Redistributions in binary form must reproduce the above 1.20 + copyright notice, this list of conditions and the 1.21 + following disclaimer in the documentation and/or other 1.22 + materials provided with the distribution. 1.23 + 1.24 +* Neither the name of the assimp team, nor the names of its 1.25 + contributors may be used to endorse or promote products 1.26 + derived from this software without specific prior 1.27 + written permission of the assimp team. 1.28 + 1.29 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.30 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.31 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.32 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.33 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.34 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.35 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.36 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.37 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.38 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.39 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.40 + 1.41 +---------------------------------------------------------------------- 1.42 +*/ 1.43 + 1.44 +/** @file BlenderDNA.h 1.45 + * @brief Blender `DNA` (file format specification embedded in 1.46 + * blend file itself) loader. 1.47 + */ 1.48 +#ifndef INCLUDED_AI_BLEND_DNA_H 1.49 +#define INCLUDED_AI_BLEND_DNA_H 1.50 + 1.51 +#include "BaseImporter.h" 1.52 +#include "TinyFormatter.h" 1.53 + 1.54 +// enable verbose log output. really verbose, so be careful. 1.55 +#ifdef _DEBUG 1.56 +# define ASSIMP_BUILD_BLENDER_DEBUG 1.57 +#endif 1.58 + 1.59 +// #define ASSIMP_BUILD_BLENDER_NO_STATS 1.60 + 1.61 +namespace Assimp { 1.62 + template <bool,bool> class StreamReader; 1.63 + typedef StreamReader<true,true> StreamReaderAny; 1.64 + 1.65 + namespace Blender { 1.66 + class FileDatabase; 1.67 + struct FileBlockHead; 1.68 + 1.69 + template <template <typename> class TOUT> 1.70 + class ObjectCache; 1.71 + 1.72 +// ------------------------------------------------------------------------------- 1.73 +/** Exception class used by the blender loader to selectively catch exceptions 1.74 + * thrown in its own code (DeadlyImportErrors thrown in general utility 1.75 + * functions are untouched then). If such an exception is not caught by 1.76 + * the loader itself, it will still be caught by Assimp due to its 1.77 + * ancestry. */ 1.78 +// ------------------------------------------------------------------------------- 1.79 +struct Error : DeadlyImportError 1.80 +{ 1.81 + Error (const std::string& s) 1.82 + : DeadlyImportError(s) 1.83 + {} 1.84 +}; 1.85 + 1.86 +// ------------------------------------------------------------------------------- 1.87 +/** The only purpose of this structure is to feed a virtual dtor into its 1.88 + * descendents. It serves as base class for all data structure fields. */ 1.89 +// ------------------------------------------------------------------------------- 1.90 +struct ElemBase 1.91 +{ 1.92 + virtual ~ElemBase() {} 1.93 + 1.94 + /** Type name of the element. The type 1.95 + * string points is the `c_str` of the `name` attribute of the 1.96 + * corresponding `Structure`, that is, it is only valid as long 1.97 + * as the DNA is not modified. The dna_type is only set if the 1.98 + * data type is not static, i.e. a boost::shared_ptr<ElemBase> 1.99 + * in the scene description would have its type resolved 1.100 + * at runtime, so this member is always set. */ 1.101 + const char* dna_type; 1.102 +}; 1.103 + 1.104 + 1.105 +// ------------------------------------------------------------------------------- 1.106 +/** Represents a generic pointer to a memory location, which can be either 32 1.107 + * or 64 bits. These pointers are loaded from the BLEND file and finally 1.108 + * fixed to point to the real, converted representation of the objects 1.109 + * they used to point to.*/ 1.110 +// ------------------------------------------------------------------------------- 1.111 +struct Pointer 1.112 +{ 1.113 + Pointer() : val() {} 1.114 + uint64_t val; 1.115 +}; 1.116 + 1.117 +// ------------------------------------------------------------------------------- 1.118 +/** Represents a generic offset within a BLEND file */ 1.119 +// ------------------------------------------------------------------------------- 1.120 +struct FileOffset 1.121 +{ 1.122 + FileOffset() : val() {} 1.123 + uint64_t val; 1.124 +}; 1.125 + 1.126 +// ------------------------------------------------------------------------------- 1.127 +/** Dummy derivate of std::vector to be able to use it in templates simultaenously 1.128 + * with boost::shared_ptr, which takes only one template argument 1.129 + * while std::vector takes three. Also we need to provide some special member 1.130 + * functions of shared_ptr */ 1.131 +// ------------------------------------------------------------------------------- 1.132 +template <typename T> 1.133 +class vector : public std::vector<T> 1.134 +{ 1.135 +public: 1.136 + using std::vector<T>::resize; 1.137 + using std::vector<T>::empty; 1.138 + 1.139 + void reset() { 1.140 + resize(0); 1.141 + } 1.142 + 1.143 + operator bool () const { 1.144 + return !empty(); 1.145 + } 1.146 +}; 1.147 + 1.148 +// ------------------------------------------------------------------------------- 1.149 +/** Mixed flags for use in #Field */ 1.150 +// ------------------------------------------------------------------------------- 1.151 +enum FieldFlags 1.152 +{ 1.153 + FieldFlag_Pointer = 0x1, 1.154 + FieldFlag_Array = 0x2 1.155 +}; 1.156 + 1.157 +// ------------------------------------------------------------------------------- 1.158 +/** Represents a single member of a data structure in a BLEND file */ 1.159 +// ------------------------------------------------------------------------------- 1.160 +struct Field 1.161 +{ 1.162 + std::string name; 1.163 + std::string type; 1.164 + 1.165 + size_t size; 1.166 + size_t offset; 1.167 + 1.168 + /** Size of each array dimension. For flat arrays, 1.169 + * the second dimension is set to 1. */ 1.170 + size_t array_sizes[2]; 1.171 + 1.172 + /** Any of the #FieldFlags enumerated values */ 1.173 + unsigned int flags; 1.174 +}; 1.175 + 1.176 +// ------------------------------------------------------------------------------- 1.177 +/** Range of possible behaviours for fields absend in the input file. Some are 1.178 + * mission critical so we need them, while others can silently be default 1.179 + * initialized and no animations are harmed. */ 1.180 +// ------------------------------------------------------------------------------- 1.181 +enum ErrorPolicy 1.182 +{ 1.183 + /** Substitute default value and ignore */ 1.184 + ErrorPolicy_Igno, 1.185 + /** Substitute default value and write to log */ 1.186 + ErrorPolicy_Warn, 1.187 + /** Substitute a massive error message and crash the whole matrix. Its time for another zion */ 1.188 + ErrorPolicy_Fail 1.189 +}; 1.190 + 1.191 +#ifdef ASSIMP_BUILD_BLENDER_DEBUG 1.192 +# define ErrorPolicy_Igno ErrorPolicy_Warn 1.193 +#endif 1.194 + 1.195 +// ------------------------------------------------------------------------------- 1.196 +/** Represents a data structure in a BLEND file. A Structure defines n fields 1.197 + * and their locatios and encodings the input stream. Usually, every 1.198 + * Structure instance pertains to one equally-named data structure in the 1.199 + * BlenderScene.h header. This class defines various utilities to map a 1.200 + * binary `blob` read from the file to such a structure instance with 1.201 + * meaningful contents. */ 1.202 +// ------------------------------------------------------------------------------- 1.203 +class Structure 1.204 +{ 1.205 + template <template <typename> class> friend class ObjectCache; 1.206 + 1.207 +public: 1.208 + 1.209 + Structure() 1.210 + : cache_idx(-1) 1.211 + {} 1.212 + 1.213 +public: 1.214 + 1.215 + // publicly accessible members 1.216 + std::string name; 1.217 + vector< Field > fields; 1.218 + std::map<std::string, size_t> indices; 1.219 + 1.220 + size_t size; 1.221 + 1.222 +public: 1.223 + 1.224 + // -------------------------------------------------------- 1.225 + /** Access a field of the structure by its canonical name. The pointer version 1.226 + * returns NULL on failure while the reference version raises an import error. */ 1.227 + inline const Field& operator [] (const std::string& ss) const; 1.228 + inline const Field* Get (const std::string& ss) const; 1.229 + 1.230 + // -------------------------------------------------------- 1.231 + /** Access a field of the structure by its index */ 1.232 + inline const Field& operator [] (const size_t i) const; 1.233 + 1.234 + // -------------------------------------------------------- 1.235 + inline bool operator== (const Structure& other) const { 1.236 + return name == other.name; // name is meant to be an unique identifier 1.237 + } 1.238 + 1.239 + // -------------------------------------------------------- 1.240 + inline bool operator!= (const Structure& other) const { 1.241 + return name != other.name; 1.242 + } 1.243 + 1.244 +public: 1.245 + 1.246 + // -------------------------------------------------------- 1.247 + /** Try to read an instance of the structure from the stream 1.248 + * and attempt to convert to `T`. This is done by 1.249 + * an appropriate specialization. If none is available, 1.250 + * a compiler complain is the result. 1.251 + * @param dest Destination value to be written 1.252 + * @param db File database, including input stream. */ 1.253 + template <typename T> inline void Convert (T& dest, 1.254 + const FileDatabase& db) const; 1.255 + 1.256 + 1.257 + 1.258 + // -------------------------------------------------------- 1.259 + // generic converter 1.260 + template <typename T> 1.261 + void Convert(boost::shared_ptr<ElemBase> in,const FileDatabase& db) const; 1.262 + 1.263 + // -------------------------------------------------------- 1.264 + // generic allocator 1.265 + template <typename T> boost::shared_ptr<ElemBase> Allocate() const; 1.266 + 1.267 + 1.268 + 1.269 + // -------------------------------------------------------- 1.270 + // field parsing for 1d arrays 1.271 + template <int error_policy, typename T, size_t M> 1.272 + void ReadFieldArray(T (& out)[M], const char* name, 1.273 + const FileDatabase& db) const; 1.274 + 1.275 + // -------------------------------------------------------- 1.276 + // field parsing for 2d arrays 1.277 + template <int error_policy, typename T, size_t M, size_t N> 1.278 + void ReadFieldArray2(T (& out)[M][N], const char* name, 1.279 + const FileDatabase& db) const; 1.280 + 1.281 + // -------------------------------------------------------- 1.282 + // field parsing for pointer or dynamic array types 1.283 + // (boost::shared_ptr or boost::shared_array) 1.284 + template <int error_policy, template <typename> class TOUT, typename T> 1.285 + void ReadFieldPtr(TOUT<T>& out, const char* name, 1.286 + const FileDatabase& db) const; 1.287 + 1.288 + // -------------------------------------------------------- 1.289 + // field parsing for static arrays of pointer or dynamic 1.290 + // array types (boost::shared_ptr[] or boost::shared_array[]) 1.291 + template <int error_policy, template <typename> class TOUT, typename T, size_t N> 1.292 + void ReadFieldPtr(TOUT<T> (&out)[N], const char* name, 1.293 + const FileDatabase& db) const; 1.294 + 1.295 + // -------------------------------------------------------- 1.296 + // field parsing for `normal` values 1.297 + template <int error_policy, typename T> 1.298 + void ReadField(T& out, const char* name, 1.299 + const FileDatabase& db) const; 1.300 + 1.301 +private: 1.302 + 1.303 + // -------------------------------------------------------- 1.304 + template <template <typename> class TOUT, typename T> 1.305 + void ResolvePointer(TOUT<T>& out, const Pointer & ptrval, 1.306 + const FileDatabase& db, const Field& f) const; 1.307 + 1.308 + // -------------------------------------------------------- 1.309 + template <template <typename> class TOUT, typename T> 1.310 + void ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, 1.311 + const FileDatabase& db, const Field& f) const; 1.312 + 1.313 + // -------------------------------------------------------- 1.314 + void ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, 1.315 + const FileDatabase& db, const Field& f) const; 1.316 + 1.317 + // -------------------------------------------------------- 1.318 + inline const FileBlockHead* LocateFileBlockForAddress( 1.319 + const Pointer & ptrval, 1.320 + const FileDatabase& db) const; 1.321 + 1.322 +private: 1.323 + 1.324 + // ------------------------------------------------------------------------------ 1.325 + template <typename T> T* _allocate(boost::shared_ptr<T>& out, size_t& s) const { 1.326 + out = boost::shared_ptr<T>(new T()); 1.327 + s = 1; 1.328 + return out.get(); 1.329 + } 1.330 + 1.331 + template <typename T> T* _allocate(vector<T>& out, size_t& s) const { 1.332 + out.resize(s); 1.333 + return s ? &out.front() : NULL; 1.334 + } 1.335 + 1.336 + // -------------------------------------------------------- 1.337 + template <int error_policy> 1.338 + struct _defaultInitializer { 1.339 + 1.340 + template <typename T, unsigned int N> 1.341 + void operator ()(T (& out)[N], const char* = NULL) { 1.342 + for (unsigned int i = 0; i < N; ++i) { 1.343 + out[i] = T(); 1.344 + } 1.345 + } 1.346 + 1.347 + template <typename T, unsigned int N, unsigned int M> 1.348 + void operator ()(T (& out)[N][M], const char* = NULL) { 1.349 + for (unsigned int i = 0; i < N; ++i) { 1.350 + for (unsigned int j = 0; j < M; ++j) { 1.351 + out[i][j] = T(); 1.352 + } 1.353 + } 1.354 + } 1.355 + 1.356 + template <typename T> 1.357 + void operator ()(T& out, const char* = NULL) { 1.358 + out = T(); 1.359 + } 1.360 + }; 1.361 + 1.362 +private: 1.363 + 1.364 + mutable size_t cache_idx; 1.365 +}; 1.366 + 1.367 +// -------------------------------------------------------- 1.368 +template <> struct Structure :: _defaultInitializer<ErrorPolicy_Warn> { 1.369 + 1.370 + template <typename T> 1.371 + void operator ()(T& out, const char* reason = "<add reason>") { 1.372 + DefaultLogger::get()->warn(reason); 1.373 + 1.374 + // ... and let the show go on 1.375 + _defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out); 1.376 + } 1.377 +}; 1.378 + 1.379 +template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> { 1.380 + 1.381 + template <typename T> 1.382 + void operator ()(T& /*out*/,const char* = "") { 1.383 + // obviously, it is crucial that _DefaultInitializer is used 1.384 + // only from within a catch clause. 1.385 + throw; 1.386 + } 1.387 +}; 1.388 + 1.389 +// ------------------------------------------------------------------------------------------------------- 1.390 +template <> inline void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, 1.391 + const Pointer & ptrval, 1.392 + const FileDatabase& db, 1.393 + const Field& f 1.394 + ) const; 1.395 + 1.396 + 1.397 +// ------------------------------------------------------------------------------- 1.398 +/** Represents the full data structure information for a single BLEND file. 1.399 + * This data is extracted from the DNA1 chunk in the file. 1.400 + * #DNAParser does the reading and represents currently the only place where 1.401 + * DNA is altered.*/ 1.402 +// ------------------------------------------------------------------------------- 1.403 +class DNA 1.404 +{ 1.405 +public: 1.406 + 1.407 + typedef void (Structure::*ConvertProcPtr) ( 1.408 + boost::shared_ptr<ElemBase> in, 1.409 + const FileDatabase& 1.410 + ) const; 1.411 + 1.412 + typedef boost::shared_ptr<ElemBase> ( 1.413 + Structure::*AllocProcPtr) () const; 1.414 + 1.415 + typedef std::pair< AllocProcPtr, ConvertProcPtr > FactoryPair; 1.416 + 1.417 +public: 1.418 + 1.419 + std::map<std::string, FactoryPair > converters; 1.420 + vector<Structure > structures; 1.421 + std::map<std::string, size_t> indices; 1.422 + 1.423 +public: 1.424 + 1.425 + // -------------------------------------------------------- 1.426 + /** Access a structure by its canonical name, the pointer version returns NULL on failure 1.427 + * while the reference version raises an error. */ 1.428 + inline const Structure& operator [] (const std::string& ss) const; 1.429 + inline const Structure* Get (const std::string& ss) const; 1.430 + 1.431 + // -------------------------------------------------------- 1.432 + /** Access a structure by its index */ 1.433 + inline const Structure& operator [] (const size_t i) const; 1.434 + 1.435 +public: 1.436 + 1.437 + // -------------------------------------------------------- 1.438 + /** Add structure definitions for all the primitive types, 1.439 + * i.e. integer, short, char, float */ 1.440 + void AddPrimitiveStructures(); 1.441 + 1.442 + // -------------------------------------------------------- 1.443 + /** Fill the @c converters member with converters for all 1.444 + * known data types. The implementation of this method is 1.445 + * in BlenderScene.cpp and is machine-generated. 1.446 + * Converters are used to quickly handle objects whose 1.447 + * exact data type is a runtime-property and not yet 1.448 + * known at compile time (consier Object::data).*/ 1.449 + void RegisterConverters(); 1.450 + 1.451 + 1.452 + // -------------------------------------------------------- 1.453 + /** Take an input blob from the stream, interpret it according to 1.454 + * a its structure name and convert it to the intermediate 1.455 + * representation. 1.456 + * @param structure Destination structure definition 1.457 + * @param db File database. 1.458 + * @return A null pointer if no appropriate converter is available.*/ 1.459 + boost::shared_ptr< ElemBase > ConvertBlobToStructure( 1.460 + const Structure& structure, 1.461 + const FileDatabase& db 1.462 + ) const; 1.463 + 1.464 + // -------------------------------------------------------- 1.465 + /** Find a suitable conversion function for a given Structure. 1.466 + * Such a converter function takes a blob from the input 1.467 + * stream, reads as much as it needs, and builds up a 1.468 + * complete object in intermediate representation. 1.469 + * @param structure Destination structure definition 1.470 + * @param db File database. 1.471 + * @return A null pointer in .first if no appropriate converter is available.*/ 1.472 + FactoryPair GetBlobToStructureConverter( 1.473 + const Structure& structure, 1.474 + const FileDatabase& db 1.475 + ) const; 1.476 + 1.477 + 1.478 +#ifdef ASSIMP_BUILD_BLENDER_DEBUG 1.479 + // -------------------------------------------------------- 1.480 + /** Dump the DNA to a text file. This is for debugging purposes. 1.481 + * The output file is `dna.txt` in the current working folder*/ 1.482 + void DumpToFile(); 1.483 +#endif 1.484 + 1.485 + // -------------------------------------------------------- 1.486 + /** Extract array dimensions from a C array declaration, such 1.487 + * as `...[4][6]`. Returned string would be `...[][]`. 1.488 + * @param out 1.489 + * @param array_sizes Receive maximally two array dimensions, 1.490 + * the second element is set to 1 if the array is flat. 1.491 + * Both are set to 1 if the input is not an array. 1.492 + * @throw DeadlyImportError if more than 2 dimensions are 1.493 + * encountered. */ 1.494 + static void ExtractArraySize( 1.495 + const std::string& out, 1.496 + size_t array_sizes[2] 1.497 + ); 1.498 +}; 1.499 + 1.500 +// special converters for primitive types 1.501 +template <> inline void Structure :: Convert<int> (int& dest,const FileDatabase& db) const; 1.502 +template <> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const; 1.503 +template <> inline void Structure :: Convert<char> (char& dest,const FileDatabase& db) const; 1.504 +template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const; 1.505 +template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const; 1.506 +template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const; 1.507 + 1.508 +// ------------------------------------------------------------------------------- 1.509 +/** Describes a master file block header. Each master file sections holds n 1.510 + * elements of a certain SDNA structure (or otherwise unspecified data). */ 1.511 +// ------------------------------------------------------------------------------- 1.512 +struct FileBlockHead 1.513 +{ 1.514 + // points right after the header of the file block 1.515 + StreamReaderAny::pos start; 1.516 + 1.517 + std::string id; 1.518 + size_t size; 1.519 + 1.520 + // original memory address of the data 1.521 + Pointer address; 1.522 + 1.523 + // index into DNA 1.524 + unsigned int dna_index; 1.525 + 1.526 + // number of structure instances to follow 1.527 + size_t num; 1.528 + 1.529 + 1.530 + 1.531 + // file blocks are sorted by address to quickly locate specific memory addresses 1.532 + bool operator < (const FileBlockHead& o) const { 1.533 + return address.val < o.address.val; 1.534 + } 1.535 + 1.536 + // for std::upper_bound 1.537 + operator const Pointer& () const { 1.538 + return address; 1.539 + } 1.540 +}; 1.541 + 1.542 +// for std::upper_bound 1.543 +inline bool operator< (const Pointer& a, const Pointer& b) { 1.544 + return a.val < b.val; 1.545 +} 1.546 + 1.547 +// ------------------------------------------------------------------------------- 1.548 +/** Utility to read all master file blocks in turn. */ 1.549 +// ------------------------------------------------------------------------------- 1.550 +class SectionParser 1.551 +{ 1.552 +public: 1.553 + 1.554 + // -------------------------------------------------------- 1.555 + /** @param stream Inout stream, must point to the 1.556 + * first section in the file. Call Next() once 1.557 + * to have it read. 1.558 + * @param ptr64 Pointer size in file is 64 bits? */ 1.559 + SectionParser(StreamReaderAny& stream,bool ptr64) 1.560 + : stream(stream) 1.561 + , ptr64(ptr64) 1.562 + { 1.563 + current.size = current.start = 0; 1.564 + } 1.565 + 1.566 +public: 1.567 + 1.568 + // -------------------------------------------------------- 1.569 + const FileBlockHead& GetCurrent() const { 1.570 + return current; 1.571 + } 1.572 + 1.573 + 1.574 +public: 1.575 + 1.576 + // -------------------------------------------------------- 1.577 + /** Advance to the next section. 1.578 + * @throw DeadlyImportError if the last chunk was passed. */ 1.579 + void Next(); 1.580 + 1.581 +public: 1.582 + 1.583 + FileBlockHead current; 1.584 + StreamReaderAny& stream; 1.585 + bool ptr64; 1.586 +}; 1.587 + 1.588 + 1.589 +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS 1.590 +// ------------------------------------------------------------------------------- 1.591 +/** Import statistics, i.e. number of file blocks read*/ 1.592 +// ------------------------------------------------------------------------------- 1.593 +class Statistics { 1.594 + 1.595 +public: 1.596 + 1.597 + Statistics () 1.598 + : fields_read () 1.599 + , pointers_resolved () 1.600 + , cache_hits () 1.601 +// , blocks_read () 1.602 + , cached_objects () 1.603 + {} 1.604 + 1.605 +public: 1.606 + 1.607 + /** total number of fields we read */ 1.608 + unsigned int fields_read; 1.609 + 1.610 + /** total number of resolved pointers */ 1.611 + unsigned int pointers_resolved; 1.612 + 1.613 + /** number of pointers resolved from the cache */ 1.614 + unsigned int cache_hits; 1.615 + 1.616 + /** number of blocks (from FileDatabase::entries) 1.617 + we did actually read from. */ 1.618 + // unsigned int blocks_read; 1.619 + 1.620 + /** objects in FileData::cache */ 1.621 + unsigned int cached_objects; 1.622 +}; 1.623 +#endif 1.624 + 1.625 +// ------------------------------------------------------------------------------- 1.626 +/** The object cache - all objects addressed by pointers are added here. This 1.627 + * avoids circular references and avoids object duplication. */ 1.628 +// ------------------------------------------------------------------------------- 1.629 +template <template <typename> class TOUT> 1.630 +class ObjectCache 1.631 +{ 1.632 +public: 1.633 + 1.634 + typedef std::map< Pointer, TOUT<ElemBase> > StructureCache; 1.635 + 1.636 +public: 1.637 + 1.638 + ObjectCache(const FileDatabase& db) 1.639 + : db(db) 1.640 + { 1.641 + // currently there are only ~400 structure records per blend file. 1.642 + // we read only a small part of them and don't cache objects 1.643 + // which we don't need, so this should suffice. 1.644 + caches.reserve(64); 1.645 + } 1.646 + 1.647 +public: 1.648 + 1.649 + // -------------------------------------------------------- 1.650 + /** Check whether a specific item is in the cache. 1.651 + * @param s Data type of the item 1.652 + * @param out Output pointer. Unchanged if the 1.653 + * cache doens't know the item yet. 1.654 + * @param ptr Item address to look for. */ 1.655 + template <typename T> void get ( 1.656 + const Structure& s, 1.657 + TOUT<T>& out, 1.658 + const Pointer& ptr) const; 1.659 + 1.660 + // -------------------------------------------------------- 1.661 + /** Add an item to the cache after the item has 1.662 + * been fully read. Do not insert anything that 1.663 + * may be faulty or might cause the loading 1.664 + * to abort. 1.665 + * @param s Data type of the item 1.666 + * @param out Item to insert into the cache 1.667 + * @param ptr address (cache key) of the item. */ 1.668 + template <typename T> void set 1.669 + (const Structure& s, 1.670 + const TOUT<T>& out, 1.671 + const Pointer& ptr); 1.672 + 1.673 +private: 1.674 + 1.675 + mutable vector<StructureCache> caches; 1.676 + const FileDatabase& db; 1.677 +}; 1.678 + 1.679 +// ------------------------------------------------------------------------------- 1.680 +// ------------------------------------------------------------------------------- 1.681 +template <> class ObjectCache<Blender::vector> 1.682 +{ 1.683 +public: 1.684 + 1.685 + ObjectCache(const FileDatabase&) {} 1.686 + 1.687 + template <typename T> void get(const Structure&, vector<T>&, const Pointer&) {} 1.688 + template <typename T> void set(const Structure&, const vector<T>&, const Pointer&) {} 1.689 +}; 1.690 + 1.691 +#ifdef _MSC_VER 1.692 +# pragma warning(disable:4355) 1.693 +#endif 1.694 + 1.695 +// ------------------------------------------------------------------------------- 1.696 +/** Memory representation of a full BLEND file and all its dependencies. The 1.697 + * output aiScene is constructed from an instance of this data structure. */ 1.698 +// ------------------------------------------------------------------------------- 1.699 +class FileDatabase 1.700 +{ 1.701 + template <template <typename> class TOUT> friend class ObjectCache; 1.702 + 1.703 +public: 1.704 + 1.705 + 1.706 + FileDatabase() 1.707 + : _cacheArrays(*this) 1.708 + , _cache(*this) 1.709 + , next_cache_idx() 1.710 + {} 1.711 + 1.712 +public: 1.713 + 1.714 + // publicly accessible fields 1.715 + bool i64bit; 1.716 + bool little; 1.717 + 1.718 + DNA dna; 1.719 + boost::shared_ptr< StreamReaderAny > reader; 1.720 + vector< FileBlockHead > entries; 1.721 + 1.722 +public: 1.723 + 1.724 + Statistics& stats() const { 1.725 + return _stats; 1.726 + } 1.727 + 1.728 + // For all our templates to work on both shared_ptr's and vector's 1.729 + // using the same code, a dummy cache for arrays is provided. Actually, 1.730 + // arrays of objects are never cached because we can't easily 1.731 + // ensure their proper destruction. 1.732 + template <typename T> 1.733 + ObjectCache<boost::shared_ptr>& cache(boost::shared_ptr<T>& /*in*/) const { 1.734 + return _cache; 1.735 + } 1.736 + 1.737 + template <typename T> 1.738 + ObjectCache<vector>& cache(vector<T>& /*in*/) const { 1.739 + return _cacheArrays; 1.740 + } 1.741 + 1.742 +private: 1.743 + 1.744 + 1.745 +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS 1.746 + mutable Statistics _stats; 1.747 +#endif 1.748 + 1.749 + mutable ObjectCache<vector> _cacheArrays; 1.750 + mutable ObjectCache<boost::shared_ptr> _cache; 1.751 + 1.752 + mutable size_t next_cache_idx; 1.753 +}; 1.754 + 1.755 +#ifdef _MSC_VER 1.756 +# pragma warning(default:4355) 1.757 +#endif 1.758 + 1.759 +// ------------------------------------------------------------------------------- 1.760 +/** Factory to extract a #DNA from the DNA1 file block in a BLEND file. */ 1.761 +// ------------------------------------------------------------------------------- 1.762 +class DNAParser 1.763 +{ 1.764 + 1.765 +public: 1.766 + 1.767 + /** Bind the parser to a empty DNA and an input stream */ 1.768 + DNAParser(FileDatabase& db) 1.769 + : db(db) 1.770 + {} 1.771 + 1.772 +public: 1.773 + 1.774 + // -------------------------------------------------------- 1.775 + /** Locate the DNA in the file and parse it. The input 1.776 + * stream is expected to point to the beginning of the DN1 1.777 + * chunk at the time this method is called and is 1.778 + * undefined afterwards. 1.779 + * @throw DeadlyImportError if the DNA cannot be read. 1.780 + * @note The position of the stream pointer is undefined 1.781 + * afterwards.*/ 1.782 + void Parse (); 1.783 + 1.784 +public: 1.785 + 1.786 + /** Obtain a reference to the extracted DNA information */ 1.787 + const Blender::DNA& GetDNA() const { 1.788 + return db.dna; 1.789 + } 1.790 + 1.791 +private: 1.792 + 1.793 + FileDatabase& db; 1.794 +}; 1.795 + 1.796 + } // end Blend 1.797 +} // end Assimp 1.798 + 1.799 +#include "BlenderDNA.inl" 1.800 + 1.801 +#endif