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