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

Merge commit '87a0e7703258576f1a7e4ba763b961da70c1cd91' into contrib

Conflicts:
	code/ColladaExporter.cpp
Léo Terziman 11 жил өмнө
parent
commit
6c0ebb679a
37 өөрчлөгдсөн 1715 нэмэгдсэн , 1196 устгасан
  1. 1 1
      CMakeLists.txt
  2. 26 24
      Readme.md
  3. 1 0
      code/AssimpCExport.cpp
  4. 17 11
      code/BlenderDNA.h
  5. 53 27
      code/BlenderDNA.inl
  6. 64 8
      code/BlenderLoader.cpp
  7. 667 638
      code/BlenderScene.cpp
  8. 35 3
      code/BlenderScene.h
  9. 198 198
      code/BlenderSceneGen.h
  10. 8 9
      code/ColladaExporter.cpp
  11. 43 6
      code/Exporter.cpp
  12. 10 5
      code/FBXDocument.cpp
  13. 2 2
      code/IRRMeshLoader.cpp
  14. 3 2
      code/IRRShared.cpp
  15. 5 0
      code/LWOLoader.cpp
  16. 13 11
      code/LWOMaterial.cpp
  17. 41 11
      code/ObjExporter.cpp
  18. 30 0
      code/ObjExporter.h
  19. 20 19
      code/ObjFileImporter.cpp
  20. 3 6
      code/ObjFileImporter.h
  21. 52 7
      code/ObjFileParser.cpp
  22. 2 2
      code/PlyExporter.cpp
  23. 11 2
      code/STLLoader.cpp
  24. 8 0
      code/ScenePrivate.h
  25. 7 1
      include/assimp/Exporter.hpp
  26. 6 0
      include/assimp/cexport.h
  27. 61 0
      include/assimp/material.h
  28. 94 22
      include/assimp/material.inl
  29. 4 4
      samples/SimpleAssimpViewX/ModelLoaderHelperClasses.h
  30. 7 6
      samples/SimpleAssimpViewX/MyDocument.h
  31. 14 10
      samples/SimpleAssimpViewX/MyDocument.mm
  32. 96 80
      samples/SimpleAssimpViewX/SimpleAssimpViewX.xcodeproj/project.pbxproj
  33. 35 34
      samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp
  34. 55 2
      scripts/BlenderImporter/genblenddna.py
  35. 7 0
      tools/assimp_cmd/CMakeLists.txt
  36. 16 13
      tools/assimp_view/CMakeLists.txt
  37. 0 32
      workspaces/xcode3/assimp.xcodeproj/project.pbxproj

+ 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
 # Globally enbale Boost resp. the Boost workaround – it is also needed by the
 # tools which include the Assimp headers.
 # 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 a simple implementation of the used Boost functions is used. Slightly reduces functionality, but enables builds without Boost available."
 )
 )
 IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
 IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )

+ 26 - 24
Readme.md

@@ -1,7 +1,7 @@
 Open Asset Import Library (assimp) 
 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__. 
 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
 - 3DS
 - BLEND (Blender 3D)
 - BLEND (Blender 3D)
-- DAE (Collada)
+- DAE/Collada
 - FBX
 - FBX
 - IFC-STEP 
 - IFC-STEP 
 - ASE
 - 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 
 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
 	/code		Source code
 	/contrib	Third-party libraries
 	/contrib	Third-party libraries
 	/doc		Documentation (doxysource and pre-compiled docs)
 	/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 
 	/samples	A small number of samples to illustrate possible 
-                        use cases for Assimp.
+                        use cases for Assimp
 	/workspaces	Build enviroments for vc,xcode,... (deprecated,
 	/workspaces	Build enviroments for vc,xcode,... (deprecated,
 			CMake has superseeded all legacy build options!)
 			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.
 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.
 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).
 (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) 
   [(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);
 	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 
 	// field parsing for pointer or dynamic array types 
 	// (boost::shared_ptr or boost::shared_array)
 	// (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>
 	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
 	// field parsing for static arrays of pointer or dynamic
 	// array types (boost::shared_ptr[] or boost::shared_array[])
 	// 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>
 	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;
 		const FileDatabase& db) const;
 
 
 	// --------------------------------------------------------
 	// --------------------------------------------------------
 	// field parsing for `normal` values
 	// field parsing for `normal` values
+	// The return value indicates whether the data was already cached.
 	template <int error_policy, typename T>
 	template <int error_policy, typename T>
 	void ReadField(T& out, const char* name, 
 	void ReadField(T& out, const char* name, 
 		const FileDatabase& db) const;
 		const FileDatabase& db) const;
@@ -299,17 +303,18 @@ private:
 
 
 	// --------------------------------------------------------
 	// --------------------------------------------------------
 	template <template <typename> class TOUT, typename T>
 	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>
 	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(
 	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 Pointer & ptrval, 
 	const FileDatabase& db, 
 	const FileDatabase& db, 
-	const Field& f
+	const Field& f,
+	bool
 	) const;
 	) 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>
 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();
 	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
 	Pointer ptrval;
 	Pointer ptrval;
@@ -203,23 +204,27 @@ void Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabas
 		_defaultInitializer<error_policy>()(out,e.what());
 		_defaultInitializer<error_policy>()(out,e.what());
 
 
 		out.reset();
 		out.reset();
-		return;
+		return false;
 	}
 	}
 
 
 	// resolve the pointer and load the corresponding structure
 	// 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
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 	++db.stats().fields_read;
 	++db.stats().fields_read;
 #endif
 #endif
+
+	return res;
 }
 }
 
 
 //--------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------
 template <int error_policy, template <typename> class TOUT, typename T, size_t N>
 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
 	const FileDatabase& db) const
 {
 {
 	// XXX see if we can reduce this to call to the 'normal' ReadFieldPtr
 	// 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) {
 		for(size_t i = 0; i < N; ++i) {
 			out[i].reset();
 			out[i].reset();
 		}
 		}
-		return;
+		return false;
 	}
 	}
+
+	bool res = true;
 	for(size_t i = 0; i < N; ++i) {
 	for(size_t i = 0; i < N; ++i) {
 		// resolve the pointer and load the corresponding structure
 		// 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
 	// 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
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 	++db.stats().fields_read;
 	++db.stats().fields_read;
 #endif
 #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>
 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) { 
 	if (!ptrval.val) { 
-		return;
+		return false;
 	}
 	}
 	const Structure& s = db.dna[f.type];
 	const Structure& s = db.dna[f.type];
 	// find the file block the pointer is pointing to
 	// 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
 	// try to retrieve the object from the cache
 	db.cache(out).get(s,out,ptrval); 
 	db.cache(out).get(s,out,ptrval); 
 	if (out) {
 	if (out) {
-		return;
+		return true;
 	}
 	}
 
 
 	// seek to this location, but save the previous stream pointer.
 	// 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.
 	// cache the object before we convert it to avoid cyclic recursion.
 	db.cache(out).set(s,out,ptrval); 
 	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
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 	if(out) {
 	if(out) {
 		++db.stats().pointers_resolved;
 		++db.stats().pointers_resolved;
 	}
 	}
 #endif
 #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
 	// Currently used exclusively by PackedFile::data to represent
 	// a simple offset into the mapped BLEND file. 
 	// a simple offset into the mapped BLEND file. 
 	out.reset();
 	out.reset();
 	if (!ptrval.val) { 
 	if (!ptrval.val) { 
-		return;
+		return false;
 	}
 	}
 
 
 	// find the file block the pointer is pointing to
 	// 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 =  boost::shared_ptr< FileOffset > (new FileOffset());
 	out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
 	out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
+	return false;
 }
 }
 
 
 //--------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------
 template <template <typename> class TOUT, typename T>
 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
 	// This is a function overload, not a template specialization. According to
 	// the partial ordering rules, it should be selected by the compiler
 	// 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();
 	out.reset();
 	if (!ptrval.val) { 
 	if (!ptrval.val) { 
-		return;
+		return false;
 	}
 	}
 
 
 	// find the file block the pointer is pointing to
 	// 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();
 	const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
 	db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
 	db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
 
 
+	bool res = false;
 	// allocate raw storage for the array
 	// allocate raw storage for the array
 	out.resize(num);
 	out.resize(num);
 	for (size_t i = 0; i< num; ++i) {
 	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);
 		Convert(val,db);
 
 
 		// and resolve the pointees
 		// and resolve the pointees
-		ResolvePointer(out[i],val,db,f); 
+		res = ResolvePointer(out[i],val,db,f) && res; 
 	}
 	}
 
 
 	db.reader->SetCurrentPos(pold);
 	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 Pointer & ptrval, 
 	const FileDatabase& db, 
 	const FileDatabase& db, 
-	const Field& /*f*/
+	const Field&,
+	bool
 ) const 
 ) const 
 {
 {
 	// Special case when the data type needs to be determined at runtime.
 	// 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();
 	out.reset();
 	if (!ptrval.val) { 
 	if (!ptrval.val) { 
-		return;
+		return false;
 	}
 	}
 
 
 	// find the file block the pointer is pointing to
 	// 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
 	// try to retrieve the object from the cache
 	db.cache(out).get(s,out,ptrval); 
 	db.cache(out).get(s,out,ptrval); 
 	if (out) {
 	if (out) {
-		return;
+		return true;
 	}
 	}
 
 
 	// seek to this location, but save the previous stream pointer.
 	// 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(),
 		DefaultLogger::get()->warn((Formatter::format(),
 			"Failed to find a converter for the `",s.name,"` structure"
 			"Failed to find a converter for the `",s.name,"` structure"
 			));
 			));
-		return;
+		return false;
 	}
 	}
 
 
 	// allocate the object hull
 	// allocate the object hull
@@ -459,11 +485,11 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
 	// to perform additional type checking.
 	// to perform additional type checking.
 	out->dna_type = s.name.c_str();
 	out->dna_type = s.name.c_str();
 
 
-	
 
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 	++db.stats().pointers_resolved;
 	++db.stats().pointers_resolved;
 #endif
 #endif
+	return false;
 }
 }
 
 
 //--------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------

+ 64 - 8
code/BlenderLoader.cpp

@@ -446,9 +446,43 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
 	else {
 	else {
 		name = aiString( img->name );
 		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());
 	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());
 	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;
 using namespace Assimp::Blender;
 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
 #endif

+ 35 - 3
code/BlenderScene.h

@@ -598,6 +598,18 @@ struct Tex : ElemBase {
 		,Type_VOXELDATA		= 15
 		,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;
 	ID id FAIL;
 	// AnimData *adt; 
 	// AnimData *adt; 
 
 
@@ -618,7 +630,8 @@ struct Tex : ElemBase {
 	//short noisedepth, noisetype;
 	//short noisedepth, noisetype;
 	//short noisebasis, noisebasis2;
 	//short noisebasis, noisebasis2;
 
 
-	//short imaflag, flag;
+	//short flag;
+	ImageFlags imaflag;
 	Type type FAIL;
 	Type type FAIL;
 	//short stype;
 	//short stype;
 
 
@@ -685,7 +698,25 @@ struct MTex : ElemBase {
 		,BlendType_BLEND_COLOR		= 13
 		,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;
 	BlendType blendtype;
 	boost::shared_ptr<Object> object;
 	boost::shared_ptr<Object> object;
@@ -705,7 +736,8 @@ struct MTex : ElemBase {
 
 
 	//float colfac, varfac;
 	//float colfac, varfac;
 
 
-	//float norfac, dispfac, warpfac;
+	float norfac;
+	//float dispfac, warpfac;
 	float colspecfac, mirrfac, alphafac;
 	float colspecfac, mirrfac, alphafac;
 	float difffac, specfac, emitfac, hardfac;
 	float difffac, specfac, emitfac, hardfac;
 	//float raymirrfac, translfac, ambfac;
 	//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 Assimp	{
 	namespace Blender {
 	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;
     aiString name;
     if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS )
     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 = '_';
         *it = '_';
+	  }
+	}
 
 
 	aiShadingMode shading;
 	aiShadingMode shading;
 	materials[a].shading_model = "phong";
 	materials[a].shading_model = "phong";

+ 43 - 6
code/Exporter.cpp

@@ -88,7 +88,7 @@ Exporter::ExportFormatEntry gExporters[] =
 
 
 #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
 #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
 	Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj, 
 	Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj, 
-		aiProcess_GenNormals /*| aiProcess_PreTransformVertices */),
+		aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */),
 #endif
 #endif
 
 
 #ifndef ASSIMP_BUILD_NO_STL_EXPORTER
 #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 )
 aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing )
 {
 {
 	ASSIMP_BEGIN_EXCEPTION_REGION();
 	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 = "";
 	pimpl->mError = "";
 	for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
 	for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
 		const Exporter::ExportFormatEntry& exp = pimpl->mExporters[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;
 				const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
 
 
 				// Erase all pp steps that were already applied to this scene
 				// 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)
 					? (priv->mPPStepsApplied & ~nonIdempotentSteps)
 					: 0u);
 					: 0u);
 
 
 				// If no extra postprocessing was specified, and we obtained this scene from an
 				// If no extra postprocessing was specified, and we obtained this scene from an
 				// Assimp importer, apply the reverse steps automatically.
 				// 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,
 				// 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.
 				// we need to run the MakeVerboseFormat step first.
 				bool must_join_again = false;
 				bool must_join_again = false;
-				if (scenecopy->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
+				if (!is_verbose_format) {
 					
 					
 					bool verbosify = false;
 					bool verbosify = false;
 					for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
 					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();
 	const Scope& shead = *ehead->Compound();
 	fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
 	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) {
 		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 {
 		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"
 #include "AssimpPCH.h"
 
 
-#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
+#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
 
 
 #include "IRRMeshLoader.h"
 #include "IRRMeshLoader.h"
 #include "ParsingUtils.h"
 #include "ParsingUtils.h"
@@ -512,4 +512,4 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
 	AI_DEBUG_INVALIDATE_PTR(reader);
 	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"
 #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 "IRRShared.h"
 #include "ParsingUtils.h"
 #include "ParsingUtils.h"
@@ -497,4 +498,4 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
 	return mat;
 	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;
 		uint8_t* const next = mFileBuffer+head->length;
 		unsigned int iUnnamed = 0;
 		unsigned int iUnnamed = 0;
 
 
+		if(!head->length) {
+			mFileBuffer = next;
+			continue;
+		}
+
 		switch (head->type)
 		switch (head->type)
 		{
 		{
 			// new layer
 			// 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 older LWOB format does not use indirect references to clips.
 		// The file name of a texture is directly specified in the tex chunk.
 		// The file name of a texture is directly specified in the tex chunk.
 		if (mIsLWO2)	{
 		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;
 			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");
 				DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
 				temp = 0;
 				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
 				// have clips at all ... check whether that's true or whether
 				// it's a bug in the loader.
 				// it's a bug in the loader.
 
 
@@ -188,16 +190,16 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
 				//continue;
 				//continue;
 			}
 			}
 			else {
 			else {
-				if (Clip::UNSUPPORTED == (*clip).type)	{
+				if (Clip::UNSUPPORTED == (*candidate).type)	{
 					DefaultLogger::get()->error("LWO2: Clip type is not supported");
 					DefaultLogger::get()->error("LWO2: Clip type is not supported");
 					continue;
 					continue;
 				}
 				}
-				AdjustTexturePath((*clip).path);
-				s.Set((*clip).path);
+				AdjustTexturePath((*candidate).path);
+				s.Set((*candidate).path);
 
 
 				// Additional image settings
 				// Additional image settings
 				int flags = 0;
 				int flags = 0;
-				if ((*clip).negate) {
+				if ((*candidate).negate) {
 					flags |= aiTextureFlags_Invert;
 					flags |= aiTextureFlags_Invert;
 				}
 				}
 				pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur));
 				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"));
 		boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
 		if(outfile == NULL) {
 		if(outfile == NULL) {
 			throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
 			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);
 		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"));
 		boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
 		if(outfile == NULL) {
 		if(outfile == NULL) {
 			throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName()));
 			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);
 		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);
 	AddNode(pScene->mRootNode,mBase);
 
 
 	// write vertex positions
 	// write vertex positions
+	vpMap.getVectors(vp);
 	mOutput << "# " << vp.size() << " vertex positions" << endl;
 	mOutput << "# " << vp.size() << " vertex positions" << endl;
 	BOOST_FOREACH(const aiVector3D& v, vp) {
 	BOOST_FOREACH(const aiVector3D& v, vp) {
 		mOutput << "v  " << v.x << " " << v.y << " " << v.z << endl;
 		mOutput << "v  " << v.x << " " << v.y << " " << v.z << endl;
@@ -206,6 +207,7 @@ void ObjExporter :: WriteGeometryFile()
 	mOutput << endl;
 	mOutput << endl;
 
 
 	// write uv coordinates
 	// write uv coordinates
+	vtMap.getVectors(vt);
 	mOutput << "# " << vt.size() << " UV coordinates" << endl;
 	mOutput << "# " << vt.size() << " UV coordinates" << endl;
 	BOOST_FOREACH(const aiVector3D& v, vt) {
 	BOOST_FOREACH(const aiVector3D& v, vt) {
 		mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
 		mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
@@ -213,6 +215,7 @@ void ObjExporter :: WriteGeometryFile()
 	mOutput << endl;
 	mOutput << endl;
 
 
 	// write vertex normals
 	// write vertex normals
+	vnMap.getVectors(vn);
 	mOutput << "# " << vn.size() << " vertex normals" << endl;
 	mOutput << "# " << vn.size() << " vertex normals" << endl;
 	BOOST_FOREACH(const aiVector3D& v, vn) {
 	BOOST_FOREACH(const aiVector3D& v, vn) {
 		mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
 		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)
 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.matname = GetMaterialName(m->mMaterialIndex);
 
 
 	mesh.faces.resize(m->mNumFaces);
 	mesh.faces.resize(m->mNumFaces);
+
 	for(unsigned int i = 0; i < m->mNumFaces; ++i) {
 	for(unsigned int i = 0; i < m->mNumFaces; ++i) {
 		const aiFace& f = m->mFaces[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) {
 		for(unsigned int a = 0; a < f.mNumIndices; ++a) {
 			const unsigned int idx = f.mIndices[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) {
 			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]) {
 			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;
 	const aiScene* const pScene;
 
 
 	std::vector<aiVector3D> vp, vn, vt;
 	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;
 	std::vector<MeshInstance> meshes;
 
 
 	// this endl() doesn't flush() the stream
 	// 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++)
 	for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
 	{
 	{
 		ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
 		ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
+	
 		if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
 		if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
 			pMesh->mNumFaces += inp->m_pVertices->size() - 1;
 			pMesh->mNumFaces += inp->m_pVertices->size() - 1;
+			pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
 		}
 		}
 		else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
 		else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
 			pMesh->mNumFaces += inp->m_pVertices->size();
 			pMesh->mNumFaces += inp->m_pVertices->size();
+			pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
 		}
 		}
 		else {
 		else {
 			++pMesh->mNumFaces;
 			++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 ];
 			pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
 			
 			
 			// Copy all normals 
 			// 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 );
 				const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
 				if ( normal >= pModel->m_Normals.size() )
 				if ( normal >= pModel->m_Normals.size() )
@@ -394,21 +403,16 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
 			}
 			}
 			
 			
 			// Copy all texture coordinates
 			// 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 );
 			ai_assert( pMesh->mNumVertices > newIndex );
@@ -587,15 +591,12 @@ void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
 
 
 	// Assign parent to child
 	// Assign parent to child
 	pChild->mParent = pParent;
 	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 
 	// If already children was assigned to the parent node, store them in a 
 	std::vector<aiNode*> temp;
 	std::vector<aiNode*> temp;
 	if (pParent->mChildren != NULL)
 	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++)
 		for (size_t index = 0; index < pParent->mNumChildren; index++)
 		{
 		{
 			temp.push_back(pParent->mChildren [ index ] );
 			temp.push_back(pParent->mChildren [ index ] );

+ 3 - 6
code/ObjFileImporter.h

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

+ 52 - 7
code/ObjFileParser.cpp

@@ -112,7 +112,7 @@ void ObjFileParser::parseFile()
 		case 'v': // Parse a vertex texture coordinate
 		case 'v': // Parse a vertex texture coordinate
 			{
 			{
 				++m_DataIt;
 				++m_DataIt;
-				if (*m_DataIt == ' ')
+				if (*m_DataIt == ' ' || *m_DataIt == '\t')
 				{
 				{
 					// Read in vertex definition
 					// Read in vertex definition
 					getVector3(m_pModel->m_Vertices);
 					getVector3(m_pModel->m_Vertices);
@@ -200,6 +200,8 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
 			break;
 			break;
 		++m_DataIt;
 		++m_DataIt;
 	}
 	}
+
+	ai_assert(index < length);
 	pBuffer[index] = '\0';
 	pBuffer[index] = '\0';
 }
 }
 
 
@@ -207,16 +209,30 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
 // Copy the next line into a temporary buffer
 // Copy the next line into a temporary buffer
 void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
 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;
 			break;
+		}
 
 
-		pBuffer[ index ] = *m_DataIt;
-		++index;
-		++m_DataIt;
+		continuation = false;
+		pBuffer[ index++ ] = c;
 	}
 	}
+	ai_assert(index < length);
 	pBuffer[ index ] = '\0';
 	pBuffer[ index ] = '\0';
 }
 }
 
 
@@ -274,6 +290,10 @@ void ObjFileParser::getFace(aiPrimitiveType type)
 	std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
 	std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
 	bool hasNormal = false;
 	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 vt = (!m_pModel->m_TextureCoord.empty());
 	const bool vn = (!m_pModel->m_Normals.empty());
 	const bool vn = (!m_pModel->m_Normals.empty());
 	int iStep = 0, iPos = 0;
 	int iStep = 0, iPos = 0;
@@ -307,7 +327,11 @@ void ObjFileParser::getFace(aiPrimitiveType type)
 		{
 		{
 			//OBJ USES 1 Base ARRAYS!!!!
 			//OBJ USES 1 Base ARRAYS!!!!
 			const int iVal = atoi( pPtr );
 			const int iVal = atoi( pPtr );
+
+			// increment iStep position based off of the sign and # of digits
 			int tmp = iVal;
 			int tmp = iVal;
+			if (iVal < 0)
+			    ++iStep;
 			while ( ( tmp = tmp / 10 )!=0 )
 			while ( ( tmp = tmp / 10 )!=0 )
 				++iStep;
 				++iStep;
 
 
@@ -332,6 +356,27 @@ void ObjFileParser::getFace(aiPrimitiveType type)
 					reportErrorTokenInFace();
 					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;
 		pPtr += iStep;
 	}
 	}

+ 2 - 2
code/PlyExporter.cpp

@@ -103,7 +103,7 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
 
 
 	mOutput << "ply" << endl;
 	mOutput << "ply" << endl;
 	mOutput << "format ascii 1.0" << 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() << '.' 
 		<< aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' 
 		<< aiGetVersionRevision() << ")" << endl;
 		<< aiGetVersionRevision() << ")" << endl;
 
 
@@ -159,7 +159,7 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
 	}
 	}
 
 
 	mOutput << "element face " << faces << endl;
 	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;
 	mOutput << "end_header" << endl;
 
 
 	for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
 	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))
 	if (IsBinarySTL(buffer, fileSize))
 		return false;
 		return false;
 
 
-	if (fileSize < 5)
+	const char* bufferEnd = buffer + fileSize;
+
+	if (!SkipSpaces(&buffer))
+		return false;
+
+	if (buffer + 5 >= bufferEnd)
 		return false;
 		return false;
 
 
 	return strncmp(buffer, "solid", 5) == 0;
 	return strncmp(buffer, "solid", 5) == 0;
@@ -209,7 +214,11 @@ void STLImporter::LoadASCIIFile()
 {
 {
 	aiMesh* pMesh = pScene->mMeshes[0];
 	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);
 	SkipSpaces(&sz);
 	const char* szMe = sz;
 	const char* szMe = sz;
 	while (!::IsSpaceOrNewLine(*sz)) {
 	while (!::IsSpaceOrNewLine(*sz)) {

+ 8 - 0
code/ScenePrivate.h

@@ -53,6 +53,7 @@ struct ScenePrivateData {
 	ScenePrivateData()
 	ScenePrivateData()
 		: mOrigImporter()
 		: mOrigImporter()
 		, mPPStepsApplied()
 		, mPPStepsApplied()
+		, mIsCopy()
 	{}
 	{}
 
 
 	// Importer that originally loaded the scene though the C-API
 	// 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.
 	// List of postprocessing steps already applied to the scene.
 	unsigned int mPPStepsApplied;
 	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
 // 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 
 	 *   redundant as exporters would apply them anyhow. A good example 
 	 *   is triangulation - whilst you can enforce it by specifying
 	 *   is triangulation - whilst you can enforce it by specifying
 	 *   the #aiProcess_Triangulate flag, most export formats support only
 	 *   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. 
 	 * @return AI_SUCCESS if everything was fine. 
 	 * @note Use aiCopyScene() to get a modifiable copy of a previously
 	 * @note Use aiCopyScene() to get a modifiable copy of a previously
 	 *   imported scene.*/
 	 *   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
 *   is triangulation - whilst you can enforce it by specifying
 *   the #aiProcess_Triangulate flag, most export formats support only
 *   the #aiProcess_Triangulate flag, most export formats support only
 *   triangulate data so they would run the step anyway.
 *   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
 * @return a status code indicating the result of the export
 * @note Use aiCopyScene() to get a modifiable copy of a previously
 * @note Use aiCopyScene() to get a modifiable copy of a previously
 *   imported scene.
 *   imported scene.

+ 61 - 0
include/assimp/material.h

@@ -691,6 +691,12 @@ public:
     aiReturn Get(const char* pKey,unsigned int type,
     aiReturn Get(const char* pKey,unsigned int type,
 		unsigned int idx, Type* pOut, unsigned int* pMax) const;
 		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 
     /** @brief Retrieve a Type value with a specific key 
      *  from the material
      *  from the material
@@ -705,6 +711,25 @@ public:
 	aiReturn Get(const char* pKey,unsigned int type,
 	aiReturn Get(const char* pKey,unsigned int type,
 		unsigned int idx,Type& pOut) const;
 		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.
 	/** Get the number of textures for a particular texture type.
 	 *  @param type Texture type to check for
 	 *  @param type Texture type to check for
@@ -797,6 +822,42 @@ public:
 		unsigned int type  = 0,
 		unsigned int type  = 0,
 		unsigned int index = 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.
 	/** @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));
 		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) {
 		if (pMax) {
 			*pMax = iNum;
 			*pMax = iNum;
 		}
 		}
@@ -115,51 +115,45 @@ inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
 			return AI_FAILURE;
 			return AI_FAILURE;
 		}
 		}
 
 
-		memcpy(&pOut,prop->mData,sizeof(Type));
+		::memcpy(&pOut,prop->mData,sizeof(Type));
 	}
 	}
 	return ret;
 	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 idx,float* pOut,
 	unsigned int* pMax) const
 	unsigned int* pMax) const
 {
 {
 	return ::aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);
 	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 idx,int* pOut,
 	unsigned int* pMax) const
 	unsigned int* pMax) const
 {
 {
 	return ::aiGetMaterialIntegerArray(this,pKey,type,idx,pOut,pMax);
 	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
 	unsigned int idx,float& pOut) const
 {
 {
 	return aiGetMaterialFloat(this,pKey,type,idx,&pOut);
 	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
 	unsigned int idx,int& pOut) const
 {
 {
 	return aiGetMaterialInteger(this,pKey,type,idx,&pOut);
 	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
 	unsigned int idx,aiColor4D& pOut) const
 {
 {
 	return aiGetMaterialColor(this,pKey,type,idx,&pOut);
 	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
 	unsigned int idx,aiColor3D& pOut) const
 {
 {
 	aiColor4D c;
 	aiColor4D c;
@@ -168,8 +162,7 @@ inline aiReturn aiMaterial::Get<aiColor3D>(const char* pKey,unsigned int type,
 	return ret;
 	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
 	unsigned int idx,aiString& pOut) const
 {
 {
 	return aiGetMaterialString(this,pKey,type,idx,&pOut);
 	return aiGetMaterialString(this,pKey,type,idx,&pOut);
@@ -189,9 +182,88 @@ aiReturn aiMaterial::AddProperty (const TYPE* pInput,
 		pKey,type,index,aiPTI_Buffer);
 		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<>
 template<>
-inline aiReturn aiMaterial::AddProperty<float> (const float* pInput,
+inline aiReturn aiMaterial::AddProperty<float>(const float* pInput,
 	const unsigned int pNumValues,
 	const unsigned int pNumValues,
 	const char* pKey,
 	const char* pKey,
 	unsigned int type,
 	unsigned int type,
@@ -204,7 +276,7 @@ inline aiReturn aiMaterial::AddProperty<float> (const float* pInput,
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 template<>
 template<>
-inline aiReturn aiMaterial::AddProperty<aiUVTransform> (const aiUVTransform* pInput,
+inline aiReturn aiMaterial::AddProperty<aiUVTransform>(const aiUVTransform* pInput,
 	const unsigned int pNumValues,
 	const unsigned int pNumValues,
 	const char* pKey,
 	const char* pKey,
 	unsigned int type,
 	unsigned int type,
@@ -217,7 +289,7 @@ inline aiReturn aiMaterial::AddProperty<aiUVTransform> (const aiUVTransform* pIn
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 template<>
 template<>
-inline aiReturn aiMaterial::AddProperty<aiColor4D> (const aiColor4D* pInput,
+inline aiReturn aiMaterial::AddProperty<aiColor4D>(const aiColor4D* pInput,
 	const unsigned int pNumValues,
 	const unsigned int pNumValues,
 	const char* pKey,
 	const char* pKey,
 	unsigned int type,
 	unsigned int type,
@@ -230,7 +302,7 @@ inline aiReturn aiMaterial::AddProperty<aiColor4D> (const aiColor4D* pInput,
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 template<>
 template<>
-inline aiReturn aiMaterial::AddProperty<aiColor3D> (const aiColor3D* pInput,
+inline aiReturn aiMaterial::AddProperty<aiColor3D>(const aiColor3D* pInput,
 	const unsigned int pNumValues,
 	const unsigned int pNumValues,
 	const char* pKey,
 	const char* pKey,
 	unsigned int type,
 	unsigned int type,
@@ -243,7 +315,7 @@ inline aiReturn aiMaterial::AddProperty<aiColor3D> (const aiColor3D* pInput,
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 template<>
 template<>
-inline aiReturn aiMaterial::AddProperty<aiVector3D> (const aiVector3D* pInput,
+inline aiReturn aiMaterial::AddProperty<aiVector3D>(const aiVector3D* pInput,
 	const unsigned int pNumValues,
 	const unsigned int pNumValues,
 	const char* pKey,
 	const char* pKey,
 	unsigned int type,
 	unsigned int type,
@@ -256,7 +328,7 @@ inline aiReturn aiMaterial::AddProperty<aiVector3D> (const aiVector3D* pInput,
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 template<>
 template<>
-inline aiReturn aiMaterial::AddProperty<int> (const int* pInput,
+inline aiReturn aiMaterial::AddProperty<int>(const int* pInput,
 	const unsigned int pNumValues,
 	const unsigned int pNumValues,
 	const char* pKey,
 	const char* pKey,
 	unsigned int type,
 	unsigned int type,

+ 4 - 4
samples/SimpleAssimpViewX/ModelLoaderHelperClasses.h

@@ -8,10 +8,10 @@
 
 
 #import <Cocoa/Cocoa.h>
 #import <Cocoa/Cocoa.h>
 #import <OpenGL/OpenGL.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:
 /* workflow:
 
 

+ 7 - 6
samples/SimpleAssimpViewX/MyDocument.h

@@ -10,9 +10,10 @@
 #import "ModelLoaderHelperClasses.h"
 #import "ModelLoaderHelperClasses.h"
 
 
 // assimp include files. These three are usually needed.
 // 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 <Cocoa/Cocoa.h>
 #import <OpenGL/OpenGL.h>
 #import <OpenGL/OpenGL.h>
@@ -29,7 +30,7 @@
     
     
     // Assimp Stuff
     // Assimp Stuff
     aiScene* _scene;
     aiScene* _scene;
-    struct aiVector3D scene_min, scene_max, scene_center;
+    aiVector3D scene_min, scene_max, scene_center;
     double normalizedScale;    
     double normalizedScale;    
     
     
     // Our array of textures.
     // Our array of textures.
@@ -53,7 +54,7 @@
 - (void) deleteGLResourcesInContext:(CGLContextObj)cgl_ctx;
 - (void) deleteGLResourcesInContext:(CGLContextObj)cgl_ctx;
 
 
 - (void) loadTexturesInContext:(CGLContextObj)cgl_ctx withModelPath:(NSString*) modelPath;
 - (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
 @end

+ 14 - 10
samples/SimpleAssimpViewX/MyDocument.mm

@@ -6,7 +6,8 @@
 //  Copyright __MyCompanyName__ 2010 . All rights reserved.
 //  Copyright __MyCompanyName__ 2010 . All rights reserved.
 //
 //
 
 
-#import "aiConfig.h"
+#import "cimport.h"
+#import "config.h"
 #import "MyDocument.h"
 #import "MyDocument.h"
 #import <OpenGL/CGLMacro.h>
 #import <OpenGL/CGLMacro.h>
 
 
@@ -16,7 +17,7 @@
 #define aisgl_min(x,y) (x<y?x:y)
 #define aisgl_min(x,y) (x<y?x:y)
 #define aisgl_max(x,y) (y>x?y:x)
 #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[0] = c->r;
 	f[1] = c->g;
 	f[1] = c->g;
@@ -160,7 +161,8 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS
                 // Load our new path.
                 // Load our new path.
                 
                 
                 // only ever give us triangles.
                 // 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;
                 NSUInteger aiPostProccesFlags;
                 
                 
@@ -181,7 +183,9 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS
                 }
                 }
                 
                 
                 // aiProcess_FlipUVs is needed for VAO / VBOs,  not sure why.
                 // 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)
                 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);
 	aiIdentityMatrix4(&trafo);
     
     
 	min->x = min->y = min->z =  1e10f;
 	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];
     [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;
 	unsigned int n = 0, t;
     
     
 	prev = *trafo;
 	prev = *trafo;
@@ -776,10 +780,10 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS
     
     
 	for (; n < nd->mNumMeshes; ++n)
 	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)
 		for (t = 0; t < mesh->mNumVertices; ++t)
         {
         {
-        	struct aiVector3D tmp = mesh->mVertices[t];
+        	aiVector3D tmp = mesh->mVertices[t];
 			aiTransformVecByMatrix4(&tmp,trafo);
 			aiTransformVecByMatrix4(&tmp,trafo);
             
             
 			min->x = aisgl_min(min->x,tmp.x);
 			min->x = aisgl_min(min->x,tmp.x);

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

@@ -9,11 +9,6 @@
 /* Begin PBXBuildFile section */
 /* Begin PBXBuildFile section */
 		1B0E9A901279ED43003108E7 /* libassimp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B0E9A8F1279ED43003108E7 /* libassimp.a */; };
 		1B0E9A901279ED43003108E7 /* libassimp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B0E9A8F1279ED43003108E7 /* libassimp.a */; };
 		1B0E9A951279EDCD003108E7 /* ModelLoaderHelperClasses.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1B0E9A941279EDCD003108E7 /* ModelLoaderHelperClasses.mm */; };
 		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 */; };
 		1B0E9B1A1279F107003108E7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B0E9B191279F107003108E7 /* libz.dylib */; };
 		1BDF446B127772AF00D3E723 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1BDF446A127772AF00D3E723 /* OpenGL.framework */; };
 		1BDF446B127772AF00D3E723 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1BDF446A127772AF00D3E723 /* OpenGL.framework */; };
 		1BDF446F127772AF00D3E723 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1BDF446E127772AF00D3E723 /* Quartz.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 */; };
 		8D15AC2F0486D014006FF6A4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165FFE840EACC02AAC07 /* InfoPlist.strings */; };
 		8D15AC310486D014006FF6A4 /* MyDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2A37F4ACFDCFA73011CA2CEA /* MyDocument.mm */; settings = {ATTRIBUTES = (); }; };
 		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 = (); }; };
 		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 */
 /* End PBXBuildFile section */
 
 
 /* Begin PBXFileReference section */
 /* Begin PBXFileReference section */
@@ -33,40 +35,6 @@
 		1B0E9A8F1279ED43003108E7 /* libassimp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libassimp.a; sourceTree = "<group>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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; };
 		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>"; };
 		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>"; };
 		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; };
 		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 */
 /* End PBXFileReference section */
 
 
 /* Begin PBXFrameworksBuildPhase section */
 /* Begin PBXFrameworksBuildPhase section */
@@ -134,40 +142,46 @@
 		1B0E9AD21279EFCC003108E7 /* include */ = {
 		1B0E9AD21279EFCC003108E7 /* include */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			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 */,
 				1B0E9AFC1279F006003108E7 /* Compiler */,
 			);
 			);
 			path = include;
 			path = include;
@@ -295,11 +309,13 @@
 				8D15AC2F0486D014006FF6A4 /* InfoPlist.strings in Resources */,
 				8D15AC2F0486D014006FF6A4 /* InfoPlist.strings in Resources */,
 				2F7446AB0DB6BCF400F9684A /* MainMenu.xib in Resources */,
 				2F7446AB0DB6BCF400F9684A /* MainMenu.xib in Resources */,
 				2F7446AC0DB6BCF400F9684A /* MyDocument.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;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -413,7 +429,7 @@
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				PREBINDING = NO;
 				PREBINDING = NO;
-				SDKROOT = macosx10.6;
+				SDKROOT = macosx;
 			};
 			};
 			name = Debug;
 			name = Debug;
 		};
 		};
@@ -425,7 +441,7 @@
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				PREBINDING = NO;
 				PREBINDING = NO;
-				SDKROOT = macosx10.6;
+				SDKROOT = macosx;
 			};
 			};
 			name = Release;
 			name = Release;
 		};
 		};

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

@@ -36,9 +36,8 @@
 #include "assimp/LogStream.hpp"
 #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
 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)
 int LoadGLTextures(const aiScene* scene)
 {
 {
@@ -220,6 +224,7 @@ int LoadGLTextures(const aiScene* scene)
 	/* get iterator */
 	/* get iterator */
 	std::map<std::string, GLuint*>::iterator itr = textureIdMap.begin();
 	std::map<std::string, GLuint*>::iterator itr = textureIdMap.begin();
 
 
+	std::string basepath = getBasePath(modelpath);
 	for (int i=0; i<numTextures; i++)
 	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);
 	return DefWindowProc(hWnd, uMsg, wParam, lParam);
 }
 }
 
 
-
 int WINAPI WinMain( HINSTANCE hInstance, // Instance
 int WINAPI WinMain( HINSTANCE hInstance, // Instance
 				   HINSTANCE hPrevInstance,      // Previous Instance
 				   HINSTANCE hPrevInstance,      // Previous Instance
 				   LPSTR lpCmdLine,              // Command Line Parameters
 				   LPSTR lpCmdLine,              // Command Line Parameters
 				   int nShowCmd )                // Window Show State
 				   int nShowCmd )                // Window Show State
 {
 {
-	MSG msg;			// Windows Message Structure
-	BOOL done=FALSE;	// Bool Variable To Exit Loop
+	MSG msg;
+	BOOL done=FALSE;
 
 
 	createAILogger();
 	createAILogger();
 	logInfo("App fired!");
 	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 ====================");
 	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)
 	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))
 	if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen))
 	{
 	{
 		return 0;
 		return 0;
 	}
 	}
 
 
-
-
-
 	while(!done)	// Game Loop
 	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
 			else
 			{
 			{
-				TranslateMessage(&msg);			// Translate The Message
-				DispatchMessage(&msg);			// Dispatch The Message
+				TranslateMessage(&msg);
+				DispatchMessage(&msg);
 			}
 			}
 		}
 		}
 		else
 		else
@@ -852,26 +857,25 @@ int WINAPI WinMain( HINSTANCE hInstance, // Instance
 			// Draw The Scene. Watch For ESC Key And Quit Messaged From DrawGLScene()
 			// Draw The Scene. Watch For ESC Key And Quit Messaged From DrawGLScene()
 			if (active)
 			if (active)
 			{
 			{
-				if (keys[VK_ESCAPE])	// Was ESC pressed?
+				if (keys[VK_ESCAPE])
 				{
 				{
-					done=TRUE;			// ESC signalled A quit
+					done=TRUE;
 				}
 				}
 				else
 				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))
 				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 ***
 	// *** cleanup ***
 
 
-	// clear map
 	textureIdMap.clear(); //no need to delete pointers in it manually here. (Pointers point to textureIds deleted in next step)
 	textureIdMap.clear(); //no need to delete pointers in it manually here. (Pointers point to textureIds deleted in next step)
 
 
-	// clear texture ids
 	if (textureIds)
 	if (textureIds)
 	{
 	{
 		delete[] textureIds;
 		delete[] textureIds;
@@ -891,8 +893,7 @@ int WINAPI WinMain( HINSTANCE hInstance, // Instance
 
 
 	// *** cleanup end ***
 	// *** cleanup end ***
 
 
-	// Shutdown
 	destroyAILogger();
 	destroyAILogger();
 	KillGLWindow();
 	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)
 # Open Asset Import Library (ASSIMP)
 # ---------------------------------------------------------------------------
 # ---------------------------------------------------------------------------
 #
 #
-# Copyright (c) 2006-2010, ASSIMP Development Team
+# Copyright (c) 2006-2013, ASSIMP Development Team
 #
 #
 # All rights reserved.
 # All rights reserved.
 #
 #
@@ -55,6 +55,55 @@ outputfile_src = os.path.join("..","..","code","BlenderScene.cpp")
 template_gen = "BlenderSceneGen.h.template"
 template_gen = "BlenderSceneGen.h.template"
 template_src = "BlenderScene.cpp.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 =  """
 Structure_Convert_decl =  """
 template <> void Structure :: Convert<{a}> (
 template <> void Structure :: Convert<{a}> (
@@ -201,7 +250,11 @@ def main():
     # -----------------------------------------------------------------------
     # -----------------------------------------------------------------------
     # Structure::Convert<T> definitions for all supported structures
     # Structure::Convert<T> definitions for all supported structures
     for k,v in hits.items():
     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:
         for type, name, policy in v:
             splits = name.split("[",1)
             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})
 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})
 TARGET_LINK_LIBRARIES( assimp_cmd assimp ${ZLIB_LIBRARIES})
 SET_TARGET_PROPERTIES( assimp_cmd PROPERTIES
 SET_TARGET_PROPERTIES( assimp_cmd PROPERTIES
 	OUTPUT_NAME assimp
 	OUTPUT_NAME assimp

+ 16 - 13
tools/assimp_view/CMakeLists.txt

@@ -1,18 +1,16 @@
 FIND_PACKAGE(DirectX REQUIRED)
 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}/include
 	${Assimp_SOURCE_DIR}/code
 	${Assimp_SOURCE_DIR}/code
 	${DirectX_INCLUDE_DIR}
 	${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
 	AnimEvaluator.cpp
 	Background.cpp
 	Background.cpp
 	Display.cpp
 	Display.cpp
@@ -45,13 +43,18 @@ add_executable(  assimp_viewer WIN32
 
 
 SET_PROPERTY(TARGET assimp_viewer PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
 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
 INSTALL( TARGETS assimp_viewer
 	DESTINATION "${ASSIMP_BIN_INSTALL_DIR}" COMPONENT assimp-dev
 	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, ); }; };
 		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 */; };
 		B919758B163AEA54009C397B /* OgreImporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C36154328B600E63FFE /* OgreImporter.hpp */; };
 		B919758C163AEA54009C397B /* OgreXmlHelper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C3A154328B600E63FFE /* OgreXmlHelper.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 */; };
 		B9197596163AEA54009C397B /* PlyExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F3115436269000682F3 /* PlyExporter.h */; };
 		B919759C163AEA54009C397B /* crc32.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704B154366AB004D91DD /* crc32.h */; };
 		B919759C163AEA54009C397B /* crc32.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704B154366AB004D91DD /* crc32.h */; };
 		B919759D163AEA54009C397B /* deflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704D154366AB004D91DD /* deflate.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 */; };
 		B919761A163AEA54009C397B /* OgreMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C37154328B600E63FFE /* OgreMaterial.cpp */; };
 		B919761B163AEA54009C397B /* OgreMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C38154328B600E63FFE /* OgreMesh.cpp */; };
 		B919761B163AEA54009C397B /* OgreMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C38154328B600E63FFE /* OgreMesh.cpp */; };
 		B919761C163AEA54009C397B /* OgreSkeleton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C39154328B600E63FFE /* OgreSkeleton.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 */; };
 		B9197620163AEA54009C397B /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F3015436269000682F3 /* PlyExporter.cpp */; };
 		B9197625163AEA54009C397B /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607047154366AB004D91DD /* adler32.c */; };
 		B9197625163AEA54009C397B /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607047154366AB004D91DD /* adler32.c */; };
 		B9197626163AEA54009C397B /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607049154366AB004D91DD /* compress.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 */; };
 		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 */; };
 		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 */; };
 		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 */; };
 		F99A9F3215436269000682F3 /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F3015436269000682F3 /* PlyExporter.cpp */; };
 		F99A9F3315436269000682F3 /* PlyExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F3115436269000682F3 /* PlyExporter.h */; };
 		F99A9F3315436269000682F3 /* PlyExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F3115436269000682F3 /* PlyExporter.h */; };
 		F99A9F3415436269000682F3 /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F3015436269000682F3 /* PlyExporter.cpp */; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		F9BA8B751543268400E63FFE /* anim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = anim.h; sourceTree = "<group>"; };
@@ -3173,7 +3161,6 @@
 				F90BAFD40F5DD8F200124155 /* IRR */,
 				F90BAFD40F5DD8F200124155 /* IRR */,
 				3AB8A3A80E50D5F400606590 /* LWO */,
 				3AB8A3A80E50D5F400606590 /* LWO */,
 				7411B15811416D6600BCD793 /* LWS */,
 				7411B15811416D6600BCD793 /* LWS */,
-				F99A9F21154361F8000682F3 /* M3 */,
 				3AF45B870E4B74DA00207D74 /* MD2 */,
 				3AF45B870E4B74DA00207D74 /* MD2 */,
 				3AF45B880E4B751000207D74 /* MD3 */,
 				3AF45B880E4B751000207D74 /* MD3 */,
 				3AF45B8A0E4B755E00207D74 /* MD5 */,
 				3AF45B8A0E4B755E00207D74 /* MD5 */,
@@ -3309,15 +3296,6 @@
 			name = IFC;
 			name = IFC;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
-		F99A9F21154361F8000682F3 /* M3 */ = {
-			isa = PBXGroup;
-			children = (
-				F99A9F2615436207000682F3 /* M3Importer.cpp */,
-				F99A9F2715436207000682F3 /* M3Importer.h */,
-			);
-			name = M3;
-			sourceTree = "<group>";
-		};
 		F99A9F5315436318000682F3 /* STEP */ = {
 		F99A9F5315436318000682F3 /* STEP */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
@@ -3499,7 +3477,6 @@
 				F9BA8C041543268400E63FFE /* version.h in Headers */,
 				F9BA8C041543268400E63FFE /* version.h in Headers */,
 				F9BA8C48154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C48154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C4C154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
 				F9BA8C4C154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
-				F99A9F2D15436207000682F3 /* M3Importer.h in Headers */,
 				F99A9F3715436269000682F3 /* PlyExporter.h in Headers */,
 				F99A9F3715436269000682F3 /* PlyExporter.h in Headers */,
 				F9607088154366AB004D91DD /* crc32.h in Headers */,
 				F9607088154366AB004D91DD /* crc32.h in Headers */,
 				F960708A154366AB004D91DD /* deflate.h in Headers */,
 				F960708A154366AB004D91DD /* deflate.h in Headers */,
@@ -3748,7 +3725,6 @@
 				F9BA8C261543268400E63FFE /* version.h in Headers */,
 				F9BA8C261543268400E63FFE /* version.h in Headers */,
 				F9BA8C4E154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C4E154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C52154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
 				F9BA8C52154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
-				F99A9F2F15436207000682F3 /* M3Importer.h in Headers */,
 				F99A9F3915436269000682F3 /* PlyExporter.h in Headers */,
 				F99A9F3915436269000682F3 /* PlyExporter.h in Headers */,
 				F960709C154366AB004D91DD /* crc32.h in Headers */,
 				F960709C154366AB004D91DD /* crc32.h in Headers */,
 				F960709E154366AB004D91DD /* deflate.h in Headers */,
 				F960709E154366AB004D91DD /* deflate.h in Headers */,
@@ -3997,7 +3973,6 @@
 				B919758A163AEA54009C397B /* version.h in Headers */,
 				B919758A163AEA54009C397B /* version.h in Headers */,
 				B919758B163AEA54009C397B /* OgreImporter.hpp in Headers */,
 				B919758B163AEA54009C397B /* OgreImporter.hpp in Headers */,
 				B919758C163AEA54009C397B /* OgreXmlHelper.hpp in Headers */,
 				B919758C163AEA54009C397B /* OgreXmlHelper.hpp in Headers */,
-				B9197595163AEA54009C397B /* M3Importer.h in Headers */,
 				B9197596163AEA54009C397B /* PlyExporter.h in Headers */,
 				B9197596163AEA54009C397B /* PlyExporter.h in Headers */,
 				B919759C163AEA54009C397B /* crc32.h in Headers */,
 				B919759C163AEA54009C397B /* crc32.h in Headers */,
 				B919759D163AEA54009C397B /* deflate.h in Headers */,
 				B919759D163AEA54009C397B /* deflate.h in Headers */,
@@ -4246,7 +4221,6 @@
 				F9BA8BC01543268400E63FFE /* version.h in Headers */,
 				F9BA8BC01543268400E63FFE /* version.h in Headers */,
 				F9BA8C3C154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C3C154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C40154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
 				F9BA8C40154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
-				F99A9F2915436207000682F3 /* M3Importer.h in Headers */,
 				F99A9F3315436269000682F3 /* PlyExporter.h in Headers */,
 				F99A9F3315436269000682F3 /* PlyExporter.h in Headers */,
 				F9607060154366AB004D91DD /* crc32.h in Headers */,
 				F9607060154366AB004D91DD /* crc32.h in Headers */,
 				F9607062154366AB004D91DD /* deflate.h in Headers */,
 				F9607062154366AB004D91DD /* deflate.h in Headers */,
@@ -4495,7 +4469,6 @@
 				F9BA8BE21543268400E63FFE /* version.h in Headers */,
 				F9BA8BE21543268400E63FFE /* version.h in Headers */,
 				F9BA8C42154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C42154328B600E63FFE /* OgreImporter.hpp in Headers */,
 				F9BA8C46154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
 				F9BA8C46154328B600E63FFE /* OgreXmlHelper.hpp in Headers */,
-				F99A9F2B15436207000682F3 /* M3Importer.h in Headers */,
 				F99A9F3515436269000682F3 /* PlyExporter.h in Headers */,
 				F99A9F3515436269000682F3 /* PlyExporter.h in Headers */,
 				F9607074154366AB004D91DD /* crc32.h in Headers */,
 				F9607074154366AB004D91DD /* crc32.h in Headers */,
 				F9607076154366AB004D91DD /* deflate.h in Headers */,
 				F9607076154366AB004D91DD /* deflate.h in Headers */,
@@ -4815,7 +4788,6 @@
 				F9BA8C49154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C49154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C4A154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C4A154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C4B154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
 				F9BA8C4B154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
-				F99A9F2C15436207000682F3 /* M3Importer.cpp in Sources */,
 				F99A9F3615436269000682F3 /* PlyExporter.cpp in Sources */,
 				F99A9F3615436269000682F3 /* PlyExporter.cpp in Sources */,
 				F9607085154366AB004D91DD /* adler32.c in Sources */,
 				F9607085154366AB004D91DD /* adler32.c in Sources */,
 				F9607086154366AB004D91DD /* compress.c in Sources */,
 				F9607086154366AB004D91DD /* compress.c in Sources */,
@@ -4978,7 +4950,6 @@
 				F9BA8C4F154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C4F154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C50154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C50154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C51154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
 				F9BA8C51154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
-				F99A9F2E15436207000682F3 /* M3Importer.cpp in Sources */,
 				F99A9F3815436269000682F3 /* PlyExporter.cpp in Sources */,
 				F99A9F3815436269000682F3 /* PlyExporter.cpp in Sources */,
 				F9607099154366AB004D91DD /* adler32.c in Sources */,
 				F9607099154366AB004D91DD /* adler32.c in Sources */,
 				F960709A154366AB004D91DD /* compress.c in Sources */,
 				F960709A154366AB004D91DD /* compress.c in Sources */,
@@ -5141,7 +5112,6 @@
 				B919761A163AEA54009C397B /* OgreMaterial.cpp in Sources */,
 				B919761A163AEA54009C397B /* OgreMaterial.cpp in Sources */,
 				B919761B163AEA54009C397B /* OgreMesh.cpp in Sources */,
 				B919761B163AEA54009C397B /* OgreMesh.cpp in Sources */,
 				B919761C163AEA54009C397B /* OgreSkeleton.cpp in Sources */,
 				B919761C163AEA54009C397B /* OgreSkeleton.cpp in Sources */,
-				B919761F163AEA54009C397B /* M3Importer.cpp in Sources */,
 				B9197620163AEA54009C397B /* PlyExporter.cpp in Sources */,
 				B9197620163AEA54009C397B /* PlyExporter.cpp in Sources */,
 				B9197625163AEA54009C397B /* adler32.c in Sources */,
 				B9197625163AEA54009C397B /* adler32.c in Sources */,
 				B9197626163AEA54009C397B /* compress.c in Sources */,
 				B9197626163AEA54009C397B /* compress.c in Sources */,
@@ -5304,7 +5274,6 @@
 				F9BA8C3D154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C3D154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C3E154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C3E154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C3F154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
 				F9BA8C3F154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
-				F99A9F2815436207000682F3 /* M3Importer.cpp in Sources */,
 				F99A9F3215436269000682F3 /* PlyExporter.cpp in Sources */,
 				F99A9F3215436269000682F3 /* PlyExporter.cpp in Sources */,
 				F960705D154366AB004D91DD /* adler32.c in Sources */,
 				F960705D154366AB004D91DD /* adler32.c in Sources */,
 				F960705E154366AB004D91DD /* compress.c in Sources */,
 				F960705E154366AB004D91DD /* compress.c in Sources */,
@@ -5467,7 +5436,6 @@
 				F9BA8C43154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C43154328B600E63FFE /* OgreMaterial.cpp in Sources */,
 				F9BA8C44154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C44154328B600E63FFE /* OgreMesh.cpp in Sources */,
 				F9BA8C45154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
 				F9BA8C45154328B600E63FFE /* OgreSkeleton.cpp in Sources */,
-				F99A9F2A15436207000682F3 /* M3Importer.cpp in Sources */,
 				F99A9F3415436269000682F3 /* PlyExporter.cpp in Sources */,
 				F99A9F3415436269000682F3 /* PlyExporter.cpp in Sources */,
 				F9607071154366AB004D91DD /* adler32.c in Sources */,
 				F9607071154366AB004D91DD /* adler32.c in Sources */,
 				F9607072154366AB004D91DD /* compress.c in Sources */,
 				F9607072154366AB004D91DD /* compress.c in Sources */,