Browse Source

Merge remote-tracking branch 'official/master' into contrib

Conflicts:
	code/ColladaParser.cpp
	include/assimp/config.h
Léo Terziman 10 năm trước cách đây
mục cha
commit
60d58901a5
64 tập tin đã thay đổi với 14010 bổ sung1562 xóa
  1. 5 1
      .gitignore
  2. 11 2
      .travis.yml
  3. 2 0
      CMakeLists.txt
  4. 5 0
      CREDITS
  5. 2 2
      code/3DSExporter.cpp
  6. 1 1
      code/AssbinExporter.cpp
  7. 1 1
      code/AssxmlExporter.cpp
  8. 17 1
      code/BlenderIntermediate.h
  9. 10 7
      code/BlenderLoader.cpp
  10. 2 0
      code/BlobIOSystem.h
  11. 3 0
      code/C4DImporter.cpp
  12. 26 3
      code/CMakeLists.txt
  13. 1 1
      code/ColladaExporter.cpp
  14. 6 4
      code/ColladaParser.cpp
  15. 128 15
      code/Exporter.cpp
  16. 13 0
      code/GenericProperty.h
  17. 2 2
      code/IFCCurve.cpp
  18. 6 3
      code/IFCLoader.cpp
  19. 1 1
      code/IFCUtil.cpp
  20. 53 47
      code/ImporterRegistry.cpp
  21. 1 1
      code/ObjExporter.cpp
  22. 518 518
      code/ObjFileImporter.cpp
  23. 37 37
      code/ObjFileImporter.h
  24. 486 486
      code/ObjFileParser.cpp
  25. 59 59
      code/ObjFileParser.h
  26. 50 50
      code/OgreImporter.h
  27. 691 0
      code/OpenGEXImporter.cpp
  28. 158 0
      code/OpenGEXImporter.h
  29. 265 0
      code/OpenGEXStructs.h
  30. 2 2
      code/PlyExporter.cpp
  31. 46 27
      code/PlyLoader.cpp
  32. 2 2
      code/STLExporter.cpp
  33. 28 9
      code/XFileExporter.cpp
  34. 8 2
      code/XFileExporter.h
  35. 64 0
      contrib/openddlparser/CMakeLists.txt
  36. 111 0
      contrib/openddlparser/README.md
  37. 184 0
      contrib/openddlparser/code/DDLNode.cpp
  38. 900 0
      contrib/openddlparser/code/OpenDDLParser.cpp
  39. 256 0
      contrib/openddlparser/code/Value.cpp
  40. 90 0
      contrib/openddlparser/include/openddlparser/DDLNode.h
  41. 170 0
      contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
  42. 131 0
      contrib/openddlparser/include/openddlparser/OpenDDLParser.h
  43. 249 0
      contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
  44. 97 0
      contrib/openddlparser/include/openddlparser/Value.h
  45. 46 46
      include/assimp/Compiler/pushpack1.h
  46. 185 9
      include/assimp/Exporter.hpp
  47. 11 2
      include/assimp/config.h
  48. 53 44
      port/jassimp/build.xml
  49. 13 0
      port/jassimp/jassimp-native/Android.mk
  50. 59 25
      port/jassimp/jassimp-native/src/jassimp.cpp
  51. 0 33
      test/RunSingleUnitTestSuite.bat
  52. 0 94
      test/RunUnitTestSuite.bat
  53. BIN
      test/models-nonbsd/FBX/2013_BINARY/anims_with_full_rotations_between_keys.fbx
  54. 754 0
      test/models-nonbsd/PLY/ant-half.ply
  55. 165 0
      test/models-nonbsd/PLY/ant-half.ply.license
  56. BIN
      test/models/BLEND/BlenderDefault_271.blend
  57. 7561 0
      test/models/Collada/anims_with_full_rotations_between_keys.DAE
  58. 95 0
      test/models/OpenGEX/Example.ogex
  59. 13 16
      test/regression/run.py
  60. 1 1
      test/regression/settings.py
  61. 1 1
      tools/assimp_cmd/CMakeLists.txt
  62. 23 7
      tools/assimp_cmd/CompareDump.cpp
  63. 124 0
      workspaces/Android-NDK/jni/Android.mk
  64. 8 0
      workspaces/Android-NDK/jni/Application.mk

+ 5 - 1
.gitignore

@@ -10,7 +10,7 @@ build
 # Output
 # Output
 bin/
 bin/
 lib/
 lib/
-contrib/
+
 
 
 # Generated
 # Generated
 assimp.pc
 assimp.pc
@@ -54,3 +54,7 @@ tools/assimp_view/assimp_viewer.vcxproj.user
 
 
 # Unix editor backups
 # Unix editor backups
 *~
 *~
+test/gtest/src/gtest-stamp/gtest-gitinfo.txt
+test/gtest/src/gtest-stamp/gtest-gitclone-lastrun.txt
+Assimp.opensdf
+contrib/zlib/CTestTestfile.cmake

+ 11 - 2
.travis.yml

@@ -1,8 +1,15 @@
 before_install:
 before_install:
   - sudo apt-get install cmake python3
   - sudo apt-get install cmake python3
+  - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
+
+branches:
+  only:
+    - master
 
 
 env:
 env:
-    matrix:
+  global:
+    - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
+  matrix:
     - LINUX=1 TRAVIS_NO_EXPORT=YES
     - LINUX=1 TRAVIS_NO_EXPORT=YES
     - LINUX=1 TRAVIS_NO_EXPORT=NO
     - LINUX=1 TRAVIS_NO_EXPORT=NO
     - LINUX=1 TRAVIS_STATIC_BUILD=ON
     - LINUX=1 TRAVIS_STATIC_BUILD=ON
@@ -11,6 +18,7 @@ env:
     - WINDOWS=1 TRAVIS_NO_EXPORT=NO
     - WINDOWS=1 TRAVIS_NO_EXPORT=NO
     - WINDOWS=1 TRAVIS_STATIC_BUILD=ON
     - WINDOWS=1 TRAVIS_STATIC_BUILD=ON
     - WINDOWS=1 TRAVIS_STATIC_BUILD=OFF
     - WINDOWS=1 TRAVIS_STATIC_BUILD=OFF
+    - ANDROID=1
 
 
 language: cpp
 language: cpp
 
 
@@ -20,8 +28,10 @@ compiler:
 
 
 install:
 install:
   - if [ $WINDOWS ]; then travis_retry sudo apt-get install -q -y gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64; fi 
   - if [ $WINDOWS ]; then travis_retry sudo apt-get install -q -y gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64; fi 
+  - if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
 
 
 script:
 script:
+  - if [ $ANDROID ]; then ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni ; fi
   - cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -STATIC_BUILD=$TRAVIS_STATIC_BUILD
   - cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -STATIC_BUILD=$TRAVIS_STATIC_BUILD
   - make
   - make
   - sudo make install
   - sudo make install
@@ -34,4 +44,3 @@ script:
   - echo "=========================================================="
   - echo "=========================================================="
   - echo "REGRESSION TEST FAILS (results/run_regression_suite_failures.csv)"
   - echo "REGRESSION TEST FAILS (results/run_regression_suite_failures.csv)"
   - cat ../results/run_regression_suite_failures.csv
   - cat ../results/run_regression_suite_failures.csv
-

+ 2 - 0
CMakeLists.txt

@@ -11,6 +11,8 @@ set (PROJECT_VERSION "${ASSIMP_VERSION}")
 
 
 set(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources")
 set(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources")
 
 
+add_definitions( -DOPENDDL_NO_USE_CPP11 )
+
 # Get the current working branch
 # Get the current working branch
 execute_process(
 execute_process(
     COMMAND git rev-parse --abbrev-ref HEAD
     COMMAND git rev-parse --abbrev-ref HEAD

+ 5 - 0
CREDITS

@@ -151,3 +151,8 @@ Ogre Binary format support
 
 
 - Filip Wasil, Tieto Poland Sp. z o.o.
 - Filip Wasil, Tieto Poland Sp. z o.o.
 Android JNI asset extraction support
 Android JNI asset extraction support
+
+- Richard Steffen
+Contributed X File exporter
+Contributed ExportProperties interface
+

+ 2 - 2
code/3DSExporter.cpp

@@ -144,7 +144,7 @@ namespace {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
-void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
 	boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
 	if(!outfile) {
 	if(!outfile) {
@@ -188,8 +188,8 @@ Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, c
 
 
 	{
 	{
 		ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
 		ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
-		WriteMeshes();
 		WriteMaterials();
 		WriteMaterials();
+		WriteMeshes();
 
 
 		{
 		{
 			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
 			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);

+ 1 - 1
code/AssbinExporter.cpp

@@ -754,7 +754,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
 		}
 		}
 	};
 	};
 
 
-void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	AssbinExport exporter;
 	AssbinExport exporter;
 	exporter.WriteBinaryDump( pFile, pIOSystem, pScene );
 	exporter.WriteBinaryDump( pFile, pIOSystem, pScene );

+ 1 - 1
code/AssxmlExporter.cpp

@@ -621,7 +621,7 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened)
 
 
 } // end of namespace AssxmlExport
 } // end of namespace AssxmlExport
 
 
-void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	IOStream * out = pIOSystem->Open( pFile, "wt" );
 	IOStream * out = pIOSystem->Open( pFile, "wt" );
 	if (!out) return;
 	if (!out) return;

+ 17 - 1
code/BlenderIntermediate.h

@@ -118,6 +118,16 @@ namespace Blender {
 #ifdef _MSC_VER
 #ifdef _MSC_VER
 #	pragma warning(disable:4351)
 #	pragma warning(disable:4351)
 #endif
 #endif
+
+	struct ObjectCompare {
+		bool operator() (const Object* left, const Object* right) const {
+			return strcmp(left->id.name, right->id.name) == -1;
+		}
+	};
+
+	// When keeping objects in sets, sort them by their name.
+	typedef std::set<const Object*, ObjectCompare> ObjectSet;
+
 	// --------------------------------------------------------------------
 	// --------------------------------------------------------------------
 	/** ConversionData acts as intermediate storage location for
 	/** ConversionData acts as intermediate storage location for
 	 *  the various ConvertXXX routines in BlenderImporter.*/
 	 *  the various ConvertXXX routines in BlenderImporter.*/
@@ -130,7 +140,13 @@ namespace Blender {
 			, db(db)
 			, db(db)
 		{}
 		{}
 
 
-		std::set<const Object*> objects;
+		struct ObjectCompare {
+			bool operator() (const Object* left, const Object* right) const {
+				return strcmp(left->id.name, right->id.name) == -1;
+			}
+		};
+
+		ObjectSet objects;
 
 
 		TempArray <std::vector, aiMesh> meshes;
 		TempArray <std::vector, aiMesh> meshes;
 		TempArray <std::vector, aiCamera> cameras;
 		TempArray <std::vector, aiCamera> cameras;

+ 10 - 7
code/BlenderLoader.cpp

@@ -559,24 +559,26 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
 		if (mesh->mMaterialIndex == static_cast<unsigned int>( -1 )) {
 		if (mesh->mMaterialIndex == static_cast<unsigned int>( -1 )) {
 
 
 			if (index == static_cast<unsigned int>( -1 )) {
 			if (index == static_cast<unsigned int>( -1 )) {
-
-				// ok, we need to add a dedicated default material for some poor material-less meshes
+				// Setup a default material.
 				boost::shared_ptr<Material> p(new Material());
 				boost::shared_ptr<Material> p(new Material());
+				ai_assert(::strlen(AI_DEFAULT_MATERIAL_NAME) < sizeof(p->id.name)-2);
 				strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME );
 				strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME );
 
 
+				// Note: MSVC11 does not zero-initialize Material here, although it should.
+				// Thus all relevant fields should be explicitly initialized. We cannot add
+				// a default constructor to Material since the DNA codegen does not support
+				// parsing it.
 				p->r = p->g = p->b = 0.6f;
 				p->r = p->g = p->b = 0.6f;
 				p->specr = p->specg = p->specb = 0.6f;
 				p->specr = p->specg = p->specb = 0.6f;
 				p->ambr = p->ambg = p->ambb = 0.0f;
 				p->ambr = p->ambg = p->ambb = 0.0f;
 				p->mirr = p->mirg = p->mirb = 0.0f;
 				p->mirr = p->mirg = p->mirb = 0.0f;
 				p->emit = 0.f;
 				p->emit = 0.f;
 				p->alpha = 0.f;
 				p->alpha = 0.f;
-
-				// XXX add more / or add default c'tor to Material
+				p->har = 0;
 
 
 				index = static_cast<unsigned int>( conv_data.materials_raw.size() );
 				index = static_cast<unsigned int>( conv_data.materials_raw.size() );
 				conv_data.materials_raw.push_back(p);
 				conv_data.materials_raw.push_back(p);
-
-				LogInfo("Adding default material ...");
+				LogInfo("Adding default material");
 			}
 			}
 			mesh->mMaterialIndex = index;
 			mesh->mMaterialIndex = index;
 		}
 		}
@@ -591,6 +593,7 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
 	
 	
 		aiMaterial* mout = new aiMaterial();
 		aiMaterial* mout = new aiMaterial();
 		conv_data.materials->push_back(mout);
 		conv_data.materials->push_back(mout);
+		// For any new material field handled here, the default material above must be updated with an appropriate default value.
 
 
 		// set material name
 		// set material name
 		aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA'
 		aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA'
@@ -1044,7 +1047,7 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
 aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, ConversionData& conv_data, const aiMatrix4x4& parentTransform)
 aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, ConversionData& conv_data, const aiMatrix4x4& parentTransform)
 {
 {
 	std::deque<const Object*> children;
 	std::deque<const Object*> children;
-	for(std::set<const Object*>::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) {
+	for(ObjectSet::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) {
 		const Object* object = *it;
 		const Object* object = *it;
 		if (object->parent == obj) {
 		if (object->parent == obj) {
 			children.push_back(object);
 			children.push_back(object);

+ 2 - 0
code/BlobIOSystem.h

@@ -120,9 +120,11 @@ public:
 		{
 		{
 		case aiOrigin_CUR:
 		case aiOrigin_CUR:
 			cursor += pOffset;
 			cursor += pOffset;
+			break;
 
 
 		case aiOrigin_END:
 		case aiOrigin_END:
 			cursor = file_size - pOffset;
 			cursor = file_size - pOffset;
+			break;
 
 
 		case aiOrigin_SET:
 		case aiOrigin_SET:
 			cursor = pOffset;
 			cursor = pOffset;

+ 3 - 0
code/C4DImporter.cpp

@@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the Cinema4D importer class.
  *  @brief Implementation of the Cinema4D importer class.
  */
  */
 #include "AssimpPCH.h"
 #include "AssimpPCH.h"
+#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
 
 
 // no #ifdefing here, Cinema4D support is carried out in a branch of assimp
 // no #ifdefing here, Cinema4D support is carried out in a branch of assimp
 // where it is turned on in the CMake settings. 
 // where it is turned on in the CMake settings. 
@@ -639,3 +640,5 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
 	ai_assert((*it).second < mat_count);
 	ai_assert((*it).second < mat_count);
 	return (*it).second;
 	return (*it).second;
 }
 }
+
+#endif // ASSIMP_BUILD_NO_C4D_IMPORTER

+ 26 - 3
code/CMakeLists.txt

@@ -265,8 +265,6 @@ SET( LWS_SRCS
 )
 )
 SOURCE_GROUP( LWS FILES ${LWS_SRCS})
 SOURCE_GROUP( LWS FILES ${LWS_SRCS})
 
 
-
-
 SET( MD2_SRCS
 SET( MD2_SRCS
 	MD2FileData.h
 	MD2FileData.h
 	MD2Loader.cpp
 	MD2Loader.cpp
@@ -360,6 +358,13 @@ SET( Ogre_SRCS
 )
 )
 SOURCE_GROUP( Ogre FILES ${Ogre_SRCS})
 SOURCE_GROUP( Ogre FILES ${Ogre_SRCS})
 
 
+SET( OpenGEX_SRCS
+    OpenGEXImporter.cpp
+    OpenGEXImporter.h
+    OpenGEXStructs.h
+)
+SOURCE_GROUP( OpenGEX FILES ${OpenGEX_SRCS})
+
 SET( Ply_SRCS
 SET( Ply_SRCS
 	PlyLoader.cpp
 	PlyLoader.cpp
 	PlyLoader.h
 	PlyLoader.h
@@ -635,6 +640,17 @@ SET( unzip_SRCS
 )
 )
 SOURCE_GROUP( unzip FILES ${unzip_SRCS})
 SOURCE_GROUP( unzip FILES ${unzip_SRCS})
 
 
+SET ( openddl_parser_SRCS
+    ../contrib/openddlparser/code/OpenDDLParser.cpp
+    ../contrib/openddlparser/code/DDLNode.cpp
+    ../contrib/openddlparser/code/Value.cpp
+    ../contrib/openddlparser/include/openddlparser/OpenDDLParser.h
+    ../contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
+    ../contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
+    ../contrib/openddlparser/include/openddlparser/DDLNode.h
+    ../contrib/openddlparser/include/openddlparser/Value.h
+)
+SOURCE_GROUP( openddl_parser FILES ${openddl_parser_SRCS})
 
 
 # VC2010 fixes
 # VC2010 fixes
 if(MSVC10)
 if(MSVC10)
@@ -690,6 +706,7 @@ SET( assimp_src
 	${OFFFormat_SRCS}
 	${OFFFormat_SRCS}
 	${Obj_SRCS}
 	${Obj_SRCS}
 	${Ogre_SRCS}
 	${Ogre_SRCS}
+    ${OpenGEX_SRCS}
 	${Ply_SRCS}
 	${Ply_SRCS}
 	${Q3D_SRCS}
 	${Q3D_SRCS}
 	${Q3BSP_SRCS}
 	${Q3BSP_SRCS}
@@ -714,6 +731,7 @@ SET( assimp_src
 	${unzip_compile_SRCS}
 	${unzip_compile_SRCS}
 	${Poly2Tri_SRCS}
 	${Poly2Tri_SRCS}
 	${Clipper_SRCS}
 	${Clipper_SRCS}
+    ${openddl_parser_SRCS}
 	# Necessary to show the headers in the project when using the VC++ generator:
 	# Necessary to show the headers in the project when using the VC++ generator:
 	${Boost_SRCS}
 	${Boost_SRCS}
 
 
@@ -725,6 +743,11 @@ SET( assimp_src
 	# Moreover it's a drag to recompile assimp entirely each time a modification is made to one of the included header, which is definitely counter-productive.)
 	# Moreover it's a drag to recompile assimp entirely each time a modification is made to one of the included header, which is definitely counter-productive.)
 	AssimpPCH.cpp
 	AssimpPCH.cpp
 )
 )
+add_definitions( -DOPENDDLPARSER_BUILD )
+
+INCLUDE_DIRECTORIES( 
+    ../contrib/openddlparser/include
+)
 
 
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 	SET( assimp_src ${assimp_src} ${C4D_SRCS})
 	SET( assimp_src ${assimp_src} ${C4D_SRCS})
@@ -735,7 +758,7 @@ ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 
 
 ADD_LIBRARY( assimp ${assimp_src} )
 ADD_LIBRARY( assimp ${assimp_src} )
 
 
-TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES})
+TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} )
 
 
 if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
 if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
 	set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)
 	set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)

+ 1 - 1
code/ColladaExporter.cpp

@@ -59,7 +59,7 @@ namespace Assimp
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
-void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	std::string path = "";
 	std::string path = "";
 	std::string file = pFile;
 	std::string file = pFile;

+ 6 - 4
code/ColladaParser.cpp

@@ -1989,10 +1989,12 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
 			break;
 			break;
 		}
 		}
 	}
 	}
-
-	// small sanity check
-	if (primType != Prim_TriFans && primType != Prim_TriStrips)
-		ai_assert(actualPrimitives == numPrimitives)
+
+#ifdef ASSIMP_BUILD_DEBUG  
+	if (primType != Prim_TriFans && primType != Prim_TriStrips) {
+		ai_assert(actualPrimitives == numPrimitives);
+	}
+#endif
 
 
 	// only when we're done reading all <p> tags (and thus know the final vertex count) can we commit the submesh
 	// only when we're done reading all <p> tags (and thus know the final vertex count) can we commit the submesh
 	subgroup.mNumFaces = actualPrimitives;
 	subgroup.mNumFaces = actualPrimitives;

+ 128 - 15
code/Exporter.cpp

@@ -72,16 +72,16 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
 // Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
 // do not use const, because some exporter need to convert the scene temporary
 // do not use const, because some exporter need to convert the scene temporary
-void ExportSceneCollada(const char*,IOSystem*, const aiScene*);
-void ExportSceneXFile(const char*,IOSystem*, const aiScene*); 
-void ExportSceneObj(const char*,IOSystem*, const aiScene*);
-void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
-void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
-void ExportScenePly(const char*,IOSystem*, const aiScene*);
-void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*);
-void ExportScene3DS(const char*, IOSystem*, const aiScene*);
-void ExportSceneAssbin(const char*, IOSystem*, const aiScene*);
-void ExportSceneAssxml(const char*, IOSystem*, const aiScene*);
+void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*); 
+void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // global array of all export formats which Assimp supports in its current build
 // global array of all export formats which Assimp supports in its current build
@@ -91,7 +91,7 @@ Exporter::ExportFormatEntry gExporters[] =
 	Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
 	Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
 #endif
 #endif
 
 
-#ifndef ASSIMP_BUILD_NO_FXILE_EXPORTER
+#ifndef ASSIMP_BUILD_NO_XFILE_EXPORTER
 	Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
 	Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
 		aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
 		aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
 #endif
 #endif
@@ -226,7 +226,7 @@ bool Exporter :: IsDefaultIOHandler() const
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter :: ExportToBlob(  const aiScene* pScene, const char* pFormatId, unsigned int )
+const aiExportDataBlob* Exporter :: ExportToBlob(  const aiScene* pScene, const char* pFormatId, unsigned int, const ExportProperties* pProperties)
 {
 {
 	if (pimpl->blob) {
 	if (pimpl->blob) {
 		delete pimpl->blob;
 		delete pimpl->blob;
@@ -282,7 +282,7 @@ bool IsVerboseFormat(const aiScene* pScene)
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-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, const ExportProperties* pProperties)
 {
 {
 	ASSIMP_BEGIN_EXCEPTION_REGION();
 	ASSIMP_BEGIN_EXCEPTION_REGION();
 
 
@@ -290,7 +290,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
 	// format. They will likely not be aware that there is a flag in the scene to indicate
 	// 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
 	// this, however. To avoid surprises and bug reports, we check for duplicates in
 	// meshes upfront.
 	// meshes upfront.
-	const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);
+	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) {
@@ -397,7 +397,8 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
 					proc.Execute(scenecopy.get());
 					proc.Execute(scenecopy.get());
 				}
 				}
 
 
-				exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get());
+				ExportProperties emptyProperties;  // Never pass NULL ExportProperties so Exporters don't have to worry.
+				exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties);
 			}
 			}
 			catch (DeadlyExportError& err) {
 			catch (DeadlyExportError& err) {
 				pimpl->mError = err.what();
 				pimpl->mError = err.what();
@@ -492,4 +493,116 @@ void Exporter :: UnregisterExporter(const char* id)
 	}
 	}
 }
 }
 
 
+ExportProperties :: ExportProperties() {}
+
+ExportProperties::ExportProperties(const ExportProperties &other)
+	 : mIntProperties(other.mIntProperties),
+   mFloatProperties(other.mFloatProperties),
+   mStringProperties(other.mStringProperties),
+   mMatrixProperties(other.mMatrixProperties)
+{
+	
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+void ExportProperties :: SetPropertyInteger(const char* szName, int iValue, 
+	bool* bWasExisting /*= NULL*/)
+{
+	SetGenericProperty<int>(mIntProperties, szName,iValue,bWasExisting);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+void ExportProperties :: SetPropertyFloat(const char* szName, float iValue, 
+	bool* bWasExisting /*= NULL*/)
+{
+	SetGenericProperty<float>(mFloatProperties, szName,iValue,bWasExisting);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+void ExportProperties :: SetPropertyString(const char* szName, const std::string& value, 
+	bool* bWasExisting /*= NULL*/)
+{
+	SetGenericProperty<std::string>(mStringProperties, szName,value,bWasExisting);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+void ExportProperties :: SetPropertyMatrix(const char* szName, const aiMatrix4x4& value, 
+	bool* bWasExisting /*= NULL*/)
+{
+	SetGenericProperty<aiMatrix4x4>(mMatrixProperties, szName,value,bWasExisting);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+int ExportProperties :: GetPropertyInteger(const char* szName, 
+	int iErrorReturn /*= 0xffffffff*/) const
+{
+	return GetGenericProperty<int>(mIntProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+float ExportProperties :: GetPropertyFloat(const char* szName, 
+	float iErrorReturn /*= 10e10*/) const
+{
+	return GetGenericProperty<float>(mFloatProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+const std::string ExportProperties :: GetPropertyString(const char* szName, 
+	const std::string& iErrorReturn /*= ""*/) const
+{
+	return GetGenericProperty<std::string>(mStringProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+const aiMatrix4x4 ExportProperties :: GetPropertyMatrix(const char* szName, 
+	const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const
+{
+	return GetGenericProperty<aiMatrix4x4>(mMatrixProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyInteger(const char* szName) const
+{
+	return HasGenericProperty<int>(mIntProperties, szName);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyBool(const char* szName) const
+{
+	return HasGenericProperty<int>(mIntProperties, szName);
+};
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyFloat(const char* szName) const
+{
+	return HasGenericProperty<float>(mFloatProperties, szName);
+};
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyString(const char* szName) const
+{
+	return HasGenericProperty<std::string>(mStringProperties, szName);
+};
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyMatrix(const char* szName) const
+{
+	return HasGenericProperty<aiMatrix4x4>(mMatrixProperties, szName);
+};
+
+
 #endif // !ASSIMP_BUILD_NO_EXPORT
 #endif // !ASSIMP_BUILD_NO_EXPORT

+ 13 - 0
code/GenericProperty.h

@@ -108,5 +108,18 @@ inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
 		*bWasExisting = true;
 		*bWasExisting = true;
 }
 }
 
 
+// ------------------------------------------------------------------------------------------------
+template <class T>
+inline const bool HasGenericProperty(const std::map< unsigned int, T >& list, 
+	const char* szName)
+{
+	ai_assert(NULL != szName);
+	const uint32_t hash = SuperFastHash(szName);
+
+	typename std::map<unsigned int, T>::const_iterator it = list.find(hash);
+	if (it == list.end()) return false;
+	
+	return true;
+}
 
 
 #endif // !! AI_GENERIC_PROPERTY_H_INCLUDED
 #endif // !! AI_GENERIC_PROPERTY_H_INCLUDED

+ 2 - 2
code/IFCCurve.cpp

@@ -648,10 +648,10 @@ void Curve :: SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
 	ai_assert(InRange(a) && InRange(b));
 	ai_assert(InRange(a) && InRange(b));
 
 
 	const size_t cnt = std::max(static_cast<size_t>(0),EstimateSampleCount(a,b));
 	const size_t cnt = std::max(static_cast<size_t>(0),EstimateSampleCount(a,b));
-	out.verts.reserve( out.verts.size() + cnt );
+	out.verts.reserve( out.verts.size() + cnt + 1);
 
 
 	IfcFloat p = a, delta = (b-a)/cnt;
 	IfcFloat p = a, delta = (b-a)/cnt;
-	for(size_t i = 0; i < cnt; ++i, p += delta) {
+	for(size_t i = 0; i <= cnt; ++i, p += delta) {
 		out.verts.push_back(Eval(p));
 		out.verts.push_back(Eval(p));
 	}
 	}
 }
 }

+ 6 - 3
code/IFCLoader.cpp

@@ -677,10 +677,11 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
 	const STEP::DB::RefMap& refs = conv.db.GetRefs();
 	const STEP::DB::RefMap& refs = conv.db.GetRefs();
 
 
 	// skip over space and annotation nodes - usually, these have no meaning in Assimp's context
 	// skip over space and annotation nodes - usually, these have no meaning in Assimp's context
+	bool skipGeometry = false;
 	if(conv.settings.skipSpaceRepresentations) {
 	if(conv.settings.skipSpaceRepresentations) {
 		if(const IfcSpace* const space = el.ToPtr<IfcSpace>()) {
 		if(const IfcSpace* const space = el.ToPtr<IfcSpace>()) {
 			IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings");
 			IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings");
-			return NULL;
+			skipGeometry = true;
 		}
 		}
 	}
 	}
 
 
@@ -850,8 +851,10 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
 			conv.apply_openings = &openings;
 			conv.apply_openings = &openings;
 		}
 		}
 
 
-		ProcessProductRepresentation(el,nd.get(),subnodes,conv);
-		conv.apply_openings = conv.collect_openings = NULL;
+		if (!skipGeometry) {
+		  ProcessProductRepresentation(el,nd.get(),subnodes,conv);
+		  conv.apply_openings = conv.collect_openings = NULL;
+		}
 
 
 		if (subnodes.size()) {
 		if (subnodes.size()) {
 			nd->mChildren = new aiNode*[subnodes.size()]();
 			nd->mChildren = new aiNode*[subnodes.size()]();

+ 1 - 1
code/IFCUtil.cpp

@@ -236,7 +236,7 @@ IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const
 
 
 struct CompareVector
 struct CompareVector
 {
 {
-	bool operator () (const IfcVector3& a, const IfcVector3& b)
+	bool operator () (const IfcVector3& a, const IfcVector3& b) const
 	{
 	{
 		IfcVector3 d = a - b;
 		IfcVector3 d = a - b;
 		IfcFloat eps = 1e-6;
 		IfcFloat eps = 1e-6;

+ 53 - 47
code/ImporterRegistry.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, assimp team
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -142,6 +142,9 @@ corresponding preprocessor flag to selectively disable formats.
 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
 #	include "OgreImporter.h"
 #	include "OgreImporter.h"
 #endif
 #endif
+#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+#   include "OpenGEXImporter.h"
+#endif
 #ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
 #ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
 #	include "MS3DLoader.h"
 #	include "MS3DLoader.h"
 #endif
 #endif
@@ -179,132 +182,135 @@ namespace Assimp {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void GetImporterInstanceList(std::vector< BaseImporter* >& out)
 void GetImporterInstanceList(std::vector< BaseImporter* >& out)
 {
 {
-	// ----------------------------------------------------------------------------
-	// Add an instance of each worker class here
-	// (register_new_importers_here)
-	// ----------------------------------------------------------------------------
-	out.reserve(64);
+    // ----------------------------------------------------------------------------
+    // Add an instance of each worker class here
+    // (register_new_importers_here)
+    // ----------------------------------------------------------------------------
+    out.reserve(64);
 #if (!defined ASSIMP_BUILD_NO_X_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_X_IMPORTER)
-	out.push_back( new XFileImporter());
+    out.push_back( new XFileImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER)
-	out.push_back( new ObjFileImporter());
+    out.push_back( new ObjFileImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
-	out.push_back( new Discreet3DSImporter());
+    out.push_back( new Discreet3DSImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER)
-	out.push_back( new MD3Importer());
+    out.push_back( new MD3Importer());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MD2_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MD2_IMPORTER)
-	out.push_back( new MD2Importer());
+    out.push_back( new MD2Importer());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_PLY_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_PLY_IMPORTER)
-	out.push_back( new PLYImporter());
+    out.push_back( new PLYImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MDL_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MDL_IMPORTER)
-	out.push_back( new MDLImporter());
+    out.push_back( new MDLImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
-	out.push_back( new ASEImporter());
+    out.push_back( new ASEImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
-	out.push_back( new HMPImporter());
+    out.push_back( new HMPImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_SMD_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_SMD_IMPORTER)
-	out.push_back( new SMDImporter());
+    out.push_back( new SMDImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MDC_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MDC_IMPORTER)
-	out.push_back( new MDCImporter());
+    out.push_back( new MDCImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MD5_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MD5_IMPORTER)
-	out.push_back( new MD5Importer());
+    out.push_back( new MD5Importer());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_STL_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_STL_IMPORTER)
-	out.push_back( new STLImporter());
+    out.push_back( new STLImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER)
-	out.push_back( new LWOImporter());
+    out.push_back( new LWOImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_DXF_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_DXF_IMPORTER)
-	out.push_back( new DXFImporter());
+    out.push_back( new DXFImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_NFF_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_NFF_IMPORTER)
-	out.push_back( new NFFImporter());
+    out.push_back( new NFFImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER)
-	out.push_back( new RAWImporter());
+    out.push_back( new RAWImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_OFF_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_OFF_IMPORTER)
-	out.push_back( new OFFImporter());
+    out.push_back( new OFFImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_AC_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_AC_IMPORTER)
-	out.push_back( new AC3DImporter());
+    out.push_back( new AC3DImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_BVH_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_BVH_IMPORTER)
-	out.push_back( new BVHLoader());
+    out.push_back( new BVHLoader());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_IRRMESH_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_IRRMESH_IMPORTER)
-	out.push_back( new IRRMeshImporter());
+    out.push_back( new IRRMeshImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_IRR_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_IRR_IMPORTER)
-	out.push_back( new IRRImporter());
+    out.push_back( new IRRImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_Q3D_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_Q3D_IMPORTER)
-	out.push_back( new Q3DImporter());
+    out.push_back( new Q3DImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_B3D_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_B3D_IMPORTER)
-	out.push_back( new B3DImporter());
+    out.push_back( new B3DImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_COLLADA_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_COLLADA_IMPORTER)
-	out.push_back( new ColladaLoader());
+    out.push_back( new ColladaLoader());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_TERRAGEN_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_TERRAGEN_IMPORTER)
-	out.push_back( new TerragenImporter());
+    out.push_back( new TerragenImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_CSM_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_CSM_IMPORTER)
-	out.push_back( new CSMImporter());
+    out.push_back( new CSMImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_3D_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_3D_IMPORTER)
-	out.push_back( new UnrealImporter());
+    out.push_back( new UnrealImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
-	out.push_back( new LWSImporter());
+    out.push_back( new LWSImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_OGRE_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_OGRE_IMPORTER)
-	out.push_back( new Ogre::OgreImporter());
+    out.push_back( new Ogre::OgreImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_OPENGEX_IMPORTER )
+    out.push_back( new OpenGEX::OpenGEXImporter() );
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_MS3D_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_MS3D_IMPORTER)
-	out.push_back( new MS3DImporter());
+    out.push_back( new MS3DImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_COB_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_COB_IMPORTER)
-	out.push_back( new COBImporter());
+    out.push_back( new COBImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_BLEND_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_BLEND_IMPORTER)
-	out.push_back( new BlenderImporter());
+    out.push_back( new BlenderImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER)
-	out.push_back( new Q3BSPFileImporter() );
+    out.push_back( new Q3BSPFileImporter() );
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
-	out.push_back( new NDOImporter() );
+    out.push_back( new NDOImporter() );
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
-	out.push_back( new IFCImporter() );
+    out.push_back( new IFCImporter() );
 #endif
 #endif
 #if ( !defined ASSIMP_BUILD_NO_XGL_IMPORTER )
 #if ( !defined ASSIMP_BUILD_NO_XGL_IMPORTER )
-	out.push_back( new XGLImporter() );
+    out.push_back( new XGLImporter() );
 #endif
 #endif
 #if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
 #if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
-	out.push_back( new FBXImporter() );
+    out.push_back( new FBXImporter() );
 #endif
 #endif
 #if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
 #if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
-	out.push_back( new AssbinImporter() );
+    out.push_back( new AssbinImporter() );
 #endif
 #endif
 
 
 #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
 #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
-	out.push_back( new C4DImporter() );
+    out.push_back( new C4DImporter() );
 #endif
 #endif
 }
 }
 
 
-}
+} // namespace Assimp

+ 1 - 1
code/ObjExporter.cpp

@@ -51,7 +51,7 @@ namespace Assimp	{
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp
-void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	// invoke the exporter 
 	// invoke the exporter 
 	ObjExporter exporter(pFile, pScene);
 	ObjExporter exporter(pFile, pScene);

+ 518 - 518
code/ObjFileImporter.cpp

@@ -48,16 +48,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ObjFileData.h"
 #include "ObjFileData.h"
 
 
 static const aiImporterDesc desc = {
 static const aiImporterDesc desc = {
-	"Wavefront Object Importer",
-	"",
-	"",
-	"surfaces not supported",
-	aiImporterFlags_SupportTextFlavour,
-	0,
-	0,
-	0,
-	0,
-	"obj"
+    "Wavefront Object Importer",
+    "",
+    "",
+    "surfaces not supported",
+    aiImporterFlags_SupportTextFlavour,
+    0,
+    0,
+    0,
+    0,
+    "obj"
 };
 };
 
 
 static const unsigned int ObjMinSize = 16;
 static const unsigned int ObjMinSize = 16;
@@ -69,99 +69,99 @@ using namespace std;
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Default constructor
 //	Default constructor
 ObjFileImporter::ObjFileImporter() :
 ObjFileImporter::ObjFileImporter() :
-	m_Buffer(),	
-	m_pRootObject( NULL ),
-	m_strAbsPath( "" )
+    m_Buffer(),	
+    m_pRootObject( NULL ),
+    m_strAbsPath( "" )
 {
 {
     DefaultIOSystem io;
     DefaultIOSystem io;
-	m_strAbsPath = io.getOsSeparator();
+    m_strAbsPath = io.getOsSeparator();
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Destructor.
 //	Destructor.
 ObjFileImporter::~ObjFileImporter()
 ObjFileImporter::~ObjFileImporter()
 {
 {
-	delete m_pRootObject;
-	m_pRootObject = NULL;
+    delete m_pRootObject;
+    m_pRootObject = NULL;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Returns true, if file is an obj file.
 //	Returns true, if file is an obj file.
 bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem*  pIOHandler , bool checkSig ) const
 bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem*  pIOHandler , bool checkSig ) const
 {
 {
-	if(!checkSig) //Check File Extension
-	{
-		return SimpleExtensionCheck(pFile,"obj");
-	}
-	else //Check file Header
-	{
-		static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
-		return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9 );
-	}
+    if(!checkSig) //Check File Extension
+    {
+        return SimpleExtensionCheck(pFile,"obj");
+    }
+    else //Check file Header
+    {
+        static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
+        return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9 );
+    }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 const aiImporterDesc* ObjFileImporter::GetInfo () const
 const aiImporterDesc* ObjFileImporter::GetInfo () const
 {
 {
-	return &desc;
+    return &desc;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Obj-file import implementation
 //	Obj-file import implementation
 void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
 void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
 {    
 {    
-	// Read file into memory
-	const std::string mode = "rb";
-	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
+    // Read file into memory
+    const std::string mode = "rb";
+    boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
     if( !file.get() ) {
     if( !file.get() ) {
         throw DeadlyImportError( "Failed to open file " + pFile + "." );
         throw DeadlyImportError( "Failed to open file " + pFile + "." );
     }
     }
 
 
-	// Get the file-size and validate it, throwing an exception when fails
-	size_t fileSize = file->FileSize();
+    // Get the file-size and validate it, throwing an exception when fails
+    size_t fileSize = file->FileSize();
     if( fileSize < ObjMinSize ) {
     if( fileSize < ObjMinSize ) {
-		throw DeadlyImportError( "OBJ-file is too small.");
+        throw DeadlyImportError( "OBJ-file is too small.");
+    }
+
+    // Allocate buffer and read file into it
+    TextFileToBuffer(file.get(),m_Buffer);
+
+    // Get the model name
+    std::string  strModelName;
+    std::string::size_type pos = pFile.find_last_of( "\\/" );
+    if ( pos != std::string::npos )	
+    {
+        strModelName = pFile.substr(pos+1, pFile.size() - pos - 1);
     }
     }
+    else
+    {
+        strModelName = pFile;
+    }
+
+    // process all '\'
+    std::vector<char> ::iterator iter = m_Buffer.begin();
+    while (iter != m_Buffer.end())
+    {
+        if (*iter == '\\')
+        {
+            // remove '\'
+            iter = m_Buffer.erase(iter);
+            // remove next character
+            while (*iter == '\r' || *iter == '\n')
+                iter = m_Buffer.erase(iter);
+        }
+        else
+            ++iter;
+    }
+
+    // parse the file into a temporary representation
+    ObjFileParser parser(m_Buffer, strModelName, pIOHandler);
+
+    // And create the proper return structures out of it
+    CreateDataFromImport(parser.GetModel(), pScene);
 
 
-	// Allocate buffer and read file into it
-	TextFileToBuffer(file.get(),m_Buffer);
-
-	// Get the model name
-	std::string  strModelName;
-	std::string::size_type pos = pFile.find_last_of( "\\/" );
-	if ( pos != std::string::npos )	
-	{
-		strModelName = pFile.substr(pos+1, pFile.size() - pos - 1);
-	}
-	else
-	{
-		strModelName = pFile;
-	}
-
-	// process all '\'
-	std::vector<char> ::iterator iter = m_Buffer.begin();
-	while (iter != m_Buffer.end())
-	{
-		if (*iter == '\\')
-		{
-			// remove '\'
-			iter = m_Buffer.erase(iter);
-			// remove next character
-			while (*iter == '\r' || *iter == '\n')
-				iter = m_Buffer.erase(iter);
-		}
-		else
-			++iter;
-	}
-
-	// parse the file into a temporary representation
-	ObjFileParser parser(m_Buffer, strModelName, pIOHandler);
-
-	// And create the proper return structures out of it
-	CreateDataFromImport(parser.GetModel(), pScene);
-
-	// Clean up allocated storage for the next import 
-	m_Buffer.clear();
+    // Clean up allocated storage for the next import 
+    m_Buffer.clear();
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -170,98 +170,98 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
     if( 0L == pModel ) {
     if( 0L == pModel ) {
         return;
         return;
     }
     }
-		
-	// Create the root node of the scene
-	pScene->mRootNode = new aiNode;
-	if ( !pModel->m_ModelName.empty() )
-	{
-		// Set the name of the scene
-		pScene->mRootNode->mName.Set(pModel->m_ModelName);
-	}
-	else
-	{
-		// This is a fatal error, so break down the application
-		ai_assert(false);
-	} 
-
-	// Create nodes for the whole scene	
-	std::vector<aiMesh*> MeshArray;
-	for (size_t index = 0; index < pModel->m_Objects.size(); index++)
-	{
-		createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
-	}
-
-	// Create mesh pointer buffer for this scene
-	if (pScene->mNumMeshes > 0)
-	{
-		pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
-		for (size_t index =0; index < MeshArray.size(); index++)
-		{
-			pScene->mMeshes [ index ] = MeshArray[ index ];
-		}
-	}
-
-	// Create all materials
-	createMaterials( pModel, pScene );
+        
+    // Create the root node of the scene
+    pScene->mRootNode = new aiNode;
+    if ( !pModel->m_ModelName.empty() )
+    {
+        // Set the name of the scene
+        pScene->mRootNode->mName.Set(pModel->m_ModelName);
+    }
+    else
+    {
+        // This is a fatal error, so break down the application
+        ai_assert(false);
+    } 
+
+    // Create nodes for the whole scene	
+    std::vector<aiMesh*> MeshArray;
+    for (size_t index = 0; index < pModel->m_Objects.size(); index++)
+    {
+        createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
+    }
+
+    // Create mesh pointer buffer for this scene
+    if (pScene->mNumMeshes > 0)
+    {
+        pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
+        for (size_t index =0; index < MeshArray.size(); index++)
+        {
+            pScene->mMeshes [ index ] = MeshArray[ index ];
+        }
+    }
+
+    // Create all materials
+    createMaterials( pModel, pScene );
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Creates all nodes of the model
 //	Creates all nodes of the model
 aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pObject, 
 aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pObject, 
-									 aiNode *pParent, aiScene* pScene, 
-									 std::vector<aiMesh*> &MeshArray )
+                                     aiNode *pParent, aiScene* pScene, 
+                                     std::vector<aiMesh*> &MeshArray )
 {
 {
-	ai_assert( NULL != pModel );
+    ai_assert( NULL != pModel );
     if( NULL == pObject ) {
     if( NULL == pObject ) {
         return NULL;
         return NULL;
     }
     }
-	
-	// Store older mesh size to be able to computes mesh offsets for new mesh instances
-	const size_t oldMeshSize = MeshArray.size();
-	aiNode *pNode = new aiNode;
-
-	pNode->mName = pObject->m_strObjName;
-	
-	// If we have a parent node, store it
+    
+    // Store older mesh size to be able to computes mesh offsets for new mesh instances
+    const size_t oldMeshSize = MeshArray.size();
+    aiNode *pNode = new aiNode;
+
+    pNode->mName = pObject->m_strObjName;
+    
+    // If we have a parent node, store it
     if( pParent != NULL ) {
     if( pParent != NULL ) {
         appendChildToParentNode( pParent, pNode );
         appendChildToParentNode( pParent, pNode );
     }
     }
 
 
-	for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ )
-	{
-		unsigned int meshId = pObject->m_Meshes[ i ];
-		aiMesh *pMesh = createTopology( pModel, pObject, meshId );	
+    for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ )
+    {
+        unsigned int meshId = pObject->m_Meshes[ i ];
+        aiMesh *pMesh = createTopology( pModel, pObject, meshId );	
         if( pMesh && pMesh->mNumFaces > 0 ) {
         if( pMesh && pMesh->mNumFaces > 0 ) {
-			MeshArray.push_back( pMesh );
-		}
-	}
-
-	// Create all nodes from the sub-objects stored in the current object
-	if ( !pObject->m_SubObjects.empty() )
-	{
-		size_t numChilds = pObject->m_SubObjects.size();
-		pNode->mNumChildren = static_cast<unsigned int>( numChilds );
-		pNode->mChildren = new aiNode*[ numChilds ];
-		pNode->mNumMeshes = 1;
-		pNode->mMeshes = new unsigned int[ 1 ];
-	}
-
-	// Set mesh instances into scene- and node-instances
-	const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
-	if ( meshSizeDiff > 0 )
-	{
-		pNode->mMeshes = new unsigned int[ meshSizeDiff ];
-		pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff );
-		size_t index = 0;
-		for (size_t i = oldMeshSize; i < MeshArray.size(); i++)
-		{
-			pNode->mMeshes[ index ] = pScene->mNumMeshes;
-			pScene->mNumMeshes++;
-			index++;
-		}
-	}
-	
-	return pNode;
+            MeshArray.push_back( pMesh );
+        }
+    }
+
+    // Create all nodes from the sub-objects stored in the current object
+    if ( !pObject->m_SubObjects.empty() )
+    {
+        size_t numChilds = pObject->m_SubObjects.size();
+        pNode->mNumChildren = static_cast<unsigned int>( numChilds );
+        pNode->mChildren = new aiNode*[ numChilds ];
+        pNode->mNumMeshes = 1;
+        pNode->mMeshes = new unsigned int[ 1 ];
+    }
+
+    // Set mesh instances into scene- and node-instances
+    const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
+    if ( meshSizeDiff > 0 )
+    {
+        pNode->mMeshes = new unsigned int[ meshSizeDiff ];
+        pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff );
+        size_t index = 0;
+        for (size_t i = oldMeshSize; i < MeshArray.size(); i++)
+        {
+            pNode->mMeshes[ index ] = pScene->mNumMeshes;
+            pScene->mNumMeshes++;
+            index++;
+        }
+    }
+    
+    return pNode;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -269,83 +269,83 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
 aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData, 
 aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData, 
                                          unsigned int uiMeshIndex )
                                          unsigned int uiMeshIndex )
 {
 {
-	// Checking preconditions
-	ai_assert( NULL != pModel );
+    // Checking preconditions
+    ai_assert( NULL != pModel );
     if( NULL == pData ) {
     if( NULL == pData ) {
         return NULL;
         return NULL;
     }
     }
 
 
-	// Create faces
-	ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
+    // Create faces
+    ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
     if( !pObjMesh ) {
     if( !pObjMesh ) {
         return NULL;
         return NULL;
     }
     }
     ai_assert( NULL != pObjMesh );
     ai_assert( NULL != pObjMesh );
     aiMesh* pMesh = new aiMesh;
     aiMesh* pMesh = new aiMesh;
-	for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
-	{
-		ObjFile::Face *const inp = pObjMesh->m_Faces[ index ];
+    for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
+    {
+        ObjFile::Face *const inp = pObjMesh->m_Faces[ index ];
         ai_assert( NULL != inp  );
         ai_assert( NULL != inp  );
 
 
-		if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
-			pMesh->mNumFaces += inp->m_pVertices->size() - 1;
-			pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
-		} else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
-			pMesh->mNumFaces += inp->m_pVertices->size();
-			pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
-		} else {
-			++pMesh->mNumFaces;
-			if (inp->m_pVertices->size() > 3) {
-				pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
-			} else {
-				pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
-			}
-		}
-	}
-
-	unsigned int uiIdxCount( 0u );
-	if ( pMesh->mNumFaces > 0 )
-	{
-		pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
-		if ( pObjMesh->m_uiMaterialIndex != ObjFile::Mesh::NoMaterial )
-		{
-			pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
-		}
-
-		unsigned int outIndex( 0 );
-
-		// Copy all data from all stored meshes
-		for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
-		{
-			ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
-			if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
-				for(size_t i = 0; i < inp->m_pVertices->size() - 1; ++i) {
-					aiFace& f = pMesh->mFaces[ outIndex++ ];
-					uiIdxCount += f.mNumIndices = 2;
-					f.mIndices = new unsigned int[2];
-				}
-				continue;
-			}
-			else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
-				for(size_t i = 0; i < inp->m_pVertices->size(); ++i) {
-					aiFace& f = pMesh->mFaces[ outIndex++ ];
-					uiIdxCount += f.mNumIndices = 1;
-					f.mIndices = new unsigned int[1];
-				}
-				continue;
-			}
-
-			aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
-			const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
-			uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
-			if (pFace->mNumIndices > 0) {
-				pFace->mIndices = new unsigned int[ uiNumIndices ];			
-			}
-		}
-	}
-
-	// Create mesh vertices
-	createVertexArray(pModel, pData, uiMeshIndex, pMesh, uiIdxCount);
+        if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
+            pMesh->mNumFaces += inp->m_pVertices->size() - 1;
+            pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+        } else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
+            pMesh->mNumFaces += inp->m_pVertices->size();
+            pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+        } else {
+            ++pMesh->mNumFaces;
+            if (inp->m_pVertices->size() > 3) {
+                pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+            } else {
+                pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+            }
+        }
+    }
+
+    unsigned int uiIdxCount( 0u );
+    if ( pMesh->mNumFaces > 0 )
+    {
+        pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
+        if ( pObjMesh->m_uiMaterialIndex != ObjFile::Mesh::NoMaterial )
+        {
+            pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
+        }
+
+        unsigned int outIndex( 0 );
+
+        // Copy all data from all stored meshes
+        for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
+        {
+            ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
+            if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
+                for(size_t i = 0; i < inp->m_pVertices->size() - 1; ++i) {
+                    aiFace& f = pMesh->mFaces[ outIndex++ ];
+                    uiIdxCount += f.mNumIndices = 2;
+                    f.mIndices = new unsigned int[2];
+                }
+                continue;
+            }
+            else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
+                for(size_t i = 0; i < inp->m_pVertices->size(); ++i) {
+                    aiFace& f = pMesh->mFaces[ outIndex++ ];
+                    uiIdxCount += f.mNumIndices = 1;
+                    f.mIndices = new unsigned int[1];
+                }
+                continue;
+            }
+
+            aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
+            const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
+            uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
+            if (pFace->mNumIndices > 0) {
+                pFace->mIndices = new unsigned int[ uiNumIndices ];			
+            }
+        }
+    }
+
+    // Create mesh vertices
+    createVertexArray(pModel, pData, uiMeshIndex, pMesh, uiIdxCount);
 
 
     return pMesh;
     return pMesh;
 }
 }
@@ -353,335 +353,335 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Creates a vertex array
 //	Creates a vertex array
 void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, 
 void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, 
-										const ObjFile::Object* pCurrentObject, 
-										unsigned int uiMeshIndex,
-										aiMesh* pMesh,
-										unsigned int uiIdxCount)
+                                        const ObjFile::Object* pCurrentObject, 
+                                        unsigned int uiMeshIndex,
+                                        aiMesh* pMesh,
+                                        unsigned int uiIdxCount)
 {
 {
-	// Checking preconditions
-	ai_assert( NULL != pCurrentObject );
-	
-	// Break, if no faces are stored in object
-	if ( pCurrentObject->m_Meshes.empty() )
-		return;
-
-	// Get current mesh
-	ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
-	if ( NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1)
-		return;
-
-	// Copy vertices of this mesh instance
-	pMesh->mNumVertices = uiIdxCount;
-	pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
-	
-	// Allocate buffer for normal vectors
-	if ( !pModel->m_Normals.empty() && pObjMesh->m_hasNormals )
-		pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
-	
-	// Allocate buffer for texture coordinates
-	if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] )
-	{
-		pMesh->mNumUVComponents[ 0 ] = 2;
-		pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
-	}
-	
-	// Copy vertices, normals and textures into aiMesh instance
-	unsigned int newIndex = 0, outIndex = 0;
-	for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ )
-	{
-		// Get source face
-		ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ]; 
-
-		// Copy all index arrays
-		for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ )
-		{
-			const unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex );
-			if ( vertex >= pModel->m_Vertices.size() ) 
-				throw DeadlyImportError( "OBJ: vertex index out of range" );
-			
-			pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
-			
-			// Copy all normals 
-			if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_pNormals->size())
-			{
-				const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
-				if ( normal >= pModel->m_Normals.size() )
-					throw DeadlyImportError("OBJ: vertex normal index out of range");
-
-				pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
-			}
-			
-			// Copy all texture coordinates
-			if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
-			{
-				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 coordinate index out of range");
-
-				const aiVector3D &coord3d = pModel->m_TextureCoord[ tex ];
+    // Checking preconditions
+    ai_assert( NULL != pCurrentObject );
+    
+    // Break, if no faces are stored in object
+    if ( pCurrentObject->m_Meshes.empty() )
+        return;
+
+    // Get current mesh
+    ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
+    if ( NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1)
+        return;
+
+    // Copy vertices of this mesh instance
+    pMesh->mNumVertices = uiIdxCount;
+    pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
+    
+    // Allocate buffer for normal vectors
+    if ( !pModel->m_Normals.empty() && pObjMesh->m_hasNormals )
+        pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
+    
+    // Allocate buffer for texture coordinates
+    if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] )
+    {
+        pMesh->mNumUVComponents[ 0 ] = 2;
+        pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
+    }
+    
+    // Copy vertices, normals and textures into aiMesh instance
+    unsigned int newIndex = 0, outIndex = 0;
+    for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ )
+    {
+        // Get source face
+        ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ]; 
+
+        // Copy all index arrays
+        for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ )
+        {
+            const unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex );
+            if ( vertex >= pModel->m_Vertices.size() ) 
+                throw DeadlyImportError( "OBJ: vertex index out of range" );
+            
+            pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
+            
+            // Copy all normals 
+            if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_pNormals->size())
+            {
+                const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
+                if ( normal >= pModel->m_Normals.size() )
+                    throw DeadlyImportError("OBJ: vertex normal index out of range");
+
+                pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
+            }
+            
+            // Copy all texture coordinates
+            if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
+            {
+                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 coordinate index out of range");
+
+                const aiVector3D &coord3d = pModel->m_TextureCoord[ tex ];
                 pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord3d.x, coord3d.y, coord3d.z );
                 pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord3d.x, coord3d.y, coord3d.z );
-			}
-
-			ai_assert( pMesh->mNumVertices > newIndex );
-
-			// Get destination face
-			aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
-
-			const bool last = ( vertexIndex == pSourceFace->m_pVertices->size() - 1 ); 
-			if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) 
-			{
-				pDestFace->mIndices[ outVertexIndex ] = newIndex;
-				outVertexIndex++;
-			}
-
-			if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT) 
-			{
-				outIndex++;
-				outVertexIndex = 0;
-			}
-			else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE) 
-			{
-				outVertexIndex = 0;
-
-				if(!last) 
-					outIndex++;
-
-				if (vertexIndex) {
-					if(!last) {
-						pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
-						if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty()) {
-							pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
-						}
-						if ( !pModel->m_TextureCoord.empty() ) {
-							for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ ) {
-								pMesh->mTextureCoords[ i ][ newIndex+1 ] = pMesh->mTextureCoords[ i ][ newIndex ];
-							}
-						}
-						++newIndex;
-					}
-
-					pDestFace[-1].mIndices[1] = newIndex;
-				}
-			}
-			else if (last) {
-				outIndex++;
-			}
-			++newIndex;
-		}
-	}	
+            }
+
+            ai_assert( pMesh->mNumVertices > newIndex );
+
+            // Get destination face
+            aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
+
+            const bool last = ( vertexIndex == pSourceFace->m_pVertices->size() - 1 ); 
+            if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) 
+            {
+                pDestFace->mIndices[ outVertexIndex ] = newIndex;
+                outVertexIndex++;
+            }
+
+            if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT) 
+            {
+                outIndex++;
+                outVertexIndex = 0;
+            }
+            else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE) 
+            {
+                outVertexIndex = 0;
+
+                if(!last) 
+                    outIndex++;
+
+                if (vertexIndex) {
+                    if(!last) {
+                        pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
+                        if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty()) {
+                            pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
+                        }
+                        if ( !pModel->m_TextureCoord.empty() ) {
+                            for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ ) {
+                                pMesh->mTextureCoords[ i ][ newIndex+1 ] = pMesh->mTextureCoords[ i ][ newIndex ];
+                            }
+                        }
+                        ++newIndex;
+                    }
+
+                    pDestFace[-1].mIndices[1] = newIndex;
+                }
+            }
+            else if (last) {
+                outIndex++;
+            }
+            ++newIndex;
+        }
+    }	
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Counts all stored meshes 
 //	Counts all stored meshes 
 void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes)
 void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes)
 {
 {
-	iNumMeshes = 0;
-	if ( rObjects.empty() )	
-		return;
-
-	iNumMeshes += static_cast<unsigned int>( rObjects.size() );
-	for (std::vector<ObjFile::Object*>::const_iterator it = rObjects.begin();
-		it != rObjects.end(); 
-		++it)
-	{
-		if (!(*it)->m_SubObjects.empty())
-		{
-			countObjects((*it)->m_SubObjects, iNumMeshes);
-		}
-	}
+    iNumMeshes = 0;
+    if ( rObjects.empty() )	
+        return;
+
+    iNumMeshes += static_cast<unsigned int>( rObjects.size() );
+    for (std::vector<ObjFile::Object*>::const_iterator it = rObjects.begin();
+        it != rObjects.end(); 
+        ++it)
+    {
+        if (!(*it)->m_SubObjects.empty())
+        {
+            countObjects((*it)->m_SubObjects, iNumMeshes);
+        }
+    }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	 Add clamp mode property to material if necessary 
 //	 Add clamp mode property to material if necessary 
 void ObjFileImporter::addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode)
 void ObjFileImporter::addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode)
 {
 {
-	ai_assert( NULL != mat);
-	mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0));
-	mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_V(type, 0));
+    ai_assert( NULL != mat);
+    mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0));
+    mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_V(type, 0));
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Creates the material 
 //	Creates the material 
 void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pScene )
 void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pScene )
 {
 {
-	ai_assert( NULL != pScene );
-	if ( NULL == pScene )
-		return;
-
-	const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size();
-	pScene->mNumMaterials = 0;
-	if ( pModel->m_MaterialLib.empty() ) {
-		DefaultLogger::get()->debug("OBJ: no materials specified");
-		return;
-	}
-	
-	pScene->mMaterials = new aiMaterial*[ numMaterials ];
-	for ( unsigned int matIndex = 0; matIndex < numMaterials; matIndex++ )
-	{		
-		// Store material name
-		std::map<std::string, ObjFile::Material*>::const_iterator it;
-		it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] );
-		
-		// No material found, use the default material
-		if ( pModel->m_MaterialMap.end() == it )
-			continue;
-
-		aiMaterial* mat = new aiMaterial;
-		ObjFile::Material *pCurrentMaterial = (*it).second;
-		mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME );
-
-		// convert illumination model
-		int sm = 0;
-		switch (pCurrentMaterial->illumination_model) 
-		{
-		case 0:
-			sm = aiShadingMode_NoShading;
-			break;
-		case 1:
-			sm = aiShadingMode_Gouraud;
-			break;
-		case 2:
-			sm = aiShadingMode_Phong;
-			break;
-		default:
-			sm = aiShadingMode_Gouraud;
-			DefaultLogger::get()->error("OBJ: unexpected illumination model (0-2 recognized)");
-		}
-	
-		mat->AddProperty<int>( &sm, 1, AI_MATKEY_SHADING_MODEL);
-
-		// multiplying the specular exponent with 2 seems to yield better results
-		pCurrentMaterial->shineness *= 4.f;
-
-		// Adding material colors
-		mat->AddProperty( &pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT );
-		mat->AddProperty( &pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
-		mat->AddProperty( &pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR );
-		mat->AddProperty( &pCurrentMaterial->emissive, 1, AI_MATKEY_COLOR_EMISSIVE );
-		mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS );
-		mat->AddProperty( &pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY );
-
-		// Adding refraction index
-		mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI );
-
-		// Adding textures
-		if ( 0 != pCurrentMaterial->texture.length ) 
-		{
-			mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureDiffuseType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_DIFFUSE);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureAmbient.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureAmbientType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_AMBIENT);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureEmissive.length )
-			mat->AddProperty( &pCurrentMaterial->textureEmissive, AI_MATKEY_TEXTURE_EMISSIVE(0));
-
-		if ( 0 != pCurrentMaterial->textureSpecular.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_SPECULAR);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureBump.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_HEIGHT);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureNormal.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_NORMALS);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureDisp.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) );
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureDispType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_DISPLACEMENT);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureOpacity.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureOpacityType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_OPACITY);
-			}
-		}
-
-		if ( 0 != pCurrentMaterial->textureSpecularity.length )
-		{
-			mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0));
-			if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularityType])
-			{
-				addTextureMappingModeProperty(mat, aiTextureType_SHININESS);
-			}
-		}
-		
-		// Store material property info in material array in scene
-		pScene->mMaterials[ pScene->mNumMaterials ] = mat;
-		pScene->mNumMaterials++;
-	}
-	
-	// Test number of created materials.
-	ai_assert( pScene->mNumMaterials == numMaterials );
+    ai_assert( NULL != pScene );
+    if ( NULL == pScene )
+        return;
+
+    const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size();
+    pScene->mNumMaterials = 0;
+    if ( pModel->m_MaterialLib.empty() ) {
+        DefaultLogger::get()->debug("OBJ: no materials specified");
+        return;
+    }
+    
+    pScene->mMaterials = new aiMaterial*[ numMaterials ];
+    for ( unsigned int matIndex = 0; matIndex < numMaterials; matIndex++ )
+    {		
+        // Store material name
+        std::map<std::string, ObjFile::Material*>::const_iterator it;
+        it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] );
+        
+        // No material found, use the default material
+        if ( pModel->m_MaterialMap.end() == it )
+            continue;
+
+        aiMaterial* mat = new aiMaterial;
+        ObjFile::Material *pCurrentMaterial = (*it).second;
+        mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME );
+
+        // convert illumination model
+        int sm = 0;
+        switch (pCurrentMaterial->illumination_model) 
+        {
+        case 0:
+            sm = aiShadingMode_NoShading;
+            break;
+        case 1:
+            sm = aiShadingMode_Gouraud;
+            break;
+        case 2:
+            sm = aiShadingMode_Phong;
+            break;
+        default:
+            sm = aiShadingMode_Gouraud;
+            DefaultLogger::get()->error("OBJ: unexpected illumination model (0-2 recognized)");
+        }
+    
+        mat->AddProperty<int>( &sm, 1, AI_MATKEY_SHADING_MODEL);
+
+        // multiplying the specular exponent with 2 seems to yield better results
+        pCurrentMaterial->shineness *= 4.f;
+
+        // Adding material colors
+        mat->AddProperty( &pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT );
+        mat->AddProperty( &pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
+        mat->AddProperty( &pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR );
+        mat->AddProperty( &pCurrentMaterial->emissive, 1, AI_MATKEY_COLOR_EMISSIVE );
+        mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS );
+        mat->AddProperty( &pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY );
+
+        // Adding refraction index
+        mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI );
+
+        // Adding textures
+        if ( 0 != pCurrentMaterial->texture.length ) 
+        {
+            mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureDiffuseType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_DIFFUSE);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureAmbient.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureAmbientType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_AMBIENT);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureEmissive.length )
+            mat->AddProperty( &pCurrentMaterial->textureEmissive, AI_MATKEY_TEXTURE_EMISSIVE(0));
+
+        if ( 0 != pCurrentMaterial->textureSpecular.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_SPECULAR);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureBump.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_HEIGHT);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureNormal.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_NORMALS);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureDisp.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) );
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureDispType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_DISPLACEMENT);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureOpacity.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureOpacityType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_OPACITY);
+            }
+        }
+
+        if ( 0 != pCurrentMaterial->textureSpecularity.length )
+        {
+            mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0));
+            if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularityType])
+            {
+                addTextureMappingModeProperty(mat, aiTextureType_SHININESS);
+            }
+        }
+        
+        // Store material property info in material array in scene
+        pScene->mMaterials[ pScene->mNumMaterials ] = mat;
+        pScene->mNumMaterials++;
+    }
+    
+    // Test number of created materials.
+    ai_assert( pScene->mNumMaterials == numMaterials );
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //	Appends this node to the parent node
 //	Appends this node to the parent node
 void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
 void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
 {
 {
-	// Checking preconditions
-	ai_assert( NULL != pParent );
-	ai_assert( NULL != pChild );
-
-	// Assign parent to child
-	pChild->mParent = pParent;
-	
-	// If already children was assigned to the parent node, store them in a 
-	std::vector<aiNode*> temp;
-	if (pParent->mChildren != NULL)
-	{
-		ai_assert( 0 != pParent->mNumChildren );
-		for (size_t index = 0; index < pParent->mNumChildren; index++)
-		{
-			temp.push_back(pParent->mChildren [ index ] );
-		}
-		delete [] pParent->mChildren;
-	}
-	
-	// Copy node instances into parent node
-	pParent->mNumChildren++;
-	pParent->mChildren = new aiNode*[ pParent->mNumChildren ];
-	for (size_t index = 0; index < pParent->mNumChildren-1; index++)
-	{
-		pParent->mChildren[ index ] = temp [ index ];
-	}
-	pParent->mChildren[ pParent->mNumChildren-1 ] = pChild;
+    // Checking preconditions
+    ai_assert( NULL != pParent );
+    ai_assert( NULL != pChild );
+
+    // Assign parent to child
+    pChild->mParent = pParent;
+    
+    // If already children was assigned to the parent node, store them in a 
+    std::vector<aiNode*> temp;
+    if (pParent->mChildren != NULL)
+    {
+        ai_assert( 0 != pParent->mNumChildren );
+        for (size_t index = 0; index < pParent->mNumChildren; index++)
+        {
+            temp.push_back(pParent->mChildren [ index ] );
+        }
+        delete [] pParent->mChildren;
+    }
+    
+    // Copy node instances into parent node
+    pParent->mNumChildren++;
+    pParent->mChildren = new aiNode*[ pParent->mNumChildren ];
+    for (size_t index = 0; index < pParent->mNumChildren-1; index++)
+    {
+        pParent->mChildren[ index ] = temp [ index ];
+    }
+    pParent->mChildren[ pParent->mNumChildren-1 ] = pChild;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 37 - 37
code/ObjFileImporter.h

@@ -64,57 +64,57 @@ struct Model;
 class ObjFileImporter : public BaseImporter
 class ObjFileImporter : public BaseImporter
 {	
 {	
 public:
 public:
-	///	\brief	Default constructor
-	ObjFileImporter();
+    ///	\brief	Default constructor
+    ObjFileImporter();
 
 
-	///	\brief	Destructor
-	~ObjFileImporter();
+    ///	\brief	Destructor
+    ~ObjFileImporter();
 
 
 public:
 public:
-	/// \brief	Returns whether the class can handle the format of the given file. 
-	/// \remark	See BaseImporter::CanRead() for details.
-	bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
+    /// \brief	Returns whether the class can handle the format of the given file. 
+    /// \remark	See BaseImporter::CanRead() for details.
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
 
 
 private:
 private:
 
 
-	//! \brief	Appends the supported extension.
-	const aiImporterDesc* GetInfo () const;
+    //! \brief	Appends the supported extension.
+    const aiImporterDesc* GetInfo () const;
 
 
-	//!	\brief	File import implementation.
-	void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
-	
-	//!	\brief	Create the data from imported content.
-	void CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene);
-	
-	//!	\brief	Creates all nodes stored in imported content.
-	aiNode *createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData,
-		aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray);
+    //!	\brief	File import implementation.
+    void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+    
+    //!	\brief	Create the data from imported content.
+    void CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene);
+    
+    //!	\brief	Creates all nodes stored in imported content.
+    aiNode *createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData,
+        aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray);
 
 
-	//!	\brief	Creates topology data like faces and meshes for the geometry.
+    //!	\brief	Creates topology data like faces and meshes for the geometry.
     aiMesh *createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
     aiMesh *createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
-		unsigned int uiMeshIndex );	
-	
-	//!	\brief	Creates vertices from model.
-	void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject,
-		unsigned int uiMeshIndex, aiMesh* pMesh,unsigned int uiIdxCount);
+        unsigned int uiMeshIndex );	
+    
+    //!	\brief	Creates vertices from model.
+    void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject,
+        unsigned int uiMeshIndex, aiMesh* pMesh,unsigned int uiIdxCount);
 
 
-	//!	\brief	Object counter helper method.
-	void countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes);
+    //!	\brief	Object counter helper method.
+    void countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes);
 
 
-	//!	\brief	Material creation.
-	void createMaterials(const ObjFile::Model* pModel, aiScene* pScene);
-	void addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode = 1);
+    //!	\brief	Material creation.
+    void createMaterials(const ObjFile::Model* pModel, aiScene* pScene);
+    void addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode = 1);
 
 
-	//!	\brief	Appends a child node to a parent node and updates the data structures.
-	void appendChildToParentNode(aiNode *pParent, aiNode *pChild);
+    //!	\brief	Appends a child node to a parent node and updates the data structures.
+    void appendChildToParentNode(aiNode *pParent, aiNode *pChild);
 
 
 private:
 private:
-	//!	Data buffer
-	std::vector<char> m_Buffer;
-	//!	Pointer to root object instance
-	ObjFile::Object *m_pRootObject;
-	//!	Absolute pathname of model in file system
-	std::string m_strAbsPath;
+    //!	Data buffer
+    std::vector<char> m_Buffer;
+    //!	Pointer to root object instance
+    ObjFile::Object *m_pRootObject;
+    //!	Absolute pathname of model in file system
+    std::string m_strAbsPath;
 };
 };
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 486 - 486
code/ObjFileParser.cpp

@@ -57,177 +57,177 @@ const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME;
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Constructor with loaded data and directories.
 //	Constructor with loaded data and directories.
 ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem *io ) :
 ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem *io ) :
-	m_DataIt(Data.begin()),
-	m_DataItEnd(Data.end()),
-	m_pModel(NULL),
-	m_uiLine(0),
-	m_pIO( io )
+    m_DataIt(Data.begin()),
+    m_DataItEnd(Data.end()),
+    m_pModel(NULL),
+    m_uiLine(0),
+    m_pIO( io )
 {
 {
-	std::fill_n(m_buffer,BUFFERSIZE,0);
+    std::fill_n(m_buffer,BUFFERSIZE,0);
 
 
-	// Create the model instance to store all the data
-	m_pModel = new ObjFile::Model();
-	m_pModel->m_ModelName = strModelName;
-	
+    // Create the model instance to store all the data
+    m_pModel = new ObjFile::Model();
+    m_pModel->m_ModelName = strModelName;
+    
     // create default material and store it
     // create default material and store it
-	m_pModel->m_pDefaultMaterial = new ObjFile::Material();
-	m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL );
+    m_pModel->m_pDefaultMaterial = new ObjFile::Material();
+    m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL );
     m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL );
     m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL );
-	m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
-	
-	// Start parsing the file
-	parseFile();
+    m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
+    
+    // Start parsing the file
+    parseFile();
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Destructor
 //	Destructor
 ObjFileParser::~ObjFileParser()
 ObjFileParser::~ObjFileParser()
 {
 {
-	delete m_pModel;
-	m_pModel = NULL;
+    delete m_pModel;
+    m_pModel = NULL;
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Returns a pointer to the model instance.
 //	Returns a pointer to the model instance.
 ObjFile::Model *ObjFileParser::GetModel() const
 ObjFile::Model *ObjFileParser::GetModel() const
 {
 {
-	return m_pModel;
+    return m_pModel;
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	File parsing method.
 //	File parsing method.
 void ObjFileParser::parseFile()
 void ObjFileParser::parseFile()
 {
 {
-	if (m_DataIt == m_DataItEnd)
-		return;
-
-	while (m_DataIt != m_DataItEnd)
-	{
-		switch (*m_DataIt)
-		{
-		case 'v': // Parse a vertex texture coordinate
-			{
-				++m_DataIt;
-				if (*m_DataIt == ' ' || *m_DataIt == '\t') {
-					// read in vertex definition
-					getVector3(m_pModel->m_Vertices);
-				} else if (*m_DataIt == 't') {
-					// read in texture coordinate ( 2D or 3D )
+    if (m_DataIt == m_DataItEnd)
+        return;
+
+    while (m_DataIt != m_DataItEnd)
+    {
+        switch (*m_DataIt)
+        {
+        case 'v': // Parse a vertex texture coordinate
+            {
+                ++m_DataIt;
+                if (*m_DataIt == ' ' || *m_DataIt == '\t') {
+                    // read in vertex definition
+                    getVector3(m_pModel->m_Vertices);
+                } else if (*m_DataIt == 't') {
+                    // read in texture coordinate ( 2D or 3D )
                                         ++m_DataIt;
                                         ++m_DataIt;
                                         getVector( m_pModel->m_TextureCoord );
                                         getVector( m_pModel->m_TextureCoord );
-				} else if (*m_DataIt == 'n') {
-					// Read in normal vector definition
-					++m_DataIt;
-					getVector3( m_pModel->m_Normals );
-				}
-			}
-			break;
-
-		case 'p': // Parse a face, line or point statement
-		case 'l':
-		case 'f':
-			{
-				getFace(*m_DataIt == 'f' ? aiPrimitiveType_POLYGON : (*m_DataIt == 'l' 
-					? aiPrimitiveType_LINE : aiPrimitiveType_POINT));
-			}
-			break;
-
-		case '#': // Parse a comment
-			{
-				getComment();
-			}
-			break;
-
-		case 'u': // Parse a material desc. setter
-			{
-				getMaterialDesc();
-			}
-			break;
-
-		case 'm': // Parse a material library or merging group ('mg')
-			{
-				if (*(m_DataIt + 1) == 'g')
-					getGroupNumberAndResolution();
-				else
-					getMaterialLib();
-			}
-			break;
-
-		case 'g': // Parse group name
-			{
-				getGroupName();
-			}
-			break;
-
-		case 's': // Parse group number
-			{
-				getGroupNumber();
-			}
-			break;
-
-		case 'o': // Parse object name
-			{
-				getObjectName();
-			}
-			break;
-		
-		default:
-			{
-				m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
-			}
-			break;
-		}
-	}
+                } else if (*m_DataIt == 'n') {
+                    // Read in normal vector definition
+                    ++m_DataIt;
+                    getVector3( m_pModel->m_Normals );
+                }
+            }
+            break;
+
+        case 'p': // Parse a face, line or point statement
+        case 'l':
+        case 'f':
+            {
+                getFace(*m_DataIt == 'f' ? aiPrimitiveType_POLYGON : (*m_DataIt == 'l' 
+                    ? aiPrimitiveType_LINE : aiPrimitiveType_POINT));
+            }
+            break;
+
+        case '#': // Parse a comment
+            {
+                getComment();
+            }
+            break;
+
+        case 'u': // Parse a material desc. setter
+            {
+                getMaterialDesc();
+            }
+            break;
+
+        case 'm': // Parse a material library or merging group ('mg')
+            {
+                if (*(m_DataIt + 1) == 'g')
+                    getGroupNumberAndResolution();
+                else
+                    getMaterialLib();
+            }
+            break;
+
+        case 'g': // Parse group name
+            {
+                getGroupName();
+            }
+            break;
+
+        case 's': // Parse group number
+            {
+                getGroupNumber();
+            }
+            break;
+
+        case 'o': // Parse object name
+            {
+                getObjectName();
+            }
+            break;
+        
+        default:
+            {
+                m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+            }
+            break;
+        }
+    }
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Copy the next word in a temporary buffer
 //	Copy the next word in a temporary buffer
 void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
 void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
 {
 {
-	size_t index = 0;
-	m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
+    size_t index = 0;
+    m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
-		pBuffer[index] = *m_DataIt;
-		index++;
+        pBuffer[index] = *m_DataIt;
+        index++;
         if( index == length - 1 ) {
         if( index == length - 1 ) {
             break;
             break;
         }
         }
-		++m_DataIt;
-	}
+        ++m_DataIt;
+    }
 
 
-	ai_assert(index < length);
-	pBuffer[index] = '\0';
+    ai_assert(index < length);
+    pBuffer[index] = '\0';
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 // 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 = 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) 
-	{
-		const char c = *m_DataIt;
-		if (c == '\\') {
-			continuation = true;
-			continue;
-		}
-		
-		if (c == '\n' || c == '\r') {
-			if(continuation) {
-				pBuffer[ index++ ] = ' ';
-				continue;
-			}
-			break;
-		}
-
-		continuation = false;
-		pBuffer[ index++ ] = c;
-	}
-	ai_assert(index < length);
-	pBuffer[ index ] = '\0';
+    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) 
+    {
+        const char c = *m_DataIt;
+        if (c == '\\') {
+            continuation = true;
+            continue;
+        }
+        
+        if (c == '\n' || c == '\r') {
+            if(continuation) {
+                pBuffer[ index++ ] = ' ';
+                continue;
+            }
+            break;
+        }
+
+        continuation = false;
+        pBuffer[ index++ ] = c;
+    }
+    ai_assert(index < length);
+    pBuffer[ index ] = '\0';
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
@@ -268,391 +268,391 @@ void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get values for a new 3D vector instance
 //	Get values for a new 3D vector instance
 void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) {
 void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) {
-	float x, y, z;
-	copyNextWord(m_buffer, BUFFERSIZE);
-	x = (float) fast_atof(m_buffer);	
-	
-	copyNextWord(m_buffer, BUFFERSIZE);
-	y = (float) fast_atof(m_buffer);
+    float x, y, z;
+    copyNextWord(m_buffer, BUFFERSIZE);
+    x = (float) fast_atof(m_buffer);	
+    
+    copyNextWord(m_buffer, BUFFERSIZE);
+    y = (float) fast_atof(m_buffer);
 
 
     copyNextWord( m_buffer, BUFFERSIZE );
     copyNextWord( m_buffer, BUFFERSIZE );
     z = ( float ) fast_atof( m_buffer );
     z = ( float ) fast_atof( m_buffer );
 
 
-	point3d_array.push_back( aiVector3D( x, y, z ) );
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    point3d_array.push_back( aiVector3D( x, y, z ) );
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get values for a new 2D vector instance
 //	Get values for a new 2D vector instance
 void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
 void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
-	float x, y;
-	copyNextWord(m_buffer, BUFFERSIZE);
-	x = (float) fast_atof(m_buffer);	
-	
-	copyNextWord(m_buffer, BUFFERSIZE);
-	y = (float) fast_atof(m_buffer);
+    float x, y;
+    copyNextWord(m_buffer, BUFFERSIZE);
+    x = (float) fast_atof(m_buffer);	
+    
+    copyNextWord(m_buffer, BUFFERSIZE);
+    y = (float) fast_atof(m_buffer);
 
 
-	point2d_array.push_back(aiVector2D(x, y));
+    point2d_array.push_back(aiVector2D(x, y));
 
 
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get values for a new face instance
 //	Get values for a new face instance
 void ObjFileParser::getFace(aiPrimitiveType type)
 void ObjFileParser::getFace(aiPrimitiveType type)
 {
 {
-	copyNextLine(m_buffer, BUFFERSIZE);
-	if (m_DataIt == m_DataItEnd)
-		return;
-
-	char *pPtr = m_buffer;
-	char *pEnd = &pPtr[BUFFERSIZE];
-	pPtr = getNextToken<char*>(pPtr, pEnd);
-	if (pPtr == pEnd || *pPtr == '\0')
-		return;
-
-	std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
-	std::vector<unsigned int> *pTexID = new std::vector<unsigned int>;
-	std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
-	bool hasNormal = false;
-
-	const int vSize = m_pModel->m_Vertices.size();
-	const int vtSize = m_pModel->m_TextureCoord.size();
-	const int vnSize = m_pModel->m_Normals.size();
-
-	const bool vt = (!m_pModel->m_TextureCoord.empty());
-	const bool vn = (!m_pModel->m_Normals.empty());
-	int iStep = 0, iPos = 0;
-	while (pPtr != pEnd)
-	{
-		iStep = 1;
-
-		if (IsLineEnd(*pPtr))
-			break;
-
-		if (*pPtr=='/' )
-		{
-			if (type == aiPrimitiveType_POINT) {
-				DefaultLogger::get()->error("Obj: Separator unexpected in point statement");
-			}
-			if (iPos == 0)
-			{
-				//if there are no texture coordinates in the file, but normals
-				if (!vt && vn) {
-					iPos = 1;
-					iStep++;
-				}
-			}
-			iPos++;
-		}
+    copyNextLine(m_buffer, BUFFERSIZE);
+    if (m_DataIt == m_DataItEnd)
+        return;
+
+    char *pPtr = m_buffer;
+    char *pEnd = &pPtr[BUFFERSIZE];
+    pPtr = getNextToken<char*>(pPtr, pEnd);
+    if (pPtr == pEnd || *pPtr == '\0')
+        return;
+
+    std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
+    std::vector<unsigned int> *pTexID = new std::vector<unsigned int>;
+    std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
+    bool hasNormal = false;
+
+    const int vSize = m_pModel->m_Vertices.size();
+    const int vtSize = m_pModel->m_TextureCoord.size();
+    const int vnSize = m_pModel->m_Normals.size();
+
+    const bool vt = (!m_pModel->m_TextureCoord.empty());
+    const bool vn = (!m_pModel->m_Normals.empty());
+    int iStep = 0, iPos = 0;
+    while (pPtr != pEnd)
+    {
+        iStep = 1;
+
+        if (IsLineEnd(*pPtr))
+            break;
+
+        if (*pPtr=='/' )
+        {
+            if (type == aiPrimitiveType_POINT) {
+                DefaultLogger::get()->error("Obj: Separator unexpected in point statement");
+            }
+            if (iPos == 0)
+            {
+                //if there are no texture coordinates in the file, but normals
+                if (!vt && vn) {
+                    iPos = 1;
+                    iStep++;
+                }
+            }
+            iPos++;
+        }
         else if( IsSpaceOrNewLine( *pPtr ) )
         else if( IsSpaceOrNewLine( *pPtr ) )
-		{
-			iPos = 0;
-		}
-		else 
-		{
-			//OBJ USES 1 Base ARRAYS!!!!
-			const int iVal = atoi( pPtr );
-
-			// increment iStep position based off of the sign and # of digits
-			int tmp = iVal;
-			if (iVal < 0)
-			    ++iStep;
-			while ( ( tmp = tmp / 10 )!=0 )
-				++iStep;
-
-			if ( iVal > 0 )
-			{
-				// Store parsed index
-				if ( 0 == iPos )
-				{
-					pIndices->push_back( iVal-1 );
-				}
-				else if ( 1 == iPos )
-				{	
-					pTexID->push_back( iVal-1 );
-				}
-				else if ( 2 == iPos )
-				{
-					pNormalID->push_back( iVal-1 );
-					hasNormal = true;
-				}
-				else
-				{
-					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;
-	}
-
-	if ( pIndices->empty() ) 
-	{
-		DefaultLogger::get()->error("Obj: Ignoring empty face");
-		m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
-		return;
-	}
-
-	ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type );
-	
-	// Set active material, if one set
-	if (NULL != m_pModel->m_pCurrentMaterial) 
-		face->m_pMaterial = m_pModel->m_pCurrentMaterial;
-	else 
-		face->m_pMaterial = m_pModel->m_pDefaultMaterial;
-
-	// Create a default object, if nothing is there
-	if ( NULL == m_pModel->m_pCurrent )
-		createObject( "defaultobject" );
-	
-	// Assign face to mesh
-	if ( NULL == m_pModel->m_pCurrentMesh )
-	{
-		createMesh();
-	}
-	
-	// Store the face
-	m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
-	m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size();
-	m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size(); 
-	if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) 
-	{
-		m_pModel->m_pCurrentMesh->m_hasNormals = true;
-	}
-	// Skip the rest of the line
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+        {
+            iPos = 0;
+        }
+        else 
+        {
+            //OBJ USES 1 Base ARRAYS!!!!
+            const int iVal = atoi( pPtr );
+
+            // increment iStep position based off of the sign and # of digits
+            int tmp = iVal;
+            if (iVal < 0)
+                ++iStep;
+            while ( ( tmp = tmp / 10 )!=0 )
+                ++iStep;
+
+            if ( iVal > 0 )
+            {
+                // Store parsed index
+                if ( 0 == iPos )
+                {
+                    pIndices->push_back( iVal-1 );
+                }
+                else if ( 1 == iPos )
+                {	
+                    pTexID->push_back( iVal-1 );
+                }
+                else if ( 2 == iPos )
+                {
+                    pNormalID->push_back( iVal-1 );
+                    hasNormal = true;
+                }
+                else
+                {
+                    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;
+    }
+
+    if ( pIndices->empty() ) 
+    {
+        DefaultLogger::get()->error("Obj: Ignoring empty face");
+        m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+        return;
+    }
+
+    ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type );
+    
+    // Set active material, if one set
+    if (NULL != m_pModel->m_pCurrentMaterial) 
+        face->m_pMaterial = m_pModel->m_pCurrentMaterial;
+    else 
+        face->m_pMaterial = m_pModel->m_pDefaultMaterial;
+
+    // Create a default object, if nothing is there
+    if ( NULL == m_pModel->m_pCurrent )
+        createObject( "defaultobject" );
+    
+    // Assign face to mesh
+    if ( NULL == m_pModel->m_pCurrentMesh )
+    {
+        createMesh();
+    }
+    
+    // Store the face
+    m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
+    m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size();
+    m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size(); 
+    if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) 
+    {
+        m_pModel->m_pCurrentMesh->m_hasNormals = true;
+    }
+    // Skip the rest of the line
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get values for a new material description
 //	Get values for a new material description
 void ObjFileParser::getMaterialDesc()
 void ObjFileParser::getMaterialDesc()
 {
 {
-	// Each material request a new object.
-	// Sometimes the object is already created (see 'o' tag by example), but it is not initialized !
-	// So, we create a new object only if the current on is already initialized !
-	if (m_pModel->m_pCurrent != NULL &&
-		(	m_pModel->m_pCurrent->m_Meshes.size() > 1 ||
-			(m_pModel->m_pCurrent->m_Meshes.size() == 1 && m_pModel->m_Meshes[m_pModel->m_pCurrent->m_Meshes[0]]->m_Faces.size() != 0)	)
-		)
-		m_pModel->m_pCurrent = NULL;
-
-	// Get next data for material data
-	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
-	if (m_DataIt == m_DataItEnd)
-		return;
-
-	char *pStart = &(*m_DataIt);
+    // Each material request a new object.
+    // Sometimes the object is already created (see 'o' tag by example), but it is not initialized !
+    // So, we create a new object only if the current on is already initialized !
+    if (m_pModel->m_pCurrent != NULL &&
+        (	m_pModel->m_pCurrent->m_Meshes.size() > 1 ||
+            (m_pModel->m_pCurrent->m_Meshes.size() == 1 && m_pModel->m_Meshes[m_pModel->m_pCurrent->m_Meshes[0]]->m_Faces.size() != 0)	)
+        )
+        m_pModel->m_pCurrent = NULL;
+
+    // Get next data for material data
+    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+    if (m_DataIt == m_DataItEnd)
+        return;
+
+    char *pStart = &(*m_DataIt);
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
         ++m_DataIt;
         ++m_DataIt;
     }
     }
 
 
-	// Get name
-	std::string strName(pStart, &(*m_DataIt));
-	if ( strName.empty())
-		return;
-
-	// Search for material
-	std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
-	if ( it == m_pModel->m_MaterialMap.end() )
-	{
-		// Not found, use default material
-		m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
-		DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
-	}
-	else
-	{
-		// Found, using detected material
-		m_pModel->m_pCurrentMaterial = (*it).second;
-		if ( needsNewMesh( strName ))
-		{
-			createMesh();	
-		}
-		m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName );
-	}
-
-	// Skip rest of line
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    // Get name
+    std::string strName(pStart, &(*m_DataIt));
+    if ( strName.empty())
+        return;
+
+    // Search for material
+    std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
+    if ( it == m_pModel->m_MaterialMap.end() )
+    {
+        // Not found, use default material
+        m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
+        DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
+    }
+    else
+    {
+        // Found, using detected material
+        m_pModel->m_pCurrentMaterial = (*it).second;
+        if ( needsNewMesh( strName ))
+        {
+            createMesh();	
+        }
+        m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName );
+    }
+
+    // Skip rest of line
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get a comment, values will be skipped
 //	Get a comment, values will be skipped
 void ObjFileParser::getComment()
 void ObjFileParser::getComment()
 {
 {
-	while (m_DataIt != m_DataItEnd)
-	{
-		if ( '\n' == (*m_DataIt))
-		{
-			++m_DataIt;
-			break;
-		}
-		else
-		{
-			++m_DataIt;
-		}
-	}
+    while (m_DataIt != m_DataItEnd)
+    {
+        if ( '\n' == (*m_DataIt))
+        {
+            ++m_DataIt;
+            break;
+        }
+        else
+        {
+            ++m_DataIt;
+        }
+    }
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Get material library from file.
 //	Get material library from file.
 void ObjFileParser::getMaterialLib()
 void ObjFileParser::getMaterialLib()
 {
 {
-	// Translate tuple
-	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+    // Translate tuple
+    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
     if( m_DataIt == m_DataItEnd ) {
     if( m_DataIt == m_DataItEnd ) {
         return;
         return;
     }
     }
-	
-	char *pStart = &(*m_DataIt);
+    
+    char *pStart = &(*m_DataIt);
     while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
     while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
         ++m_DataIt;
         ++m_DataIt;
     }
     }
 
 
-	// Check for existence
-	const std::string strMatName(pStart, &(*m_DataIt));
-	IOStream *pFile = m_pIO->Open(strMatName);
+    // Check for existence
+    const std::string strMatName(pStart, &(*m_DataIt));
+    IOStream *pFile = m_pIO->Open(strMatName);
 
 
-	if (!pFile )
-	{
-		DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
-		m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
-		return;
-	}
+    if (!pFile )
+    {
+        DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
+        m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+        return;
+    }
 
 
-	// Import material library data from file
-	std::vector<char> buffer;
-	BaseImporter::TextFileToBuffer(pFile,buffer);
-	m_pIO->Close( pFile );
+    // Import material library data from file
+    std::vector<char> buffer;
+    BaseImporter::TextFileToBuffer(pFile,buffer);
+    m_pIO->Close( pFile );
 
 
-	// Importing the material library 
-	ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel );			
+    // Importing the material library 
+    ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel );			
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Set a new material definition as the current material.
 //	Set a new material definition as the current material.
 void ObjFileParser::getNewMaterial()
 void ObjFileParser::getNewMaterial()
 {
 {
-	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
-	m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
+    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+    m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
     if( m_DataIt == m_DataItEnd ) {
     if( m_DataIt == m_DataItEnd ) {
         return;
         return;
     }
     }
 
 
-	char *pStart = &(*m_DataIt);
-	std::string strMat( pStart, *m_DataIt );
+    char *pStart = &(*m_DataIt);
+    std::string strMat( pStart, *m_DataIt );
     while( m_DataIt != m_DataItEnd && IsSpaceOrNewLine( *m_DataIt ) ) {
     while( m_DataIt != m_DataItEnd && IsSpaceOrNewLine( *m_DataIt ) ) {
         ++m_DataIt;
         ++m_DataIt;
     }
     }
-	std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
-	if ( it == m_pModel->m_MaterialMap.end() )
-	{
-		// Show a warning, if material was not found
-		DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat);
-		m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
-	}
-	else
-	{
-		// Set new material
-		if ( needsNewMesh( strMat ) )
-		{
-			createMesh();	
-		}
-		m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat );
-	}
-
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
+    if ( it == m_pModel->m_MaterialMap.end() )
+    {
+        // Show a warning, if material was not found
+        DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat);
+        m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
+    }
+    else
+    {
+        // Set new material
+        if ( needsNewMesh( strMat ) )
+        {
+            createMesh();	
+        }
+        m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat );
+    }
+
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
 int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
 {
 {
-	int mat_index = -1;
+    int mat_index = -1;
     if( strMaterialName.empty() ) {
     if( strMaterialName.empty() ) {
         return mat_index;
         return mat_index;
     }
     }
-	for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
-	{
-		if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
-		{
-			mat_index = (int)index;
-			break;
-		}
-	}
-	return mat_index;
+    for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
+    {
+        if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
+        {
+            mat_index = (int)index;
+            break;
+        }
+    }
+    return mat_index;
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Getter for a group name.  
 //	Getter for a group name.  
 void ObjFileParser::getGroupName()
 void ObjFileParser::getGroupName()
 {
 {
-	std::string strGroupName;
+    std::string strGroupName;
    
    
-	m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
+    m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
     if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) {
     if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) {
         return;
         return;
     }
     }
 
 
-	// Change active group, if necessary
-	if ( m_pModel->m_strActiveGroup != strGroupName )
-	{
-		// Search for already existing entry
-		ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(strGroupName);
-		
-		// We are mapping groups into the object structure
-		createObject( strGroupName );
-		
-		// New group name, creating a new entry
-		if (it == m_pModel->m_Groups.end())
-		{
-			std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
-			m_pModel->m_Groups[ strGroupName ] = pFaceIDArray;
-			m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
-		}
-		else
-		{
-			m_pModel->m_pGroupFaceIDs = (*it).second;
-		}
-		m_pModel->m_strActiveGroup = strGroupName;
-	}
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    // Change active group, if necessary
+    if ( m_pModel->m_strActiveGroup != strGroupName )
+    {
+        // Search for already existing entry
+        ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(strGroupName);
+        
+        // We are mapping groups into the object structure
+        createObject( strGroupName );
+        
+        // New group name, creating a new entry
+        if (it == m_pModel->m_Groups.end())
+        {
+            std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
+            m_pModel->m_Groups[ strGroupName ] = pFaceIDArray;
+            m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
+        }
+        else
+        {
+            m_pModel->m_pGroupFaceIDs = (*it).second;
+        }
+        m_pModel->m_strActiveGroup = strGroupName;
+    }
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Not supported
 //	Not supported
 void ObjFileParser::getGroupNumber()
 void ObjFileParser::getGroupNumber()
 {
 {
-	// Not used
+    // Not used
 
 
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Not supported
 //	Not supported
 void ObjFileParser::getGroupNumberAndResolution()
 void ObjFileParser::getGroupNumberAndResolution()
 {
 {
-	// Not used
+    // Not used
 
 
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
@@ -660,105 +660,105 @@ void ObjFileParser::getGroupNumberAndResolution()
 //	identify it.
 //	identify it.
 void ObjFileParser::getObjectName()
 void ObjFileParser::getObjectName()
 {
 {
-	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
     if( m_DataIt == m_DataItEnd ) {
     if( m_DataIt == m_DataItEnd ) {
         return;
         return;
     }
     }
-	char *pStart = &(*m_DataIt);
+    char *pStart = &(*m_DataIt);
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
         ++m_DataIt;
         ++m_DataIt;
     }
     }
 
 
-	std::string strObjectName(pStart, &(*m_DataIt));
-	if (!strObjectName.empty()) 
-	{
-		// Reset current object
-		m_pModel->m_pCurrent = NULL;
-		
-		// Search for actual object
-		for (std::vector<ObjFile::Object*>::const_iterator it = m_pModel->m_Objects.begin();
-			it != m_pModel->m_Objects.end();
-			++it)
-		{
-			if ((*it)->m_strObjName == strObjectName)
-			{
-				m_pModel->m_pCurrent = *it;
-				break;
-			}
-		}
-
-		// Allocate a new object, if current one was not found before
+    std::string strObjectName(pStart, &(*m_DataIt));
+    if (!strObjectName.empty()) 
+    {
+        // Reset current object
+        m_pModel->m_pCurrent = NULL;
+        
+        // Search for actual object
+        for (std::vector<ObjFile::Object*>::const_iterator it = m_pModel->m_Objects.begin();
+            it != m_pModel->m_Objects.end();
+            ++it)
+        {
+            if ((*it)->m_strObjName == strObjectName)
+            {
+                m_pModel->m_pCurrent = *it;
+                break;
+            }
+        }
+
+        // Allocate a new object, if current one was not found before
         if( NULL == m_pModel->m_pCurrent ) {
         if( NULL == m_pModel->m_pCurrent ) {
             createObject( strObjectName );
             createObject( strObjectName );
         }
         }
-	}
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    }
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Creates a new object instance
 //	Creates a new object instance
 void ObjFileParser::createObject(const std::string &strObjectName)
 void ObjFileParser::createObject(const std::string &strObjectName)
 {
 {
-	ai_assert( NULL != m_pModel );
-	//ai_assert( !strObjectName.empty() );
-
-	m_pModel->m_pCurrent = new ObjFile::Object;
-	m_pModel->m_pCurrent->m_strObjName = strObjectName;
-	m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
-	
-	createMesh();
-
-	if( m_pModel->m_pCurrentMaterial )
-	{
-		m_pModel->m_pCurrentMesh->m_uiMaterialIndex = 
-			getMaterialIndex( m_pModel->m_pCurrentMaterial->MaterialName.data );
-		m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial;
-	}		
+    ai_assert( NULL != m_pModel );
+    //ai_assert( !strObjectName.empty() );
+
+    m_pModel->m_pCurrent = new ObjFile::Object;
+    m_pModel->m_pCurrent->m_strObjName = strObjectName;
+    m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
+    
+    createMesh();
+
+    if( m_pModel->m_pCurrentMaterial )
+    {
+        m_pModel->m_pCurrentMesh->m_uiMaterialIndex = 
+            getMaterialIndex( m_pModel->m_pCurrentMaterial->MaterialName.data );
+        m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial;
+    }		
 }
 }
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Creates a new mesh
 //	Creates a new mesh
 void ObjFileParser::createMesh()
 void ObjFileParser::createMesh()
 {
 {
-	ai_assert( NULL != m_pModel );
-	m_pModel->m_pCurrentMesh = new ObjFile::Mesh;
-	m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh );
-	unsigned int meshId = m_pModel->m_Meshes.size()-1;
-	if ( NULL != m_pModel->m_pCurrent )
-	{
-		m_pModel->m_pCurrent->m_Meshes.push_back( meshId );
-	}
-	else
-	{
-		DefaultLogger::get()->error("OBJ: No object detected to attach a new mesh instance.");
-	}
+    ai_assert( NULL != m_pModel );
+    m_pModel->m_pCurrentMesh = new ObjFile::Mesh;
+    m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh );
+    unsigned int meshId = m_pModel->m_Meshes.size()-1;
+    if ( NULL != m_pModel->m_pCurrent )
+    {
+        m_pModel->m_pCurrent->m_Meshes.push_back( meshId );
+    }
+    else
+    {
+        DefaultLogger::get()->error("OBJ: No object detected to attach a new mesh instance.");
+    }
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Returns true, if a new mesh must be created.
 //	Returns true, if a new mesh must be created.
 bool ObjFileParser::needsNewMesh( const std::string &rMaterialName )
 bool ObjFileParser::needsNewMesh( const std::string &rMaterialName )
 {
 {
-	if(m_pModel->m_pCurrentMesh == 0)
-	{
-		// No mesh data yet
-		return true;
-	}
-	bool newMat = false;
-	int matIdx = getMaterialIndex( rMaterialName );
-	int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
-	if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) || curMatIdx != matIdx )
-	{
-		// New material -> only one material per mesh, so we need to create a new 
-		// material
-		newMat = true;
-	}
-	return newMat;
+    if(m_pModel->m_pCurrentMesh == 0)
+    {
+        // No mesh data yet
+        return true;
+    }
+    bool newMat = false;
+    int matIdx = getMaterialIndex( rMaterialName );
+    int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
+    if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) || curMatIdx != matIdx )
+    {
+        // New material -> only one material per mesh, so we need to create a new 
+        // material
+        newMat = true;
+    }
+    return newMat;
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //	Shows an error in parsing process.
 //	Shows an error in parsing process.
 void ObjFileParser::reportErrorTokenInFace()
 void ObjFileParser::reportErrorTokenInFace()
 {		
 {		
-	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
-	DefaultLogger::get()->error("OBJ: Not supported token in face description detected");
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+    DefaultLogger::get()->error("OBJ: Not supported token in face description detected");
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------

+ 59 - 59
code/ObjFileParser.h

@@ -63,76 +63,76 @@ class IOSystem;
 class ObjFileParser
 class ObjFileParser
 {
 {
 public:
 public:
-	static const size_t BUFFERSIZE = 4096;
-	typedef std::vector<char> DataArray;
-	typedef std::vector<char>::iterator DataArrayIt;
-	typedef std::vector<char>::const_iterator ConstDataArrayIt;
+    static const size_t BUFFERSIZE = 4096;
+    typedef std::vector<char> DataArray;
+    typedef std::vector<char>::iterator DataArrayIt;
+    typedef std::vector<char>::const_iterator ConstDataArrayIt;
 
 
 public:
 public:
-	///	\brief	Constructor with data array.
-	ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem* io);
-	///	\brief	Destructor
-	~ObjFileParser();
-	///	\brief	Model getter.
-	ObjFile::Model *GetModel() const;
+    ///	\brief	Constructor with data array.
+    ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem* io);
+    ///	\brief	Destructor
+    ~ObjFileParser();
+    ///	\brief	Model getter.
+    ObjFile::Model *GetModel() const;
 
 
 private:
 private:
-	///	Parse the loaded file
-	void parseFile();
-	///	Method to copy the new delimited word in the current line.
-	void copyNextWord(char *pBuffer, size_t length);
-	///	Method to copy the new line.
-	void copyNextLine(char *pBuffer, size_t length);
+    ///	Parse the loaded file
+    void parseFile();
+    ///	Method to copy the new delimited word in the current line.
+    void copyNextWord(char *pBuffer, size_t length);
+    ///	Method to copy the new line.
+    void copyNextLine(char *pBuffer, size_t length);
     /// Stores the vector 
     /// Stores the vector 
     void getVector( std::vector<aiVector3D> &point3d_array );
     void getVector( std::vector<aiVector3D> &point3d_array );
     ///	Stores the following 3d vector.
     ///	Stores the following 3d vector.
-	void getVector3( std::vector<aiVector3D> &point3d_array );
-	///	Stores the following 3d vector.
-	void getVector2(std::vector<aiVector2D> &point2d_array);
+    void getVector3( std::vector<aiVector3D> &point3d_array );
+    ///	Stores the following 3d vector.
+    void getVector2(std::vector<aiVector2D> &point2d_array);
     ///	Stores the following face.
     ///	Stores the following face.
-	void getFace(aiPrimitiveType type);
-	/// Reads the material description.
+    void getFace(aiPrimitiveType type);
+    /// Reads the material description.
     void getMaterialDesc();
     void getMaterialDesc();
-	///	Gets a comment.
-	void getComment();
-	/// Gets a a material library.
-	void getMaterialLib();
-	/// Creates a new material.
-	void getNewMaterial();
-	/// Gets the group name from file.
-	void getGroupName();
-	/// Gets the group number from file.
-	void getGroupNumber();
-	/// Gets the group number and resolution from file.
-	void getGroupNumberAndResolution();
-	/// Returns the index of the material. Is -1 if not material was found.
-	int getMaterialIndex( const std::string &strMaterialName );
-	/// Parse object name
-	void getObjectName();
-	/// Creates a new object.
-	void createObject(const std::string &strObjectName);
-	///	Creates a new mesh.
-	void createMesh(); 
-	///	Returns true, if a new mesh instance must be created.
-	bool needsNewMesh( const std::string &rMaterialName );
-	///	Error report in token
-	void reportErrorTokenInFace();
+    ///	Gets a comment.
+    void getComment();
+    /// Gets a a material library.
+    void getMaterialLib();
+    /// Creates a new material.
+    void getNewMaterial();
+    /// Gets the group name from file.
+    void getGroupName();
+    /// Gets the group number from file.
+    void getGroupNumber();
+    /// Gets the group number and resolution from file.
+    void getGroupNumberAndResolution();
+    /// Returns the index of the material. Is -1 if not material was found.
+    int getMaterialIndex( const std::string &strMaterialName );
+    /// Parse object name
+    void getObjectName();
+    /// Creates a new object.
+    void createObject(const std::string &strObjectName);
+    ///	Creates a new mesh.
+    void createMesh(); 
+    ///	Returns true, if a new mesh instance must be created.
+    bool needsNewMesh( const std::string &rMaterialName );
+    ///	Error report in token
+    void reportErrorTokenInFace();
 
 
 private:
 private:
-	///	Default material name
-	static const std::string DEFAULT_MATERIAL;
-	//!	Iterator to current position in buffer
-	DataArrayIt m_DataIt;
-	//!	Iterator to end position of buffer
-	DataArrayIt m_DataItEnd;
-	//!	Pointer to model instance
-	ObjFile::Model *m_pModel;
-	//!	Current line (for debugging)
-	unsigned int m_uiLine;
-	//!	Helper buffer
-	char m_buffer[BUFFERSIZE];
-	///	Pointer to IO system instance.
-	IOSystem *m_pIO;
+    ///	Default material name
+    static const std::string DEFAULT_MATERIAL;
+    //!	Iterator to current position in buffer
+    DataArrayIt m_DataIt;
+    //!	Iterator to end position of buffer
+    DataArrayIt m_DataItEnd;
+    //!	Pointer to model instance
+    ObjFile::Model *m_pModel;
+    //!	Current line (for debugging)
+    unsigned int m_uiLine;
+    //!	Helper buffer
+    char m_buffer[BUFFERSIZE];
+    ///	Pointer to IO system instance.
+    IOSystem *m_pIO;
 };
 };
 
 
 }	// Namespace Assimp
 }	// Namespace Assimp

+ 50 - 50
code/OgreImporter.h

@@ -36,63 +36,63 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
-*/
-
+*/
+
 #ifndef AI_OGREIMPORTER_H_INC
 #ifndef AI_OGREIMPORTER_H_INC
 #define AI_OGREIMPORTER_H_INC
 #define AI_OGREIMPORTER_H_INC
 
 
 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
-
-#include "BaseImporter.h"
-
-#include "OgreStructs.h"
-#include "OgreParsingUtils.h"
-
-namespace Assimp
-{
-namespace Ogre
-{
-
+
+#include "BaseImporter.h"
+
+#include "OgreStructs.h"
+#include "OgreParsingUtils.h"
+
+namespace Assimp
+{
+namespace Ogre
+{
+
 /**	Importer for Ogre mesh, skeleton and material formats.
 /**	Importer for Ogre mesh, skeleton and material formats.
-	@todo Support vertex colors.
-	@todo Support poses/animations from the mesh file. 
-	Currently only skeleton file animations are supported. */
-class OgreImporter : public BaseImporter
-{
-public:
-	/// BaseImporter override.
-	virtual bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
-	
-	/// BaseImporter override.
+	@todo Support vertex colors.
+	@todo Support poses/animations from the mesh file. 
+	Currently only skeleton file animations are supported. */
+class OgreImporter : public BaseImporter
+{
+public:
+	/// BaseImporter override.
+	virtual bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
+	
+	/// BaseImporter override.
 	virtual void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
 	virtual void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
 	
 	
 	/// BaseImporter override.
 	/// BaseImporter override.
-	virtual const aiImporterDesc *GetInfo() const;
-	
-	/// BaseImporter override.
-	virtual void SetupProperties(const Importer *pImp);
-
-private:
-	/// Read materials referenced by the @c mesh to @c pScene.
-	void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh);
-	void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh);
-	void AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials);
-	
-	/// Reads material
-	aiMaterial* ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string MaterialName);
-
-	// These functions parse blocks from a material file from @c ss. Starting parsing from "{" and ending it to "}".
-	bool ReadTechnique(const std::string &techniqueName, std::stringstream &ss, aiMaterial *material);
-	bool ReadPass(const std::string &passName, std::stringstream &ss, aiMaterial *material);	
-	bool ReadTextureUnit(const std::string &textureUnitName, std::stringstream &ss, aiMaterial *material);
-
-	std::string m_userDefinedMaterialLibFile;
-	bool m_detectTextureTypeFromFilename;
-	
-	std::map<aiTextureType, unsigned int> m_textures;
-};
-} // Ogre
-} // Assimp
-
+	virtual const aiImporterDesc *GetInfo() const;
+	
+	/// BaseImporter override.
+	virtual void SetupProperties(const Importer *pImp);
+
+private:
+	/// Read materials referenced by the @c mesh to @c pScene.
+	void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh);
+	void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh);
+	void AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials);
+	
+	/// Reads material
+	aiMaterial* ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string MaterialName);
+
+	// These functions parse blocks from a material file from @c ss. Starting parsing from "{" and ending it to "}".
+	bool ReadTechnique(const std::string &techniqueName, std::stringstream &ss, aiMaterial *material);
+	bool ReadPass(const std::string &passName, std::stringstream &ss, aiMaterial *material);	
+	bool ReadTextureUnit(const std::string &textureUnitName, std::stringstream &ss, aiMaterial *material);
+
+	std::string m_userDefinedMaterialLibFile;
+	bool m_detectTextureTypeFromFilename;
+	
+	std::map<aiTextureType, unsigned int> m_textures;
+};
+} // Ogre
+} // Assimp
+
 #endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
 #endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
 #endif // AI_OGREIMPORTER_H_INC
 #endif // AI_OGREIMPORTER_H_INC

+ 691 - 0
code/OpenGEXImporter.cpp

@@ -0,0 +1,691 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2014, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+
+#include "AssimpPCH.h"
+#include "OpenGEXImporter.h"
+#include "DefaultIOSystem.h"
+
+#include <openddlparser/OpenDDLParser.h>
+
+#include <vector>
+
+static const aiImporterDesc desc = {
+    "Open Game Engine Exchange",
+    "",
+    "",
+    "",
+    aiImporterFlags_SupportTextFlavour,
+    0,
+    0,
+    0,
+    0,
+    "ogex"
+};
+
+namespace Grammar {
+    static const char *MetricType          = "Metric";
+    static const char *Metric_DistanceType = "distance";
+    static const char *Metric_AngleType    = "angle";
+    static const char *Metric_TimeType     = "time";
+    static const char *Metric_UpType       = "up";
+    static const char *NameType            = "Name";
+    static const char *ObjectRefType       = "ObjectRef";
+    static const char *MaterialRefType     = "MaterialRef";
+    static const char *MetricKeyType       = "key";
+    static const char *GeometryNodeType    = "GeometryNode";
+    static const char *GeometryObjectType  = "GeometryObject";
+    static const char *TransformType       = "Transform";
+    static const char *MeshType            = "Mesh";
+    static const char *VertexArrayType     = "VertexArray";
+    static const char *IndexArrayType      = "IndexArray";
+    static const char *MaterialType        = "Material";
+    static const char *ColorType           = "Color";
+    static const char *TextureType         = "Texture";
+
+    enum TokenType {
+        NoneType = -1,
+        MetricToken,
+        NameToken,
+        ObjectRefToken,
+        MaterialRefToken,
+        MetricKeyToken,
+        GeometryNodeToken,
+        GeometryObjectToken,
+        TransformToken,
+        MeshToken,
+        VertexArrayToken,
+        IndexArrayToken,
+        MaterialToken,
+        ColorToken,
+        TextureToken
+    };
+
+    static const char *ValidMetricToken[ 4 ] = {
+        Metric_DistanceType,
+        Metric_AngleType,
+        Metric_TimeType,
+        Metric_UpType
+    };
+
+    static int isValidMetricType( const char *token ) {
+        if( NULL == token ) {
+            return false;
+        }
+
+        int idx( -1 );
+        for( size_t i = 0; i < 4; i++ ) {
+            if( 0 == strncmp( ValidMetricToken[ i ], token, strlen( token ) ) ) {
+                idx = (int) i;
+                break;
+            }
+        }
+
+        return idx;
+    }
+
+    static TokenType matchTokenType( const char *tokenType ) {
+        if( 0 == strncmp( MetricType, tokenType, strlen( MetricType ) ) ) {
+            return MetricToken;
+        } else if( 0 == strncmp( NameType, tokenType, strlen( NameType ) ) ) {
+            return NameToken;
+        }
+        else if( 0 == strncmp( ObjectRefType, tokenType, strlen( ObjectRefType ) ) ) {
+            return ObjectRefToken;
+        }
+        else if( 0 == strncmp( MaterialRefType, tokenType, strlen( MaterialRefType ) ) ) {
+            return MaterialRefToken; 
+        }
+        else if( 0 == strncmp( MetricKeyType, tokenType, strlen( MetricKeyType ) ) ) {
+            return MetricKeyToken;
+        }
+        else if( 0 == strncmp( GeometryNodeType, tokenType, strlen( GeometryNodeType ) ) ) {
+            return GeometryNodeToken;
+        }
+        else if( 0 == strncmp( GeometryObjectType, tokenType, strlen( GeometryObjectType ) ) ) {
+            return GeometryObjectToken;
+        }
+        else if( 0 == strncmp( TransformType, tokenType, strlen( TransformType ) ) ) {
+            return TransformToken;
+        }
+        else if( 0 == strncmp( MeshType, tokenType, strlen( MeshType ) ) ) {
+            return MeshToken;
+        }
+        else if( 0 == strncmp( VertexArrayType, tokenType, strlen( VertexArrayType ) ) ) {
+            return VertexArrayToken;
+        }
+        else if( 0 == strncmp( IndexArrayType, tokenType, strlen( IndexArrayType ) ) ) {
+            return IndexArrayToken;
+        }
+        else if( 0 == strncmp( MaterialType, tokenType, strlen( MaterialType ) ) ) {
+            return MaterialToken;
+        }
+        else if( 0 == strncmp( ColorType, tokenType, strlen( ColorType ) ) ) {
+            return ColorToken;
+        }
+        else if( 0 == strncmp( TextureType, tokenType, strlen( TextureType ) ) ) {
+            return TextureToken;
+        }
+
+        return NoneType;
+    }
+
+} // Namespace Grammar
+
+namespace Assimp {
+namespace OpenGEX {
+
+USE_ODDLPARSER_NS
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::RefInfo::RefInfo( aiNode *node, Type type, std::vector<std::string> &names )
+: m_node( node )
+, m_type( type )
+, m_Names( names ) {
+    // empty
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::RefInfo::~RefInfo() {
+    // empty
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::OpenGEXImporter() 
+: m_meshCache()
+, m_mesh2refMap()
+, m_ctx( NULL )
+, m_currentNode( NULL )
+, m_currentMesh( NULL )
+, m_nodeStack()
+, m_unresolvedRefStack() {
+    // empty
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::~OpenGEXImporter() {
+    m_ctx = NULL;
+}
+
+//------------------------------------------------------------------------------------------------
+bool OpenGEXImporter::CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const {
+    bool canRead( false );
+    if( !checkSig ) {
+        canRead = SimpleExtensionCheck( file, "ogex" );
+    } else {
+        static const char *token[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" };
+        canRead = BaseImporter::SearchFileHeaderForToken( pIOHandler, file, token, 4 );
+    }
+
+    return canRead;
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::InternReadFile( const std::string &filename, aiScene *pScene, IOSystem *pIOHandler ) {
+    // open source file
+    IOStream *file = pIOHandler->Open( filename, "rb" );
+    if( !file ) {
+        throw DeadlyImportError( "Failed to open file " + filename );
+    }
+
+    std::vector<char> buffer;
+    TextFileToBuffer( file, buffer );
+
+    OpenDDLParser myParser;
+    myParser.setBuffer( &buffer[ 0 ], buffer.size() );
+    bool success( myParser.parse() );
+    if( success ) {
+        m_ctx = myParser.getContext();
+        pScene->mRootNode = new aiNode;
+        pScene->mRootNode->mName.Set( filename );
+        handleNodes( m_ctx->m_root, pScene );
+    }
+
+    resolveReferences();
+}
+
+//------------------------------------------------------------------------------------------------
+const aiImporterDesc *OpenGEXImporter::GetInfo() const {
+    return &desc;
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::SetupProperties( const Importer *pImp ) {
+    if( NULL == pImp ) {
+        return;
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleNodes( DDLNode *node, aiScene *pScene ) {
+    if( NULL == node ) {
+        return;
+    }
+
+    DDLNode::DllNodeList childs = node->getChildNodeList();
+    for( DDLNode::DllNodeList::iterator it = childs.begin(); it != childs.end(); it++ ) {
+        Grammar::TokenType tokenType( Grammar::matchTokenType( ( *it )->getType().c_str() ) );
+        switch( tokenType ) {
+            case Grammar::MetricToken:
+                handleMetricNode( *it, pScene );
+                break;
+
+            case Grammar::NameToken:
+                handleNameNode( *it, pScene );
+                break;
+
+            case Grammar::ObjectRefToken:
+                handleObjectRefNode( *it, pScene );
+                break;
+
+            case Grammar::MaterialRefToken:
+                handleMaterialRefNode( *it, pScene );
+                break;
+
+            case Grammar::MetricKeyToken:
+                break;
+
+            case Grammar::GeometryNodeToken:
+                handleGeometryNode( *it, pScene );
+                break;
+
+            case Grammar::GeometryObjectToken:
+                handleGeometryObject( *it, pScene );
+                break;
+
+            case Grammar::TransformToken:
+                handleTransformNode( *it, pScene );
+                break;
+
+            case Grammar::MeshToken:
+                handleMeshNode( *it, pScene );
+                break;
+
+            case Grammar::VertexArrayToken:
+                handleVertexArrayNode( *it, pScene );
+                break;
+
+            case Grammar::IndexArrayToken:
+                handleIndexArrayNode( *it, pScene );
+                break;
+
+            case Grammar::MaterialToken:
+                handleMaterialNode( *it, pScene );
+                break;
+
+            case Grammar::ColorToken:
+                handleColorNode( *it, pScene );
+                break;
+
+            case Grammar::TextureToken:
+                handleTextureNode( *it, pScene );
+                break;
+            
+            default:
+                break;
+        }
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMetricNode( DDLNode *node, aiScene *pScene ) {
+    if( NULL == node || NULL == m_ctx ) {
+        return;
+    }
+
+    if( m_ctx->m_root != node->getParent() ) {
+        return;
+    }
+
+    Property *prop( node->getProperties() );
+    while( NULL != prop ) {
+        if( NULL != prop->m_id ) {
+            if( Value::ddl_string == prop->m_primData->m_type ) {
+                std::string valName( (char*) prop->m_primData->m_data );
+                int type( Grammar::isValidMetricType( valName.c_str() ) );
+                if( Grammar::NoneType != type ) {
+                    Value *val( node->getValue() );
+                    if( NULL != val ) {
+                        if( Value::ddl_float == val->m_type ) {
+                            m_metrics[ type ].m_floatValue = val->getFloat();
+                        } else if( Value::ddl_int32 == val->m_type ) {
+                            m_metrics[ type ].m_intValue = val->getInt32();
+                        } else if( Value::ddl_string == val->m_type ) {
+                            m_metrics[type].m_stringValue = std::string( val->getString() );
+                        } else {
+                            throw DeadlyImportError( "OpenGEX: invalid data type for Metric node." );
+                        }
+                    }
+                }
+            }
+        }
+        prop = prop->m_next;
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleNameNode( DDLNode *node, aiScene *pScene ) {
+    if( NULL == m_currentNode ) {
+        throw DeadlyImportError( "No parent node for name." );
+        return;
+    }
+
+    Value *val( node->getValue() );
+    if( NULL != val ) {
+        if( Value::ddl_string != val->m_type ) {
+            throw DeadlyImportError( "OpenGEX: invalid data type for value in node name." );
+            return;
+        }
+
+        const std::string name( val->getString() );
+        m_currentNode->mName.Set( name.c_str() );
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+static void getRefNames( DDLNode *node, std::vector<std::string> &names ) {
+    ai_assert( NULL != node );
+
+    Reference *ref = node->getReferences();
+    if( NULL != ref ) {
+        for( size_t i = 0; i < ref->m_numRefs; i++ )  {
+            Name *currentName( ref->m_referencedName[ i ] );
+            if( NULL != currentName && NULL != currentName->m_id ) {
+                const std::string name( currentName->m_id->m_buffer );
+                if( !name.empty() ) {
+                    names.push_back( name );
+                }
+            }
+        }
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleObjectRefNode( DDLNode *node, aiScene *pScene ) {
+    if( NULL == m_currentNode ) {
+        throw DeadlyImportError( "No parent node for name." );
+        return;
+    }
+
+    std::vector<std::string> objRefNames;
+    getRefNames( node, objRefNames );
+    m_currentNode->mNumMeshes = objRefNames.size();
+    m_currentNode->mMeshes = new unsigned int[ objRefNames.size() ];
+    if( !objRefNames.empty() ) {
+        m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MeshRef, objRefNames ) );
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+    if( NULL == m_currentNode ) {
+        throw DeadlyImportError( "No parent node for name." );
+        return;
+    }
+
+    std::vector<std::string> matRefNames;
+    getRefNames( node, matRefNames );
+    if( !matRefNames.empty() ) {
+        m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MaterialRef, matRefNames ) );
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleGeometryNode( DDLNode *node, aiScene *pScene ) {
+    aiNode *newNode = new aiNode;
+    pushNode( newNode, pScene );
+    m_currentNode = newNode;
+    handleNodes( node, pScene );
+    
+    popNode();
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleGeometryObject( DDLNode *node, aiScene *pScene ) {
+    aiMesh *currentMesh( new aiMesh );
+    const size_t idx( m_meshCache.size() );
+    m_meshCache.push_back( currentMesh );
+
+    // store name to reference relation
+    m_mesh2refMap[ node->getName() ] = idx;
+
+    // todo: child nodes?
+
+    handleNodes( node, pScene );
+}
+
+//------------------------------------------------------------------------------------------------
+static void setMatrix( aiNode *node, DataArrayList *transformData ) {
+    ai_assert( NULL != node );
+    ai_assert( NULL != transformData );
+
+    float m[ 16 ];
+    size_t i( 1 );
+    Value *next( transformData->m_dataList->m_next );
+    m[ 0 ] = transformData->m_dataList->getFloat();
+    while(  next != NULL ) {
+        m[ i ] = next->getFloat();
+        next = next->m_next;
+        i++;
+    }
+    
+    node->mTransformation.a1 = m[ 0 ];
+    node->mTransformation.a2 = m[ 1 ];
+    node->mTransformation.a3 = m[ 2 ];
+    node->mTransformation.a4 = m[ 3 ];
+
+    node->mTransformation.b1 = m[ 4 ];
+    node->mTransformation.b2 = m[ 5 ];
+    node->mTransformation.b3 = m[ 6 ];
+    node->mTransformation.b4 = m[ 7 ];
+
+    node->mTransformation.c1 = m[ 8 ];
+    node->mTransformation.c2 = m[ 9 ];
+    node->mTransformation.c3 = m[ 10 ];
+    node->mTransformation.c4 = m[ 11 ];
+
+    node->mTransformation.d1 = m[ 12 ];
+    node->mTransformation.d2 = m[ 13 ];
+    node->mTransformation.d3 = m[ 14 ];
+    node->mTransformation.d4 = m[ 15 ];
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleTransformNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+    if( NULL == m_currentNode ) {
+        throw DeadlyImportError( "No parent node for name." );
+        return;
+    }
+
+
+    DataArrayList *transformData( node->getDataArrayList() );
+    if( NULL != transformData ) {
+        if( transformData->m_numItems != 16 ) {
+            throw DeadlyImportError( "Invalid number of data for transform matrix." );
+            return;
+        }
+        setMatrix( m_currentNode, transformData );
+    } 
+}
+
+//------------------------------------------------------------------------------------------------
+static void propId2StdString( Property *prop, std::string &name, std::string &key ) {
+    name = key = "";
+    if( NULL == prop ) {
+        return;
+    }
+
+    if( NULL != prop->m_id ) {
+        name = prop->m_id->m_buffer;
+        if( Value::ddl_string == prop->m_primData->m_type ) {
+            key = prop->m_primData->getString();
+        }
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMeshNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+    Property *prop = node->getProperties();
+    m_currentMesh = new aiMesh;
+    m_meshCache.push_back( m_currentMesh );
+    
+    if( NULL != prop ) {
+        std::string propName, propKey;
+        propId2StdString( prop, propName, propKey );
+        if( "triangles" == propName ) {
+            m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+        }
+    }
+
+    handleNodes( node, pScene );
+}
+
+//------------------------------------------------------------------------------------------------
+enum MeshAttribute {
+    None,
+    Position,
+    Normal,
+    TexCoord
+};
+
+//------------------------------------------------------------------------------------------------
+static MeshAttribute getAttributeByName( const char *attribName ) {
+    ai_assert( NULL != attribName  );
+
+    if( 0 == strncmp( "position", attribName, strlen( "position" ) ) ) {
+        return Position;
+    } else if( 0 == strncmp( "normal", attribName, strlen( "normal" ) ) ) {
+        return Normal;
+    } else if( 0 == strncmp( "texcoord", attribName, strlen( "texcoord" ) ) ) {
+        return TexCoord;
+    }
+
+    return None;
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+    if( NULL == node ) {
+        throw DeadlyImportError( "No parent node for name." );
+        return;
+    }
+
+    Property *prop( node->getProperties() );
+    if( NULL != prop ) {
+        std::string propName, propKey;
+        propId2StdString( prop, propName, propKey );
+        MeshAttribute attribType( getAttributeByName( propName.c_str() ) );
+        if( None == attribType ) {
+            return;
+        }
+
+        DataArrayList *vaList = node->getDataArrayList();
+        if( NULL == vaList ) {
+            return;
+        }
+
+        if( Position == attribType ) {
+            aiVector3D *pos = new aiVector3D[ vaList->m_numItems ];
+            Value *next( vaList->m_dataList );
+            for( size_t i = 0; i < vaList->m_numItems; i++ ) {
+                
+            }
+        } else if( Normal == attribType ) {
+            aiVector3D *normal = new aiVector3D[ vaList->m_numItems ];
+        } else if( TexCoord == attribType ) {
+            aiVector3D *tex = new aiVector3D[ vaList->m_numItems ];
+        }
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMaterialNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::resolveReferences() {
+    if( m_unresolvedRefStack.empty() ) {
+        return;
+    }
+
+    RefInfo *currentRefInfo( NULL );
+    for( std::vector<RefInfo*>::iterator it = m_unresolvedRefStack.begin(); it != m_unresolvedRefStack.end(); ++it ) {
+        currentRefInfo = *it;
+        if( NULL != currentRefInfo ) {
+            aiNode *node( currentRefInfo->m_node );
+            if( RefInfo::MeshRef == currentRefInfo->m_type ) {
+                for( size_t i = 0; i < currentRefInfo->m_Names.size(); i++ ) {
+                    const std::string &name(currentRefInfo->m_Names[ i ] );
+                    unsigned int meshIdx = m_mesh2refMap[ name ];
+                    node->mMeshes[ i ] = meshIdx;
+                }
+            } else if( RefInfo::MaterialRef == currentRefInfo->m_type ) {
+                // ToDo
+            } else {
+                throw DeadlyImportError( "Unknown reference info to resolve." );
+            }
+        }
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::pushNode( aiNode *node, aiScene *pScene ) {
+    ai_assert( NULL != pScene );
+
+    if( NULL != node ) {
+        if( m_nodeStack.empty() ) {
+            node->mParent = pScene->mRootNode;
+        } else {
+            aiNode *parent( m_nodeStack.back() );
+            ai_assert( NULL != parent );
+            node->mParent = parent;
+        }
+        m_nodeStack.push_back( node );
+    }
+}
+
+//------------------------------------------------------------------------------------------------
+aiNode *OpenGEXImporter::popNode() {
+    if( m_nodeStack.empty() ) {
+        return NULL;
+    }
+    
+    aiNode *node( top() );
+    m_nodeStack.pop_back();
+    
+    return node;
+}
+
+//------------------------------------------------------------------------------------------------
+aiNode *OpenGEXImporter::top() const {
+    if( m_nodeStack.empty() ) {
+        return NULL;
+    }
+
+    return m_nodeStack.back();
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::clearNodeStack() {
+    m_nodeStack.clear();
+}
+
+//------------------------------------------------------------------------------------------------
+
+} // Namespace OpenGEX
+} // Namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_OPENGEX_IMPORTER

+ 158 - 0
code/OpenGEXImporter.h

@@ -0,0 +1,158 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2014, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#ifndef AI_OPENGEX_IMPORTER_H
+#define AI_OPENGEX_IMPORTER_H
+
+#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+
+#include "BaseImporter.h"
+
+#include <vector>
+
+namespace ODDLParser {
+    class DDLNode;
+    struct Context;
+}
+
+namespace Assimp {
+namespace OpenGEX {
+
+struct MetricInfo {
+    enum Type {
+        Distance = 0,
+        Angle,
+        Time,
+        Up,
+        Max
+    };
+
+    std::string m_stringValue;
+    float m_floatValue;
+    int m_intValue;
+
+    MetricInfo()
+    : m_stringValue( "" )
+    , m_floatValue( 0.0f )
+    , m_intValue( -1 ) {
+        // empty
+    }
+};
+
+/** @brief  This class is used to implement the OpenGEX importer
+ *
+ *  See http://opengex.org/OpenGEX.pdf for spec.
+ */
+class OpenGEXImporter : public BaseImporter {
+public:
+    /// The class constructor.
+    OpenGEXImporter();
+
+    /// The class destructor.
+    virtual ~OpenGEXImporter();
+
+    /// BaseImporter override.
+    virtual bool CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const;
+
+    /// BaseImporter override.
+    virtual void InternReadFile( const std::string &file, aiScene *pScene, IOSystem *pIOHandler );
+
+    /// BaseImporter override.
+    virtual const aiImporterDesc *GetInfo() const;
+
+    /// BaseImporter override.
+    virtual void SetupProperties( const Importer *pImp );
+
+protected:
+    void handleNodes( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleMetricNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleNameNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleObjectRefNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleGeometryNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleGeometryObject( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleTransformNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleMeshNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleMaterialNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleColorNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void handleTextureNode( ODDLParser::DDLNode *node, aiScene *pScene );
+    void resolveReferences();
+    void pushNode( aiNode *node, aiScene *pScene );
+    aiNode *popNode();
+    aiNode *top() const;
+    void clearNodeStack();
+
+private:
+    struct RefInfo {
+        enum Type {
+            MeshRef,
+            MaterialRef
+        };
+
+        aiNode *m_node;
+        Type m_type;
+        std::vector<std::string> m_Names;
+
+        RefInfo( aiNode *node, Type type, std::vector<std::string> &names );
+        ~RefInfo();
+
+    private:
+        RefInfo( const RefInfo & );
+        RefInfo &operator = ( const RefInfo & );
+    };
+
+    std::vector<aiMesh*> m_meshCache;
+    std::map<std::string, size_t> m_mesh2refMap;
+
+    ODDLParser::Context *m_ctx;
+    MetricInfo m_metrics[ MetricInfo::Max ];
+    aiNode *m_currentNode;
+    aiMesh *m_currentMesh;
+    std::vector<aiNode*> m_nodeStack;
+    std::vector<RefInfo*> m_unresolvedRefStack;
+};
+
+} // Namespace OpenGEX
+} // Namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+
+#endif // AI_OPENGEX_IMPORTER_H

+ 265 - 0
code/OpenGEXStructs.h

@@ -0,0 +1,265 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2014, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#ifndef AI_OPENGEXSTRUCTS_H_INC
+#define AI_OPENGEXSTRUCTS_H_INC
+
+#include <string>
+#include <map>
+
+namespace Assimp {
+namespace OpenGEX {
+
+struct Skin;
+struct Object;
+struct LightObject;
+struct CameraObject;
+struct Material;
+struct BoneNode;
+struct BoneCountArray;
+struct BoneIndexArray;
+struct BoneWeightArray;
+
+struct Metric {
+    float m_distance;
+    float m_angle;
+    float m_time;
+    float m_up;
+};
+
+struct VertexArray {
+    std::string arrayAttrib;
+    unsigned int morphIndex;
+};
+
+struct IndexArray {
+    unsigned int materialIndex;
+    unsigned int restartIndex;
+    std::string frontFace;
+};
+
+struct Mesh {
+    unsigned int meshLevel;
+    std::string meshPrimitive;
+    Skin *skinStructure;
+};
+
+struct Node {
+    std::string nodeName;
+};
+
+struct GeometryNode {
+    bool visibleFlag[ 2 ];
+    bool shadowFlag[ 2 ];
+    bool motionBlurFlag[ 2 ];
+};
+
+struct LightNode {
+    bool shadowFlag[ 2 ];
+    const LightObject *lightObjectStructure;
+};
+
+struct CameraNode {
+    const CameraObject *cameraObjectStructure;
+};
+
+struct GeometryObject {
+    Object *object;
+    bool visibleFlag;
+    bool shadowFlag;
+    bool motionBlurFlag;
+    std::map<std::string, Mesh*> meshMap;
+};
+
+struct LightObject {
+    Object *object;
+    std::string typeString;
+    bool shadowFlag;
+};
+
+
+struct CameraObject {
+    float focalLength;
+    float nearDepth;
+    float farDepth;
+};
+
+struct Matrix {
+    bool objectFlag;
+};
+
+struct Transform {
+    Matrix *matrix;
+    int transformCount;
+    const float	*transformArray;
+};
+
+struct Translation {
+    std::string translationKind;
+};
+
+struct Rotation {
+    std::string rotationKind;
+};
+
+struct Scale {
+    std::string scaleKind;
+};
+
+struct Name {
+    std::string	name;
+};
+
+
+struct ObjectRef {
+    Object *targetStructure;
+};
+
+struct MaterialRef {
+    unsigned int materialIndex;
+    const Material *targetStructure;
+};
+
+struct BoneRefArray {
+    int	boneCount;
+    const BoneNode **boneNodeArray;
+};
+
+struct BoneCount {
+    int	vertexCount;
+    const unsigned short *boneCountArray;
+    unsigned short *arrayStorage;
+};
+
+struct BoneIndex {
+    int	boneIndexCount;
+    const unsigned short *boneIndexArray;
+    unsigned short *arrayStorage;
+};
+
+
+struct BoneWeight {
+    int boneWeightCount;
+    const float *boneWeightArray;
+};
+
+struct Skeleton {
+    const BoneRefArray *boneRefArrayStructure;
+    const Transform *transformStructure;
+};
+
+struct Skin {
+    const Skeleton *skeletonStructure;
+    const BoneCountArray *boneCountArrayStructure;
+    const BoneIndexArray *boneIndexArrayStructure;
+    const BoneWeightArray *boneWeightArrayStructure;
+};
+
+struct Material {
+    bool twoSidedFlag;
+    const char *materialName;
+};
+
+struct Attrib {
+    std::string attribString;
+};
+
+struct Param {
+    float param;
+};
+
+struct Color {
+    float color[ 4 ];
+};
+
+struct Texture {
+    std::string textureName;
+    unsigned int texcoordIndex;
+};
+
+struct Atten {
+    std::string attenKind;
+    std::string curveType;
+
+    float beginParam;
+    float endParam;
+
+    float scaleParam;
+    float offsetParam;
+
+    float constantParam;
+    float linearParam;
+    float quadraticParam;
+
+    float powerParam;
+};
+
+struct Key {
+    std::string keyKind;
+    bool scalarFlag;
+};
+
+struct Curve {
+    std::string curveType;
+    const Key *keyValueStructure;
+    const Key *keyControlStructure[ 2 ];
+    const Key *keyTensionStructure;
+    const Key *keyContinuityStructure;
+    const Key *keyBiasStructure;
+};
+
+struct Animation {
+    int clipIndex;
+    bool beginFlag;
+    bool endFlag;
+    float beginTime;
+    float endTime;
+};
+
+struct OpenGexDataDescription {
+    float distanceScale;
+    float angleScale;
+    float timeScale;
+    int upDirection;
+};
+
+} // Namespace OpenGEX
+} // Namespace Assimp
+
+#endif // AI_OPENGEXSTRUCTS_H_INC

+ 2 - 2
code/PlyExporter.cpp

@@ -50,7 +50,7 @@ namespace Assimp	{
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to PLY. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to PLY. Prototyped and registered in Exporter.cpp
-void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	// invoke the exporter 
 	// invoke the exporter 
 	PlyExporter exporter(pFile, pScene);
 	PlyExporter exporter(pFile, pScene);
@@ -64,7 +64,7 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
 	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);
 }
 }
 
 
-void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	// invoke the exporter 
 	// invoke the exporter 
 	PlyExporter exporter(pFile, pScene, true);
 	PlyExporter exporter(pFile, pScene, true);

+ 46 - 27
code/PlyLoader.cpp

@@ -64,6 +64,25 @@ static const aiImporterDesc desc = {
 	"ply" 
 	"ply" 
 };
 };
 
 
+
+// ------------------------------------------------------------------------------------------------
+// Internal stuff
+namespace
+{
+	// ------------------------------------------------------------------------------------------------
+	// Checks that property index is within range
+	template <class T>
+	const T &GetProperty(const std::vector<T> &props, int idx)
+	{
+        if( static_cast< size_t >( idx ) >= props.size() ) {
+            throw DeadlyImportError( "Invalid .ply file: Property index is out of range." );
+        }
+
+		return props[idx];
+	}
+}
+
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 PLYImporter::PLYImporter()
 PLYImporter::PLYImporter()
@@ -431,13 +450,13 @@ void PLYImporter::LoadTextureCoordinates(std::vector<aiVector2D>* pvOut)
 			if (0xFFFFFFFF != aiPositions[0])
 			if (0xFFFFFFFF != aiPositions[0])
 			{
 			{
 				vOut.x = PLY::PropertyInstance::ConvertTo<float>(
 				vOut.x = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
+					GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
 			}
 			}
 
 
 			if (0xFFFFFFFF != aiPositions[1])
 			if (0xFFFFFFFF != aiPositions[1])
 			{
 			{
 				vOut.y = PLY::PropertyInstance::ConvertTo<float>(
 				vOut.y = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
+					GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
 			}
 			}
 			// and add them to our nice list
 			// and add them to our nice list
 			pvOut->push_back(vOut);
 			pvOut->push_back(vOut);
@@ -541,19 +560,19 @@ void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
 			if (0xFFFFFFFF != aiPositions[0])
 			if (0xFFFFFFFF != aiPositions[0])
 			{
 			{
 				vOut.x = PLY::PropertyInstance::ConvertTo<float>(
 				vOut.x = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
+					GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
 			}
 			}
 
 
 			if (0xFFFFFFFF != aiPositions[1])
 			if (0xFFFFFFFF != aiPositions[1])
 			{
 			{
 				vOut.y = PLY::PropertyInstance::ConvertTo<float>(
 				vOut.y = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
+					GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
 			}
 			}
 
 
 			if (0xFFFFFFFF != aiPositions[2])
 			if (0xFFFFFFFF != aiPositions[2])
 			{
 			{
 				vOut.z = PLY::PropertyInstance::ConvertTo<float>(
 				vOut.z = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[2]].avList.front(),aiTypes[2]);
+					GetProperty((*i).alProperties, aiPositions[2]).avList.front(),aiTypes[2]);
 			}
 			}
 
 
 			// and add them to our nice list
 			// and add them to our nice list
@@ -659,28 +678,28 @@ void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
 			
 			
 			if (0xFFFFFFFF != aiPositions[0])
 			if (0xFFFFFFFF != aiPositions[0])
 			{
 			{
-				vOut.r = NormalizeColorValue((*i).alProperties[
-					aiPositions[0]].avList.front(),aiTypes[0]);
+				vOut.r = NormalizeColorValue(GetProperty((*i).alProperties,
+					aiPositions[0]).avList.front(),aiTypes[0]);
 			}
 			}
 
 
 			if (0xFFFFFFFF != aiPositions[1])
 			if (0xFFFFFFFF != aiPositions[1])
 			{
 			{
-				vOut.g = NormalizeColorValue((*i).alProperties[
-					aiPositions[1]].avList.front(),aiTypes[1]);
+				vOut.g = NormalizeColorValue(GetProperty((*i).alProperties,
+					aiPositions[1]).avList.front(),aiTypes[1]);
 			}
 			}
 
 
 			if (0xFFFFFFFF != aiPositions[2])
 			if (0xFFFFFFFF != aiPositions[2])
 			{
 			{
-				vOut.b = NormalizeColorValue((*i).alProperties[
-					aiPositions[2]].avList.front(),aiTypes[2]);
+				vOut.b = NormalizeColorValue(GetProperty((*i).alProperties,
+					aiPositions[2]).avList.front(),aiTypes[2]);
 			}
 			}
 
 
 			// assume 1.0 for the alpha channel ifit is not set
 			// assume 1.0 for the alpha channel ifit is not set
 			if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f;
 			if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f;
 			else
 			else
 			{
 			{
-				vOut.a = NormalizeColorValue((*i).alProperties[
-					aiPositions[3]].avList.front(),aiTypes[3]);
+				vOut.a = NormalizeColorValue(GetProperty((*i).alProperties,
+					aiPositions[3]).avList.front(),aiTypes[3]);
 			}
 			}
 
 
 			// and add them to our nice list
 			// and add them to our nice list
@@ -773,11 +792,11 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 				// parse the list of vertex indices
 				// parse the list of vertex indices
 				if (0xFFFFFFFF != iProperty)
 				if (0xFFFFFFFF != iProperty)
 				{
 				{
-					const unsigned int iNum = (unsigned int)(*i).alProperties[iProperty].avList.size();
+					const unsigned int iNum = (unsigned int)GetProperty((*i).alProperties, iProperty).avList.size();
 					sFace.mIndices.resize(iNum);
 					sFace.mIndices.resize(iNum);
 
 
 					std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p = 
 					std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p = 
-						(*i).alProperties[iProperty].avList.begin();
+						GetProperty((*i).alProperties, iProperty).avList.begin();
 
 
 					for (unsigned int a = 0; a < iNum;++a,++p)
 					for (unsigned int a = 0; a < iNum;++a,++p)
 					{
 					{
@@ -789,7 +808,7 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 				if (0xFFFFFFFF != iMaterialIndex)
 				if (0xFFFFFFFF != iMaterialIndex)
 				{
 				{
 					sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
 					sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
-						(*i).alProperties[iMaterialIndex].avList.front(),eType2);
+						GetProperty((*i).alProperties, iMaterialIndex).avList.front(),eType2);
 				}
 				}
 				pvOut->push_back(sFace);
 				pvOut->push_back(sFace);
 			}
 			}
@@ -800,7 +819,7 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 			// a value of -1 indicates a restart of the strip
 			// a value of -1 indicates a restart of the strip
 			bool flip = false;
 			bool flip = false;
 			for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
 			for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
-				const std::vector<PLY::PropertyInstance::ValueUnion>& quak = (*i).alProperties[iProperty].avList;
+				const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty((*i).alProperties, iProperty).avList;
 				pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u));
 				pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u));
 
 
 				int aiTable[2] = {-1,-1};
 				int aiTable[2] = {-1,-1};
@@ -851,30 +870,30 @@ void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avL
 	if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
 	if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
 	else
 	else
 	{
 	{
-		clrOut->r = NormalizeColorValue(avList[
-			aiPositions[0]].avList.front(),aiTypes[0]);
+		clrOut->r = NormalizeColorValue(GetProperty(avList,
+			aiPositions[0]).avList.front(),aiTypes[0]);
 	}
 	}
 
 
 	if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
 	if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
 	else
 	else
 	{
 	{
-		clrOut->g = NormalizeColorValue(avList[
-			aiPositions[1]].avList.front(),aiTypes[1]);
+		clrOut->g = NormalizeColorValue(GetProperty(avList,
+			aiPositions[1]).avList.front(),aiTypes[1]);
 	}
 	}
 
 
 	if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
 	if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
 	else
 	else
 	{
 	{
-		clrOut->b = NormalizeColorValue(avList[
-			aiPositions[2]].avList.front(),aiTypes[2]);
+		clrOut->b = NormalizeColorValue(GetProperty(avList,
+			aiPositions[2]).avList.front(),aiTypes[2]);
 	}
 	}
 
 
 	// assume 1.0 for the alpha channel ifit is not set
 	// assume 1.0 for the alpha channel ifit is not set
 	if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
 	if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
 	else
 	else
 	{
 	{
-		clrOut->a = NormalizeColorValue(avList[
-			aiPositions[3]].avList.front(),aiTypes[3]);
+		clrOut->a = NormalizeColorValue(GetProperty(avList, 
+			aiPositions[3]).avList.front(),aiTypes[3]);
 	}
 	}
 }
 }
 
 
@@ -1025,7 +1044,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut)
 			// handle phong power and shading mode
 			// handle phong power and shading mode
 			int iMode;
 			int iMode;
 			if (0xFFFFFFFF != iPhong)	{
 			if (0xFFFFFFFF != iPhong)	{
-				float fSpec = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),ePhong);
+				float fSpec = PLY::PropertyInstance::ConvertTo<float>(GetProperty((*i).alProperties, iPhong).avList.front(),ePhong);
 
 
 				// if shininess is 0 (and the pow() calculation would therefore always
 				// if shininess is 0 (and the pow() calculation would therefore always
 				// become 1, not depending on the angle), use gouraud lighting
 				// become 1, not depending on the angle), use gouraud lighting
@@ -1043,7 +1062,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut)
 
 
 			// handle opacity
 			// handle opacity
 			if (0xFFFFFFFF != iOpacity)	{
 			if (0xFFFFFFFF != iOpacity)	{
-				float fOpacity = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),eOpacity);
+				float fOpacity = PLY::PropertyInstance::ConvertTo<float>(GetProperty((*i).alProperties, iPhong).avList.front(),eOpacity);
 				pcHelper->AddProperty<float>(&fOpacity, 1, AI_MATKEY_OPACITY);
 				pcHelper->AddProperty<float>(&fOpacity, 1, AI_MATKEY_OPACITY);
 			}
 			}
 
 

+ 2 - 2
code/STLExporter.cpp

@@ -50,7 +50,7 @@ namespace Assimp	{
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to Stereolithograpy. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to Stereolithograpy. Prototyped and registered in Exporter.cpp
-void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	// invoke the exporter 
 	// invoke the exporter 
 	STLExporter exporter(pFile, pScene);
 	STLExporter exporter(pFile, pScene);
@@ -63,7 +63,7 @@ void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
 
 
 	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);
 }
 }
-void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	// invoke the exporter 
 	// invoke the exporter 
 	STLExporter exporter(pFile, pScene, true);
 	STLExporter exporter(pFile, pScene, true);

+ 28 - 9
code/XFileExporter.cpp

@@ -59,7 +59,7 @@ namespace Assimp
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
 // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
-void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
 {
 	std::string path = "";
 	std::string path = "";
 	std::string file = pFile;
 	std::string file = pFile;
@@ -78,13 +78,19 @@ void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pSce
 		}
 		}
 	}
 	}
 
 
+	// create/copy Properties
+	ExportProperties props(*pProperties);
+
+	// set standard properties if not set
+	if (!props.HasPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT)) props.SetPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT, false);
+
 	// invoke the exporter 
 	// invoke the exporter 
-	XFileExporter iDoTheExportThing( pScene, pIOSystem, path, file);
+	XFileExporter iDoTheExportThing( pScene, pIOSystem, path, file, &props);
 
 
 	// we're still here - export successfully completed. Write result to the given IOSYstem
 	// we're still here - export successfully completed. Write result to the given IOSYstem
 	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 .dae file: " + std::string(pFile));
+		throw DeadlyExportError("could not open output .x file: " + std::string(pFile));
 	}
 	}
 
 
 	// XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
 	// XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
@@ -96,7 +102,7 @@ void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pSce
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor for a specific scene to export
 // Constructor for a specific scene to export
-XFileExporter::XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file)
+XFileExporter::XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties) : mIOSystem(pIOSystem), mPath(path), mFile(file), mProperties(pProperties)
 {
 {
 	// make sure that all formatting happens using the standard, C locale and not the user's current locale
 	// make sure that all formatting happens using the standard, C locale and not the user's current locale
 	mOutput.imbue( std::locale("C") );
 	mOutput.imbue( std::locale("C") );
@@ -126,7 +132,7 @@ void XFileExporter::WriteFile()
 {
 {
 	// note, that all realnumber values must be comma separated in x files
 	// note, that all realnumber values must be comma separated in x files
 	mOutput.setf(std::ios::fixed);
 	mOutput.setf(std::ios::fixed);
-	mOutput.precision(6); // precission for float
+	mOutput.precision(16); // precission for double
 
 
 	// entry of writing the file
 	// entry of writing the file
 	WriteHeader();
 	WriteHeader();
@@ -148,7 +154,10 @@ void XFileExporter::WriteFile()
 // Writes the asset header
 // Writes the asset header
 void XFileExporter::WriteHeader()
 void XFileExporter::WriteHeader()
 {
 {
-	mOutput << startstr << "xof 0303txt 0032" << endstr;
+	if (mProperties->GetPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT) == true)
+		mOutput << startstr << "xof 0303txt 0064" << endstr;
+	else
+		mOutput << startstr << "xof 0303txt 0032" << endstr;
 	mOutput << endstr;
 	mOutput << endstr;
 	mOutput << startstr << "template Frame {" << endstr;
 	mOutput << startstr << "template Frame {" << endstr;
 	PushTag();
 	PushTag();
@@ -298,7 +307,7 @@ void XFileExporter::WriteNode( aiNode* pNode)
 		ss << "Node_" << pNode;
 		ss << "Node_" << pNode;
 		pNode->mName.Set(ss.str());
 		pNode->mName.Set(ss.str());
 	}
 	}
-	mOutput << startstr << "Frame " << pNode->mName.C_Str() << " {" << endstr;
+	mOutput << startstr << "Frame " << toXFileString(pNode->mName) << " {" << endstr;
 
 
 	PushTag();
 	PushTag();
 
 
@@ -318,9 +327,9 @@ void XFileExporter::WriteNode( aiNode* pNode)
 	mOutput << startstr << "}" << endstr << endstr;
 	mOutput << startstr << "}" << endstr << endstr;
 }
 }
 
 
-void XFileExporter::WriteMesh(const aiMesh* mesh)
+void XFileExporter::WriteMesh(aiMesh* mesh)
 {
 {
-	mOutput << startstr << "Mesh " << mesh->mName.C_Str() << "_mShape" << " {" << endstr;
+	mOutput << startstr << "Mesh " << toXFileString(mesh->mName) << "_mShape" << " {" << endstr;
 
 
 	PushTag();
 	PushTag();
 
 
@@ -496,6 +505,16 @@ void XFileExporter::WriteMesh(const aiMesh* mesh)
 
 
 }
 }
 
 
+std::string XFileExporter::toXFileString(aiString &name)
+{
+	std::string str = std::string(name.C_Str());
+	std::replace(str.begin(), str.end(), '<', '_');
+	std::replace(str.begin(), str.end(), '>', '_');
+	std::replace(str.begin(), str.end(), '{', '_');
+	std::replace(str.begin(), str.end(), '}', '_');
+	std::replace(str.begin(), str.end(), '$', '_');
+	return str;
+}
 
 
 void XFileExporter::writePath(aiString path)
 void XFileExporter::writePath(aiString path)
 {
 {

+ 8 - 2
code/XFileExporter.h

@@ -61,7 +61,7 @@ class XFileExporter
 {
 {
 public:
 public:
 	/// Constructor for a specific scene to export
 	/// Constructor for a specific scene to export
-	XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file);
+	XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties);
 
 
 	/// Destructor
 	/// Destructor
 	virtual ~XFileExporter();
 	virtual ~XFileExporter();
@@ -80,7 +80,7 @@ protected:
 	void WriteNode( aiNode* pNode );
 	void WriteNode( aiNode* pNode );
 
 
 	/// write a mesh entry of the scene
 	/// write a mesh entry of the scene
-	void WriteMesh(const aiMesh* mesh);
+	void WriteMesh( aiMesh* mesh);
 
 
 	/// Enters a new xml element, which increases the indentation
 	/// Enters a new xml element, which increases the indentation
 	void PushTag() { startstr.append( "  "); }
 	void PushTag() { startstr.append( "  "); }
@@ -94,6 +94,12 @@ public:
 
 
 protected:
 protected:
 
 
+	/// normalize the name to be accepted by xfile readers
+	std::string toXFileString(aiString &name);
+
+	/// hold the properties pointer
+	const ExportProperties* mProperties;
+
 	/// write a path
 	/// write a path
 	void writePath(aiString path);	
 	void writePath(aiString path);	
 
 

+ 64 - 0
contrib/openddlparser/CMakeLists.txt

@@ -0,0 +1,64 @@
+CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )
+PROJECT( OpenDDL-Parser )
+SET ( OPENDDL_PARSER_VERSION_MAJOR 0 )
+SET ( OPENDDL_PARSER_VERSION_MINOR 1 )
+SET ( OPENDDL_PARSER_VERSION_PATCH 0 )
+SET ( OPENDDL_PARSER_VERSION ${CPPCORE_VERSION_MAJOR}.${CPPCORE_VERSION_MINOR}.${CPPCORE_VERSION_PATCH} )
+SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
+
+if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+    find_package(Threads)
+else()
+    add_definitions( -D_CRT_SECURE_NO_WARNINGS )
+endif()
+
+add_definitions( -DOPENDDLPARSER_BUILD )
+add_definitions( -DOPENDDL_NO_USE_CPP11 )
+add_definitions( -D_VARIADIC_MAX=10 )
+
+INCLUDE_DIRECTORIES(
+    ./
+    include/
+    contrib/gtest-1.7.0/include
+    contrib/gtest-1.7.0/
+)
+
+link_directories(
+    ./
+)
+
+SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
+SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
+SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
+
+if( WIN32 AND NOT CYGWIN )
+  set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc" )  # Force to always compile with W4
+  if( CMAKE_CXX_FLAGS MATCHES "/W[0-4]" )
+    string( REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" )
+  else()
+    set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4" )
+  endif()
+elseif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+  # Update if necessary
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++0x")
+elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++11")
+endif()
+
+SET ( openddl_parser_src
+    code/OpenDDLParser.cpp
+    code/DDLNode.cpp
+    code/Value.cpp
+    include/openddlparser/OpenDDLParser.h
+    include/openddlparser/OpenDDLParserUtils.h
+    include/openddlparser/OpenDDLCommon.h
+    include/openddlparser/DDLNode.h
+    include/openddlparser/Value.h
+    README.md
+)
+ 
+SOURCE_GROUP( code            FILES ${openddl_parser_src} )
+
+ADD_LIBRARY( openddl_parser SHARED
+    ${openddl_parser_src}
+)

+ 111 - 0
contrib/openddlparser/README.md

@@ -0,0 +1,111 @@
+The OpenDDL-Parser
+==================
+
+A simple and fast OpenDDL Parser
+Current build status: [![Build Status](https://travis-ci.org/kimkulling/openddl-parser.png)](https://travis-ci.org/kimkulling/openddl-parser)
+
+Get the source code
+===================
+You can get the code from our git repository, which is located at GitHub. You can clone the repository like:
+
+> git clone https://github.com/kimkulling/openddl-parser.git
+
+Build from repo
+===============
+To build the library you need to install cmake first ( see http://www.cmake.org/ for more information ). Make also sure that a compiler toolchain is installed on your machine.
+After installing it you can open a console and type:
+
+> cmake CMakeLists.txt
+
+This command will generate a build environment for your installed build enrironment ( for Visual Studio the project files will be generated, for gcc the makefiles will be generated ).
+When using an IDE open the IDE and run the build. When using GNU-make type in your console:
+
+> make
+
+and that's all.
+
+Use the library
+===============
+To use the OpenDDL-parser you need to build the lib first. Now add the 
+> <Repo-folder>/include 
+
+to your include-path and the 
+
+> <Repo-folder>/lib
+
+to your lib-folder. Link the openddl.lib to your application. 
+
+Here is a small example how to use the lib:
+
+```cpp
+
+#include <iostream>
+#include <cassert>
+#include <openddlparser/OpenDDLParser.h>
+
+USE_ODDLPARSER_NS;
+
+int main( int argc, char *argv[] ) {
+    if( argc < 3 ) {
+        return 1;
+    }
+
+    char *filename( nullptr );
+    if( 0 == strncmp( FileOption, argv[ 1 ], strlen( FileOption ) ) ) {
+        filename = argv[ 2 ];
+    }
+    std::cout << "file to import: " << filename << std::endl;   
+    if( nullptr == filename ) {
+        std::cerr << "Invalid filename." << std::endl;
+        return Error;
+    }
+
+    FILE *fileStream = fopen( filename, "r+" );
+    if( NULL == filename ) {
+        std::cerr << "Cannot open file " << filename << std::endl;
+        return 1;
+    }
+
+    // obtain file size:
+    fseek( fileStream, 0, SEEK_END );
+    const size_t size( ftell( fileStream ) );   
+    rewind( fileStream );   
+    if( size > 0 ) {
+        char *buffer = new char[ size ];
+        const size_t readSize( fread( buffer, sizeof( char ), size, fileStream ) );
+        assert( readSize == size );
+        OpenDDLParser theParser;
+        theParser.setBuffer( buffer, size );
+        const bool result( theParser.parse() );
+        if( !result ) {
+            std::cerr << "Error while parsing file " << filename << "." << std::endl;
+        }
+    }
+    return 0;
+}
+
+```
+
+How to access the imported data
+===============================
+The data is organized as a tree. You can get the root tree with the following code:
+
+```
+OpenDDLParser theParser;
+theParser.setBuffer( buffer, size );
+const bool result( theParser.parse() );
+if ( result ) {
+    DDLNode *root = theParser.getRoot();
+
+    DDLNode::DllNodeList childs = root->getChildNodeList();
+    for ( size_t i=0; i<childs.size(); i++ ) {
+        DDLNode *child = childs[ i ];
+        Property *prop = child->getProperty(); // to get properties
+        std:.string type = child->getType();   // to get the node type
+        Value *values = child->getValue();     // to get the data;
+    }
+}
+
+```
+
+The instance called root contains the data.

+ 184 - 0
contrib/openddlparser/code/DDLNode.cpp

@@ -0,0 +1,184 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLParser.h>
+
+#include <algorithm>
+
+BEGIN_ODDLPARSER_NS
+
+DDLNode::DllNodeList DDLNode::s_allocatedNodes;
+
+template<class T>
+inline
+static void releaseDataType( T *ptr ) {
+    if( ddl_nullptr == ptr ) {
+        return;
+    }
+
+    T *current( ddl_nullptr );
+    while( ptr ) {
+        current = ptr;
+        ptr = ptr->m_next;
+        delete current;
+    }
+}
+
+static void releaseReferencedNames( Reference *ref ) {
+    if( ddl_nullptr == ref ) {
+        return;
+    }
+
+    if( ref->m_referencedName ) {
+        for( size_t i = 0; i < ref->m_numRefs; i++ ) {
+            delete ref->m_referencedName;
+        }
+    }
+}
+
+DDLNode::DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent )
+: m_type( type )
+, m_name( name )
+, m_parent( parent )
+, m_children()
+, m_properties( ddl_nullptr )
+, m_value( ddl_nullptr )
+, m_dtArrayList( ddl_nullptr )
+, m_references( ddl_nullptr )
+, m_idx( idx ) {
+    if( m_parent ) {
+        m_parent->m_children.push_back( this );
+    }
+}
+
+DDLNode::~DDLNode() {
+    releaseDataType<Property>( m_properties );
+    releaseDataType<Value>( m_value );
+    releaseReferencedNames( m_references );
+
+    delete m_dtArrayList;
+    m_dtArrayList = ddl_nullptr;
+    if( s_allocatedNodes[ m_idx ] == this ) {
+        s_allocatedNodes[ m_idx ] = ddl_nullptr;
+    }
+}
+
+void DDLNode::attachParent( DDLNode *parent ) {
+    if( m_parent == parent ) {
+        return;
+    }
+
+    m_parent = parent;
+    if( ddl_nullptr != m_parent ) {
+        m_parent->m_children.push_back( this );
+    }
+}
+
+void DDLNode::detachParent() {
+    if( m_parent ) {
+        std::vector<DDLNode*>::iterator it;
+        it = std::find( m_parent->m_children.begin(), m_parent->m_children.end(), this );
+        if( m_parent->m_children.end() != it ) {
+            m_parent->m_children.erase( it );
+        }
+        m_parent = ddl_nullptr;
+    }
+}
+
+DDLNode *DDLNode::getParent() const {
+    return m_parent;
+}
+
+const DDLNode::DllNodeList &DDLNode::getChildNodeList() const {
+    return m_children;
+}
+
+void DDLNode::setType( const std::string &type ) {
+    m_type = type;
+}
+
+const std::string &DDLNode::getType() const {
+    return m_type;
+}
+
+
+void DDLNode::setName( const std::string &name ) {
+    m_name = name;
+}
+
+const std::string &DDLNode::getName() const {
+    return m_name;
+}
+
+void DDLNode::setProperties( Property *prop ) {
+    m_properties = prop;
+}
+
+Property *DDLNode::getProperties() const {
+    return m_properties;
+}
+
+void DDLNode::setValue( Value *val ) {
+    m_value = val;
+}
+
+Value *DDLNode::getValue() const {
+    return m_value;
+}
+
+void DDLNode::setDataArrayList( DataArrayList  *dtArrayList ) {
+    m_dtArrayList = dtArrayList;
+}
+
+DataArrayList *DDLNode::getDataArrayList() const {
+    return m_dtArrayList;
+}
+
+void DDLNode::setReferences( Reference *refs ) {
+    m_references = refs;
+}
+
+Reference *DDLNode::getReferences() const {
+    return m_references;
+}
+
+DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLNode *parent ) {
+    const size_t idx( s_allocatedNodes.size() );
+    DDLNode *node = new DDLNode( type, name, idx, parent );
+    s_allocatedNodes.push_back( node );
+    
+    return node;
+}
+
+void DDLNode::releaseNodes() {
+    if( s_allocatedNodes.size() > 0 ) {
+        for( DllNodeList::iterator it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
+            if( *it ) {
+                delete *it;
+            }
+        }
+        s_allocatedNodes.clear();
+    }
+}
+
+END_ODDLPARSER_NS

+ 900 - 0
contrib/openddlparser/code/OpenDDLParser.cpp

@@ -0,0 +1,900 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/OpenDDLParser.h>
+
+#include <cassert>
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+#include <math.h>
+
+#ifdef _WIN32
+#  include <windows.h>
+#endif // _WIN32
+
+#define DEBUG_HEADER_NAME 
+
+BEGIN_ODDLPARSER_NS
+
+static const char *Version = "0.1.0";
+
+namespace Grammar {
+    static const char *OpenBracketToken   = "{";
+    static const char *CloseBracketToken  = "}";
+    static const char *OpenPropertyToken  = "(";
+    static const char *ClosePropertyToken = ")";
+    static const char *BoolTrue           = "true";
+    static const char *BoolFalse          = "false";
+    static const char *RefToken           = "ref";
+
+    static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = {
+        "bool",
+        "int8",
+        "int16",
+        "int32",
+        "int64",
+        "unsigned_int8",
+        "unsigned_int16",
+        "unsigned_int32",
+        "unsigned_int64",
+        "half",
+        "float",
+        "double",
+        "string",
+        "ref"
+    };
+} // Namespace Grammar
+
+
+static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) {
+    std::stringstream stream;
+    stream << "Invalid token " << *in << ", " << exp << " expected." << std::endl;
+    callback( ddl_error_msg, stream.str() );
+}
+
+static bool isIntegerType( Value::ValueType integerType ) {
+    if( integerType != Value::ddl_int8 && integerType != Value::ddl_int16 && 
+            integerType != Value::ddl_int32 && integerType != Value::ddl_int64 ) {
+        return false;
+    }
+
+    return true;
+}
+
+static DDLNode *createDDLNode( Identifier *id, OpenDDLParser *parser ) {
+    if( ddl_nullptr == id || ddl_nullptr == parser ) {
+        return ddl_nullptr;
+    }
+
+    const std::string type( id->m_buffer );
+    DDLNode *parent( parser->top() );
+    DDLNode *node = DDLNode::create( type, "", parent );
+
+    return node;
+}
+
+static void logMessage( LogSeverity severity, const std::string &msg ) {
+    std::string log;
+    if( ddl_debug_msg == severity ) {
+        log += "Debug:";
+    } else if( ddl_info_msg == severity ) {
+        log += "Info :";
+    } else if( ddl_warn_msg == severity ) {
+        log += "Warn :";
+    } else if( ddl_error_msg == severity ) {
+        log += "Error:";
+    } else {
+        log += "None :";
+    }
+
+    log += msg;
+    std::cout << log;
+}
+
+OpenDDLParser::OpenDDLParser()
+: m_logCallback( logMessage )
+, m_buffer()
+, m_stack()
+, m_context( ddl_nullptr ) {
+    // empty
+}
+
+OpenDDLParser::OpenDDLParser( char *buffer, size_t len )
+: m_logCallback( &logMessage )
+, m_buffer()
+, m_context( ddl_nullptr ) {
+    if( 0 != len ) {
+        setBuffer( buffer, len );
+    }
+}
+
+OpenDDLParser::~OpenDDLParser() {
+    clear();
+}
+
+void OpenDDLParser::setLogCallback( logCallback callback ) {
+    if( ddl_nullptr != callback ) {
+        // install user-specific log callback
+        m_logCallback = callback;
+    } else {
+        // install default log callback
+        m_logCallback = &logMessage;
+    }
+}
+
+OpenDDLParser::logCallback OpenDDLParser::getLogCallback() const {
+    return m_logCallback;
+}
+
+void OpenDDLParser::setBuffer( char *buffer, size_t len ) {
+    clear();
+    if( 0 == len ) {
+        return;
+    }
+
+    m_buffer.resize( len );
+    ::memcpy(&m_buffer[ 0 ], buffer, len );
+}
+
+void OpenDDLParser::setBuffer( const std::vector<char> &buffer ) {
+    clear();
+    m_buffer.resize( buffer.size() );
+    std::copy( buffer.begin(), buffer.end(), m_buffer.begin() );
+}
+
+const char *OpenDDLParser::getBuffer() const {
+    if( m_buffer.empty() ) {
+        return ddl_nullptr;
+    }
+
+    return &m_buffer[ 0 ];
+}
+
+size_t OpenDDLParser::getBufferSize() const {
+    return m_buffer.size();
+}
+
+void OpenDDLParser::clear() {
+    m_buffer.resize( 0 );
+    if( m_context ) {
+        m_context->m_root = ddl_nullptr;
+    }
+
+    DDLNode::releaseNodes();
+}
+
+bool OpenDDLParser::parse() {
+    if( m_buffer.empty() ) {
+        return false;
+    }
+    
+    normalizeBuffer( m_buffer );
+
+    std::cout << &m_buffer[0] << std::endl;
+
+    m_context = new Context;
+    m_context->m_root = DDLNode::create( "root", "", ddl_nullptr );
+    pushNode( m_context->m_root );
+
+    // do the main parsing
+    char *current( &m_buffer[ 0 ] );
+    char *end( &m_buffer[ m_buffer.size() - 1 ] + 1 );
+    size_t pos( current - &m_buffer[ 0 ] );
+    while( pos < m_buffer.size() ) {
+        current = parseNextNode( current, end );
+        pos = current - &m_buffer[ 0 ];
+    }
+    return true;
+}
+
+char *OpenDDLParser::parseNextNode( char *in, char *end ) {
+    in = parseHeader( in, end );
+    in = parseStructure( in, end );
+
+    return in;
+}
+
+static void dumpId( Identifier *id ) {
+    if( ddl_nullptr != id ) {
+        std::cout << id->m_buffer << std::endl;
+    }
+}
+
+char *OpenDDLParser::parseHeader( char *in, char *end ) {
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    Identifier *id( ddl_nullptr );
+    in = OpenDDLParser::parseIdentifier( in, end, &id );
+
+#ifdef DEBUG_HEADER_NAME    
+    dumpId( id );
+#endif // DEBUG_HEADER_NAME
+
+    in = lookForNextToken( in, end );
+    Property *first( ddl_nullptr );
+    if( ddl_nullptr != id ) {
+        if( *in == '(' ) {
+            in++;
+            Property *prop( ddl_nullptr ), *prev( ddl_nullptr );
+            while( *in != ')' && in != end ) {
+                in = OpenDDLParser::parseProperty( in, end, &prop );
+                in = lookForNextToken( in, end );
+
+                if( *in != ',' && *in != ')' ) {
+                    logInvalidTokenError( in, ")", m_logCallback );
+                    return in;
+                }
+                
+                if( ddl_nullptr != prop && *in != ',' ) {
+                    if( ddl_nullptr == first ) {
+                        first = prop;
+                    }
+                    if( ddl_nullptr != prev ) {
+                        prev->m_next = prop;
+                    }
+                    prev = prop;
+                }
+            }
+            in++;
+        }
+
+        // store the node
+        DDLNode *node( createDDLNode( id, this ) );
+        if( ddl_nullptr != node ) {
+            pushNode( node );
+        } else {
+            std::cerr << "nullptr returned by creating DDLNode." << std::endl;
+        }
+
+        // set the properties
+        if( ddl_nullptr != first ) {
+            node->setProperties( first );
+        }
+
+        Name *name( ddl_nullptr );
+        in = OpenDDLParser::parseName( in, end, &name );
+        if( ddl_nullptr != name ) {
+            const std::string nodeName( name->m_id->m_buffer );
+            node->setName( nodeName );
+        }
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseStructure( char *in, char *end ) {
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    bool error( false );
+    in = lookForNextToken( in, end );
+    if( *in == '{' ) {
+        // loop over all children ( data and nodes )
+        do {
+            in = parseStructureBody( in, end, error );
+        } while ( *in != '}' );
+        in++;
+    } else {
+        in++;
+        logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback );
+        error = true;
+        return in;
+    }
+    in = lookForNextToken( in, end );
+    
+    // pop node from stack after successful parsing
+    if( !error ) {
+        popNode();
+    }
+
+    return in;
+}
+
+static void setNodeValues( DDLNode *currentNode, Value *values ) {
+    if( ddl_nullptr != values ){
+        if( ddl_nullptr != currentNode ) {
+            currentNode->setValue( values );
+        }
+    }
+}
+
+static void setNodeReferences( DDLNode *currentNode, Reference *refs ) {
+    if( ddl_nullptr != refs ) {
+        if( ddl_nullptr != currentNode ) {
+            currentNode->setReferences( refs );
+        }
+    }
+}
+
+static void setNodeDataArrayList( DDLNode *currentNode, DataArrayList *dtArrayList ) {
+    if( ddl_nullptr != dtArrayList ) {
+        if( ddl_nullptr != currentNode ) {
+            currentNode->setDataArrayList( dtArrayList );
+        }
+    }
+}
+
+char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) {
+    if( !isNumeric( *in ) && !isCharacter( *in ) ) {
+        in++;
+    }
+
+    in = lookForNextToken( in, end );
+    Value::ValueType type( Value::ddl_none );
+    size_t arrayLen( 0 );
+    in = OpenDDLParser::parsePrimitiveDataType( in, end, type, arrayLen );
+    if( Value::ddl_none != type ) {
+        // parse a primitive data type
+        in = lookForNextToken( in, end );
+        if( *in == '{' ) {
+            Reference *refs( ddl_nullptr );
+            DataArrayList *dtArrayList( ddl_nullptr );
+            Value *values( ddl_nullptr );
+            if( 1 == arrayLen ) {
+                size_t numRefs( 0 ), numValues( 0 );
+                in = parseDataList( in, end, &values, numValues, &refs, numRefs );
+                setNodeValues( top(), values );
+                setNodeReferences( top(), refs );
+            } else if( arrayLen > 1 ) {
+                in = parseDataArrayList( in, end, &dtArrayList );
+                setNodeDataArrayList( top(), dtArrayList );
+            } else {
+                std::cerr << "0 for array is invalid." << std::endl;
+                error = true;
+            }
+        }
+
+        in = lookForNextToken( in, end );
+        if( *in != '}' ) {
+            logInvalidTokenError( in, std::string( Grammar::CloseBracketToken ), m_logCallback );
+        } else {
+            //in++;
+        }
+    } else {
+        // parse a complex data type
+        in = parseNextNode( in, end );
+    }
+
+    return in;
+}
+
+void OpenDDLParser::pushNode( DDLNode *node ) {
+    if( ddl_nullptr == node ) {
+        return;
+    }
+
+    m_stack.push_back( node );
+}
+
+DDLNode *OpenDDLParser::popNode() {
+    if( m_stack.empty() ) {
+        return ddl_nullptr;
+    }
+
+    DDLNode *topNode( top() );
+    m_stack.pop_back();
+
+    return topNode;
+}
+
+DDLNode *OpenDDLParser::top() {
+    if( m_stack.empty() ) {
+        return ddl_nullptr;
+    }
+    
+    DDLNode *top( m_stack.back() );
+    return top;
+}
+
+DDLNode *OpenDDLParser::getRoot() const {
+    if( ddl_nullptr == m_context ) {
+        return ddl_nullptr;
+    }
+
+    return m_context->m_root;
+}
+
+Context *OpenDDLParser::getContext() const {
+    return m_context;
+}
+
+void OpenDDLParser::normalizeBuffer( std::vector<char> &buffer) {
+    if( buffer.empty() ) {
+        return;
+    }
+
+    std::vector<char> newBuffer;
+    const size_t len( buffer.size() );
+    char *end( &buffer[ len-1 ] + 1 );
+    for( size_t readIdx = 0; readIdx<len; ++readIdx ) {
+        char *c( &buffer[readIdx] );
+        // check for a comment
+        if( !isComment<char>( c, end ) && !isNewLine( *c ) ) {
+            newBuffer.push_back( buffer[ readIdx ] );
+        } else {
+            if( isComment<char>( c, end ) ) {
+                readIdx++;
+                // skip the comment and the rest of the line
+                while( !isEndofLine( buffer[ readIdx ] ) ) {
+                    readIdx++;
+                }
+            }
+        }
+    }
+    buffer = newBuffer;
+}
+
+char *OpenDDLParser::parseName( char *in, char *end, Name **name ) {
+    *name = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    // ignore blanks
+    in = lookForNextToken( in, end );
+    if( *in != '$' && *in != '%' ) {
+        return in;
+    }
+
+    NameType ntype( GlobalName );
+    if( *in == '%' ) {
+        ntype = LocalName;
+    }
+
+    Name *currentName( ddl_nullptr );
+    Identifier *id( ddl_nullptr );
+    in = parseIdentifier( in, end, &id );
+    if( id ) {
+        currentName = new Name( ntype, id );
+        if( currentName ) {
+            *name = currentName;
+        }
+    }
+    
+    return in;
+}
+
+char *OpenDDLParser::parseIdentifier( char *in, char *end, Identifier **id ) {
+    *id = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    // ignore blanks
+    in = lookForNextToken( in, end );
+    
+    // staring with a number is forbidden
+    if( isNumeric<const char>( *in ) ) {
+        return in;
+    }
+
+    // get size of id
+    size_t idLen( 0 );
+    char *start( in );
+    while( !isSeparator( *in ) && !isNewLine( *in ) && ( in != end ) && *in != '(' && *in != ')' ) {
+        in++;
+        idLen++;
+    }
+    
+    const size_t len( idLen + 1 );
+    Identifier *newId = new Identifier( len, new char[ len ] );
+    ::strncpy( newId->m_buffer, start, newId->m_len-1 );
+    newId->m_buffer[ newId->m_len - 1 ] = '\0';
+    *id = newId;
+
+    return in;
+}
+
+char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueType &type, size_t &len ) {
+    type = Value::ddl_none;
+    len = 0;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    size_t prim_len( 0 );
+    for( unsigned int i = 0; i < Value::ddl_types_max; i++ ) {
+        prim_len = strlen( Grammar::PrimitiveTypeToken[ i ] );
+        if( 0 == strncmp( in, Grammar::PrimitiveTypeToken[ i ], prim_len ) ) {
+            type = ( Value::ValueType ) i;
+            break;
+        }
+    }
+
+    if( Value::ddl_none == type ) {
+        in = lookForNextToken( in, end );
+        return in;
+    } else {
+        in += prim_len;
+    }
+
+    bool ok( true );
+    if( *in == '[' ) {
+        ok = false;
+        in++;
+        char *start( in );
+        while ( in != end ) {
+            in++;
+            if( *in == ']' ) {
+                len = atoi( start );
+                ok = true;
+                in++;
+                break;
+            }
+        }
+    } else {
+        len = 1;
+    }
+    if( !ok ) {
+        type = Value::ddl_none;
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseReference( char *in, char *end, std::vector<Name*> &names ) {
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    Name *nextName( ddl_nullptr );
+    in = parseName( in, end, &nextName );
+    if( nextName ) {
+        names.push_back( nextName );
+    }
+    while( ',' == *in ) {
+        in = getNextSeparator( in, end );
+        if( ',' == *in ) {
+            in = parseName( in, end, &nextName );
+            if( nextName ) {
+                names.push_back( nextName );
+            }
+        } else {
+            break;
+        }
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseBooleanLiteral( char *in, char *end, Value **boolean ) {
+    *boolean = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    char *start( in );
+    size_t len( 0 );
+    while( !isSeparator( *in ) && in != end ) {
+        in++;
+        len++;
+    }
+    len++;
+    int res = ::strncmp( Grammar::BoolTrue, start, strlen( Grammar::BoolTrue ) );
+    if( 0 != res ) {
+        res = ::strncmp( Grammar::BoolFalse, start, strlen( Grammar::BoolFalse ) );
+        if( 0 != res ) {
+            *boolean = ddl_nullptr;
+            return in;
+        }
+        *boolean = ValueAllocator::allocPrimData( Value::ddl_bool );
+        (*boolean)->setBool( false );
+    } else {
+        *boolean = ValueAllocator::allocPrimData( Value::ddl_bool );
+        (*boolean)->setBool( true );
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseIntegerLiteral( char *in, char *end, Value **integer, Value::ValueType integerType ) {
+    *integer = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    if( !isIntegerType( integerType ) ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    char *start( in );
+    while( !isSeparator( *in ) && in != end ) {
+        in++;
+    }
+
+    if( isNumeric( *start ) ) {
+        const int value( atoi( start ) );
+        *integer = ValueAllocator::allocPrimData( integerType );
+        switch( integerType ) {
+            case Value::ddl_int8:
+                    ( *integer )->setInt8( (int8) value );
+                    break;
+            case Value::ddl_int16:
+                    ( *integer )->setInt16( ( int16 ) value );
+                    break;
+            case Value::ddl_int32:
+                    ( *integer )->setInt32( ( int32 ) value );
+                    break;
+            case Value::ddl_int64:
+                    ( *integer )->setInt64( ( int64 ) value );
+                    break;
+            default:
+                break;
+        }
+    } 
+
+    return in;
+}
+
+char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating ) {
+    *floating = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    char *start( in );
+    while( !isSeparator( *in ) && in != end ) {
+        in++;
+    }
+
+    // parse the float value
+    bool ok( false );
+    if( isNumeric( *start ) ) {
+        ok = true;
+    } else {
+        if( *start == '-' ) {
+            if( isNumeric( *(start+1) ) ) {
+                ok = true;
+            }
+        }
+    }
+
+    if( ok ) {
+        const float value( ( float ) atof( start ) );
+        *floating = ValueAllocator::allocPrimData( Value::ddl_float );
+        ( *floating )->setFloat( value );
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseStringLiteral( char *in, char *end, Value **stringData ) {
+    *stringData = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    size_t len( 0 );
+    char *start( in );
+    if( *start == '\"' ) {
+        start++;
+        in++;
+        while( *in != '\"' && in != end ) {
+            in++;
+            len++;
+        }
+
+        *stringData = ValueAllocator::allocPrimData( Value::ddl_string, len );
+        ::strncpy( ( char* ) ( *stringData )->m_data, start, len );
+        ( *stringData )->m_data[len] = '\0';
+        in++;
+    }
+
+    return in;
+}
+
+static void createPropertyWithData( Identifier *id, Value *primData, Property **prop ) {
+    if( ddl_nullptr != primData ) {
+        ( *prop ) = new Property( id );
+        ( *prop )->m_primData = primData;
+    }
+}
+
+char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
+    *data = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    if( *in != '0' ) {
+        return in;
+    }
+
+    in++;
+    if( *in != 'x' && *in != 'X' ) {
+        return in;
+    }
+
+    in++;
+    bool ok( true );
+    char *start( in );
+    int pos( 0 );
+    while( !isSeparator( *in ) && in != end ) {
+        if( ( *in < '0' && *in > '9' ) || ( *in < 'a' && *in > 'f' ) || ( *in < 'A' && *in > 'F' ) ) {
+            ok = false;
+            break;
+        }
+        pos++;
+        in++;
+    }
+
+    if( !ok ) {
+        return in;
+    }
+
+    int value( 0 );
+    while( pos > 0 ) {
+        pos--;
+        value += hex2Decimal( *start ) * static_cast<int>( pow( 16.0, pos ) );
+        start++;
+    }
+
+    *data = ValueAllocator::allocPrimData( Value::ddl_int32 );
+    (*data)->setInt32( value );
+
+    return in;
+}
+
+char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) {
+    *prop = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    Identifier *id( ddl_nullptr );
+    in = parseIdentifier( in, end, &id );
+    if( ddl_nullptr != id ) {
+        in = lookForNextToken( in, end );
+        if( *in == '=' ) {
+            in++;
+            in = getNextToken( in, end );
+            Value *primData( ddl_nullptr );
+            if( isInteger( in, end ) ) {
+                in = parseIntegerLiteral( in, end, &primData );
+                createPropertyWithData( id, primData, prop );
+            } else if( isFloat( in, end ) ) {
+                in = parseFloatingLiteral( in, end, &primData );
+                createPropertyWithData( id, primData, prop );
+            } else if( isStringLiteral( *in ) ) { // string data
+                in = parseStringLiteral( in, end, &primData );
+                createPropertyWithData( id, primData, prop );
+            } else {                          // reference data
+                std::vector<Name*> names;
+                in = parseReference( in, end, names );
+                if( !names.empty() ) {
+                    Reference *ref = new Reference( names.size(), &names[ 0 ] );
+                    ( *prop ) = new Property( id );
+                    ( *prop )->m_ref = ref;
+                }
+            }
+        } 
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseDataList( char *in, char *end, Value **data, size_t &numValues, Reference **refs, size_t &numRefs ) {
+    *data = ddl_nullptr;
+    numValues = numRefs = 0;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    if( *in == '{' ) {
+        in++;
+        Value *current( ddl_nullptr ), *prev( ddl_nullptr );
+        while( '}' != *in ) {
+            current = ddl_nullptr;
+            in = lookForNextToken( in, end );
+            if( isInteger( in, end ) ) {
+                in = parseIntegerLiteral( in, end, &current );
+            } else if( isFloat( in, end ) ) {
+                in = parseFloatingLiteral( in, end, &current );
+            } else if( isStringLiteral( *in ) ) {
+                in = parseStringLiteral( in, end, &current );
+            } else if( isHexLiteral( in, end ) ) {
+                in = parseHexaLiteral( in, end, &current );
+            } else {                          // reference data
+                std::vector<Name*> names;
+                in = parseReference( in, end, names );
+                if( !names.empty() ) {
+                    Reference *ref = new Reference( names.size(), &names[ 0 ] );
+                    *refs = ref;
+                    numRefs = names.size();
+                }
+            }
+
+            if( ddl_nullptr != current ) {
+                if( ddl_nullptr == *data ) {
+                    *data = current;
+                    prev = current;
+                } else {
+                    prev->setNext( current );
+                    prev = current;
+                }
+                numValues++;
+            }
+
+            in = getNextSeparator( in, end );
+            if( ',' != *in && '}' != *in && !isSpace( *in ) ) {
+                break;
+            }
+        }
+        in++;
+    }
+
+    return in;
+}
+
+char *OpenDDLParser::parseDataArrayList( char *in, char *end, DataArrayList **dataList ) {
+    *dataList = ddl_nullptr;
+    if( ddl_nullptr == in || in == end ) {
+        return in;
+    }
+
+    in = lookForNextToken( in, end );
+    if( *in == Grammar::OpenBracketToken[ 0 ] ) {
+        in++;
+        Value *current( ddl_nullptr );
+        Reference *refs( ddl_nullptr );
+        DataArrayList *prev( ddl_nullptr ), *currentDataList( ddl_nullptr );
+        do {
+            size_t numRefs( 0 ), numValues( 0 );
+            in = parseDataList( in, end, &current, numValues, &refs, numRefs );
+            if( ddl_nullptr != current ) {
+                if( ddl_nullptr == prev ) {
+                    *dataList = new DataArrayList;
+                    ( *dataList )->m_dataList = current;
+                    ( *dataList )->m_numItems = numValues;
+                    prev = *dataList;
+                } else {
+                    currentDataList = new DataArrayList;
+                    if( ddl_nullptr != prev ) {
+                        prev->m_next = currentDataList;
+                        prev = currentDataList;
+                    }
+                }
+            }
+        } while( ',' == *in && in != end );
+        in = lookForNextToken( in, end );
+        in++;
+    }
+
+    return in;
+}
+
+const char *OpenDDLParser::getVersion() {
+    return Version;
+}
+
+END_ODDLPARSER_NS

+ 256 - 0
contrib/openddlparser/code/Value.cpp

@@ -0,0 +1,256 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/Value.h>
+
+#include <iostream>
+#include <cassert>
+
+BEGIN_ODDLPARSER_NS
+
+Value::Value()
+: m_type( ddl_none )
+, m_size( 0 )
+, m_data( ddl_nullptr )
+, m_next( ddl_nullptr ) {
+    // empty
+}
+
+Value::~Value() {
+    // empty
+}
+
+void Value::setBool( bool value ) {
+    assert( ddl_bool == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+bool Value::getBool() {
+    assert( ddl_bool == m_type );
+    return ( bool ) ( *m_data );
+}
+
+void Value::setInt8( int8 value ) {
+    assert( ddl_int8 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int8 Value::getInt8() {
+    assert( ddl_int8 == m_type );
+    return ( int8 ) ( *m_data );
+}
+
+void Value::setInt16( int16 value ) {
+    assert( ddl_int16 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int16 Value::getInt16() {
+    assert( ddl_int16 == m_type );
+    return ( int16 ) ( *m_data );
+}
+
+void Value::setInt32( int32 value ) {
+    assert( ddl_int32 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int32 Value::getInt32() {
+    assert( ddl_int32 == m_type );
+    return ( int32 ) ( *m_data );
+}
+
+void Value::setInt64( int64 value ) {
+    assert( ddl_int32 == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+int64 Value::getInt64() {
+    return ( int64 ) ( *m_data );
+}
+
+void Value::setFloat( float value ) {
+    assert( ddl_float == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+float Value::getFloat() const {
+    float v;
+    ::memcpy( &v, m_data, m_size );
+    return v;
+}
+
+void Value::setDouble( double value ) {
+    assert( ddl_double == m_type );
+    ::memcpy( m_data, &value, m_size );
+}
+
+double Value::getDouble() const {
+    double v;
+    ::memcpy( &v, m_data, m_size );
+    return v;
+}
+
+void Value::setString( const std::string &str ) {
+    assert( ddl_string == m_type );
+    ::memcpy( m_data, str.c_str(), str.size() );
+    m_data[ str.size() ] = '\0';
+}
+const char *Value::getString() const {
+    return (const char*) m_data;
+}
+
+void Value::dump() {
+    switch( m_type ) {
+    case ddl_none:
+        std::cout << "None" << std::endl;
+        break;
+    case ddl_bool:
+        std::cout << getBool() << std::endl;
+        break;
+    case ddl_int8:
+        std::cout << getInt8() << std::endl;
+        break;
+    case ddl_int16:
+        std::cout << getInt16() << std::endl;
+        break;
+    case ddl_int32:
+        std::cout << getInt32() << std::endl;
+        break;
+    case ddl_int64:
+        std::cout << getInt64() << std::endl;
+        break;
+    case ddl_unsigned_int8:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_unsigned_int16:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_unsigned_int32:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_unsigned_int64:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_half:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_float:
+        std::cout << getFloat() << std::endl;
+        break;
+    case ddl_double:
+        std::cout << getDouble() << std::endl;
+        break;
+    case ddl_string:
+        std::cout << "Not supported" << std::endl;
+        break;
+    case ddl_ref:
+        std::cout << "Not supported" << std::endl;
+        break;
+    default:
+        break;
+    }
+}
+
+void Value::setNext( Value *next ) {
+    m_next = next;
+}
+
+Value *Value::getNext() const {
+    return m_next;
+}
+
+Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
+    if( type == Value::ddl_none || Value::ddl_types_max == type ) {
+        return ddl_nullptr;
+    }
+
+    Value *data = new Value;
+    data->m_type = type;
+    switch( type ) {
+        case Value::ddl_bool:
+            data->m_size = sizeof( bool );
+            break;
+        case Value::ddl_int8:
+            data->m_size = sizeof( char );
+            break;
+        case Value::ddl_int16:
+            data->m_size = sizeof( short );
+            break;
+        case Value::ddl_int32:
+            data->m_size = sizeof( int );
+            break;
+        case Value::ddl_int64:
+            data->m_size = sizeof( long );
+            break;
+        case Value::ddl_unsigned_int8:
+            data->m_size = sizeof( unsigned char );
+            break;
+        case Value::ddl_unsigned_int32:
+            data->m_size = sizeof( unsigned int );
+            break;
+        case Value::ddl_unsigned_int64:
+            data->m_size = sizeof( unsigned long );
+            break;
+        case Value::ddl_half:
+            data->m_size = sizeof( short );
+            break;
+        case Value::ddl_float:
+            data->m_size = sizeof( float );
+            break;
+        case Value::ddl_double:
+            data->m_size = sizeof( double );
+            break;
+        case Value::ddl_string:
+            data->m_size = sizeof( char );
+            break;
+        case Value::ddl_ref:
+            data->m_size = sizeof( char );
+            break;
+        case Value::ddl_none:
+        case Value::ddl_types_max:
+        default:
+            break;
+    }
+
+    if( data->m_size ) {
+        size_t len1( len );
+        if( Value::ddl_string == type ) {
+            len1++;
+        }
+        data->m_size *= len1;
+        data->m_data = new unsigned char[ data->m_size ];
+    }
+
+    return data;
+}
+
+void ValueAllocator::releasePrimData( Value **data ) {
+    if( !data ) {
+        return;
+    }
+
+    delete *data;
+    *data = ddl_nullptr;
+}
+
+END_ODDLPARSER_NS

+ 90 - 0
contrib/openddlparser/include/openddlparser/DDLNode.h

@@ -0,0 +1,90 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_DDLNODE_H_INC
+#define OPENDDLPARSER_DDLNODE_H_INC
+
+#include <openddlparser/OpenDDLCommon.h>
+
+#include <vector>
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+class Value;
+class OpenDDLParser;
+
+struct Identifier;
+struct Reference;
+struct Property;
+struct DataArrayList;
+
+class DLL_ODDLPARSER_EXPORT DDLNode {
+public:
+    friend class OpenDDLParser;
+
+    typedef std::vector<DDLNode*> DllNodeList;
+
+public:
+    ~DDLNode();
+    void attachParent( DDLNode *parent );
+    void detachParent();
+    DDLNode *getParent() const;
+    const DllNodeList &getChildNodeList() const;
+    void setType( const std::string &name );
+    const std::string &getType() const;
+    void setName( const std::string &name );
+    const std::string &getName() const;
+    void setProperties( Property *prop );
+    Property *getProperties() const;
+    void setValue( Value *val );
+    Value *getValue() const;
+    void setDataArrayList( DataArrayList  *dtArrayList );
+    DataArrayList *getDataArrayList() const;
+    void setReferences( Reference  *refs );
+    Reference *getReferences() const;
+    static DDLNode *create( const std::string &type, const std::string &name, DDLNode *parent = ddl_nullptr );
+
+private:
+    DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent = ddl_nullptr );
+    DDLNode();
+    DDLNode( const DDLNode & );
+    DDLNode &operator = ( const DDLNode & );
+    static void releaseNodes();
+
+private:
+    std::string m_type;
+    std::string m_name;
+    DDLNode *m_parent;
+    std::vector<DDLNode*> m_children;
+    Property *m_properties;
+    Value *m_value;
+    DataArrayList *m_dtArrayList;
+    Reference *m_references;
+    size_t m_idx;
+    static DllNodeList s_allocatedNodes;
+};
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_DDLNODE_H_INC

+ 170 - 0
contrib/openddlparser/include/openddlparser/OpenDDLCommon.h

@@ -0,0 +1,170 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
+#define OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
+
+#include <cstddef>
+#include <vector>
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#   define TAG_DLL_EXPORT __declspec(dllexport)
+#   define TAG_DLL_IMPORT __declspec(dllimport )
+#   ifdef OPENDDLPARSER_BUILD
+#       define DLL_ODDLPARSER_EXPORT TAG_DLL_EXPORT
+#   else
+#       define DLL_ODDLPARSER_EXPORT TAG_DLL_IMPORT
+#   endif // OPENDDLPARSER_BUILD
+#   pragma warning( disable : 4251 )
+#else
+#   define DLL_ODDLPARSER_EXPORT
+#endif // _WIN32
+
+#define BEGIN_ODDLPARSER_NS namespace ODDLParser {
+#define END_ODDLPARSER_NS   }
+#define USE_ODDLPARSER_NS   using namespace ODDLParser;
+
+BEGIN_ODDLPARSER_NS
+
+#ifndef OPENDDL_NO_USE_CPP11
+#   define ddl_nullptr nullptr
+#else
+#   define ddl_nullptr NULL
+#endif // OPENDDL_NO_USE_CPP11
+
+class DDLNode;
+class Value;
+
+struct Name;
+struct Identifier;
+struct Reference;
+struct Property;
+struct DataArrayList;
+
+typedef char  int8;
+typedef short int16;
+typedef int   int32;
+typedef long  int64;
+
+enum NameType {
+    GlobalName,
+    LocalName
+};
+
+struct Name {
+    NameType    m_type;
+    Identifier *m_id;
+
+    Name( NameType type, Identifier *id )
+        : m_type( type )
+        , m_id( id ) {
+        // empty
+    }
+};
+
+struct Reference {
+    size_t   m_numRefs;
+    Name   **m_referencedName;
+
+    Reference()
+    : m_numRefs( 0 )
+    , m_referencedName( ddl_nullptr ) {
+        // empty
+    }
+     
+    Reference( size_t numrefs, Name **names )
+    : m_numRefs( numrefs )
+    , m_referencedName( ddl_nullptr ) {
+        m_referencedName = new Name *[ numrefs ];
+        for( size_t i = 0; i < numrefs; i++ ) {
+            Name *name = new Name( names[ i ]->m_type, names[ i ]->m_id );
+            m_referencedName[ i ] = name;
+        }
+    }
+};
+
+struct Identifier {
+    size_t m_len;
+    char *m_buffer;
+
+    Identifier( size_t len, char buffer[] )
+        : m_len( len )
+        , m_buffer( buffer ) {
+        // empty
+    }
+};
+
+struct Property {
+    Identifier *m_id;
+    Value *m_primData;
+    Reference *m_ref;
+    Property *m_next;
+
+    Property( Identifier *id )
+        : m_id( id )
+        , m_primData( ddl_nullptr )
+        , m_ref( ddl_nullptr )
+        , m_next( ddl_nullptr ) {
+        // empty
+    }
+};
+
+struct DataArrayList {
+    size_t m_numItems;
+    Value *m_dataList;
+    DataArrayList *m_next;
+
+    DataArrayList()
+        : m_numItems( 0 )
+        , m_dataList( ddl_nullptr )
+        , m_next( ddl_nullptr ) {
+        // empty
+    }
+};
+
+struct Context {
+    DDLNode *m_root;
+
+    Context()
+        : m_root( ddl_nullptr ) {
+        // empty
+    }
+};
+
+struct BufferIt {
+    std::vector<char> m_buffer;
+    size_t m_idx;
+
+    BufferIt( const std::vector<char> &buffer )
+        : m_buffer( buffer )
+        , m_idx( 0 ) {
+        // empty
+    }
+};
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
+

+ 131 - 0
contrib/openddlparser/include/openddlparser/OpenDDLParser.h

@@ -0,0 +1,131 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_OPENDDLPARSER_H_INC
+#define OPENDDLPARSER_OPENDDLPARSER_H_INC
+
+#include <openddlparser/OpenDDLCommon.h>
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLParserUtils.h>
+#include <openddlparser/Value.h>
+
+#include <vector>
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+class DDLNode;
+class Value;
+
+struct Identifier;
+struct Reference;
+struct Property;
+
+template<class T>
+inline
+T *lookForNextToken( T *in, T *end ) {
+    while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) {
+        in++;
+    }
+    return in;
+}
+
+template<class T>
+inline
+T *getNextToken( T *in, T *end ) {
+    T *tmp( in );
+    while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) {
+        in++;
+    }
+    if( tmp == in ) {
+        in++;
+    }
+    return in;
+}
+
+///	@brief  Defines the log severity.
+enum LogSeverity {
+    ddl_debug_msg = 0,  ///< Debug message, for debugging
+    ddl_info_msg,       ///< Info messages, normal mode
+    ddl_warn_msg,       ///< Parser warnings
+    ddl_error_msg       ///< Parser errors
+};
+
+class DLL_ODDLPARSER_EXPORT OpenDDLParser {
+public:
+    typedef void( *logCallback )( LogSeverity severity, const std::string &msg );
+
+public:
+    OpenDDLParser();
+    OpenDDLParser( char *buffer, size_t len );
+    ~OpenDDLParser();
+    void setLogCallback( logCallback callback );
+    logCallback getLogCallback() const;
+    void setBuffer( char *buffer, size_t len );
+    void setBuffer( const std::vector<char> &buffer );
+    const char *getBuffer() const;
+    size_t getBufferSize() const;
+    void clear();
+    bool parse();
+    char *parseNextNode( char *current, char *end );
+    char *parseHeader( char *in, char *end );
+    char *parseStructure( char *in, char *end );
+    char *parseStructureBody( char *in, char *end, bool &error );
+    void pushNode( DDLNode *node );
+    DDLNode *popNode();
+    DDLNode *top();
+    DDLNode *getRoot() const;
+    Context *getContext() const;
+
+public: // static parser helpers
+    static void normalizeBuffer( std::vector<char> &buffer );
+    static char *parseName( char *in, char *end, Name **name );
+    static char *parseIdentifier( char *in, char *end, Identifier **id );
+    static char *parsePrimitiveDataType( char *in, char *end, Value::ValueType &type, size_t &len );
+    static char *parseReference( char *in, char *end, std::vector<Name*> &names );
+    static char *parseBooleanLiteral( char *in, char *end, Value **boolean );
+    static char *parseIntegerLiteral( char *in, char *end, Value **integer, Value::ValueType integerType = Value::ddl_int32 );
+    static char *parseFloatingLiteral( char *in, char *end, Value **floating );
+    static char *parseStringLiteral( char *in, char *end, Value **stringData );
+    static char *parseHexaLiteral( char *in, char *end, Value **data );
+    static char *parseProperty( char *in, char *end, Property **prop );
+    static char *parseDataList( char *in, char *end, Value **data, size_t &numValues, Reference **refs, size_t &numRefs );
+    static char *parseDataArrayList( char *in, char *end, DataArrayList **dataList );
+    static const char *getVersion();
+
+private:
+    OpenDDLParser( const OpenDDLParser & );
+    OpenDDLParser &operator = ( const OpenDDLParser & );
+
+private:
+    logCallback m_logCallback;
+    std::vector<char> m_buffer;
+
+    typedef std::vector<DDLNode*> DDLNodeStack;
+    DDLNodeStack m_stack;
+    Context *m_context;
+};
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_OPENDDLPARSER_H_INC

+ 249 - 0
contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h

@@ -0,0 +1,249 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC
+#define OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC
+
+#include <openddlparser/OpenDDLCommon.h>
+
+BEGIN_ODDLPARSER_NS
+
+template<class T>
+inline
+bool isComment( T *in, T *end ) {
+    if( *in == '/' ) {
+        if( in + 1 != end ) {
+            if( *( in + 1 ) == '/' ) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+template<class T>
+inline
+bool isUpperCase( T in ) {
+    return ( in >= 'A' && in <= 'Z' );
+}
+
+template<class T>
+inline
+bool isLowerCase( T in ) {
+    return ( in >= 'a' && in <= 'z' );
+}
+
+template<class T> 
+inline 
+bool isSpace( const T in ) {
+    return ( ' ' == in || '\t' == in );
+}
+
+template<class T>
+inline
+bool isNewLine( const T in ) {
+    return ( '\n' == in || ( '\r' == in ) );
+}
+
+template<class T>
+inline
+bool isSeparator( T in ) {
+    if( isSpace( in ) || ',' == in || '{' == in || '}' == in || '[' == in ) {
+        return true;
+    }
+    return false;
+}
+
+static const unsigned char chartype_table[ 256 ] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 48-63
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64-79
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-95
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96-111
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112-127
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // > 127 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+template<class T>
+inline
+bool isNumeric( const T in ) {
+    return ( in >= '0' && in <= '9' );
+    //return ( chartype_table[in] );
+    /*if (in >= '0' &&  in <= '9' )
+    return true;
+
+    return false;*/
+}
+
+template<class T>
+inline
+bool isInteger( T *in, T *end ) {
+    if( in != end ) {
+        if( *in == '-' ) {
+            in++;
+        }
+    }
+
+    bool result( false );
+    while( '}' != *in && ',' != *in && !isSpace( *in ) && in != end ) {
+        result = isNumeric( *in );
+        if( !result ) {
+            break;
+        }
+        in++;
+    }
+
+    return result;
+}
+
+template<class T>
+inline
+bool isFloat( T *in, T *end ) {
+    if( in != end ) {
+        if( *in == '-' ) {
+            in++;
+        }
+    }
+
+    // check for <1>.0f
+    bool result( false );
+    while( !isSpace( *in ) && in != end ) {
+        if( *in == '.' ) {
+            result = true;
+            break;
+        }
+        result = isNumeric( *in );
+        if( !result ) {
+            return false;
+        }
+        in++;
+    }
+
+    // check for 1<.>0f
+    if( *in == '.' ) {
+        in++;
+    } else {
+        return false;
+    }
+
+    // check for 1.<0>f
+    while( !isSpace( *in ) && in != end && *in != ',' ) {
+        result = isNumeric( *in );
+        if( !result ) {
+            return false;
+        }
+        in++;
+    }
+
+    return result;
+}
+
+template<class T>
+inline
+bool isCharacter( const T in ) {
+    return ( ( in >= 'a' && in <= 'z' ) || ( in >= 'A' && in <= 'Z' ) );
+}
+
+template<class T>
+inline
+bool isStringLiteral( const T in ) {
+    return ( in == '\"' );
+}
+
+template<class T>
+inline
+bool isHexLiteral( T *in, T *end ) {
+    if( *in == '0' ) {
+        if( in + 1 != end ) {
+            if( *( in + 1 ) == 'x' || *( in + 1 ) == 'X' ) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+template<class T>
+inline
+bool isReference( T *in, T *end ) {
+    if( *in == 'r' ) {
+        if( *(in+1) == 'e' ) {
+            if( *(in+2) == 'f' ) {
+                if( ( in + 2 ) != end ) {
+                    return true;
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+template<class T>
+inline
+bool isEndofLine( const T in ) {
+    return ( '\n' == in );
+}
+
+template<class T>
+inline
+static T *getNextSeparator( T *in, T *end ) {
+    while( !isSeparator( *in ) || in == end ) {
+        in++;
+    }
+    return in;
+}
+
+static const int ErrorHex2Decimal = 9999;
+
+inline
+int hex2Decimal( char in ) {
+    if( isNumeric( in ) ) {
+        return (int) in-48;
+    }
+    char hexCodeLower( 'a' ), hexCodeUpper( 'A' );
+    for( int i = 0; i<16; i++ ) {
+        if( in == hexCodeLower + i || in == hexCodeUpper + i ) {
+            return i+10;
+        }
+    }
+
+    return ErrorHex2Decimal;
+}
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC

+ 97 - 0
contrib/openddlparser/include/openddlparser/Value.h

@@ -0,0 +1,97 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+#ifndef OPENDDLPARSER_VALUE_H_INC
+#define OPENDDLPARSER_VALUE_H_INC
+
+#include <openddlparser/OpenDDLCommon.h>
+
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+///------------------------------------------------------------------------------------------------
+///	@brief  This class implements a value.
+///
+///	Values are used to store data types like boolean, integer, floats, double and many mode. To get
+///	an overview please check the enum VylueType ( @see Value::ValueType ).
+/// Values can be single items or lists of items. They are implemented as linked lists.
+///------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT Value {
+public:
+    ///	@brief  This enum describes the data type stored in the value.
+    enum ValueType {
+        ddl_none = -1,          ///< Nothing specified
+        ddl_bool = 0,           ///< A boolean type
+        ddl_int8,               ///< Integer type, 8 bytes
+        ddl_int16,              ///< Integer type, 16 bytes
+        ddl_int32,              ///< Integer type, 32 bytes
+        ddl_int64,              ///< Integer type, 64 bytes
+        ddl_unsigned_int8,      ///< Unsigned integer type, 8 bytes
+        ddl_unsigned_int16,     ///< Unsigned integer type, 16 bytes
+        ddl_unsigned_int32,     ///< Unsigned integer type, 32 bytes
+        ddl_unsigned_int64,     ///< Unsigned integer type, 64 bytes
+        ddl_half,               
+        ddl_float,
+        ddl_double,
+        ddl_string,
+        ddl_ref,
+        ddl_types_max
+    };
+
+    Value();
+    ~Value();
+    void setBool( bool value );
+    bool getBool();
+    void setInt8( int8 value );
+    int8 getInt8();
+    void setInt16( int16 value );
+    int16  getInt16();
+    void setInt32( int32 value );
+    int32  getInt32();
+    void setInt64( int64 value );
+    int64  getInt64();
+    void setFloat( float value );
+    float getFloat() const;
+    void setDouble( double value );
+    double getDouble() const;
+    void setString( const std::string &str );
+    const char *getString() const;
+    void dump();
+    void setNext( Value *next );
+    Value *getNext() const;
+
+    ValueType m_type;
+    size_t m_size;
+    unsigned char *m_data;
+    Value *m_next;
+};
+
+struct DLL_ODDLPARSER_EXPORT ValueAllocator {
+    static Value *allocPrimData( Value::ValueType type, size_t len = 1 );
+    static void releasePrimData( Value **data );
+};
+
+END_ODDLPARSER_NS
+
+#endif // OPENDDLPARSER_VALUE_H_INC

+ 46 - 46
include/assimp/Compiler/pushpack1.h

@@ -1,46 +1,46 @@
-
-
-// ===============================================================================
-// May be included multiple times - sets structure packing to 1 
-// for all supported compilers. #include <poppack1.h> reverts the changes.
-//
-// Currently this works on the following compilers:
-// MSVC 7,8,9
-// GCC
-// BORLAND (complains about 'pack state changed but not reverted', but works)
-// Clang
-//
-//
-// USAGE:
-//
-// struct StructToBePacked {
-// } PACK_STRUCT;
-//
-// ===============================================================================
-
-#ifdef AI_PUSHPACK_IS_DEFINED
-#	error poppack1.h must be included after pushpack1.h
-#endif
-
-#if defined(_MSC_VER) ||  defined(__BORLANDC__) ||	defined (__BCPLUSPLUS__)
-#	pragma pack(push,1)
-#	define PACK_STRUCT
-#elif defined( __GNUC__ )
-#	if defined(__clang__)
-#		define PACK_STRUCT	__attribute__((__packed__))
-#	else
-#		define PACK_STRUCT	__attribute__((gcc_struct, __packed__))
-#	endif
-#else
-#	error Compiler not supported
-#endif
-
-#if defined(_MSC_VER)
-
-// C4103: Packing was changed after the inclusion of the header, propably missing #pragma pop
-#	pragma warning (disable : 4103) 
-#endif
-
-#define AI_PUSHPACK_IS_DEFINED
-
-
+
+
+// ===============================================================================
+// May be included multiple times - sets structure packing to 1 
+// for all supported compilers. #include <poppack1.h> reverts the changes.
+//
+// Currently this works on the following compilers:
+// MSVC 7,8,9
+// GCC
+// BORLAND (complains about 'pack state changed but not reverted', but works)
+// Clang
+//
+//
+// USAGE:
+//
+// struct StructToBePacked {
+// } PACK_STRUCT;
+//
+// ===============================================================================
+
+#ifdef AI_PUSHPACK_IS_DEFINED
+#	error poppack1.h must be included after pushpack1.h
+#endif
+
+#if defined(_MSC_VER) ||  defined(__BORLANDC__) ||	defined (__BCPLUSPLUS__)
+#	pragma pack(push,1)
+#	define PACK_STRUCT
+#elif defined( __GNUC__ )
+#	if !defined(HOST_MINGW)
+#		define PACK_STRUCT	__attribute__((__packed__))
+#	else
+#		define PACK_STRUCT	__attribute__((gcc_struct, __packed__))
+#	endif
+#else
+#	error Compiler not supported
+#endif
+
+#if defined(_MSC_VER)
+
+// C4103: Packing was changed after the inclusion of the header, propably missing #pragma pop
+#	pragma warning (disable : 4103) 
+#endif
+
+#define AI_PUSHPACK_IS_DEFINED
+
+

+ 185 - 9
include/assimp/Exporter.hpp

@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
 
 
 #include "cexport.h"
 #include "cexport.h"
+#include <map>
 
 
 namespace Assimp	{
 namespace Assimp	{
 	class ExporterPimpl;
 	class ExporterPimpl;
@@ -72,6 +73,9 @@ namespace Assimp	{
  * #ExportToBlob is especially useful if you intend to work 
  * #ExportToBlob is especially useful if you intend to work 
  * with the data in-memory. 
  * with the data in-memory. 
 */
 */
+
+class ASSIMP_API ExportProperties;
+
 class ASSIMP_API Exporter
 class ASSIMP_API Exporter
 	// TODO: causes good ol' base class has no dll interface warning
 	// TODO: causes good ol' base class has no dll interface warning
 //#ifdef __cplusplus
 //#ifdef __cplusplus
@@ -81,7 +85,7 @@ class ASSIMP_API Exporter
 public:
 public:
 
 
 	/** Function pointer type of a Export worker function */
 	/** Function pointer type of a Export worker function */
-	typedef void (*fpExportFunc)(const char*,IOSystem*, const aiScene*);
+	typedef void (*fpExportFunc)(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 
 
 	/** Internal description of an Assimp export format option */
 	/** Internal description of an Assimp export format option */
 	struct ExportFormatEntry
 	struct ExportFormatEntry
@@ -171,8 +175,8 @@ public:
 	*   Any IO handlers set via #SetIOHandler are ignored here.
 	*   Any IO handlers set via #SetIOHandler are ignored here.
 	* @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. */
-	const aiExportDataBlob* ExportToBlob(  const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u );
-	inline const aiExportDataBlob* ExportToBlob(  const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u );
+	const aiExportDataBlob* ExportToBlob(  const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
+	inline const aiExportDataBlob* ExportToBlob(  const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
 
 
 
 
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
@@ -208,8 +212,8 @@ public:
 	 * @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.*/
-	aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing = 0u);
-	inline aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath,  unsigned int pPreprocessing = 0u);
+	aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
+	inline aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath,  unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
 
 
 
 
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
@@ -309,16 +313,188 @@ protected:
 };
 };
 
 
 
 
+class ASSIMP_API ExportProperties
+{
+public:
+	// Data type to store the key hash
+	typedef unsigned int KeyType;
+	
+	// typedefs for our four configuration maps.
+	// We don't need more, so there is no need for a generic solution
+	typedef std::map<KeyType, int> IntPropertyMap;
+	typedef std::map<KeyType, float> FloatPropertyMap;
+	typedef std::map<KeyType, std::string> StringPropertyMap;
+	typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
+
+public:
+
+	/** Standard constructor
+	* @see ExportProperties()
+	*/
+
+	ExportProperties();
+
+	// -------------------------------------------------------------------
+	/** Copy constructor.
+	 * 
+	 * This copies the configuration properties of another ExportProperties.
+	 * @see ExportProperties(const ExportProperties& other)
+	 */
+	ExportProperties(const ExportProperties& other);
+
+	// -------------------------------------------------------------------
+	/** Set an integer configuration property.
+	 * @param szName Name of the property. All supported properties
+	 *   are defined in the aiConfig.g header (all constants share the
+	 *   prefix AI_CONFIG_XXX and are simple strings).
+	 * @param iValue New value of the property
+	 * @param bWasExisting Optional pointer to receive true if the
+	 *   property was set before. The new value replaces the previous value
+	 *   in this case.
+	 * @note Property of different types (float, int, string ..) are kept
+	 *   on different stacks, so calling SetPropertyInteger() for a 
+	 *   floating-point property has no effect - the loader will call
+	 *   GetPropertyFloat() to read the property, but it won't be there.
+	 */
+	void SetPropertyInteger(const char* szName, int iValue, 
+		bool* bWasExisting = NULL);
+
+	// -------------------------------------------------------------------
+	/** Set a boolean configuration property. Boolean properties
+	 *  are stored on the integer stack internally so it's possible
+	 *  to set them via #SetPropertyBool and query them with
+	 *  #GetPropertyBool and vice versa.
+	 * @see SetPropertyInteger()
+	 */
+	void SetPropertyBool(const char* szName, bool value, bool* bWasExisting = NULL)	{
+		SetPropertyInteger(szName,value,bWasExisting);
+	}
+
+	// -------------------------------------------------------------------
+	/** Set a floating-point configuration property.
+	 * @see SetPropertyInteger()
+	 */
+	void SetPropertyFloat(const char* szName, float fValue, 
+		bool* bWasExisting = NULL);
+
+	// -------------------------------------------------------------------
+	/** Set a string configuration property.
+	 * @see SetPropertyInteger()
+	 */
+	void SetPropertyString(const char* szName, const std::string& sValue, 
+		bool* bWasExisting = NULL);
+
+	// -------------------------------------------------------------------
+	/** Set a matrix configuration property.
+	 * @see SetPropertyInteger()
+	 */
+	void SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue, 
+		bool* bWasExisting = NULL);
+
+	// -------------------------------------------------------------------
+	/** Get a configuration property.
+	 * @param szName Name of the property. All supported properties
+	 *   are defined in the aiConfig.g header (all constants share the
+	 *   prefix AI_CONFIG_XXX).
+	 * @param iErrorReturn Value that is returned if the property 
+	 *   is not found. 
+	 * @return Current value of the property
+	 * @note Property of different types (float, int, string ..) are kept
+	 *   on different lists, so calling SetPropertyInteger() for a 
+	 *   floating-point property has no effect - the loader will call
+	 *   GetPropertyFloat() to read the property, but it won't be there.
+	 */
+	int GetPropertyInteger(const char* szName, 
+		int iErrorReturn = 0xffffffff) const;
+
+	// -------------------------------------------------------------------
+	/** Get a boolean configuration property. Boolean properties
+	 *  are stored on the integer stack internally so it's possible
+	 *  to set them via #SetPropertyBool and query them with
+	 *  #GetPropertyBool and vice versa.
+	 * @see GetPropertyInteger()
+	 */
+	bool GetPropertyBool(const char* szName, bool bErrorReturn = false) const {
+		return GetPropertyInteger(szName,bErrorReturn)!=0;
+	}
+
+	// -------------------------------------------------------------------
+	/** Get a floating-point configuration property
+	 * @see GetPropertyInteger()
+	 */
+	float GetPropertyFloat(const char* szName, 
+		float fErrorReturn = 10e10f) const;
+
+	// -------------------------------------------------------------------
+	/** Get a string configuration property
+	 *
+	 *  The return value remains valid until the property is modified.
+	 * @see GetPropertyInteger()
+	 */
+	const std::string GetPropertyString(const char* szName,
+		const std::string& sErrorReturn = "") const;
+
+	// -------------------------------------------------------------------
+	/** Get a matrix configuration property
+	 *
+	 *  The return value remains valid until the property is modified.
+	 * @see GetPropertyInteger()
+	 */
+	const aiMatrix4x4 GetPropertyMatrix(const char* szName,
+		const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const;
+
+	// -------------------------------------------------------------------
+	/** Determine a integer configuration property has been set.
+	* @see HasPropertyInteger()
+	 */
+	bool HasPropertyInteger(const char* szName) const;
+
+	/** Determine a boolean configuration property has been set.
+	* @see HasPropertyBool()
+	 */
+	bool HasPropertyBool(const char* szName) const;
+
+	/** Determine a boolean configuration property has been set.
+	* @see HasPropertyFloat()
+	 */
+	bool HasPropertyFloat(const char* szName) const;
+
+	/** Determine a String configuration property has been set.
+	* @see HasPropertyString()
+	 */
+	bool HasPropertyString(const char* szName) const;
+
+	/** Determine a Matrix configuration property has been set.
+	* @see HasPropertyMatrix()
+	 */
+	bool HasPropertyMatrix(const char* szName) const;
+
+protected:
+
+	/** List of integer properties */
+	IntPropertyMap mIntProperties;
+
+	/** List of floating-point properties */
+	FloatPropertyMap mFloatProperties;
+
+	/** List of string properties */
+	StringPropertyMap mStringProperties;
+
+	/** List of Matrix properties */
+	MatrixPropertyMap mMatrixProperties;
+};
+
+
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
-inline const aiExportDataBlob* Exporter :: ExportToBlob(  const aiScene* pScene, const std::string& pFormatId,unsigned int pPreprocessing ) 
+inline const aiExportDataBlob* Exporter :: ExportToBlob(  const aiScene* pScene, const std::string& pFormatId,unsigned int pPreprocessing, const ExportProperties* pProperties) 
 {
 {
-	return ExportToBlob(pScene,pFormatId.c_str(),pPreprocessing);
+	return ExportToBlob(pScene,pFormatId.c_str(),pPreprocessing, pProperties);
 }
 }
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
-inline aiReturn Exporter :: Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing )
+inline aiReturn Exporter :: Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing, const ExportProperties* pProperties)
 {
 {
-	return Export(pScene,pFormatId.c_str(),pPath.c_str(),pPreprocessing);
+	return Export(pScene,pFormatId.c_str(),pPath.c_str(),pPreprocessing, pProperties);
 }
 }
 
 
 } // namespace Assimp
 } // namespace Assimp

+ 11 - 2
include/assimp/config.h

@@ -885,7 +885,7 @@ enum aiComponent
  * Property type: Bool. Default value: false.
  * Property type: Bool. Default value: false.
  */
  */
 #define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION"
 #define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION"
-
+
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** @brief Specifies whether the Collada loader will invert the transparency value.
 /** @brief Specifies whether the Collada loader will invert the transparency value.
  *
  *
@@ -894,6 +894,15 @@ enum aiComponent
  * not respect the standard and do the opposite of what is normally expected.
  * not respect the standard and do the opposite of what is normally expected.
  * Property type: Bool. Default value: false.
  * Property type: Bool. Default value: false.
  */
  */
-#define AI_CONFIG_IMPORT_COLLADA_INVERT_TRANSPARENCY "IMPORT_COLLADA_INVERT_TRANSPARENCY"
+#define AI_CONFIG_IMPORT_COLLADA_INVERT_TRANSPARENCY "IMPORT_COLLADA_INVERT_TRANSPARENCY"
+
+// ---------- All the Export defines ------------
+
+/** @brief Specifies the xfile use double for real values of float
+ *
+ * Property type: Bool. Default value: false.
+ */
+
+#define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
 
 
 #endif // !! AI_CONFIG_H_INC
 #endif // !! AI_CONFIG_H_INC

+ 53 - 44
port/jassimp/build.xml

@@ -1,45 +1,54 @@
 <project name="jassimp" basedir="." default="all">
 <project name="jassimp" basedir="." default="all">
-  <property name="native-src.dir" value="jassimp-native/src" />
-  <property name="src.dir" value="jassimp/src" />
-  <property name="jassimp.lwjgl-src.dir" value="jassimp.lwjgl/src" />
-  <property name="build.dir" value="jassimp/bin" />
-  <property name="dist.dir" value="dist" />
-  <property name="doc.dir" value="doc" />
-  
-  <path id="classpath">
-  </path>
-
-  <target name="compile">
-    <delete dir="${build.dir}" />
-    <mkdir dir="${build.dir}" />
-    <javac classpathref="classpath" destdir="${build.dir}" srcdir="${src.dir}"
-      source="1.6" target="1.6" includeantruntime="false">
-    </javac>
-  </target>
-
-  <target name="jni_header">
-    <mkdir dir="${native-src.dir}" />
-    <javah outputfile="${native-src.dir}/jassimp.h" force="yes">
-      <classpath>
-        <pathelement path="${build.dir}" />
-      </classpath>
-      <class name="jassimp.Jassimp" />
-    </javah>
-  </target>
-  
-  <target name="package" depends="compile">
-    <jar destfile="${dist.dir}/jassimp.jar" basedir="${build.dir}">
-    </jar>
-  </target>
-  
-  
-  <target name="doc">
-    <delete dir="${doc.dir}" />
-    <javadoc access="public" author="false" destdir="${doc.dir}"
-      sourcepath="${src.dir}">
-    </javadoc>
-  </target>
-  
-  <target name="all" depends="package, doc">
-  </target>
-</project>
+	<property name="native-src.dir" value="jassimp-native/src" />
+	<property name="src.dir" value="jassimp/src" />
+	<property name="jassimp.lwjgl-src.dir" value="jassimp.lwjgl/src" />
+	<property name="build.dir" value="jassimp/bin" />
+	<property name="dist.dir" value="dist" />
+	<property name="doc.dir" value="doc" />
+	<property environment="env"/>
+	<property name="ndk.dir" value="${env.NDK_HOME}" />
+	<property name="my.dir" value="${env.PWD}" />
+
+	<path id="classpath">
+	</path>
+
+	<target name="compile">
+		<delete dir="${build.dir}" />
+		<mkdir dir="${build.dir}" />
+		<javac classpathref="classpath" destdir="${build.dir}" srcdir="${src.dir}"
+			source="1.6" target="1.6" includeantruntime="false">
+		</javac>
+	</target>
+
+	<target name="jni_header">
+		<mkdir dir="${native-src.dir}" />
+		<javah outputfile="${native-src.dir}/jassimp.h" force="yes">
+			<classpath>
+				<pathelement path="${build.dir}" />
+			</classpath>
+			<class name="jassimp.Jassimp" />
+		</javah>
+	</target>
+
+	<target name="ndk-jni" depends="package">
+		<exec executable="${ndk.dir}/ndk-build">
+			<arg line="all NDK_PROJECT_PATH=${my.dir}/workspaces/Android-NDK"/>
+		</exec>
+	</target>
+
+	<target name="package" depends="compile">
+		<jar destfile="${dist.dir}/jassimp.jar" basedir="${build.dir}">
+		</jar>
+	</target>
+
+
+	<target name="doc">
+		<delete dir="${doc.dir}" />
+		<javadoc access="public" author="false" destdir="${doc.dir}"
+			sourcepath="${src.dir}">
+		</javadoc>
+	</target>
+
+	<target name="all" depends="package, doc">
+	</target>
+</project>

+ 13 - 0
port/jassimp/jassimp-native/Android.mk

@@ -0,0 +1,13 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := jassimp
+LOCAL_SRC_FILES :=  src/jassimp.cpp
+
+LOCAL_CFLAGS += -DJNI_LOG
+
+#LOCAL_STATIC_LIBRARIES := assimp_static
+LOCAL_SHARED_LIBRARIES := assimp
+LOCAL_LDLIBS    := -llog
+
+include $(BUILD_SHARED_LIBRARY)

+ 59 - 25
port/jassimp/jassimp-native/src/jassimp.cpp

@@ -5,12 +5,16 @@
 
 
 
 
 #ifdef JNI_LOG
 #ifdef JNI_LOG
+#ifdef ANDROID
+#include <android/log.h>
+#define lprintf(...) __android_log_print(ANDROID_LOG_VERBOSE, __func__, __VA_ARGS__)
+#else
 #define lprintf(...) printf (__VA_ARGS__)
 #define lprintf(...) printf (__VA_ARGS__)
+#endif /* ANDROID */
 #else
 #else
 #define lprintf
 #define lprintf
 #endif
 #endif
 
 
-
 static bool createInstance(JNIEnv *env, const char* className, jobject& newInstance)
 static bool createInstance(JNIEnv *env, const char* className, jobject& newInstance)
 {
 {
 	jclass clazz = env->FindClass(className);
 	jclass clazz = env->FindClass(className);
@@ -30,6 +34,7 @@ static bool createInstance(JNIEnv *env, const char* className, jobject& newInsta
 	}
 	}
 
 
 	newInstance = env->NewObject(clazz, ctr_id);
 	newInstance = env->NewObject(clazz, ctr_id);
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == newInstance) 
 	if (NULL == newInstance) 
 	{
 	{
@@ -41,7 +46,7 @@ static bool createInstance(JNIEnv *env, const char* className, jobject& newInsta
 }
 }
 
 
 
 
-static bool createInstance(JNIEnv *env, const char* className, const char* signature, const jvalue* params, jobject& newInstance)
+static bool createInstance(JNIEnv *env, const char* className, const char* signature,/* const*/ jvalue* params, jobject& newInstance)
 {
 {
 	jclass clazz = env->FindClass(className);
 	jclass clazz = env->FindClass(className);
 
 
@@ -60,6 +65,7 @@ static bool createInstance(JNIEnv *env, const char* className, const char* signa
 	}
 	}
 
 
 	newInstance = env->NewObjectA(clazz, ctr_id, params);
 	newInstance = env->NewObjectA(clazz, ctr_id, params);
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == newInstance) 
 	if (NULL == newInstance) 
 	{
 	{
@@ -82,6 +88,7 @@ static bool getField(JNIEnv *env, jobject object, const char* fieldName, const c
 	}
 	}
 
 
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature);
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature);
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == fieldId)
 	if (NULL == fieldId)
 	{
 	{
@@ -106,6 +113,7 @@ static bool setIntField(JNIEnv *env, jobject object, const char* fieldName, jint
 	}
 	}
 
 
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, "I");
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, "I");
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == fieldId)
 	if (NULL == fieldId)
 	{
 	{
@@ -130,6 +138,7 @@ static bool setFloatField(JNIEnv *env, jobject object, const char* fieldName, jf
 	}
 	}
 
 
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, "F");
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, "F");
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == fieldId)
 	if (NULL == fieldId)
 	{
 	{
@@ -154,6 +163,7 @@ static bool setObjectField(JNIEnv *env, jobject object, const char* fieldName, c
 	}
 	}
 
 
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature);
 	jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature);
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == fieldId)
 	if (NULL == fieldId)
 	{
 	{
@@ -192,7 +202,7 @@ static bool getStaticField(JNIEnv *env, const char* className, const char* field
 
 
 
 
 static bool call(JNIEnv *env, jobject object, const char* typeName, const char* methodName, 
 static bool call(JNIEnv *env, jobject object, const char* typeName, const char* methodName, 
-	const char* signature, const jvalue* params)
+	const char* signature,/* const*/ jvalue* params)
 {
 {
 	jclass clazz = env->FindClass(typeName);
 	jclass clazz = env->FindClass(typeName);
 
 
@@ -203,6 +213,7 @@ static bool call(JNIEnv *env, jobject object, const char* typeName, const char*
 	}
 	}
 
 
 	jmethodID mid = env->GetMethodID(clazz, methodName, signature);
 	jmethodID mid = env->GetMethodID(clazz, methodName, signature);
+	env->DeleteLocalRef(clazz);
 
 
 	if (NULL == mid)
 	if (NULL == mid)
 	{
 	{
@@ -210,6 +221,27 @@ static bool call(JNIEnv *env, jobject object, const char* typeName, const char*
 		return false;
 		return false;
 	}
 	}
 
 
+	jboolean jReturnValue = env->CallBooleanMethod(object, mid, params[0].l);
+
+	return (bool)jReturnValue;
+}
+static bool callv(JNIEnv *env, jobject object, const char* typeName,
+		const char* methodName, const char* signature,/* const*/ jvalue* params) {
+	jclass clazz = env->FindClass(typeName);
+
+	if (NULL == clazz) {
+		lprintf("could not find class %s\n", typeName);
+		return false;
+	}
+
+	jmethodID mid = env->GetMethodID(clazz, methodName, signature);
+	env->DeleteLocalRef(clazz);
+
+	if (NULL == mid) {
+		lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName);
+		return false;
+	}
+
 	env->CallVoidMethodA(object, mid, params);
 	env->CallVoidMethodA(object, mid, params);
 
 
 	return true;
 	return true;
@@ -217,7 +249,7 @@ static bool call(JNIEnv *env, jobject object, const char* typeName, const char*
 
 
 
 
 static bool callStaticObject(JNIEnv *env, const char* typeName, const char* methodName, 
 static bool callStaticObject(JNIEnv *env, const char* typeName, const char* methodName, 
-	const char* signature, const jvalue* params, jobject& returnValue)
+	const char* signature,/* const*/ jvalue* params, jobject& returnValue)
 {
 {
 	jclass clazz = env->FindClass(typeName);
 	jclass clazz = env->FindClass(typeName);
 
 
@@ -338,7 +370,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		/* set general mesh data in java */
 		/* set general mesh data in java */
 		jvalue setTypesParams[1];
 		jvalue setTypesParams[1];
 		setTypesParams[0].i = cMesh->mPrimitiveTypes;
 		setTypesParams[0].i = cMesh->mPrimitiveTypes;
-		if (!call(env, jMesh, "jassimp/AiMesh", "setPrimitiveTypes", "(I)V", setTypesParams))
+		if (!callv(env, jMesh, "jassimp/AiMesh", "setPrimitiveTypes", "(I)V", setTypesParams))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -380,7 +412,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		allocateBuffersParams[1].i = cMesh->mNumFaces;
 		allocateBuffersParams[1].i = cMesh->mNumFaces;
 		allocateBuffersParams[2].z = isPureTriangle;
 		allocateBuffersParams[2].z = isPureTriangle;
 		allocateBuffersParams[3].i = (jint) faceBufferSize;
 		allocateBuffersParams[3].i = (jint) faceBufferSize;
-		if (!call(env, jMesh, "jassimp/AiMesh", "allocateBuffers", "(IIZI)V", allocateBuffersParams))
+		if (!callv(env, jMesh, "jassimp/AiMesh", "allocateBuffers", "(IIZI)V", allocateBuffersParams))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -470,7 +502,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			jvalue allocateDataChannelParams[2];
 			jvalue allocateDataChannelParams[2];
 			allocateDataChannelParams[0].i = 0;
 			allocateDataChannelParams[0].i = 0;
 			allocateDataChannelParams[1].i = 0;
 			allocateDataChannelParams[1].i = 0;
-			if (!call(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+			if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
 			{
 			{
 				lprintf("could not allocate normal data channel\n");
 				lprintf("could not allocate normal data channel\n");
 				return false;
 				return false;
@@ -491,7 +523,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			jvalue allocateDataChannelParams[2];
 			jvalue allocateDataChannelParams[2];
 			allocateDataChannelParams[0].i = 1;
 			allocateDataChannelParams[0].i = 1;
 			allocateDataChannelParams[1].i = 0;
 			allocateDataChannelParams[1].i = 0;
-			if (!call(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+			if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
 			{
 			{
 				lprintf("could not allocate tangents data channel\n");
 				lprintf("could not allocate tangents data channel\n");
 				return false;
 				return false;
@@ -512,7 +544,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			jvalue allocateDataChannelParams[2];
 			jvalue allocateDataChannelParams[2];
 			allocateDataChannelParams[0].i = 2;
 			allocateDataChannelParams[0].i = 2;
 			allocateDataChannelParams[1].i = 0;
 			allocateDataChannelParams[1].i = 0;
-			if (!call(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+			if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
 			{
 			{
 				lprintf("could not allocate bitangents data channel\n");
 				lprintf("could not allocate bitangents data channel\n");
 				return false;
 				return false;
@@ -535,7 +567,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				jvalue allocateDataChannelParams[2];
 				jvalue allocateDataChannelParams[2];
 				allocateDataChannelParams[0].i = 3;
 				allocateDataChannelParams[0].i = 3;
 				allocateDataChannelParams[1].i = c;
 				allocateDataChannelParams[1].i = c;
-				if (!call(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+				if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
 				{
 				{
 					lprintf("could not allocate colorset data channel\n");
 					lprintf("could not allocate colorset data channel\n");
 					return false;
 					return false;
@@ -574,7 +606,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				}
 				}
 
 
 				allocateDataChannelParams[1].i = c;
 				allocateDataChannelParams[1].i = c;
-				if (!call(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+				if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
 				{
 				{
 					lprintf("could not allocate texture coordinates data channel\n");
 					lprintf("could not allocate texture coordinates data channel\n");
 					return false;
 					return false;
@@ -671,7 +703,7 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				wrapParams[0].l = jMatrixArr;
 				wrapParams[0].l = jMatrixArr;
 				jobject jMatrix;
 				jobject jMatrix;
 				
 				
-				if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapMatrix", "([F)Ljava/lang/Object;", wrapParams, jMatrix)) 
+				if (!callStaticObject(env, "jassimp/Jassimp", "wrapMatrix", "([F)Ljava/lang/Object;", wrapParams, jMatrix))
 				{
 				{
 					return false;
 					return false;
 				}
 				}
@@ -701,6 +733,8 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				}
 				}
 			}
 			}
 		}
 		}
+		env->DeleteLocalRef(jMeshes);
+		env->DeleteLocalRef(jMesh);
 	}
 	}
 
 
 	return true;
 	return true;
@@ -719,7 +753,7 @@ static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobj
 	wrapMatParams[0].l = jMatrixArr;
 	wrapMatParams[0].l = jMatrixArr;
 	jobject jMatrix;
 	jobject jMatrix;
 				
 				
-	if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapMatrix", "([F)Ljava/lang/Object;", wrapMatParams, jMatrix)) 
+	if (!callStaticObject(env, "jassimp/Jassimp", "wrapMatrix", "([F)Ljava/lang/Object;", wrapMatParams, jMatrix))
 	{
 	{
 		return false;
 		return false;
 	}
 	}
@@ -749,7 +783,7 @@ static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobj
 	wrapNodeParams[2].l = jMeshrefArr;
 	wrapNodeParams[2].l = jMeshrefArr;
 	wrapNodeParams[3].l = jNodeName;
 	wrapNodeParams[3].l = jNodeName;
 	jobject jNode;
 	jobject jNode;
-	if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapSceneNode", 
+	if (!callStaticObject(env, "jassimp/Jassimp", "wrapSceneNode",
 		"(Ljava/lang/Object;Ljava/lang/Object;[ILjava/lang/String;)Ljava/lang/Object;", wrapNodeParams, jNode)) 
 		"(Ljava/lang/Object;Ljava/lang/Object;[ILjava/lang/String;)Ljava/lang/Object;", wrapNodeParams, jNode)) 
 	{
 	{
 		return false;
 		return false;
@@ -842,7 +876,7 @@ static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 			setNumberParams[0].i = ttInd;
 			setNumberParams[0].i = ttInd;
 			setNumberParams[1].i = num;
 			setNumberParams[1].i = num;
 
 
-			if (!call(env, jMaterial, "jassimp/AiMaterial", "setTextureNumber", "(II)V", setNumberParams))
+			if (!callv(env, jMaterial, "jassimp/AiMaterial", "setTextureNumber", "(II)V", setNumberParams))
 			{
 			{
 				return false;
 				return false;
 			}
 			}
@@ -880,7 +914,7 @@ static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				wrapColorParams[0].f = ((float*) cProperty->mData)[0];
 				wrapColorParams[0].f = ((float*) cProperty->mData)[0];
 				wrapColorParams[1].f = ((float*) cProperty->mData)[1];
 				wrapColorParams[1].f = ((float*) cProperty->mData)[1];
 				wrapColorParams[2].f = ((float*) cProperty->mData)[2];
 				wrapColorParams[2].f = ((float*) cProperty->mData)[2];
-				if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jData)) 
+				if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jData))
 				{
 				{
 					return false;
 					return false;
 				}
 				}
@@ -905,7 +939,7 @@ static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 				wrapColorParams[1].f = ((float*) cProperty->mData)[1];
 				wrapColorParams[1].f = ((float*) cProperty->mData)[1];
 				wrapColorParams[2].f = ((float*) cProperty->mData)[2];
 				wrapColorParams[2].f = ((float*) cProperty->mData)[2];
 				wrapColorParams[3].f = ((float*) cProperty->mData)[3];
 				wrapColorParams[3].f = ((float*) cProperty->mData)[3];
-				if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapColor4", "(FFFF)Ljava/lang/Object;", wrapColorParams, jData)) 
+				if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor4", "(FFFF)Ljava/lang/Object;", wrapColorParams, jData))
 				{
 				{
 					return false;
 					return false;
 				}
 				}
@@ -1137,7 +1171,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapColorParams[1].f = cLight->mColorDiffuse.g;
 		wrapColorParams[1].f = cLight->mColorDiffuse.g;
 		wrapColorParams[2].f = cLight->mColorDiffuse.b;
 		wrapColorParams[2].f = cLight->mColorDiffuse.b;
 		jobject jDiffuse;
 		jobject jDiffuse;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jDiffuse)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jDiffuse))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1146,7 +1180,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapColorParams[1].f = cLight->mColorSpecular.g;
 		wrapColorParams[1].f = cLight->mColorSpecular.g;
 		wrapColorParams[2].f = cLight->mColorSpecular.b;
 		wrapColorParams[2].f = cLight->mColorSpecular.b;
 		jobject jSpecular;
 		jobject jSpecular;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jSpecular)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jSpecular))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1155,7 +1189,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapColorParams[1].f = cLight->mColorAmbient.g;
 		wrapColorParams[1].f = cLight->mColorAmbient.g;
 		wrapColorParams[2].f = cLight->mColorAmbient.b;
 		wrapColorParams[2].f = cLight->mColorAmbient.b;
 		jobject jAmbient;
 		jobject jAmbient;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jAmbient)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jAmbient))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1167,7 +1201,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapVec3Params[1].f = cLight->mPosition.y;
 		wrapVec3Params[1].f = cLight->mPosition.y;
 		wrapVec3Params[2].f = cLight->mPosition.z;
 		wrapVec3Params[2].f = cLight->mPosition.z;
 		jobject jPosition;
 		jobject jPosition;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapVec3Params, jPosition)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapVec3Params, jPosition))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1176,7 +1210,7 @@ static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapVec3Params[1].f = cLight->mPosition.y;
 		wrapVec3Params[1].f = cLight->mPosition.y;
 		wrapVec3Params[2].f = cLight->mPosition.z;
 		wrapVec3Params[2].f = cLight->mPosition.z;
 		jobject jDirection;
 		jobject jDirection;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapVec3Params, jDirection)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapVec3Params, jDirection))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1242,7 +1276,7 @@ static bool loadCameras(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapPositionParams[1].f = cCamera->mPosition.y;
 		wrapPositionParams[1].f = cCamera->mPosition.y;
 		wrapPositionParams[2].f = cCamera->mPosition.z;
 		wrapPositionParams[2].f = cCamera->mPosition.z;
 		jobject jPosition;
 		jobject jPosition;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jPosition)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jPosition))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1251,7 +1285,7 @@ static bool loadCameras(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapPositionParams[1].f = cCamera->mUp.y;
 		wrapPositionParams[1].f = cCamera->mUp.y;
 		wrapPositionParams[2].f = cCamera->mUp.z;
 		wrapPositionParams[2].f = cCamera->mUp.z;
 		jobject jUp;
 		jobject jUp;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jUp)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jUp))
 		{
 		{
 			return false;
 			return false;
 		}
 		}
@@ -1260,7 +1294,7 @@ static bool loadCameras(JNIEnv *env, const aiScene* cScene, jobject& jScene)
 		wrapPositionParams[1].f = cCamera->mLookAt.y;
 		wrapPositionParams[1].f = cCamera->mLookAt.y;
 		wrapPositionParams[2].f = cCamera->mLookAt.z;
 		wrapPositionParams[2].f = cCamera->mLookAt.z;
 		jobject jLookAt;
 		jobject jLookAt;
-		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jLookAt)) 
+		if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jLookAt))
 		{
 		{
 			return false;
 			return false;
 		}
 		}

+ 0 - 33
test/RunSingleUnitTestSuite.bat

@@ -1,33 +0,0 @@
-
-rem ------------------------------------------------------------------------------
-rem Tiny script to execute a single unit test suite.
-rem 
-rem Usage:
-rem    SET  OUTDIR=<directory_for_test_results>
-rem    SET  BINDIR=<directory_where_binaries_are_stored>
-rem
-rem    CALL RunSingleUnitTestSuite <name_of_test> <output_file>
-rem
-rem Post:
-rem    FIRSTUTNA       - if the test wasn't found, receives the test name
-rem    FIRSTUTFAILUR   - if the test failed, receives the test name
-rem
-rem ------------------------------------------------------------------------------
-IF NOT EXIST %BINDIR%\%1\unit.exe (
-
-   echo NOT AVAILABLE. Please rebuild this configuration
-   echo Unable to find %BINDIR%\%1\unit.exe > %OUTDIR%%2
-   SET FIRSTUTNA=%2
-) ELSE (
-
-   %BINDIR%\%1\unit.exe > %OUTDIR%%2
-   IF errorlevel == 0 ( 
-      echo SUCCESS
-   ) ELSE (
-      echo FAILURE, check output file: %2
-      SET FIRSTUTFAILURE=%2
-   )
-)
-
-echo.
-echo.

+ 0 - 94
test/RunUnitTestSuite.bat

@@ -1,94 +0,0 @@
-rem ------------------------------------------------------------------------------
-rem Tiny script to execute Assimp's fully unit test suite for all configurations
-rem 
-rem Usage: call RunUnitTestSuite
-rem ------------------------------------------------------------------------------
-
-rem Setup the console environment
-set errorlevel=0
-color 4e
-cls
-
-@echo off
-
-rem Setup target architecture
-SET ARCHEXT=x64
-IF %PROCESSOR_ARCHITECTURE% == x86 (
-   SET ARCHEXT=win32
-)
-
-rem Setup standard paths from here
-SET OUTDIR=results\
-SET BINDIR=..\bin\
-SET FIRSTUTFAILURE=nil
-SET FIRSTUTNA=nil
-
-echo #=====================================================================
-echo # Open Asset Import Library - Unittests                               
-echo #=====================================================================
-echo #                                                                     
-echo # Executes the Assimp library unit test suite for the following                
-echo # build configurations (if available):                                               
-echo #                                                                     
-echo #  Release                                                           
-echo #  Release -st                                                        
-echo #  Release -noboost                                                   
-echo #  Release -dll                                                       
-echo #                                                                     
-echo #  Debug                                                              
-echo #  Debug   -st                                                        
-echo #  Debug   -noboost                                                   
-echo #  Debug   -dll                                                                                                                        
-echo ======================================================================
-echo.
-echo.
-
-
-echo assimp-core release 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_release_%ARCHEXT% release.txt
-
-echo assimp-core release -st 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_release-st_%ARCHEXT% release-st.txt
-
-echo assimp-core release -noboost 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_release-noboost-st_%ARCHEXT% release-st-noboost.txt
-
-echo assimp-core release -dll 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_release-dll_%ARCHEXT% release-dll.txt
-
-echo assimp-core debug
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_debug_%ARCHEXT% debug.txt
-
-echo assimp-core debug -st 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_debug-st_%ARCHEXT% debug-st.txt
-
-echo assimp-core debug -noboost 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_debug-noboost-st_%ARCHEXT% debug-st-noboost.txt
-
-echo assimp-core debug -dll 
-echo **********************************************************************
-call RunSingleUnitTestSuite unit_debug-dll_%ARCHEXT% debug-dll.txt
-
-
-echo ======================================================================
-IF %FIRSTUTNA% == nil (
-   echo All test configs have been found.
-) ELSE (
-   echo One or more test configs are not available.
-)
-
-IF %FIRSTUTFAILURE% == nil (
-   echo All tests have been successful. 
-) ELSE (
-   echo One or more tests failed.
-)
-echo.
-
-pause

BIN
test/models-nonbsd/FBX/2013_BINARY/anims_with_full_rotations_between_keys.fbx


+ 754 - 0
test/models-nonbsd/PLY/ant-half.ply

@@ -0,0 +1,754 @@
+ply
+format ascii 1.0
+element vertex 486
+property float32 x
+property float32 y
+property float32 z
+element face 912
+property list uint8 int32 vertex_indices
+end_header
+-1.106 3.844 9.073 
+-0.3523 0.4402 11.07 
+1.028 3.76 9.209 
+0.137 -0.5632 10.73 
+2.01 4.503 5.887 
+0.07813 5.232 6.794 
+-0.7266 3.741 3.839 
+-2.789 3.179 5.07 
+-0.9185 2.402 3.279 
+1.445 2.139 3.394 
+-3.114 1.498 5.285 
+-1.317 -1.269 8.385 
+-0.854 -1.319 5.036 
+-0.9351 5.347 0.6162 
+-0.8184 2.622 3.235 
+0.4875 5.529 -0.2241 
+3.193 2.756 1.633 
+3.213 1.145 -2.568 
+-2.25 1.208 2.767 
+0.3225 0.8339 3.323 
+1.354 -1.725 1.105 
+0.1887 1.133 -5.785 
+-3.637 2.696 0.3325 
+-3.706 0.8936 -0.5452 
+-0.4326 -0.8737 -4.095 
+-2.994 -0.4858 0.9023 
+0.1252 -2.079 -1.51 
+2.856 -0.7459 -1.187 
+2.32 3.733 8.13 
+2.031 3.721 9.095 
+2.819 3.567 8.537 
+1.994 2.581 9.711 
+2.64 2.491 9.542 
+3.187 2.528 8.375 
+1.628 2.491 7.518 
+1.62 3.721 8.274 
+0.9868 2.471 8.914 
+1.552 2.106 9.414 
+2.657 1.774 8.918 
+-1.805 3.733 8.13 
+-2.094 3.721 9.095 
+-1.306 3.567 8.537 
+-2.131 2.581 9.711 
+-1.485 2.491 9.542 
+-0.938 2.528 8.375 
+-2.497 2.491 7.518 
+-2.505 3.721 8.274 
+-3.138 2.471 8.914 
+-2.573 2.106 9.414 
+-1.469 1.774 8.918 
+1.549 3.638 6.803 
+1.355 3.638 6.7 
+1.424 5.126 6.883 
+1.615 5.083 6.981 
+1.169 3.638 6.815 
+1.237 5.115 6.997 
+1.176 3.638 7.035 
+1.241 5.061 7.21 
+1.369 3.638 7.138 
+1.433 5.018 7.308 
+1.556 3.638 7.023 
+1.62 5.029 7.194 
+1.625 6.512 7.421 
+1.811 6.429 7.504 
+1.437 6.49 7.531 
+1.434 6.386 7.724 
+1.619 6.304 7.807 
+1.808 6.326 7.697 
+1.945 7.702 8.276 
+2.121 7.585 8.335 
+1.754 7.672 8.38 
+1.74 7.525 8.542 
+1.916 7.408 8.601 
+2.107 7.439 8.497 
+2.362 8.615 9.391 
+2.526 8.473 9.417 
+2.168 8.578 9.487 
+2.138 8.398 9.608 
+2.303 8.255 9.635 
+2.497 8.293 9.539 
+2.847 9.189 10.69 
+2.998 9.03 10.68 
+2.649 9.148 10.78 
+2.603 8.947 10.85 
+2.753 8.788 10.84 
+2.95 8.83 10.75 
+3.368 9.385 12.08 
+3.503 9.22 12.03 
+3.167 9.342 12.16 
+3.101 9.134 12.18 
+3.236 8.97 12.13 
+3.438 9.013 12.06 
+3.889 9.189 13.48 
+4.01 9.03 13.39 
+3.684 9.148 13.54 
+3.599 8.947 13.51 
+3.719 8.788 13.42 
+3.925 8.83 13.36 
+4.374 8.615 14.77 
+4.481 8.473 14.65 
+4.165 8.578 14.83 
+4.063 8.398 14.76 
+4.17 8.255 14.63 
+4.379 8.293 14.57 
+4.791 7.702 15.89 
+4.886 7.585 15.73 
+4.579 7.672 15.94 
+4.462 7.525 15.82 
+4.556 7.408 15.66 
+4.769 7.439 15.62 
+5.111 6.512 16.74 
+5.196 6.429 16.56 
+4.896 6.49 16.78 
+4.768 6.386 16.64 
+4.853 6.304 16.46 
+5.068 6.326 16.42 
+-1.141 5.126 6.883 
+-1.072 3.638 6.7 
+-1.266 3.638 6.803 
+-1.332 5.083 6.981 
+-0.9541 5.115 6.997 
+-0.886 3.638 6.815 
+-0.9585 5.061 7.21 
+-0.8928 3.638 7.035 
+-1.15 5.018 7.308 
+-1.086 3.638 7.138 
+-1.337 5.029 7.194 
+-1.272 3.638 7.023 
+-1.342 6.512 7.421 
+-1.528 6.429 7.504 
+-1.154 6.49 7.531 
+-1.151 6.386 7.724 
+-1.336 6.304 7.807 
+-1.525 6.326 7.697 
+-1.662 7.702 8.276 
+-1.838 7.585 8.335 
+-1.471 7.672 8.38 
+-1.457 7.525 8.542 
+-1.633 7.408 8.601 
+-1.824 7.439 8.497 
+-2.079 8.615 9.391 
+-2.243 8.473 9.417 
+-1.885 8.578 9.487 
+-1.855 8.398 9.608 
+-2.02 8.255 9.635 
+-2.214 8.293 9.539 
+-2.564 9.189 10.69 
+-2.715 9.03 10.68 
+-2.366 9.148 10.78 
+-2.32 8.947 10.85 
+-2.47 8.788 10.84 
+-2.667 8.83 10.75 
+-3.085 9.385 12.08 
+-3.22 9.22 12.03 
+-2.884 9.342 12.16 
+-2.818 9.134 12.18 
+-2.953 8.97 12.13 
+-3.155 9.013 12.06 
+-3.606 9.189 13.48 
+-3.726 9.03 13.39 
+-3.4 9.148 13.54 
+-3.316 8.947 13.51 
+-3.437 8.788 13.42 
+-3.642 8.83 13.36 
+-4.091 8.615 14.77 
+-4.198 8.473 14.65 
+-3.882 8.578 14.83 
+-3.78 8.398 14.76 
+-3.887 8.255 14.63 
+-4.096 8.293 14.57 
+-4.508 7.702 15.89 
+-4.603 7.585 15.73 
+-4.296 7.672 15.94 
+-4.179 7.525 15.82 
+-4.273 7.408 15.66 
+-4.485 7.439 15.62 
+-4.828 6.512 16.74 
+-4.913 6.429 16.56 
+-4.613 6.49 16.78 
+-4.484 6.386 16.64 
+-4.57 6.304 16.46 
+-4.784 6.326 16.42 
+-1.519 -2.27 2.989 
+-1.987 -1.082 3.408 
+-2.709 -1.989 3.536 
+-1.513 -2.259 2.974 
+-2.524 -1.536 2.471 
+-4.318 -0.3933 4.187 
+-4.692 -0.6204 3.123 
+-6.274 0.9227 4.173 
+-5.533 1.852 4.043 
+-6.084 1.387 3.082 
+-6.844 2.279 4.015 
+-6.83 1.957 4.012 
+-6.886 2.118 3.737 
+-7.536 1.346 4.658 
+-7.229 0.9683 4.298 
+-8.053 1.724 3.821 
+-7.747 1.346 3.46 
+-9.085 -0.1982 5.078 
+-9.347 -0.1982 3.597 
+-8.702 -0.7393 4.247 
+-10.91 -1.528 5.154 
+-10.39 -2.11 4.847 
+-11.08 -1.528 4.148 
+-10.49 -2.11 4.26 
+-11.58 -2.509 4.768 
+-11.57 -2.523 4.76 
+-11.59 -2.509 4.742 
+-11.57 -2.523 4.744 
+-12.39 -3.546 5.269 
+-11.93 -3.852 5.034 
+-12.52 -3.546 4.548 
+-12.87 -4.803 5.622 
+-12.58 -5.09 4.606 
+-13.49 -4.516 4.767 
+-13.11 -6.264 5.38 
+-14.78 -6.803 5.643 
+-14.49 -7.092 4.622 
+-15.35 -8.042 5.637 
+-14.73 -8.43 5.528 
+-15.15 -8.236 4.95 
+-15.78 -9.378 5.503 
+-15.77 -9.385 5.497 
+-15.78 -9.375 5.495 
+-15.78 -9.378 5.486 
+-15.77 -9.383 5.484 
+-1.522 -2.262 -1.24 
+-1.519 -2.258 -1.231 
+-1.522 -2.262 -1.222 
+-1.529 -2.27 -1.222 
+-1.529 -2.27 -1.24 
+-2.061 -1.082 -0.8906 
+-2.428 -1.536 -1.907 
+-3.082 -0.4963 -0.5522 
+-3.082 -0.4963 -1.91 
+-3.759 -1.333 -1.628 
+-5.567 0.1257 -0.8323 
+-5.665 1.852 -0.8818 
+-6.417 0.9227 -0.8818 
+-6.041 1.387 -1.924 
+-6.95 2.279 -1.137 
+-6.937 1.957 -1.326 
+-6.943 2.118 -1.418 
+-7.378 0.9683 -0.9246 
+-8.108 1.724 -0.9246 
+-7.743 1.346 -1.84 
+-8.797 0.8371 -0.6052 
+-9.793 0.269 -1.611 
+-8.891 -0.6654 -1.611 
+-10.59 -2.11 -0.9326 
+-10.57 -0.523 -0.8679 
+-11.3 -1.375 -0.9326 
+-10.94 -1.742 -1.823 
+-11.75 -2.506 -1.223 
+-11.73 -2.523 -1.223 
+-11.74 -2.514 -1.247 
+-12.76 -3.466 -1.017 
+-12.14 -3.852 -1.017 
+-12.45 -3.659 -1.656 
+-13.16 -4.803 -0.6001 
+-12.7 -5.09 -1.55 
+-13.62 -4.516 -1.55 
+-13.36 -6.264 -0.8809 
+-15.05 -6.803 -0.9114 
+-14.58 -7.092 -1.866 
+-15.6 -8.042 -1.016 
+-14.98 -8.43 -1.016 
+-15.29 -8.236 -1.658 
+-16.01 -9.378 -1.222 
+-15.99 -9.385 -1.226 
+-16.01 -9.375 -1.231 
+-16.01 -9.378 -1.24 
+-16 -9.383 -1.24 
+-1.522 -2.27 -4.918 
+-2.105 -1.082 -4.684 
+-2.827 -1.989 -4.812 
+-1.513 -2.262 -4.935 
+-2.29 -1.536 -5.749 
+-4.562 -0.3933 -4.75 
+-4.55 -0.6204 -5.878 
+-6.395 0.9227 -5.432 
+-5.655 1.852 -5.302 
+-5.844 1.387 -6.393 
+-6.877 2.279 -5.776 
+-6.863 1.957 -5.773 
+-6.821 2.118 -6.051 
+-7.747 1.346 -5.408 
+-7.335 0.9683 -5.641 
+-7.947 1.724 -6.372 
+-7.536 1.346 -6.605 
+-9.347 -0.1982 -5.543 
+-9.085 -0.1982 -7.025 
+-8.702 -0.7393 -6.193 
+-11.08 -1.528 -6.095 
+-10.49 -2.11 -6.206 
+-10.91 -1.528 -7.101 
+-10.39 -2.11 -6.794 
+-11.59 -2.509 -6.689 
+-11.57 -2.523 -6.691 
+-11.58 -2.509 -6.715 
+-11.57 -2.523 -6.707 
+-12.52 -3.546 -6.495 
+-12.01 -3.852 -6.559 
+-12.39 -3.546 -7.217 
+-13.09 -4.803 -6.326 
+-12.47 -5.09 -7.18 
+-13.38 -4.516 -7.341 
+-13.24 -6.264 -6.637 
+-14.89 -6.803 -6.96 
+-14.27 -7.092 -7.819 
+-15.42 -8.042 -7.159 
+-14.8 -8.43 -7.051 
+-15 -8.236 -7.738 
+-15.78 -9.378 -7.432 
+-15.77 -9.385 -7.434 
+-15.78 -9.375 -7.442 
+-15.78 -9.378 -7.45 
+-15.77 -9.383 -7.448 
+1.522 -2.27 -4.918 
+1.511 -2.258 -4.926 
+1.513 -2.262 -4.935 
+2.828 -1.989 -4.812 
+2.105 -1.082 -4.684 
+2.29 -1.536 -5.749 
+4.55 -0.6204 -5.878 
+4.562 -0.3933 -4.75 
+6.395 0.9227 -5.432 
+5.655 1.852 -5.302 
+5.844 1.387 -6.393 
+6.877 2.279 -5.776 
+6.863 1.957 -5.773 
+6.821 2.118 -6.051 
+7.335 0.9683 -5.641 
+7.747 1.346 -5.408 
+7.947 1.724 -6.372 
+7.536 1.346 -6.605 
+9.347 -0.1982 -5.543 
+9.086 -0.1982 -7.025 
+8.702 -0.7393 -6.193 
+11.08 -1.528 -6.095 
+10.49 -2.11 -6.206 
+10.91 -1.528 -7.101 
+10.39 -2.11 -6.794 
+11.59 -2.509 -6.689 
+11.57 -2.523 -6.691 
+11.58 -2.509 -6.715 
+11.57 -2.523 -6.707 
+12.52 -3.546 -6.495 
+12.01 -3.852 -6.559 
+12.39 -3.546 -7.217 
+12.47 -5.09 -7.18 
+13.09 -4.803 -6.326 
+13.38 -4.516 -7.341 
+13.24 -6.264 -6.637 
+14.89 -6.803 -6.96 
+14.27 -7.092 -7.819 
+15.42 -8.042 -7.159 
+14.8 -8.43 -7.051 
+15 -8.236 -7.738 
+15.78 -9.378 -7.432 
+15.77 -9.385 -7.434 
+15.78 -9.375 -7.442 
+15.78 -9.378 -7.45 
+15.77 -9.383 -7.448 
+-0.9592 -0.9547 10.35 
+0.007813 0.3928 11.6 
+-0.7324 1.062 10.63 
+0.007813 -1.855 11.37 
+0.007813 -2.459 10.63 
+0.007813 0.3928 9.662 
+-0.3928 1.509 10.63 
+0.7327 1.062 10.63 
+-0.007813 0.3928 11.6 
+0.9595 -0.9547 10.35 
+-0.007813 -1.855 11.37 
+-0.007813 -2.459 10.63 
+-0.007813 0.3928 9.662 
+0.3931 1.509 10.63 
+1.513 -2.262 2.988 
+1.511 -2.258 2.979 
+1.516 -2.262 2.97 
+1.522 -2.27 2.971 
+1.52 -2.27 2.989 
+1.987 -1.082 3.408 
+2.524 -1.536 2.471 
+2.933 -0.4963 3.919 
+3.168 -0.4963 2.581 
+3.786 -1.333 2.977 
+5.429 0.1257 4.074 
+5.534 1.852 4.042 
+6.274 0.9227 4.173 
+6.085 1.387 3.082 
+6.863 1.957 3.827 
+6.844 2.279 4.015 
+6.886 2.118 3.737 
+7.229 0.9683 4.298 
+7.947 1.724 4.425 
+7.747 1.346 3.46 
+8.57 0.8371 4.859 
+9.726 0.269 4.042 
+8.838 -0.6654 3.885 
+10.39 -2.11 4.847 
+10.37 -0.523 4.909 
+11.09 -1.375 4.97 
+10.89 -1.742 4.032 
+11.59 -2.506 4.763 
+11.57 -2.523 4.76 
+11.58 -2.514 4.739 
+12.55 -3.466 5.142 
+11.93 -3.852 5.034 
+12.35 -3.659 4.459 
+12.58 -5.09 4.606 
+12.87 -4.803 5.622 
+13.49 -4.516 4.767 
+13.11 -6.264 5.38 
+14.78 -6.803 5.643 
+14.49 -7.092 4.622 
+15.35 -8.042 5.637 
+14.73 -8.43 5.528 
+15.15 -8.236 4.95 
+15.78 -9.378 5.503 
+15.77 -9.385 5.497 
+15.78 -9.375 5.495 
+15.78 -9.378 5.486 
+15.77 -9.383 5.484 
+1.529 -2.27 -1.222 
+1.519 -2.258 -1.231 
+1.522 -2.262 -1.24 
+2.795 -1.989 -0.8906 
+2.062 -1.082 -0.8906 
+2.428 -1.536 -1.907 
+4.677 -0.6204 -1.642 
+4.493 -0.3933 -0.5283 
+6.417 0.9227 -0.8818 
+5.665 1.852 -0.8818 
+6.041 1.387 -1.924 
+6.951 2.279 -1.137 
+6.937 1.957 -1.137 
+6.944 2.118 -1.418 
+7.379 0.9683 -0.9246 
+7.743 1.346 -0.623 
+8.108 1.724 -1.538 
+7.743 1.346 -1.84 
+9.343 -0.1982 -0.4792 
+9.343 -0.1982 -1.983 
+8.82 -0.7393 -1.231 
+11.15 -1.528 -0.7207 
+10.59 -2.11 -0.9326 
+11.15 -1.528 -1.742 
+10.59 -2.11 -1.53 
+11.75 -2.509 -1.218 
+11.73 -2.523 -1.223 
+11.75 -2.509 -1.245 
+11.73 -2.523 -1.239 
+12.63 -3.546 -0.8647 
+12.14 -3.852 -1.017 
+12.63 -3.546 -1.598 
+12.7 -5.09 -1.55 
+13.16 -4.803 -0.6001 
+13.62 -4.516 -1.55 
+13.36 -6.264 -0.8804 
+15.05 -6.803 -0.9111 
+14.58 -7.092 -1.866 
+15.6 -8.042 -1.016 
+14.98 -8.43 -1.016 
+15.29 -8.236 -1.658 
+16.01 -9.378 -1.222 
+15.99 -9.385 -1.226 
+16.01 -9.375 -1.231 
+16.01 -9.378 -1.24 
+16 -9.383 -1.24 
+-0.7932 4.462 -7.734 
+-0.3843 1.974 -5.495 
+1.95 3.241 -7.348 
+1.167 0.6428 -6.109 
+3.808 0.1871 -9.572 
+3.644 1.688 -11.88 
+0.07617 4.961 -10.12 
+3.28 -0.5704 -14.15 
+0.2488 -1.848 -16.78 
+-0.9744 -2.686 -16.57 
+0.7307 -3.159 -16.47 
+-2.678 2.963 -8.185 
+-2.616 -2.779 -12.24 
+-1.159 -1.533 -8.922 
+3 0 1 2 
+3 1 3 2 
+3 2 4 5 
+3 4 6 5 
+3 5 6 7 
+3 7 6 8 
+3 2 3 9 
+3 2 9 4 
+3 4 9 6 
+3 6 9 8 
+3 5 0 2 
+3 5 7 0 
+3 8 10 7 
+3 7 10 0 
+3 0 10 1 
+3 1 10 11 
+3 1 11 3 
+3 10 12 11 
+3 11 12 3 
+3 3 12 9 
+3 10 8 12 
+3 12 8 9 
+3 13 14 15 
+3 15 14 16 
+3 17 15 16 
+3 18 19 14 
+3 14 19 16 
+3 19 20 16 
+3 15 17 21 
+3 15 21 13 
+3 14 13 18 
+3 21 22 13 
+3 13 22 18 
+3 21 23 22 
+3 21 24 23 
+3 23 25 22 
+3 22 25 18 
+3 18 25 20 
+3 18 20 19 
+3 23 26 25 
+3 25 26 20 
+3 23 24 26 
+3 26 24 27 
+3 26 27 20 
+3 20 27 16 
+3 24 21 27 
+3 27 21 17 
+3 27 17 16 
+3 28 29 30 
+3 31 32 29 
+3 29 32 30 
+3 32 33 30 
+3 30 33 28 
+3 28 33 34 
+3 28 34 35 
+3 35 34 36 
+3 28 35 29 
+3 35 36 29 
+3 29 36 31 
+3 36 37 31 
+3 31 37 32 
+3 37 38 32 
+3 32 38 33 
+3 36 34 37 
+3 37 34 38 
+3 38 34 33 
+3 39 40 41 
+3 42 43 40 
+3 40 43 41 
+3 43 44 41 
+3 41 44 39 
+3 39 44 45 
+3 39 45 46 
+3 46 45 47 
+3 39 46 40 
+3 46 47 40 
+3 40 47 42 
+3 47 48 42 
+3 42 48 43 
+3 48 49 43 
+3 43 49 44 
+3 47 45 48 
+3 48 45 49 
+3 49 45 44 
+3 50 51 52 
+3 50 52 53 
+3 51 54 55 
+3 51 55 52 
+3 54 56 57 
+3 54 57 55 
+3 56 58 59 
+3 56 59 57 
+3 58 60 61 
+3 58 61 59 
+3 60 50 53 
+3 60 53 61 
+3 53 52 62 
+3 53 62 63 
+3 52 55 64 
+3 52 64 62 
+3 55 57 65 
+3 55 65 64 
+3 57 59 66 
+3 57 66 65 
+3 59 61 67 
+3 59 67 66 
+3 61 53 63 
+3 61 63 67 
+3 63 62 68 
+3 63 68 69 
+3 62 64 70 
+3 62 70 68 
+3 64 65 71 
+3 64 71 70 
+3 65 66 72 
+3 65 72 71 
+3 66 67 73 
+3 66 73 72 
+3 67 63 69 
+3 67 69 73 
+3 69 68 74 
+3 69 74 75 
+3 68 70 76 
+3 68 76 74 
+3 70 71 77 
+3 70 77 76 
+3 71 72 78 
+3 71 78 77 
+3 72 73 79 
+3 72 79 78 
+3 73 69 75 
+3 73 75 79 
+3 75 74 80 
+3 75 80 81 
+3 74 76 82 
+3 74 82 80 
+3 76 77 83 
+3 76 83 82 
+3 77 78 84 
+3 77 84 83 
+3 78 79 85 
+3 78 85 84 
+3 79 75 81 
+3 79 81 85 
+3 81 80 86 
+3 81 86 87 
+3 80 82 88 
+3 80 88 86 
+3 82 83 89 
+3 82 89 88 
+3 83 84 90 
+3 83 90 89 
+3 84 85 91 
+3 84 91 90 
+3 85 81 87 
+3 85 87 91 
+3 87 86 92 
+3 87 92 93 
+3 86 88 94 
+3 86 94 92 
+3 88 89 95 
+3 88 95 94 
+3 89 90 96 
+3 89 96 95 
+3 90 91 97 
+3 90 97 96 
+3 91 87 93 
+3 91 93 97 
+3 93 92 98 
+3 93 98 99 
+3 92 94 100 
+3 92 100 98 
+3 94 95 101 
+3 94 101 100 
+3 95 96 102 
+3 95 102 101 
+3 96 97 103 
+3 96 103 102 
+3 97 93 99 
+3 97 99 103 
+3 99 98 104 
+3 99 104 105 
+3 98 100 106 
+3 98 106 104 
+3 100 101 107 
+3 100 107 106 
+3 101 102 108 
+3 101 108 107 
+3 102 103 109 
+3 102 109 108 
+3 103 99 105 
+3 103 105 109 
+3 105 104 110 
+3 105 110 111 
+3 104 106 112 
+3 104 112 110 
+3 106 107 113 
+3 106 113 112 
+3 107 108 114 
+3 107 114 113 
+3 108 109 115 
+3 108 115 114 
+3 109 105 111 
+3 109 111 115 
+3 54 51 50 
+3 56 54 50 
+3 58 56 50 
+3 60 58 50 
+3 112 113 110 
+3 113 114 110 
+3 114 115 110 
+3 115 111 110 
+3 116 117 118 
+3 119 116 118 
+3 120 121 117 
+3 116 120 117 
+3 122 123 121 
+3 120 122 121 
+3 124 125 123 
+3 122 124 123 
+3 126 127 125 
+3 124 126 125 
+3 119 118 127 
+3 126 119 127 
+3 128 116 119 
+3 129 128 119 
+3 130 120 116 
+3 128 130 116 
+3 131 122 120 
+3 130 131 120 
+3 132 124 122 
+3 131 132 122 
+3 133 126 124 
+3 132 133 124 
+3 129 119 126 
+3 133 129 126 
+3 134 128 129 
+3 135 134 129 
+3 136 130 128 
+3 134 136 128 
+3 137 131 130 
+3 136 137 130 
+3 138 132 131 
+3 137 138 131 
+3 139 133 132 
+3 138 139 132 
+3 135 129 133 
+3 139 135 133 
+3 140 134 135 
+3 141 140 135 
+3 142 136 134 
+3 140 142 134 
+3 143 137 136 
+3 142 143 136 
+3 144 138 137 
+3 143 144 137 
+3 145 139 138 
+3 144 145 138 
+3 141 135 139 

+ 165 - 0
test/models-nonbsd/PLY/ant-half.ply.license

@@ -0,0 +1,165 @@
+		   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.

BIN
test/models/BLEND/BlenderDefault_271.blend


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 7561 - 0
test/models/Collada/anims_with_full_rotations_between_keys.DAE


+ 95 - 0
test/models/OpenGEX/Example.ogex

@@ -0,0 +1,95 @@
+Metric (key = "distance") {float {1}}
+Metric (key = "angle") {float {1}}
+Metric (key = "time") {float {1}}
+Metric (key = "up") {string {"z"}}
+
+GeometryNode $node1
+{
+	Name {string {"Box001"}}
+	ObjectRef {ref {$geometry1}}
+	MaterialRef {ref {$material1}}
+
+	Transform
+	{
+		float[16]
+		{
+			{0x3F800000, 0x00000000, 0x00000000, 0x00000000,		// {1, 0, 0, 0
+			 0x00000000, 0x3F800000, 0x00000000, 0x00000000,		//  0, 1, 0, 0
+			 0x00000000, 0x00000000, 0x3F800000, 0x00000000,		//  0, 0, 1, 0
+			 0xBEF33B00, 0x411804DE, 0x00000000, 0x3F800000}		//  -0.47506, 9.50119, 0, 1}
+		}
+	}
+}
+
+GeometryNode $node2
+{
+	Name {string {"Box002"}}
+	ObjectRef {ref {$geometry1}}
+	MaterialRef {ref {$material1}}
+
+	Transform
+	{
+		float[16]
+		{
+			{0x3F800000, 0x00000000, 0x00000000, 0x00000000,		// {1, 0, 0, 0
+			 0x00000000, 0x3F800000, 0x00000000, 0x00000000,		//  0, 1, 0, 0
+			 0x00000000, 0x00000000, 0x3F800000, 0x00000000,		//  0, 0, 1, 0
+			 0x43041438, 0x411804DE, 0x00000000, 0x3F800000}		//  132.079, 9.50119, 0, 1}
+		}
+	}
+}
+
+GeometryObject $geometry1		// Box001, Box002
+{
+	Mesh (primitive = "triangles")
+	{
+		VertexArray (attrib = "position")
+		{
+			float[3]		// 24
+			{
+				{0xC2501375, 0xC24C468A, 0x00000000}, {0xC2501375, 0x424C468A, 0x00000000}, {0x42501375, 0x424C468A, 0x00000000}, {0x42501375, 0xC24C468A, 0x00000000}, {0xC2501375, 0xC24C468A, 0x42BA3928}, {0x42501375, 0xC24C468A, 0x42BA3928}, {0x42501375, 0x424C468A, 0x42BA3928}, {0xC2501375, 0x424C468A, 0x42BA3928},
+				{0xC2501375, 0xC24C468A, 0x00000000}, {0x42501375, 0xC24C468A, 0x00000000}, {0x42501375, 0xC24C468A, 0x42BA3928}, {0xC2501375, 0xC24C468A, 0x42BA3928}, {0x42501375, 0xC24C468A, 0x00000000}, {0x42501375, 0x424C468A, 0x00000000}, {0x42501375, 0x424C468A, 0x42BA3928}, {0x42501375, 0xC24C468A, 0x42BA3928},
+				{0x42501375, 0x424C468A, 0x00000000}, {0xC2501375, 0x424C468A, 0x00000000}, {0xC2501375, 0x424C468A, 0x42BA3928}, {0x42501375, 0x424C468A, 0x42BA3928}, {0xC2501375, 0x424C468A, 0x00000000}, {0xC2501375, 0xC24C468A, 0x00000000}, {0xC2501375, 0xC24C468A, 0x42BA3928}, {0xC2501375, 0x424C468A, 0x42BA3928}
+			}
+		}
+
+		VertexArray (attrib = "normal")
+		{
+			float[3]		// 24
+			{
+				{0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0x3F800000}, {0x00000000, 0x00000000, 0x3F800000}, {0x00000000, 0x00000000, 0x3F800000}, {0x00000000, 0x00000000, 0x3F800000},
+				{0x00000000, 0xBF800000, 0x00000000}, {0x00000000, 0xBF800000, 0x00000000}, {0x00000000, 0xBF800000, 0x00000000}, {0x80000000, 0xBF800000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000},
+				{0x00000000, 0x3F800000, 0x00000000}, {0x00000000, 0x3F800000, 0x00000000}, {0x00000000, 0x3F800000, 0x00000000}, {0x80000000, 0x3F800000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000}
+			}
+		}
+
+		VertexArray (attrib = "texcoord")
+		{
+			float[2]		// 24
+			{
+				{0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}, {0x00000000, 0x00000000}, {0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000},
+				{0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}, {0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000},
+				{0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}, {0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}
+			}
+		}
+
+		IndexArray
+		{
+			unsigned_int32[3]		// 12
+			{
+				{0, 1, 2}, {2, 3, 0}, {4, 5, 6}, {6, 7, 4}, {8, 9, 10}, {10, 11, 8}, {12, 13, 14}, {14, 15, 12}, {16, 17, 18}, {18, 19, 16}, {20, 21, 22}, {22, 23, 20}
+			}
+		}
+	}
+}
+
+Material $material1
+{
+	Name {string {"03 - Default"}}
+
+	Color (attrib = "diffuse") {float[3] {{0.588235, 0.588235, 0.588235}}}
+	Texture (attrib = "diffuse")
+	{
+		string {"texture/Concrete.tga"}
+	}
+}

+ 13 - 16
test/regression/run.py

@@ -167,11 +167,11 @@ def process_dir(d, outfile_results, zipin, result):
     print("Processing directory " + d)
     print("Processing directory " + d)
     for f in sorted(os.listdir(d)):
     for f in sorted(os.listdir(d)):
         fullpath = os.path.join(d, f)
         fullpath = os.path.join(d, f)
-        if os.path.isdir(fullpath) and not f == ".svn":
+        if os.path.isdir(fullpath) and not f[:1] == '.':
             process_dir(fullpath, outfile_results, zipin, result)
             process_dir(fullpath, outfile_results, zipin, result)
             continue
             continue
 
 
-        if f in settings.files_to_ignore:
+        if f in settings.files_to_ignore or os.path.splitext(f)[1] in settings.exclude_extensions:
             print("Ignoring " + f)
             print("Ignoring " + f)
             continue
             continue
 
 
@@ -190,32 +190,26 @@ def process_dir(d, outfile_results, zipin, result):
                     "regression database? Use gen_db.zip to re-generate.")
                     "regression database? Use gen_db.zip to re-generate.")
                 continue
                 continue
 
 
-            # Ignore extensions via settings.py configured list
-            # todo: Fix for multi dot extensions like .skeleton.xml
-            ext = os.path.splitext(fullpath)[1].lower()
-            if ext != "" and ext in settings.exclude_extensions:
-                continue
-
             print("-"*60 + "\n  " + os.path.realpath(fullpath) + " pp: " + pppreset) 
             print("-"*60 + "\n  " + os.path.realpath(fullpath) + " pp: " + pppreset) 
             
             
             outfile_actual = prepare_output_dir(fullpath, filehash, "ACTUAL")
             outfile_actual = prepare_output_dir(fullpath, filehash, "ACTUAL")
             outfile_expect = prepare_output_dir(fullpath, filehash, "EXPECT")
             outfile_expect = prepare_output_dir(fullpath, filehash, "EXPECT")
             outfile_results.write("assimp dump    "+"-"*80+"\n")
             outfile_results.write("assimp dump    "+"-"*80+"\n")
             outfile_results.flush()
             outfile_results.flush()
-
             command = [assimp_bin_path,
             command = [assimp_bin_path,
                 "dump",
                 "dump",
                 fullpath, outfile_actual, "-b", "-s", "-l" ] +\
                 fullpath, outfile_actual, "-b", "-s", "-l" ] +\
                 pppreset.split()
                 pppreset.split()
-
             r = subprocess.call(command, **shellparams)
             r = subprocess.call(command, **shellparams)
-            print(r)
+            outfile_results.flush()
 
 
             if r and not failure:
             if r and not failure:
                 result.fail(fullpath, outfile_expect, pppreset, IMPORT_FAILURE, r)
                 result.fail(fullpath, outfile_expect, pppreset, IMPORT_FAILURE, r)
+                outfile_results.write("Failed to import\n")
                 continue
                 continue
             elif failure and not r:
             elif failure and not r:
                 result.fail(fullpath, outfile_expect, pppreset, EXPECTED_FAILURE_NOT_MET)
                 result.fail(fullpath, outfile_expect, pppreset, EXPECTED_FAILURE_NOT_MET)
+                outfile_results.write("Expected import to fail\n")
                 continue
                 continue
             
             
             with open(outfile_expect, "wb") as s:
             with open(outfile_expect, "wb") as s:
@@ -227,21 +221,24 @@ def process_dir(d, outfile_results, zipin, result):
             except IOError:
             except IOError:
                 continue
                 continue
                 
                 
+            outfile_results.write("Expected data length: {0}\n".format(len(input_expected)))
+            outfile_results.write("Actual data length: {0}\n".format(len(input_actual)))
+            failed = False
             if len(input_expected) != len(input_actual):
             if len(input_expected) != len(input_actual):
                 result.fail(fullpath, outfile_expect, pppreset, DATABASE_LENGTH_MISMATCH,
                 result.fail(fullpath, outfile_expect, pppreset, DATABASE_LENGTH_MISMATCH,
                         len(input_expected), len(input_actual))
                         len(input_expected), len(input_actual))
-                continue
+                # Still compare the dumps to see what the difference is
+                failed = True
 
 
             outfile_results.write("assimp cmpdump "+"-"*80+"\n")
             outfile_results.write("assimp cmpdump "+"-"*80+"\n")
             outfile_results.flush()
             outfile_results.flush()
-
             command = [ assimp_bin_path, 'cmpdump', outfile_actual, outfile_expect ]
             command = [ assimp_bin_path, 'cmpdump', outfile_actual, outfile_expect ]
             if subprocess.call(command, **shellparams) != 0:
             if subprocess.call(command, **shellparams) != 0:
-                result.fail(fullpath, outfile_expect, pppreset, DATABASE_VALUE_MISMATCH)
+                if not failed:
+                    result.fail(fullpath, outfile_expect, pppreset, DATABASE_VALUE_MISMATCH)
                 continue 
                 continue 
             
             
-            result.ok(fullpath, pppreset, COMPARE_SUCCESS, 
-                len(input_expected))     
+            result.ok(fullpath, pppreset, COMPARE_SUCCESS, len(input_expected))     
 
 
 # -------------------------------------------------------------------------------
 # -------------------------------------------------------------------------------
 def del_folder_with_contents(folder):
 def del_folder_with_contents(folder):

+ 1 - 1
test/regression/settings.py

@@ -62,7 +62,7 @@ files_to_ignore = ["pond.0.ply"]
 exclude_extensions = [
 exclude_extensions = [
     ".lws", ".assbin", ".assxml", ".txt", ".md",
     ".lws", ".assbin", ".assxml", ".txt", ".md",
     ".jpeg", ".jpg", ".png", ".gif", ".tga", ".bmp",
     ".jpeg", ".jpg", ".png", ".gif", ".tga", ".bmp",
-    ".skeleton", ".skeleton.xml"
+    ".skeleton", ".skeleton.xml", ".license"
 ]
 ]
 
 
 # -------------------------------------------------------------------------------
 # -------------------------------------------------------------------------------

+ 1 - 1
tools/assimp_cmd/CMakeLists.txt

@@ -28,7 +28,7 @@ IF( WIN32 )
 		MAIN_DEPENDENCY assimp)
 		MAIN_DEPENDENCY assimp)
 ENDIF( WIN32 )
 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
 )
 )

+ 23 - 7
tools/assimp_cmd/CompareDump.cpp

@@ -257,16 +257,32 @@ private:
 	/* read from both streams simult.*/
 	/* read from both streams simult.*/
 	template <typename T> void read(T& filla,T& fille) {
 	template <typename T> void read(T& filla,T& fille) {
 		if(1 != fread(&filla,sizeof(T),1,actual)) {
 		if(1 != fread(&filla,sizeof(T),1,actual)) {
-			throw compare_fails_exception("Unexpected EOF reading ACTUAL");
+			EOFActual();
 		}
 		}
 		if(1 != fread(&fille,sizeof(T),1,expect)) {
 		if(1 != fread(&fille,sizeof(T),1,expect)) {
-			throw compare_fails_exception("Unexpected EOF reading EXPECT");
+			EOFExpect();
 		}
 		}
 	}
 	}
 
 
-
 private:
 private:
 
 
+	void EOFActual() {
+		std::stringstream ss;
+		throw compare_fails_exception((ss
+			<< "Unexpected EOF reading ACTUAL.\nCurrent position in scene hierarchy is "
+			<< print_hierarchy(),ss.str().c_str()
+			));
+	}
+
+	void EOFExpect() {
+		std::stringstream ss;
+		throw compare_fails_exception((ss
+			<< "Unexpected EOF reading EXPECT.\nCurrent position in scene hierarchy is "
+			<< print_hierarchy(),ss.str().c_str()
+			));
+	}
+
+
 	FILE *const actual, *const expect;
 	FILE *const actual, *const expect;
 
 
 	typedef std::map<std::string,unsigned int> PerChunkCounter;
 	typedef std::map<std::string,unsigned int> PerChunkCounter;
@@ -290,10 +306,10 @@ template <> void comparer_context :: read<aiString>(aiString& filla,aiString& fi
 	read(lena,lene);
 	read(lena,lene);
 
 
 	if(lena && 1 != fread(&filla.data,lena,1,actual)) {
 	if(lena && 1 != fread(&filla.data,lena,1,actual)) {
-		throw compare_fails_exception("Unexpected EOF reading ACTUAL");
+		EOFActual();
 	}
 	}
 	if(lene && 1 != fread(&fille.data,lene,1,expect)) {
 	if(lene && 1 != fread(&fille.data,lene,1,expect)) {
-		throw compare_fails_exception("Unexpected EOF reading ACTUAL");
+		EOFExpect();
 	}
 	}
 
 
 	fille.data[fille.length=static_cast<unsigned int>(lene)] = '\0';
 	fille.data[fille.length=static_cast<unsigned int>(lene)] = '\0';
@@ -487,7 +503,7 @@ private:
 		res|=fread(&actual.second,4,1,ctx.get_actual())		<<3u;
 		res|=fread(&actual.second,4,1,ctx.get_actual())		<<3u;
 
 
 		if(res!=0xf) {
 		if(res!=0xf) {
-			ctx.failure("I/OError reading chunk head, dumps are not well-defined","<ChunkHead>");
+			ctx.failure("IO Error reading chunk head, dumps are malformed","<ChunkHead>");
 		}
 		}
 
 
 		if (current.first != actual.first) {
 		if (current.first != actual.first) {
@@ -504,7 +520,7 @@ private:
 		if (current.first != actual.first) {
 		if (current.first != actual.first) {
 			std::stringstream ss;
 			std::stringstream ss;
 			ctx.failure((ss
 			ctx.failure((ss
-				<<"Chunk lenghts do not match. EXPECT: "
+				<<"Chunk lengths do not match. EXPECT: "
 				<<current.second
 				<<current.second
 				<<" ACTUAL: " 
 				<<" ACTUAL: " 
 				<< actual.second,
 				<< actual.second,

+ 124 - 0
workspaces/Android-NDK/jni/Android.mk

@@ -0,0 +1,124 @@
+LOCAL_PATH := $(call my-dir)/../../../
+
+include $(CLEAR_VARS)
+LOCAL_MODULE    := assimp_static
+ASSIMP_SRC_DIR = code
+
+FILE_LIST := $(wildcard $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/*.cpp)
+FILE_LIST += $(wildcard $(LOCAL_PATH)/contrib/openddlparser/code/*.cpp)
+FILE_LIST += $(wildcard $(LOCAL_PATH)/contrib/unzip/*.c)
+FILE_LIST += $(wildcard $(LOCAL_PATH)/contrib/poly2tri/poly2tri/*/*.cc)
+
+LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
+
+LOCAL_SRC_FILES += contrib/clipper/clipper.cpp \
+	contrib/ConvertUTF/ConvertUTF.c \
+	contrib/irrXML/irrXML.cpp
+
+# enables -frtti and -fexceptions
+LOCAL_CPP_FEATURES := exceptions
+# identifier 'nullptr' will become a keyword in C++0x [-Wc++0x-compat]
+# but next breaks blender and other importer
+# LOCAL_CFLAGS += -std=c++11
+  
+# cant be disabled? rudamentary function?
+#       -DASSIMP_BUILD_NO_FLIPWINDING_PROCESS  \
+#
+DontBuildProcess = \
+        -DASSIMP_BUILD_NO_FLIPUVS_PROCESS  \
+        -DASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS \
+        -DASSIMP_BUILD_NO_CALCTANGENTS_PROCESS \
+        -DASSIMP_BUILD_NO_DEBONE_PROCESS \
+        -DASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS \
+        -DASSIMP_BUILD_NO_FINDINSTANCES_PROCESS \
+        -DASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS \
+        -DASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS \
+        -DASSIMP_BUILD_NO_GENFACENORMALS_PROCESS \
+        -DASSIMP_BUILD_NO_GENUVCOORDS_PROCESS \
+        -DASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS \
+        -DASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS \
+        -DASSIMP_BUILD_NO_JOINVERTICES_PROCESS \
+        -DASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS \
+        -DASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS \
+        -DASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS \
+        -DASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS \
+        -DASSIMP_BUILD_NO_REMOVEVC_PROCESS \
+        -DASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS \
+        -DASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS \
+        -DASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS \
+        -DASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS \
+        -DASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS \
+        -DASSIMP_BUILD_NO_TRIANGULATE_PROCESS \
+        -DASSIMP_BUILD_NO_VALIDATEDS_PROCESS
+
+DontBuildImporters = \
+        -DASSIMP_BUILD_NO_X_IMPORTER \
+        -DASSIMP_BUILD_NO_3DS_IMPORTER \
+        -DASSIMP_BUILD_NO_MD3_IMPORTER \
+        -DASSIMP_BUILD_NO_MDL_IMPORTER \
+        -DASSIMP_BUILD_NO_MD2_IMPORTER \
+        -DASSIMP_BUILD_NO_PLY_IMPORTER \
+        -DASSIMP_BUILD_NO_ASE_IMPORTER \
+        -DASSIMP_BUILD_NO_HMP_IMPORTER \
+        -DASSIMP_BUILD_NO_SMD_IMPORTER \
+        -DASSIMP_BUILD_NO_MDC_IMPORTER \
+        -DASSIMP_BUILD_NO_MD5_IMPORTER \
+        -DASSIMP_BUILD_NO_STL_IMPORTER \
+        -DASSIMP_BUILD_NO_LWO_IMPORTER \
+        -DASSIMP_BUILD_NO_DXF_IMPORTER \
+        -DASSIMP_BUILD_NO_NFF_IMPORTER \
+        -DASSIMP_BUILD_NO_RAW_IMPORTER \
+        -DASSIMP_BUILD_NO_OFF_IMPORTER \
+        -DASSIMP_BUILD_NO_AC_IMPORTER \
+        -DASSIMP_BUILD_NO_BVH_IMPORTER \
+        -DASSIMP_BUILD_NO_IRRMESH_IMPORTER \
+        -DASSIMP_BUILD_NO_IRR_IMPORTER \
+        -DASSIMP_BUILD_NO_Q3D_IMPORTER \
+        -DASSIMP_BUILD_NO_B3D_IMPORTER \
+        -DASSIMP_BUILD_NO_COLLADA_IMPORTER \
+        -DASSIMP_BUILD_NO_TERRAGEN_IMPORTER \
+        -DASSIMP_BUILD_NO_CSM_IMPORTER \
+        -DASSIMP_BUILD_NO_3D_IMPORTER \
+        -DASSIMP_BUILD_NO_LWS_IMPORTER \
+        -DASSIMP_BUILD_NO_OGRE_IMPORTER \
+        -DASSIMP_BUILD_NO_MS3D_IMPORTER \
+        -DASSIMP_BUILD_NO_COB_IMPORTER \
+        -DASSIMP_BUILD_NO_Q3BSP_IMPORTER \
+        -DASSIMP_BUILD_NO_NDO_IMPORTER \
+        -DASSIMP_BUILD_NO_IFC_IMPORTER \
+        -DASSIMP_BUILD_NO_XGL_IMPORTER \
+        -DASSIMP_BUILD_NO_FBX_IMPORTER \
+        -DASSIMP_BUILD_NO_C4D_IMPORTER \
+	-DASSIMP_BUILD_NO_OPENGEX_IMPORTER \
+        -DASSIMP_BUILD_NO_ASSBIN_IMPORTER
+#        -DASSIMP_BUILD_NO_BLEND_IMPORTER \
+#         -DASSIMP_BUILD_NO_GEO_IMPORTER
+#         -DASSIMP_BUILD_NO_OBJ_IMPORTER \
+#
+DontBuildImporters := -DASSIMP_BUILD_NO_IFC_IMPORTER -DASSIMP_BUILD_NO_IRRMESH_IMPORTER  -DASSIMP_BUILD_NO_IRR_IMPORTER -DASSIMP_BUILD_NO_C4D_IMPORTER
+
+ASSIMP_FLAGS_3_0 = -DASSIMP_BUILD_DLL_EXPORT -DASSIMP_BUILD_NO_OWN_ZLIB -DASSIMP_BUILD_BOOST_WORKAROUND -Dassimp_EXPORTS -fPIC -fvisibility=hidden -Wall
+ASSIMP_FLAGS_3_1 = $(ASSIMP_FLAGS_3_0) # -DASSIMP_BUILD_BLENDER_DEBUG
+
+LOCAL_CFLAGS += $(ASSIMP_FLAGS_3_1) -DASSIMP_BUILD_NO_EXPORT -DOPENDDL_NO_USE_CPP11 $(DontBuildImporters)  # $(DontBuildProcess) 
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/include $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/BoostWorkaround $(LOCAL_PATH)/contrib/openddlparser/include ./ 
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/BoostWorkaround
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE    := assimp
+
+LOCAL_CFLAGS += -UASSIMP_BUILD_DLL_EXPORT
+LOCAL_WHOLE_STATIC_LIBRARIES = assimp_static
+
+LOCAL_LDLIBS := -lz
+
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/BoostWorkaround
+include $(BUILD_SHARED_LIBRARY)
+
+-include $(LOCAL_PATH)/assimp_cmd.mk
+
+# let it on original place
+include $(LOCAL_PATH)/port/jassimp/jassimp-native/Android.mk

+ 8 - 0
workspaces/Android-NDK/jni/Application.mk

@@ -0,0 +1,8 @@
+ifeq ($(CC),clang)
+    NDK_TOOLCHAIN_VERSION := $(CC)
+    $(info "Use llvm Compiler")
+endif
+
+APP_ABI := armeabi-v7a
+
+APP_STL := stlport_static

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác