2
0
Эх сурвалжийг харах

Merge branch 'master' of github.com:assimp/assimp

acgessler 12 жил өмнө
parent
commit
7e16767229

+ 17 - 11
code/BlenderDNA.h

@@ -278,19 +278,23 @@ public:
 	// --------------------------------------------------------
 	// field parsing for pointer or dynamic array types 
 	// (boost::shared_ptr or boost::shared_array)
+	// The return value indicates whether the data was already cached.
 	template <int error_policy, template <typename> class TOUT, typename T>
-	void ReadFieldPtr(TOUT<T>& out, const char* name, 
-		const FileDatabase& db) const;
+	bool ReadFieldPtr(TOUT<T>& out, const char* name, 
+		const FileDatabase& db,
+		bool non_recursive = false) const;
 
 	// --------------------------------------------------------
 	// field parsing for static arrays of pointer or dynamic
 	// array types (boost::shared_ptr[] or boost::shared_array[])
+	// The return value indicates whether the data was already cached.
 	template <int error_policy, template <typename> class TOUT, typename T, size_t N>
-	void ReadFieldPtr(TOUT<T> (&out)[N], const char* name, 
+	bool ReadFieldPtr(TOUT<T> (&out)[N], const char* name, 
 		const FileDatabase& db) const;
 
 	// --------------------------------------------------------
 	// field parsing for `normal` values
+	// The return value indicates whether the data was already cached.
 	template <int error_policy, typename T>
 	void ReadField(T& out, const char* name, 
 		const FileDatabase& db) const;
@@ -299,17 +303,18 @@ private:
 
 	// --------------------------------------------------------
 	template <template <typename> class TOUT, typename T>
-	void ResolvePointer(TOUT<T>& out, const Pointer & ptrval, 
-		const FileDatabase& db, const Field& f) const;
+	bool ResolvePointer(TOUT<T>& out, const Pointer & ptrval, 
+		const FileDatabase& db, const Field& f,
+		bool non_recursive = false) const;
 
 	// --------------------------------------------------------
 	template <template <typename> class TOUT, typename T>
-	void ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, 
-		const FileDatabase& db, const Field& f) const;
+	bool ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, 
+		const FileDatabase& db, const Field& f, bool) const;
 
 	// --------------------------------------------------------
-	void ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, 
-		const FileDatabase& db, const Field& f) const;
+	bool ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, 
+		const FileDatabase& db, const Field& f, bool) const;
 
 	// --------------------------------------------------------
 	inline const FileBlockHead* LocateFileBlockForAddress(
@@ -384,10 +389,11 @@ template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> {
 };
 
 // -------------------------------------------------------------------------------------------------------
-template <> inline void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, 
+template <> inline bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, 
 	const Pointer & ptrval, 
 	const FileDatabase& db, 
-	const Field& f
+	const Field& f,
+	bool
 	) const;
 
 

+ 53 - 27
code/BlenderDNA.inl

@@ -180,7 +180,8 @@ void Structure :: ReadFieldArray2(T (& out)[M][N], const char* name, const FileD
 
 //--------------------------------------------------------------------------------
 template <int error_policy, template <typename> class TOUT, typename T>
-void Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabase& db) const
+bool Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabase& db,
+	bool non_recursive /*= false*/) const
 {
 	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
 	Pointer ptrval;
@@ -203,23 +204,27 @@ void Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabas
 		_defaultInitializer<error_policy>()(out,e.what());
 
 		out.reset();
-		return;
+		return false;
 	}
 
 	// resolve the pointer and load the corresponding structure
-	ResolvePointer(out,ptrval,db,*f);
+	const bool res = ResolvePointer(out,ptrval,db,*f, non_recursive);
 
-	// and recover the previous stream position
-	db.reader->SetCurrentPos(old);
+	if(!non_recursive) {
+		// and recover the previous stream position
+		db.reader->SetCurrentPos(old);
+	}
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 	++db.stats().fields_read;
 #endif
+
+	return res;
 }
 
 //--------------------------------------------------------------------------------
 template <int error_policy, template <typename> class TOUT, typename T, size_t N>
-void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name, 
+bool Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name, 
 	const FileDatabase& db) const
 {
 	// XXX see if we can reduce this to call to the 'normal' ReadFieldPtr
@@ -253,11 +258,13 @@ void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
 		for(size_t i = 0; i < N; ++i) {
 			out[i].reset();
 		}
-		return;
+		return false;
 	}
+
+	bool res = true;
 	for(size_t i = 0; i < N; ++i) {
 		// resolve the pointer and load the corresponding structure
-		ResolvePointer(out[i],ptrval[i],db,*f);
+		res = ResolvePointer(out[i],ptrval[i],db,*f) && res;
 	}
 
 	// and recover the previous stream position
@@ -266,6 +273,7 @@ void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 	++db.stats().fields_read;
 #endif
+	return res;
 }
 
 //--------------------------------------------------------------------------------
@@ -296,11 +304,13 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co
 
 //--------------------------------------------------------------------------------
 template <template <typename> class TOUT, typename T>
-void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db, const Field& f) const 
+bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db, 
+	const Field& f, 
+	bool non_recursive /*= false*/) const 
 {
-	out.reset();
+	out.reset(); // ensure null pointers work
 	if (!ptrval.val) { 
-		return;
+		return false;
 	}
 	const Structure& s = db.dna[f.type];
 	// find the file block the pointer is pointing to
@@ -318,7 +328,7 @@ void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const Fil
 	// try to retrieve the object from the cache
 	db.cache(out).get(s,out,ptrval); 
 	if (out) {
-		return;
+		return true;
 	}
 
 	// seek to this location, but save the previous stream pointer.
@@ -334,27 +344,36 @@ void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const Fil
 	// cache the object before we convert it to avoid cyclic recursion.
 	db.cache(out).set(s,out,ptrval); 
 
-	for (size_t i = 0; i < num; ++i,++o) {
-		s.Convert(*o,db);
-	}
+	// if the non_recursive flag is set, we don't do anything but leave
+	// the cursor at the correct position to resolve the object.
+	if (!non_recursive) {
+		for (size_t i = 0; i < num; ++i,++o) {
+			s.Convert(*o,db);
+		}
 
-	db.reader->SetCurrentPos(pold);
+		db.reader->SetCurrentPos(pold);
+	}
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 	if(out) {
 		++db.stats().pointers_resolved;
 	}
 #endif
+	return false;
 }
 
+
 //--------------------------------------------------------------------------------
-inline void Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, const FileDatabase& db, const Field& /*f*/) const
+inline bool Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, 
+	const FileDatabase& db, 
+	const Field&,
+	bool) const
 {
 	// Currently used exclusively by PackedFile::data to represent
 	// a simple offset into the mapped BLEND file. 
 	out.reset();
 	if (!ptrval.val) { 
-		return;
+		return false;
 	}
 
 	// find the file block the pointer is pointing to
@@ -362,11 +381,15 @@ inline void Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, c
 
 	out =  boost::shared_ptr< FileOffset > (new FileOffset());
 	out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
+	return false;
 }
 
 //--------------------------------------------------------------------------------
 template <template <typename> class TOUT, typename T>
-void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, const FileDatabase& db, const Field& f) const 
+bool Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, 
+	const FileDatabase& db, 
+	const Field& f,
+	bool) const 
 {
 	// This is a function overload, not a template specialization. According to
 	// the partial ordering rules, it should be selected by the compiler
@@ -374,7 +397,7 @@ void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
 
 	out.reset();
 	if (!ptrval.val) { 
-		return;
+		return false;
 	}
 
 	// find the file block the pointer is pointing to
@@ -385,6 +408,7 @@ void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
 	const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
 	db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
 
+	bool res = false;
 	// allocate raw storage for the array
 	out.resize(num);
 	for (size_t i = 0; i< num; ++i) {
@@ -392,17 +416,19 @@ void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
 		Convert(val,db);
 
 		// and resolve the pointees
-		ResolvePointer(out[i],val,db,f); 
+		res = ResolvePointer(out[i],val,db,f) && res; 
 	}
 
 	db.reader->SetCurrentPos(pold);
+	return res;
 }
 
 //--------------------------------------------------------------------------------
-template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, 
+template <> bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, 
 	const Pointer & ptrval, 
 	const FileDatabase& db, 
-	const Field& /*f*/
+	const Field&,
+	bool
 ) const 
 {
 	// Special case when the data type needs to be determined at runtime.
@@ -410,7 +436,7 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
 
 	out.reset();
 	if (!ptrval.val) { 
-		return;
+		return false;
 	}
 
 	// find the file block the pointer is pointing to
@@ -422,7 +448,7 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
 	// try to retrieve the object from the cache
 	db.cache(out).get(s,out,ptrval); 
 	if (out) {
-		return;
+		return true;
 	}
 
 	// seek to this location, but save the previous stream pointer.
@@ -440,7 +466,7 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
 		DefaultLogger::get()->warn((Formatter::format(),
 			"Failed to find a converter for the `",s.name,"` structure"
 			));
-		return;
+		return false;
 	}
 
 	// allocate the object hull
@@ -459,11 +485,11 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
 	// to perform additional type checking.
 	out->dna_type = s.name.c_str();
 
-	
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 	++db.stats().pointers_resolved;
 #endif
+	return false;
 }
 
 //--------------------------------------------------------------------------------

+ 665 - 638
code/BlenderScene.cpp

@@ -51,644 +51,671 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace Assimp;
 using namespace Assimp::Blender;
 
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<Object> (
-    Object& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
-    ReadFieldArray2<ErrorPolicy_Warn>(dest.obmat,"obmat",db);
-    ReadFieldArray2<ErrorPolicy_Warn>(dest.parentinv,"parentinv",db);
-    ReadFieldArray<ErrorPolicy_Warn>(dest.parsubstr,"parsubstr",db);
-    {
-        boost::shared_ptr<Object> parent;
-        ReadFieldPtr<ErrorPolicy_Warn>(parent,"*parent",db);
-        dest.parent = parent.get();
-    }
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.track,"*track",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy,"*proxy",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy_from,"*proxy_from",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy_group,"*proxy_group",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.dup_group,"*dup_group",db);
-    ReadFieldPtr<ErrorPolicy_Fail>(dest.data,"*data",db);
-    ReadField<ErrorPolicy_Igno>(dest.modifiers,"modifiers",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<Group> (
-    Group& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadField<ErrorPolicy_Igno>(dest.layer,"layer",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.gobject,"*gobject",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MTex> (
-    MTex& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Igno>((int&)dest.blendtype,"blendtype",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.object,"*object",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.tex,"*tex",db);
-    ReadFieldArray<ErrorPolicy_Igno>(dest.uvname,"uvname",db);
-    ReadField<ErrorPolicy_Igno>((int&)dest.projx,"projx",db);
-    ReadField<ErrorPolicy_Igno>((int&)dest.projy,"projy",db);
-    ReadField<ErrorPolicy_Igno>((int&)dest.projz,"projz",db);
-    ReadField<ErrorPolicy_Igno>(dest.mapping,"mapping",db);
-    ReadFieldArray<ErrorPolicy_Igno>(dest.ofs,"ofs",db);
-    ReadFieldArray<ErrorPolicy_Igno>(dest.size,"size",db);
-    ReadField<ErrorPolicy_Igno>(dest.rot,"rot",db);
-    ReadField<ErrorPolicy_Igno>(dest.texflag,"texflag",db);
-    ReadField<ErrorPolicy_Igno>(dest.colormodel,"colormodel",db);
-    ReadField<ErrorPolicy_Igno>(dest.pmapto,"pmapto",db);
-    ReadField<ErrorPolicy_Igno>(dest.pmaptoneg,"pmaptoneg",db);
-    ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
-    ReadField<ErrorPolicy_Warn>(dest.g,"g",db);
-    ReadField<ErrorPolicy_Warn>(dest.b,"b",db);
-    ReadField<ErrorPolicy_Warn>(dest.k,"k",db);
-    ReadField<ErrorPolicy_Igno>(dest.colspecfac,"colspecfac",db);
-    ReadField<ErrorPolicy_Igno>(dest.mirrfac,"mirrfac",db);
-    ReadField<ErrorPolicy_Igno>(dest.alphafac,"alphafac",db);
-    ReadField<ErrorPolicy_Igno>(dest.difffac,"difffac",db);
-    ReadField<ErrorPolicy_Igno>(dest.specfac,"specfac",db);
-    ReadField<ErrorPolicy_Igno>(dest.emitfac,"emitfac",db);
-    ReadField<ErrorPolicy_Igno>(dest.hardfac,"hardfac",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<TFace> (
-    TFace& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db);
-    ReadFieldArray<ErrorPolicy_Fail>(dest.col,"col",db);
-    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-    ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
-    ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
-    ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<SubsurfModifierData> (
-    SubsurfModifierData& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db);
-    ReadField<ErrorPolicy_Warn>(dest.subdivType,"subdivType",db);
-    ReadField<ErrorPolicy_Fail>(dest.levels,"levels",db);
-    ReadField<ErrorPolicy_Igno>(dest.renderLevels,"renderLevels",db);
-    ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MFace> (
-    MFace& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db);
-    ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db);
-    ReadField<ErrorPolicy_Fail>(dest.v3,"v3",db);
-    ReadField<ErrorPolicy_Fail>(dest.v4,"v4",db);
-    ReadField<ErrorPolicy_Fail>(dest.mat_nr,"mat_nr",db);
-    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<Lamp> (
-    Lamp& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
-    ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db);
-    ReadField<ErrorPolicy_Igno>(dest.colormodel,"colormodel",db);
-    ReadField<ErrorPolicy_Igno>(dest.totex,"totex",db);
-    ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
-    ReadField<ErrorPolicy_Warn>(dest.g,"g",db);
-    ReadField<ErrorPolicy_Warn>(dest.b,"b",db);
-    ReadField<ErrorPolicy_Warn>(dest.k,"k",db);
-    ReadField<ErrorPolicy_Igno>(dest.energy,"energy",db);
-    ReadField<ErrorPolicy_Igno>(dest.dist,"dist",db);
-    ReadField<ErrorPolicy_Igno>(dest.spotsize,"spotsize",db);
-    ReadField<ErrorPolicy_Igno>(dest.spotblend,"spotblend",db);
-    ReadField<ErrorPolicy_Igno>(dest.att1,"att1",db);
-    ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db);
-    ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db);
-    ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MDeformWeight> (
-    MDeformWeight& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.def_nr,"def_nr",db);
-    ReadField<ErrorPolicy_Fail>(dest.weight,"weight",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<PackedFile> (
-    PackedFile& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Warn>(dest.size,"size",db);
-    ReadField<ErrorPolicy_Warn>(dest.seek,"seek",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.data,"*data",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<Base> (
-    Base& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    {
-        boost::shared_ptr<Base> prev;
-        ReadFieldPtr<ErrorPolicy_Warn>(prev,"*prev",db);
-        dest.prev = prev.get();
-    }
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.next,"*next",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.object,"*object",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MTFace> (
-    MTFace& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db);
-    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-    ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
-    ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
-    ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<Material> (
-    Material& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
-    ReadField<ErrorPolicy_Warn>(dest.g,"g",db);
-    ReadField<ErrorPolicy_Warn>(dest.b,"b",db);
-    ReadField<ErrorPolicy_Warn>(dest.specr,"specr",db);
-    ReadField<ErrorPolicy_Warn>(dest.specg,"specg",db);
-    ReadField<ErrorPolicy_Warn>(dest.specb,"specb",db);
-    ReadField<ErrorPolicy_Igno>(dest.har,"har",db);
-    ReadField<ErrorPolicy_Warn>(dest.ambr,"ambr",db);
-    ReadField<ErrorPolicy_Warn>(dest.ambg,"ambg",db);
-    ReadField<ErrorPolicy_Warn>(dest.ambb,"ambb",db);
-    ReadField<ErrorPolicy_Igno>(dest.mirr,"mirr",db);
-    ReadField<ErrorPolicy_Igno>(dest.mirg,"mirg",db);
-    ReadField<ErrorPolicy_Igno>(dest.mirb,"mirb",db);
-    ReadField<ErrorPolicy_Warn>(dest.emit,"emit",db);
-    ReadField<ErrorPolicy_Warn>(dest.alpha,"alpha",db);
-    ReadField<ErrorPolicy_Igno>(dest.ref,"ref",db);
-    ReadField<ErrorPolicy_Igno>(dest.translucency,"translucency",db);
-    ReadField<ErrorPolicy_Igno>(dest.roughness,"roughness",db);
-    ReadField<ErrorPolicy_Igno>(dest.darkness,"darkness",db);
-    ReadField<ErrorPolicy_Igno>(dest.refrac,"refrac",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.group,"*group",db);
-    ReadField<ErrorPolicy_Warn>(dest.diff_shader,"diff_shader",db);
-    ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.mtex,"*mtex",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MTexPoly> (
-    MTexPoly& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    {
-        boost::shared_ptr<Image> tpage;
-        ReadFieldPtr<ErrorPolicy_Igno>(tpage,"*tpage",db);
-        dest.tpage = tpage.get();
-    }
-    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-    ReadField<ErrorPolicy_Igno>(dest.transp,"transp",db);
-    ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
-    ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
-    ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<Mesh> (
-    Mesh& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadField<ErrorPolicy_Fail>(dest.totface,"totface",db);
-    ReadField<ErrorPolicy_Fail>(dest.totedge,"totedge",db);
-    ReadField<ErrorPolicy_Fail>(dest.totvert,"totvert",db);
-    ReadField<ErrorPolicy_Igno>(dest.totloop,"totloop",db);
-    ReadField<ErrorPolicy_Igno>(dest.totpoly,"totpoly",db);
-    ReadField<ErrorPolicy_Igno>(dest.subdiv,"subdiv",db);
-    ReadField<ErrorPolicy_Igno>(dest.subdivr,"subdivr",db);
-    ReadField<ErrorPolicy_Igno>(dest.subsurftype,"subsurftype",db);
-    ReadField<ErrorPolicy_Igno>(dest.smoothresh,"smoothresh",db);
-    ReadFieldPtr<ErrorPolicy_Fail>(dest.mface,"*mface",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.mtface,"*mtface",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.tface,"*tface",db);
-    ReadFieldPtr<ErrorPolicy_Fail>(dest.mvert,"*mvert",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.medge,"*medge",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.mloop,"*mloop",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.mloopuv,"*mloopuv",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.mloopcol,"*mloopcol",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.mpoly,"*mpoly",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.mtpoly,"*mtpoly",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.dvert,"*dvert",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
-    ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MDeformVert> (
-    MDeformVert& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.dw,"*dw",db);
-    ReadField<ErrorPolicy_Igno>(dest.totweight,"totweight",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<World> (
-    World& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MLoopCol> (
-    MLoopCol& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Igno>(dest.r,"r",db);
-    ReadField<ErrorPolicy_Igno>(dest.g,"g",db);
-    ReadField<ErrorPolicy_Igno>(dest.b,"b",db);
-    ReadField<ErrorPolicy_Igno>(dest.a,"a",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MVert> (
-    MVert& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadFieldArray<ErrorPolicy_Fail>(dest.co,"co",db);
-    ReadFieldArray<ErrorPolicy_Fail>(dest.no,"no",db);
-    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-    ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
-    ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MEdge> (
-    MEdge& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db);
-    ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db);
-    ReadField<ErrorPolicy_Igno>(dest.crease,"crease",db);
-    ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
-    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MLoopUV> (
-    MLoopUV& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadFieldArray<ErrorPolicy_Igno>(dest.uv,"uv",db);
-    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<GroupObject> (
-    GroupObject& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadFieldPtr<ErrorPolicy_Fail>(dest.prev,"*prev",db);
-    ReadFieldPtr<ErrorPolicy_Fail>(dest.next,"*next",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.ob,"*ob",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<ListBase> (
-    ListBase& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.first,"*first",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.last,"*last",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MLoop> (
-    MLoop& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Igno>(dest.v,"v",db);
-    ReadField<ErrorPolicy_Igno>(dest.e,"e",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<ModifierData> (
-    ModifierData& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.next,"*next",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.prev,"*prev",db);
-    ReadField<ErrorPolicy_Igno>(dest.type,"type",db);
-    ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
-    ReadFieldArray<ErrorPolicy_Igno>(dest.name,"name",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<ID> (
-    ID& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
-    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MCol> (
-    MCol& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.r,"r",db);
-    ReadField<ErrorPolicy_Fail>(dest.g,"g",db);
-    ReadField<ErrorPolicy_Fail>(dest.b,"b",db);
-    ReadField<ErrorPolicy_Fail>(dest.a,"a",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MPoly> (
-    MPoly& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Igno>(dest.loopstart,"loopstart",db);
-    ReadField<ErrorPolicy_Igno>(dest.totloop,"totloop",db);
-    ReadField<ErrorPolicy_Igno>(dest.mat_nr,"mat_nr",db);
-    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<Scene> (
-    Scene& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.camera,"*camera",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.world,"*world",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.basact,"*basact",db);
-    ReadField<ErrorPolicy_Igno>(dest.base,"base",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<Library> (
-    Library& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
-    ReadFieldArray<ErrorPolicy_Fail>(dest.filename,"filename",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.parent,"*parent",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<Tex> (
-    Tex& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.ima,"*ima",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<Camera> (
-    Camera& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadField<ErrorPolicy_Warn>((int&)dest.type,"type",db);
-    ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db);
-    ReadField<ErrorPolicy_Warn>(dest.angle,"angle",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<MirrorModifierData> (
-    MirrorModifierData& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db);
-    ReadField<ErrorPolicy_Igno>(dest.axis,"axis",db);
-    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-    ReadField<ErrorPolicy_Igno>(dest.tolerance,"tolerance",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.mirror_ob,"*mirror_ob",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-template <> void Structure :: Convert<Image> (
-    Image& dest,
-    const FileDatabase& db
-    ) const
-{ 
-
-    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
-    ReadField<ErrorPolicy_Igno>(dest.ok,"ok",db);
-    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-    ReadField<ErrorPolicy_Igno>(dest.source,"source",db);
-    ReadField<ErrorPolicy_Igno>(dest.type,"type",db);
-    ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
-    ReadField<ErrorPolicy_Igno>(dest.pad1,"pad1",db);
-    ReadField<ErrorPolicy_Igno>(dest.lastframe,"lastframe",db);
-    ReadField<ErrorPolicy_Igno>(dest.tpageflag,"tpageflag",db);
-    ReadField<ErrorPolicy_Igno>(dest.totbind,"totbind",db);
-    ReadField<ErrorPolicy_Igno>(dest.xrep,"xrep",db);
-    ReadField<ErrorPolicy_Igno>(dest.yrep,"yrep",db);
-    ReadField<ErrorPolicy_Igno>(dest.twsta,"twsta",db);
-    ReadField<ErrorPolicy_Igno>(dest.twend,"twend",db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.packedfile,"*packedfile",db);
-    ReadField<ErrorPolicy_Igno>(dest.lastupdate,"lastupdate",db);
-    ReadField<ErrorPolicy_Igno>(dest.lastused,"lastused",db);
-    ReadField<ErrorPolicy_Igno>(dest.animspeed,"animspeed",db);
-    ReadField<ErrorPolicy_Igno>(dest.gen_x,"gen_x",db);
-    ReadField<ErrorPolicy_Igno>(dest.gen_y,"gen_y",db);
-    ReadField<ErrorPolicy_Igno>(dest.gen_type,"gen_type",db);
-
-	db.reader->IncPtr(size);
-}
-
-//--------------------------------------------------------------------------------
-void DNA::RegisterConverters() {
-
-    converters["Object"] = DNA::FactoryPair( &Structure::Allocate<Object>, &Structure::Convert<Object> );
-    converters["Group"] = DNA::FactoryPair( &Structure::Allocate<Group>, &Structure::Convert<Group> );
-    converters["MTex"] = DNA::FactoryPair( &Structure::Allocate<MTex>, &Structure::Convert<MTex> );
-    converters["TFace"] = DNA::FactoryPair( &Structure::Allocate<TFace>, &Structure::Convert<TFace> );
-    converters["SubsurfModifierData"] = DNA::FactoryPair( &Structure::Allocate<SubsurfModifierData>, &Structure::Convert<SubsurfModifierData> );
-    converters["MFace"] = DNA::FactoryPair( &Structure::Allocate<MFace>, &Structure::Convert<MFace> );
-    converters["Lamp"] = DNA::FactoryPair( &Structure::Allocate<Lamp>, &Structure::Convert<Lamp> );
-    converters["MDeformWeight"] = DNA::FactoryPair( &Structure::Allocate<MDeformWeight>, &Structure::Convert<MDeformWeight> );
-    converters["PackedFile"] = DNA::FactoryPair( &Structure::Allocate<PackedFile>, &Structure::Convert<PackedFile> );
-    converters["Base"] = DNA::FactoryPair( &Structure::Allocate<Base>, &Structure::Convert<Base> );
-    converters["MTFace"] = DNA::FactoryPair( &Structure::Allocate<MTFace>, &Structure::Convert<MTFace> );
-    converters["Material"] = DNA::FactoryPair( &Structure::Allocate<Material>, &Structure::Convert<Material> );
-    converters["MTexPoly"] = DNA::FactoryPair( &Structure::Allocate<MTexPoly>, &Structure::Convert<MTexPoly> );
-    converters["Mesh"] = DNA::FactoryPair( &Structure::Allocate<Mesh>, &Structure::Convert<Mesh> );
-    converters["MDeformVert"] = DNA::FactoryPair( &Structure::Allocate<MDeformVert>, &Structure::Convert<MDeformVert> );
-    converters["World"] = DNA::FactoryPair( &Structure::Allocate<World>, &Structure::Convert<World> );
-    converters["MLoopCol"] = DNA::FactoryPair( &Structure::Allocate<MLoopCol>, &Structure::Convert<MLoopCol> );
-    converters["MVert"] = DNA::FactoryPair( &Structure::Allocate<MVert>, &Structure::Convert<MVert> );
-    converters["MEdge"] = DNA::FactoryPair( &Structure::Allocate<MEdge>, &Structure::Convert<MEdge> );
-    converters["MLoopUV"] = DNA::FactoryPair( &Structure::Allocate<MLoopUV>, &Structure::Convert<MLoopUV> );
-    converters["GroupObject"] = DNA::FactoryPair( &Structure::Allocate<GroupObject>, &Structure::Convert<GroupObject> );
-    converters["ListBase"] = DNA::FactoryPair( &Structure::Allocate<ListBase>, &Structure::Convert<ListBase> );
-    converters["MLoop"] = DNA::FactoryPair( &Structure::Allocate<MLoop>, &Structure::Convert<MLoop> );
-    converters["ModifierData"] = DNA::FactoryPair( &Structure::Allocate<ModifierData>, &Structure::Convert<ModifierData> );
-    converters["ID"] = DNA::FactoryPair( &Structure::Allocate<ID>, &Structure::Convert<ID> );
-    converters["MCol"] = DNA::FactoryPair( &Structure::Allocate<MCol>, &Structure::Convert<MCol> );
-    converters["MPoly"] = DNA::FactoryPair( &Structure::Allocate<MPoly>, &Structure::Convert<MPoly> );
-    converters["Scene"] = DNA::FactoryPair( &Structure::Allocate<Scene>, &Structure::Convert<Scene> );
-    converters["Library"] = DNA::FactoryPair( &Structure::Allocate<Library>, &Structure::Convert<Library> );
-    converters["Tex"] = DNA::FactoryPair( &Structure::Allocate<Tex>, &Structure::Convert<Tex> );
-    converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> );
-    converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> );
-    converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
-}
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<Object> (
+    Object& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
+    ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
+    ReadFieldArray2<ErrorPolicy_Warn>(dest.obmat,"obmat",db);
+    ReadFieldArray2<ErrorPolicy_Warn>(dest.parentinv,"parentinv",db);
+    ReadFieldArray<ErrorPolicy_Warn>(dest.parsubstr,"parsubstr",db);
+    {
+        boost::shared_ptr<Object> parent;
+        ReadFieldPtr<ErrorPolicy_Warn>(parent,"*parent",db);
+        dest.parent = parent.get();
+    }
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.track,"*track",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy,"*proxy",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy_from,"*proxy_from",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy_group,"*proxy_group",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.dup_group,"*dup_group",db);
+    ReadFieldPtr<ErrorPolicy_Fail>(dest.data,"*data",db);
+    ReadField<ErrorPolicy_Igno>(dest.modifiers,"modifiers",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<Group> (
+    Group& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
+    ReadField<ErrorPolicy_Igno>(dest.layer,"layer",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.gobject,"*gobject",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MTex> (
+    MTex& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Igno>((int&)dest.blendtype,"blendtype",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.object,"*object",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.tex,"*tex",db);
+    ReadFieldArray<ErrorPolicy_Igno>(dest.uvname,"uvname",db);
+    ReadField<ErrorPolicy_Igno>((int&)dest.projx,"projx",db);
+    ReadField<ErrorPolicy_Igno>((int&)dest.projy,"projy",db);
+    ReadField<ErrorPolicy_Igno>((int&)dest.projz,"projz",db);
+    ReadField<ErrorPolicy_Igno>(dest.mapping,"mapping",db);
+    ReadFieldArray<ErrorPolicy_Igno>(dest.ofs,"ofs",db);
+    ReadFieldArray<ErrorPolicy_Igno>(dest.size,"size",db);
+    ReadField<ErrorPolicy_Igno>(dest.rot,"rot",db);
+    ReadField<ErrorPolicy_Igno>(dest.texflag,"texflag",db);
+    ReadField<ErrorPolicy_Igno>(dest.colormodel,"colormodel",db);
+    ReadField<ErrorPolicy_Igno>(dest.pmapto,"pmapto",db);
+    ReadField<ErrorPolicy_Igno>(dest.pmaptoneg,"pmaptoneg",db);
+    ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
+    ReadField<ErrorPolicy_Warn>(dest.g,"g",db);
+    ReadField<ErrorPolicy_Warn>(dest.b,"b",db);
+    ReadField<ErrorPolicy_Warn>(dest.k,"k",db);
+    ReadField<ErrorPolicy_Igno>(dest.colspecfac,"colspecfac",db);
+    ReadField<ErrorPolicy_Igno>(dest.mirrfac,"mirrfac",db);
+    ReadField<ErrorPolicy_Igno>(dest.alphafac,"alphafac",db);
+    ReadField<ErrorPolicy_Igno>(dest.difffac,"difffac",db);
+    ReadField<ErrorPolicy_Igno>(dest.specfac,"specfac",db);
+    ReadField<ErrorPolicy_Igno>(dest.emitfac,"emitfac",db);
+    ReadField<ErrorPolicy_Igno>(dest.hardfac,"hardfac",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<TFace> (
+    TFace& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db);
+    ReadFieldArray<ErrorPolicy_Fail>(dest.col,"col",db);
+    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
+    ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
+    ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
+    ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<SubsurfModifierData> (
+    SubsurfModifierData& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db);
+    ReadField<ErrorPolicy_Warn>(dest.subdivType,"subdivType",db);
+    ReadField<ErrorPolicy_Fail>(dest.levels,"levels",db);
+    ReadField<ErrorPolicy_Igno>(dest.renderLevels,"renderLevels",db);
+    ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MFace> (
+    MFace& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db);
+    ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db);
+    ReadField<ErrorPolicy_Fail>(dest.v3,"v3",db);
+    ReadField<ErrorPolicy_Fail>(dest.v4,"v4",db);
+    ReadField<ErrorPolicy_Fail>(dest.mat_nr,"mat_nr",db);
+    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<Lamp> (
+    Lamp& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
+    ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
+    ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db);
+    ReadField<ErrorPolicy_Igno>(dest.colormodel,"colormodel",db);
+    ReadField<ErrorPolicy_Igno>(dest.totex,"totex",db);
+    ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
+    ReadField<ErrorPolicy_Warn>(dest.g,"g",db);
+    ReadField<ErrorPolicy_Warn>(dest.b,"b",db);
+    ReadField<ErrorPolicy_Warn>(dest.k,"k",db);
+    ReadField<ErrorPolicy_Igno>(dest.energy,"energy",db);
+    ReadField<ErrorPolicy_Igno>(dest.dist,"dist",db);
+    ReadField<ErrorPolicy_Igno>(dest.spotsize,"spotsize",db);
+    ReadField<ErrorPolicy_Igno>(dest.spotblend,"spotblend",db);
+    ReadField<ErrorPolicy_Igno>(dest.att1,"att1",db);
+    ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db);
+    ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db);
+    ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MDeformWeight> (
+    MDeformWeight& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.def_nr,"def_nr",db);
+    ReadField<ErrorPolicy_Fail>(dest.weight,"weight",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<PackedFile> (
+    PackedFile& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Warn>(dest.size,"size",db);
+    ReadField<ErrorPolicy_Warn>(dest.seek,"seek",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.data,"*data",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<Base> (
+    Base& dest,
+    const FileDatabase& db
+    ) const
+{ 
+	// note: as per https://github.com/assimp/assimp/issues/128,
+	// reading the Object linked list recursively is prone to stack overflow.
+	// This structure converter is therefore an hand-written exception that
+	// does it iteratively.
+
+	const int initial_pos = db.reader->GetCurrentPos();
+
+	std::pair<Base*, int> todo = std::make_pair(&dest, initial_pos);
+
+	Base* saved_prev = NULL;
+
+	while(true) {
+	
+		Base& cur_dest = *todo.first;
+		db.reader->SetCurrentPos(todo.second);
+
+		// we know that this is a double-linked, circular list which we never
+		// traverse backwards, so don't bother resolving the back links.
+		cur_dest.prev = NULL;
+
+		ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.object,"*object",db);
+
+		// just record the offset of the blob data and allocate storage.
+		// Does _not_ invoke Convert() recursively.
+		const int old = db.reader->GetCurrentPos();
+
+		// the return value of ReadFieldPtr indicates whether the object 
+		// was already cached. In this case, we don't need to resolve
+		// it again.
+		if(!ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.next,"*next",db, true) && cur_dest.next) {
+			todo = std::make_pair(&*cur_dest.next, db.reader->GetCurrentPos());
+			continue;
+		}
+		break;
+	}
+	
+	db.reader->SetCurrentPos(initial_pos + size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MTFace> (
+    MTFace& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db);
+    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
+    ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
+    ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
+    ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<Material> (
+    Material& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
+    ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
+    ReadField<ErrorPolicy_Warn>(dest.g,"g",db);
+    ReadField<ErrorPolicy_Warn>(dest.b,"b",db);
+    ReadField<ErrorPolicy_Warn>(dest.specr,"specr",db);
+    ReadField<ErrorPolicy_Warn>(dest.specg,"specg",db);
+    ReadField<ErrorPolicy_Warn>(dest.specb,"specb",db);
+    ReadField<ErrorPolicy_Igno>(dest.har,"har",db);
+    ReadField<ErrorPolicy_Warn>(dest.ambr,"ambr",db);
+    ReadField<ErrorPolicy_Warn>(dest.ambg,"ambg",db);
+    ReadField<ErrorPolicy_Warn>(dest.ambb,"ambb",db);
+    ReadField<ErrorPolicy_Igno>(dest.mirr,"mirr",db);
+    ReadField<ErrorPolicy_Igno>(dest.mirg,"mirg",db);
+    ReadField<ErrorPolicy_Igno>(dest.mirb,"mirb",db);
+    ReadField<ErrorPolicy_Warn>(dest.emit,"emit",db);
+    ReadField<ErrorPolicy_Warn>(dest.alpha,"alpha",db);
+    ReadField<ErrorPolicy_Igno>(dest.ref,"ref",db);
+    ReadField<ErrorPolicy_Igno>(dest.translucency,"translucency",db);
+    ReadField<ErrorPolicy_Igno>(dest.roughness,"roughness",db);
+    ReadField<ErrorPolicy_Igno>(dest.darkness,"darkness",db);
+    ReadField<ErrorPolicy_Igno>(dest.refrac,"refrac",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.group,"*group",db);
+    ReadField<ErrorPolicy_Warn>(dest.diff_shader,"diff_shader",db);
+    ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.mtex,"*mtex",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MTexPoly> (
+    MTexPoly& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    {
+        boost::shared_ptr<Image> tpage;
+        ReadFieldPtr<ErrorPolicy_Igno>(tpage,"*tpage",db);
+        dest.tpage = tpage.get();
+    }
+    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
+    ReadField<ErrorPolicy_Igno>(dest.transp,"transp",db);
+    ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
+    ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
+    ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<Mesh> (
+    Mesh& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
+    ReadField<ErrorPolicy_Fail>(dest.totface,"totface",db);
+    ReadField<ErrorPolicy_Fail>(dest.totedge,"totedge",db);
+    ReadField<ErrorPolicy_Fail>(dest.totvert,"totvert",db);
+    ReadField<ErrorPolicy_Igno>(dest.totloop,"totloop",db);
+    ReadField<ErrorPolicy_Igno>(dest.totpoly,"totpoly",db);
+    ReadField<ErrorPolicy_Igno>(dest.subdiv,"subdiv",db);
+    ReadField<ErrorPolicy_Igno>(dest.subdivr,"subdivr",db);
+    ReadField<ErrorPolicy_Igno>(dest.subsurftype,"subsurftype",db);
+    ReadField<ErrorPolicy_Igno>(dest.smoothresh,"smoothresh",db);
+    ReadFieldPtr<ErrorPolicy_Fail>(dest.mface,"*mface",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.mtface,"*mtface",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.tface,"*tface",db);
+    ReadFieldPtr<ErrorPolicy_Fail>(dest.mvert,"*mvert",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.medge,"*medge",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.mloop,"*mloop",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.mloopuv,"*mloopuv",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.mloopcol,"*mloopcol",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.mpoly,"*mpoly",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.mtpoly,"*mtpoly",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.dvert,"*dvert",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
+    ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MDeformVert> (
+    MDeformVert& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.dw,"*dw",db);
+    ReadField<ErrorPolicy_Igno>(dest.totweight,"totweight",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<World> (
+    World& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MLoopCol> (
+    MLoopCol& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Igno>(dest.r,"r",db);
+    ReadField<ErrorPolicy_Igno>(dest.g,"g",db);
+    ReadField<ErrorPolicy_Igno>(dest.b,"b",db);
+    ReadField<ErrorPolicy_Igno>(dest.a,"a",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MVert> (
+    MVert& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadFieldArray<ErrorPolicy_Fail>(dest.co,"co",db);
+    ReadFieldArray<ErrorPolicy_Fail>(dest.no,"no",db);
+    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
+    ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
+    ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MEdge> (
+    MEdge& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db);
+    ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db);
+    ReadField<ErrorPolicy_Igno>(dest.crease,"crease",db);
+    ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
+    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MLoopUV> (
+    MLoopUV& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadFieldArray<ErrorPolicy_Igno>(dest.uv,"uv",db);
+    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<GroupObject> (
+    GroupObject& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadFieldPtr<ErrorPolicy_Fail>(dest.prev,"*prev",db);
+    ReadFieldPtr<ErrorPolicy_Fail>(dest.next,"*next",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.ob,"*ob",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<ListBase> (
+    ListBase& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.first,"*first",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.last,"*last",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MLoop> (
+    MLoop& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Igno>(dest.v,"v",db);
+    ReadField<ErrorPolicy_Igno>(dest.e,"e",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<ModifierData> (
+    ModifierData& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.next,"*next",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.prev,"*prev",db);
+    ReadField<ErrorPolicy_Igno>(dest.type,"type",db);
+    ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
+    ReadFieldArray<ErrorPolicy_Igno>(dest.name,"name",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<ID> (
+    ID& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
+    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MCol> (
+    MCol& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.r,"r",db);
+    ReadField<ErrorPolicy_Fail>(dest.g,"g",db);
+    ReadField<ErrorPolicy_Fail>(dest.b,"b",db);
+    ReadField<ErrorPolicy_Fail>(dest.a,"a",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MPoly> (
+    MPoly& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Igno>(dest.loopstart,"loopstart",db);
+    ReadField<ErrorPolicy_Igno>(dest.totloop,"totloop",db);
+    ReadField<ErrorPolicy_Igno>(dest.mat_nr,"mat_nr",db);
+    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<Scene> (
+    Scene& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.camera,"*camera",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.world,"*world",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.basact,"*basact",db);
+    ReadField<ErrorPolicy_Igno>(dest.base,"base",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<Library> (
+    Library& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
+    ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
+    ReadFieldArray<ErrorPolicy_Fail>(dest.filename,"filename",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.parent,"*parent",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<Tex> (
+    Tex& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.ima,"*ima",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<Camera> (
+    Camera& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
+    ReadField<ErrorPolicy_Warn>((int&)dest.type,"type",db);
+    ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db);
+    ReadField<ErrorPolicy_Warn>(dest.angle,"angle",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<MirrorModifierData> (
+    MirrorModifierData& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db);
+    ReadField<ErrorPolicy_Igno>(dest.axis,"axis",db);
+    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
+    ReadField<ErrorPolicy_Igno>(dest.tolerance,"tolerance",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.mirror_ob,"*mirror_ob",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure :: Convert<Image> (
+    Image& dest,
+    const FileDatabase& db
+    ) const
+{ 
+
+    ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
+    ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
+    ReadField<ErrorPolicy_Igno>(dest.ok,"ok",db);
+    ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
+    ReadField<ErrorPolicy_Igno>(dest.source,"source",db);
+    ReadField<ErrorPolicy_Igno>(dest.type,"type",db);
+    ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
+    ReadField<ErrorPolicy_Igno>(dest.pad1,"pad1",db);
+    ReadField<ErrorPolicy_Igno>(dest.lastframe,"lastframe",db);
+    ReadField<ErrorPolicy_Igno>(dest.tpageflag,"tpageflag",db);
+    ReadField<ErrorPolicy_Igno>(dest.totbind,"totbind",db);
+    ReadField<ErrorPolicy_Igno>(dest.xrep,"xrep",db);
+    ReadField<ErrorPolicy_Igno>(dest.yrep,"yrep",db);
+    ReadField<ErrorPolicy_Igno>(dest.twsta,"twsta",db);
+    ReadField<ErrorPolicy_Igno>(dest.twend,"twend",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.packedfile,"*packedfile",db);
+    ReadField<ErrorPolicy_Igno>(dest.lastupdate,"lastupdate",db);
+    ReadField<ErrorPolicy_Igno>(dest.lastused,"lastused",db);
+    ReadField<ErrorPolicy_Igno>(dest.animspeed,"animspeed",db);
+    ReadField<ErrorPolicy_Igno>(dest.gen_x,"gen_x",db);
+    ReadField<ErrorPolicy_Igno>(dest.gen_y,"gen_y",db);
+    ReadField<ErrorPolicy_Igno>(dest.gen_type,"gen_type",db);
+
+	db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+void DNA::RegisterConverters() {
+
+    converters["Object"] = DNA::FactoryPair( &Structure::Allocate<Object>, &Structure::Convert<Object> );
+    converters["Group"] = DNA::FactoryPair( &Structure::Allocate<Group>, &Structure::Convert<Group> );
+    converters["MTex"] = DNA::FactoryPair( &Structure::Allocate<MTex>, &Structure::Convert<MTex> );
+    converters["TFace"] = DNA::FactoryPair( &Structure::Allocate<TFace>, &Structure::Convert<TFace> );
+    converters["SubsurfModifierData"] = DNA::FactoryPair( &Structure::Allocate<SubsurfModifierData>, &Structure::Convert<SubsurfModifierData> );
+    converters["MFace"] = DNA::FactoryPair( &Structure::Allocate<MFace>, &Structure::Convert<MFace> );
+    converters["Lamp"] = DNA::FactoryPair( &Structure::Allocate<Lamp>, &Structure::Convert<Lamp> );
+    converters["MDeformWeight"] = DNA::FactoryPair( &Structure::Allocate<MDeformWeight>, &Structure::Convert<MDeformWeight> );
+    converters["PackedFile"] = DNA::FactoryPair( &Structure::Allocate<PackedFile>, &Structure::Convert<PackedFile> );
+    converters["Base"] = DNA::FactoryPair( &Structure::Allocate<Base>, &Structure::Convert<Base> );
+    converters["MTFace"] = DNA::FactoryPair( &Structure::Allocate<MTFace>, &Structure::Convert<MTFace> );
+    converters["Material"] = DNA::FactoryPair( &Structure::Allocate<Material>, &Structure::Convert<Material> );
+    converters["MTexPoly"] = DNA::FactoryPair( &Structure::Allocate<MTexPoly>, &Structure::Convert<MTexPoly> );
+    converters["Mesh"] = DNA::FactoryPair( &Structure::Allocate<Mesh>, &Structure::Convert<Mesh> );
+    converters["MDeformVert"] = DNA::FactoryPair( &Structure::Allocate<MDeformVert>, &Structure::Convert<MDeformVert> );
+    converters["World"] = DNA::FactoryPair( &Structure::Allocate<World>, &Structure::Convert<World> );
+    converters["MLoopCol"] = DNA::FactoryPair( &Structure::Allocate<MLoopCol>, &Structure::Convert<MLoopCol> );
+    converters["MVert"] = DNA::FactoryPair( &Structure::Allocate<MVert>, &Structure::Convert<MVert> );
+    converters["MEdge"] = DNA::FactoryPair( &Structure::Allocate<MEdge>, &Structure::Convert<MEdge> );
+    converters["MLoopUV"] = DNA::FactoryPair( &Structure::Allocate<MLoopUV>, &Structure::Convert<MLoopUV> );
+    converters["GroupObject"] = DNA::FactoryPair( &Structure::Allocate<GroupObject>, &Structure::Convert<GroupObject> );
+    converters["ListBase"] = DNA::FactoryPair( &Structure::Allocate<ListBase>, &Structure::Convert<ListBase> );
+    converters["MLoop"] = DNA::FactoryPair( &Structure::Allocate<MLoop>, &Structure::Convert<MLoop> );
+    converters["ModifierData"] = DNA::FactoryPair( &Structure::Allocate<ModifierData>, &Structure::Convert<ModifierData> );
+    converters["ID"] = DNA::FactoryPair( &Structure::Allocate<ID>, &Structure::Convert<ID> );
+    converters["MCol"] = DNA::FactoryPair( &Structure::Allocate<MCol>, &Structure::Convert<MCol> );
+    converters["MPoly"] = DNA::FactoryPair( &Structure::Allocate<MPoly>, &Structure::Convert<MPoly> );
+    converters["Scene"] = DNA::FactoryPair( &Structure::Allocate<Scene>, &Structure::Convert<Scene> );
+    converters["Library"] = DNA::FactoryPair( &Structure::Allocate<Library>, &Structure::Convert<Library> );
+    converters["Tex"] = DNA::FactoryPair( &Structure::Allocate<Tex>, &Structure::Convert<Tex> );
+    converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> );
+    converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> );
+    converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
+}
 
 
 #endif

+ 198 - 198
code/BlenderSceneGen.h

@@ -47,204 +47,204 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp	{
 	namespace Blender {
 
-
-template <> void Structure :: Convert<Object> (
-    Object& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<Group> (
-    Group& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MTex> (
-    MTex& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<TFace> (
-    TFace& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<SubsurfModifierData> (
-    SubsurfModifierData& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MFace> (
-    MFace& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<Lamp> (
-    Lamp& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MDeformWeight> (
-    MDeformWeight& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<PackedFile> (
-    PackedFile& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<Base> (
-    Base& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MTFace> (
-    MTFace& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<Material> (
-    Material& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MTexPoly> (
-    MTexPoly& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<Mesh> (
-    Mesh& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MDeformVert> (
-    MDeformVert& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<World> (
-    World& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MLoopCol> (
-    MLoopCol& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MVert> (
-    MVert& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MEdge> (
-    MEdge& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MLoopUV> (
-    MLoopUV& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<GroupObject> (
-    GroupObject& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<ListBase> (
-    ListBase& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MLoop> (
-    MLoop& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<ModifierData> (
-    ModifierData& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<ID> (
-    ID& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MCol> (
-    MCol& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MPoly> (
-    MPoly& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<Scene> (
-    Scene& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<Library> (
-    Library& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<Tex> (
-    Tex& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<Camera> (
-    Camera& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<MirrorModifierData> (
-    MirrorModifierData& dest,
-    const FileDatabase& db
-    ) const
-;
-
-template <> void Structure :: Convert<Image> (
-    Image& dest,
-    const FileDatabase& db
-    ) const
-;
+
+template <> void Structure :: Convert<Object> (
+    Object& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<Group> (
+    Group& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MTex> (
+    MTex& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<TFace> (
+    TFace& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<SubsurfModifierData> (
+    SubsurfModifierData& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MFace> (
+    MFace& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<Lamp> (
+    Lamp& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MDeformWeight> (
+    MDeformWeight& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<PackedFile> (
+    PackedFile& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<Base> (
+    Base& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MTFace> (
+    MTFace& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<Material> (
+    Material& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MTexPoly> (
+    MTexPoly& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<Mesh> (
+    Mesh& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MDeformVert> (
+    MDeformVert& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<World> (
+    World& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MLoopCol> (
+    MLoopCol& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MVert> (
+    MVert& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MEdge> (
+    MEdge& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MLoopUV> (
+    MLoopUV& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<GroupObject> (
+    GroupObject& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<ListBase> (
+    ListBase& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MLoop> (
+    MLoop& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<ModifierData> (
+    ModifierData& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<ID> (
+    ID& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MCol> (
+    MCol& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MPoly> (
+    MPoly& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<Scene> (
+    Scene& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<Library> (
+    Library& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<Tex> (
+    Tex& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<Camera> (
+    Camera& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<MirrorModifierData> (
+    MirrorModifierData& dest,
+    const FileDatabase& db
+    ) const
+;
+
+template <> void Structure :: Convert<Image> (
+    Image& dest,
+    const FileDatabase& db
+    ) const
+;
 
 
 	}

+ 55 - 2
scripts/BlenderImporter/genblenddna.py

@@ -5,7 +5,7 @@
 # Open Asset Import Library (ASSIMP)
 # ---------------------------------------------------------------------------
 #
-# Copyright (c) 2006-2010, ASSIMP Development Team
+# Copyright (c) 2006-2013, ASSIMP Development Team
 #
 # All rights reserved.
 #
@@ -55,6 +55,55 @@ outputfile_src = os.path.join("..","..","code","BlenderScene.cpp")
 template_gen = "BlenderSceneGen.h.template"
 template_src = "BlenderScene.cpp.template"
 
+# workaround for stackoverflowing when reading the linked list of scene objects
+# with the usual approach. See embedded notes for details.
+Structure_Convert_Base_fullcode = """
+template <> void Structure :: Convert<Base> (
+    Base& dest,
+    const FileDatabase& db
+    ) const
+{ 
+	// note: as per https://github.com/assimp/assimp/issues/128,
+	// reading the Object linked list recursively is prone to stack overflow.
+	// This structure converter is therefore an hand-written exception that
+	// does it iteratively.
+
+	const int initial_pos = db.reader->GetCurrentPos();
+
+	std::pair<Base*, int> todo = std::make_pair(&dest, initial_pos);
+
+	Base* saved_prev = NULL;
+
+	while(true) {
+	
+		Base& cur_dest = *todo.first;
+		db.reader->SetCurrentPos(todo.second);
+
+		// we know that this is a double-linked, circular list which we never
+		// traverse backwards, so don't bother resolving the back links.
+		cur_dest.prev = NULL;
+
+		ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.object,"*object",db);
+
+		// just record the offset of the blob data and allocate storage.
+		// Does _not_ invoke Convert() recursively.
+		const int old = db.reader->GetCurrentPos();
+
+		// the return value of ReadFieldPtr indicates whether the object 
+		// was already cached. In this case, we don't need to resolve
+		// it again.
+		if(!ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.next,"*next",db, true) && cur_dest.next) {
+			todo = std::make_pair(&*cur_dest.next, db.reader->GetCurrentPos());
+			continue;
+		}
+		break;
+	}
+	
+	db.reader->SetCurrentPos(initial_pos + size);
+}
+
+"""
+
 
 Structure_Convert_decl =  """
 template <> void Structure :: Convert<{a}> (
@@ -201,7 +250,11 @@ def main():
     # -----------------------------------------------------------------------
     # Structure::Convert<T> definitions for all supported structures
     for k,v in hits.items():
-        s += "//" + "-"*80 + Structure_Convert_decl.format(a=k)+ "{ \n";
+    	s += "//" + "-"*80
+    	if k == 'Base':
+    		s += Structure_Convert_Base_fullcode 
+    		continue
+        s += Structure_Convert_decl.format(a=k)+ "{ \n";
 
         for type, name, policy in v:
             splits = name.split("[",1)