瀏覽代碼

Merge commit '87a0e7703258576f1a7e4ba763b961da70c1cd91' into contrib

Conflicts:
	code/ColladaExporter.cpp
Léo Terziman 11 年之前
父節點
當前提交
6c0ebb679a

+ 1 - 1
CMakeLists.txt

@@ -72,7 +72,7 @@ add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/c
 
 # Globally enbale Boost resp. the Boost workaround – it is also needed by the
 # tools which include the Assimp headers.
-SET ( ASSIMP_ENABLE_BOOST_WORKAROUND OFF CACHE BOOL
+SET ( ASSIMP_ENABLE_BOOST_WORKAROUND ON CACHE BOOL
 	"If a simple implementation of the used Boost functions is used. Slightly reduces functionality, but enables builds without Boost available."
 )
 IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )

+ 26 - 24
Readme.md

@@ -1,7 +1,7 @@
 Open Asset Import Library (assimp) 
 ========
 
-Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a single, in-memory format__. It supports more than 30 file formats. It also supports exporting files to a few selected file formats.
+Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a single, in-memory format__. It supports more than 30 file formats. It also supports exporting files to a growing selection of file formats.
 
 Its abbreviated name under which it is commonly known is __assimp__. 
 
@@ -13,7 +13,7 @@ The library provides importers for a lot of file formats, including:
 
 - 3DS
 - BLEND (Blender 3D)
-- DAE (Collada)
+- DAE/Collada
 - FBX
 - IFC-STEP 
 - ASE
@@ -61,7 +61,7 @@ See [the full list here](http://assimp.sourceforge.net/main_features_formats.htm
 
 
 
-#### 1.2 Repository structure ####
+#### Repository structure ####
 
 
 Open Asset Import Library is implemented in C++ (but provides both a C and a 
@@ -71,48 +71,50 @@ C++ish interface). The directory structure is:
 	/code		Source code
 	/contrib	Third-party libraries
 	/doc		Documentation (doxysource and pre-compiled docs)
-	/include	Public header C and C++ header files.
-	/lib		Static library location for Windows.
-	/obj		Object file location for Windows.
-	/port		Ports to other languages and scripts to maintain those. 
-	/test		Unit- and regression tests, test suite of models.
-	/tools		Tools (viewer, command line `assimp`).
+	/include	Public header C and C++ header files
+	/lib		Static library location for Windows
+	/obj		Object file location for Windows
+	/scripts 	Scripts used to generate the loading code for some formats
+	/port		Ports to other languages and scripts to maintain those.
+	/test		Unit- and regression tests, test suite of models
+	/tools		Tools (viewer, command line `assimp`)
 	/samples	A small number of samples to illustrate possible 
-                        use cases for Assimp.
+                        use cases for Assimp
 	/workspaces	Build enviroments for vc,xcode,... (deprecated,
 			CMake has superseeded all legacy build options!)
 
 
 
-### 2. Build the library ###
+### Building ###
 
 
 Take a look into the `INSTALL` file. Or fire up CMake with the usual steps.
 
 
-
-### 3. Where to get help ###
+### Where to get help ###
 
 
 For more information, visit [our website](http://assimp.sourceforge.net/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
 (CHMs for Windows are included in some release packages and should be located right here in the root folder).
 
-If the documentation doesn't solve your problems, try our forums at SF.net 
-
+If the documentation doesn't solve your problems, 
+[try our forums at SF.net](http://sourceforge.net/p/assimp/discussion/817654) or ask on
+[StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
 
-- [Open Discussion](http://sourceforge.net/projects/assimp/forums/forum/817653) 
-- [General Help](http://sourceforge.net/projects/assimp/forums/forum/817654)
-
-
-For development stuff, there is also a mailing list, _assimp-discussions_
+For development discussions, there is also a mailing list, _assimp-discussions_
   [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions) 
 
+### Contributing ###
+
+Contributions to assimp are highly appreciated. The easiest way to get involved is to submit 
+a pull request with your changes against the main repository's `master` branch.
 
 
-### 4. License ###
+### License ###
 
-The license of the Asset Import Library is based on the modified, __3-clause BSD__-License, which is a very liberal license. An _informal_ summary is: do whatever you want, but include Assimp's license text with your product - and don't sue us if our code doesn't work.
+Our license is based on the modified, __3-clause BSD__-License, which is very liberal. 
 
-Note that, unlike LGPLed code, you may link statically to Assimp.
-For the formal details, see the `LICENSE` file. 
+An _informal_ summary is: do whatever you want, but include Assimp's license text with your product - 
+and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp.
+For the legal details, see the `LICENSE` file. 
 

+ 1 - 0
code/AssimpCExport.cpp

@@ -73,6 +73,7 @@ ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut)
 	}
 
 	SceneCombiner::CopyScene(pOut,pIn,true);
+	ScenePriv(*pOut)->mIsCopy = true;
 }
 
 

+ 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;
 }
 
 //--------------------------------------------------------------------------------

+ 64 - 8
code/BlenderLoader.cpp

@@ -446,9 +446,43 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
 	else {
 		name = aiString( img->name );
 	}
-	out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(
-		conv_data.next_texture[aiTextureType_DIFFUSE]++)
-	);
+
+	aiTextureType texture_type = aiTextureType_UNKNOWN;
+	MTex::MapType map_type = tex->mapto;
+
+	if (map_type & MTex::MapType_COL)
+	    texture_type = aiTextureType_DIFFUSE;
+	else if (map_type & MTex::MapType_NORM) {
+	    if (tex->tex->imaflag & Tex::ImageFlags_NORMALMAP) {
+	        texture_type = aiTextureType_NORMALS;
+	    }
+	    else {
+	        texture_type = aiTextureType_HEIGHT;
+	    }
+	    out->AddProperty(&tex->norfac,1,AI_MATKEY_BUMPSCALING);
+	}
+	else if (map_type & MTex::MapType_COLSPEC)
+		texture_type = aiTextureType_SPECULAR;
+	else if (map_type & MTex::MapType_COLMIR)
+		texture_type = aiTextureType_REFLECTION;
+	//else if (map_type & MTex::MapType_REF)
+	else if (map_type & MTex::MapType_SPEC)
+		texture_type = aiTextureType_SHININESS;
+	else if (map_type & MTex::MapType_EMIT)
+		texture_type = aiTextureType_EMISSIVE;
+	//else if (map_type & MTex::MapType_ALPHA)
+	//else if (map_type & MTex::MapType_HAR)
+	//else if (map_type & MTex::MapType_RAYMIRR)
+	//else if (map_type & MTex::MapType_TRANSLU)
+	else if (map_type & MTex::MapType_AMB)
+		texture_type = aiTextureType_AMBIENT;
+	else if (map_type & MTex::MapType_DISPLACE)
+		texture_type = aiTextureType_DISPLACEMENT;
+	//else if (map_type & MTex::MapType_WARP)
+
+	out->AddProperty(&name,AI_MATKEY_TEXTURE(texture_type,
+	    conv_data.next_texture[texture_type]++));
+
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -958,19 +992,41 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
 }
 
 // ------------------------------------------------------------------------------------------------
-aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* /*obj*/, const Camera* /*mesh*/, ConversionData& /*conv_data*/)
+aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* camera, ConversionData& /*conv_data*/)
 {
 	ScopeGuard<aiCamera> out(new aiCamera());
-
-	return NULL ; //out.dismiss();
+	out->mName = obj->id.name+2;
+	out->mPosition = aiVector3D(0.f, 0.f, 0.f);
+	out->mUp = aiVector3D(0.f, 1.f, 0.f);
+	out->mLookAt = aiVector3D(0.f, 0.f, -1.f);
+	return out.dismiss();
 }
 
 // ------------------------------------------------------------------------------------------------
-aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* /*obj*/, const Lamp* /*mesh*/, ConversionData& /*conv_data*/)
+aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const Lamp* lamp, ConversionData& conv_data)
 {
 	ScopeGuard<aiLight> out(new aiLight());
+	out->mName = obj->id.name+2;
+
+	switch (lamp->type)
+	{
+	    case Lamp::Type_Local:
+	        out->mType = aiLightSource_POINT;
+	        break;
+	    case Lamp::Type_Sun:
+	        out->mType = aiLightSource_DIRECTIONAL;
+
+	        // blender orients directional lights as facing toward -z
+	        out->mDirection = aiVector3D(0.f, 0.f, -1.f);
+	        break;
+	    default:
+	        break;
+	}
 
-	return NULL ; //out.dismiss();
+	out->mColorAmbient = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
+	out->mColorSpecular = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
+	out->mColorDiffuse = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
+	return out.dismiss();
 }
 
 // ------------------------------------------------------------------------------------------------

+ 667 - 638
code/BlenderScene.cpp

@@ -51,644 +51,673 @@ 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>((short&)dest.mapto,"mapto",db);
+    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);
+    ReadField<ErrorPolicy_Igno>(dest.norfac,"norfac",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_Igno>((short&)dest.imaflag,"imaflag",db);
+    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

+ 35 - 3
code/BlenderScene.h

@@ -598,6 +598,18 @@ struct Tex : ElemBase {
 		,Type_VOXELDATA		= 15
 	};
 
+	enum ImageFlags {
+	     ImageFlags_INTERPOL    	 = 1
+	    ,ImageFlags_USEALPHA    	 = 2
+	    ,ImageFlags_MIPMAP      	 = 4
+	    ,ImageFlags_IMAROT      	 = 16
+	    ,ImageFlags_CALCALPHA   	 = 32
+	    ,ImageFlags_NORMALMAP   	 = 2048
+	    ,ImageFlags_GAUSS_MIP   	 = 4096
+	    ,ImageFlags_FILTER_MIN  	 = 8192
+	    ,ImageFlags_DERIVATIVEMAP   = 16384
+	};
+
 	ID id FAIL;
 	// AnimData *adt; 
 
@@ -618,7 +630,8 @@ struct Tex : ElemBase {
 	//short noisedepth, noisetype;
 	//short noisebasis, noisebasis2;
 
-	//short imaflag, flag;
+	//short flag;
+	ImageFlags imaflag;
 	Type type FAIL;
 	//short stype;
 
@@ -685,7 +698,25 @@ struct MTex : ElemBase {
 		,BlendType_BLEND_COLOR		= 13
 	};
 
-	// short texco, mapto, maptoneg;
+	enum MapType {
+	     MapType_COL         = 1
+	    ,MapType_NORM        = 2
+	    ,MapType_COLSPEC     = 4
+	    ,MapType_COLMIR      = 8
+	    ,MapType_REF         = 16
+	    ,MapType_SPEC        = 32
+	    ,MapType_EMIT        = 64
+	    ,MapType_ALPHA       = 128
+	    ,MapType_HAR         = 256
+	    ,MapType_RAYMIRR     = 512
+	    ,MapType_TRANSLU     = 1024
+	    ,MapType_AMB         = 2048
+	    ,MapType_DISPLACE    = 4096
+	    ,MapType_WARP        = 8192
+	};
+
+	// short texco, maptoneg;
+	MapType mapto;
 
 	BlendType blendtype;
 	boost::shared_ptr<Object> object;
@@ -705,7 +736,8 @@ struct MTex : ElemBase {
 
 	//float colfac, varfac;
 
-	//float norfac, dispfac, warpfac;
+	float norfac;
+	//float dispfac, warpfac;
 	float colspecfac, mirrfac, alphafac;
 	float difffac, specfac, emitfac, hardfac;
 	//float raymirrfac, translfac, ambfac;

+ 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
+;
 
 
 	}

+ 8 - 9
code/ColladaExporter.cpp

@@ -311,16 +311,15 @@ void ColladaExporter::WriteMaterials()
 
     aiString name;
     if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS )
-      name = "mat";
-	if(material_names.find(name.C_Str()) != material_names.end()) {
-		materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + "_" + name.C_Str();
-		material_names.insert(materials[a].name);
-	} else {
-		materials[a].name = name.C_Str();
-	}
-    for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it )
-      if( !isalnum( *it) )
+      name = "mat";
+    materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + name.C_Str();
+    for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
+		// isalnum on MSVC asserts for code points in [0,255]. Thus prevent unwanted promotion
+		// of char to signed int and take the unsigned char value.
+      if( !isalnum( static_cast<uint8_t>(*it) ) ) {
         *it = '_';
+	  }
+	}
 
 	aiShadingMode shading;
 	materials[a].shading_model = "phong";

+ 43 - 6
code/Exporter.cpp

@@ -88,7 +88,7 @@ Exporter::ExportFormatEntry gExporters[] =
 
 #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
 	Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj, 
-		aiProcess_GenNormals /*| aiProcess_PreTransformVertices */),
+		aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */),
 #endif
 
 #ifndef ASSIMP_BUILD_NO_STL_EXPORTER
@@ -227,11 +227,47 @@ const aiExportDataBlob* Exporter :: ExportToBlob(  const aiScene* pScene, const
 }
 
 
+// ------------------------------------------------------------------------------------------------
+bool IsVerboseFormat(const aiMesh* mesh) 
+{
+	// avoid slow vector<bool> specialization
+	std::vector<unsigned int> seen(mesh->mNumVertices,0);
+	for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
+		const aiFace& f = mesh->mFaces[i];
+		for(unsigned int j = 0; j < f.mNumIndices; ++j) {
+			if(++seen[f.mIndices[j]] == 2) {
+				// found a duplicate index
+				return false;
+			}
+		}
+	}
+	return true;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+bool IsVerboseFormat(const aiScene* pScene) 
+{
+	for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+		if(!IsVerboseFormat(pScene->mMeshes[i])) {
+			return false;
+		}
+	}
+	return true;
+}
+
+
 // ------------------------------------------------------------------------------------------------
 aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing )
 {
 	ASSIMP_BEGIN_EXCEPTION_REGION();
 
+	// when they create scenes from scratch, users will likely create them not in verbose
+	// format. They will likely not be aware that there is a flag in the scene to indicate
+	// this, however. To avoid surprises and bug reports, we check for duplicates in
+	// meshes upfront.
+	const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);
+
 	pimpl->mError = "";
 	for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
 		const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
@@ -253,20 +289,21 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
 				const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
 
 				// Erase all pp steps that were already applied to this scene
-				unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv 
+				const unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv && !priv->mIsCopy
 					? (priv->mPPStepsApplied & ~nonIdempotentSteps)
 					: 0u);
 
 				// If no extra postprocessing was specified, and we obtained this scene from an
 				// Assimp importer, apply the reverse steps automatically.
-				if (!pPreprocessing && priv) {
-					pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
-				}
+				// TODO: either drop this, or document it. Otherwise it is just a bad surprise.
+				//if (!pPreprocessing && priv) {
+				//	pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
+				//}
 
 				// If the input scene is not in verbose format, but there is at least postprocessing step that relies on it,
 				// we need to run the MakeVerboseFormat step first.
 				bool must_join_again = false;
-				if (scenecopy->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
+				if (!is_verbose_format) {
 					
 					bool verbosify = false;
 					for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {

+ 10 - 5
code/FBXDocument.cpp

@@ -290,14 +290,19 @@ void Document::ReadHeader()
 	const Scope& shead = *ehead->Compound();
 	fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
 
-	
-	if(fbxVersion < 7200 || fbxVersion > 7300) {
+	// while we maye have some success with newer files, we don't support
+	// the older 6.n fbx format
+	if(fbxVersion < 7200) {
+		DOMError("unsupported, old format version, supported are only FBX 2012 and FBX 2013");
+	}
+	if(fbxVersion > 7300) {
 		if(Settings().strictMode) {
-			DOMError("unsupported format version, supported are only FBX 2012 and FBX 2013"\
-				" in ASCII format (turn off strict mode to try anyhow) ");
+			DOMError("unsupported, newer format version, supported are only FBX 2012 and FBX 2013"
+				" (turn off strict mode to try anyhow) ");
 		}
 		else {
-			DOMWarning("unsupported format version, supported are only FBX 2012 and FBX 2013, trying to read it nevertheless");
+			DOMWarning("unsupported, newer format version, supported are only FBX 2012 and FBX 2013,"
+				" trying to read it nevertheless");
 		}
 	}
 	

+ 2 - 2
code/IRRMeshLoader.cpp

@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "AssimpPCH.h"
 
-#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
+#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
 
 #include "IRRMeshLoader.h"
 #include "ParsingUtils.h"
@@ -512,4 +512,4 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
 	AI_DEBUG_INVALIDATE_PTR(reader);
 }
 
-#endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER
+#endif // !! ASSIMP_BUILD_NO_IRRMESH_IMPORTER

+ 3 - 2
code/IRRShared.cpp

@@ -45,7 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "AssimpPCH.h"
 
-#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
+//This section should be excluded only if both the Irrlicht AND the Irrlicht Mesh importers were omitted.
+#if !(defined(ASSIMP_BUILD_NO_IRR_IMPORTER) && defined(ASSIMP_BUILD_NO_IRRMESH_IMPORTER))
 
 #include "IRRShared.h"
 #include "ParsingUtils.h"
@@ -497,4 +498,4 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
 	return mat;
 }
 
-#endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER
+#endif // !(defined(ASSIMP_BUILD_NO_IRR_IMPORTER) && defined(ASSIMP_BUILD_NO_IRRMESH_IMPORTER))

+ 5 - 0
code/LWOLoader.cpp

@@ -1296,6 +1296,11 @@ void LWOImporter::LoadLWO2File()
 		uint8_t* const next = mFileBuffer+head->length;
 		unsigned int iUnnamed = 0;
 
+		if(!head->length) {
+			mFileBuffer = next;
+			continue;
+		}
+
 		switch (head->type)
 		{
 			// new layer

+ 13 - 11
code/LWOMaterial.cpp

@@ -167,19 +167,21 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
 		// The older LWOB format does not use indirect references to clips.
 		// The file name of a texture is directly specified in the tex chunk.
 		if (mIsLWO2)	{
-			// find the corresponding clip
-			ClipList::iterator clip = mClips.begin();
+			// find the corresponding clip (take the last one if multiple
+			// share the same index)
+			ClipList::iterator end = mClips.end(), candidate = end;
 			temp = (*it).mClipIdx;
-			for (ClipList::iterator end = mClips.end(); clip != end; ++clip)	{
-				if ((*clip).idx == temp)
-					break;
+			for (ClipList::iterator clip = mClips.begin(); clip != end; ++clip)	{
+				if ((*clip).idx == temp) {
+					candidate = clip;
+				}
 				
 			}
-			if (mClips.end() == clip)	{
+			if (candidate == end)	{
 				DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
 				temp = 0;
 
-				// fixme: appearently some LWO files shipping with Doom3 don't
+				// fixme: apparently some LWO files shipping with Doom3 don't
 				// have clips at all ... check whether that's true or whether
 				// it's a bug in the loader.
 
@@ -188,16 +190,16 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
 				//continue;
 			}
 			else {
-				if (Clip::UNSUPPORTED == (*clip).type)	{
+				if (Clip::UNSUPPORTED == (*candidate).type)	{
 					DefaultLogger::get()->error("LWO2: Clip type is not supported");
 					continue;
 				}
-				AdjustTexturePath((*clip).path);
-				s.Set((*clip).path);
+				AdjustTexturePath((*candidate).path);
+				s.Set((*candidate).path);
 
 				// Additional image settings
 				int flags = 0;
-				if ((*clip).negate) {
+				if ((*candidate).negate) {
 					flags |= aiTextureFlags_Invert;
 				}
 				pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur));

+ 41 - 11
code/ObjExporter.cpp

@@ -61,14 +61,14 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
 		boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
 		if(outfile == NULL) {
 			throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
-		}
+		} 
 		outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
 	}
 	{
 		boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
 		if(outfile == NULL) {
 			throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName()));
-		}
+		} 
 		outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1);
 	}
 }
@@ -199,6 +199,7 @@ void ObjExporter :: WriteGeometryFile()
 	AddNode(pScene->mRootNode,mBase);
 
 	// write vertex positions
+	vpMap.getVectors(vp);
 	mOutput << "# " << vp.size() << " vertex positions" << endl;
 	BOOST_FOREACH(const aiVector3D& v, vp) {
 		mOutput << "v  " << v.x << " " << v.y << " " << v.z << endl;
@@ -206,6 +207,7 @@ void ObjExporter :: WriteGeometryFile()
 	mOutput << endl;
 
 	// write uv coordinates
+	vtMap.getVectors(vt);
 	mOutput << "# " << vt.size() << " UV coordinates" << endl;
 	BOOST_FOREACH(const aiVector3D& v, vt) {
 		mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
@@ -213,6 +215,7 @@ void ObjExporter :: WriteGeometryFile()
 	mOutput << endl;
 
 	// write vertex normals
+	vnMap.getVectors(vn);
 	mOutput << "# " << vn.size() << " vertex normals" << endl;
 	BOOST_FOREACH(const aiVector3D& v, vn) {
 		mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
@@ -252,6 +255,31 @@ void ObjExporter :: WriteGeometryFile()
 	}
 }
 
+
+
+
+
+int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
+{
+	vecIndexMap::dataType::iterator vertIt = vecMap.find(vec); 
+	if(vertIt != vecMap.end()){// vertex already exists, so reference it
+		return vertIt->second;
+	}
+	vecMap[vec] = mNextIndex;
+	int ret = mNextIndex;
+	mNextIndex++;
+	return ret;
+}
+
+void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
+{
+	vecs.resize(vecMap.size());
+	for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); it++){
+		vecs[it->second-1] = it->first;
+	}
+}
+
+
 // ------------------------------------------------------------------------------------------------
 void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
 {
@@ -262,6 +290,7 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri
 	mesh.matname = GetMaterialName(m->mMaterialIndex);
 
 	mesh.faces.resize(m->mNumFaces);
+
 	for(unsigned int i = 0; i < m->mNumFaces; ++i) {
 		const aiFace& f = m->mFaces[i];
 
@@ -281,21 +310,22 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri
 		for(unsigned int a = 0; a < f.mNumIndices; ++a) {
 			const unsigned int idx = f.mIndices[a];
 
-			// XXX need a way to check if this is an unique vertex or if we had it already, 
-			// in which case we should instead reference the previous occurrence.
-			ai_assert(m->mVertices);
-			vp.push_back( mat * m->mVertices[idx] );
-			face.indices[a].vp = vp.size();
+			aiVector3D vert = mat * m->mVertices[idx];
+			face.indices[a].vp = vpMap.getIndex(vert);
 
 			if (m->mNormals) {
-				vn.push_back( m->mNormals[idx] );
+				face.indices[a].vn = vnMap.getIndex(m->mNormals[idx]);
+			}
+			else{
+				face.indices[a].vn = 0;
 			}
-			face.indices[a].vn = vn.size();
 
 			if (m->mTextureCoords[0]) {
-				vt.push_back( m->mTextureCoords[0][idx] );
+				face.indices[a].vt = vtMap.getIndex(m->mTextureCoords[0][idx]);
+			}
+			else{
+				face.indices[a].vt = 0;
 			}
-			face.indices[a].vt = vt.size();
 		}
 	}
 }

+ 30 - 0
code/ObjExporter.h

@@ -112,6 +112,36 @@ private:
 	const aiScene* const pScene;
 
 	std::vector<aiVector3D> vp, vn, vt;
+
+
+	struct aiVectorCompare
+	{
+		bool operator() (const aiVector3D& a, const aiVector3D& b) const 
+		{
+			if(a.x < b.x) return true;
+			if(a.x > b.x) return false;
+			if(a.y < b.y) return true;
+			if(a.y > b.y) return false;
+			if(a.z < b.z) return true;
+			return false;
+		}
+	};
+
+	class vecIndexMap
+	{
+		int mNextIndex;
+		typedef std::map<aiVector3D, int, aiVectorCompare> dataType;
+		dataType vecMap;
+	public:
+
+		vecIndexMap():mNextIndex(1)
+		{}
+
+		int getIndex(const aiVector3D& vec);
+		void getVectors( std::vector<aiVector3D>& vecs );
+	};
+
+	vecIndexMap vpMap, vnMap, vtMap;
 	std::vector<MeshInstance> meshes;
 
 	// this endl() doesn't flush() the stream

+ 20 - 19
code/ObjFileImporter.cpp

@@ -276,14 +276,23 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
 	for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
 	{
 		ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
+	
 		if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
 			pMesh->mNumFaces += inp->m_pVertices->size() - 1;
+			pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
 		}
 		else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
 			pMesh->mNumFaces += inp->m_pVertices->size();
+			pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
 		}
 		else {
 			++pMesh->mNumFaces;
+			if (inp->m_pVertices->size() > 3) {
+				pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+			}
+			else {
+				pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+			}
 		}
 	}
 
@@ -384,7 +393,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
 			pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
 			
 			// Copy all normals 
-			if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty())
+			if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_pNormals->size())
 			{
 				const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
 				if ( normal >= pModel->m_Normals.size() )
@@ -394,21 +403,16 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
 			}
 			
 			// Copy all texture coordinates
-			if ( !pModel->m_TextureCoord.empty() )
+			if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
 			{
-				if ( !pSourceFace->m_pTexturCoords->empty() )
-				{
-					const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
-					ai_assert( tex < pModel->m_TextureCoord.size() );
-					for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ )
-					{
-						if ( tex >= pModel->m_TextureCoord.size() )
-							throw DeadlyImportError("OBJ: texture coord index out of range");
-
-						aiVector2D coord2d = pModel->m_TextureCoord[ tex ];
-						pMesh->mTextureCoords[ i ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 );
-					}
-				}
+				const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
+				ai_assert( tex < pModel->m_TextureCoord.size() );
+					
+				if ( tex >= pModel->m_TextureCoord.size() )
+					throw DeadlyImportError("OBJ: texture coord index out of range");
+
+				aiVector2D coord2d = pModel->m_TextureCoord[ tex ];
+				pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 );
 			}
 
 			ai_assert( pMesh->mNumVertices > newIndex );
@@ -587,15 +591,12 @@ void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
 
 	// Assign parent to child
 	pChild->mParent = pParent;
-	size_t sNumChildren = 0;
-	(void)sNumChildren; // remove warning on release build
 	
 	// If already children was assigned to the parent node, store them in a 
 	std::vector<aiNode*> temp;
 	if (pParent->mChildren != NULL)
 	{
-		sNumChildren = pParent->mNumChildren;
-		ai_assert( 0 != sNumChildren );
+		ai_assert( 0 != pParent->mNumChildren );
 		for (size_t index = 0; index < pParent->mNumChildren; index++)
 		{
 			temp.push_back(pParent->mChildren [ index ] );

+ 3 - 6
code/ObjFileImporter.h

@@ -77,7 +77,7 @@ public:
 
 private:
 
-	//! \brief	Appends the supported extention.
+	//! \brief	Appends the supported extension.
 	const aiImporterDesc* GetInfo () const;
 
 	//!	\brief	File import implementation.
@@ -104,18 +104,15 @@ private:
 	//!	\brief	Material creation.
 	void createMaterials(const ObjFile::Model* pModel, aiScene* pScene);
 
-	//!	\brief	Appends a child node to a parentnode and updates the datastructures.
+	//!	\brief	Appends a child node to a parent node and updates the data structures.
 	void appendChildToParentNode(aiNode *pParent, aiNode *pChild);
 
-	//!	\brief TODO!
-	void createAnimations();
-
 private:
 	//!	Data buffer
 	std::vector<char> m_Buffer;
 	//!	Pointer to root object instance
 	ObjFile::Object *m_pRootObject;
-	//!	Absolute pathname of model in filesystem
+	//!	Absolute pathname of model in file system
 	std::string m_strAbsPath;
 };
 

+ 52 - 7
code/ObjFileParser.cpp

@@ -112,7 +112,7 @@ void ObjFileParser::parseFile()
 		case 'v': // Parse a vertex texture coordinate
 			{
 				++m_DataIt;
-				if (*m_DataIt == ' ')
+				if (*m_DataIt == ' ' || *m_DataIt == '\t')
 				{
 					// Read in vertex definition
 					getVector3(m_pModel->m_Vertices);
@@ -200,6 +200,8 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
 			break;
 		++m_DataIt;
 	}
+
+	ai_assert(index < length);
 	pBuffer[index] = '\0';
 }
 
@@ -207,16 +209,30 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
 // Copy the next line into a temporary buffer
 void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
 {
-	size_t index = 0;
-	while (m_DataIt != m_DataItEnd)
+	size_t index = 0u;
+
+	// some OBJ files have line continuations using \ (such as in C++ et al)
+	bool continuation = false;
+	for (;m_DataIt != m_DataItEnd && index < length-1; ++m_DataIt) 
 	{
-		if (*m_DataIt == '\n' || *m_DataIt == '\r' || index == length-1)
+		const char c = *m_DataIt;
+		if (c == '\\') {
+			continuation = true;
+			continue;
+		}
+		
+		if (c == '\n' || c == '\r') {
+			if(continuation) {
+				pBuffer[ index++ ] = ' ';
+				continue;
+			}
 			break;
+		}
 
-		pBuffer[ index ] = *m_DataIt;
-		++index;
-		++m_DataIt;
+		continuation = false;
+		pBuffer[ index++ ] = c;
 	}
+	ai_assert(index < length);
 	pBuffer[ index ] = '\0';
 }
 
@@ -274,6 +290,10 @@ void ObjFileParser::getFace(aiPrimitiveType type)
 	std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
 	bool hasNormal = false;
 
+	const int vSize = m_pModel->m_Vertices.size();
+	const int vtSize = m_pModel->m_TextureCoord.size();
+	const int vnSize = m_pModel->m_Normals.size();
+
 	const bool vt = (!m_pModel->m_TextureCoord.empty());
 	const bool vn = (!m_pModel->m_Normals.empty());
 	int iStep = 0, iPos = 0;
@@ -307,7 +327,11 @@ void ObjFileParser::getFace(aiPrimitiveType type)
 		{
 			//OBJ USES 1 Base ARRAYS!!!!
 			const int iVal = atoi( pPtr );
+
+			// increment iStep position based off of the sign and # of digits
 			int tmp = iVal;
+			if (iVal < 0)
+			    ++iStep;
 			while ( ( tmp = tmp / 10 )!=0 )
 				++iStep;
 
@@ -332,6 +356,27 @@ void ObjFileParser::getFace(aiPrimitiveType type)
 					reportErrorTokenInFace();
 				}
 			}
+			else if ( iVal < 0 )
+			{
+				// Store relatively index
+				if ( 0 == iPos )
+				{
+					pIndices->push_back( vSize + iVal );
+				}
+				else if ( 1 == iPos )
+				{
+					pTexID->push_back( vtSize + iVal );
+				}
+				else if ( 2 == iPos )
+				{
+					pNormalID->push_back( vnSize + iVal );
+					hasNormal = true;
+				}
+				else
+				{
+					reportErrorTokenInFace();
+				}
+			}
 		}
 		pPtr += iStep;
 	}

+ 2 - 2
code/PlyExporter.cpp

@@ -103,7 +103,7 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
 
 	mOutput << "ply" << endl;
 	mOutput << "format ascii 1.0" << endl;
-	mOutput << "Created by Open Asset Import Library - http://assimp.sf.net (v"
+	mOutput << "comment Created by Open Asset Import Library - http://assimp.sf.net (v"
 		<< aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' 
 		<< aiGetVersionRevision() << ")" << endl;
 
@@ -159,7 +159,7 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
 	}
 
 	mOutput << "element face " << faces << endl;
-	mOutput << "property list uint uint vertex_indices" << endl;
+	mOutput << "property list uint uint vertex_index" << endl;
 	mOutput << "end_header" << endl;
 
 	for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {

+ 11 - 2
code/STLLoader.cpp

@@ -86,7 +86,12 @@ bool IsAsciiSTL(const char* buffer, unsigned int fileSize) {
 	if (IsBinarySTL(buffer, fileSize))
 		return false;
 
-	if (fileSize < 5)
+	const char* bufferEnd = buffer + fileSize;
+
+	if (!SkipSpaces(&buffer))
+		return false;
+
+	if (buffer + 5 >= bufferEnd)
 		return false;
 
 	return strncmp(buffer, "solid", 5) == 0;
@@ -209,7 +214,11 @@ void STLImporter::LoadASCIIFile()
 {
 	aiMesh* pMesh = pScene->mMeshes[0];
 
-	const char* sz = mBuffer + 5; // skip the "solid"
+	const char* sz = mBuffer;
+	SkipSpaces(&sz);
+	ai_assert(!IsLineEnd(sz));
+
+	sz += 5; // skip the "solid"
 	SkipSpaces(&sz);
 	const char* szMe = sz;
 	while (!::IsSpaceOrNewLine(*sz)) {

+ 8 - 0
code/ScenePrivate.h

@@ -53,6 +53,7 @@ struct ScenePrivateData {
 	ScenePrivateData()
 		: mOrigImporter()
 		, mPPStepsApplied()
+		, mIsCopy()
 	{}
 
 	// Importer that originally loaded the scene though the C-API
@@ -61,6 +62,13 @@ struct ScenePrivateData {
 
 	// List of postprocessing steps already applied to the scene.
 	unsigned int mPPStepsApplied;
+
+	// true if the scene is a copy made with aiCopyScene()
+	// or the corresponding C++ API. This means that user code
+	// may have made modifications to it, so mPPStepsApplied
+	// and mOrigImporter are no longer safe to rely on and only
+	// serve informative purposes.
+	bool mIsCopy;
 };
 
 // Access private data stored in the scene

+ 7 - 1
include/assimp/Exporter.hpp

@@ -198,7 +198,13 @@ public:
 	 *   redundant as exporters would apply them anyhow. A good example 
 	 *   is triangulation - whilst you can enforce it by specifying
 	 *   the #aiProcess_Triangulate flag, most export formats support only
-	 *  triangulate data so they would run the step even if it wasn't requested.
+	 *   triangulate data so they would run the step even if it wasn't requested.
+	 *
+	 *   If assimp detects that the input scene was directly taken from the importer side of 
+     *   the library (i.e. not copied using aiCopyScene and potetially modified afterwards), 
+     *   any postprocessing steps already applied to the scene will not be applied again, unless
+     *   they show non-idempotent behaviour (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and 
+     *   #aiProcess_FlipWindingOrder).
 	 * @return AI_SUCCESS if everything was fine. 
 	 * @note Use aiCopyScene() to get a modifiable copy of a previously
 	 *   imported scene.*/

+ 6 - 0
include/assimp/cexport.h

@@ -143,6 +143,12 @@ ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn);
 *   is triangulation - whilst you can enforce it by specifying
 *   the #aiProcess_Triangulate flag, most export formats support only
 *   triangulate data so they would run the step anyway.
+*
+*   If assimp detects that the input scene was directly taken from the importer side of 
+*   the library (i.e. not copied using aiCopyScene and potetially modified afterwards), 
+*   any postprocessing steps already applied to the scene will not be applied again, unless
+*   they show non-idempotent behaviour (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and 
+*   #aiProcess_FlipWindingOrder).
 * @return a status code indicating the result of the export
 * @note Use aiCopyScene() to get a modifiable copy of a previously
 *   imported scene.

+ 61 - 0
include/assimp/material.h

@@ -691,6 +691,12 @@ public:
     aiReturn Get(const char* pKey,unsigned int type,
 		unsigned int idx, Type* pOut, unsigned int* pMax) const;
 
+	aiReturn Get(const char* pKey,unsigned int type,
+		unsigned int idx, int* pOut, unsigned int* pMax) const;
+
+	aiReturn Get(const char* pKey,unsigned int type,
+		unsigned int idx, float* pOut, unsigned int* pMax) const;
+
     // -------------------------------------------------------------------
     /** @brief Retrieve a Type value with a specific key 
      *  from the material
@@ -705,6 +711,25 @@ public:
 	aiReturn Get(const char* pKey,unsigned int type,
 		unsigned int idx,Type& pOut) const;
 
+
+	aiReturn Get(const char* pKey,unsigned int type,
+		unsigned int idx, int& pOut) const;
+
+	aiReturn Get(const char* pKey,unsigned int type,
+		unsigned int idx, float& pOut) const;
+
+	aiReturn Get(const char* pKey,unsigned int type,
+		unsigned int idx, aiString& pOut) const;
+
+	aiReturn Get(const char* pKey,unsigned int type,
+		unsigned int idx, aiColor3D& pOut) const;
+
+	aiReturn Get(const char* pKey,unsigned int type,
+		unsigned int idx, aiColor4D& pOut) const;
+
+	aiReturn Get(const char* pKey,unsigned int type,
+		unsigned int idx, aiUVTransform& pOut) const;
+
 	// -------------------------------------------------------------------
 	/** Get the number of textures for a particular texture type.
 	 *  @param type Texture type to check for
@@ -797,6 +822,42 @@ public:
 		unsigned int type  = 0,
 		unsigned int index = 0);
 
+	aiReturn AddProperty (const aiVector3D* pInput,
+		unsigned int pNumValues,
+		const char* pKey,
+		unsigned int type  = 0,
+		unsigned int index = 0);
+
+	aiReturn AddProperty (const aiColor3D* pInput,
+		unsigned int pNumValues,
+		const char* pKey,
+		unsigned int type  = 0,
+		unsigned int index = 0);
+
+	aiReturn AddProperty (const aiColor4D* pInput,
+		unsigned int pNumValues,
+		const char* pKey,
+		unsigned int type  = 0,
+		unsigned int index = 0);
+
+	aiReturn AddProperty (const int* pInput,
+		unsigned int pNumValues,
+		const char* pKey,
+		unsigned int type  = 0,
+		unsigned int index = 0);
+
+	aiReturn AddProperty (const float* pInput,
+		unsigned int pNumValues,
+		const char* pKey,
+		unsigned int type  = 0,
+		unsigned int index = 0);
+
+	aiReturn AddProperty (const aiUVTransform* pInput,
+		unsigned int pNumValues,
+		const char* pKey,
+		unsigned int type  = 0,
+		unsigned int index = 0);
+
 	// ------------------------------------------------------------------------------
 	/** @brief Remove a given key from the list.
 	 *

+ 94 - 22
include/assimp/material.inl

@@ -89,7 +89,7 @@ inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
 		}
 
 		iNum = std::min((size_t)iNum,prop->mDataLength / sizeof(Type));
-		memcpy(pOut,prop->mData,iNum * sizeof(Type));
+		::memcpy(pOut,prop->mData,iNum * sizeof(Type));
 		if (pMax) {
 			*pMax = iNum;
 		}
@@ -115,51 +115,45 @@ inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
 			return AI_FAILURE;
 		}
 
-		memcpy(&pOut,prop->mData,sizeof(Type));
+		::memcpy(&pOut,prop->mData,sizeof(Type));
 	}
 	return ret;
 }
 
 // ---------------------------------------------------------------------------
-template <>
-inline aiReturn aiMaterial::Get<float>(const char* pKey,unsigned int type,
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
 	unsigned int idx,float* pOut,
 	unsigned int* pMax) const
 {
 	return ::aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);
 }
 // ---------------------------------------------------------------------------
-template <>
-inline aiReturn aiMaterial::Get<int>(const char* pKey,unsigned int type,
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
 	unsigned int idx,int* pOut,
 	unsigned int* pMax) const
 {
 	return ::aiGetMaterialIntegerArray(this,pKey,type,idx,pOut,pMax);
 }
 // ---------------------------------------------------------------------------
-template <>
-inline aiReturn aiMaterial::Get<float>(const char* pKey,unsigned int type,
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
 	unsigned int idx,float& pOut) const
 {
 	return aiGetMaterialFloat(this,pKey,type,idx,&pOut);
 }
 // ---------------------------------------------------------------------------
-template <>
-inline aiReturn aiMaterial::Get<int>(const char* pKey,unsigned int type,
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
 	unsigned int idx,int& pOut) const
 {
 	return aiGetMaterialInteger(this,pKey,type,idx,&pOut);
 }
 // ---------------------------------------------------------------------------
-template <>
-inline aiReturn aiMaterial::Get<aiColor4D>(const char* pKey,unsigned int type,
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
 	unsigned int idx,aiColor4D& pOut) const
 {
 	return aiGetMaterialColor(this,pKey,type,idx,&pOut);
 }
 // ---------------------------------------------------------------------------
-template <>
-inline aiReturn aiMaterial::Get<aiColor3D>(const char* pKey,unsigned int type,
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
 	unsigned int idx,aiColor3D& pOut) const
 {
 	aiColor4D c;
@@ -168,8 +162,7 @@ inline aiReturn aiMaterial::Get<aiColor3D>(const char* pKey,unsigned int type,
 	return ret;
 }
 // ---------------------------------------------------------------------------
-template <>
-inline aiReturn aiMaterial::Get<aiString>(const char* pKey,unsigned int type,
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
 	unsigned int idx,aiString& pOut) const
 {
 	return aiGetMaterialString(this,pKey,type,idx,&pOut);
@@ -189,9 +182,88 @@ aiReturn aiMaterial::AddProperty (const TYPE* pInput,
 		pKey,type,index,aiPTI_Buffer);
 }
 
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const float* pInput,
+	const unsigned int pNumValues,
+	const char* pKey,
+	unsigned int type,
+	unsigned int index)
+{
+	return AddBinaryProperty((const void*)pInput,
+		pNumValues * sizeof(float),
+		pKey,type,index,aiPTI_Float);
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const aiUVTransform* pInput,
+	const unsigned int pNumValues,
+	const char* pKey,
+	unsigned int type,
+	unsigned int index)
+{
+	return AddBinaryProperty((const void*)pInput,
+		pNumValues * sizeof(aiUVTransform),
+		pKey,type,index,aiPTI_Float);
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const aiColor4D* pInput,
+	const unsigned int pNumValues,
+	const char* pKey,
+	unsigned int type,
+	unsigned int index)
+{
+	return AddBinaryProperty((const void*)pInput,
+		pNumValues * sizeof(aiColor4D),
+		pKey,type,index,aiPTI_Float);
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const aiColor3D* pInput,
+	const unsigned int pNumValues,
+	const char* pKey,
+	unsigned int type,
+	unsigned int index)
+{
+	return AddBinaryProperty((const void*)pInput,
+		pNumValues * sizeof(aiColor3D),
+		pKey,type,index,aiPTI_Float);
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const aiVector3D* pInput,
+	const unsigned int pNumValues,
+	const char* pKey,
+	unsigned int type,
+	unsigned int index)
+{
+	return AddBinaryProperty((const void*)pInput,
+		pNumValues * sizeof(aiVector3D),
+		pKey,type,index,aiPTI_Float);
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const int* pInput,
+	const unsigned int pNumValues,
+	const char* pKey,
+	unsigned int type,
+	unsigned int index)
+{
+	return AddBinaryProperty((const void*)pInput,
+		pNumValues * sizeof(int),
+		pKey,type,index,aiPTI_Integer);
+}
+
+
+// ---------------------------------------------------------------------------
+// The template specializations below are for backwards compatibility.
+// The recommended way to add material properties is using the non-template
+// overloads.
+// ---------------------------------------------------------------------------
+
 // ---------------------------------------------------------------------------
 template<>
-inline aiReturn aiMaterial::AddProperty<float> (const float* pInput,
+inline aiReturn aiMaterial::AddProperty<float>(const float* pInput,
 	const unsigned int pNumValues,
 	const char* pKey,
 	unsigned int type,
@@ -204,7 +276,7 @@ inline aiReturn aiMaterial::AddProperty<float> (const float* pInput,
 
 // ---------------------------------------------------------------------------
 template<>
-inline aiReturn aiMaterial::AddProperty<aiUVTransform> (const aiUVTransform* pInput,
+inline aiReturn aiMaterial::AddProperty<aiUVTransform>(const aiUVTransform* pInput,
 	const unsigned int pNumValues,
 	const char* pKey,
 	unsigned int type,
@@ -217,7 +289,7 @@ inline aiReturn aiMaterial::AddProperty<aiUVTransform> (const aiUVTransform* pIn
 
 // ---------------------------------------------------------------------------
 template<>
-inline aiReturn aiMaterial::AddProperty<aiColor4D> (const aiColor4D* pInput,
+inline aiReturn aiMaterial::AddProperty<aiColor4D>(const aiColor4D* pInput,
 	const unsigned int pNumValues,
 	const char* pKey,
 	unsigned int type,
@@ -230,7 +302,7 @@ inline aiReturn aiMaterial::AddProperty<aiColor4D> (const aiColor4D* pInput,
 
 // ---------------------------------------------------------------------------
 template<>
-inline aiReturn aiMaterial::AddProperty<aiColor3D> (const aiColor3D* pInput,
+inline aiReturn aiMaterial::AddProperty<aiColor3D>(const aiColor3D* pInput,
 	const unsigned int pNumValues,
 	const char* pKey,
 	unsigned int type,
@@ -243,7 +315,7 @@ inline aiReturn aiMaterial::AddProperty<aiColor3D> (const aiColor3D* pInput,
 
 // ---------------------------------------------------------------------------
 template<>
-inline aiReturn aiMaterial::AddProperty<aiVector3D> (const aiVector3D* pInput,
+inline aiReturn aiMaterial::AddProperty<aiVector3D>(const aiVector3D* pInput,
 	const unsigned int pNumValues,
 	const char* pKey,
 	unsigned int type,
@@ -256,7 +328,7 @@ inline aiReturn aiMaterial::AddProperty<aiVector3D> (const aiVector3D* pInput,
 
 // ---------------------------------------------------------------------------
 template<>
-inline aiReturn aiMaterial::AddProperty<int> (const int* pInput,
+inline aiReturn aiMaterial::AddProperty<int>(const int* pInput,
 	const unsigned int pNumValues,
 	const char* pKey,
 	unsigned int type,

+ 4 - 4
samples/SimpleAssimpViewX/ModelLoaderHelperClasses.h

@@ -8,10 +8,10 @@
 
 #import <Cocoa/Cocoa.h>
 #import <OpenGL/OpenGL.h>
-#import "aiColor4D.h"
-#import "aiVector3D.h"
-#import "aiVector2D.h"
-#import "aiMatrix4x4.h"
+#import "color4.h"
+#import "vector3.h"
+#import "vector2.h"
+#import "matrix4x4.h"
 
 /* workflow:
 

+ 7 - 6
samples/SimpleAssimpViewX/MyDocument.h

@@ -10,9 +10,10 @@
 #import "ModelLoaderHelperClasses.h"
 
 // assimp include files. These three are usually needed.
-#import "assimp.h"
-#import "aiPostProcess.h"
-#import "aiScene.h"
+#import "cimport.h"
+#import "postprocess.h"
+#import "scene.h"
+#import "types.h"
 
 #import <Cocoa/Cocoa.h>
 #import <OpenGL/OpenGL.h>
@@ -29,7 +30,7 @@
     
     // Assimp Stuff
     aiScene* _scene;
-    struct aiVector3D scene_min, scene_max, scene_center;
+    aiVector3D scene_min, scene_max, scene_center;
     double normalizedScale;    
     
     // Our array of textures.
@@ -53,7 +54,7 @@
 - (void) deleteGLResourcesInContext:(CGLContextObj)cgl_ctx;
 
 - (void) loadTexturesInContext:(CGLContextObj)cgl_ctx withModelPath:(NSString*) modelPath;
-- (void) getBoundingBoxWithMinVector:(struct aiVector3D*) min maxVectr:(struct aiVector3D*) max;
-- (void) getBoundingBoxForNode:(const struct aiNode*)nd  minVector:(struct aiVector3D*) min maxVector:(struct aiVector3D*) max matrix:(struct aiMatrix4x4*) trafo;
+- (void) getBoundingBoxWithMinVector:(aiVector3D*) min maxVectr:(aiVector3D*) max;
+- (void) getBoundingBoxForNode:(const aiNode*)nd  minVector:(aiVector3D*) min maxVector:(aiVector3D*) max matrix:(aiMatrix4x4*) trafo;
 
 @end

+ 14 - 10
samples/SimpleAssimpViewX/MyDocument.mm

@@ -6,7 +6,8 @@
 //  Copyright __MyCompanyName__ 2010 . All rights reserved.
 //
 
-#import "aiConfig.h"
+#import "cimport.h"
+#import "config.h"
 #import "MyDocument.h"
 #import <OpenGL/CGLMacro.h>
 
@@ -16,7 +17,7 @@
 #define aisgl_min(x,y) (x<y?x:y)
 #define aisgl_max(x,y) (y>x?y:x)
 
-static void color4_to_float4(const struct aiColor4D *c, float f[4])
+static void color4_to_float4(const aiColor4D *c, float f[4])
 {
 	f[0] = c->r;
 	f[1] = c->g;
@@ -160,7 +161,8 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS
                 // Load our new path.
                 
                 // only ever give us triangles.
-                aiSetImportPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT );
+                aiPropertyStore* props = aiCreatePropertyStore();
+                aiSetImportPropertyInteger(props, AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT );
                 
                 NSUInteger aiPostProccesFlags;
                 
@@ -181,7 +183,9 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS
                 }
                 
                 // aiProcess_FlipUVs is needed for VAO / VBOs,  not sure why.
-                _scene = (aiScene*) aiImportFile([[openPanel filename] cStringUsingEncoding:[NSString defaultCStringEncoding]], aiPostProccesFlags | aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_PreTransformVertices | 0 );
+                _scene = (aiScene*) aiImportFileExWithProperties([[openPanel filename] cStringUsingEncoding:[NSString defaultCStringEncoding]], aiPostProccesFlags | aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_PreTransformVertices | 0, NULL, props);
+
+                aiReleasePropertyStore(props);
                 
                 if (_scene)
                 {       
@@ -755,9 +759,9 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS
     
 }
 
-- (void) getBoundingBoxWithMinVector:(struct aiVector3D*) min maxVectr:(struct aiVector3D*) max
+- (void) getBoundingBoxWithMinVector:(aiVector3D*) min maxVectr:(aiVector3D*) max
 {
-	struct aiMatrix4x4 trafo;
+	aiMatrix4x4 trafo;
 	aiIdentityMatrix4(&trafo);
     
 	min->x = min->y = min->z =  1e10f;
@@ -766,9 +770,9 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS
     [self getBoundingBoxForNode:_scene->mRootNode minVector:min maxVector:max matrix:&trafo];
 }
 
-- (void) getBoundingBoxForNode:(const struct aiNode*)nd  minVector:(struct aiVector3D*) min maxVector:(struct aiVector3D*) max matrix:(struct aiMatrix4x4*) trafo
+- (void) getBoundingBoxForNode:(const aiNode*)nd  minVector:(aiVector3D*) min maxVector:(aiVector3D*) max matrix:(aiMatrix4x4*) trafo
 {
-	struct aiMatrix4x4 prev;
+	aiMatrix4x4 prev;
 	unsigned int n = 0, t;
     
 	prev = *trafo;
@@ -776,10 +780,10 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS
     
 	for (; n < nd->mNumMeshes; ++n)
     {
-		const struct aiMesh* mesh = _scene->mMeshes[nd->mMeshes[n]];
+		const aiMesh* mesh = _scene->mMeshes[nd->mMeshes[n]];
 		for (t = 0; t < mesh->mNumVertices; ++t)
         {
-        	struct aiVector3D tmp = mesh->mVertices[t];
+        	aiVector3D tmp = mesh->mVertices[t];
 			aiTransformVecByMatrix4(&tmp,trafo);
             
 			min->x = aisgl_min(min->x,tmp.x);

+ 96 - 80
samples/SimpleAssimpViewX/SimpleAssimpViewX.xcodeproj/project.pbxproj

@@ -9,11 +9,6 @@
 /* Begin PBXBuildFile section */
 		1B0E9A901279ED43003108E7 /* libassimp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B0E9A8F1279ED43003108E7 /* libassimp.a */; };
 		1B0E9A951279EDCD003108E7 /* ModelLoaderHelperClasses.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1B0E9A941279EDCD003108E7 /* ModelLoaderHelperClasses.mm */; };
-		1B0E9AF51279EFCC003108E7 /* aiColor4D.inl in Resources */ = {isa = PBXBuildFile; fileRef = 1B0E9AD71279EFCC003108E7 /* aiColor4D.inl */; };
-		1B0E9AF61279EFCC003108E7 /* aiMaterial.inl in Resources */ = {isa = PBXBuildFile; fileRef = 1B0E9ADD1279EFCC003108E7 /* aiMaterial.inl */; };
-		1B0E9AF71279EFCC003108E7 /* aiMatrix3x3.inl in Resources */ = {isa = PBXBuildFile; fileRef = 1B0E9ADF1279EFCC003108E7 /* aiMatrix3x3.inl */; };
-		1B0E9AF81279EFCC003108E7 /* aiMatrix4x4.inl in Resources */ = {isa = PBXBuildFile; fileRef = 1B0E9AE11279EFCC003108E7 /* aiMatrix4x4.inl */; };
-		1B0E9AF91279EFCC003108E7 /* aiVector3D.inl in Resources */ = {isa = PBXBuildFile; fileRef = 1B0E9AEA1279EFCC003108E7 /* aiVector3D.inl */; };
 		1B0E9B1A1279F107003108E7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B0E9B191279F107003108E7 /* libz.dylib */; };
 		1BDF446B127772AF00D3E723 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1BDF446A127772AF00D3E723 /* OpenGL.framework */; };
 		1BDF446F127772AF00D3E723 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1BDF446E127772AF00D3E723 /* Quartz.framework */; };
@@ -25,6 +20,13 @@
 		8D15AC2F0486D014006FF6A4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165FFE840EACC02AAC07 /* InfoPlist.strings */; };
 		8D15AC310486D014006FF6A4 /* MyDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2A37F4ACFDCFA73011CA2CEA /* MyDocument.mm */; settings = {ATTRIBUTES = (); }; };
 		8D15AC320486D014006FF6A4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A37F4B0FDCFA73011CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
+		C75BB4F617EE0B64004F0260 /* color4.inl in Resources */ = {isa = PBXBuildFile; fileRef = C75BB4F117EE0B64004F0260 /* color4.inl */; };
+		C75BB4F717EE0B64004F0260 /* quaternion.inl in Resources */ = {isa = PBXBuildFile; fileRef = C75BB4F517EE0B64004F0260 /* quaternion.inl */; };
+		C75BB51417EE0B75004F0260 /* material.inl in Resources */ = {isa = PBXBuildFile; fileRef = C75BB50317EE0B75004F0260 /* material.inl */; };
+		C75BB51517EE0B75004F0260 /* matrix3x3.inl in Resources */ = {isa = PBXBuildFile; fileRef = C75BB50517EE0B75004F0260 /* matrix3x3.inl */; };
+		C75BB51617EE0B75004F0260 /* matrix4x4.inl in Resources */ = {isa = PBXBuildFile; fileRef = C75BB50717EE0B75004F0260 /* matrix4x4.inl */; };
+		C75BB51717EE0B75004F0260 /* vector2.inl in Resources */ = {isa = PBXBuildFile; fileRef = C75BB51017EE0B75004F0260 /* vector2.inl */; };
+		C75BB51817EE0B75004F0260 /* vector3.inl in Resources */ = {isa = PBXBuildFile; fileRef = C75BB51217EE0B75004F0260 /* vector3.inl */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
@@ -33,40 +35,6 @@
 		1B0E9A8F1279ED43003108E7 /* libassimp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libassimp.a; sourceTree = "<group>"; };
 		1B0E9A931279EDCD003108E7 /* ModelLoaderHelperClasses.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModelLoaderHelperClasses.h; sourceTree = "<group>"; };
 		1B0E9A941279EDCD003108E7 /* ModelLoaderHelperClasses.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ModelLoaderHelperClasses.mm; sourceTree = "<group>"; };
-		1B0E9AD31279EFCC003108E7 /* aiAnim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiAnim.h; sourceTree = "<group>"; };
-		1B0E9AD41279EFCC003108E7 /* aiAssert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiAssert.h; sourceTree = "<group>"; };
-		1B0E9AD51279EFCC003108E7 /* aiCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiCamera.h; sourceTree = "<group>"; };
-		1B0E9AD61279EFCC003108E7 /* aiColor4D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiColor4D.h; sourceTree = "<group>"; };
-		1B0E9AD71279EFCC003108E7 /* aiColor4D.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = aiColor4D.inl; sourceTree = "<group>"; };
-		1B0E9AD81279EFCC003108E7 /* aiConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiConfig.h; sourceTree = "<group>"; };
-		1B0E9AD91279EFCC003108E7 /* aiDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiDefines.h; sourceTree = "<group>"; };
-		1B0E9ADA1279EFCC003108E7 /* aiFileIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiFileIO.h; sourceTree = "<group>"; };
-		1B0E9ADB1279EFCC003108E7 /* aiLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiLight.h; sourceTree = "<group>"; };
-		1B0E9ADC1279EFCC003108E7 /* aiMaterial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiMaterial.h; sourceTree = "<group>"; };
-		1B0E9ADD1279EFCC003108E7 /* aiMaterial.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = aiMaterial.inl; sourceTree = "<group>"; };
-		1B0E9ADE1279EFCC003108E7 /* aiMatrix3x3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiMatrix3x3.h; sourceTree = "<group>"; };
-		1B0E9ADF1279EFCC003108E7 /* aiMatrix3x3.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = aiMatrix3x3.inl; sourceTree = "<group>"; };
-		1B0E9AE01279EFCC003108E7 /* aiMatrix4x4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiMatrix4x4.h; sourceTree = "<group>"; };
-		1B0E9AE11279EFCC003108E7 /* aiMatrix4x4.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = aiMatrix4x4.inl; sourceTree = "<group>"; };
-		1B0E9AE21279EFCC003108E7 /* aiMesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiMesh.h; sourceTree = "<group>"; };
-		1B0E9AE31279EFCC003108E7 /* aiPostProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiPostProcess.h; sourceTree = "<group>"; };
-		1B0E9AE41279EFCC003108E7 /* aiQuaternion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiQuaternion.h; sourceTree = "<group>"; };
-		1B0E9AE51279EFCC003108E7 /* aiScene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiScene.h; sourceTree = "<group>"; };
-		1B0E9AE61279EFCC003108E7 /* aiTexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiTexture.h; sourceTree = "<group>"; };
-		1B0E9AE71279EFCC003108E7 /* aiTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiTypes.h; sourceTree = "<group>"; };
-		1B0E9AE81279EFCC003108E7 /* aiVector2D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiVector2D.h; sourceTree = "<group>"; };
-		1B0E9AE91279EFCC003108E7 /* aiVector3D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiVector3D.h; sourceTree = "<group>"; };
-		1B0E9AEA1279EFCC003108E7 /* aiVector3D.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = aiVector3D.inl; sourceTree = "<group>"; };
-		1B0E9AEB1279EFCC003108E7 /* aiVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aiVersion.h; sourceTree = "<group>"; };
-		1B0E9AEC1279EFCC003108E7 /* assimp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assimp.h; sourceTree = "<group>"; };
-		1B0E9AED1279EFCC003108E7 /* assimp.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = assimp.hpp; sourceTree = "<group>"; };
-		1B0E9AEE1279EFCC003108E7 /* DefaultLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultLogger.h; sourceTree = "<group>"; };
-		1B0E9AEF1279EFCC003108E7 /* IOStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOStream.h; sourceTree = "<group>"; };
-		1B0E9AF01279EFCC003108E7 /* IOSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSystem.h; sourceTree = "<group>"; };
-		1B0E9AF11279EFCC003108E7 /* Logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logger.h; sourceTree = "<group>"; };
-		1B0E9AF21279EFCC003108E7 /* LogStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogStream.h; sourceTree = "<group>"; };
-		1B0E9AF31279EFCC003108E7 /* NullLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NullLogger.h; sourceTree = "<group>"; };
-		1B0E9AF41279EFCC003108E7 /* ProgressHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgressHandler.h; sourceTree = "<group>"; };
 		1B0E9AFD1279F006003108E7 /* poppack1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = poppack1.h; path = "/Users/vade/Asset Import/include/Compiler/poppack1.h"; sourceTree = "<absolute>"; };
 		1B0E9AFE1279F006003108E7 /* pushpack1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pushpack1.h; path = "/Users/vade/Asset Import/include/Compiler/pushpack1.h"; sourceTree = "<absolute>"; };
 		1B0E9B191279F107003108E7 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
@@ -85,6 +53,46 @@
 		7788DA0506752A1600599AAD /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
 		8D15AC360486D014006FF6A4 /* SimpleAssimpViewX-Info.plist */ = {isa = PBXFileReference; explicitFileType = text.plist.xml; fileEncoding = 4; path = "SimpleAssimpViewX-Info.plist"; sourceTree = "<group>"; };
 		8D15AC370486D014006FF6A4 /* SimpleAssimpViewX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SimpleAssimpViewX.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		C75BB4EA17EE0B64004F0260 /* ai_assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ai_assert.h; sourceTree = "<group>"; };
+		C75BB4EB17EE0B64004F0260 /* anim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = anim.h; sourceTree = "<group>"; };
+		C75BB4EC17EE0B64004F0260 /* camera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = camera.h; sourceTree = "<group>"; };
+		C75BB4ED17EE0B64004F0260 /* cexport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cexport.h; sourceTree = "<group>"; };
+		C75BB4EE17EE0B64004F0260 /* cfileio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cfileio.h; sourceTree = "<group>"; };
+		C75BB4EF17EE0B64004F0260 /* cimport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cimport.h; sourceTree = "<group>"; };
+		C75BB4F017EE0B64004F0260 /* color4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = color4.h; sourceTree = "<group>"; };
+		C75BB4F117EE0B64004F0260 /* color4.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = color4.inl; sourceTree = "<group>"; };
+		C75BB4F217EE0B64004F0260 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
+		C75BB4F317EE0B64004F0260 /* metadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadata.h; sourceTree = "<group>"; };
+		C75BB4F417EE0B64004F0260 /* NullLogger.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = NullLogger.hpp; sourceTree = "<group>"; };
+		C75BB4F517EE0B64004F0260 /* quaternion.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = quaternion.inl; sourceTree = "<group>"; };
+		C75BB4F817EE0B75004F0260 /* DefaultLogger.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DefaultLogger.hpp; sourceTree = "<group>"; };
+		C75BB4F917EE0B75004F0260 /* defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = defs.h; sourceTree = "<group>"; };
+		C75BB4FA17EE0B75004F0260 /* Exporter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Exporter.hpp; sourceTree = "<group>"; };
+		C75BB4FB17EE0B75004F0260 /* Importer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Importer.hpp; sourceTree = "<group>"; };
+		C75BB4FC17EE0B75004F0260 /* importerdesc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = importerdesc.h; sourceTree = "<group>"; };
+		C75BB4FD17EE0B75004F0260 /* IOStream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = IOStream.hpp; sourceTree = "<group>"; };
+		C75BB4FE17EE0B75004F0260 /* IOSystem.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = IOSystem.hpp; sourceTree = "<group>"; };
+		C75BB4FF17EE0B75004F0260 /* light.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = light.h; sourceTree = "<group>"; };
+		C75BB50017EE0B75004F0260 /* Logger.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Logger.hpp; sourceTree = "<group>"; };
+		C75BB50117EE0B75004F0260 /* LogStream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LogStream.hpp; sourceTree = "<group>"; };
+		C75BB50217EE0B75004F0260 /* material.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = material.h; sourceTree = "<group>"; };
+		C75BB50317EE0B75004F0260 /* material.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = material.inl; sourceTree = "<group>"; };
+		C75BB50417EE0B75004F0260 /* matrix3x3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrix3x3.h; sourceTree = "<group>"; };
+		C75BB50517EE0B75004F0260 /* matrix3x3.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = matrix3x3.inl; sourceTree = "<group>"; };
+		C75BB50617EE0B75004F0260 /* matrix4x4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrix4x4.h; sourceTree = "<group>"; };
+		C75BB50717EE0B75004F0260 /* matrix4x4.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = matrix4x4.inl; sourceTree = "<group>"; };
+		C75BB50817EE0B75004F0260 /* mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mesh.h; sourceTree = "<group>"; };
+		C75BB50917EE0B75004F0260 /* postprocess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = postprocess.h; sourceTree = "<group>"; };
+		C75BB50A17EE0B75004F0260 /* ProgressHandler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ProgressHandler.hpp; sourceTree = "<group>"; };
+		C75BB50B17EE0B75004F0260 /* quaternion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = quaternion.h; sourceTree = "<group>"; };
+		C75BB50C17EE0B75004F0260 /* scene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scene.h; sourceTree = "<group>"; };
+		C75BB50D17EE0B75004F0260 /* texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = texture.h; sourceTree = "<group>"; };
+		C75BB50E17EE0B75004F0260 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = "<group>"; };
+		C75BB50F17EE0B75004F0260 /* vector2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vector2.h; sourceTree = "<group>"; };
+		C75BB51017EE0B75004F0260 /* vector2.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = vector2.inl; sourceTree = "<group>"; };
+		C75BB51117EE0B75004F0260 /* vector3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vector3.h; sourceTree = "<group>"; };
+		C75BB51217EE0B75004F0260 /* vector3.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = vector3.inl; sourceTree = "<group>"; };
+		C75BB51317EE0B75004F0260 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -134,40 +142,46 @@
 		1B0E9AD21279EFCC003108E7 /* include */ = {
 			isa = PBXGroup;
 			children = (
-				1B0E9AD31279EFCC003108E7 /* aiAnim.h */,
-				1B0E9AD41279EFCC003108E7 /* aiAssert.h */,
-				1B0E9AD51279EFCC003108E7 /* aiCamera.h */,
-				1B0E9AD61279EFCC003108E7 /* aiColor4D.h */,
-				1B0E9AD71279EFCC003108E7 /* aiColor4D.inl */,
-				1B0E9AD81279EFCC003108E7 /* aiConfig.h */,
-				1B0E9AD91279EFCC003108E7 /* aiDefines.h */,
-				1B0E9ADA1279EFCC003108E7 /* aiFileIO.h */,
-				1B0E9ADB1279EFCC003108E7 /* aiLight.h */,
-				1B0E9ADC1279EFCC003108E7 /* aiMaterial.h */,
-				1B0E9ADD1279EFCC003108E7 /* aiMaterial.inl */,
-				1B0E9ADE1279EFCC003108E7 /* aiMatrix3x3.h */,
-				1B0E9ADF1279EFCC003108E7 /* aiMatrix3x3.inl */,
-				1B0E9AE01279EFCC003108E7 /* aiMatrix4x4.h */,
-				1B0E9AE11279EFCC003108E7 /* aiMatrix4x4.inl */,
-				1B0E9AE21279EFCC003108E7 /* aiMesh.h */,
-				1B0E9AE31279EFCC003108E7 /* aiPostProcess.h */,
-				1B0E9AE41279EFCC003108E7 /* aiQuaternion.h */,
-				1B0E9AE51279EFCC003108E7 /* aiScene.h */,
-				1B0E9AE61279EFCC003108E7 /* aiTexture.h */,
-				1B0E9AE71279EFCC003108E7 /* aiTypes.h */,
-				1B0E9AE81279EFCC003108E7 /* aiVector2D.h */,
-				1B0E9AE91279EFCC003108E7 /* aiVector3D.h */,
-				1B0E9AEA1279EFCC003108E7 /* aiVector3D.inl */,
-				1B0E9AEB1279EFCC003108E7 /* aiVersion.h */,
-				1B0E9AEC1279EFCC003108E7 /* assimp.h */,
-				1B0E9AED1279EFCC003108E7 /* assimp.hpp */,
-				1B0E9AEE1279EFCC003108E7 /* DefaultLogger.h */,
-				1B0E9AEF1279EFCC003108E7 /* IOStream.h */,
-				1B0E9AF01279EFCC003108E7 /* IOSystem.h */,
-				1B0E9AF11279EFCC003108E7 /* Logger.h */,
-				1B0E9AF21279EFCC003108E7 /* LogStream.h */,
-				1B0E9AF31279EFCC003108E7 /* NullLogger.h */,
-				1B0E9AF41279EFCC003108E7 /* ProgressHandler.h */,
+				C75BB4F817EE0B75004F0260 /* DefaultLogger.hpp */,
+				C75BB4F917EE0B75004F0260 /* defs.h */,
+				C75BB4FA17EE0B75004F0260 /* Exporter.hpp */,
+				C75BB4FB17EE0B75004F0260 /* Importer.hpp */,
+				C75BB4FC17EE0B75004F0260 /* importerdesc.h */,
+				C75BB4FD17EE0B75004F0260 /* IOStream.hpp */,
+				C75BB4FE17EE0B75004F0260 /* IOSystem.hpp */,
+				C75BB4FF17EE0B75004F0260 /* light.h */,
+				C75BB50017EE0B75004F0260 /* Logger.hpp */,
+				C75BB50117EE0B75004F0260 /* LogStream.hpp */,
+				C75BB50217EE0B75004F0260 /* material.h */,
+				C75BB50317EE0B75004F0260 /* material.inl */,
+				C75BB50417EE0B75004F0260 /* matrix3x3.h */,
+				C75BB50517EE0B75004F0260 /* matrix3x3.inl */,
+				C75BB50617EE0B75004F0260 /* matrix4x4.h */,
+				C75BB50717EE0B75004F0260 /* matrix4x4.inl */,
+				C75BB50817EE0B75004F0260 /* mesh.h */,
+				C75BB50917EE0B75004F0260 /* postprocess.h */,
+				C75BB50A17EE0B75004F0260 /* ProgressHandler.hpp */,
+				C75BB50B17EE0B75004F0260 /* quaternion.h */,
+				C75BB50C17EE0B75004F0260 /* scene.h */,
+				C75BB50D17EE0B75004F0260 /* texture.h */,
+				C75BB50E17EE0B75004F0260 /* types.h */,
+				C75BB50F17EE0B75004F0260 /* vector2.h */,
+				C75BB51017EE0B75004F0260 /* vector2.inl */,
+				C75BB51117EE0B75004F0260 /* vector3.h */,
+				C75BB51217EE0B75004F0260 /* vector3.inl */,
+				C75BB51317EE0B75004F0260 /* version.h */,
+				C75BB4EA17EE0B64004F0260 /* ai_assert.h */,
+				C75BB4EB17EE0B64004F0260 /* anim.h */,
+				C75BB4EC17EE0B64004F0260 /* camera.h */,
+				C75BB4ED17EE0B64004F0260 /* cexport.h */,
+				C75BB4EE17EE0B64004F0260 /* cfileio.h */,
+				C75BB4EF17EE0B64004F0260 /* cimport.h */,
+				C75BB4F017EE0B64004F0260 /* color4.h */,
+				C75BB4F117EE0B64004F0260 /* color4.inl */,
+				C75BB4F217EE0B64004F0260 /* config.h */,
+				C75BB4F317EE0B64004F0260 /* metadata.h */,
+				C75BB4F417EE0B64004F0260 /* NullLogger.hpp */,
+				C75BB4F517EE0B64004F0260 /* quaternion.inl */,
 				1B0E9AFC1279F006003108E7 /* Compiler */,
 			);
 			path = include;
@@ -295,11 +309,13 @@
 				8D15AC2F0486D014006FF6A4 /* InfoPlist.strings in Resources */,
 				2F7446AB0DB6BCF400F9684A /* MainMenu.xib in Resources */,
 				2F7446AC0DB6BCF400F9684A /* MyDocument.xib in Resources */,
-				1B0E9AF51279EFCC003108E7 /* aiColor4D.inl in Resources */,
-				1B0E9AF61279EFCC003108E7 /* aiMaterial.inl in Resources */,
-				1B0E9AF71279EFCC003108E7 /* aiMatrix3x3.inl in Resources */,
-				1B0E9AF81279EFCC003108E7 /* aiMatrix4x4.inl in Resources */,
-				1B0E9AF91279EFCC003108E7 /* aiVector3D.inl in Resources */,
+				C75BB4F617EE0B64004F0260 /* color4.inl in Resources */,
+				C75BB4F717EE0B64004F0260 /* quaternion.inl in Resources */,
+				C75BB51417EE0B75004F0260 /* material.inl in Resources */,
+				C75BB51517EE0B75004F0260 /* matrix3x3.inl in Resources */,
+				C75BB51617EE0B75004F0260 /* matrix4x4.inl in Resources */,
+				C75BB51717EE0B75004F0260 /* vector2.inl in Resources */,
+				C75BB51817EE0B75004F0260 /* vector3.inl in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -413,7 +429,7 @@
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				PREBINDING = NO;
-				SDKROOT = macosx10.6;
+				SDKROOT = macosx;
 			};
 			name = Debug;
 		};
@@ -425,7 +441,7 @@
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				PREBINDING = NO;
-				SDKROOT = macosx10.6;
+				SDKROOT = macosx;
 			};
 			name = Release;
 		};

+ 35 - 34
samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp

@@ -36,9 +36,8 @@
 #include "assimp/LogStream.hpp"
 
 
-// currently these are hardcoded
-static const std::string basepath = "../../test/models/OBJ/";
-static const std::string modelname = "spider.obj";
+// The default hardcoded path. Can be overridden by supplying a path through the commandline.
+static std::string modelpath = "../../test/models/OBJ/spider.obj";
 
 
 HGLRC		hRC=NULL;			// Permanent Rendering Context
@@ -165,6 +164,11 @@ void ReSizeGLScene(GLsizei width, GLsizei height)				// Resize And Initialize Th
 }
 
 
+std::string getBasePath(const std::string& path)
+{
+	size_t pos = path.find_last_of("\\/");
+	return (std::string::npos == pos) ? "" : path.substr(0, pos + 1);
+}
 
 int LoadGLTextures(const aiScene* scene)
 {
@@ -220,6 +224,7 @@ int LoadGLTextures(const aiScene* scene)
 	/* get iterator */
 	std::map<std::string, GLuint*>::iterator itr = textureIdMap.begin();
 
+	std::string basepath = getBasePath(modelpath);
 	for (int i=0; i<numTextures; i++)
 	{
 
@@ -799,52 +804,52 @@ LRESULT CALLBACK WndProc(HWND hWnd,				// Handles for this Window
 	return DefWindowProc(hWnd, uMsg, wParam, lParam);
 }
 
-
 int WINAPI WinMain( HINSTANCE hInstance, // Instance
 				   HINSTANCE hPrevInstance,      // Previous Instance
 				   LPSTR lpCmdLine,              // Command Line Parameters
 				   int nShowCmd )                // Window Show State
 {
-	MSG msg;			// Windows Message Structure
-	BOOL done=FALSE;	// Bool Variable To Exit Loop
+	MSG msg;
+	BOOL done=FALSE;
 
 	createAILogger();
 	logInfo("App fired!");
 
-	// load scene
+	// Check the command line for an override file path.
+	int argc;
+	LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+	if (argv != NULL && argc > 1)
+	{
+		std::wstring modelpathW(argv[1]);
+		modelpath = std::string(modelpathW.begin(), modelpathW.end());
+	}
 
-	if (!Import3DFromFile(basepath+modelname)) return 0;
+	if (!Import3DFromFile(modelpath)) return 0;
 
 	logInfo("=============== Post Import ====================");
 
-
-	// Ask The User Which Screen Mode They Prefer
 	if (MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start Fullscreen?", MB_YESNO|MB_ICONEXCLAMATION)==IDNO)
 	{
-		fullscreen=FALSE;		// Windowed Mode
+		fullscreen=FALSE;
 	}
 
-	// Create Our OpenGL Window (also calls GLinit und LoadGLTextures)
 	if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen))
 	{
 		return 0;
 	}
 
-
-
-
 	while(!done)	// Game Loop
 	{
-		if (PeekMessage(&msg, NULL, 0,0, PM_REMOVE))	// Is There A Message Waiting
+		if (PeekMessage(&msg, NULL, 0,0, PM_REMOVE))
 		{
-			if (msg.message==WM_QUIT)			// Have we received A Quit Message?
+			if (msg.message==WM_QUIT)
 			{
-				done=TRUE;						// If So done=TRUE
+				done=TRUE;
 			}
 			else
 			{
-				TranslateMessage(&msg);			// Translate The Message
-				DispatchMessage(&msg);			// Dispatch The Message
+				TranslateMessage(&msg);
+				DispatchMessage(&msg);
 			}
 		}
 		else
@@ -852,26 +857,25 @@ int WINAPI WinMain( HINSTANCE hInstance, // Instance
 			// Draw The Scene. Watch For ESC Key And Quit Messaged From DrawGLScene()
 			if (active)
 			{
-				if (keys[VK_ESCAPE])	// Was ESC pressed?
+				if (keys[VK_ESCAPE])
 				{
-					done=TRUE;			// ESC signalled A quit
+					done=TRUE;
 				}
 				else
 				{
-					DrawGLScene();		// Draw The Scene
-					SwapBuffers(hDC);	// Swap Buffers (Double Buffering)
+					DrawGLScene();
+					SwapBuffers(hDC);
 				}
 			}
 
-			if (keys[VK_F1])		// Is F1 Being Pressed?
+			if (keys[VK_F1])
 			{
-				keys[VK_F1]=FALSE;	// If so make Key FALSE
-				KillGLWindow();		// Kill Our Current Window
-				fullscreen=!fullscreen;	// Toggle Fullscreen
-				//recreate Our OpenGL Window
+				keys[VK_F1]=FALSE;
+				KillGLWindow();
+				fullscreen=!fullscreen;
 				if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen))
 				{
-					return 0;		// Quit if Window Was Not Created
+					return 0;
 				}
 			}
 		}
@@ -879,10 +883,8 @@ int WINAPI WinMain( HINSTANCE hInstance, // Instance
 
 	// *** cleanup ***
 
-	// clear map
 	textureIdMap.clear(); //no need to delete pointers in it manually here. (Pointers point to textureIds deleted in next step)
 
-	// clear texture ids
 	if (textureIds)
 	{
 		delete[] textureIds;
@@ -891,8 +893,7 @@ int WINAPI WinMain( HINSTANCE hInstance, // Instance
 
 	// *** cleanup end ***
 
-	// Shutdown
 	destroyAILogger();
 	KillGLWindow();
-	return (msg.wParam);	// Exit The Program
+	return (msg.wParam);
 }

+ 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)

+ 7 - 0
tools/assimp_cmd/CMakeLists.txt

@@ -19,6 +19,13 @@ ADD_EXECUTABLE( assimp_cmd
 
 SET_PROPERTY(TARGET assimp_cmd PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
 
+IF( WIN32 )
+	ADD_CUSTOM_COMMAND(TARGET assimp_cmd
+		PRE_BUILD
+		COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:assimp> $<TARGET_FILE_DIR:assimp_cmd>
+		MAIN_DEPENDENCY assimp)
+ENDIF( WIN32 )
+
 TARGET_LINK_LIBRARIES( assimp_cmd assimp ${ZLIB_LIBRARIES})
 SET_TARGET_PROPERTIES( assimp_cmd PROPERTIES
 	OUTPUT_NAME assimp

+ 16 - 13
tools/assimp_view/CMakeLists.txt

@@ -1,18 +1,16 @@
 FIND_PACKAGE(DirectX REQUIRED)
 
-# Make sure the compiler can find include files from our Hello library.
-include_directories (
+
+INCLUDE_DIRECTORIES (
 	${Assimp_SOURCE_DIR}/include
 	${Assimp_SOURCE_DIR}/code
 	${DirectX_INCLUDE_DIR}
 )
 
-# Make sure the linker can find the Hello library once it is built.
-link_directories (${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib)
+# Make sure the linker can find the Assimp library once it is built.
+LINK_DIRECTORIES (${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib)
 
-# Add executable called "helloDemo" that is built from the source files
-# "demo.cxx" and "demo_b.cxx". The extensions are automatically found.
-add_executable(  assimp_viewer WIN32
+ADD_EXECUTABLE(  assimp_viewer WIN32
 	AnimEvaluator.cpp
 	Background.cpp
 	Display.cpp
@@ -45,13 +43,18 @@ add_executable(  assimp_viewer WIN32
 
 SET_PROPERTY(TARGET assimp_viewer PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
 
-IF( WIN32 )
-	ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
-	ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
-ENDIF( WIN32 )
+ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
+ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
+
+
+#
+ADD_CUSTOM_COMMAND(TARGET assimp_viewer 
+	PRE_BUILD
+	COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:assimp> $<TARGET_FILE_DIR:assimp_viewer>
+	MAIN_DEPENDENCY assimp)
 
-# Link the executable to the Hello library.
-target_link_libraries ( assimp_viewer assimp ${DirectX_LIBRARY} ${DirectX_D3DX9_LIBRARY} comctl32.lib Winmm.lib  ) 
+# Link the executable to the assimp + dx libs.
+TARGET_LINK_LIBRARIES ( assimp_viewer assimp ${DirectX_LIBRARY} ${DirectX_D3DX9_LIBRARY} comctl32.lib Winmm.lib  ) 
 
 INSTALL( TARGETS assimp_viewer
 	DESTINATION "${ASSIMP_BIN_INSTALL_DIR}" COMPONENT assimp-dev

+ 0 - 32
workspaces/xcode3/assimp.xcodeproj/project.pbxproj

@@ -1487,7 +1487,6 @@
 		B919758A163AEA54009C397B /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9E1543268400E63FFE /* version.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		B919758B163AEA54009C397B /* OgreImporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C36154328B600E63FFE /* OgreImporter.hpp */; };
 		B919758C163AEA54009C397B /* OgreXmlHelper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C3A154328B600E63FFE /* OgreXmlHelper.hpp */; };
-		B9197595163AEA54009C397B /* M3Importer.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F2715436207000682F3 /* M3Importer.h */; };
 		B9197596163AEA54009C397B /* PlyExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F3115436269000682F3 /* PlyExporter.h */; };
 		B919759C163AEA54009C397B /* crc32.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704B154366AB004D91DD /* crc32.h */; };
 		B919759D163AEA54009C397B /* deflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704D154366AB004D91DD /* deflate.h */; };
@@ -1565,7 +1564,6 @@
 		B919761A163AEA54009C397B /* OgreMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C37154328B600E63FFE /* OgreMaterial.cpp */; };
 		B919761B163AEA54009C397B /* OgreMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C38154328B600E63FFE /* OgreMesh.cpp */; };
 		B919761C163AEA54009C397B /* OgreSkeleton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C39154328B600E63FFE /* OgreSkeleton.cpp */; };
-		B919761F163AEA54009C397B /* M3Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F2615436207000682F3 /* M3Importer.cpp */; };
 		B9197620163AEA54009C397B /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F3015436269000682F3 /* PlyExporter.cpp */; };
 		B9197625163AEA54009C397B /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607047154366AB004D91DD /* adler32.c */; };
 		B9197626163AEA54009C397B /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607049154366AB004D91DD /* compress.c */; };
@@ -1830,14 +1828,6 @@
 		F97BA03715439DB3009EB9DD /* ai_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = F97BA03515439DB3009EB9DD /* ai_assert.h */; };
 		F97BA03815439DB3009EB9DD /* ai_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = F97BA03515439DB3009EB9DD /* ai_assert.h */; };
 		F97BA03915439DB3009EB9DD /* ai_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = F97BA03515439DB3009EB9DD /* ai_assert.h */; };
-		F99A9F2815436207000682F3 /* M3Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F2615436207000682F3 /* M3Importer.cpp */; };
-		F99A9F2915436207000682F3 /* M3Importer.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F2715436207000682F3 /* M3Importer.h */; };
-		F99A9F2A15436207000682F3 /* M3Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F2615436207000682F3 /* M3Importer.cpp */; };
-		F99A9F2B15436207000682F3 /* M3Importer.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F2715436207000682F3 /* M3Importer.h */; };
-		F99A9F2C15436207000682F3 /* M3Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F2615436207000682F3 /* M3Importer.cpp */; };
-		F99A9F2D15436207000682F3 /* M3Importer.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F2715436207000682F3 /* M3Importer.h */; };
-		F99A9F2E15436207000682F3 /* M3Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F2615436207000682F3 /* M3Importer.cpp */; };
-		F99A9F2F15436207000682F3 /* M3Importer.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F2715436207000682F3 /* M3Importer.h */; };
 		F99A9F3215436269000682F3 /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F3015436269000682F3 /* PlyExporter.cpp */; };
 		F99A9F3315436269000682F3 /* PlyExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F3115436269000682F3 /* PlyExporter.h */; };
 		F99A9F3415436269000682F3 /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F3015436269000682F3 /* PlyExporter.cpp */; };
@@ -2369,8 +2359,6 @@
 		F96070DD1543675E004D91DD /* sweep_context.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sweep_context.cc; sourceTree = "<group>"; };
 		F96070DE1543675E004D91DD /* sweep_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sweep_context.h; sourceTree = "<group>"; };
 		F97BA03515439DB3009EB9DD /* ai_assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ai_assert.h; sourceTree = "<group>"; };
-		F99A9F2615436207000682F3 /* M3Importer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = M3Importer.cpp; path = ../../code/M3Importer.cpp; sourceTree = SOURCE_ROOT; };
-		F99A9F2715436207000682F3 /* M3Importer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = M3Importer.h; path = ../../code/M3Importer.h; sourceTree = SOURCE_ROOT; };
 		F99A9F3015436269000682F3 /* PlyExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlyExporter.cpp; sourceTree = "<group>"; };
 		F99A9F3115436269000682F3 /* PlyExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlyExporter.h; sourceTree = "<group>"; };
 		F9BA8B751543268400E63FFE /* anim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = anim.h; sourceTree = "<group>"; };
@@ -3173,7 +3161,6 @@
 				F90BAFD40F5DD8F200124155 /* IRR */,
 				3AB8A3A80E50D5F400606590 /* LWO */,
 				7411B15811416D6600BCD793 /* LWS */,
-				F99A9F21154361F8000682F3 /* M3 */,
 				3AF45B870E4B74DA00207D74 /* MD2 */,
 				3AF45B880E4B751000207D74 /* MD3 */,
 				3AF45B8A0E4B755E00207D74 /* MD5 */,
@@ -3309,15 +3296,6 @@
 			name = IFC;
 			sourceTree = "<group>";
 		};
-		F99A9F21154361F8000682F3 /* M3 */ = {
-			isa = PBXGroup;
-			children = (
-				F99A9F2615436207000682F3 /* M3Importer.cpp */,
-				F99A9F2715436207000682F3 /* M3Importer.h */,
-			);
-			name = M3;
-			sourceTree = "<group>";
-		};
 		F99A9F5315436318000682F3 /* STEP */ = {
 			isa = PBXGroup;
 			children = (
@@ -3499,7 +3477,6 @@
 				F9BA8C041543268400E63FFE /* version.h in Headers */,
 				F9BA8C48154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C4C154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
-				F99A9F2D15436207000682F3 /* M3Importer.h in Headers */,
 				F99A9F3715436269000682F3 /* PlyExporter.h in Headers */,
 				F9607088154366AB004D91DD /* crc32.h in Headers */,
 				F960708A154366AB004D91DD /* deflate.h in Headers */,
@@ -3748,7 +3725,6 @@
 				F9BA8C261543268400E63FFE /* version.h in Headers */,
 				F9BA8C4E154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C52154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
-				F99A9F2F15436207000682F3 /* M3Importer.h in Headers */,
 				F99A9F3915436269000682F3 /* PlyExporter.h in Headers */,
 				F960709C154366AB004D91DD /* crc32.h in Headers */,
 				F960709E154366AB004D91DD /* deflate.h in Headers */,
@@ -3997,7 +3973,6 @@
 				B919758A163AEA54009C397B /* version.h in Headers */,
 				B919758B163AEA54009C397B /* OgreImporter.hpp in Headers */,
 				B919758C163AEA54009C397B /* OgreXmlHelper.hpp in Headers */,
-				B9197595163AEA54009C397B /* M3Importer.h in Headers */,
 				B9197596163AEA54009C397B /* PlyExporter.h in Headers */,
 				B919759C163AEA54009C397B /* crc32.h in Headers */,
 				B919759D163AEA54009C397B /* deflate.h in Headers */,
@@ -4246,7 +4221,6 @@
 				F9BA8BC01543268400E63FFE /* version.h in Headers */,
 				F9BA8C3C154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C40154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
-				F99A9F2915436207000682F3 /* M3Importer.h in Headers */,
 				F99A9F3315436269000682F3 /* PlyExporter.h in Headers */,
 				F9607060154366AB004D91DD /* crc32.h in Headers */,
 				F9607062154366AB004D91DD /* deflate.h in Headers */,
@@ -4495,7 +4469,6 @@
 				F9BA8BE21543268400E63FFE /* version.h in Headers */,
 				F9BA8C42154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C46154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
-				F99A9F2B15436207000682F3 /* M3Importer.h in Headers */,
 				F99A9F3515436269000682F3 /* PlyExporter.h in Headers */,
 				F9607074154366AB004D91DD /* crc32.h in Headers */,
 				F9607076154366AB004D91DD /* deflate.h in Headers */,
@@ -4815,7 +4788,6 @@
 				F9BA8C49154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C4A154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C4B154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
-				F99A9F2C15436207000682F3 /* M3Importer.cpp in Sources */,
 				F99A9F3615436269000682F3 /* PlyExporter.cpp in Sources */,
 				F9607085154366AB004D91DD /* adler32.c in Sources */,
 				F9607086154366AB004D91DD /* compress.c in Sources */,
@@ -4978,7 +4950,6 @@
 				F9BA8C4F154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C50154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C51154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
-				F99A9F2E15436207000682F3 /* M3Importer.cpp in Sources */,
 				F99A9F3815436269000682F3 /* PlyExporter.cpp in Sources */,
 				F9607099154366AB004D91DD /* adler32.c in Sources */,
 				F960709A154366AB004D91DD /* compress.c in Sources */,
@@ -5141,7 +5112,6 @@
 				B919761A163AEA54009C397B /* OgreMaterial.cpp in Sources */,
 				B919761B163AEA54009C397B /* OgreMesh.cpp in Sources */,
 				B919761C163AEA54009C397B /* OgreSkeleton.cpp in Sources */,
-				B919761F163AEA54009C397B /* M3Importer.cpp in Sources */,
 				B9197620163AEA54009C397B /* PlyExporter.cpp in Sources */,
 				B9197625163AEA54009C397B /* adler32.c in Sources */,
 				B9197626163AEA54009C397B /* compress.c in Sources */,
@@ -5304,7 +5274,6 @@
 				F9BA8C3D154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C3E154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C3F154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
-				F99A9F2815436207000682F3 /* M3Importer.cpp in Sources */,
 				F99A9F3215436269000682F3 /* PlyExporter.cpp in Sources */,
 				F960705D154366AB004D91DD /* adler32.c in Sources */,
 				F960705E154366AB004D91DD /* compress.c in Sources */,
@@ -5467,7 +5436,6 @@
 				F9BA8C43154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C44154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C45154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
-				F99A9F2A15436207000682F3 /* M3Importer.cpp in Sources */,
 				F99A9F3415436269000682F3 /* PlyExporter.cpp in Sources */,
 				F9607071154366AB004D91DD /* adler32.c in Sources */,
 				F9607072154366AB004D91DD /* compress.c in Sources */,