瀏覽代碼

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

Léo Terziman 11 年之前
父節點
當前提交
e2d9512275
共有 72 個文件被更改,包括 3359 次插入508 次删除
  1. 6 4
      .travis.yml
  2. 19 16
      CMakeLists.txt
  3. 5 1
      Readme.md
  4. 560 0
      code/3DSExporter.cpp
  5. 94 0
      code/3DSExporter.h
  6. 2 2
      code/3DSLoader.h
  7. 762 0
      code/AssbinExporter.cpp
  8. 49 0
      code/AssbinExporter.h
  9. 671 0
      code/AssbinLoader.cpp
  10. 94 0
      code/AssbinLoader.h
  11. 2 2
      code/BlenderLoader.cpp
  12. 3 3
      code/BoostWorkaround/boost/tuple/tuple.hpp
  13. 14 1
      code/CMakeLists.txt
  14. 3 3
      code/CalcTangentsProcess.cpp
  15. 39 31
      code/ColladaExporter.cpp
  16. 19 9
      code/ConvertToLHProcess.cpp
  17. 2 2
      code/DeboneProcess.cpp
  18. 11 5
      code/Exporter.cpp
  19. 1 1
      code/FBXAnimation.cpp
  20. 6 6
      code/FBXConverter.cpp
  21. 10 5
      code/FBXDocument.cpp
  22. 2 2
      code/FBXDocument.h
  23. 2 0
      code/FBXImporter.cpp
  24. 1 1
      code/FBXMaterial.cpp
  25. 4 2
      code/FBXMeshGeometry.cpp
  26. 24 34
      code/FBXParser.cpp
  27. 1 1
      code/FBXProperties.cpp
  28. 2 4
      code/FBXProperties.h
  29. 1 2
      code/FindInstancesProcess.cpp
  30. 1 1
      code/GenVertexNormalsProcess.cpp
  31. 1 1
      code/GenVertexNormalsProcess.h
  32. 1 1
      code/IFCBoolean.cpp
  33. 2 2
      code/IFCOpenings.cpp
  34. 1 1
      code/IFCProfile.cpp
  35. 3 3
      code/IFCReaderGen.cpp
  36. 13 4
      code/Importer.cpp
  37. 6 0
      code/ImporterRegistry.cpp
  38. 1 1
      code/JoinVerticesProcess.h
  39. 10 17
      code/LimitBoneWeightsProcess.cpp
  40. 20 14
      code/ObjExporter.cpp
  41. 11 11
      code/ObjFileMtlImporter.cpp
  42. 28 21
      code/ObjFileParser.cpp
  43. 1 1
      code/ObjTools.h
  44. 5 6
      code/OgreBinarySerializer.cpp
  45. 6 2
      code/OgreBinarySerializer.h
  46. 13 11
      code/OgreStructs.cpp
  47. 59 26
      code/ParsingUtils.h
  48. 2 0
      code/Q3BSPFileImporter.cpp
  49. 5 5
      code/Q3BSPZipArchive.cpp
  50. 2 2
      code/STLLoader.cpp
  51. 235 0
      code/StreamWriter.h
  52. 81 0
      code/XMLTools.h
  53. 42 6
      code/fast_atof.h
  54. 2 0
      contrib/clipper/clipper.cpp
  55. 1 1
      contrib/unzip/unzip.c
  56. 29 3
      include/assimp/ProgressHandler.hpp
  57. 1 1
      include/assimp/importerdesc.h
  58. 2 1
      samples/SimpleOpenGL/CMakeLists.txt
  59. 48 46
      samples/SimpleOpenGL/Sample_SimpleOpenGL.c
  60. 41 57
      samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp
  61. 14 105
      test/CMakeLists.txt
  62. 210 0
      test/models/Collada/cube_xmlspecialchars.dae
  63. 1 1
      test/models/OBJ/empty_mat.mtl
  64. 11 0
      test/models/OBJ/multiple_spaces.obj
  65. 23 0
      test/models/OBJ/number_formats.obj
  66. 1 1
      test/unit/CCompilerTest.c
  67. 3 4
      test/unit/Main.cpp
  68. 5 5
      test/unit/utImporter.cpp
  69. 2 2
      test/unit/utNoBoostTest.h
  70. 2 2
      test/unit/utRemoveComments.cpp
  71. 1 1
      tools/assimp_cmd/WriteDumb.cpp
  72. 4 5
      tools/assimp_view/MessageProc.cpp

+ 6 - 4
.travis.yml

@@ -1,5 +1,5 @@
 before_install:
 before_install:
-  - sudo apt-get install cmake
+  - sudo apt-get install cmake libcppunit-dev
 
 
 env:
 env:
   - TRAVIS_NO_EXPORT=YES
   - TRAVIS_NO_EXPORT=YES
@@ -13,7 +13,9 @@ compiler:
   - gcc
   - gcc
   - clang
   - clang
 
 
-script: cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -STATIC_BUILD=$TRAVIS_STATIC_BUILD && make
-
-
+script:
+  - cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -STATIC_BUILD=$TRAVIS_STATIC_BUILD
+  - make
+  - cd test/unit
+  - ../../bin/unit
 
 

+ 19 - 16
CMakeLists.txt

@@ -76,8 +76,7 @@ SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE PATH
 	"Path the header files are installed to." )
 	"Path the header files are installed to." )
 SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH
 SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH
 	"Path the tool executables are installed to." )
 	"Path the tool executables are installed to." )
-SET ( ASSIMP_BUILD_STATIC_LIB OFF CACHE BOOL
-    "Build a static (.a) version of the library" )
+option (ASSIMP_BUILD_STATIC_LIB "Build a static (.a) version of the library" OFF)
 
 
 SET(ASSIMP_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools")
 SET(ASSIMP_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools")
 
 
@@ -102,8 +101,9 @@ ENDIF()
 
 
 # Globally enable Boost resp. the Boost workaround – it is also needed by the
 # Globally enable Boost resp. the Boost workaround – it is also needed by the
 # tools which include the Assimp headers.
 # tools which include the Assimp headers.
-SET ( ASSIMP_ENABLE_BOOST_WORKAROUND ON CACHE BOOL
+option ( ASSIMP_ENABLE_BOOST_WORKAROUND
 	"If a simple implementation of the used Boost functions is used. Slightly reduces functionality, but enables builds without Boost available."
 	"If a simple implementation of the used Boost functions is used. Slightly reduces functionality, but enables builds without Boost available."
+	ON
 )
 )
 IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
 IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
 	INCLUDE_DIRECTORIES( code/BoostWorkaround )
 	INCLUDE_DIRECTORIES( code/BoostWorkaround )
@@ -129,8 +129,9 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in"         "${C
 configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
 configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
 install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake"             "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
 install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake"             "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
 
 
-SET ( ASSIMP_NO_EXPORT OFF CACHE BOOL
-	"Disable Assimp's export functionality." 
+option ( ASSIMP_NO_EXPORT
+	"Disable Assimp's export functionality."
+	OFF
 )
 )
 
 
 # Search for external dependencies, and build them from source if not found
 # Search for external dependencies, and build them from source if not found
@@ -186,8 +187,9 @@ ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "")
 MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
 MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
 
 
 ADD_SUBDIRECTORY( code/ )
 ADD_SUBDIRECTORY( code/ )
-SET ( ASSIMP_BUILD_ASSIMP_TOOLS ON CACHE BOOL
+option ( ASSIMP_BUILD_ASSIMP_TOOLS
 	"If the supplementary tools for Assimp are built in addition to the library."
 	"If the supplementary tools for Assimp are built in addition to the library."
+	ON
 )
 )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 	IF ( WIN32 )
 	IF ( WIN32 )
@@ -196,8 +198,9 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 	ADD_SUBDIRECTORY( tools/assimp_cmd/ )
 	ADD_SUBDIRECTORY( tools/assimp_cmd/ )
 ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 
 
-SET ( ASSIMP_BUILD_SAMPLES OFF CACHE BOOL
+option ( ASSIMP_BUILD_SAMPLES
 	"If the official samples are built as well (needs Glut)."
 	"If the official samples are built as well (needs Glut)."
+	OFF
 )
 )
 
 
 IF ( ASSIMP_BUILD_SAMPLES)
 IF ( ASSIMP_BUILD_SAMPLES)
@@ -207,19 +210,19 @@ IF ( ASSIMP_BUILD_SAMPLES)
 	ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
 	ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
 ENDIF ( ASSIMP_BUILD_SAMPLES )
 ENDIF ( ASSIMP_BUILD_SAMPLES )
 
 
-IF ( WIN32 )
-	SET ( ASSIMP_BUILD_TESTS ON CACHE BOOL
-		"If the test suite for Assimp is built in addition to the library."
-	)
+option ( ASSIMP_BUILD_TESTS
+	"If the test suite for Assimp is built in addition to the library."
+	ON
+)
 	
 	
-	IF ( ASSIMP_BUILD_TESTS )
-		ADD_SUBDIRECTORY( test/ )
-	ENDIF ( ASSIMP_BUILD_TESTS )
-ENDIF ( WIN32 )
+IF ( ASSIMP_BUILD_TESTS )
+	ADD_SUBDIRECTORY( test/ )
+ENDIF ( ASSIMP_BUILD_TESTS )
 
 
 IF(MSVC)
 IF(MSVC)
-	SET ( ASSIMP_INSTALL_PDB ON CACHE BOOL
+	option ( ASSIMP_INSTALL_PDB
 		"Install MSVC debug files."
 		"Install MSVC debug files."
+		ON
 	)
 	)
 ENDIF(MSVC)
 ENDIF(MSVC)
 
 

+ 5 - 1
Readme.md

@@ -1,7 +1,7 @@
 Open Asset Import Library (assimp) 
 Open Asset Import Library (assimp) 
 ========
 ========
 
 
-Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a shared, in-memory format__. It supports more than __30 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials_ and many more.
+Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a shared, in-memory format__. It supports more than __40 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials_ and many more.
 
 
 This is the development trunk of assimp containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories. According to [Travis-CI] (https://travis-ci.org/), the current build status of the trunk is [![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
 This is the development trunk of assimp containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories. According to [Travis-CI] (https://travis-ci.org/), the current build status of the trunk is [![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
 
 
@@ -46,6 +46,7 @@ The library provides importers for a lot of file formats, including:
 - Ogre Binary
 - Ogre Binary
 - Ogre XML
 - Ogre XML
 - Q3D
 - Q3D
+- ASSBIN (Assimp scene serialization)
  
  
 Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries.
 Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries.
 
 
@@ -57,7 +58,10 @@ Exporters include:
 - STL
 - STL
 - OBJ
 - OBJ
 - PLY
 - PLY
+- X
+- 3DS
 - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
 - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
+- ASSBIN
 	
 	
 See [the full list here](http://assimp.sourceforge.net/main_features_formats.html).
 See [the full list here](http://assimp.sourceforge.net/main_features_formats.html).
 
 

+ 560 - 0
code/3DSExporter.cpp

@@ -0,0 +1,560 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, 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.
+
+----------------------------------------------------------------------
+*/
+
+#include "AssimpPCH.h"
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
+
+#include "3DSExporter.h"
+#include "3DSLoader.h"
+#include "SceneCombiner.h"
+#include "SplitLargeMeshes.h"
+
+using namespace Assimp;
+namespace Assimp	{
+
+namespace {
+
+	//////////////////////////////////////////////////////////////////////////////////////
+	// Scope utility to write a 3DS file chunk.
+	//
+	// Upon construction, the chunk header is written with the chunk type (flags)
+	// filled out, but the chunk size left empty. Upon destruction, the correct chunk
+	// size based on the then-position of the output stream cursor is filled in.
+	class ChunkWriter {
+		enum {
+			  CHUNK_SIZE_NOT_SET = 0xdeadbeef
+			, SIZE_OFFSET        = 2
+		};
+	public:
+
+		ChunkWriter(StreamWriterLE& writer, uint16_t chunk_type)
+			: writer(writer)
+		{
+			chunk_start_pos = writer.GetCurrentPos();
+			writer.PutU2(chunk_type);
+			writer.PutU4(CHUNK_SIZE_NOT_SET);
+		}
+
+		~ChunkWriter() {
+			std::size_t head_pos = writer.GetCurrentPos();
+
+			ai_assert(head_pos > chunk_start_pos);
+			const std::size_t chunk_size = head_pos - chunk_start_pos;
+
+			writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET);
+			writer.PutU4(chunk_size);
+			writer.SetCurrentPos(head_pos);
+		}
+		
+	private:
+		StreamWriterLE& writer;
+		std::size_t chunk_start_pos;
+	};
+
+
+	// Return an unique name for a given |mesh| attached to |node| that
+	// preserves the mesh's given name if it has one. |index| is the index
+	// of the mesh in |aiScene::mMeshes|.
+	std::string GetMeshName(const aiMesh& mesh, unsigned int index, const aiNode& node) {
+		static const std::string underscore = "_";
+		char postfix[10] = {0};
+		ASSIMP_itoa10(postfix, index);
+
+		std::string result = node.mName.C_Str();
+		if (mesh.mName.length > 0) {
+			result += underscore + mesh.mName.C_Str();
+		}
+		return result + underscore + postfix;
+	}
+
+	// Return an unique name for a given |mat| with original position |index|
+	// in |aiScene::mMaterials|. The name preserves the original material
+	// name if possible.
+	std::string GetMaterialName(const aiMaterial& mat, unsigned int index) {
+		static const std::string underscore = "_";
+		char postfix[10] = {0};
+		ASSIMP_itoa10(postfix, index);
+
+		aiString mat_name;
+		if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
+			return mat_name.C_Str() + underscore + postfix;
+		}
+
+		return "Material" + underscore + postfix;
+	}
+
+	// Collect world transformations for each node
+	void CollectTrafos(const aiNode* node, std::map<const aiNode*, aiMatrix4x4>& trafos) {
+		const aiMatrix4x4& parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4();
+		trafos[node] = parent * node->mTransformation;
+		for (unsigned int i = 0; i < node->mNumChildren; ++i) {
+			CollectTrafos(node->mChildren[i], trafos);
+		}
+	}
+
+	// Generate a flat list of the meshes (by index) assigned to each node
+	void CollectMeshes(const aiNode* node, std::multimap<const aiNode*, unsigned int>& meshes) {
+		for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
+			meshes.insert(std::make_pair(node, node->mMeshes[i]));
+		}
+		for (unsigned int i = 0; i < node->mNumChildren; ++i) {
+			CollectMeshes(node->mChildren[i], meshes);
+		}
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+// Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
+void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+{
+	boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
+	if(!outfile) {
+		throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile));
+	} 
+
+	// TODO: This extra copy should be avoided and all of this made a preprocess
+	// requirement of the 3DS exporter.
+	//
+	// 3DS meshes can be max 0xffff (16 Bit) vertices and faces, respectively.
+	// SplitLargeMeshes can do this, but it requires the correct limit to be set
+	// which is not possible with the current way of specifying preprocess steps
+	// in |Exporter::ExportFormatEntry|.
+	aiScene* scenecopy_tmp;
+	SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
+	std::auto_ptr<aiScene> scenecopy(scenecopy_tmp);
+
+	SplitLargeMeshesProcess_Triangle tri_splitter;
+	tri_splitter.SetLimit(0xffff);
+	tri_splitter.Execute(scenecopy.get());
+
+	SplitLargeMeshesProcess_Vertex vert_splitter;
+	vert_splitter.SetLimit(0xffff);
+	vert_splitter.Execute(scenecopy.get());
+
+	// Invoke the actual exporter 
+	Discreet3DSExporter exporter(outfile, scenecopy.get());
+}
+
+} // end of namespace Assimp
+
+// ------------------------------------------------------------------------------------------------
+Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* scene)
+: scene(scene)
+, writer(outfile)
+{
+	CollectTrafos(scene->mRootNode, trafos);
+	CollectMeshes(scene->mRootNode, meshes);
+
+	ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAIN);
+
+	{
+		ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
+		WriteMeshes();
+		WriteMaterials();
+
+		{
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
+			writer.PutF4(1.0f);
+		}
+	}
+
+	{
+		ChunkWriter chunk(writer, Discreet3DS::CHUNK_KEYFRAMER);
+		WriteHierarchy(*scene->mRootNode, -1, -1);
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling_level)
+{
+	// 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec
+	{
+		ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
+		{
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
+
+			// Assimp node names are unique and distinct from all mesh-node
+			// names we generate; thus we can use them as-is
+			WriteString(node.mName);
+
+			// Two unknown int16 values - it is even unclear if 0 is a safe value
+			// but luckily importers do not know better either.
+			writer.PutI4(0);
+
+			int16_t hierarchy_pos = static_cast<int16_t>(seq);
+			if (sibling_level != -1) {
+				hierarchy_pos = sibling_level;
+			}
+
+			// Write the hierarchy position
+			writer.PutI2(hierarchy_pos);
+		}
+	}
+
+	// TODO: write transformation chunks
+
+	++seq;
+	sibling_level = seq;
+
+	// Write all children
+	for (unsigned int i = 0; i < node.mNumChildren; ++i) {
+		seq = WriteHierarchy(*node.mChildren[i], seq, i == 0 ? -1 : sibling_level);
+	}
+
+	// Write all meshes as separate nodes to be able to reference the meshes by name
+	for (unsigned int i = 0; i < node.mNumMeshes; ++i) {
+		const bool first_child = node.mNumChildren == 0 && i == 0;
+
+		const unsigned int mesh_idx = node.mMeshes[i];
+		const aiMesh& mesh = *scene->mMeshes[mesh_idx];
+
+		ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
+		{
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
+			WriteString(GetMeshName(mesh, mesh_idx, node));
+
+			writer.PutI4(0);
+			writer.PutI2(static_cast<int16_t>(first_child ? seq : sibling_level));
+			++seq;
+		}
+	}
+	return seq;
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteMaterials()
+{
+	for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
+		ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL);
+		const aiMaterial& mat = *scene->mMaterials[i];
+
+		{
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATNAME);
+			const std::string& name = GetMaterialName(mat, i);
+			WriteString(name);
+		}
+
+		aiColor3D color;
+		if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) {
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE);
+			WriteColor(color);
+		}
+
+		if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) {
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
+			WriteColor(color);
+		}
+
+		if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) {
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
+			WriteColor(color);
+		}
+
+		if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) {
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM);
+			WriteColor(color);
+		}
+
+		aiShadingMode shading_mode;
+		if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
+
+			Discreet3DS::shadetype3ds shading_mode_out;
+			switch(shading_mode) {
+			case aiShadingMode_Flat:
+			case aiShadingMode_NoShading:
+				shading_mode_out = Discreet3DS::Flat;
+				break;
+
+			case aiShadingMode_Gouraud:
+			case aiShadingMode_Toon:
+			case aiShadingMode_OrenNayar:
+			case aiShadingMode_Minnaert:
+				shading_mode_out = Discreet3DS::Gouraud;
+				break;
+
+			case aiShadingMode_Phong:
+			case aiShadingMode_Blinn:
+			case aiShadingMode_CookTorrance:
+			case aiShadingMode_Fresnel:
+				shading_mode_out = Discreet3DS::Phong;
+				break;
+
+			default:
+				ai_assert(false);
+			};
+			writer.PutU2(static_cast<uint16_t>(shading_mode_out));
+		}
+
+
+		float f;
+		if (mat.Get(AI_MATKEY_SHININESS, f) == AI_SUCCESS) {
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS);
+			WritePercentChunk(f);
+		}
+
+		if (mat.Get(AI_MATKEY_SHININESS_STRENGTH, f) == AI_SUCCESS) {
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS_PERCENT);
+			WritePercentChunk(f);
+		}
+
+		int twosided;
+		if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE);
+			writer.PutI2(1);
+		}
+		
+		WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE);
+		WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP);
+		WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP);
+		WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP);
+		WriteTexture(mat, aiTextureType_SPECULAR, Discreet3DS::CHUNK_MAT_SPECMAP);
+		WriteTexture(mat, aiTextureType_EMISSIVE, Discreet3DS::CHUNK_MAT_SELFIMAP);
+		WriteTexture(mat, aiTextureType_REFLECTION, Discreet3DS::CHUNK_MAT_REFLMAP);
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags) 
+{
+	aiString path;
+	aiTextureMapMode map_mode[2] = {
+		aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
+	};
+	float blend = 1.0f;
+	if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) {
+		return;
+	}
+
+	// TODO: handle embedded textures properly
+	if (path.data[0] == '*') {
+		DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str()));
+		return;
+	}
+
+	ChunkWriter chunk(writer, chunk_flags);
+	{
+		ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE);
+		WriteString(path);
+	}
+
+	WritePercentChunk(blend);
+
+	{
+		ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING);
+		uint16_t val = 0; // WRAP
+		if (map_mode[0] == aiTextureMapMode_Mirror) {
+			val = 0x2;
+		}
+		else if (map_mode[0] == aiTextureMapMode_Decal) {
+			val = 0x10;
+		}
+		writer.PutU2(val);
+	}
+	// TODO: export texture transformation (i.e. UV offset, scale, rotation)
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteMeshes()
+{
+	// NOTE: 3DS allows for instances. However:
+	//   i)  not all importers support reading them
+	//   ii) instances are not as flexible as they are in assimp, in particular,
+	//        nodes can carry (and instance) only one mesh.
+	//
+	// This exporter currently deep clones all instanced meshes, i.e. for each mesh
+	// attached to a node a full TRIMESH chunk is written to the file.
+	//
+	// Furthermore, the TRIMESH is transformed into world space so that it will
+	// appear correctly if importers don't read the scene hierarchy at all.
+	for (MeshesByNodeMap::const_iterator it = meshes.begin(); it != meshes.end(); ++it) {
+		const aiNode& node = *(*it).first;
+		const unsigned int mesh_idx = (*it).second;
+
+		const aiMesh& mesh = *scene->mMeshes[mesh_idx];
+
+		// This should not happen if the SLM step is correctly executed
+		// before the scene is handed to the exporter
+		ai_assert(mesh.mNumVertices <= 0xffff);
+		ai_assert(mesh.mNumFaces <= 0xffff);
+
+		const aiMatrix4x4& trafo = trafos[&node];
+
+		ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJBLOCK);
+
+		// Mesh name is tied to the node it is attached to so it can later be referenced
+		const std::string& name = GetMeshName(mesh, mesh_idx, node);
+		WriteString(name);
+
+
+		// TRIMESH chunk
+		ChunkWriter chunk2(writer, Discreet3DS::CHUNK_TRIMESH);
+
+		// Vertices in world space
+		{
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_VERTLIST);
+
+			const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
+			writer.PutU2(count);
+			for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
+				const aiVector3D& v = trafo * mesh.mVertices[i];
+				writer.PutF4(v.x);
+				writer.PutF4(v.y);
+				writer.PutF4(v.z);
+			}
+		}
+
+		// UV coordinates
+		if (mesh.HasTextureCoords(0)) {
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPLIST);
+			const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
+			writer.PutU2(count);
+
+			for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
+				const aiVector3D& v = mesh.mTextureCoords[0][i];
+				writer.PutF4(v.x);
+				writer.PutF4(v.y);
+			}
+		}
+
+		// Faces (indices)
+		{
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACELIST);
+
+			ai_assert(mesh.mNumFaces <= 0xffff);
+
+			// Count triangles, discard lines and points
+			uint16_t count = 0;
+			for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
+				const aiFace& f = mesh.mFaces[i];
+				if (f.mNumIndices < 3) {
+					continue;
+				}
+				// TRIANGULATE step is a pre-requisite so we should not see polys here
+				ai_assert(f.mNumIndices == 3);
+				++count;
+			}
+
+			writer.PutU2(count);
+			for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
+				const aiFace& f = mesh.mFaces[i];
+				if (f.mNumIndices < 3) {
+					continue;
+				}
+
+				for (unsigned int j = 0; j < 3; ++j) {
+					ai_assert(f.mIndices[j] <= 0xffff);
+					writer.PutI2(static_cast<uint16_t>(f.mIndices[j]));
+				}
+
+				// Edge visibility flag
+				writer.PutI2(0x0);
+			}
+
+			// TODO: write smoothing groups (CHUNK_SMOOLIST)
+
+			WriteFaceMaterialChunk(mesh);
+		}
+
+		// Transformation matrix by which the mesh vertices have been pre-transformed with.
+		{
+			ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRMATRIX);
+			for (unsigned int r = 0; r < 4; ++r) {
+				for (unsigned int c = 0; c < 3; ++c) {
+					writer.PutF4(trafo[r][c]);
+				}
+			}
+		}
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh)
+{
+	ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACEMAT);
+	const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex);
+	WriteString(name);
+
+	// Because assimp splits meshes by material, only a single
+	// FACEMAT chunk needs to be written
+	ai_assert(mesh.mNumFaces <= 0xffff);
+	const uint16_t count = static_cast<uint16_t>(mesh.mNumFaces);
+	writer.PutU2(count);
+
+	for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
+		writer.PutU2(static_cast<uint16_t>(i));
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteString(const std::string& s) {
+	for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
+		writer.PutI1(*it);
+	}
+	writer.PutI1('\0');
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteString(const aiString& s) {
+	for (std::size_t i = 0; i < s.length; ++i) {
+		writer.PutI1(s.data[i]);
+	}
+	writer.PutI1('\0');
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteColor(const aiColor3D& color) {
+	ChunkWriter chunk(writer, Discreet3DS::CHUNK_RGBF);
+	writer.PutF4(color.r);
+	writer.PutF4(color.g);
+	writer.PutF4(color.b);
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WritePercentChunk(float f) {
+	ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTF);
+	writer.PutF4(f);
+}
+
+
+#endif // ASSIMP_BUILD_NO_3DS_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT

+ 94 - 0
code/3DSExporter.h

@@ -0,0 +1,94 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, 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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file 3DSExporter.h
+ * 3DS Exporter Main Header
+ */
+#ifndef AI_3DSEXPORTER_H_INC
+#define AI_3DSEXPORTER_H_INC
+
+#include <map>
+
+#include "StreamWriter.h"
+
+struct aiScene;
+struct aiNode;
+
+namespace Assimp	
+{
+
+// ------------------------------------------------------------------------------------------------
+/** Helper class to export a given scene to a 3DS file. */
+// ------------------------------------------------------------------------------------------------
+class Discreet3DSExporter
+{
+public:
+	Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* pScene);
+
+private:
+
+	void WriteMeshes();
+	void WriteMaterials();
+	void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
+
+	void WriteFaceMaterialChunk(const aiMesh& mesh);
+
+	int WriteHierarchy(const aiNode& node, int level, int sibling_level);
+
+	void WriteString(const std::string& s);
+	void WriteString(const aiString& s);
+	void WriteColor(const aiColor3D& color);
+	void WritePercentChunk(float f);
+
+private:
+
+	const aiScene* const scene;
+	StreamWriterLE writer;
+
+	std::map<const aiNode*, aiMatrix4x4> trafos;
+
+	typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
+	MeshesByNodeMap meshes;
+
+};
+
+}
+
+#endif

+ 2 - 2
code/3DSLoader.h

@@ -273,8 +273,8 @@ protected:
 	bool bIsPrj;
 	bool bIsPrj;
 };
 };
 
 
-#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
-
 } // end of namespace Assimp
 } // end of namespace Assimp
 
 
+#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
+
 #endif // AI_3DSIMPORTER_H_INC
 #endif // AI_3DSIMPORTER_H_INC

+ 762 - 0
code/AssbinExporter.cpp

@@ -0,0 +1,762 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, 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.
+
+----------------------------------------------------------------------
+*/
+/** @file  AssbinExporter.cpp
+ *  ASSBIN exporter main code
+ */
+#include "AssimpPCH.h"
+#include "assbin_chunks.h"
+#include "./../include/assimp/version.h"
+#include "ProcessHelper.h"
+
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+#	include <zlib.h>
+#else
+#	include "../contrib/zlib/zlib.h"
+#endif
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+
+using namespace Assimp;
+
+namespace Assimp	{
+
+template <typename T> 
+size_t Write(IOStream * stream, const T& v)
+{
+	return stream->Write( &v, sizeof(T), 1 );
+}
+
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiString
+template <>
+inline size_t Write<aiString>(IOStream * stream, const aiString& s)
+{
+	const size_t s2 = (uint32_t)s.length;
+	stream->Write(&s,4,1);
+	stream->Write(s.data,s2,1);
+	return s2+4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an unsigned int as uint32_t
+template <>
+inline size_t Write<unsigned int>(IOStream * stream, const unsigned int& w)
+{
+	const uint32_t t = (uint32_t)w;
+	if (w > t) {
+		// this shouldn't happen, integers in Assimp data structures never exceed 2^32
+		throw new DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion");
+	}
+
+	stream->Write(&t,4,1);
+	return 4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an unsigned int as uint16_t
+template <>
+inline size_t Write<uint16_t>(IOStream * stream, const uint16_t& w)
+{
+	BOOST_STATIC_ASSERT(sizeof(uint16_t)==2);
+	stream->Write(&w,2,1);
+	return 2;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a float
+template <>
+inline size_t Write<float>(IOStream * stream, const float& f)
+{
+	BOOST_STATIC_ASSERT(sizeof(float)==4);
+	stream->Write(&f,4,1);
+	return 4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a double
+template <>
+inline size_t Write<double>(IOStream * stream, const double& f)
+{
+	BOOST_STATIC_ASSERT(sizeof(double)==8);
+	stream->Write(&f,8,1);
+	return 8;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a vec3
+template <>
+inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v)
+{
+	size_t t = Write<float>(stream,v.x);
+	t += Write<float>(stream,v.y);
+	t += Write<float>(stream,v.z);
+	return t;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a color value
+template <>
+inline size_t Write<aiColor4D>(IOStream * stream, const aiColor4D& v)
+{
+	size_t t = Write<float>(stream,v.r);
+	t += Write<float>(stream,v.g);
+	t += Write<float>(stream,v.b);
+	t += Write<float>(stream,v.a);
+	return t;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a quaternion
+template <>
+inline size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v)
+{
+	size_t t = Write<float>(stream,v.w);
+	t += Write<float>(stream,v.x);
+	t += Write<float>(stream,v.y);
+	t += Write<float>(stream,v.z);
+	return 16;
+}
+
+
+// -----------------------------------------------------------------------------------
+// Serialize a vertex weight
+template <>
+inline size_t Write<aiVertexWeight>(IOStream * stream, const aiVertexWeight& v)
+{
+	size_t t = Write<unsigned int>(stream,v.mVertexId);
+	return t+Write<float>(stream,v.mWeight);
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a mat4x4
+template <>
+inline size_t Write<aiMatrix4x4>(IOStream * stream, const aiMatrix4x4& m)
+{
+	for (unsigned int i = 0; i < 4;++i) {
+		for (unsigned int i2 = 0; i2 < 4;++i2) {
+			Write<float>(stream,m[i][i2]);
+		}
+	}
+	return 64;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiVectorKey
+template <>
+inline size_t Write<aiVectorKey>(IOStream * stream, const aiVectorKey& v)
+{
+	const size_t t = Write<double>(stream,v.mTime);
+	return t + Write<aiVector3D>(stream,v.mValue);
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiQuatKey
+template <>
+inline size_t Write<aiQuatKey>(IOStream * stream, const aiQuatKey& v)
+{
+	const size_t t = Write<double>(stream,v.mTime);
+	return t + Write<aiQuaternion>(stream,v.mValue);
+}
+
+template <typename T>
+inline size_t WriteBounds(IOStream * stream, const T* in, unsigned int size)
+{
+	T minc,maxc;
+	ArrayBounds(in,size,minc,maxc);
+
+	const size_t t = Write<T>(stream,minc);
+	return t + Write<T>(stream,maxc);
+}
+
+// We use this to write out non-byte arrays so that we write using the specializations.
+// This way we avoid writing out extra bytes that potentially come from struct alignment.
+template <typename T>
+inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
+{
+	size_t n = 0;
+	for (unsigned int i=0; i<size; i++) n += Write<T>(stream,in[i]);
+	return n;
+}
+
+	// ----------------------------------------------------------------------------------
+	/**	@class	AssbinChunkWriter
+	 *	@brief	Chunk writer mechanism for the .assbin file structure
+	 *
+	 *  This is a standard in-memory IOStream (most of the code is based on BlobIOStream),
+	 *  the difference being that this takes another IOStream as a "container" in the
+	 *  constructor, and when it is destroyed, it appends the magic number, the chunk size,
+	 *  and the chunk contents to the container stream. This allows relatively easy chunk
+	 *  chunk construction, even recursively.
+	 */
+	class AssbinChunkWriter : public IOStream
+	{
+	private:
+
+		uint8_t* buffer;
+		uint32_t magic;
+		IOStream * container;
+		size_t cur_size, cursor, initial;
+
+	private:
+		// -------------------------------------------------------------------
+		void Grow(size_t need = 0) 
+		{
+			size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
+
+			const uint8_t* const old = buffer;
+			buffer = new uint8_t[new_size];
+
+			if (old) {
+				memcpy(buffer,old,cur_size);
+				delete[] old;
+			}
+
+			cur_size = new_size;
+		}
+
+	public:
+
+		AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096) 
+			: buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial)
+		{
+		}
+
+		virtual ~AssbinChunkWriter() 
+		{
+			if (container) {
+				container->Write( &magic, sizeof(uint32_t), 1 );
+				container->Write( &cursor, sizeof(uint32_t), 1 );
+				container->Write( buffer, 1, cursor );
+			}
+			if (buffer) delete[] buffer;
+		}
+
+		void * GetBufferPointer() { return buffer; };
+
+		// -------------------------------------------------------------------
+		virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; };
+		virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; };
+		virtual size_t Tell() const { return cursor; };
+		virtual void Flush() { };
+
+		virtual size_t FileSize() const
+		{
+			return cursor;
+		}
+
+		// -------------------------------------------------------------------
+		virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount) 
+		{
+			pSize *= pCount;
+			if (cursor + pSize > cur_size) {
+				Grow(cursor + pSize);
+			}
+
+			memcpy(buffer+cursor, pvBuffer, pSize);
+			cursor += pSize;
+
+			return pCount; 
+		}
+
+	};
+
+	// ----------------------------------------------------------------------------------
+	/**	@class	AssbinExport
+	 *	@brief	Assbin exporter class
+	 *
+	 *  This class performs the .assbin exporting, and is responsible for the file layout.
+	 */
+	class AssbinExport
+	{
+	private:
+		bool shortened;
+		bool compressed;
+
+	protected:
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryNode( IOStream * container, const aiNode* node)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
+
+			Write<aiString>(&chunk,node->mName);
+			Write<aiMatrix4x4>(&chunk,node->mTransformation);
+			Write<unsigned int>(&chunk,node->mNumChildren);
+			Write<unsigned int>(&chunk,node->mNumMeshes);
+
+			for (unsigned int i = 0; i < node->mNumMeshes;++i) {
+				Write<unsigned int>(&chunk,node->mMeshes[i]);
+			}
+
+			for (unsigned int i = 0; i < node->mNumChildren;++i) {
+				WriteBinaryNode( &chunk, node->mChildren[i] );
+			}
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryTexture(IOStream * container, const aiTexture* tex)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AITEXTURE );
+
+			Write<unsigned int>(&chunk,tex->mWidth);
+			Write<unsigned int>(&chunk,tex->mHeight);
+			chunk.Write( tex->achFormatHint, sizeof(char), 4 );
+
+			if(!shortened) {
+				if (!tex->mHeight) {
+					chunk.Write(tex->pcData,1,tex->mWidth);
+				}
+				else {
+					chunk.Write(tex->pcData,1,tex->mWidth*tex->mHeight*4);
+				}
+			}
+
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryBone(IOStream * container, const aiBone* b)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIBONE );
+
+			Write<aiString>(&chunk,b->mName);
+			Write<unsigned int>(&chunk,b->mNumWeights);
+			Write<aiMatrix4x4>(&chunk,b->mOffsetMatrix);
+
+			// for the moment we write dumb min/max values for the bones, too.
+			// maybe I'll add a better, hash-like solution later
+			if (shortened) {
+				WriteBounds(&chunk,b->mWeights,b->mNumWeights);
+			} // else write as usual
+			else WriteArray<aiVertexWeight>(&chunk,b->mWeights,b->mNumWeights);
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryMesh(IOStream * container, const aiMesh* mesh)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMESH );
+
+			Write<unsigned int>(&chunk,mesh->mPrimitiveTypes);
+			Write<unsigned int>(&chunk,mesh->mNumVertices);
+			Write<unsigned int>(&chunk,mesh->mNumFaces);
+			Write<unsigned int>(&chunk,mesh->mNumBones);
+			Write<unsigned int>(&chunk,mesh->mMaterialIndex);
+
+			// first of all, write bits for all existent vertex components
+			unsigned int c = 0;
+			if (mesh->mVertices) {
+				c |= ASSBIN_MESH_HAS_POSITIONS;
+			}
+			if (mesh->mNormals) {
+				c |= ASSBIN_MESH_HAS_NORMALS;
+			}
+			if (mesh->mTangents && mesh->mBitangents) {
+				c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS;
+			}
+			for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
+				if (!mesh->mTextureCoords[n]) {
+					break;
+				}
+				c |= ASSBIN_MESH_HAS_TEXCOORD(n);
+			}
+			for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
+				if (!mesh->mColors[n]) {
+					break;
+				}
+				c |= ASSBIN_MESH_HAS_COLOR(n);
+			}
+			Write<unsigned int>(&chunk,c);
+
+			aiVector3D minVec, maxVec;
+			if (mesh->mVertices) {
+				if (shortened) {
+					WriteBounds(&chunk,mesh->mVertices,mesh->mNumVertices);
+				} // else write as usual
+				else WriteArray<aiVector3D>(&chunk,mesh->mVertices,mesh->mNumVertices);
+			}
+			if (mesh->mNormals) {
+				if (shortened) {
+					WriteBounds(&chunk,mesh->mNormals,mesh->mNumVertices);
+				} // else write as usual
+				else WriteArray<aiVector3D>(&chunk,mesh->mNormals,mesh->mNumVertices);
+			}
+			if (mesh->mTangents && mesh->mBitangents) {
+				if (shortened) {
+					WriteBounds(&chunk,mesh->mTangents,mesh->mNumVertices);
+					WriteBounds(&chunk,mesh->mBitangents,mesh->mNumVertices);
+				} // else write as usual
+				else {
+					WriteArray<aiVector3D>(&chunk,mesh->mTangents,mesh->mNumVertices);
+					WriteArray<aiVector3D>(&chunk,mesh->mBitangents,mesh->mNumVertices);
+				}
+			}
+			for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
+				if (!mesh->mColors[n])
+					break;
+
+				if (shortened) {
+					WriteBounds(&chunk,mesh->mColors[n],mesh->mNumVertices);
+				} // else write as usual
+				else WriteArray<aiColor4D>(&chunk,mesh->mColors[n],mesh->mNumVertices);
+			}
+			for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
+				if (!mesh->mTextureCoords[n])
+					break;
+
+				// write number of UV components
+				Write<unsigned int>(&chunk,mesh->mNumUVComponents[n]);
+
+				if (shortened) {
+					WriteBounds(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices);
+				} // else write as usual
+				else WriteArray<aiVector3D>(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices);
+			}
+
+			// write faces. There are no floating-point calculations involved
+			// in these, so we can write a simple hash over the face data
+			// to the dump file. We generate a single 32 Bit hash for 512 faces
+			// using Assimp's standard hashing function.
+			if (shortened) {
+				unsigned int processed = 0;
+				for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) {
+
+					uint32_t hash = 0;
+					for (unsigned int a = 0; a < job;++a) {
+
+						const aiFace& f = mesh->mFaces[processed+a];
+						uint32_t tmp = f.mNumIndices;
+						hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
+						for (unsigned int i = 0; i < f.mNumIndices; ++i) {
+							BOOST_STATIC_ASSERT(AI_MAX_VERTICES <= 0xffffffff);
+							tmp = static_cast<uint32_t>( f.mIndices[i] );
+							hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
+						}
+					}
+					Write<unsigned int>(&chunk,hash);
+				}
+			}
+			else // else write as usual
+			{
+				// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
+				for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
+					const aiFace& f = mesh->mFaces[i];
+
+					BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff);
+					Write<uint16_t>(&chunk,f.mNumIndices);
+
+					for (unsigned int a = 0; a < f.mNumIndices;++a) {
+						if (mesh->mNumVertices < (1u<<16)) {
+							Write<uint16_t>(&chunk,f.mIndices[a]);
+						}
+						else Write<unsigned int>(&chunk,f.mIndices[a]);
+					}
+				}
+			}
+
+			// write bones
+			if (mesh->mNumBones) {
+				for (unsigned int a = 0; a < mesh->mNumBones;++a) {
+					const aiBone* b = mesh->mBones[a];
+					WriteBinaryBone(&chunk,b);
+				}
+			}
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryMaterialProperty(IOStream * container, const aiMaterialProperty* prop)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIALPROPERTY );
+
+			Write<aiString>(&chunk,prop->mKey);
+			Write<unsigned int>(&chunk,prop->mSemantic);
+			Write<unsigned int>(&chunk,prop->mIndex);
+
+			Write<unsigned int>(&chunk,prop->mDataLength);
+			Write<unsigned int>(&chunk,(unsigned int)prop->mType);
+			chunk.Write(prop->mData,1,prop->mDataLength);
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryMaterial(IOStream * container, const aiMaterial* mat)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIAL);
+
+			Write<unsigned int>(&chunk,mat->mNumProperties);
+			for (unsigned int i = 0; i < mat->mNumProperties;++i) {
+				WriteBinaryMaterialProperty( &chunk, mat->mProperties[i]);
+			}
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryNodeAnim(IOStream * container, const aiNodeAnim* nd)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODEANIM );
+
+			Write<aiString>(&chunk,nd->mNodeName);
+			Write<unsigned int>(&chunk,nd->mNumPositionKeys);
+			Write<unsigned int>(&chunk,nd->mNumRotationKeys);
+			Write<unsigned int>(&chunk,nd->mNumScalingKeys);
+			Write<unsigned int>(&chunk,nd->mPreState);
+			Write<unsigned int>(&chunk,nd->mPostState);
+
+			if (nd->mPositionKeys) {
+				if (shortened) {
+					WriteBounds(&chunk,nd->mPositionKeys,nd->mNumPositionKeys);
+
+				} // else write as usual
+				else WriteArray<aiVectorKey>(&chunk,nd->mPositionKeys,nd->mNumPositionKeys);
+			}
+			if (nd->mRotationKeys) {
+				if (shortened) {
+					WriteBounds(&chunk,nd->mRotationKeys,nd->mNumRotationKeys);
+
+				} // else write as usual
+				else WriteArray<aiQuatKey>(&chunk,nd->mRotationKeys,nd->mNumRotationKeys);
+			}
+			if (nd->mScalingKeys) {
+				if (shortened) {
+					WriteBounds(&chunk,nd->mScalingKeys,nd->mNumScalingKeys);
+
+				} // else write as usual
+				else WriteArray<aiVectorKey>(&chunk,nd->mScalingKeys,nd->mNumScalingKeys);
+			}
+		}
+
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryAnim( IOStream * container, const aiAnimation* anim )
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIANIMATION );
+
+			Write<aiString>(&chunk,anim->mName);
+			Write<double>(&chunk,anim->mDuration);
+			Write<double>(&chunk,anim->mTicksPerSecond);
+			Write<unsigned int>(&chunk,anim->mNumChannels);
+
+			for (unsigned int a = 0; a < anim->mNumChannels;++a) {
+				const aiNodeAnim* nd = anim->mChannels[a];
+				WriteBinaryNodeAnim(&chunk,nd);	
+			}
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryLight( IOStream * container, const aiLight* l )
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AILIGHT );
+
+			Write<aiString>(&chunk,l->mName);
+			Write<unsigned int>(&chunk,l->mType);
+
+			if (l->mType != aiLightSource_DIRECTIONAL) { 
+				Write<float>(&chunk,l->mAttenuationConstant);
+				Write<float>(&chunk,l->mAttenuationLinear);
+				Write<float>(&chunk,l->mAttenuationQuadratic);
+			}
+
+			Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorDiffuse);
+			Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorSpecular);
+			Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorAmbient);
+
+			if (l->mType == aiLightSource_SPOT) {
+				Write<float>(&chunk,l->mAngleInnerCone);
+				Write<float>(&chunk,l->mAngleOuterCone);
+			}
+
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryCamera( IOStream * container, const aiCamera* cam )
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AICAMERA );
+
+			Write<aiString>(&chunk,cam->mName);
+			Write<aiVector3D>(&chunk,cam->mPosition);
+			Write<aiVector3D>(&chunk,cam->mLookAt);
+			Write<aiVector3D>(&chunk,cam->mUp);
+			Write<float>(&chunk,cam->mHorizontalFOV);
+			Write<float>(&chunk,cam->mClipPlaneNear);
+			Write<float>(&chunk,cam->mClipPlaneFar);
+			Write<float>(&chunk,cam->mAspect);
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryScene( IOStream * container, const aiScene* scene)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AISCENE );
+
+			// basic scene information
+			Write<unsigned int>(&chunk,scene->mFlags);
+			Write<unsigned int>(&chunk,scene->mNumMeshes);
+			Write<unsigned int>(&chunk,scene->mNumMaterials);
+			Write<unsigned int>(&chunk,scene->mNumAnimations);
+			Write<unsigned int>(&chunk,scene->mNumTextures);
+			Write<unsigned int>(&chunk,scene->mNumLights);
+			Write<unsigned int>(&chunk,scene->mNumCameras);
+
+			// write node graph
+			WriteBinaryNode( &chunk, scene->mRootNode );
+
+			// write all meshes
+			for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+				const aiMesh* mesh = scene->mMeshes[i];
+				WriteBinaryMesh( &chunk,mesh);
+			}
+
+			// write materials
+			for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
+				const aiMaterial* mat = scene->mMaterials[i];
+				WriteBinaryMaterial(&chunk,mat);
+			}
+
+			// write all animations
+			for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
+				const aiAnimation* anim = scene->mAnimations[i];
+				WriteBinaryAnim(&chunk,anim);
+			}
+
+
+			// write all textures
+			for (unsigned int i = 0; i < scene->mNumTextures;++i) {
+				const aiTexture* mesh = scene->mTextures[i];
+				WriteBinaryTexture(&chunk,mesh);
+			}
+
+			// write lights
+			for (unsigned int i = 0; i < scene->mNumLights;++i) {
+				const aiLight* l = scene->mLights[i];
+				WriteBinaryLight(&chunk,l);
+			}
+
+			// write cameras
+			for (unsigned int i = 0; i < scene->mNumCameras;++i) {
+				const aiCamera* cam = scene->mCameras[i];
+				WriteBinaryCamera(&chunk,cam);
+			}
+
+		}
+
+	public:
+		AssbinExport() 
+			: shortened(false), compressed(false) // temporary settings until properties are introduced for exporters
+		{
+		}
+
+		// -----------------------------------------------------------------------------------
+		// Write a binary model dump
+		void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+		{
+			IOStream * out = pIOSystem->Open( pFile, "wb" );
+			if (!out) return;
+
+			time_t tt = time(NULL);
+			tm* p     = gmtime(&tt);
+
+			// header
+			char s[64];
+			memset( s, 0, 64 );
+#if _MSC_VER >= 1400
+			sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p));
+#else
+			snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p));
+#endif
+			out->Write( s, 44, 1 );
+			// == 44 bytes
+
+			Write<unsigned int>( out, ASSBIN_VERSION_MAJOR );
+			Write<unsigned int>( out, ASSBIN_VERSION_MINOR );
+			Write<unsigned int>( out, aiGetVersionRevision() );
+			Write<unsigned int>( out, aiGetCompileFlags() );
+			Write<uint16_t>( out, shortened );
+			Write<uint16_t>( out, compressed );
+			// ==  20 bytes
+
+			char buff[256]; 
+			strncpy(buff,pFile,256);
+			out->Write(buff,sizeof(char),256);
+
+			char cmd[] = "\0";
+			strncpy(buff,cmd,128);
+			out->Write(buff,sizeof(char),128);
+
+			// leave 64 bytes free for future extensions
+			memset(buff,0xcd,64);
+			out->Write(buff,sizeof(char),64);
+			// == 435 bytes
+
+			// ==== total header size: 512 bytes
+			ai_assert( out->Tell() == ASSBIN_HEADER_LENGTH );
+
+			// Up to here the data is uncompressed. For compressed files, the rest
+			// is compressed using standard DEFLATE from zlib.
+			if (compressed)
+			{
+				AssbinChunkWriter uncompressedStream( NULL, 0 );
+				WriteBinaryScene( &uncompressedStream, pScene );
+
+				uLongf uncompressedSize = uncompressedStream.Tell();
+				uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.);
+				uint8_t* compressedBuffer = new uint8_t[ compressedSize ];
+
+				compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 );
+
+				out->Write( &uncompressedSize, sizeof(uint32_t), 1 );
+				out->Write( compressedBuffer, sizeof(char), compressedSize );
+
+				delete[] compressedBuffer;
+			}
+			else
+			{
+				WriteBinaryScene( out, pScene );
+			}
+
+			pIOSystem->Close( out );
+		}
+	};
+
+void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+{
+	AssbinExport exporter;
+	exporter.WriteBinaryDump( pFile, pIOSystem, pScene );
+}
+} // end of namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT

+ 49 - 0
code/AssbinExporter.h

@@ -0,0 +1,49 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, 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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file AssbinExporter.h
+ * ASSBIN Exporter Main Header
+ */
+#ifndef AI_ASSBINEXPORTER_H_INC
+#define AI_ASSBINEXPORTER_H_INC
+
+// nothing really needed here - reserved for future use like properties
+
+#endif

+ 671 - 0
code/AssbinLoader.cpp

@@ -0,0 +1,671 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, 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.
+---------------------------------------------------------------------------
+*/
+
+/** @file  AssbinLoader.cpp
+ *  @brief Implementation of the .assbin importer class
+ *
+ *  see assbin_chunks.h
+ */
+
+#include "AssimpPCH.h"
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+// internal headers
+#include "AssbinLoader.h"
+#include "assbin_chunks.h"
+#include "MemoryIOWrapper.h"
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+#	include <zlib.h>
+#else
+#	include "../contrib/zlib/zlib.h"
+#endif
+
+using namespace Assimp;
+
+static const aiImporterDesc desc = {
+	".assbin Importer",
+	"Gargaj / Conspiracy",
+	"",
+	"",
+	aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour,
+	0,
+	0,
+	0,
+	0,
+	"assbin" 
+};
+
+const aiImporterDesc* AssbinImporter::GetInfo() const
+{
+	return &desc;
+}
+
+bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const
+{
+	IOStream * in = pIOHandler->Open(pFile);
+	if (!in)
+		return false;
+
+	char s[32];
+	in->Read( s, sizeof(char), 32 );
+
+	pIOHandler->Close(in);
+
+	return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0;
+}
+
+template <typename T>
+T Read(IOStream * stream)
+{
+	T t;
+	stream->Read( &t, sizeof(T), 1 );
+	return t;
+}
+
+template <>
+aiVector3D Read<aiVector3D>(IOStream * stream)
+{
+	aiVector3D v;
+	v.x = Read<float>(stream);
+	v.y = Read<float>(stream);
+	v.z = Read<float>(stream);
+	return v;
+}
+
+template <>
+aiColor4D Read<aiColor4D>(IOStream * stream)
+{
+	aiColor4D c;
+	c.r = Read<float>(stream);
+	c.g = Read<float>(stream);
+	c.b = Read<float>(stream);
+	c.a = Read<float>(stream);
+	return c;
+}
+
+template <>
+aiQuaternion Read<aiQuaternion>(IOStream * stream)
+{
+	aiQuaternion v;
+	v.w = Read<float>(stream);
+	v.x = Read<float>(stream);
+	v.y = Read<float>(stream);
+	v.z = Read<float>(stream);
+	return v;
+}
+
+template <>
+aiString Read<aiString>(IOStream * stream)
+{
+	aiString s;
+	stream->Read(&s.length,4,1);
+	stream->Read(s.data,s.length,1);
+	return s;
+}
+
+template <>
+aiVertexWeight Read<aiVertexWeight>(IOStream * stream)
+{
+	aiVertexWeight w;
+	w.mVertexId = Read<unsigned int>(stream);
+	w.mWeight = Read<float>(stream);
+	return w;
+}
+
+template <>
+aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream)
+{
+	aiMatrix4x4 m;
+	for (unsigned int i = 0; i < 4;++i) {
+		for (unsigned int i2 = 0; i2 < 4;++i2) {
+			m[i][i2] = Read<float>(stream);
+		}
+	}
+	return m;
+}
+
+template <>
+aiVectorKey Read<aiVectorKey>(IOStream * stream)
+{
+	aiVectorKey v;
+	v.mTime = Read<double>(stream);
+	v.mValue = Read<aiVector3D>(stream);
+	return v;
+}
+
+template <>
+aiQuatKey Read<aiQuatKey>(IOStream * stream)
+{
+	aiQuatKey v;
+	v.mTime = Read<double>(stream);
+	v.mValue = Read<aiQuaternion>(stream);
+	return v;
+}
+
+template <typename T>
+void ReadArray(IOStream * stream, T * out, unsigned int size)
+{ 
+	for (unsigned int i=0; i<size; i++) out[i] = Read<T>(stream);
+}
+
+template <typename T> void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n )
+{
+	// not sure what to do here, the data isn't really useful.
+	stream->Seek( sizeof(T) * n, aiOrigin_CUR );
+}
+
+void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AINODE);
+	/*uint32_t size =*/ Read<uint32_t>(stream);
+
+	*node = new aiNode();
+
+	(*node)->mName = Read<aiString>(stream);
+	(*node)->mTransformation = Read<aiMatrix4x4>(stream);
+	(*node)->mNumChildren = Read<unsigned int>(stream);
+	(*node)->mNumMeshes = Read<unsigned int>(stream);
+
+	if ((*node)->mNumMeshes)
+	{
+		(*node)->mMeshes = new unsigned int[(*node)->mNumMeshes];
+		for (unsigned int i = 0; i < (*node)->mNumMeshes; ++i) {
+			(*node)->mMeshes[i] = Read<unsigned int>(stream);
+		}
+	}
+
+	if ((*node)->mNumChildren)
+	{
+		(*node)->mChildren = new aiNode*[(*node)->mNumChildren];
+		for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) {
+			ReadBinaryNode( stream, &(*node)->mChildren[i] );
+		}
+	}
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIBONE );
+	/*uint32_t size =*/ Read<uint32_t>(stream);
+
+	b->mName = Read<aiString>(stream);
+	b->mNumWeights = Read<unsigned int>(stream);
+	b->mOffsetMatrix = Read<aiMatrix4x4>(stream);
+
+	// for the moment we write dumb min/max values for the bones, too.
+	// maybe I'll add a better, hash-like solution later
+	if (shortened) 
+	{
+		ReadBounds(stream,b->mWeights,b->mNumWeights);
+	} // else write as usual
+	else 
+	{
+		b->mWeights = new aiVertexWeight[b->mNumWeights];
+		ReadArray<aiVertexWeight>(stream,b->mWeights,b->mNumWeights);
+	}
+}
+
+
+void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMESH);
+	/*uint32_t size =*/ Read<uint32_t>(stream);
+
+	mesh->mPrimitiveTypes = Read<unsigned int>(stream);
+	mesh->mNumVertices = Read<unsigned int>(stream);
+	mesh->mNumFaces = Read<unsigned int>(stream);
+	mesh->mNumBones = Read<unsigned int>(stream);
+	mesh->mMaterialIndex = Read<unsigned int>(stream);
+
+	// first of all, write bits for all existent vertex components
+	unsigned int c = Read<unsigned int>(stream);
+
+	if (c & ASSBIN_MESH_HAS_POSITIONS) 
+	{
+		if (shortened) {
+			ReadBounds(stream,mesh->mVertices,mesh->mNumVertices);
+		} // else write as usual
+		else 
+		{
+			mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+			ReadArray<aiVector3D>(stream,mesh->mVertices,mesh->mNumVertices);
+		}
+	}
+	if (c & ASSBIN_MESH_HAS_NORMALS) 
+	{
+		if (shortened) {
+			ReadBounds(stream,mesh->mNormals,mesh->mNumVertices);
+		} // else write as usual
+		else 
+		{
+			mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+			ReadArray<aiVector3D>(stream,mesh->mNormals,mesh->mNumVertices);
+		}
+	}
+	if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) 
+	{
+		if (shortened) {
+			ReadBounds(stream,mesh->mTangents,mesh->mNumVertices);
+			ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices);
+		} // else write as usual
+		else 
+		{
+			mesh->mTangents = new aiVector3D[mesh->mNumVertices];
+			ReadArray<aiVector3D>(stream,mesh->mTangents,mesh->mNumVertices);
+			mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
+			ReadArray<aiVector3D>(stream,mesh->mBitangents,mesh->mNumVertices);
+		}
+	}
+	for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) 
+	{
+		if (!(c & ASSBIN_MESH_HAS_COLOR(n)))
+			break;
+
+		if (shortened) 
+		{
+			ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices);
+		} // else write as usual
+		else 
+		{
+			mesh->mColors[n] = new aiColor4D[mesh->mNumVertices];
+			ReadArray<aiColor4D>(stream,mesh->mColors[n],mesh->mNumVertices);
+		}
+	}
+	for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) 
+	{
+		if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n)))
+			break;
+
+		// write number of UV components
+		mesh->mNumUVComponents[n] = Read<unsigned int>(stream);
+
+		if (shortened) {
+			ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
+		} // else write as usual
+		else 
+		{
+			mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
+			ReadArray<aiVector3D>(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
+		}
+	}
+
+	// write faces. There are no floating-point calculations involved
+	// in these, so we can write a simple hash over the face data
+	// to the dump file. We generate a single 32 Bit hash for 512 faces
+	// using Assimp's standard hashing function.
+	if (shortened) {
+		Read<unsigned int>(stream);
+	}
+	else // else write as usual
+	{
+		// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
+		mesh->mFaces = new aiFace[mesh->mNumFaces];
+		for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
+			aiFace& f = mesh->mFaces[i];
+
+			BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff);
+			f.mNumIndices = Read<uint16_t>(stream);
+			f.mIndices = new unsigned int[f.mNumIndices];
+
+			for (unsigned int a = 0; a < f.mNumIndices;++a) {
+				if (mesh->mNumVertices < (1u<<16)) 
+				{
+					f.mIndices[a] = Read<uint16_t>(stream);
+				}
+				else 
+				{
+					f.mIndices[a] = Read<unsigned int>(stream);
+				}
+			}
+		}
+	}
+
+	// write bones
+	if (mesh->mNumBones) {
+		mesh->mBones = new C_STRUCT aiBone*[mesh->mNumBones];
+		for (unsigned int a = 0; a < mesh->mNumBones;++a) {
+			mesh->mBones[a] = new aiBone();
+			ReadBinaryBone(stream,mesh->mBones[a]);
+		}
+	}
+}
+
+void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop)
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMATERIALPROPERTY);
+	/*uint32_t size =*/ Read<uint32_t>(stream);
+
+	prop->mKey = Read<aiString>(stream);
+	prop->mSemantic = Read<unsigned int>(stream);
+	prop->mIndex = Read<unsigned int>(stream);
+
+	prop->mDataLength = Read<unsigned int>(stream);
+	prop->mType = (aiPropertyTypeInfo)Read<unsigned int>(stream);
+	prop->mData = new char [ prop->mDataLength ];
+	stream->Read(prop->mData,1,prop->mDataLength);
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMATERIAL);
+	/*uint32_t size =*/ Read<uint32_t>(stream);
+
+	mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream);
+	if (mat->mNumProperties)
+	{
+		if (mat->mProperties) 
+		{
+			delete[] mat->mProperties;
+		}
+		mat->mProperties = new aiMaterialProperty*[mat->mNumProperties];
+		for (unsigned int i = 0; i < mat->mNumProperties;++i) {
+			mat->mProperties[i] = new aiMaterialProperty();
+			ReadBinaryMaterialProperty( stream, mat->mProperties[i]);
+		}
+	}
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AINODEANIM);
+	/*uint32_t size =*/ Read<uint32_t>(stream);
+
+	nd->mNodeName = Read<aiString>(stream);
+	nd->mNumPositionKeys = Read<unsigned int>(stream);
+	nd->mNumRotationKeys = Read<unsigned int>(stream);
+	nd->mNumScalingKeys = Read<unsigned int>(stream);
+	nd->mPreState = (aiAnimBehaviour)Read<unsigned int>(stream);
+	nd->mPostState = (aiAnimBehaviour)Read<unsigned int>(stream);
+
+	if (nd->mNumPositionKeys) {
+		if (shortened) {
+			ReadBounds(stream,nd->mPositionKeys,nd->mNumPositionKeys);
+
+		} // else write as usual
+		else {
+			nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
+			ReadArray<aiVectorKey>(stream,nd->mPositionKeys,nd->mNumPositionKeys);
+		}
+	}
+	if (nd->mNumRotationKeys) {
+		if (shortened) {
+			ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys);
+
+		} // else write as usual
+		else 
+		{
+			nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
+			ReadArray<aiQuatKey>(stream,nd->mRotationKeys,nd->mNumRotationKeys);
+		}
+	}
+	if (nd->mNumScalingKeys) {
+		if (shortened) {
+			ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys);
+
+		} // else write as usual
+		else 
+		{
+			nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
+			ReadArray<aiVectorKey>(stream,nd->mScalingKeys,nd->mNumScalingKeys);
+		}
+	}
+}
+
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIANIMATION);
+	/*uint32_t size =*/ Read<uint32_t>(stream);
+
+	anim->mName = Read<aiString> (stream);
+	anim->mDuration = Read<double> (stream);
+	anim->mTicksPerSecond = Read<double> (stream);
+	anim->mNumChannels = Read<unsigned int>(stream);
+
+	if (anim->mNumChannels)
+	{
+		anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ];
+		for (unsigned int a = 0; a < anim->mNumChannels;++a) {
+			anim->mChannels[a] = new aiNodeAnim();
+			ReadBinaryNodeAnim(stream,anim->mChannels[a]);
+		}
+	}
+}
+
+void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AITEXTURE);
+	/*uint32_t size =*/ Read<uint32_t>(stream);
+
+	tex->mWidth = Read<unsigned int>(stream);
+	tex->mHeight = Read<unsigned int>(stream);
+	stream->Read( tex->achFormatHint, sizeof(char), 4 );
+
+	if(!shortened) {
+		if (!tex->mHeight) {
+			tex->pcData = new aiTexel[ tex->mWidth ];
+			stream->Read(tex->pcData,1,tex->mWidth);
+		}
+		else {
+			tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ];
+			stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4);
+		}
+	}
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AILIGHT);
+	/*uint32_t size =*/ Read<uint32_t>(stream);
+
+	l->mName = Read<aiString>(stream);
+	l->mType = (aiLightSourceType)Read<unsigned int>(stream);
+
+	if (l->mType != aiLightSource_DIRECTIONAL) { 
+		l->mAttenuationConstant = Read<float>(stream);
+		l->mAttenuationLinear = Read<float>(stream);
+		l->mAttenuationQuadratic = Read<float>(stream);
+	}
+
+	l->mColorDiffuse = Read<aiColor3D>(stream);
+	l->mColorSpecular = Read<aiColor3D>(stream);
+	l->mColorAmbient = Read<aiColor3D>(stream);
+
+	if (l->mType == aiLightSource_SPOT) {
+		l->mAngleInnerCone = Read<float>(stream);
+		l->mAngleOuterCone = Read<float>(stream);
+	}
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AICAMERA);
+	/*uint32_t size =*/ Read<uint32_t>(stream);
+
+	cam->mName = Read<aiString>(stream);
+	cam->mPosition = Read<aiVector3D>(stream);
+	cam->mLookAt = Read<aiVector3D>(stream);
+	cam->mUp = Read<aiVector3D>(stream);
+	cam->mHorizontalFOV = Read<float>(stream);
+	cam->mClipPlaneNear = Read<float>(stream);
+	cam->mClipPlaneFar = Read<float>(stream);
+	cam->mAspect = Read<float>(stream);
+}
+
+void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AISCENE);
+	/*uint32_t size =*/ Read<uint32_t>(stream);
+
+	scene->mFlags         = Read<unsigned int>(stream);
+	scene->mNumMeshes     = Read<unsigned int>(stream);
+	scene->mNumMaterials  = Read<unsigned int>(stream);
+	scene->mNumAnimations = Read<unsigned int>(stream);
+	scene->mNumTextures   = Read<unsigned int>(stream);
+	scene->mNumLights     = Read<unsigned int>(stream);
+	scene->mNumCameras    = Read<unsigned int>(stream);
+
+	// Read node graph
+	scene->mRootNode = new aiNode[1];
+	ReadBinaryNode( stream, &scene->mRootNode );
+
+	// Read all meshes
+	if (scene->mNumMeshes)
+	{
+		scene->mMeshes = new aiMesh*[scene->mNumMeshes];
+		for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+			scene->mMeshes[i] = new aiMesh();
+			ReadBinaryMesh( stream,scene->mMeshes[i]);
+		}
+	}
+
+	// Read materials
+	if (scene->mNumMaterials)
+	{
+		scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
+		for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
+			scene->mMaterials[i] = new aiMaterial();
+			ReadBinaryMaterial(stream,scene->mMaterials[i]);
+		}
+	}
+
+	// Read all animations
+	if (scene->mNumAnimations)
+	{
+		scene->mAnimations = new aiAnimation*[scene->mNumAnimations];
+		for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
+			scene->mAnimations[i] = new aiAnimation();
+			ReadBinaryAnim(stream,scene->mAnimations[i]);
+		}
+	}
+
+	// Read all textures
+	if (scene->mNumTextures)
+	{
+		scene->mTextures = new aiTexture*[scene->mNumTextures];
+		for (unsigned int i = 0; i < scene->mNumTextures;++i) {
+			scene->mTextures[i] = new aiTexture();
+			ReadBinaryTexture(stream,scene->mTextures[i]);
+		}
+	}
+
+	// Read lights
+	if (scene->mNumLights)
+	{
+		scene->mLights = new aiLight*[scene->mNumLights];
+		for (unsigned int i = 0; i < scene->mNumLights;++i) {
+			scene->mLights[i] = new aiLight();
+			ReadBinaryLight(stream,scene->mLights[i]);
+		}
+	}
+
+	// Read cameras
+	if (scene->mNumCameras)
+	{
+		scene->mCameras = new aiCamera*[scene->mNumCameras];
+		for (unsigned int i = 0; i < scene->mNumCameras;++i) {
+			scene->mCameras[i] = new aiCamera();
+			ReadBinaryCamera(stream,scene->mCameras[i]);
+		}
+	}
+
+}
+
+void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler )
+{
+	IOStream * stream = pIOHandler->Open(pFile,"rb");
+	if (!stream)
+		return;
+
+	stream->Seek( 44, aiOrigin_CUR ); // signature
+
+	/*unsigned int versionMajor =*/ Read<unsigned int>(stream);
+	/*unsigned int versionMinor =*/ Read<unsigned int>(stream);
+	/*unsigned int versionRevision =*/ Read<unsigned int>(stream);
+	/*unsigned int compileFlags =*/ Read<unsigned int>(stream);
+
+	shortened = Read<uint16_t>(stream) > 0;
+	compressed = Read<uint16_t>(stream) > 0;
+
+	if (shortened)
+		throw DeadlyImportError( "Shortened binaries are not supported!" );
+
+	stream->Seek( 256, aiOrigin_CUR ); // original filename
+	stream->Seek( 128, aiOrigin_CUR ); // options
+	stream->Seek( 64, aiOrigin_CUR ); // padding
+
+	if (compressed)
+	{
+		uLongf uncompressedSize = Read<uint32_t>(stream);
+		uLongf compressedSize = stream->FileSize() - stream->Tell();
+
+		unsigned char * compressedData = new unsigned char[ compressedSize ];
+		stream->Read( compressedData, 1, compressedSize );
+
+		unsigned char * uncompressedData = new unsigned char[ uncompressedSize ];
+
+		uncompress( uncompressedData, &uncompressedSize, compressedData, compressedSize );
+
+		MemoryIOStream io( uncompressedData, uncompressedSize );
+
+		ReadBinaryScene(&io,pScene);
+
+		delete[] uncompressedData;
+		delete[] compressedData;
+	}
+	else
+	{
+		ReadBinaryScene(stream,pScene);
+	}
+	
+	pIOHandler->Close(stream);
+}
+
+#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER

+ 94 - 0
code/AssbinLoader.h

@@ -0,0 +1,94 @@
+
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, 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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file  AssbinLoader.h
+ *  @brief .assbin File format loader
+ */
+#ifndef AI_ASSBINIMPORTER_H_INC
+#define AI_ASSBINIMPORTER_H_INC
+
+#include "BaseImporter.h"
+#include "../include/assimp/types.h"
+
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+namespace Assimp	{
+
+// ---------------------------------------------------------------------------------
+/** Importer class for 3D Studio r3 and r4 3DS files
+ */
+class AssbinImporter : public BaseImporter
+{
+private:
+  bool shortened;
+  bool compressed;
+protected:
+
+public:
+  virtual bool CanRead( 
+    const std::string& pFile, 
+    IOSystem* pIOHandler, 
+    bool checkSig
+    ) const;
+  virtual const aiImporterDesc* GetInfo() const;
+  virtual void InternReadFile( 
+    const std::string& pFile, 
+    aiScene* pScene, 
+    IOSystem* pIOHandler
+    );
+  void ReadBinaryScene( IOStream * stream, aiScene* pScene );
+  void ReadBinaryNode( IOStream * stream, aiNode** mRootNode );
+  void ReadBinaryMesh( IOStream * stream, aiMesh* mesh );
+  void ReadBinaryBone( IOStream * stream, aiBone* bone );
+  void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat);
+  void ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop);
+  void ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd);
+  void ReadBinaryAnim( IOStream * stream, aiAnimation* anim );
+  void ReadBinaryTexture(IOStream * stream, aiTexture* tex);
+  void ReadBinaryLight( IOStream * stream, aiLight* l );
+  void ReadBinaryCamera( IOStream * stream, aiCamera* cam );
+};
+
+} // end of namespace Assimp
+
+#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+#endif // AI_ASSBINIMPORTER_H_INC

+ 2 - 2
code/BlenderLoader.cpp

@@ -999,7 +999,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* camera, ConversionData& /*conv_data*/)
+aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* /*camera*/, ConversionData& /*conv_data*/)
 {
 {
 	ScopeGuard<aiCamera> out(new aiCamera());
 	ScopeGuard<aiCamera> out(new aiCamera());
 	out->mName = obj->id.name+2;
 	out->mName = obj->id.name+2;
@@ -1010,7 +1010,7 @@ aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj,
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const Lamp* lamp, ConversionData& conv_data)
+aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/)
 {
 {
 	ScopeGuard<aiLight> out(new aiLight());
 	ScopeGuard<aiLight> out(new aiLight());
 	out->mName = obj->id.name+2;
 	out->mName = obj->id.name+2;

+ 3 - 3
code/BoostWorkaround/boost/tuple/tuple.hpp

@@ -100,7 +100,7 @@ namespace boost	{
 			};
 			};
 
 
 			// dummy
 			// dummy
-			list_elem& operator = (const list_elem& other)	{
+			list_elem& operator = (const list_elem& /*other*/)	{
 				return *this;
 				return *this;
 			}
 			}
 
 
@@ -142,7 +142,7 @@ namespace boost	{
 				return me.me;
 				return me.me;
 			}
 			}
 		};
 		};
-	};
+	}
 
 
 	// A very minimal implementation for up to 5 elements
 	// A very minimal implementation for up to 5 elements
 	template <typename T0  = detail::nulltype,
 	template <typename T0  = detail::nulltype,
@@ -278,6 +278,6 @@ namespace boost	{
 		tuple <> t;
 		tuple <> t;
 		return t;
 		return t;
 	}
 	}
-};
+}
 
 
 #endif // !! BOOST_TUPLE_INCLUDED
 #endif // !! BOOST_TUPLE_INCLUDED

+ 14 - 1
code/CMakeLists.txt

@@ -111,6 +111,7 @@ SET( Common_SRCS
 	MemoryIOWrapper.h
 	MemoryIOWrapper.h
 	ParsingUtils.h
 	ParsingUtils.h
 	StreamReader.h
 	StreamReader.h
+	StreamWriter.h
 	StringComparison.h
 	StringComparison.h
 	SGSpatialSort.cpp
 	SGSpatialSort.cpp
 	SGSpatialSort.h
 	SGSpatialSort.h
@@ -143,6 +144,7 @@ SET( Common_SRCS
 	LogAux.h
 	LogAux.h
 	Bitmap.cpp
 	Bitmap.cpp
 	Bitmap.h
 	Bitmap.h
+	XMLTools.h
 )
 )
 SOURCE_GROUP(Common FILES ${Common_SRCS})
 SOURCE_GROUP(Common FILES ${Common_SRCS})
 
 
@@ -151,6 +153,8 @@ SET( 3DS_SRCS
 	3DSHelper.h
 	3DSHelper.h
 	3DSLoader.cpp
 	3DSLoader.cpp
 	3DSLoader.h
 	3DSLoader.h
+	3DSExporter.h
+	3DSExporter.cpp
 )
 )
 SOURCE_GROUP(3DS FILES ${3DS_SRCS})
 SOURCE_GROUP(3DS FILES ${3DS_SRCS})
 
 
@@ -168,6 +172,14 @@ SET( ASE_SRCS
 )
 )
 SOURCE_GROUP( ASE FILES ${ASE_SRCS})
 SOURCE_GROUP( ASE FILES ${ASE_SRCS})
 
 
+SET( ASSBIN_SRCS
+	AssbinExporter.h
+	AssbinExporter.cpp
+	AssbinLoader.h
+	AssbinLoader.cpp
+)
+SOURCE_GROUP( Assbin FILES ${ASSBIN_SRCS})
+
 SET( B3D_SRCS
 SET( B3D_SRCS
 	B3DImporter.cpp
 	B3DImporter.cpp
 	B3DImporter.h
 	B3DImporter.h
@@ -612,7 +624,7 @@ SOURCE_GROUP( unzip FILES ${unzip_SRCS})
 
 
 # VC2010 fixes
 # VC2010 fixes
 if(MSVC10)
 if(MSVC10)
-	OPTION( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
+	option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
 	if( VC10_STDINT_FIX )
 	if( VC10_STDINT_FIX )
 		ADD_DEFINITIONS( -D_STDINT )
 		ADD_DEFINITIONS( -D_STDINT )
 	endif( VC10_STDINT_FIX )
 	endif( VC10_STDINT_FIX )
@@ -643,6 +655,7 @@ SET( assimp_src
 	${3DS_SRCS}
 	${3DS_SRCS}
 	${AC_SRCS}
 	${AC_SRCS}
 	${ASE_SRCS}
 	${ASE_SRCS}
+	${ASSBIN_SRCS}
 	${B3D_SRCS}
 	${B3D_SRCS}
 	${BVH_SRCS}
 	${BVH_SRCS}
 	${Collada_SRCS}
 	${Collada_SRCS}

+ 3 - 3
code/CalcTangentsProcess.cpp

@@ -115,9 +115,9 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
 	// we assume that the mesh is still in the verbose vertex format where each face has its own set
 	// we assume that the mesh is still in the verbose vertex format where each face has its own set
 	// of vertices and no vertices are shared between faces. Sadly I don't know any quick test to 
 	// of vertices and no vertices are shared between faces. Sadly I don't know any quick test to 
 	// assert() it here.
 	// assert() it here.
-    //assert( must be verbose, dammit);
+    // assert( must be verbose, dammit);
 
 
-	if (pMesh->mTangents) // thisimplies that mBitangents is also there
+	if (pMesh->mTangents) // this implies that mBitangents is also there
 		return false;
 		return false;
 
 
 	// If the mesh consists of lines and/or points but not of
 	// If the mesh consists of lines and/or points but not of
@@ -271,7 +271,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
 		const aiVector3D& origNorm = pMesh->mNormals[a];
 		const aiVector3D& origNorm = pMesh->mNormals[a];
 		const aiVector3D& origTang = pMesh->mTangents[a];
 		const aiVector3D& origTang = pMesh->mTangents[a];
 		const aiVector3D& origBitang = pMesh->mBitangents[a];
 		const aiVector3D& origBitang = pMesh->mBitangents[a];
-		closeVertices.clear();
+		closeVertices.resize( 0 );
 
 
 		// find all vertices close to that position
 		// find all vertices close to that position
 		vertexFinder->FindPositions( origPos, posEpsilon, verticesFound);
 		vertexFinder->FindPositions( origPos, posEpsilon, verticesFound);

+ 39 - 31
code/ColladaExporter.cpp

@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "Bitmap.h"
 #include "Bitmap.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
 #include "SceneCombiner.h" 
 #include "SceneCombiner.h" 
+#include "XMLTools.h"
 
 
 #include <ctime>
 #include <ctime>
 #include <set>
 #include <set>
@@ -93,6 +94,7 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p
 } // end of namespace Assimp
 } // end of namespace Assimp
 
 
 
 
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor for a specific scene to export
 // Constructor for a specific scene to export
 ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file)
 ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file)
@@ -140,7 +142,7 @@ void ColladaExporter::WriteFile()
 	// useless Collada fu at the end, just in case we haven't had enough indirections, yet. 
 	// useless Collada fu at the end, just in case we haven't had enough indirections, yet. 
 	mOutput << startstr << "<scene>" << endstr;
 	mOutput << startstr << "<scene>" << endstr;
 	PushTag();
 	PushTag();
-	mOutput << startstr << "<instance_visual_scene url=\"#" + std::string(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr;
+	mOutput << startstr << "<instance_visual_scene url=\"#" + XMLEscape(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr;
 	PopTag();
 	PopTag();
 	mOutput << startstr << "</scene>" << endstr;
 	mOutput << startstr << "</scene>" << endstr;
 	PopTag();
 	PopTag();
@@ -236,12 +238,12 @@ void ColladaExporter::WriteHeader()
 	if (!meta || !meta->Get("Author", value))		
 	if (!meta || !meta->Get("Author", value))		
 		mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr;
 		mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr;
 	else		
 	else		
-		mOutput << startstr << "<author>" << value.C_Str() << "</author>" << endstr;
+		mOutput << startstr << "<author>" << XMLEscape(value.C_Str()) << "</author>" << endstr;
 
 
 	if (!meta || !meta->Get("AuthoringTool", value))
 	if (!meta || !meta->Get("AuthoringTool", value))
 		mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr;
 		mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr;
 	else		
 	else		
-		mOutput << startstr << "<authoring_tool>" << value.C_Str() << "</authoring_tool>" << endstr;
+		mOutput << startstr << "<authoring_tool>" << XMLEscape(value.C_Str()) << "</authoring_tool>" << endstr;
 
 
 	//mOutput << startstr << "<author>" << mScene->author.C_Str() << "</author>" << endstr;
 	//mOutput << startstr << "<author>" << mScene->author.C_Str() << "</author>" << endstr;
 	//mOutput << startstr << "<authoring_tool>" << mScene->authoringTool.C_Str() << "</authoring_tool>" << endstr;
 	//mOutput << startstr << "<authoring_tool>" << mScene->authoringTool.C_Str() << "</authoring_tool>" << endstr;
@@ -342,16 +344,20 @@ void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::strin
 {
 {
   if( !pSurface.texture.empty() )
   if( !pSurface.texture.empty() )
   {
   {
-    mOutput << startstr << "<image id=\"" << pNameAdd << "\">" << endstr;
+    mOutput << startstr << "<image id=\"" << XMLEscape(pNameAdd) << "\">" << endstr;
     PushTag(); 
     PushTag(); 
     mOutput << startstr << "<init_from>";
     mOutput << startstr << "<init_from>";
+	
+	// URL encode image file name first, then XML encode on top
+	std::stringstream imageUrlEncoded;
     for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it )
     for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it )
     {
     {
       if( isalnum( *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' )
       if( isalnum( *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' )
-        mOutput << *it;
+        imageUrlEncoded << *it;
       else
       else
-        mOutput << '%' << std::hex << size_t( (unsigned char) *it) << std::dec;
+        imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec;
     }
     }
+	mOutput << XMLEscape(imageUrlEncoded.str());
     mOutput << "</init_from>" << endstr;
     mOutput << "</init_from>" << endstr;
     PopTag();
     PopTag();
     mOutput << startstr << "</image>" << endstr;
     mOutput << startstr << "</image>" << endstr;
@@ -371,7 +377,7 @@ void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std
     }
     }
 	else
 	else
     {
     {
-      mOutput << startstr << "<texture texture=\"" << pImageName << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
+      mOutput << startstr << "<texture texture=\"" << XMLEscape(pImageName) << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
     }
     }
     PopTag();
     PopTag();
     mOutput << startstr << "</" << pTypeName << ">" << endstr;
     mOutput << startstr << "</" << pTypeName << ">" << endstr;
@@ -385,21 +391,21 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std
   // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture
   // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture
   if( !pSurface.texture.empty() )
   if( !pSurface.texture.empty() )
   {
   {
-    mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-surface\">" << endstr;
+    mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-surface\">" << endstr;
     PushTag();
     PushTag();
     mOutput << startstr << "<surface type=\"2D\">" << endstr;
     mOutput << startstr << "<surface type=\"2D\">" << endstr;
     PushTag();
     PushTag();
-    mOutput << startstr << "<init_from>" << pMatName << "-" << pTypeName << "-image</init_from>" << endstr;
+    mOutput << startstr << "<init_from>" << XMLEscape(pMatName) << "-" << pTypeName << "-image</init_from>" << endstr;
     PopTag();
     PopTag();
     mOutput << startstr << "</surface>" << endstr;
     mOutput << startstr << "</surface>" << endstr;
     PopTag();
     PopTag();
     mOutput << startstr << "</newparam>" << endstr;
     mOutput << startstr << "</newparam>" << endstr;
 
 
-    mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-sampler\">" << endstr;
+    mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-sampler\">" << endstr;
     PushTag();
     PushTag();
     mOutput << startstr << "<sampler2D>" << endstr;
     mOutput << startstr << "<sampler2D>" << endstr;
     PushTag();
     PushTag();
-    mOutput << startstr << "<source>" << pMatName << "-" << pTypeName << "-surface</source>" << endstr;
+    mOutput << startstr << "<source>" << XMLEscape(pMatName) << "-" << pTypeName << "-surface</source>" << endstr;
     PopTag();
     PopTag();
     mOutput << startstr << "</sampler2D>" << endstr;
     mOutput << startstr << "</sampler2D>" << endstr;
     PopTag();
     PopTag();
@@ -439,7 +445,7 @@ void ColladaExporter::WriteMaterials()
       name = "mat";
       name = "mat";
     materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + name.C_Str();
     materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + name.C_Str();
     for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
     for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
-		// isalnum on MSVC asserts for code points in [0,255]. Thus prevent unwanted promotion
+		// isalnum on MSVC asserts for code points outside [0,255]. Thus prevent unwanted promotion
 		// of char to signed int and take the unsigned char value.
 		// of char to signed int and take the unsigned char value.
       if( !isalnum( static_cast<uint8_t>(*it) ) ) {
       if( !isalnum( static_cast<uint8_t>(*it) ) ) {
         *it = '_';
         *it = '_';
@@ -510,7 +516,7 @@ void ColladaExporter::WriteMaterials()
     {
     {
       const Material& mat = *it;
       const Material& mat = *it;
       // this is so ridiculous it must be right
       // this is so ridiculous it must be right
-      mOutput << startstr << "<effect id=\"" << mat.name << "-fx\" name=\"" << mat.name << "\">" << endstr;
+      mOutput << startstr << "<effect id=\"" << XMLEscape(mat.name) << "-fx\" name=\"" << XMLEscape(mat.name) << "\">" << endstr;
       PushTag();
       PushTag();
       mOutput << startstr << "<profile_COMMON>" << endstr;
       mOutput << startstr << "<profile_COMMON>" << endstr;
       PushTag();
       PushTag();
@@ -561,9 +567,9 @@ void ColladaExporter::WriteMaterials()
     for( std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it )
     for( std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it )
     {
     {
       const Material& mat = *it;
       const Material& mat = *it;
-      mOutput << startstr << "<material id=\"" << mat.name << "\" name=\"" << mat.name << "\">" << endstr;
+      mOutput << startstr << "<material id=\"" << XMLEscape(mat.name) << "\" name=\"" << mat.name << "\">" << endstr;
       PushTag();
       PushTag();
-      mOutput << startstr << "<instance_effect url=\"#" << mat.name << "-fx\"/>" << endstr;
+      mOutput << startstr << "<instance_effect url=\"#" << XMLEscape(mat.name) << "-fx\"/>" << endstr;
       PopTag();
       PopTag();
       mOutput << startstr << "</material>" << endstr;
       mOutput << startstr << "</material>" << endstr;
     }
     }
@@ -591,13 +597,14 @@ void ColladaExporter::WriteGeometryLibrary()
 void ColladaExporter::WriteGeometry( size_t pIndex)
 void ColladaExporter::WriteGeometry( size_t pIndex)
 {
 {
 	const aiMesh* mesh = mScene->mMeshes[pIndex];
 	const aiMesh* mesh = mScene->mMeshes[pIndex];
-	std::string idstr = GetMeshId( pIndex);
+	const std::string idstr = GetMeshId( pIndex);
+	const std::string idstrEscaped = XMLEscape(idstr);
 
 
   if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
   if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
     return;
     return;
 
 
 	// opening tag
 	// opening tag
-	mOutput << startstr << "<geometry id=\"" << idstr << "\" name=\"" << idstr << "_name\" >" << endstr;
+	mOutput << startstr << "<geometry id=\"" << idstrEscaped << "\" name=\"" << idstrEscaped << "_name\" >" << endstr;
 	PushTag();
 	PushTag();
 
 
 	mOutput << startstr << "<mesh>" << endstr;
 	mOutput << startstr << "<mesh>" << endstr;
@@ -627,20 +634,20 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
 	}
 	}
 
 
 	// assemble vertex structure
 	// assemble vertex structure
-	mOutput << startstr << "<vertices id=\"" << idstr << "-vertices" << "\">" << endstr;
+	mOutput << startstr << "<vertices id=\"" << idstrEscaped << "-vertices" << "\">" << endstr;
 	PushTag();
 	PushTag();
-	mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstr << "-positions\" />" << endstr;
+	mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstrEscaped << "-positions\" />" << endstr;
 	if( mesh->HasNormals() )
 	if( mesh->HasNormals() )
-		mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << idstr << "-normals\" />" << endstr;
+		mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << idstrEscaped << "-normals\" />" << endstr;
 	for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
 	for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
 	{
 	{
 		if( mesh->HasTextureCoords( a) )
 		if( mesh->HasTextureCoords( a) )
-			mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << idstr << "-tex" << a << "\" " /*<< "set=\"" << a << "\"" */ << " />" << endstr;
+			mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << idstrEscaped << "-tex" << a << "\" " /*<< "set=\"" << a << "\"" */ << " />" << endstr;
 	}
 	}
 	for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
 	for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
 	{
 	{
 		if( mesh->HasVertexColors( a) )
 		if( mesh->HasVertexColors( a) )
-			mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstr << "-color" << a << "\" " /*<< set=\"" << a << "\"" */ << " />" << endstr;
+			mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstrEscaped << "-color" << a << "\" " /*<< set=\"" << a << "\"" */ << " />" << endstr;
 	}
 	}
 	
 	
 	PopTag();
 	PopTag();
@@ -660,7 +667,7 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
 	{
 	{
 		mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr;
 		mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr;
 		PushTag();
 		PushTag();
-		mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstr << "-vertices\" />" << endstr;
+		mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
 		mOutput << startstr << "<p>";
 		mOutput << startstr << "<p>";
 		for( size_t a = 0; a < mesh->mNumFaces; ++a )
 		for( size_t a = 0; a < mesh->mNumFaces; ++a )
 		{
 		{
@@ -681,7 +688,7 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
 	{		
 	{		
 		mOutput << startstr << "<polylist count=\"" << countPoly << "\" material=\"defaultMaterial\">" << endstr;
 		mOutput << startstr << "<polylist count=\"" << countPoly << "\" material=\"defaultMaterial\">" << endstr;
 		PushTag();
 		PushTag();
-		mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstr << "-vertices\" />" << endstr;
+		mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
 	
 	
 		mOutput << startstr << "<vcount>";
 		mOutput << startstr << "<vcount>";
 		for( size_t a = 0; a < mesh->mNumFaces; ++a )
 		for( size_t a = 0; a < mesh->mNumFaces; ++a )
@@ -728,11 +735,11 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
 
 
 	std::string arrayId = pIdString + "-array";
 	std::string arrayId = pIdString + "-array";
 
 
-	mOutput << startstr << "<source id=\"" << pIdString << "\" name=\"" << pIdString << "\">" << endstr;
+	mOutput << startstr << "<source id=\"" << XMLEscape(pIdString) << "\" name=\"" << XMLEscape(pIdString) << "\">" << endstr;
 	PushTag();
 	PushTag();
 
 
 	// source array
 	// source array
-	mOutput << startstr << "<float_array id=\"" << arrayId << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
+	mOutput << startstr << "<float_array id=\"" << XMLEscape(arrayId) << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
 	PushTag();
 	PushTag();
 
 
 	if( pType == FloatType_TexCoord2 )
 	if( pType == FloatType_TexCoord2 )
@@ -804,11 +811,11 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
 // Writes the scene library
 // Writes the scene library
 void ColladaExporter::WriteSceneLibrary()
 void ColladaExporter::WriteSceneLibrary()
 {
 {
-	std::string scene_name = mScene->mRootNode->mName.C_Str();
+	const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str());
 
 
 	mOutput << startstr << "<library_visual_scenes>" << endstr;
 	mOutput << startstr << "<library_visual_scenes>" << endstr;
 	PushTag();
 	PushTag();
-	mOutput << startstr << "<visual_scene id=\"" + scene_name + "\" name=\"" + scene_name + "\">" << endstr;
+	mOutput << startstr << "<visual_scene id=\"" + scene_name_escaped + "\" name=\"" + scene_name_escaped + "\">" << endstr;
 	PushTag();
 	PushTag();
 
 
 	// start recursive write at the root node
 	// start recursive write at the root node
@@ -833,7 +840,8 @@ void ColladaExporter::WriteNode(aiNode* pNode)
 		pNode->mName.Set(ss.str());
 		pNode->mName.Set(ss.str());
 	}
 	}
 
 
-	mOutput << startstr << "<node id=\"" << pNode->mName.data << "\" name=\"" << pNode->mName.data << "\">" << endstr;
+	const std::string node_name_escaped = XMLEscape(pNode->mName.data);
+	mOutput << startstr << "<node id=\"" << node_name_escaped << "\" name=\"" << node_name_escaped << "\">" << endstr;
 	PushTag();
 	PushTag();
 
 
 	// write transformation - we can directly put the matrix there
 	// write transformation - we can directly put the matrix there
@@ -854,13 +862,13 @@ void ColladaExporter::WriteNode(aiNode* pNode)
 	if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
 	if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
 		continue;
 		continue;
 
 
-		mOutput << startstr << "<instance_geometry url=\"#" << GetMeshId( pNode->mMeshes[a]) << "\">" << endstr;
+		mOutput << startstr << "<instance_geometry url=\"#" << XMLEscape(GetMeshId( pNode->mMeshes[a])) << "\">" << endstr;
 		PushTag();
 		PushTag();
 	mOutput << startstr << "<bind_material>" << endstr;
 	mOutput << startstr << "<bind_material>" << endstr;
 	PushTag();
 	PushTag();
 	mOutput << startstr << "<technique_common>" << endstr;
 	mOutput << startstr << "<technique_common>" << endstr;
 	PushTag();
 	PushTag();
-	mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << materials[mesh->mMaterialIndex].name << "\" />" << endstr;
+	mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << XMLEscape(materials[mesh->mMaterialIndex].name) << "\" />" << endstr;
 		PopTag();
 		PopTag();
 	mOutput << startstr << "</technique_common>" << endstr;
 	mOutput << startstr << "</technique_common>" << endstr;
 	PopTag();
 	PopTag();

+ 19 - 9
code/ConvertToLHProcess.cpp

@@ -57,12 +57,15 @@ using namespace Assimp;
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 MakeLeftHandedProcess::MakeLeftHandedProcess()
 MakeLeftHandedProcess::MakeLeftHandedProcess()
-{}
+: BaseProcess() {
+    // empty
+}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-MakeLeftHandedProcess::~MakeLeftHandedProcess()
-{}
+MakeLeftHandedProcess::~MakeLeftHandedProcess() {
+    // empty
+}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the processing step is present in the given flag field.
 // Returns whether the processing step is present in the given flag field.
@@ -121,8 +124,9 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare
 	pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
 	pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
 
 
 	// continue for all children
 	// continue for all children
-	for( size_t a = 0; a < pNode->mNumChildren; ++a)
-		ProcessNode( pNode->mChildren[a], pParentGlobalRotation * pNode->mTransformation);
+    for( size_t a = 0; a < pNode->mNumChildren; ++a ) {
+        ProcessNode( pNode->mChildren[ a ], pParentGlobalRotation * pNode->mTransformation );
+    }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -244,6 +248,10 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
 	aiMaterial* mat = (aiMaterial*)_mat;
 	aiMaterial* mat = (aiMaterial*)_mat;
 	for (unsigned int a = 0; a < mat->mNumProperties;++a)	{
 	for (unsigned int a = 0; a < mat->mNumProperties;++a)	{
 		aiMaterialProperty* prop = mat->mProperties[a];
 		aiMaterialProperty* prop = mat->mProperties[a];
+        if( !prop ) {
+            DefaultLogger::get()->debug( "Property is null" );
+            continue;
+        }
 
 
 		// UV transformation key?
 		// UV transformation key?
 		if (!::strcmp( prop->mKey.data, "$tex.uvtrafo"))	{
 		if (!::strcmp( prop->mKey.data, "$tex.uvtrafo"))	{
@@ -263,11 +271,13 @@ void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
 {
 {
 	// mirror texture y coordinate
 	// mirror texture y coordinate
 	for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)	{
 	for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)	{
-		if( !pMesh->HasTextureCoords( a))
-			break;
+        if( !pMesh->HasTextureCoords( a ) ) {
+            break;
+        }
 
 
-		for( unsigned int b = 0; b < pMesh->mNumVertices; b++)
-			pMesh->mTextureCoords[a][b].y = 1.0f - pMesh->mTextureCoords[a][b].y;
+        for( unsigned int b = 0; b < pMesh->mNumVertices; b++ ) {
+            pMesh->mTextureCoords[ a ][ b ].y = 1.0f - pMesh->mTextureCoords[ a ][ b ].y;
+        }
 	}
 	}
 }
 }
 
 

+ 2 - 2
code/DeboneProcess.cpp

@@ -111,8 +111,8 @@ void DeboneProcess::Execute( aiScene* pScene)
 
 
 	if(numSplits)	{
 	if(numSplits)	{
 		// we need to do something. Let's go.
 		// we need to do something. Let's go.
-		mSubMeshIndices.clear();
-		mSubMeshIndices.resize(pScene->mNumMeshes);
+		//mSubMeshIndices.clear();                  // really needed?
+		mSubMeshIndices.resize(pScene->mNumMeshes); // because we're doing it here anyway
 
 
 		// build a new array of meshes for the scene
 		// build a new array of meshes for the scene
 		std::vector<aiMesh*> meshes;
 		std::vector<aiMesh*> meshes;

+ 11 - 5
code/Exporter.cpp

@@ -78,7 +78,8 @@ void ExportSceneObj(const char*,IOSystem*, const aiScene*);
 void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
 void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
 void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
 void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
 void ExportScenePly(const char*,IOSystem*, const aiScene*);
 void ExportScenePly(const char*,IOSystem*, const aiScene*);
-void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
+void ExportScene3DS(const char*, IOSystem*, const aiScene*);
+void ExportSceneAssbin(const char*, IOSystem*, const aiScene*);
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // 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
@@ -90,7 +91,7 @@ Exporter::ExportFormatEntry gExporters[] =
 
 
 #ifndef ASSIMP_BUILD_NO_FXILE_EXPORTER
 #ifndef ASSIMP_BUILD_NO_FXILE_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
 
 
 #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
 #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
@@ -113,9 +114,14 @@ Exporter::ExportFormatEntry gExporters[] =
 	),
 	),
 #endif
 #endif
 
 
-//#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
-//	ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS),
-//#endif
+#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
+	Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
+		aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+	Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0),
+#endif
 };
 };
 
 
 #define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
 #define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))

+ 1 - 1
code/FBXAnimation.cpp

@@ -59,7 +59,7 @@ namespace FBX {
 	using namespace Util;
 	using namespace Util;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc)
+AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
 : Object(id, element, name)
 : Object(id, element, name)
 {
 {
 	const Scope& sc = GetRequiredScope(element);
 	const Scope& sc = GetRequiredScope(element);

+ 6 - 6
code/FBXConverter.cpp

@@ -1319,7 +1319,7 @@ private:
 
 
 
 
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
-	void ConvertCluster(std::vector<aiBone*>& bones, const Model& model, const Cluster& cl, 		
+	void ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
 		std::vector<size_t>& out_indices,
 		std::vector<size_t>& out_indices,
 		std::vector<size_t>& index_out_indices,
 		std::vector<size_t>& index_out_indices,
 		std::vector<size_t>& count_out_indices,
 		std::vector<size_t>& count_out_indices,
@@ -2347,7 +2347,7 @@ private:
 
 
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
 	aiNodeAnim* GenerateScalingNodeAnim(const std::string& name, 
 	aiNodeAnim* GenerateScalingNodeAnim(const std::string& name, 
-		const Model& target, 
+		const Model& /*target*/,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const LayerMap& layer_map,
 		const LayerMap& layer_map,
 		double& max_time,
 		double& max_time,
@@ -2378,7 +2378,7 @@ private:
 
 
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
 	aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name, 
 	aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name, 
-		const Model& target, 
+		const Model& /*target*/,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const LayerMap& layer_map,
 		const LayerMap& layer_map,
 		double& max_time,
 		double& max_time,
@@ -2830,7 +2830,7 @@ private:
 
 
 
 
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
-	void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& layers,
+	void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
 		double& maxTime,
 		double& maxTime,
 		double& minTime)
 		double& minTime)
 	{
 	{
@@ -2851,7 +2851,7 @@ private:
 
 
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
 	void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, 
 	void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, 
-		const LayerMap& layers,
+		const LayerMap& /*layers*/,
 		double& maxTime,
 		double& maxTime,
 		double& minTime)
 		double& minTime)
 	{
 	{
@@ -2869,7 +2869,7 @@ private:
 
 
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
 	void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, 
 	void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, 
-		const LayerMap& layers, 
+		const LayerMap& /*layers*/,
 		double& maxTime,
 		double& maxTime,
 		double& minTime,
 		double& minTime,
 		Model::RotOrder order)
 		Model::RotOrder order)

+ 10 - 5
code/FBXDocument.cpp

@@ -253,8 +253,8 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
 : settings(settings)
 : settings(settings)
 , parser(parser)
 , parser(parser)
 {
 {
-	// cannot use array default initialization syntax because vc8 fails on it
-	for (unsigned int i = 0; i < 7; ++i) {
+	// Cannot use array default initialization syntax because vc8 fails on it
+	for (unsigned int i = 0; i < sizeof(creationTimeStamp) / sizeof(creationTimeStamp[0]); ++i) {
 		creationTimeStamp[i] = 0;
 		creationTimeStamp[i] = 0;
 	}
 	}
 
 
@@ -263,7 +263,7 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
 
 
 	ReadGlobalSettings();
 	ReadGlobalSettings();
 
 
-	// this order is important, connections need parsed objects to check
+	// This order is important, connections need parsed objects to check
 	// whether connections are ok or not. Objects may not be evaluated yet,
 	// whether connections are ok or not. Objects may not be evaluated yet,
 	// though, since this may require valid connections.
 	// though, since this may require valid connections.
 	ReadObjects();
 	ReadObjects();
@@ -277,13 +277,18 @@ Document::~Document()
 	BOOST_FOREACH(ObjectMap::value_type& v, objects) {
 	BOOST_FOREACH(ObjectMap::value_type& v, objects) {
 		delete v.second;
 		delete v.second;
 	}
 	}
+
+	BOOST_FOREACH(ConnectionMap::value_type& v, src_connections) {
+		delete v.second;
+	}
+	// |dest_connections| contain the same Connection objects as the |src_connections|
 }
 }
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Document::ReadHeader()
 void Document::ReadHeader()
 {
 {
-	// read ID objects from "Objects" section
+	// Read ID objects from "Objects" section
 	const Scope& sc = parser.GetRootScope();
 	const Scope& sc = parser.GetRootScope();
 	const Element* const ehead = sc["FBXHeaderExtension"];
 	const Element* const ehead = sc["FBXHeaderExtension"];
 	if(!ehead || !ehead->Compound()) {
 	if(!ehead || !ehead->Compound()) {
@@ -293,7 +298,7 @@ void Document::ReadHeader()
 	const Scope& shead = *ehead->Compound();
 	const Scope& shead = *ehead->Compound();
 	fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
 	fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
 
 
-	// while we maye have some success with newer files, we don't support
+	// While we maye have some success with newer files, we don't support
 	// the older 6.n fbx format
 	// the older 6.n fbx format
 	if(fbxVersion < 7100) {
 	if(fbxVersion < 7100) {
 		DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013");
 		DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013");

+ 2 - 2
code/FBXDocument.h

@@ -696,7 +696,7 @@ public:
 public:
 public:
 
 
 	/** Get the Skin attached to this geometry or NULL */
 	/** Get the Skin attached to this geometry or NULL */
-	const Skin* const DeformerSkin() const {
+	const Skin* DeformerSkin() const {
 		return skin;
 		return skin;
 	}
 	}
 
 
@@ -1096,7 +1096,7 @@ public:
 		return transformLink;
 		return transformLink;
 	}
 	}
 
 
-	const Model* const TargetNode() const {
+	const Model* TargetNode() const {
 		return node;
 		return node;
 	}
 	}
 
 

+ 2 - 0
code/FBXImporter.cpp

@@ -179,6 +179,8 @@ void FBXImporter::InternReadFile( const std::string& pFile,
 
 
 		// convert the FBX DOM to aiScene
 		// convert the FBX DOM to aiScene
 		ConvertToAssimpScene(pScene,doc);
 		ConvertToAssimpScene(pScene,doc);
+
+		std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
 	}
 	}
 	catch(std::exception&) {
 	catch(std::exception&) {
 		std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
 		std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());

+ 1 - 1
code/FBXMaterial.cpp

@@ -207,7 +207,7 @@ Texture::~Texture()
 
 
 }
 }
 
 
-LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name)
 : Object(id,element,name)
 : Object(id,element,name)
 ,texture(0)
 ,texture(0)
 ,blendMode(BlendMode_Modulate)
 ,blendMode(BlendMode_Modulate)

+ 4 - 2
code/FBXMeshGeometry.cpp

@@ -466,8 +466,9 @@ void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out,
 	const std::string& MappingInformationType,
 	const std::string& MappingInformationType,
 	const std::string& ReferenceInformationType)
 	const std::string& ReferenceInformationType)
 {
 {
+	const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
 	ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
 	ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
-		"Tangent",
+		str,
 		"TangentIndex",
 		"TangentIndex",
 		vertices.size(),
 		vertices.size(),
 		mapping_counts,
 		mapping_counts,
@@ -481,8 +482,9 @@ void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_ou
 	const std::string& MappingInformationType,
 	const std::string& MappingInformationType,
 	const std::string& ReferenceInformationType)
 	const std::string& ReferenceInformationType)
 {
 {
+	const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal";
 	ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
 	ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
-		"Binormal",
+		str,
 		"BinormalIndex",
 		"BinormalIndex",
 		vertices.size(),
 		vertices.size(),
 		mapping_counts,
 		mapping_counts,

+ 24 - 34
code/FBXParser.cpp

@@ -93,7 +93,7 @@ namespace {
 	}
 	}
 
 
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
-	void ParseWarning(const std::string& message, const Element* element = NULL)
+/*	void ParseWarning(const std::string& message, const Element* element = NULL)
 	{
 	{
 		if(element) {
 		if(element) {
 			ParseWarning(message,element->KeyToken());
 			ParseWarning(message,element->KeyToken());
@@ -103,7 +103,7 @@ namespace {
 			DefaultLogger::get()->warn("FBX-Parser: " + message);
 			DefaultLogger::get()->warn("FBX-Parser: " + message);
 		}
 		}
 	}
 	}
-
+*/
 	// ------------------------------------------------------------------------------------------------
 	// ------------------------------------------------------------------------------------------------
 	void ParseError(const std::string& message, TokenPtr token)
 	void ParseError(const std::string& message, TokenPtr token)
 	{
 	{
@@ -113,6 +113,18 @@ namespace {
 		ParseError(message);
 		ParseError(message);
 	}
 	}
 
 
+	// Initially, we did reinterpret_cast, breaking strict aliasing rules.
+	// This actually caused trouble on Android, so let's be safe this time.
+	// https://github.com/assimp/assimp/issues/24
+	template <typename T>
+	T SafeParse(const char* data, const char* end) {
+		// Actual size validation happens during Tokenization so
+		// this is valid as an assertion.
+		ai_assert(static_cast<size_t>(end - data) >= sizeof(T));
+		T result = static_cast<T>(0);
+		::memcpy(&result, data, sizeof(T));
+		return result;
+	}
 }
 }
 
 
 namespace Assimp {
 namespace Assimp {
@@ -275,9 +287,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
 			return 0L;
 			return 0L;
 		}
 		}
 
 
-		ai_assert(t.end() - data == 9);
-
-		BE_NCONST uint64_t id = *reinterpret_cast<const uint64_t*>(data+1);
+		BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
 		AI_SWAP8(id);
 		AI_SWAP8(id);
 		return id;
 		return id;
 	}
 	}
@@ -316,8 +326,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
 			return 0;
 			return 0;
 		}
 		}
 
 
-		ai_assert(t.end() - data == 9);
-		BE_NCONST uint64_t id = *reinterpret_cast<const uint64_t*>(data+1);
+		BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
 		AI_SWAP8(id);
 		AI_SWAP8(id);
 		return static_cast<size_t>(id);
 		return static_cast<size_t>(id);
 	}
 	}
@@ -364,24 +373,10 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
 		}
 		}
 
 
 		if (data[0] == 'F') {
 		if (data[0] == 'F') {
-			// Actual size validation happens during Tokenization so
-			// this is valid as an assertion.
-			ai_assert(t.end() - data == sizeof(float) + 1);
-			// Initially, we did reinterpret_cast, breaking strict aliasing rules.
-			// This actually caused trouble on Android, so let's be safe this time.
-			// https://github.com/assimp/assimp/issues/24
-			
-			float out_float;
-			::memcpy(&out_float, data+1, sizeof(float));
-			return out_float;
+			return SafeParse<float>(data+1, t.end());
 		}
 		}
 		else {
 		else {
-			ai_assert(t.end() - data == sizeof(double) + 1);
-			
-			// Same
-			double out_double;
-			::memcpy(&out_double, data+1, sizeof(double));
-			return static_cast<float>(out_double);
+			return SafeParse<double>(data+1, t.end());
 		}
 		}
 	}
 	}
 
 
@@ -416,8 +411,7 @@ int ParseTokenAsInt(const Token& t, const char*& err_out)
 			return 0;
 			return 0;
 		}
 		}
 
 
-		ai_assert(t.end() - data == 5);
-		BE_NCONST int32_t ival = *reinterpret_cast<const int32_t*>(data+1);
+		BE_NCONST int32_t ival = SafeParse<int32_t>(data+1, t.end());
 		AI_SWAP4(ival);
 		AI_SWAP4(ival);
 		return static_cast<int>(ival);
 		return static_cast<int>(ival);
 	}
 	}
@@ -453,10 +447,8 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
 			return "";
 			return "";
 		}
 		}
 
 
-		ai_assert(t.end() - data >= 5);
-
 		// read string length
 		// read string length
-		BE_NCONST int32_t len = *reinterpret_cast<const int32_t*>(data+1);
+		BE_NCONST int32_t len = SafeParse<int32_t>(data+1, t.end());
 		AI_SWAP4(len);
 		AI_SWAP4(len);
 
 
 		ai_assert(t.end() - data == 5 + len);
 		ai_assert(t.end() - data == 5 + len);
@@ -494,7 +486,7 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
 	type = *data;
 	type = *data;
 
 
 	// read number of elements
 	// read number of elements
-	BE_NCONST uint32_t len = *reinterpret_cast<const uint32_t*>(data+1);
+	BE_NCONST uint32_t len = SafeParse<uint32_t>(data+1, end);
 	AI_SWAP4(len);
 	AI_SWAP4(len);
 
 
 	count = len;
 	count = len;
@@ -506,16 +498,14 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
 // read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
 // read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
 void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end, 
 void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end, 
 	std::vector<char>& buff, 
 	std::vector<char>& buff, 
-	const Element& el)
+	const Element& /*el*/)
 {
 {
-	ai_assert(static_cast<size_t>(end-data) >= 4); // runtime check for this happens at tokenization stage
-
-	BE_NCONST uint32_t encmode = *reinterpret_cast<const uint32_t*>(data);
+	BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end);
 	AI_SWAP4(encmode);
 	AI_SWAP4(encmode);
 	data += 4;
 	data += 4;
 
 
 	// next comes the compressed length
 	// next comes the compressed length
-	BE_NCONST uint32_t comp_len = *reinterpret_cast<const uint32_t*>(data);
+	BE_NCONST uint32_t comp_len = SafeParse<uint32_t>(data, end);
 	AI_SWAP4(comp_len);
 	AI_SWAP4(comp_len);
 	data += 4;
 	data += 4;
 
 

+ 1 - 1
code/FBXProperties.cpp

@@ -105,7 +105,7 @@ Property* ReadTypedProperty(const Element& element)
 			ParseTokenAsFloat(*tok[6]))
 			ParseTokenAsFloat(*tok[6]))
 		);
 		);
 	}
 	}
-	else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"KTime") || !strcmp(cs,"Float")) {
+	else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"KTime") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView")) {
 		return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
 		return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
 	}
 	}
 	return NULL;
 	return NULL;

+ 2 - 4
code/FBXProperties.h

@@ -143,8 +143,7 @@ private:
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename T>
 template <typename T>
 inline T PropertyGet(const PropertyTable& in, const std::string& name, 
 inline T PropertyGet(const PropertyTable& in, const std::string& name, 
-	const T& defaultValue, 
-	bool ignoreTemplate = false)
+	const T& defaultValue)
 {
 {
 	const Property* const prop = in.Get(name);
 	const Property* const prop = in.Get(name);
 	if(!prop) {
 	if(!prop) {
@@ -164,8 +163,7 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name,
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename T>
 template <typename T>
 inline T PropertyGet(const PropertyTable& in, const std::string& name, 
 inline T PropertyGet(const PropertyTable& in, const std::string& name, 
-	bool& result, 
-	bool ignoreTemplate = false)
+	bool& result)
 {
 {
 	const Property* const prop = in.Get(name);
 	const Property* const prop = in.Get(name);
 	if(!prop) {
 	if(!prop) {

+ 1 - 2
code/FindInstancesProcess.cpp

@@ -174,7 +174,6 @@ void FindInstancesProcess::Execute( aiScene* pScene)
 
 
 					// use a constant epsilon for colors and UV coordinates
 					// use a constant epsilon for colors and UV coordinates
 					static const float uvEpsilon = 10e-4f;
 					static const float uvEpsilon = 10e-4f;
-
 					{
 					{
 						unsigned int i, end = orig->GetNumUVChannels();
 						unsigned int i, end = orig->GetNumUVChannels();
 						for(i = 0; i < end; ++i) {
 						for(i = 0; i < end; ++i) {
@@ -260,7 +259,7 @@ void FindInstancesProcess::Execute( aiScene* pScene)
 					pScene->mMeshes[real++] = pScene->mMeshes[i];
 					pScene->mMeshes[real++] = pScene->mMeshes[i];
 			}
 			}
 
 
-			// And update the nodegraph with our nice lookup table
+			// And update the node graph with our nice lookup table
 			UpdateMeshIndices(pScene->mRootNode,remapping.get());
 			UpdateMeshIndices(pScene->mRootNode,remapping.get());
 
 
 			// write to log
 			// write to log

+ 1 - 1
code/GenVertexNormalsProcess.cpp

@@ -93,7 +93,7 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene)
 	bool bHas = false;
 	bool bHas = false;
 	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
 	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
 	{
 	{
-		if(GenMeshVertexNormals( pScene->mMeshes[a],a))
+        if(GenMeshVertexNormals( pScene->mMeshes[a],a))
 			bHas = true;
 			bHas = true;
 	}
 	}
 
 

+ 1 - 1
code/GenVertexNormalsProcess.h

@@ -53,7 +53,7 @@ namespace Assimp {
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** The GenFaceNormalsProcess computes vertex normals for all vertizes
 /** The GenFaceNormalsProcess computes vertex normals for all vertizes
 */
 */
-class ASSIMP_API_WINONLY GenVertexNormalsProcess : public BaseProcess
+class ASSIMP_API GenVertexNormalsProcess : public BaseProcess
 {
 {
 public:
 public:
 
 

+ 1 - 1
code/IFCBoolean.cpp

@@ -85,7 +85,7 @@ Intersect IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const I
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result, 
 void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result, 
 									   const TempMesh& first_operand, 
 									   const TempMesh& first_operand, 
-									   ConversionData& conv)
+									   ConversionData& /*conv*/)
 {
 {
 	ai_assert(hs != NULL);
 	ai_assert(hs != NULL);
 
 

+ 2 - 2
code/IFCOpenings.cpp

@@ -259,7 +259,7 @@ BoundingBox GetBoundingBox(const ClipperLib::Polygon& poly)
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void InsertWindowContours(const ContourVector& contours,
 void InsertWindowContours(const ContourVector& contours,
-	const std::vector<TempOpening>& openings,
+	const std::vector<TempOpening>& /*openings*/,
 	TempMesh& curmesh)
 	TempMesh& curmesh)
 {
 {
 	// fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now
 	// fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now
@@ -1741,4 +1741,4 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
 #undef from_int64
 #undef from_int64
 #undef one_vec
 #undef one_vec
 
 
-#endif 
+#endif 

+ 1 - 1
code/IFCProfile.cpp

@@ -101,7 +101,7 @@ void ProcessOpenProfile(const IfcArbitraryOpenProfileDef& def, TempMesh& meshout
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv)
+void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& /*conv*/)
 {
 {
 	if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) {
 	if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) {
 		const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
 		const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;

+ 3 - 3
code/IFCReaderGen.cpp

@@ -1045,7 +1045,7 @@ void IFC::GetSchema(EXPRESS::ConversionSchema& out)
 namespace STEP {
 namespace STEP {
 
 
 // -----------------------------------------------------------------------------------------------------------
 // -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
+template <> size_t GenericFill<NotImplemented>(const STEP::DB& /*db*/, const LIST& /*params*/, NotImplemented* /*in*/)
 {
 {
 	return 0;
 	return 0;
 }
 }
@@ -1253,7 +1253,7 @@ template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST&
 	return base;
 	return base;
 }
 }
 // -----------------------------------------------------------------------------------------------------------
 // -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRepresentationItem>(const DB& db, const LIST& params, IfcRepresentationItem* in)
+template <> size_t GenericFill<IfcRepresentationItem>(const DB& /*db*/, const LIST& /*params*/, IfcRepresentationItem* /*in*/)
 {
 {
 	size_t base = 0;
 	size_t base = 0;
 	return base;
 	return base;
@@ -1715,7 +1715,7 @@ template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, I
 	return base;
 	return base;
 }
 }
 // -----------------------------------------------------------------------------------------------------------
 // -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcObjectPlacement>(const DB& db, const LIST& params, IfcObjectPlacement* in)
+template <> size_t GenericFill<IfcObjectPlacement>(const DB& /*db*/, const LIST& /*params*/, IfcObjectPlacement* /*in*/)
 {
 {
 	size_t base = 0;
 	size_t base = 0;
 	return base;
 	return base;

+ 13 - 4
code/Importer.cpp

@@ -640,16 +640,25 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
 			}
 			}
 		}
 		}
 
 
+		// Get file size for progress handler
+		IOStream * fileIO = pimpl->mIOHandler->Open( pFile );
+		uint32_t fileSize = 0;
+		if (fileIO)
+		{
+			fileSize = fileIO->FileSize();
+			pimpl->mIOHandler->Close( fileIO );
+		}
+
 		// Dispatch the reading to the worker class for this format
 		// Dispatch the reading to the worker class for this format
 		DefaultLogger::get()->info("Found a matching importer for this file format");
 		DefaultLogger::get()->info("Found a matching importer for this file format");
-		pimpl->mProgressHandler->Update();
+		pimpl->mProgressHandler->UpdateFileRead( 0, fileSize );
 
 
 		if (profiler) {
 		if (profiler) {
 			profiler->BeginRegion("import");
 			profiler->BeginRegion("import");
 		}
 		}
 
 
 		pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
 		pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
-		pimpl->mProgressHandler->Update();
+		pimpl->mProgressHandler->UpdateFileRead( fileSize, fileSize );
 
 
 		if (profiler) {
 		if (profiler) {
 			profiler->EndRegion("import");
 			profiler->EndRegion("import");
@@ -678,7 +687,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
 			ScenePreprocessor pre(pimpl->mScene);
 			ScenePreprocessor pre(pimpl->mScene);
 			pre.ProcessScene();
 			pre.ProcessScene();
 
 
-			pimpl->mProgressHandler->Update();
 			if (profiler) {
 			if (profiler) {
 				profiler->EndRegion("preprocess");
 				profiler->EndRegion("preprocess");
 			}
 			}
@@ -768,6 +776,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
 	for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)	{
 	for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)	{
 
 
 		BaseProcess* process = pimpl->mPostProcessingSteps[a];
 		BaseProcess* process = pimpl->mPostProcessingSteps[a];
+		pimpl->mProgressHandler->UpdatePostProcess( a, pimpl->mPostProcessingSteps.size() );
 		if( process->IsActive( pFlags))	{
 		if( process->IsActive( pFlags))	{
 
 
 			if (profiler) {
 			if (profiler) {
@@ -775,7 +784,6 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
 			}
 			}
 
 
 			process->ExecuteOnScene	( this );
 			process->ExecuteOnScene	( this );
-			pimpl->mProgressHandler->Update();
 
 
 			if (profiler) {
 			if (profiler) {
 				profiler->EndRegion("postprocess");
 				profiler->EndRegion("postprocess");
@@ -803,6 +811,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
 		}
 		}
 #endif // ! DEBUG
 #endif // ! DEBUG
 	}
 	}
+	pimpl->mProgressHandler->UpdatePostProcess( pimpl->mPostProcessingSteps.size(), pimpl->mPostProcessingSteps.size() );
 
 
 	// update private scene flags
 	// update private scene flags
   if( pimpl->mScene )
   if( pimpl->mScene )

+ 6 - 0
code/ImporterRegistry.cpp

@@ -166,6 +166,9 @@ corresponding preprocessor flag to selectively disable formats.
 #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 #   include "FBXImporter.h"
 #   include "FBXImporter.h"
 #endif 
 #endif 
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+#   include "AssbinLoader.h"
+#endif 
 
 
 namespace Assimp {
 namespace Assimp {
 
 
@@ -291,6 +294,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
 #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 )
+	out.push_back( new AssbinImporter() );
+#endif
 }
 }
 
 
 }
 }

+ 1 - 1
code/JoinVerticesProcess.h

@@ -59,7 +59,7 @@ class JoinVerticesTest;
  * erases all but one of the copies. This usually reduces the number of vertices
  * erases all but one of the copies. This usually reduces the number of vertices
  * in a mesh by a serious amount and is the standard form to render a mesh.
  * in a mesh by a serious amount and is the standard form to render a mesh.
  */
  */
-class ASSIMP_API_WINONLY JoinVerticesProcess : public BaseProcess
+class ASSIMP_API JoinVerticesProcess : public BaseProcess
 {
 {
 public:
 public:
 
 

+ 10 - 17
code/LimitBoneWeightsProcess.cpp

@@ -131,10 +131,15 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
 
 
 		// and renormalize the weights
 		// and renormalize the weights
 		float sum = 0.0f;
 		float sum = 0.0f;
-		for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it)
-			sum += it->mWeight;
-		for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it)
-			it->mWeight /= sum;
+        for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it ) {
+            sum += it->mWeight;
+        }
+        if( 0.0f != sum ) {
+            const float invSum = 1.0f / sum;
+            for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it ) {
+                it->mWeight *= invSum;
+            }
+        }
 	}
 	}
 
 
 	if (bChanged)	{
 	if (bChanged)	{
@@ -157,18 +162,6 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
 			const std::vector<aiVertexWeight>& bw = boneWeights[a];
 			const std::vector<aiVertexWeight>& bw = boneWeights[a];
 			aiBone* bone = pMesh->mBones[a];
 			aiBone* bone = pMesh->mBones[a];
 
 
-			// ignore the bone if no vertex weights were removed there
-
-			// FIX (Aramis, 07|22|08)
-			// NO! we can't ignore it in this case ... it is possible that
-			// the number of weights did not change, but the weight values did.
-
-			// if( bw.size() == bone->mNumWeights)
-			//	continue;
-
-			// FIX (Aramis, 07|21|08)
-			// It is possible that all weights of a bone have been removed.
-			// This would naturally cause an exception in &bw[0].
 			if ( bw.empty() )
 			if ( bw.empty() )
 			{
 			{
 				abNoNeed[a] = bChanged = true;
 				abNoNeed[a] = bChanged = true;
@@ -177,7 +170,7 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
 
 
 			// copy the weight list. should always be less weights than before, so we don't need a new allocation
 			// copy the weight list. should always be less weights than before, so we don't need a new allocation
 			ai_assert( bw.size() <= bone->mNumWeights);
 			ai_assert( bw.size() <= bone->mNumWeights);
-			bone->mNumWeights = (unsigned int) bw.size();
+			bone->mNumWeights = static_cast<unsigned int>( bw.size() );
 			::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
 			::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
 		}
 		}
 
 

+ 20 - 14
code/ObjExporter.cpp

@@ -75,6 +75,7 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp
 
 
+static const std::string MaterialExt = ".mtl";
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
 ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
@@ -107,7 +108,7 @@ std::string ObjExporter :: GetMaterialLibName()
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 std::string ObjExporter :: GetMaterialLibFileName()
 std::string ObjExporter :: GetMaterialLibFileName()
 {	
 {	
-	return filename + ".mtl";
+    return filename + MaterialExt;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -132,7 +133,7 @@ std::string ObjExporter :: GetMaterialName(unsigned int index)
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void ObjExporter :: WriteMaterialFile()
+void ObjExporter::WriteMaterialFile()
 {
 {
 	WriteHeader(mOutputMat);
 	WriteHeader(mOutputMat);
 
 
@@ -144,16 +145,16 @@ void ObjExporter :: WriteMaterialFile()
 
 
 		aiColor4D c;
 		aiColor4D c;
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE,c)) {
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE,c)) {
-			mOutputMat << "kd " << c.r << " " << c.g << " " << c.b << endl;
+			mOutputMat << "Kd " << c.r << " " << c.g << " " << c.b << endl;
 		}
 		}
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT,c)) {
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT,c)) {
-			mOutputMat << "ka " << c.r << " " << c.g << " " << c.b << endl;
+			mOutputMat << "Ka " << c.r << " " << c.g << " " << c.b << endl;
 		}
 		}
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR,c)) {
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR,c)) {
-			mOutputMat << "ks " << c.r << " " << c.g << " " << c.b << endl;
+			mOutputMat << "Ks " << c.r << " " << c.g << " " << c.b << endl;
 		}
 		}
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) {
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) {
-			mOutputMat << "ke " << c.r << " " << c.g << " " << c.b << endl;
+			mOutputMat << "Ke " << c.r << " " << c.g << " " << c.b << endl;
 		}
 		}
 
 
 		float o;
 		float o;
@@ -170,16 +171,19 @@ void ObjExporter :: WriteMaterialFile()
 
 
 		aiString s;
 		aiString s;
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_DIFFUSE(0),s)) {
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_DIFFUSE(0),s)) {
-			mOutputMat << "map_kd " << s.data << endl;
+			mOutputMat << "map_Kd " << s.data << endl;
 		}
 		}
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_AMBIENT(0),s)) {
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_AMBIENT(0),s)) {
-			mOutputMat << "map_ka " << s.data << endl;
+			mOutputMat << "map_Ka " << s.data << endl;
 		}
 		}
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SPECULAR(0),s)) {
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SPECULAR(0),s)) {
-			mOutputMat << "map_ks " << s.data << endl;
+			mOutputMat << "map_Ks " << s.data << endl;
 		}
 		}
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SHININESS(0),s)) {
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SHININESS(0),s)) {
-			mOutputMat << "map_ns " << s.data << endl;
+			mOutputMat << "map_Ns " << s.data << endl;
+		}
+		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_OPACITY(0),s)) {
+			mOutputMat << "map_d " << s.data << endl;
 		}
 		}
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_HEIGHT(0),s) || AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_NORMALS(0),s)) {
 		if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_HEIGHT(0),s) || AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_NORMALS(0),s)) {
 			// implementations seem to vary here, so write both variants
 			// implementations seem to vary here, so write both variants
@@ -281,7 +285,7 @@ void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
+void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
 {
 {
 	meshes.push_back(MeshInstance());
 	meshes.push_back(MeshInstance());
 	MeshInstance& mesh = meshes.back();
 	MeshInstance& mesh = meshes.back();
@@ -332,7 +336,7 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void ObjExporter :: AddNode(const aiNode* nd, const aiMatrix4x4& mParent)
+void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent)
 {
 {
 	const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
 	const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
 
 
@@ -345,5 +349,7 @@ void ObjExporter :: AddNode(const aiNode* nd, const aiMatrix4x4& mParent)
 	}
 	}
 }
 }
 
 
-#endif
-#endif
+// ------------------------------------------------------------------------------------------------
+
+#endif // ASSIMP_BUILD_NO_OBJ_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT

+ 11 - 11
code/ObjFileMtlImporter.cpp

@@ -54,6 +54,7 @@ static const std::string DiffuseTexture      = "map_kd";
 static const std::string AmbientTexture      = "map_ka";
 static const std::string AmbientTexture      = "map_ka";
 static const std::string SpecularTexture     = "map_ks";
 static const std::string SpecularTexture     = "map_ks";
 static const std::string OpacityTexture      = "map_d";
 static const std::string OpacityTexture      = "map_d";
+static const std::string EmmissiveTexture    = "map_emissive";
 static const std::string BumpTexture1        = "map_bump";
 static const std::string BumpTexture1        = "map_bump";
 static const std::string BumpTexture2        = "map_Bump";
 static const std::string BumpTexture2        = "map_Bump";
 static const std::string BumpTexture3        = "bump";
 static const std::string BumpTexture3        = "bump";
@@ -128,6 +129,7 @@ void ObjFileMtlImporter::load()
 	{
 	{
 		switch (*m_DataIt)
 		switch (*m_DataIt)
 		{
 		{
+		case 'k':
 		case 'K':
 		case 'K':
 			{
 			{
 				++m_DataIt;
 				++m_DataIt;
@@ -221,15 +223,17 @@ void ObjFileMtlImporter::getColorRGBA( aiColor3D *pColor )
 {
 {
 	ai_assert( NULL != pColor );
 	ai_assert( NULL != pColor );
 	
 	
-	float r, g, b;
+	float r( 0.0f ), g( 0.0f ), b( 0.0f );
 	m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r );
 	m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r );
 	pColor->r = r;
 	pColor->r = r;
 	
 	
-	m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g );
-	pColor->g = g;
-
-	m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b );
-	pColor->b = b;
+    // we have to check if color is default 0 with only one token
+    if( !isNewLine( *m_DataIt ) ) {
+        m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g );
+        m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b );
+    }
+    pColor->g = g;
+    pColor->b = b;
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
@@ -303,11 +307,7 @@ void ObjFileMtlImporter::getTexture() {
 		// Opacity texture
 		// Opacity texture
 		out = & m_pModel->m_pCurrentMaterial->textureOpacity;
 		out = & m_pModel->m_pCurrentMaterial->textureOpacity;
 		clampIndex = ObjFile::Material::TextureOpacityType;
 		clampIndex = ObjFile::Material::TextureOpacityType;
-	} else if (!ASSIMP_strincmp( pPtr,"map_ka",6)) {
-		// Ambient texture
-		out = & m_pModel->m_pCurrentMaterial->textureAmbient;
-		clampIndex = ObjFile::Material::TextureAmbientType;
-	} else if (!ASSIMP_strincmp(&(*m_DataIt),"map_emissive",6)) {
+	} else if (!ASSIMP_strincmp( pPtr, EmmissiveTexture.c_str(), EmmissiveTexture.size())) {
 		// Emissive texture
 		// Emissive texture
 		out = & m_pModel->m_pCurrentMaterial->textureEmissive;
 		out = & m_pModel->m_pCurrentMaterial->textureEmissive;
 		clampIndex = ObjFile::Material::TextureEmissiveType;
 		clampIndex = ObjFile::Material::TextureEmissiveType;

+ 28 - 21
code/ObjFileParser.cpp

@@ -113,8 +113,8 @@ void ObjFileParser::parseFile()
 					getVector3(m_pModel->m_Vertices);
 					getVector3(m_pModel->m_Vertices);
 				} else if (*m_DataIt == 't') {
 				} else if (*m_DataIt == 't') {
 					// read in texture coordinate ( 2D or 3D )
 					// read in texture coordinate ( 2D or 3D )
-                    ++m_DataIt;
-                    getVector( m_pModel->m_TextureCoord );
+                                        ++m_DataIt;
+                                        getVector( m_pModel->m_TextureCoord );
 				} else if (*m_DataIt == 'n') {
 				} else if (*m_DataIt == 'n') {
 					// Read in normal vector definition
 					// Read in normal vector definition
 					++m_DataIt;
 					++m_DataIt;
@@ -233,12 +233,13 @@ void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
 void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
     size_t numComponents( 0 );
     size_t numComponents( 0 );
-    DataArrayIt tmp( m_DataIt );
+    const char* tmp( &m_DataIt[0] );
     while( !IsLineEnd( *tmp ) ) {
     while( !IsLineEnd( *tmp ) ) {
-        if( *tmp == ' ' ) {
-            ++numComponents;
+        if ( !SkipSpaces( &tmp ) ) {
+            break;
         }
         }
-        tmp++;
+        SkipToken( tmp );
+        ++numComponents;
     }
     }
     float x, y, z;
     float x, y, z;
     if( 2 == numComponents ) {
     if( 2 == numComponents ) {
@@ -550,13 +551,15 @@ void ObjFileParser::getNewMaterial()
 {
 {
 	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
 	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
 	m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
 	m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
-	if ( m_DataIt == m_DataItEnd )
-		return;
+    if( m_DataIt == m_DataItEnd ) {
+        return;
+    }
 
 
 	char *pStart = &(*m_DataIt);
 	char *pStart = &(*m_DataIt);
 	std::string strMat( pStart, *m_DataIt );
 	std::string strMat( pStart, *m_DataIt );
-	while ( m_DataIt != m_DataItEnd && isSeparator( *m_DataIt ) )
-		m_DataIt++;
+    while( m_DataIt != m_DataItEnd && isSeparator( *m_DataIt ) ) {
+        ++m_DataIt;
+    }
 	std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
 	std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
 	if ( it == m_pModel->m_MaterialMap.end() )
 	if ( it == m_pModel->m_MaterialMap.end() )
 	{
 	{
@@ -581,8 +584,9 @@ void ObjFileParser::getNewMaterial()
 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() )
-		return mat_index;
+    if( strMaterialName.empty() ) {
+        return mat_index;
+    }
 	for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
 	for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
 	{
 	{
 		if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
 		if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
@@ -601,8 +605,9 @@ 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 ) )
-		return;
+    if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) {
+        return;
+    }
 
 
 	// Change active group, if necessary
 	// Change active group, if necessary
 	if ( m_pModel->m_strActiveGroup != strGroupName )
 	if ( m_pModel->m_strActiveGroup != strGroupName )
@@ -653,11 +658,13 @@ void ObjFileParser::getGroupNumberAndResolution()
 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)
-		return;
+    if( m_DataIt == m_DataItEnd ) {
+        return;
+    }
 	char *pStart = &(*m_DataIt);
 	char *pStart = &(*m_DataIt);
-	while ( m_DataIt != m_DataItEnd && !isSeparator( *m_DataIt ) )
-		++m_DataIt;
+    while( m_DataIt != m_DataItEnd && !isSeparator( *m_DataIt ) ) {
+        ++m_DataIt;
+    }
 
 
 	std::string strObjectName(pStart, &(*m_DataIt));
 	std::string strObjectName(pStart, &(*m_DataIt));
 	if (!strObjectName.empty()) 
 	if (!strObjectName.empty()) 
@@ -678,8 +685,9 @@ void ObjFileParser::getObjectName()
 		}
 		}
 
 
 		// Allocate a new object, if current one was not found before
 		// Allocate a new object, if current one was not found before
-		if ( NULL == m_pModel->m_pCurrent )
-			createObject(strObjectName);
+        if( NULL == m_pModel->m_pCurrent ) {
+            createObject( strObjectName );
+        }
 	}
 	}
 	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
@@ -694,7 +702,6 @@ void ObjFileParser::createObject(const std::string &strObjectName)
 	m_pModel->m_pCurrent->m_strObjName = strObjectName;
 	m_pModel->m_pCurrent->m_strObjName = strObjectName;
 	m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
 	m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
 	
 	
-
 	createMesh();
 	createMesh();
 
 
 	if( m_pModel->m_pCurrentMaterial )
 	if( m_pModel->m_pCurrentMaterial )

+ 1 - 1
code/ObjTools.h

@@ -259,4 +259,4 @@ unsigned int tokenize( const string_type& str, std::vector<string_type>& tokens,
 
 
 } // Namespace Assimp
 } // Namespace Assimp
 
 
-#endif
+#endif // OBJ_TOOLS_H_INC

+ 5 - 6
code/OgreBinarySerializer.cpp

@@ -376,14 +376,14 @@ void OgreBinarySerializer::ReadMeshSkeletonLink(Mesh *mesh)
 	mesh->skeletonRef = ReadLine();
 	mesh->skeletonRef = ReadLine();
 }
 }
 
 
-void OgreBinarySerializer::ReadMeshBounds(Mesh *mesh)
+void OgreBinarySerializer::ReadMeshBounds(Mesh * /*mesh*/)
 {
 {
 	// Skip bounds, not compatible with Assimp.
 	// Skip bounds, not compatible with Assimp.
 	// 2x float vec3 + 1x float sphere radius
 	// 2x float vec3 + 1x float sphere radius
 	SkipBytes(sizeof(float) * 7);
 	SkipBytes(sizeof(float) * 7);
 }
 }
 
 
-void OgreBinarySerializer::ReadMeshExtremes(Mesh *mesh)
+void OgreBinarySerializer::ReadMeshExtremes(Mesh * /*mesh*/)
 {
 {
 	// Skip extremes, not compatible with Assimp.
 	// Skip extremes, not compatible with Assimp.
 	size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE; 
 	size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE; 
@@ -534,7 +534,6 @@ void OgreBinarySerializer::ReadSubMeshTextureAlias(SubMesh *submesh)
 void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh)
 void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh)
 {
 {
 	uint16_t id = 0;
 	uint16_t id = 0;
-	uint16_t submeshIndex = 0;
 
 
 	if (!AtEnd())
 	if (!AtEnd())
 	{
 	{
@@ -644,7 +643,7 @@ void OgreBinarySerializer::ReadGeometryVertexBuffer(VertexData *dest)
 	DefaultLogger::get()->debug(Formatter::format() << "    - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes");
 	DefaultLogger::get()->debug(Formatter::format() << "    - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes");
 }
 }
 
 
-void OgreBinarySerializer::ReadEdgeList(Mesh *mesh)
+void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/)
 {
 {
 	// Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
 	// Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
 
 
@@ -1055,7 +1054,7 @@ void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton)
 	DefaultLogger::get()->debug(Formatter::format() << "    " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");	
 	DefaultLogger::get()->debug(Formatter::format() << "    " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");	
 }
 }
 
 
-void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest)
+void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton * /*skeleton*/, Animation *dest)
 {
 {
 	uint16_t boneId = Read<uint16_t>();
 	uint16_t boneId = Read<uint16_t>();
 	Bone *bone = dest->parentSkeleton->BoneById(boneId);
 	Bone *bone = dest->parentSkeleton->BoneById(boneId);
@@ -1097,7 +1096,7 @@ void OgreBinarySerializer::ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *d
 	dest->transformKeyFrames.push_back(keyframe);
 	dest->transformKeyFrames.push_back(keyframe);
 }
 }
 
 
-void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton *skeleton)
+void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton * /*skeleton*/)
 {
 {
 	// Skip bounds, not compatible with Assimp.
 	// Skip bounds, not compatible with Assimp.
 	ReadLine(); // skeleton name
 	ReadLine(); // skeleton name

+ 6 - 2
code/OgreBinarySerializer.h

@@ -75,8 +75,8 @@ private:
 	};
 	};
 	
 	
 	OgreBinarySerializer(MemoryStreamReader *reader, AssetMode mode) :
 	OgreBinarySerializer(MemoryStreamReader *reader, AssetMode mode) :
-		m_reader(reader),
 		m_currentLen(0),
 		m_currentLen(0),
+		m_reader(reader),
 		assetMode(mode)
 		assetMode(mode)
 	{
 	{
 	}
 	}
@@ -301,11 +301,12 @@ enum MeshChunkId
 						// unsigned short poseIndex 
 						// unsigned short poseIndex 
 						// float influence
 						// float influence
 		// Optional submesh extreme vertex list chink
 		// Optional submesh extreme vertex list chink
-		M_TABLE_EXTREMES = 0xE000,
+		M_TABLE_EXTREMES = 0xE000
 		// unsigned short submesh_index;
 		// unsigned short submesh_index;
 		// float extremes [n_extremes][3];
 		// float extremes [n_extremes][3];
 };
 };
 
 
+/*
 static std::string MeshHeaderToString(MeshChunkId id)
 static std::string MeshHeaderToString(MeshChunkId id)
 {
 {
 	switch(id)
 	switch(id)
@@ -347,6 +348,7 @@ static std::string MeshHeaderToString(MeshChunkId id)
 	}
 	}
 	return "Unknown_MeshChunkId";
 	return "Unknown_MeshChunkId";
 }
 }
+*/
 
 
 enum SkeletonChunkId
 enum SkeletonChunkId
 {
 {
@@ -393,6 +395,7 @@ enum SkeletonChunkId
 		// float scale							: scale to apply to trans/scale keys
 		// float scale							: scale to apply to trans/scale keys
 };
 };
 
 
+/*
 static std::string SkeletonHeaderToString(SkeletonChunkId id)
 static std::string SkeletonHeaderToString(SkeletonChunkId id)
 {
 {
 	switch(id)
 	switch(id)
@@ -409,6 +412,7 @@ static std::string SkeletonHeaderToString(SkeletonChunkId id)
 	}
 	}
 	return "Unknown_SkeletonChunkId";
 	return "Unknown_SkeletonChunkId";
 }
 }
+*/
 } // Ogre
 } // Ogre
 } // Assimp
 } // Assimp
 
 

+ 13 - 11
code/OgreStructs.cpp

@@ -404,9 +404,9 @@ size_t IndexData::FaceSize() const
 // Mesh
 // Mesh
 
 
 Mesh::Mesh() :
 Mesh::Mesh() :
-	sharedVertexData(0),
-	skeleton(0),
-	hasSkeletalAnimations(false)
+	hasSkeletalAnimations(false),
+	skeleton(NULL),
+	sharedVertexData(NULL)
 {
 {
 }
 }
 
 
@@ -712,8 +712,8 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
 // MeshXml
 // MeshXml
 
 
 MeshXml::MeshXml() :
 MeshXml::MeshXml() :
-	sharedVertexData(0),
-	skeleton(0)
+	skeleton(0),
+	sharedVertexData(0)
 {
 {
 }
 }
 
 
@@ -797,8 +797,8 @@ void MeshXml::ConvertToAssimpScene(aiScene* dest)
 // SubMeshXml
 // SubMeshXml
 
 
 SubMeshXml::SubMeshXml() :
 SubMeshXml::SubMeshXml() :
-	vertexData(0),
-	indexData(new IndexDataXml())
+	indexData(new IndexDataXml()),
+	vertexData(0)
 {
 {
 }
 }
 
 
@@ -912,8 +912,8 @@ aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent)
 // Animation
 // Animation
 
 
 Animation::Animation(Skeleton *parent) :
 Animation::Animation(Skeleton *parent) :
+	parentMesh(NULL),
 	parentSkeleton(parent),
 	parentSkeleton(parent),
-	parentMesh(0),
 	length(0.0f),
 	length(0.0f),
 	baseTime(-1.0f)
 	baseTime(-1.0f)
 {
 {
@@ -963,6 +963,8 @@ aiAnimation *Animation::ConvertToAssimpAnimation()
 // Skeleton
 // Skeleton
 
 
 Skeleton::Skeleton() :
 Skeleton::Skeleton() :
+	bones(),
+	animations(),
 	blendMode(ANIMBLEND_AVERAGE)
 	blendMode(ANIMBLEND_AVERAGE)
 {
 {
 }
 }
@@ -1103,7 +1105,7 @@ aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode)
 	return node;
 	return node;
 }
 }
 
 
-aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights)
+aiBone *Bone::ConvertToAssimpBone(Skeleton * /*parent*/, const std::vector<aiVertexWeight> &boneWeights)
 {
 {
 	aiBone *bone = new aiBone();
 	aiBone *bone = new aiBone();
 	bone->mName = name;
 	bone->mName = name;
@@ -1122,8 +1124,8 @@ aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWe
 // VertexAnimationTrack
 // VertexAnimationTrack
 
 
 VertexAnimationTrack::VertexAnimationTrack() :
 VertexAnimationTrack::VertexAnimationTrack() :
-	target(0),
-	type(VAT_NONE)
+	type(VAT_NONE),
+	target(0)
 {
 {
 }
 }
 
 

+ 59 - 26
code/ParsingUtils.h

@@ -46,16 +46,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_PARSING_UTILS_H_INC
 #define AI_PARSING_UTILS_H_INC
 
 
 #include "StringComparison.h"
 #include "StringComparison.h"
+
 namespace Assimp {
 namespace Assimp {
 
 
-	// NOTE: the functions below are mostly intended as replacement for
-	// std::upper, std::lower, std::isupper, std::islower, std::isspace.
-	// we don't bother of locales. We don't want them. We want reliable
-	// (i.e. identical) results across all locales.
+// NOTE: the functions below are mostly intended as replacement for
+// std::upper, std::lower, std::isupper, std::islower, std::isspace.
+// we don't bother of locales. We don't want them. We want reliable
+// (i.e. identical) results across all locales.
+
+// The functions below accept any character type, but know only
+// about ASCII. However, UTF-32 is the only safe ASCII superset to
+// use since it doesn't have multi-byte sequences.
 
 
-	// The functions below accept any character type, but know only
-	// about ASCII. However, UTF-32 is the only safe ASCII superset to
-	// use since it doesn't have multibyte sequences.
+static const unsigned int BufferSize = 4096;
 
 
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
@@ -63,118 +66,145 @@ AI_FORCE_INLINE char_t ToLower( char_t in)
 {
 {
 	return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
 	return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
-AI_FORCE_INLINE char_t ToUpper( char_t in)
-{
-	return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
+AI_FORCE_INLINE char_t ToUpper( char_t in) {
+    return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool IsUpper( char_t in)
 AI_FORCE_INLINE bool IsUpper( char_t in)
 {
 {
 	return (in >= (char_t)'A' && in <= (char_t)'Z');
 	return (in >= (char_t)'A' && in <= (char_t)'Z');
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool IsLower( char_t in)
 AI_FORCE_INLINE bool IsLower( char_t in)
 {
 {
 	return (in >= (char_t)'a' && in <= (char_t)'z');
 	return (in >= (char_t)'a' && in <= (char_t)'z');
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool IsSpace( char_t in)
 AI_FORCE_INLINE bool IsSpace( char_t in)
 {
 {
 	return (in == (char_t)' ' || in == (char_t)'\t');
 	return (in == (char_t)' ' || in == (char_t)'\t');
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool IsLineEnd( char_t in)
 AI_FORCE_INLINE bool IsLineEnd( char_t in)
 {
 {
 	return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0');
 	return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0');
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in)
 AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in)
 {
 {
 	return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
 	return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out)
 AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out)
 {
 {
-	while (*in == (char_t)' ' || *in == (char_t)'\t')in++;
+    while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) {
+        ++in;
+    }
 	*out = in;
 	*out = in;
 	return !IsLineEnd<char_t>(*in);
 	return !IsLineEnd<char_t>(*in);
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool SkipSpaces( const char_t** inout)
 AI_FORCE_INLINE bool SkipSpaces( const char_t** inout)
 {
 {
 	return SkipSpaces<char_t>(*inout,inout);
 	return SkipSpaces<char_t>(*inout,inout);
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out)
 AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out)
 {
 {
-	while (*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0')in++;
+    while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) {
+        ++in;
+    }
 
 
 	// files are opened in binary mode. Ergo there are both NL and CR
 	// files are opened in binary mode. Ergo there are both NL and CR
-	while (*in == (char_t)'\r' || *in == (char_t)'\n')in++;
+    while( *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
+        ++in;
+    }
 	*out = in;
 	*out = in;
 	return *in != (char_t)'\0';
 	return *in != (char_t)'\0';
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool SkipLine( const char_t** inout)
 AI_FORCE_INLINE bool SkipLine( const char_t** inout)
 {
 {
 	return SkipLine<char_t>(*inout,inout);
 	return SkipLine<char_t>(*inout,inout);
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
 AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
 {
 {
-	while (*in == (char_t)' ' || *in == (char_t)'\t' ||
-		*in == (char_t)'\r' || *in == (char_t)'\n')in++;
+    while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
+        ++in;
+    }
 	*out = in;
 	*out = in;
 	return *in != '\0';
 	return *in != '\0';
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout)
 AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout)
 {
 {
 	return SkipSpacesAndLineEnd<char_t>(*inout,inout);
 	return SkipSpacesAndLineEnd<char_t>(*inout,inout);
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
-AI_FORCE_INLINE bool GetNextLine(const char_t*& buffer, char_t out[4096])
+AI_FORCE_INLINE bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] )
 {
 {
-	if ((char_t)'\0' == *buffer)return false;
+    if( ( char_t )'\0' == *buffer ) {
+        return false;
+    }
 
 
 	char* _out = out;
 	char* _out = out;
-	char* const end = _out+4096;
-	while (!IsLineEnd( *buffer ) && _out < end)
-		*_out++ = *buffer++;
+    char* const end = _out + BufferSize;
+    while( !IsLineEnd( *buffer ) && _out < end ) {
+        *_out++ = *buffer++;
+    }
 	*_out = (char_t)'\0';
 	*_out = (char_t)'\0';
 
 
-	while (IsLineEnd( *buffer ) && '\0' != *buffer)++buffer;
-	return true;
+    while( IsLineEnd( *buffer ) && '\0' != *buffer ) {
+        ++buffer;
+    }
+
+    return true;
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool IsNumeric( char_t in)
 AI_FORCE_INLINE bool IsNumeric( char_t in)
 {
 {
 	return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in;
 	return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in;
 }
 }
+
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 template <class char_t>
 template <class char_t>
 AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len)
 AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len)
 {
 {
-	if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len]))
-	{
+	if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
 		in += len+1;
 		in += len+1;
 		return true;
 		return true;
 	}
 	}
+
 	return false;
 	return false;
 }
 }
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
@@ -185,8 +215,7 @@ AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len
  */
  */
 AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len)
 AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len)
 {
 {
-	if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len]))
-	{
+	if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
 		in += len+1;
 		in += len+1;
 		return true;
 		return true;
 	}
 	}
@@ -206,5 +235,9 @@ AI_FORCE_INLINE std::string GetNextToken(const char*& in)
 	while (!IsSpaceOrNewLine(*in))++in;
 	while (!IsSpaceOrNewLine(*in))++in;
 	return std::string(cur,(size_t)(in-cur));
 	return std::string(cur,(size_t)(in-cur));
 }
 }
+
+// ---------------------------------------------------------------------------------
+
 } // ! namespace Assimp
 } // ! namespace Assimp
+
 #endif // ! AI_PARSING_UTILS_H_INC
 #endif // ! AI_PARSING_UTILS_H_INC

+ 2 - 0
code/Q3BSPFileImporter.cpp

@@ -73,11 +73,13 @@ static const aiImporterDesc desc = {
 
 
 namespace Assimp {
 namespace Assimp {
 
 
+/*
 static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) {
 static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) {
     supportedExtensions.push_back( ".jpg" );
     supportedExtensions.push_back( ".jpg" );
     supportedExtensions.push_back( ".png" );
     supportedExtensions.push_back( ".png" );
     supportedExtensions.push_back( ".tga" );
     supportedExtensions.push_back( ".tga" );
 }
 }
+*/
     
     
 using namespace Q3BSP;
 using namespace Q3BSP;
 
 

+ 5 - 5
code/Q3BSPZipArchive.cpp

@@ -68,25 +68,25 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
 	return (voidpf) io_system->Open(filename, mode_fopen);
 	return (voidpf) io_system->Open(filename, mode_fopen);
 }
 }
 
 
-uLong IOSystem2Unzip::read(voidpf opaque, voidpf stream, void* buf, uLong size) {
+uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
 	IOStream* io_stream = (IOStream*) stream;
 	IOStream* io_stream = (IOStream*) stream;
 
 
 	return io_stream->Read(buf, 1, size);
 	return io_stream->Read(buf, 1, size);
 }
 }
 
 
-uLong IOSystem2Unzip::write(voidpf opaque, voidpf stream, const void* buf, uLong size) {
+uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) {
 	IOStream* io_stream = (IOStream*) stream;
 	IOStream* io_stream = (IOStream*) stream;
 
 
 	return io_stream->Write(buf, 1, size);
 	return io_stream->Write(buf, 1, size);
 }
 }
 
 
-long IOSystem2Unzip::tell(voidpf opaque, voidpf stream) {
+long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
 	IOStream* io_stream = (IOStream*) stream;
 	IOStream* io_stream = (IOStream*) stream;
 
 
 	return io_stream->Tell();
 	return io_stream->Tell();
 }
 }
 
 
-long IOSystem2Unzip::seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
+long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
 	IOStream* io_stream = (IOStream*) stream;
 	IOStream* io_stream = (IOStream*) stream;
 
 
 	aiOrigin assimp_origin;
 	aiOrigin assimp_origin;
@@ -115,7 +115,7 @@ int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
 	return 0;
 	return 0;
 }
 }
 
 
-int IOSystem2Unzip::testerror(voidpf opaque, voidpf stream) {
+int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
 	return 0;
 	return 0;
 }
 }
 
 

+ 2 - 2
code/STLLoader.cpp

@@ -348,8 +348,8 @@ bool STLImporter::LoadBinaryFile()
 	bool bIsMaterialise = false;
 	bool bIsMaterialise = false;
 
 
 	// search for an occurence of "COLOR=" in the header
 	// search for an occurence of "COLOR=" in the header
-	const char* sz2 = (const char*)mBuffer;
-	const char* const szEnd = sz2+80;
+	const unsigned char* sz2 = (const unsigned char*)mBuffer;
+	const unsigned char* const szEnd = sz2+80;
 	while (sz2 < szEnd)	{
 	while (sz2 < szEnd)	{
 
 
 		if ('C' == *sz2++ && 'O' == *sz2++ && 'L' == *sz2++ &&
 		if ('C' == *sz2++ && 'O' == *sz2++ && 'L' == *sz2++ &&

+ 235 - 0
code/StreamWriter.h

@@ -0,0 +1,235 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, 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.
+---------------------------------------------------------------------------
+*/
+
+/** @file Defines the StreamWriter class which writes data to
+ *  a binary stream with a well-defined endianess. */
+
+#ifndef AI_STREAMWRITER_H_INCLUDED
+#define AI_STREAMWRITER_H_INCLUDED
+
+#include "ByteSwap.h"
+
+namespace Assimp {
+
+// --------------------------------------------------------------------------------------------
+/** Wrapper class around IOStream to allow for consistent writing of binary data in both 
+ *  little and big endian format. Don't attempt to instance the template directly. Use 
+ *  StreamWriterLE to read from a little-endian stream and StreamWriterBE to read from a 
+ *  BE stream. Alternatively, there is StreamWriterAny if the endianess of the output
+ *  stream is to be determined at runtime.
+ */
+// --------------------------------------------------------------------------------------------
+template <bool SwapEndianess = false, bool RuntimeSwitch = false>
+class StreamWriter
+{
+	enum {
+		INITIAL_CAPACITY = 1024
+	};
+
+public:
+
+	// ---------------------------------------------------------------------
+	/** Construction from a given stream with a well-defined endianess.
+	 * 
+	 *  The StreamReader holds a permanent strong reference to the
+	 *  stream, which is released upon destruction.
+	 *  @param stream Input stream. The stream is not re-seeked and writing
+	      continues at the current position of the stream cursor.
+	 *  @param le If @c RuntimeSwitch is true: specifies whether the
+	 *    stream is in little endian byte order. Otherwise the
+	 *    endianess information is defined by the @c SwapEndianess
+	 *    template parameter and this parameter is meaningless.  */
+	StreamWriter(boost::shared_ptr<IOStream> stream, bool le = false)
+		: stream(stream)
+		, le(le)
+		, cursor()
+	{
+		ai_assert(stream); 
+		buffer.reserve(INITIAL_CAPACITY);
+	}
+
+	// ---------------------------------------------------------------------
+	StreamWriter(IOStream* stream, bool le = false)
+		: stream(boost::shared_ptr<IOStream>(stream))
+		, le(le)
+		, cursor()
+	{
+		ai_assert(stream);
+		buffer.reserve(INITIAL_CAPACITY);
+	}
+
+	// ---------------------------------------------------------------------
+	~StreamWriter() {
+		stream->Write(&buffer[0], 1, buffer.size());
+		stream->Flush();
+	}
+
+public:
+
+	// ---------------------------------------------------------------------
+	/** Write a float to the stream  */
+	void PutF4(float f)
+	{
+		Put(f);
+	}
+
+	// ---------------------------------------------------------------------
+	/** Write a double to the stream  */
+	void PutF8(double d)	{
+		Put(d);
+	}
+
+	// ---------------------------------------------------------------------
+	/** Write a signed 16 bit integer to the stream */
+	void PutI2(int16_t n)	{
+		Put(n);
+	}
+
+	// ---------------------------------------------------------------------
+	/** Write a signed 8 bit integer to the stream */
+	void PutI1(int8_t n)	{
+		Put(n);
+	}
+
+	// ---------------------------------------------------------------------
+	/** Write an signed 32 bit integer to the stream */
+	void PutI4(int32_t n)	{
+		Put(n);
+	}
+
+	// ---------------------------------------------------------------------
+	/** Write a signed 64 bit integer to the stream */
+	void PutI8(int64_t n)	{
+		Put(n);
+	}
+
+	// ---------------------------------------------------------------------
+	/** Write a unsigned 16 bit integer to the stream */
+	void PutU2(uint16_t n)	{
+		Put(n);
+	}
+
+	// ---------------------------------------------------------------------
+	/** Write a unsigned 8 bit integer to the stream */
+	void PutU1(uint8_t n)	{
+		Put(n);
+	}
+
+	// ---------------------------------------------------------------------
+	/** Write an unsigned 32 bit integer to the stream */
+	void PutU4(uint32_t n)	{
+		Put(n);
+	}
+
+	// ---------------------------------------------------------------------
+	/** Write a unsigned 64 bit integer to the stream */
+	void PutU8(uint64_t n)	{
+		Put(n);
+	}
+
+public:
+
+	// ---------------------------------------------------------------------
+	/** overload operator<< and allow chaining of MM ops. */
+	template <typename T>
+	StreamWriter& operator << (T f) {
+		Put(f); 
+		return *this;
+	}
+
+	// ---------------------------------------------------------------------
+	std::size_t GetCurrentPos() const {
+		return cursor;
+	}
+
+	// ---------------------------------------------------------------------
+	void SetCurrentPos(std::size_t new_cursor) {
+		cursor = new_cursor;
+	}
+
+private:
+
+	// ---------------------------------------------------------------------
+	/** Generic write method. ByteSwap::Swap(T*) *must* be defined */
+	template <typename T>
+	void Put(T f)	{
+		Intern :: Getter<SwapEndianess,T,RuntimeSwitch>() (&f, le);
+		
+		if (cursor + sizeof(T) >= buffer.size()) {
+			buffer.resize(cursor + sizeof(T));
+		}
+
+		void* dest = &buffer[cursor];
+
+		// reinterpret_cast + assignment breaks strict aliasing rules
+		// and generally causes trouble on platforms such as ARM that
+		// do not silently ignore alignment faults.
+		::memcpy(dest, &f, sizeof(T));
+		cursor += sizeof(T);
+	}
+
+private:
+
+	boost::shared_ptr<IOStream> stream;
+	bool le;
+
+	std::vector<uint8_t> buffer;
+	std::size_t cursor;
+};
+
+
+// --------------------------------------------------------------------------------------------
+// `static` StreamWriter. Their byte order is fixed and they might be a little bit faster.
+#ifdef AI_BUILD_BIG_ENDIAN
+	typedef StreamWriter<true>  StreamWriterLE;
+	typedef StreamWriter<false> StreamWriterBE;
+#else
+	typedef StreamWriter<true>  StreamWriterBE;
+	typedef StreamWriter<false> StreamWriterLE;
+#endif
+
+// `dynamic` StreamWriter. The byte order of the input data is specified in the
+// c'tor. This involves runtime branching and might be a little bit slower.
+typedef StreamWriter<true,true> StreamWriterAny;
+
+} // end namespace Assimp
+
+#endif // !! AI_STREAMWriter_H_INCLUDED

+ 81 - 0
code/XMLTools.h

@@ -0,0 +1,81 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, 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 INCLUDED_ASSIMP_XML_TOOLS_H
+#define INCLUDED_ASSIMP_XML_TOOLS_H
+
+#include <string>
+
+namespace Assimp {
+	// XML escape the 5 XML special characters (",',<,> and &) in |data|
+	// Based on http://stackoverflow.com/questions/5665231
+	std::string XMLEscape(const std::string& data) {
+		std::string buffer;
+
+		const size_t size = data.size();
+		buffer.reserve(size + size / 8);
+		for(size_t i = 0; i < size; ++i) {
+			const char c = data[i];
+			switch(c) {
+				case '&' :
+					buffer.append("&amp;");
+					break;
+				case '\"':
+					buffer.append("&quot;");
+					break;
+				case '\'':
+					buffer.append("&apos;");
+					break;
+				case '<' :
+					buffer.append("&lt;");
+					break;
+				case '>' :
+					buffer.append("&gt;");
+					break;
+				default:
+					buffer.append(&c, 1);
+					break;
+			}
+		}
+		return buffer;
+	}
+}
+
+#endif // INCLUDED_ASSIMP_XML_TOOLS_H

+ 42 - 6
code/fast_atof.h

@@ -16,7 +16,9 @@
 #define __FAST_A_TO_F_H_INCLUDED__
 #define __FAST_A_TO_F_H_INCLUDED__
 
 
 #include <math.h>
 #include <math.h>
-#include <limits.h>
+#include <limits>
+
+#include "StringComparison.h"
 
 
 namespace Assimp
 namespace Assimp
 {
 {
@@ -229,15 +231,45 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
 template <typename Real>
 template <typename Real>
 inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
 inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
 {
 {
-	Real f;
+	Real f = 0;
 
 
-	bool inv = (*c=='-');
-	if (inv || *c=='+') {
+	bool inv = (*c == '-');
+	if (inv || *c == '+') {
 		++c;
 		++c;
 	}
 	}
 
 
-	f = static_cast<Real>( strtoul10_64 ( c, &c) );
-	if (*c == '.' || (check_comma && c[0] == ',' && c[1] >= '0' && c[1] <= '9')) // allow for commas, too
+	if ((c[0] == 'N' || c[0] == 'n') && ASSIMP_strincmp(c, "nan", 3) == 0)
+	{
+		out = std::numeric_limits<Real>::quiet_NaN();
+		c += 3;
+		return c;
+	}
+
+	if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inf", 3) == 0)
+	{
+		out = std::numeric_limits<Real>::infinity();
+		c += 3;
+		if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inity", 5) == 0)
+		{
+			c += 5;
+		}
+		return c;
+	}
+
+	if (!(c[0] >= '0' && c[0] <= '9') &&
+	    !(c[0] == '.' && c[1] >= '0' && c[1] <= '9'))
+	{
+		throw std::invalid_argument("Cannot parse string "
+		                            "as real number: does not start with digit "
+		                            "or decimal point followed by digit.");
+	}
+
+	if (*c != '.')
+	{
+		f = static_cast<Real>( strtoul10_64 ( c, &c) );
+	}
+
+	if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')
 	{
 	{
 		++c;
 		++c;
 
 
@@ -255,6 +287,10 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma
 		pl *= fast_atof_table[diff];
 		pl *= fast_atof_table[diff];
 		f += static_cast<Real>( pl );
 		f += static_cast<Real>( pl );
 	}
 	}
+	// For backwards compatibility: eat trailing dots, but not trailing commas.
+	else if (*c == '.') {
+		++c;
+	}
 
 
 	// A major 'E' must be allowed. Necessary for proper reading of some DXF files.
 	// A major 'E' must be allowed. Necessary for proper reading of some DXF files.
 	// Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..)
 	// Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..)

+ 2 - 0
contrib/clipper/clipper.cpp

@@ -2124,11 +2124,13 @@ void Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
     {
     {
       //check for 'rounding' artefacts ...
       //check for 'rounding' artefacts ...
       if (outRec->sides == esNeither && pt.Y == op->pt.Y)
       if (outRec->sides == esNeither && pt.Y == op->pt.Y)
+      {
         if (ToFront)
         if (ToFront)
         {
         {
           if (pt.X == op->pt.X +1) return;    //ie wrong side of bottomPt
           if (pt.X == op->pt.X +1) return;    //ie wrong side of bottomPt
         }
         }
         else if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt
         else if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt
+      }
 
 
       outRec->sides = (EdgeSide)(outRec->sides | e->side);
       outRec->sides = (EdgeSide)(outRec->sides | e->side);
       if (outRec->sides == esBoth)
       if (outRec->sides == esBoth)

+ 1 - 1
contrib/unzip/unzip.c

@@ -1246,7 +1246,7 @@ extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
         return UNZ_PARAMERROR;
         return UNZ_PARAMERROR;
 
 
 
 
-    if ((pfile_in_zip_read_info->read_buffer == NULL))
+    if (pfile_in_zip_read_info->read_buffer == NULL)
         return UNZ_END_OF_LIST_OF_FILE;
         return UNZ_END_OF_LIST_OF_FILE;
     if (len==0)
     if (len==0)
         return 0;
         return 0;

+ 29 - 3
include/assimp/ProgressHandler.hpp

@@ -81,13 +81,39 @@ public:
 	 *   all needed cleanup tasks prior to returning control to the
 	 *   all needed cleanup tasks prior to returning control to the
 	 *   caller). If the loading is aborted, #Importer::ReadFile()
 	 *   caller). If the loading is aborted, #Importer::ReadFile()
 	 *   returns always NULL.
 	 *   returns always NULL.
-	 *
-	 *  @note Currently, percentage is always -1.f because there is 
-	 *   no reliable way to compute it.
 	 *   */
 	 *   */
 	virtual bool Update(float percentage = -1.f) = 0;
 	virtual bool Update(float percentage = -1.f) = 0;
 
 
+	// -------------------------------------------------------------------
+	/** @brief Progress callback for file loading steps
+	 *  @param numberOfSteps The number of total post-processing
+	 *   steps
+	 *  @param currentStep The index of the current post-processing
+	 *   step that will run, or equal to numberOfSteps if all of
+	 *   them has finished. This number is always strictly monotone
+	 *   increasing, although not necessarily linearly.
+	 *
+	 *  @note This is currently only used at the start and the end
+	 *   of the file parsing.
+	 *   */
+	virtual void UpdateFileRead(int currentStep /*= 0*/, int numberOfSteps /*= 0*/) {
+		float f = numberOfSteps ? currentStep / (float)numberOfSteps : 1.0f;
+		Update( f * 0.5f );
+	};
 
 
+	// -------------------------------------------------------------------
+	/** @brief Progress callback for post-processing steps
+	 *  @param numberOfSteps The number of total post-processing
+	 *   steps
+	 *  @param currentStep The index of the current post-processing
+	 *   step that will run, or equal to numberOfSteps if all of
+	 *   them has finished. This number is always strictly monotone
+	 *   increasing, although not necessarily linearly.
+	 *   */
+	virtual void UpdatePostProcess(int currentStep /*= 0*/, int numberOfSteps /*= 0*/) {
+		float f = numberOfSteps ? currentStep / (float)numberOfSteps : 1.0f;
+		Update( f * 0.5f + 0.5f );
+	};
 
 
 }; // !class ProgressHandler 
 }; // !class ProgressHandler 
 // ------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------

+ 1 - 1
include/assimp/importerdesc.h

@@ -72,7 +72,7 @@ enum aiImporterFlags
 	  * should be used with care. This only happens for trunk
 	  * should be used with care. This only happens for trunk
 	  * (i.e. SVN) versions, experimental code is not included
 	  * (i.e. SVN) versions, experimental code is not included
 	  * in releases. */
 	  * in releases. */
-	aiImporterFlags_Experimental = 0x10,
+	aiImporterFlags_Experimental = 0x10
 };
 };
 
 
 
 

+ 2 - 1
samples/SimpleOpenGL/CMakeLists.txt

@@ -1,5 +1,6 @@
 FIND_PACKAGE(OpenGL)
 FIND_PACKAGE(OpenGL)
 FIND_PACKAGE(GLUT)
 FIND_PACKAGE(GLUT)
+find_library(M_LIB m)
 
 
 IF ( NOT GLUT_FOUND )
 IF ( NOT GLUT_FOUND )
 	IF ( MSVC )
 	IF ( MSVC )
@@ -29,7 +30,7 @@ ADD_EXECUTABLE( assimp_simpleogl
 
 
 SET_PROPERTY(TARGET assimp_simpleogl PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
 SET_PROPERTY(TARGET assimp_simpleogl PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
 
 
-TARGET_LINK_LIBRARIES( assimp_simpleogl assimp ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} )
+TARGET_LINK_LIBRARIES( assimp_simpleogl assimp ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${M_LIB} )
 SET_TARGET_PROPERTIES( assimp_simpleogl PROPERTIES
 SET_TARGET_PROPERTIES( assimp_simpleogl PROPERTIES
 	OUTPUT_NAME assimp_simpleogl
 	OUTPUT_NAME assimp_simpleogl
 )
 )

+ 48 - 46
samples/SimpleOpenGL/Sample_SimpleOpenGL.c

@@ -1,4 +1,4 @@
-// ----------------------------------------------------------------------------
+/* ----------------------------------------------------------------------------
 // Simple sample to prove that Assimp is easy to use with OpenGL.
 // Simple sample to prove that Assimp is easy to use with OpenGL.
 // It takes a file name as command line parameter, loads it using standard
 // It takes a file name as command line parameter, loads it using standard
 // settings and displays it.
 // settings and displays it.
@@ -9,29 +9,30 @@
 // The vc8 solution links against assimp-release-dll_win32 - be sure to
 // The vc8 solution links against assimp-release-dll_win32 - be sure to
 // have this configuration built.
 // have this configuration built.
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
+*/
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdio.h>
 
 
 #include <GL/glut.h>
 #include <GL/glut.h>
 
 
-// assimp include files. These three are usually needed.
+/* assimp include files. These three are usually needed. */
 #include <assimp/cimport.h>
 #include <assimp/cimport.h>
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>
 
 
-// the global Assimp scene object
+/* the global Assimp scene object */
 const struct aiScene* scene = NULL;
 const struct aiScene* scene = NULL;
 GLuint scene_list = 0;
 GLuint scene_list = 0;
 struct aiVector3D scene_min, scene_max, scene_center;
 struct aiVector3D scene_min, scene_max, scene_center;
 
 
-// current rotation angle
+/* current rotation angle */
 static float angle = 0.f;
 static float angle = 0.f;
 
 
 #define aisgl_min(x,y) (x<y?x:y)
 #define aisgl_min(x,y) (x<y?x:y)
 #define aisgl_max(x,y) (y>x?y:x)
 #define aisgl_max(x,y) (y>x?y:x)
 
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void reshape(int width, int height)
 void reshape(int width, int height)
 {
 {
 	const double aspectRatio = (float) width / height, fieldOfView = 45.0;
 	const double aspectRatio = (float) width / height, fieldOfView = 45.0;
@@ -43,7 +44,7 @@ void reshape(int width, int height)
 	glViewport(0, 0, width, height);
 	glViewport(0, 0, width, height);
 }
 }
 
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void get_bounding_box_for_node (const struct aiNode* nd, 
 void get_bounding_box_for_node (const struct aiNode* nd, 
 	struct aiVector3D* min, 
 	struct aiVector3D* min, 
 	struct aiVector3D* max, 
 	struct aiVector3D* max, 
@@ -78,7 +79,7 @@ void get_bounding_box_for_node (const struct aiNode* nd,
 	*trafo = prev;
 	*trafo = prev;
 }
 }
 
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max)
 void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max)
 {
 {
 	struct aiMatrix4x4 trafo;
 	struct aiMatrix4x4 trafo;
@@ -89,7 +90,7 @@ void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max)
 	get_bounding_box_for_node(scene->mRootNode,min,max,&trafo);
 	get_bounding_box_for_node(scene->mRootNode,min,max,&trafo);
 }
 }
 
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void color4_to_float4(const struct aiColor4D *c, float f[4])
 void color4_to_float4(const struct aiColor4D *c, float f[4])
 {
 {
 	f[0] = c->r;
 	f[0] = c->r;
@@ -98,7 +99,7 @@ void color4_to_float4(const struct aiColor4D *c, float f[4])
 	f[3] = c->a;
 	f[3] = c->a;
 }
 }
 
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void set_float4(float f[4], float a, float b, float c, float d)
 void set_float4(float f[4], float a, float b, float c, float d)
 {
 {
 	f[0] = a;
 	f[0] = a;
@@ -107,7 +108,7 @@ void set_float4(float f[4], float a, float b, float c, float d)
 	f[3] = d;
 	f[3] = d;
 }
 }
 
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void apply_material(const struct aiMaterial *mtl)
 void apply_material(const struct aiMaterial *mtl)
 {
 {
 	float c[4];
 	float c[4];
@@ -173,19 +174,19 @@ void apply_material(const struct aiMaterial *mtl)
 		glEnable(GL_CULL_FACE);
 		glEnable(GL_CULL_FACE);
 }
 }
 
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
 void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
 {
 {
 	unsigned int i;
 	unsigned int i;
 	unsigned int n = 0, t;
 	unsigned int n = 0, t;
 	struct aiMatrix4x4 m = nd->mTransformation;
 	struct aiMatrix4x4 m = nd->mTransformation;
 
 
-	// update transform
+	/* update transform */
 	aiTransposeMatrix4(&m);
 	aiTransposeMatrix4(&m);
 	glPushMatrix();
 	glPushMatrix();
 	glMultMatrixf((float*)&m);
 	glMultMatrixf((float*)&m);
 
 
-	// draw all meshes assigned to this node
+	/* draw all meshes assigned to this node */
 	for (; n < nd->mNumMeshes; ++n) {
 	for (; n < nd->mNumMeshes; ++n) {
 		const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
 		const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
 
 
@@ -224,7 +225,7 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
 
 
 	}
 	}
 
 
-	// draw all children
+	/* draw all children */
 	for (n = 0; n < nd->mNumChildren; ++n) {
 	for (n = 0; n < nd->mNumChildren; ++n) {
 		recursive_render(sc, nd->mChildren[n]);
 		recursive_render(sc, nd->mChildren[n]);
 	}
 	}
@@ -232,7 +233,7 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
 	glPopMatrix();
 	glPopMatrix();
 }
 }
 
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void do_motion (void)
 void do_motion (void)
 {
 {
 	static GLint prev_time = 0;
 	static GLint prev_time = 0;
@@ -244,7 +245,7 @@ void do_motion (void)
 	prev_time = time;
 	prev_time = time;
 
 
 	frames += 1;
 	frames += 1;
-	if ((time - prev_fps_time) > 1000) // update every seconds
+	if ((time - prev_fps_time) > 1000) /* update every seconds */
     {
     {
         int current_fps = frames * 1000 / (time - prev_fps_time);
         int current_fps = frames * 1000 / (time - prev_fps_time);
         printf("%d fps\n", current_fps);
         printf("%d fps\n", current_fps);
@@ -256,7 +257,7 @@ void do_motion (void)
 	glutPostRedisplay ();
 	glutPostRedisplay ();
 }
 }
 
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void display(void)
 void display(void)
 {
 {
 	float tmp;
 	float tmp;
@@ -267,27 +268,27 @@ void display(void)
 	glLoadIdentity();
 	glLoadIdentity();
 	gluLookAt(0.f,0.f,3.f,0.f,0.f,-5.f,0.f,1.f,0.f);
 	gluLookAt(0.f,0.f,3.f,0.f,0.f,-5.f,0.f,1.f,0.f);
 
 
-	// rotate it around the y axis
+	/* rotate it around the y axis */
 	glRotatef(angle,0.f,1.f,0.f);
 	glRotatef(angle,0.f,1.f,0.f);
 
 
-	// scale the whole asset to fit into our view frustum 
+	/* scale the whole asset to fit into our view frustum */
 	tmp = scene_max.x-scene_min.x;
 	tmp = scene_max.x-scene_min.x;
 	tmp = aisgl_max(scene_max.y - scene_min.y,tmp);
 	tmp = aisgl_max(scene_max.y - scene_min.y,tmp);
 	tmp = aisgl_max(scene_max.z - scene_min.z,tmp);
 	tmp = aisgl_max(scene_max.z - scene_min.z,tmp);
 	tmp = 1.f / tmp;
 	tmp = 1.f / tmp;
 	glScalef(tmp, tmp, tmp);
 	glScalef(tmp, tmp, tmp);
 
 
-        // center the model
+        /* center the model */
 	glTranslatef( -scene_center.x, -scene_center.y, -scene_center.z );
 	glTranslatef( -scene_center.x, -scene_center.y, -scene_center.z );
 
 
-        // if the display list has not been made yet, create a new one and
-        // fill it with scene contents
+        /* if the display list has not been made yet, create a new one and
+           fill it with scene contents */
 	if(scene_list == 0) {
 	if(scene_list == 0) {
 	    scene_list = glGenLists(1);
 	    scene_list = glGenLists(1);
 	    glNewList(scene_list, GL_COMPILE);
 	    glNewList(scene_list, GL_COMPILE);
-            // now begin at the root node of the imported data and traverse
-            // the scenegraph by multiplying subsequent local transforms
-            // together on GL's matrix stack.
+            /* now begin at the root node of the imported data and traverse
+               the scenegraph by multiplying subsequent local transforms
+               together on GL's matrix stack. */
 	    recursive_render(scene, scene->mRootNode);
 	    recursive_render(scene, scene->mRootNode);
 	    glEndList();
 	    glEndList();
 	}
 	}
@@ -299,11 +300,11 @@ void display(void)
 	do_motion();
 	do_motion();
 }
 }
 
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 int loadasset (const char* path)
 int loadasset (const char* path)
 {
 {
-	// we are taking one of the postprocessing presets to avoid
-	// spelling out 20+ single postprocessing flags here.
+	/* we are taking one of the postprocessing presets to avoid
+	   spelling out 20+ single postprocessing flags here. */
 	scene = aiImportFile(path,aiProcessPreset_TargetRealtime_MaxQuality);
 	scene = aiImportFile(path,aiProcessPreset_TargetRealtime_MaxQuality);
 
 
 	if (scene) {
 	if (scene) {
@@ -316,7 +317,7 @@ int loadasset (const char* path)
 	return 1;
 	return 1;
 }
 }
 
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 int main(int argc, char **argv)
 int main(int argc, char **argv)
 {
 {
 	struct aiLogStream stream;
 	struct aiLogStream stream;
@@ -330,21 +331,21 @@ int main(int argc, char **argv)
 	glutDisplayFunc(display);
 	glutDisplayFunc(display);
 	glutReshapeFunc(reshape);
 	glutReshapeFunc(reshape);
 
 
-	// get a handle to the predefined STDOUT log stream and attach
-	// it to the logging system. It remains active for all further
-	// calls to aiImportFile(Ex) and aiApplyPostProcessing.
+	/* get a handle to the predefined STDOUT log stream and attach
+	   it to the logging system. It remains active for all further
+	   calls to aiImportFile(Ex) and aiApplyPostProcessing. */
 	stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL);
 	stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL);
 	aiAttachLogStream(&stream);
 	aiAttachLogStream(&stream);
 
 
-	// ... same procedure, but this stream now writes the
-	// log messages to assimp_log.txt
+	/* ... same procedure, but this stream now writes the
+	   log messages to assimp_log.txt */
 	stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt");
 	stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt");
 	aiAttachLogStream(&stream);
 	aiAttachLogStream(&stream);
 
 
-	// the model name can be specified on the command line. If none
-	// is specified, we try to locate one of the more expressive test 
-	// models from the repository (/models-nonbsd may be missing in 
-	// some distributions so we need a fallback from /models!).
+	/* the model name can be specified on the command line. If none
+	  is specified, we try to locate one of the more expressive test 
+	  models from the repository (/models-nonbsd may be missing in 
+	  some distributions so we need a fallback from /models!). */
 	if( 0 != loadasset( argc >= 2 ? argv[1] : "../../test/models-nonbsd/X/dwarf.x")) {
 	if( 0 != loadasset( argc >= 2 ? argv[1] : "../../test/models-nonbsd/X/dwarf.x")) {
 		if( argc != 1 || (0 != loadasset( "../../../../test/models-nonbsd/X/dwarf.x") && 0 != loadasset( "../../test/models/X/Testwuson.X"))) { 
 		if( argc != 1 || (0 != loadasset( "../../../../test/models-nonbsd/X/dwarf.x") && 0 != loadasset( "../../test/models/X/Testwuson.X"))) { 
 			return -1;
 			return -1;
@@ -354,14 +355,14 @@ int main(int argc, char **argv)
 	glClearColor(0.1f,0.1f,0.1f,1.f);
 	glClearColor(0.1f,0.1f,0.1f,1.f);
 
 
 	glEnable(GL_LIGHTING);
 	glEnable(GL_LIGHTING);
-	glEnable(GL_LIGHT0);    // Uses default lighting parameters
+	glEnable(GL_LIGHT0);    /* Uses default lighting parameters */
 
 
 	glEnable(GL_DEPTH_TEST);
 	glEnable(GL_DEPTH_TEST);
 
 
 	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
 	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
 	glEnable(GL_NORMALIZE);
 	glEnable(GL_NORMALIZE);
 
 
-	// XXX docs say all polygons are emitted CCW, but tests show that some aren't.
+	/* XXX docs say all polygons are emitted CCW, but tests show that some aren't. */
 	if(getenv("MODEL_IS_BROKEN"))  
 	if(getenv("MODEL_IS_BROKEN"))  
 		glFrontFace(GL_CW);
 		glFrontFace(GL_CW);
 
 
@@ -370,14 +371,15 @@ int main(int argc, char **argv)
 	glutGet(GLUT_ELAPSED_TIME);
 	glutGet(GLUT_ELAPSED_TIME);
 	glutMainLoop();
 	glutMainLoop();
 
 
-	// cleanup - calling 'aiReleaseImport' is important, as the library 
-	// keeps internal resources until the scene is freed again. Not 
-	// doing so can cause severe resource leaking.
+	/* cleanup - calling 'aiReleaseImport' is important, as the library 
+	   keeps internal resources until the scene is freed again. Not 
+	   doing so can cause severe resource leaking. */
 	aiReleaseImport(scene);
 	aiReleaseImport(scene);
 
 
-	// We added a log stream to the library, it's our job to disable it
-	// again. This will definitely release the last resources allocated
-	// by Assimp.
+	/* We added a log stream to the library, it's our job to disable it
+	   again. This will definitely release the last resources allocated
+	   by Assimp.*/
 	aiDetachAllLogStreams();
 	aiDetachAllLogStreams();
 	return 0;
 	return 0;
 }
 }
+

+ 41 - 57
samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp

@@ -12,9 +12,6 @@
 // Thanks to NeHe on whose OpenGL tutorials this one's based on! :)
 // Thanks to NeHe on whose OpenGL tutorials this one's based on! :)
 // http://nehe.gamedev.net/
 // http://nehe.gamedev.net/
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
-
-
-
 #include <windows.h>
 #include <windows.h>
 #include <stdio.h>
 #include <stdio.h>
 #include <GL/gl.h>
 #include <GL/gl.h>
@@ -36,7 +33,7 @@
 #include "assimp/LogStream.hpp"
 #include "assimp/LogStream.hpp"
 
 
 
 
-// The default hardcoded path. Can be overridden by supplying a path through the commandline.
+// The default hard-coded path. Can be overridden by supplying a path through the command line.
 static std::string modelpath = "../../test/models/OBJ/spider.obj";
 static std::string modelpath = "../../test/models/OBJ/spider.obj";
 
 
 
 
@@ -47,7 +44,7 @@ HINSTANCE	hInstance;	// Holds The Instance Of The Application
 
 
 bool		keys[256];			// Array used for Keyboard Routine;
 bool		keys[256];			// Array used for Keyboard Routine;
 bool		active=TRUE;		// Window Active Flag Set To TRUE by Default
 bool		active=TRUE;		// Window Active Flag Set To TRUE by Default
-bool		fullscreen=TRUE;	// Fullscreen Flag Set To Fullscreen By Default
+bool		fullscreen=TRUE;	// full-screen Flag Set To full-screen By Default
 
 
 GLfloat		xrot;
 GLfloat		xrot;
 GLfloat		yrot;
 GLfloat		yrot;
@@ -80,6 +77,7 @@ Assimp::Importer importer;
 
 
 void createAILogger()
 void createAILogger()
 {
 {
+    // Change this line to normal if you not want to analyse the import process
 	//Assimp::Logger::LogSeverity severity = Assimp::Logger::NORMAL;
 	//Assimp::Logger::LogSeverity severity = Assimp::Logger::NORMAL;
 	Assimp::Logger::LogSeverity severity = Assimp::Logger::VERBOSE;
 	Assimp::Logger::LogSeverity severity = Assimp::Logger::VERBOSE;
 
 
@@ -101,20 +99,20 @@ void destroyAILogger()
 
 
 void logInfo(std::string logString)
 void logInfo(std::string logString)
 {
 {
-	//Will add message to File with "info" Tag
+	// Will add message to File with "info" Tag
 	Assimp::DefaultLogger::get()->info(logString.c_str());
 	Assimp::DefaultLogger::get()->info(logString.c_str());
 }
 }
 
 
 void logDebug(const char* logString)
 void logDebug(const char* logString)
 {
 {
-	//Will add message to File with "debug" Tag
+	// Will add message to File with "debug" Tag
 	Assimp::DefaultLogger::get()->debug(logString);
 	Assimp::DefaultLogger::get()->debug(logString);
 }
 }
 
 
 
 
 bool Import3DFromFile( const std::string& pFile)
 bool Import3DFromFile( const std::string& pFile)
 {
 {
-	//check if file exists
+	// Check if file exists
 	std::ifstream fin(pFile.c_str());
 	std::ifstream fin(pFile.c_str());
 	if(!fin.fail())
 	if(!fin.fail())
 	{
 	{
@@ -143,12 +141,14 @@ bool Import3DFromFile( const std::string& pFile)
 	return true;
 	return true;
 }
 }
 
 
-
-void ReSizeGLScene(GLsizei width, GLsizei height)				// Resize And Initialize The GL Window
+// Resize And Initialize The GL Window
+void ReSizeGLScene(GLsizei width, GLsizei height)				
 {
 {
-	if (height==0)								// Prevent A Divide By Zero By
+    // Prevent A Divide By Zero By
+	if (height==0)								
 	{
 	{
-		height=1;							// Making Height Equal One
+        // Making Height Equal One
+        height=1;		
 	}
 	}
 
 
 	glViewport(0, 0, width, height);					// Reset The Current Viewport
 	glViewport(0, 0, width, height);					// Reset The Current Viewport
@@ -217,9 +217,6 @@ int LoadGLTextures(const aiScene* scene)
 	textureIds = new GLuint[numTextures];
 	textureIds = new GLuint[numTextures];
 	glGenTextures(numTextures, textureIds); /* Texture name generation */
 	glGenTextures(numTextures, textureIds); /* Texture name generation */
 
 
-	/* define texture path */
-	//std::string texturepath = "../../../test/models/Obj/";
-
 	/* get iterator */
 	/* get iterator */
 	std::map<std::string, GLuint*>::iterator itr = textureIdMap.begin();
 	std::map<std::string, GLuint*>::iterator itr = textureIdMap.begin();
 
 
@@ -239,48 +236,50 @@ int LoadGLTextures(const aiScene* scene)
 
 
 		if (success) /* If no error occured: */
 		if (success) /* If no error occured: */
 		{
 		{
-			success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); /* Convert every colour component into
-			unsigned byte. If your image contains alpha channel you can replace IL_RGB with IL_RGBA */
+            // Convert every colour component into unsigned byte.If your image contains 
+            // alpha channel you can replace IL_RGB with IL_RGBA
+            success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);
 			if (!success)
 			if (!success)
 			{
 			{
 				/* Error occured */
 				/* Error occured */
 				abortGLInit("Couldn't convert image");
 				abortGLInit("Couldn't convert image");
 				return -1;
 				return -1;
 			}
 			}
-			//glGenTextures(numTextures, &textureIds[i]); /* Texture name generation */
-			glBindTexture(GL_TEXTURE_2D, textureIds[i]); /* Binding of texture name */
-			//redefine standard texture values
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* We will use linear
-			interpolation for magnification filter */
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); /* We will use linear
-			interpolation for minifying filter */
-			glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
+            // Binding of texture name
+            glBindTexture(GL_TEXTURE_2D, textureIds[i]); 
+			// redefine standard texture values
+            // We will use linear interpolation for magnification filter
+            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+            // We will use linear interpolation for minifying filter
+            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+            // Texture specification
+            glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
 				ilGetInteger(IL_IMAGE_HEIGHT), 0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE,
 				ilGetInteger(IL_IMAGE_HEIGHT), 0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE,
-				ilGetData()); /* Texture specification */
+				ilGetData()); 
+            // we also want to be able to deal with odd texture dimensions
+            glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+            glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
+            glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
+            glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
 		}
 		}
 		else
 		else
 		{
 		{
 			/* Error occured */
 			/* Error occured */
 			MessageBox(NULL, ("Couldn't load Image: " + fileloc).c_str() , "ERROR", MB_OK | MB_ICONEXCLAMATION);
 			MessageBox(NULL, ("Couldn't load Image: " + fileloc).c_str() , "ERROR", MB_OK | MB_ICONEXCLAMATION);
 		}
 		}
-
-
 	}
 	}
+    // Because we have already copied image data into texture data  we can release memory used by image.
+	ilDeleteImages(numTextures, imageIds); 
 
 
-	ilDeleteImages(numTextures, imageIds); /* Because we have already copied image data into texture data
-	we can release memory used by image. */
-
-	//Cleanup
+	// Cleanup
 	delete [] imageIds;
 	delete [] imageIds;
 	imageIds = NULL;
 	imageIds = NULL;
 
 
-	//return success;
 	return TRUE;
 	return TRUE;
 }
 }
 
 
-
-
-int InitGL()					 // All Setup For OpenGL goes here
+// All Setup For OpenGL goes here
+int InitGL()
 {
 {
 	if (!LoadGLTextures(scene))
 	if (!LoadGLTextures(scene))
 	{
 	{
@@ -307,9 +306,6 @@ int InitGL()					 // All Setup For OpenGL goes here
 	glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
 	glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
 	glEnable(GL_LIGHT1);
 	glEnable(GL_LIGHT1);
 
 
-	//glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
-
-
 	return TRUE;					// Initialization Went OK
 	return TRUE;					// Initialization Went OK
 }
 }
 
 
@@ -449,8 +445,6 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd, float
 			glDisable(GL_COLOR_MATERIAL);
 			glDisable(GL_COLOR_MATERIAL);
 		}
 		}
 
 
-
-
 		for (t = 0; t < mesh->mNumFaces; ++t) {
 		for (t = 0; t < mesh->mNumFaces; ++t) {
 			const struct aiFace* face = &mesh->mFaces[t];
 			const struct aiFace* face = &mesh->mFaces[t];
 			GLenum face_mode;
 			GLenum face_mode;
@@ -480,14 +474,10 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd, float
 					glNormal3fv(&mesh->mNormals[vertexIndex].x);
 					glNormal3fv(&mesh->mNormals[vertexIndex].x);
 					glVertex3fv(&mesh->mVertices[vertexIndex].x);
 					glVertex3fv(&mesh->mVertices[vertexIndex].x);
 			}
 			}
-
 			glEnd();
 			glEnd();
-
 		}
 		}
-
 	}
 	}
 
 
-
 	// draw all children
 	// draw all children
 	for (n = 0; n < nd->mNumChildren; ++n)
 	for (n = 0; n < nd->mNumChildren; ++n)
 	{
 	{
@@ -521,12 +511,11 @@ int DrawGLScene()				//Here's where we do all the drawing
 
 
 	drawAiScene(scene);
 	drawAiScene(scene);
 
 
-
 	//xrot+=0.3f;
 	//xrot+=0.3f;
 	yrot+=0.2f;
 	yrot+=0.2f;
 	//zrot+=0.4f;
 	//zrot+=0.4f;
 
 
-	return TRUE;					// Ewwrissing okay
+	return TRUE;					// okay
 }
 }
 
 
 
 
@@ -667,11 +656,6 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 	{
 	{
 		abortGLInit("Window Creation Error.");
 		abortGLInit("Window Creation Error.");
 		return FALSE;
 		return FALSE;
-		/*
-		KillGLWindow();											// Reset The Display
-		MessageBox(NULL, "Window Creation Error.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
-		return FALSE;											// Return False
-		*/
 	}
 	}
 
 
 	static	PIXELFORMATDESCRIPTOR pfd=					// pfd Tells Windows How We Want Things To Be
 	static	PIXELFORMATDESCRIPTOR pfd=					// pfd Tells Windows How We Want Things To Be
@@ -767,8 +751,8 @@ LRESULT CALLBACK WndProc(HWND hWnd,				// Handles for this Window
 			{
 			{
 				switch (wParam)
 				switch (wParam)
 				{
 				{
-					case SC_SCREENSAVE:		// Screensaver trying to start
-					case SC_MONITORPOWER:	// Monitor tryig to enter powersafe
+					case SC_SCREENSAVE:		// Screen-saver trying to start
+					case SC_MONITORPOWER:	// Monitor trying to enter power-safe
 					return 0;
 					return 0;
 				}
 				}
 				break;
 				break;
@@ -799,12 +783,12 @@ LRESULT CALLBACK WndProc(HWND hWnd,				// Handles for this Window
 			}
 			}
 	}
 	}
 
 
-	// Pass All Unhandled Messaged To DefWindowProc
+	// Pass All unhandled Messaged To DefWindowProc
 	return DefWindowProc(hWnd, uMsg, wParam, lParam);
 	return DefWindowProc(hWnd, uMsg, wParam, lParam);
 }
 }
 
 
-int WINAPI WinMain( HINSTANCE hInstance, // Instance
-				   HINSTANCE hPrevInstance,      // Previous Instance
+int WINAPI WinMain( HINSTANCE hInstance,         // The instance
+				   HINSTANCE hPrevInstance,      // Previous instance
 				   LPSTR lpCmdLine,              // Command Line Parameters
 				   LPSTR lpCmdLine,              // Command Line Parameters
 				   int nShowCmd )                // Window Show State
 				   int nShowCmd )                // Window Show State
 {
 {

+ 14 - 105
test/CMakeLists.txt

@@ -15,7 +15,8 @@ SOURCE_GROUP( unit FILES
 	unit/BoostWorkaround/tupletest.cpp
 	unit/BoostWorkaround/tupletest.cpp
 )
 )
 
 
-SOURCE_GROUP( cppunit FILES 
+if(WIN32)
+SET( CPPUNIT_SRCS
 	../contrib/cppunit-1.12.1/src/cppunit/AdditionalMessage.cpp
 	../contrib/cppunit-1.12.1/src/cppunit/AdditionalMessage.cpp
 	../contrib/cppunit-1.12.1/src/cppunit/Asserter.cpp
 	../contrib/cppunit-1.12.1/src/cppunit/Asserter.cpp
 	../contrib/cppunit-1.12.1/src/cppunit/BeOsDynamicLibraryManager.cpp
 	../contrib/cppunit-1.12.1/src/cppunit/BeOsDynamicLibraryManager.cpp
@@ -70,11 +71,12 @@ SOURCE_GROUP( cppunit FILES
 	../contrib/cppunit-1.12.1/src/cppunit/XmlOutputter.cpp
 	../contrib/cppunit-1.12.1/src/cppunit/XmlOutputter.cpp
 	../contrib/cppunit-1.12.1/src/cppunit/XmlOutputterHook.cpp
 	../contrib/cppunit-1.12.1/src/cppunit/XmlOutputterHook.cpp
 )
 )
+SOURCE_GROUP(cppunit FILES  ${CPPUNIT_SRCS})
+else()
+	find_library(CPPUNIT_LIBRARY cppunit)
+endif()
 
 
-SOURCE_GROUP( tests FILES 
-	unit/Main.cpp
-	unit/UnitTestPCH.cpp
-	unit/UnitTestPCH.h
+SET( TEST_SRCS
 	unit/utFindDegenerates.cpp
 	unit/utFindDegenerates.cpp
 	unit/utFindDegenerates.h
 	unit/utFindDegenerates.h
 	unit/utFindInvalidData.cpp
 	unit/utFindInvalidData.cpp
@@ -116,114 +118,21 @@ SOURCE_GROUP( tests FILES
 	unit/utVertexTriangleAdjacency.h
 	unit/utVertexTriangleAdjacency.h
 	unit/utNoBoostTest.cpp
 	unit/utNoBoostTest.cpp
 	unit/utNoBoostTest.h
 	unit/utNoBoostTest.h
+	unit/BoostWorkaround/tupletest.cpp	
 )
 )
 
 
+SOURCE_GROUP(tests FILES  ${TEST_SRCS})
+
+
 add_executable(  unit
 add_executable(  unit
 	unit/CCompilerTest.c
 	unit/CCompilerTest.c
 	unit/Main.cpp
 	unit/Main.cpp
 	unit/UnitTestPCH.cpp
 	unit/UnitTestPCH.cpp
 	unit/UnitTestPCH.h
 	unit/UnitTestPCH.h
-	unit/utFindDegenerates.cpp
-	unit/utFindDegenerates.h
-	unit/utFindInvalidData.cpp
-	unit/utFindInvalidData.h
-	unit/utFixInfacingNormals.cpp
-	unit/utGenNormals.cpp
-	unit/utGenNormals.h
-	unit/utImporter.cpp
-	unit/utImporter.h
-	unit/utImproveCacheLocality.cpp
-	unit/utJoinVertices.cpp
-	unit/utJoinVertices.h
-	unit/utLimitBoneWeights.cpp
-	unit/utLimitBoneWeights.h
-	unit/utMaterialSystem.cpp
-	unit/utMaterialSystem.h
-	unit/utPretransformVertices.cpp
-	unit/utPretransformVertices.h
-	unit/utRemoveComments.cpp
-	unit/utRemoveComments.h
-	unit/utRemoveComponent.cpp
-	unit/utRemoveComponent.h
-	unit/utRemoveRedundantMaterials.cpp
-	unit/utRemoveRedundantMaterials.h
-	unit/utScenePreprocessor.cpp
-	unit/utScenePreprocessor.h
-	unit/utSharedPPData.cpp
-	unit/utSharedPPData.h
-	unit/utSortByPType.cpp
-	unit/utSortByPType.h
-	unit/utSplitLargeMeshes.cpp
-	unit/utSplitLargeMeshes.h
-	unit/utTargetAnimation.cpp
-	unit/utTargetAnimation.h
-	unit/utTextureTransform.cpp
-	unit/utTriangulate.cpp
-	unit/utTriangulate.h
-	unit/utVertexTriangleAdjacency.cpp
-	unit/utVertexTriangleAdjacency.h
-	unit/utNoBoostTest.cpp
-	unit/utNoBoostTest.h
-	unit/BoostWorkaround/tupletest.cpp	
-	../contrib/cppunit-1.12.1/src/cppunit/AdditionalMessage.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/Asserter.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/BeOsDynamicLibraryManager.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/BriefTestProgressListener.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/CompilerOutputter.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/DefaultProtector.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/DefaultProtector.h
-	../contrib/cppunit-1.12.1/src/cppunit/DllMain.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/DynamicLibraryManager.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/DynamicLibraryManagerException.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/Exception.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/Message.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/PlugInManager.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/PlugInParameters.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/Protector.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/ProtectorChain.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/ProtectorChain.h
-	../contrib/cppunit-1.12.1/src/cppunit/ProtectorContext.h
-	../contrib/cppunit-1.12.1/src/cppunit/RepeatedTest.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/ShlDynamicLibraryManager.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/SourceLine.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/StringTools.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/SynchronizedObject.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/Test.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestAssert.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestCase.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestCaseDecorator.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestComposite.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestDecorator.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestFactoryRegistry.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestFailure.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestLeaf.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestNamer.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestPath.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestPlugInDefaultImpl.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestResult.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestResultCollector.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestRunner.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestSetUp.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestSuccessListener.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestSuite.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TestSuiteBuilderContext.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TextOutputter.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TextTestProgressListener.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TextTestResult.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TextTestRunner.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/TypeInfoHelper.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/UnixDynamicLibraryManager.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/Win32DynamicLibraryManager.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/XmlDocument.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/XmlElement.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/XmlOutputter.cpp
-	../contrib/cppunit-1.12.1/src/cppunit/XmlOutputterHook.cpp
+	${TEST_SRCS}
+	${CPPUNIT_SRCS}
 )
 )
 
 
-IF( WIN32 )
-	FIND_PACKAGE(DirectX REQUIRED)
-ENDIF( WIN32 )
 SET_PROPERTY(TARGET assimp PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
 SET_PROPERTY(TARGET assimp PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
 
 
-# TODO: Port to non-Windows platforms.
-target_link_libraries ( unit assimp ${DirectX_LIBRARY} ${DirectX_D3DX9_LIBRARY} comctl32.lib Winmm.lib ) 
+target_link_libraries ( unit assimp ${CPPUNIT_LIBRARY} )

+ 210 - 0
test/models/Collada/cube_xmlspecialchars.dae

@@ -0,0 +1,210 @@
+<?xml version="1.0"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+    <asset>
+        <contributor>
+            <author>alorino</author>
+            <authoring_tool>Maya 7.0 | ColladaMaya v2.01 Jun  9 2006 at 16:08:19 | FCollada v1.11</authoring_tool>
+            <comments>Collada Maya Export Options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=0;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;exportVertexColors=1;exportTangents=0;
+exportTexTangents=0;exportConstraints=0;exportPhysics=0;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+            <copyright>
+Copyright 2006 Sony Computer Entertainment Inc.
+Licensed under the SCEA Shared Source License, Version 1.0 (the
+&quot;License&quot;); you may not use this file except in compliance with the
+License. You may obtain a copy of the License at:
+http://research.scea.com/scea_shared_source_license.html 
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+</copyright>
+        </contributor>
+        <created>2006-06-21T21:23:22Z</created>
+        <modified>2006-06-21T21:23:22Z</modified>
+        <unit meter="0.01" name="centimeter"/>
+        <up_axis>Y_UP</up_axis>
+    </asset>
+    <library_cameras>
+        <camera id="PerspCamera" name="PerspCamera">
+            <optics>
+                <technique_common>
+                    <perspective>
+                        <yfov>37.8493</yfov>
+                        <aspect_ratio>1</aspect_ratio>
+                        <znear>10</znear>
+                        <zfar>1000</zfar>
+                    </perspective>
+                </technique_common>
+            </optics>
+        </camera>
+        <camera id="testCameraShape" name="testCameraShape">
+            <optics>
+                <technique_common>
+                    <perspective>
+                        <yfov>37.8501</yfov>
+                        <aspect_ratio>1</aspect_ratio>
+                        <znear>0.01</znear>
+                        <zfar>1000</zfar>
+                    </perspective>
+                </technique_common>
+            </optics>
+        </camera>
+    </library_cameras>
+    <library_lights>
+        <light id="light-lib" name="light">
+            <technique_common>
+                <point>
+                    <color>1 1 1</color>
+                    <constant_attenuation>1</constant_attenuation>
+                    <linear_attenuation>0</linear_attenuation>
+                    <quadratic_attenuation>0</quadratic_attenuation>
+                </point>
+            </technique_common>
+            <technique profile="MAX3D">
+                <intensity>1.000000</intensity>
+            </technique>
+        </light>
+        <light id="pointLightShape1-lib" name="pointLightShape1">
+            <technique_common>
+                <point>
+                    <color>1 1 1</color>
+                    <constant_attenuation>1</constant_attenuation>
+                    <linear_attenuation>0</linear_attenuation>
+                    <quadratic_attenuation>0</quadratic_attenuation>
+                </point>
+            </technique_common>
+        </light>
+    </library_lights>
+    <library_materials>
+        <material id="Blue" name="Blue">
+            <instance_effect url="#Blue-fx"/>
+        </material>
+    </library_materials>
+    <library_effects>
+        <effect id="Blue-fx">
+            <profile_COMMON>
+                <technique sid="common">
+                    <phong>
+                        <emission>
+                            <color>0 0 0 1</color>
+                        </emission>
+                        <ambient>
+                            <color>0 0 0 1</color>
+                        </ambient>
+                        <diffuse>
+                            <color>0.137255 0.403922 0.870588 1</color>
+                        </diffuse>
+                        <specular>
+                            <color>0.5 0.5 0.5 1</color>
+                        </specular>
+                        <shininess>
+                            <float>16</float>
+                        </shininess>
+                        <reflective>
+                            <color>0 0 0 1</color>
+                        </reflective>
+                        <reflectivity>
+                            <float>0.5</float>
+                        </reflectivity>
+                        <transparent>
+                            <color>0 0 0 1</color>
+                        </transparent>
+                        <transparency>
+                            <float>1</float>
+                        </transparency>
+                        <index_of_refraction>
+                            <float>0</float>
+                        </index_of_refraction>
+                    </phong>
+                </technique>
+            </profile_COMMON>
+        </effect>
+    </library_effects>
+    <library_geometries>
+        <geometry id="&quot;&amp;&lt;box-lib&gt;&amp;&quot;" name="&quot;&amp;&lt;box&gt;&amp;&quot;">
+            <mesh>
+                <source id="&quot;&amp;&lt;box-lib-positions&gt;&amp;&quot;" name="position">
+                    <float_array id="box-lib-positions-array" count="24">-50 50 50 50 50 50 -50 -50 50 50 -50 50 -50 50 -50 50 50 -50 -50 -50 -50 50 -50 -50</float_array>
+                    <technique_common>
+                        <accessor count="8" offset="0" source="#box-lib-positions-array" stride="3">
+                            <param name="X" type="float"></param>
+                            <param name="Y" type="float"></param>
+                            <param name="Z" type="float"></param>
+                        </accessor>
+                    </technique_common>
+                </source>
+                <source id="&quot;&amp;&lt;box-lib-normals&gt;&amp;&quot;" name="normal">
+                    <float_array id="box-lib-normals-array" count="72">0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 -1 0 0 -1 0 0 -1 0 0 -1</float_array>
+                    <technique_common>
+                        <accessor count="24" offset="0" source="#box-lib-normals-array" stride="3">
+                            <param name="X" type="float"></param>
+                            <param name="Y" type="float"></param>
+                            <param name="Z" type="float"></param>
+                        </accessor>
+                    </technique_common>
+                </source>
+                <vertices id="&quot;&amp;&lt;box-lib-vertices&gt;&amp;&quot;">
+                    <input semantic="POSITION" source="#&quot;&amp;&lt;box-lib-positions&gt;&amp;&quot;"/>
+                </vertices>
+                <polylist count="6" material="BlueSG">
+                    <input offset="0" semantic="VERTEX" source="#&quot;&amp;&lt;box-lib-vertices&gt;&amp;&quot;"/>
+                    <input offset="1" semantic="NORMAL" source="#&quot;&amp;&lt;box-lib-normals&gt;&amp;&quot;"/>
+                    <vcount>4 4 4 4 4 4</vcount>
+                    <p>0 0 2 1 3 2 1 3 0 4 1 5 5 6 4 7 6 8 7 9 3 10 2 11 0 12 4 13 6 14 2 15 3 16 7 17 5 18 1 19 5 20 7 21 6 22 4 23</p>
+                </polylist>
+            </mesh>
+        </geometry>
+    </library_geometries>
+    <library_visual_scenes>
+        <visual_scene id="&quot;&amp;&lt;VisualSceneNode&gt;&amp;&quot;" name="untitled">
+            <node id="Camera" name="Camera">
+                <translate sid="translate">-427.749 333.855 655.017</translate>
+                <rotate sid="rotateY">0 1 0 -33</rotate>
+                <rotate sid="rotateX">1 0 0 -22.1954</rotate>
+                <rotate sid="rotateZ">0 0 1 0</rotate>
+                <instance_camera url="#PerspCamera"/>
+            </node>
+            <node id="Light" name="Light">
+                <translate sid="translate">-500 1000 400</translate>
+                <rotate sid="rotateZ">0 0 1 0</rotate>
+                <rotate sid="rotateY">0 1 0 0</rotate>
+                <rotate sid="rotateX">1 0 0 0</rotate>
+                <instance_light url="#light-lib"/>
+            </node>
+            <node id="Box" name="&quot;&amp;&lt;Box&gt;&amp;&quot;">
+                <rotate sid="rotateZ">0 0 1 0</rotate>
+                <rotate sid="rotateY">0 1 0 0</rotate>
+                <rotate sid="rotateX">1 0 0 0</rotate>
+                <instance_geometry url="#&quot;&amp;&lt;box-lib&gt;&amp;&quot;">
+                    <bind_material>
+                        <technique_common>
+                            <instance_material symbol="BlueSG" target="#Blue"/>
+                        </technique_common>
+                    </bind_material>
+                </instance_geometry>
+            </node>
+            <node id="testCamera" name="testCamera">
+                <translate sid="translate">-427.749 333.855 655.017</translate>
+                <rotate sid="rotateY">0 1 0 -33</rotate>
+                <rotate sid="rotateX">1 0 0 -22.1954</rotate>
+                <rotate sid="rotateZ">0 0 1 0</rotate>
+                <instance_camera url="#testCameraShape"/>
+            </node>
+            <node id="pointLight1" name="pointLight1">
+                <translate sid="translate">3 4 10</translate>
+                <rotate sid="rotateZ">0 0 1 0</rotate>
+                <rotate sid="rotateY">0 1 0 0</rotate>
+                <rotate sid="rotateX">1 0 0 0</rotate>
+                <instance_light url="#pointLightShape1-lib"/>
+            </node>
+        </visual_scene>
+    </library_visual_scenes>
+    <scene>
+        <instance_visual_scene url="#&quot;&amp;&lt;VisualSceneNode&gt;&amp;&quot;"/>
+    </scene>
+</COLLADA>

+ 1 - 1
test/models/OBJ/empty_mat.mtl

@@ -4,7 +4,7 @@ newmtl
 Ns 0
 Ns 0
 Ka 0.000000 0.000000 0.000000
 Ka 0.000000 0.000000 0.000000
 Kd 0.8 0.8 0.8
 Kd 0.8 0.8 0.8
-Ks 0.8 0.8 0.8
+Ks 0
 d 1
 d 1
 illum 2
 illum 2
 
 

+ 11 - 0
test/models/OBJ/multiple_spaces.obj

@@ -0,0 +1,11 @@
+v   1.0 2.0 3.0   
+v 2.0   3.0 1.0
+v 3.0 1.0   2.0
+v   1.0    2.0    3.0
+
+vt   1.0 2.0 3.0   
+vt 2.0   3.0 1.0
+vt 3.0 1.0   2.0
+vt   1.0    2.0    3.0
+
+f 1  2   3    

+ 23 - 0
test/models/OBJ/number_formats.obj

@@ -0,0 +1,23 @@
+v 0 0 0
+
+v 1 2. 3.0
+v +1 +2. +3.0
+v -1 -2. -3.0
+
+v 1e2 2.e1 3.1e2
+v +1e2 +2.e1 +3.1e2
+v -1e2 -2.e1 -3.1e2
+
+v 1e+2 2.e+1 3.1+e2
+v +1e+2 +2.e+1 +3.1+e2
+v -1e+2 -2.e+1 -3.1+e2
+
+v 1e-2 2.e-1 3.1-e2
+v +1e-2 +2.e-1 +3.1-e2
+v -1e-2 -2.e-1 -3.1-e2
+
+v 1e10 2.e01 3.1e10
+
+v 1E2 2.E1 3.1E2
+
+f 1 2 4

+ 1 - 1
test/unit/CCompilerTest.c

@@ -1,5 +1,5 @@
 
 
-// This is just a small test to check whether Assimp's API compiles from C
+/* This is just a small test to check whether Assimp's API compiles from C */
 
 
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>
 #include <assimp/scene.h>
 #include <assimp/scene.h>

+ 3 - 4
test/unit/Main.cpp

@@ -26,9 +26,8 @@ int main (int argc, char* argv[])
 
 
 	// .. and C. They should smoothly work together
 	// .. and C. They should smoothly work together
 	aiEnableVerboseLogging(AI_TRUE);
 	aiEnableVerboseLogging(AI_TRUE);
-	aiAttachLogStream(&aiGetPredefinedLogStream(
-		aiDefaultLogStream_FILE,
-		"AssimpLog_C.txt"));
+	aiLogStream logstream= aiGetPredefinedLogStream(aiDefaultLogStream_FILE, "AssimpLog_C.txt");
+	aiAttachLogStream(&logstream);
 
 
 
 
 	// ............................................................................
 	// ............................................................................
@@ -66,4 +65,4 @@ int main (int argc, char* argv[])
 
 
     // Rueckmeldung, ob Tests erfolgreich waren
     // Rueckmeldung, ob Tests erfolgreich waren
     return collectedresults.wasSuccessful () ? 0 : 1;
     return collectedresults.wasSuccessful () ? 0 : 1;
-}
+}

+ 5 - 5
test/unit/utImporter.cpp

@@ -72,7 +72,7 @@ static const aiImporterDesc desc = {
 
 
 
 
 bool TestPlugin :: CanRead( const std::string& pFile, 
 bool TestPlugin :: CanRead( const std::string& pFile, 
-	IOSystem* pIOHandler, bool test) const
+	IOSystem* /*pIOHandler*/, bool /*test*/) const
 {
 {
 	std::string::size_type pos = pFile.find_last_of('.');
 	std::string::size_type pos = pFile.find_last_of('.');
 	// no file extension - can't read
 	// no file extension - can't read
@@ -90,8 +90,8 @@ const aiImporterDesc* TestPlugin :: GetInfo() const
 	return & desc;
 	return & desc;
 }
 }
 
 
-void TestPlugin :: InternReadFile( const std::string& pFile, 
-	aiScene* pScene, IOSystem* pIOHandler)
+void TestPlugin :: InternReadFile( const std::string& /*pFile*/,
+	aiScene* /*pScene*/, IOSystem* /*pIOHandler*/)
 {
 {
 	throw DeadlyImportError(AIUT_DEF_ERROR_TEXT);
 	throw DeadlyImportError(AIUT_DEF_ERROR_TEXT);
 }
 }
@@ -208,11 +208,11 @@ void  ImporterTest :: testMultipleReads (void)
 
 
 	CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/test.x",flags));
 	CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/test.x",flags));
 	//CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/dwarf.x",flags)); # is in nonbsd
 	//CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/dwarf.x",flags)); # is in nonbsd
-	CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/Testwuson.x",flags));
+	CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/Testwuson.X",flags));
 	CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/anim_test.x",flags));
 	CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/anim_test.x",flags));
 	//CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/dwarf.x",flags)); # is in nonbsd
 	//CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/dwarf.x",flags)); # is in nonbsd
 
 
 	CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/anim_test.x",flags));
 	CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/anim_test.x",flags));
-	CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/bcn_epileptic.x",flags));
+	CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/BCN_Epileptic.X",flags));
 	//CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/dwarf.x",flags)); # is in nonbsd
 	//CPPUNIT_ASSERT(pImp->ReadFile("../../test/models/X/dwarf.x",flags)); # is in nonbsd
 }
 }

+ 2 - 2
test/unit/utNoBoostTest.h

@@ -4,7 +4,7 @@
 namespace noboost {
 namespace noboost {
 
 
 #define ASSIMP_FORCE_NOBOOST
 #define ASSIMP_FORCE_NOBOOST
-#include "..\..\code\BoostWorkaround\boost\format.hpp"
+#include "../../code/BoostWorkaround/boost/format.hpp"
 	using boost::format;
 	using boost::format;
 	using boost::str;
 	using boost::str;
 
 
@@ -34,4 +34,4 @@ class NoBoostTest : public CPPUNIT_NS :: TestFixture
 	
 	
 };
 };
 
 
-#endif 
+#endif

+ 2 - 2
test/unit/utRemoveComments.cpp

@@ -43,7 +43,7 @@ void RemoveCommentsTest :: testSingleLineComments (void)
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void RemoveCommentsTest :: testMultiLineComments (void)
 void RemoveCommentsTest :: testMultiLineComments (void)
 {
 {
-	char* szTest = 
+	const char* szTest = 
 		"/* comment to be removed */\n"
 		"/* comment to be removed */\n"
 		"valid text /* \n "
 		"valid text /* \n "
 		" comment across multiple lines */"
 		" comment across multiple lines */"
@@ -62,4 +62,4 @@ void RemoveCommentsTest :: testMultiLineComments (void)
 	CPPUNIT_ASSERT(0 == ::strcmp(szTest2,szTestResult));
 	CPPUNIT_ASSERT(0 == ::strcmp(szTest2,szTestResult));
 
 
 	delete[] szTest2;
 	delete[] szTest2;
-}
+}

+ 1 - 1
tools/assimp_cmd/WriteDumb.cpp

@@ -656,7 +656,7 @@ uint32_t WriteBinaryScene(const aiScene* scene)
 // -----------------------------------------------------------------------------------
 // -----------------------------------------------------------------------------------
 // Write a binary model dump
 // Write a binary model dump
 void WriteBinaryDump(const aiScene* scene, FILE* _out, const char* src, const char* cmd, 
 void WriteBinaryDump(const aiScene* scene, FILE* _out, const char* src, const char* cmd, 
-	bool _shortened, bool compressed, ImportData& imp)
+	bool _shortened, bool compressed, ImportData& /*imp*/)
 {
 {
 	out = _out;
 	out = _out;
 	shortened = _shortened;
 	shortened = _shortened;

+ 4 - 5
tools/assimp_view/MessageProc.cpp

@@ -1030,18 +1030,17 @@ void PopulateExportMenu()
 //-------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------
 void DoExport(size_t formatId)
 void DoExport(size_t formatId)
 {
 {
-	if (!g_szFileName) {
+	if (!g_szFileName[0]) {
+		MessageBox(g_hDlg, "No model loaded", "Export", MB_ICONERROR);
 		return;
 		return;
 	}
 	}
-
 	Exporter exp;
 	Exporter exp;
 	const aiExportFormatDesc* const e = exp.GetExportFormatDescription(formatId);
 	const aiExportFormatDesc* const e = exp.GetExportFormatDescription(formatId);
 	ai_assert(e);
 	ai_assert(e);
 
 
 	char szFileName[MAX_PATH*2];
 	char szFileName[MAX_PATH*2];
-	DWORD dwTemp;
-	if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"ModelExportDest",NULL,NULL,(BYTE*)szFileName,&dwTemp)) {
-		ai_assert(dwTemp == MAX_PATH + 1);
+	DWORD dwTemp = sizeof(szFileName);
+	if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"ModelExportDest",NULL,NULL,(BYTE*)szFileName, &dwTemp)) {
 		ai_assert(strlen(szFileName) <= MAX_PATH);
 		ai_assert(strlen(szFileName) <= MAX_PATH);
 
 
 		// invent a nice default file name 
 		// invent a nice default file name