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

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

Léo Terziman 11 жил өмнө
parent
commit
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:
-  - sudo apt-get install cmake
+  - sudo apt-get install cmake libcppunit-dev
 
 env:
   - TRAVIS_NO_EXPORT=YES
@@ -13,7 +13,9 @@ compiler:
   - gcc
   - 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." )
 SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH
 	"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")
 
@@ -102,8 +101,9 @@ ENDIF()
 
 # Globally enable Boost resp. the Boost workaround – it is also needed by the
 # 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."
+	ON
 )
 IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
 	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)
 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
@@ -186,8 +187,9 @@ ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "")
 MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
 
 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."
+	ON
 )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 	IF ( WIN32 )
@@ -196,8 +198,9 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 	ADD_SUBDIRECTORY( tools/assimp_cmd/ )
 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)."
+	OFF
 )
 
 IF ( ASSIMP_BUILD_SAMPLES)
@@ -207,19 +210,19 @@ IF ( ASSIMP_BUILD_SAMPLES)
 	ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
 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)
-	SET ( ASSIMP_INSTALL_PDB ON CACHE BOOL
+	option ( ASSIMP_INSTALL_PDB
 		"Install MSVC debug files."
+		ON
 	)
 ENDIF(MSVC)
 

+ 5 - 1
Readme.md

@@ -1,7 +1,7 @@
 Open Asset Import Library (assimp) 
 ========
 
-Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a 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)
 
@@ -46,6 +46,7 @@ The library provides importers for a lot of file formats, including:
 - Ogre Binary
 - Ogre XML
 - 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.
 
@@ -57,7 +58,10 @@ Exporters include:
 - STL
 - OBJ
 - PLY
+- X
+- 3DS
 - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
+- ASSBIN
 	
 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;
 };
 
-#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
-
 } // end of namespace Assimp
 
+#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
+
 #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());
 	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());
 	out->mName = obj->id.name+2;

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

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

+ 14 - 1
code/CMakeLists.txt

@@ -111,6 +111,7 @@ SET( Common_SRCS
 	MemoryIOWrapper.h
 	ParsingUtils.h
 	StreamReader.h
+	StreamWriter.h
 	StringComparison.h
 	SGSpatialSort.cpp
 	SGSpatialSort.h
@@ -143,6 +144,7 @@ SET( Common_SRCS
 	LogAux.h
 	Bitmap.cpp
 	Bitmap.h
+	XMLTools.h
 )
 SOURCE_GROUP(Common FILES ${Common_SRCS})
 
@@ -151,6 +153,8 @@ SET( 3DS_SRCS
 	3DSHelper.h
 	3DSLoader.cpp
 	3DSLoader.h
+	3DSExporter.h
+	3DSExporter.cpp
 )
 SOURCE_GROUP(3DS FILES ${3DS_SRCS})
 
@@ -168,6 +172,14 @@ SET( 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
 	B3DImporter.cpp
 	B3DImporter.h
@@ -612,7 +624,7 @@ SOURCE_GROUP( unzip FILES ${unzip_SRCS})
 
 # VC2010 fixes
 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 )
 		ADD_DEFINITIONS( -D_STDINT )
 	endif( VC10_STDINT_FIX )
@@ -643,6 +655,7 @@ SET( assimp_src
 	${3DS_SRCS}
 	${AC_SRCS}
 	${ASE_SRCS}
+	${ASSBIN_SRCS}
 	${B3D_SRCS}
 	${BVH_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
 	// of vertices and no vertices are shared between faces. Sadly I don't know any quick test to 
 	// 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;
 
 	// 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& origTang = pMesh->mTangents[a];
 		const aiVector3D& origBitang = pMesh->mBitangents[a];
-		closeVertices.clear();
+		closeVertices.resize( 0 );
 
 		// find all vertices close to that position
 		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 "fast_atof.h"
 #include "SceneCombiner.h" 
+#include "XMLTools.h"
 
 #include <ctime>
 #include <set>
@@ -93,6 +94,7 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p
 } // end of namespace Assimp
 
 
+
 // ------------------------------------------------------------------------------------------------
 // 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)
@@ -140,7 +142,7 @@ void ColladaExporter::WriteFile()
 	// useless Collada fu at the end, just in case we haven't had enough indirections, yet. 
 	mOutput << startstr << "<scene>" << endstr;
 	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();
 	mOutput << startstr << "</scene>" << endstr;
 	PopTag();
@@ -236,12 +238,12 @@ void ColladaExporter::WriteHeader()
 	if (!meta || !meta->Get("Author", value))		
 		mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr;
 	else		
-		mOutput << startstr << "<author>" << value.C_Str() << "</author>" << endstr;
+		mOutput << startstr << "<author>" << XMLEscape(value.C_Str()) << "</author>" << endstr;
 
 	if (!meta || !meta->Get("AuthoringTool", value))
 		mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr;
 	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 << "<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() )
   {
-    mOutput << startstr << "<image id=\"" << pNameAdd << "\">" << endstr;
+    mOutput << startstr << "<image id=\"" << XMLEscape(pNameAdd) << "\">" << endstr;
     PushTag(); 
     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 )
     {
       if( isalnum( *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' )
-        mOutput << *it;
+        imageUrlEncoded << *it;
       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;
     PopTag();
     mOutput << startstr << "</image>" << endstr;
@@ -371,7 +377,7 @@ void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std
     }
 	else
     {
-      mOutput << startstr << "<texture texture=\"" << pImageName << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
+      mOutput << startstr << "<texture texture=\"" << XMLEscape(pImageName) << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
     }
     PopTag();
     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( !pSurface.texture.empty() )
   {
-    mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-surface\">" << endstr;
+    mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-surface\">" << endstr;
     PushTag();
     mOutput << startstr << "<surface type=\"2D\">" << endstr;
     PushTag();
-    mOutput << startstr << "<init_from>" << pMatName << "-" << pTypeName << "-image</init_from>" << endstr;
+    mOutput << startstr << "<init_from>" << XMLEscape(pMatName) << "-" << pTypeName << "-image</init_from>" << endstr;
     PopTag();
     mOutput << startstr << "</surface>" << endstr;
     PopTag();
     mOutput << startstr << "</newparam>" << endstr;
 
-    mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-sampler\">" << endstr;
+    mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-sampler\">" << endstr;
     PushTag();
     mOutput << startstr << "<sampler2D>" << endstr;
     PushTag();
-    mOutput << startstr << "<source>" << pMatName << "-" << pTypeName << "-surface</source>" << endstr;
+    mOutput << startstr << "<source>" << XMLEscape(pMatName) << "-" << pTypeName << "-surface</source>" << endstr;
     PopTag();
     mOutput << startstr << "</sampler2D>" << endstr;
     PopTag();
@@ -439,7 +445,7 @@ void ColladaExporter::WriteMaterials()
       name = "mat";
     materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + name.C_Str();
     for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
-		// isalnum on MSVC asserts for code points in [0,255]. Thus prevent unwanted promotion
+		// 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.
       if( !isalnum( static_cast<uint8_t>(*it) ) ) {
         *it = '_';
@@ -510,7 +516,7 @@ void ColladaExporter::WriteMaterials()
     {
       const Material& mat = *it;
       // 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();
       mOutput << startstr << "<profile_COMMON>" << endstr;
       PushTag();
@@ -561,9 +567,9 @@ void ColladaExporter::WriteMaterials()
     for( std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++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();
-      mOutput << startstr << "<instance_effect url=\"#" << mat.name << "-fx\"/>" << endstr;
+      mOutput << startstr << "<instance_effect url=\"#" << XMLEscape(mat.name) << "-fx\"/>" << endstr;
       PopTag();
       mOutput << startstr << "</material>" << endstr;
     }
@@ -591,13 +597,14 @@ void ColladaExporter::WriteGeometryLibrary()
 void ColladaExporter::WriteGeometry( size_t 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 )
     return;
 
 	// opening tag
-	mOutput << startstr << "<geometry id=\"" << idstr << "\" name=\"" << idstr << "_name\" >" << endstr;
+	mOutput << startstr << "<geometry id=\"" << idstrEscaped << "\" name=\"" << idstrEscaped << "_name\" >" << endstr;
 	PushTag();
 
 	mOutput << startstr << "<mesh>" << endstr;
@@ -627,20 +634,20 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
 	}
 
 	// assemble vertex structure
-	mOutput << startstr << "<vertices id=\"" << idstr << "-vertices" << "\">" << endstr;
+	mOutput << startstr << "<vertices id=\"" << idstrEscaped << "-vertices" << "\">" << endstr;
 	PushTag();
-	mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstr << "-positions\" />" << endstr;
+	mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstrEscaped << "-positions\" />" << endstr;
 	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 )
 	{
 		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 )
 	{
 		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();
@@ -660,7 +667,7 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
 	{
 		mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr;
 		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>";
 		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;
 		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>";
 		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";
 
-	mOutput << startstr << "<source id=\"" << pIdString << "\" name=\"" << pIdString << "\">" << endstr;
+	mOutput << startstr << "<source id=\"" << XMLEscape(pIdString) << "\" name=\"" << XMLEscape(pIdString) << "\">" << endstr;
 	PushTag();
 
 	// source array
-	mOutput << startstr << "<float_array id=\"" << arrayId << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
+	mOutput << startstr << "<float_array id=\"" << XMLEscape(arrayId) << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
 	PushTag();
 
 	if( pType == FloatType_TexCoord2 )
@@ -804,11 +811,11 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
 // Writes the scene library
 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;
 	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();
 
 	// start recursive write at the root node
@@ -833,7 +840,8 @@ void ColladaExporter::WriteNode(aiNode* pNode)
 		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();
 
 	// 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 )
 		continue;
 
-		mOutput << startstr << "<instance_geometry url=\"#" << GetMeshId( pNode->mMeshes[a]) << "\">" << endstr;
+		mOutput << startstr << "<instance_geometry url=\"#" << XMLEscape(GetMeshId( pNode->mMeshes[a])) << "\">" << endstr;
 		PushTag();
 	mOutput << startstr << "<bind_material>" << endstr;
 	PushTag();
 	mOutput << startstr << "<technique_common>" << endstr;
 	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();
 	mOutput << startstr << "</technique_common>" << endstr;
 	PopTag();

+ 19 - 9
code/ConvertToLHProcess.cpp

@@ -57,12 +57,15 @@ using namespace Assimp;
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 MakeLeftHandedProcess::MakeLeftHandedProcess()
-{}
+: BaseProcess() {
+    // empty
+}
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
-MakeLeftHandedProcess::~MakeLeftHandedProcess()
-{}
+MakeLeftHandedProcess::~MakeLeftHandedProcess() {
+    // empty
+}
 
 // ------------------------------------------------------------------------------------------------
 // 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...
 
 	// 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;
 	for (unsigned int a = 0; a < mat->mNumProperties;++a)	{
 		aiMaterialProperty* prop = mat->mProperties[a];
+        if( !prop ) {
+            DefaultLogger::get()->debug( "Property is null" );
+            continue;
+        }
 
 		// UV transformation key?
 		if (!::strcmp( prop->mKey.data, "$tex.uvtrafo"))	{
@@ -263,11 +271,13 @@ void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
 {
 	// mirror texture y coordinate
 	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)	{
 		// 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
 		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 ExportSceneSTLBinary(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
@@ -90,7 +91,7 @@ Exporter::ExportFormatEntry gExporters[] =
 
 #ifndef ASSIMP_BUILD_NO_FXILE_EXPORTER
 	Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
-	aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
+		aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
 #endif
 
 #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
@@ -113,9 +114,14 @@ Exporter::ExportFormatEntry gExporters[] =
 	),
 #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]))

+ 1 - 1
code/FBXAnimation.cpp

@@ -59,7 +59,7 @@ namespace FBX {
 	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)
 {
 	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>& index_out_indices,
 		std::vector<size_t>& count_out_indices,
@@ -2347,7 +2347,7 @@ private:
 
 	// ------------------------------------------------------------------------------------------------
 	aiNodeAnim* GenerateScalingNodeAnim(const std::string& name, 
-		const Model& target, 
+		const Model& /*target*/,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const LayerMap& layer_map,
 		double& max_time,
@@ -2378,7 +2378,7 @@ private:
 
 	// ------------------------------------------------------------------------------------------------
 	aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name, 
-		const Model& target, 
+		const Model& /*target*/,
 		const std::vector<const AnimationCurveNode*>& curves,
 		const LayerMap& layer_map,
 		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& minTime)
 	{
@@ -2851,7 +2851,7 @@ private:
 
 	// ------------------------------------------------------------------------------------------------
 	void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, 
-		const LayerMap& layers,
+		const LayerMap& /*layers*/,
 		double& maxTime,
 		double& minTime)
 	{
@@ -2869,7 +2869,7 @@ private:
 
 	// ------------------------------------------------------------------------------------------------
 	void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, 
-		const LayerMap& layers, 
+		const LayerMap& /*layers*/,
 		double& maxTime,
 		double& minTime,
 		Model::RotOrder order)

+ 10 - 5
code/FBXDocument.cpp

@@ -253,8 +253,8 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
 : settings(settings)
 , 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;
 	}
 
@@ -263,7 +263,7 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
 
 	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,
 	// though, since this may require valid connections.
 	ReadObjects();
@@ -277,13 +277,18 @@ Document::~Document()
 	BOOST_FOREACH(ObjectMap::value_type& v, objects) {
 		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()
 {
-	// read ID objects from "Objects" section
+	// Read ID objects from "Objects" section
 	const Scope& sc = parser.GetRootScope();
 	const Element* const ehead = sc["FBXHeaderExtension"];
 	if(!ehead || !ehead->Compound()) {
@@ -293,7 +298,7 @@ void Document::ReadHeader()
 	const Scope& shead = *ehead->Compound();
 	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
 	if(fbxVersion < 7100) {
 		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:
 
 	/** Get the Skin attached to this geometry or NULL */
-	const Skin* const DeformerSkin() const {
+	const Skin* DeformerSkin() const {
 		return skin;
 	}
 
@@ -1096,7 +1096,7 @@ public:
 		return transformLink;
 	}
 
-	const Model* const TargetNode() const {
+	const Model* TargetNode() const {
 		return node;
 	}
 

+ 2 - 0
code/FBXImporter.cpp

@@ -179,6 +179,8 @@ void FBXImporter::InternReadFile( const std::string& pFile,
 
 		// convert the FBX DOM to aiScene
 		ConvertToAssimpScene(pScene,doc);
+
+		std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
 	}
 	catch(std::exception&) {
 		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)
 ,texture(0)
 ,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& ReferenceInformationType)
 {
+	const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
 	ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
-		"Tangent",
+		str,
 		"TangentIndex",
 		vertices.size(),
 		mapping_counts,
@@ -481,8 +482,9 @@ void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_ou
 	const std::string& MappingInformationType,
 	const std::string& ReferenceInformationType)
 {
+	const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal";
 	ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
-		"Binormal",
+		str,
 		"BinormalIndex",
 		vertices.size(),
 		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) {
 			ParseWarning(message,element->KeyToken());
@@ -103,7 +103,7 @@ namespace {
 			DefaultLogger::get()->warn("FBX-Parser: " + message);
 		}
 	}
-
+*/
 	// ------------------------------------------------------------------------------------------------
 	void ParseError(const std::string& message, TokenPtr token)
 	{
@@ -113,6 +113,18 @@ namespace {
 		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 {
@@ -275,9 +287,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
 			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);
 		return id;
 	}
@@ -316,8 +326,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
 			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);
 		return static_cast<size_t>(id);
 	}
@@ -364,24 +373,10 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
 		}
 
 		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 {
-			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;
 		}
 
-		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);
 		return static_cast<int>(ival);
 	}
@@ -453,10 +447,8 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
 			return "";
 		}
 
-		ai_assert(t.end() - data >= 5);
-
 		// 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_assert(t.end() - data == 5 + len);
@@ -494,7 +486,7 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
 	type = *data;
 
 	// 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);
 
 	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)
 void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end, 
 	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);
 	data += 4;
 
 	// 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);
 	data += 4;
 

+ 1 - 1
code/FBXProperties.cpp

@@ -105,7 +105,7 @@ Property* ReadTypedProperty(const Element& element)
 			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 NULL;

+ 2 - 4
code/FBXProperties.h

@@ -143,8 +143,7 @@ private:
 // ------------------------------------------------------------------------------------------------
 template <typename T>
 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);
 	if(!prop) {
@@ -164,8 +163,7 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name,
 // ------------------------------------------------------------------------------------------------
 template <typename T>
 inline T PropertyGet(const PropertyTable& in, const std::string& name, 
-	bool& result, 
-	bool ignoreTemplate = false)
+	bool& result)
 {
 	const Property* const prop = in.Get(name);
 	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
 					static const float uvEpsilon = 10e-4f;
-
 					{
 						unsigned int i, end = orig->GetNumUVChannels();
 						for(i = 0; i < end; ++i) {
@@ -260,7 +259,7 @@ void FindInstancesProcess::Execute( aiScene* pScene)
 					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());
 
 			// write to log

+ 1 - 1
code/GenVertexNormalsProcess.cpp

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

+ 1 - 1
code/GenVertexNormalsProcess.h

@@ -53,7 +53,7 @@ namespace Assimp {
 // ---------------------------------------------------------------------------
 /** The GenFaceNormalsProcess computes vertex normals for all vertizes
 */
-class ASSIMP_API_WINONLY GenVertexNormalsProcess : public BaseProcess
+class ASSIMP_API GenVertexNormalsProcess : public BaseProcess
 {
 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, 
 									   const TempMesh& first_operand, 
-									   ConversionData& conv)
+									   ConversionData& /*conv*/)
 {
 	ai_assert(hs != NULL);
 

+ 2 - 2
code/IFCOpenings.cpp

@@ -259,7 +259,7 @@ BoundingBox GetBoundingBox(const ClipperLib::Polygon& poly)
 
 // ------------------------------------------------------------------------------------------------
 void InsertWindowContours(const ContourVector& contours,
-	const std::vector<TempOpening>& openings,
+	const std::vector<TempOpening>& /*openings*/,
 	TempMesh& curmesh)
 {
 	// 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 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>()) {
 		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 {
 
 // -----------------------------------------------------------------------------------------------------------
-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;
 }
@@ -1253,7 +1253,7 @@ template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST&
 	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;
 	return base;
@@ -1715,7 +1715,7 @@ template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, I
 	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;
 	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
 		DefaultLogger::get()->info("Found a matching importer for this file format");
-		pimpl->mProgressHandler->Update();
+		pimpl->mProgressHandler->UpdateFileRead( 0, fileSize );
 
 		if (profiler) {
 			profiler->BeginRegion("import");
 		}
 
 		pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
-		pimpl->mProgressHandler->Update();
+		pimpl->mProgressHandler->UpdateFileRead( fileSize, fileSize );
 
 		if (profiler) {
 			profiler->EndRegion("import");
@@ -678,7 +687,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
 			ScenePreprocessor pre(pimpl->mScene);
 			pre.ProcessScene();
 
-			pimpl->mProgressHandler->Update();
 			if (profiler) {
 				profiler->EndRegion("preprocess");
 			}
@@ -768,6 +776,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
 	for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)	{
 
 		BaseProcess* process = pimpl->mPostProcessingSteps[a];
+		pimpl->mProgressHandler->UpdatePostProcess( a, pimpl->mPostProcessingSteps.size() );
 		if( process->IsActive( pFlags))	{
 
 			if (profiler) {
@@ -775,7 +784,6 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
 			}
 
 			process->ExecuteOnScene	( this );
-			pimpl->mProgressHandler->Update();
 
 			if (profiler) {
 				profiler->EndRegion("postprocess");
@@ -803,6 +811,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
 		}
 #endif // ! DEBUG
 	}
+	pimpl->mProgressHandler->UpdatePostProcess( pimpl->mPostProcessingSteps.size(), pimpl->mPostProcessingSteps.size() );
 
 	// update private scene flags
   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
 #   include "FBXImporter.h"
 #endif 
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+#   include "AssbinLoader.h"
+#endif 
 
 namespace Assimp {
 
@@ -291,6 +294,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
 #if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
 	out.push_back( new FBXImporter() );
 #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
  * 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:
 

+ 10 - 17
code/LimitBoneWeightsProcess.cpp

@@ -131,10 +131,15 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
 
 		// and renormalize the weights
 		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)	{
@@ -157,18 +162,6 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
 			const std::vector<aiVertexWeight>& bw = boneWeights[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() )
 			{
 				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
 			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));
 		}
 

+ 20 - 14
code/ObjExporter.cpp

@@ -75,6 +75,7 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
 
 } // end of namespace Assimp
 
+static const std::string MaterialExt = ".mtl";
 
 // ------------------------------------------------------------------------------------------------
 ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
@@ -107,7 +108,7 @@ std::string ObjExporter :: GetMaterialLibName()
 // ------------------------------------------------------------------------------------------------
 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);
 
@@ -144,16 +145,16 @@ void ObjExporter :: WriteMaterialFile()
 
 		aiColor4D 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)) {
-			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)) {
-			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)) {
-			mOutputMat << "ke " << c.r << " " << c.g << " " << c.b << endl;
+			mOutputMat << "Ke " << c.r << " " << c.g << " " << c.b << endl;
 		}
 
 		float o;
@@ -170,16 +171,19 @@ void ObjExporter :: WriteMaterialFile()
 
 		aiString 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)) {
-			mOutputMat << "map_ka " << s.data << endl;
+			mOutputMat << "map_Ka " << s.data << endl;
 		}
 		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)) {
-			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)) {
 			// 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());
 	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;
 
@@ -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 SpecularTexture     = "map_ks";
 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 BumpTexture2        = "map_Bump";
 static const std::string BumpTexture3        = "bump";
@@ -128,6 +129,7 @@ void ObjFileMtlImporter::load()
 	{
 		switch (*m_DataIt)
 		{
+		case 'k':
 		case 'K':
 			{
 				++m_DataIt;
@@ -221,15 +223,17 @@ void ObjFileMtlImporter::getColorRGBA( aiColor3D *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 );
 	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
 		out = & m_pModel->m_pCurrentMaterial->textureOpacity;
 		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
 		out = & m_pModel->m_pCurrentMaterial->textureEmissive;
 		clampIndex = ObjFile::Material::TextureEmissiveType;

+ 28 - 21
code/ObjFileParser.cpp

@@ -113,8 +113,8 @@ void ObjFileParser::parseFile()
 					getVector3(m_pModel->m_Vertices);
 				} else if (*m_DataIt == 't') {
 					// 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') {
 					// Read in normal vector definition
 					++m_DataIt;
@@ -233,12 +233,13 @@ void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
 // -------------------------------------------------------------------
 void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
     size_t numComponents( 0 );
-    DataArrayIt tmp( m_DataIt );
+    const char* tmp( &m_DataIt[0] );
     while( !IsLineEnd( *tmp ) ) {
-        if( *tmp == ' ' ) {
-            ++numComponents;
+        if ( !SkipSpaces( &tmp ) ) {
+            break;
         }
-        tmp++;
+        SkipToken( tmp );
+        ++numComponents;
     }
     float x, y, z;
     if( 2 == numComponents ) {
@@ -550,13 +551,15 @@ void ObjFileParser::getNewMaterial()
 {
 	m_DataIt = getNextToken<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);
 	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 );
 	if ( it == m_pModel->m_MaterialMap.end() )
 	{
@@ -581,8 +584,9 @@ void ObjFileParser::getNewMaterial()
 int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
 {
 	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)
 	{
 		if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
@@ -601,8 +605,9 @@ void ObjFileParser::getGroupName()
 	std::string 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
 	if ( m_pModel->m_strActiveGroup != strGroupName )
@@ -653,11 +658,13 @@ void ObjFileParser::getGroupNumberAndResolution()
 void ObjFileParser::getObjectName()
 {
 	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
-	if (m_DataIt == m_DataItEnd)
-		return;
+    if( m_DataIt == m_DataItEnd ) {
+        return;
+    }
 	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));
 	if (!strObjectName.empty()) 
@@ -678,8 +685,9 @@ void ObjFileParser::getObjectName()
 		}
 
 		// 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 );
 }
@@ -694,7 +702,6 @@ void ObjFileParser::createObject(const std::string &strObjectName)
 	m_pModel->m_pCurrent->m_strObjName = strObjectName;
 	m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
 	
-
 	createMesh();
 
 	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
 
-#endif
+#endif // OBJ_TOOLS_H_INC

+ 5 - 6
code/OgreBinarySerializer.cpp

@@ -376,14 +376,14 @@ void OgreBinarySerializer::ReadMeshSkeletonLink(Mesh *mesh)
 	mesh->skeletonRef = ReadLine();
 }
 
-void OgreBinarySerializer::ReadMeshBounds(Mesh *mesh)
+void OgreBinarySerializer::ReadMeshBounds(Mesh * /*mesh*/)
 {
 	// Skip bounds, not compatible with Assimp.
 	// 2x float vec3 + 1x float sphere radius
 	SkipBytes(sizeof(float) * 7);
 }
 
-void OgreBinarySerializer::ReadMeshExtremes(Mesh *mesh)
+void OgreBinarySerializer::ReadMeshExtremes(Mesh * /*mesh*/)
 {
 	// Skip extremes, not compatible with Assimp.
 	size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE; 
@@ -534,7 +534,6 @@ void OgreBinarySerializer::ReadSubMeshTextureAlias(SubMesh *submesh)
 void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh)
 {
 	uint16_t id = 0;
-	uint16_t submeshIndex = 0;
 
 	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");
 }
 
-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.
 
@@ -1055,7 +1054,7 @@ void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton)
 	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>();
 	Bone *bone = dest->parentSkeleton->BoneById(boneId);
@@ -1097,7 +1096,7 @@ void OgreBinarySerializer::ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *d
 	dest->transformKeyFrames.push_back(keyframe);
 }
 
-void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton *skeleton)
+void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton * /*skeleton*/)
 {
 	// Skip bounds, not compatible with Assimp.
 	ReadLine(); // skeleton name

+ 6 - 2
code/OgreBinarySerializer.h

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

+ 13 - 11
code/OgreStructs.cpp

@@ -404,9 +404,9 @@ size_t IndexData::FaceSize() const
 // 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() :
-	sharedVertexData(0),
-	skeleton(0)
+	skeleton(0),
+	sharedVertexData(0)
 {
 }
 
@@ -797,8 +797,8 @@ void MeshXml::ConvertToAssimpScene(aiScene* dest)
 // 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(Skeleton *parent) :
+	parentMesh(NULL),
 	parentSkeleton(parent),
-	parentMesh(0),
 	length(0.0f),
 	baseTime(-1.0f)
 {
@@ -963,6 +963,8 @@ aiAnimation *Animation::ConvertToAssimpAnimation()
 // Skeleton
 
 Skeleton::Skeleton() :
+	bones(),
+	animations(),
 	blendMode(ANIMBLEND_AVERAGE)
 {
 }
@@ -1103,7 +1105,7 @@ aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode)
 	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();
 	bone->mName = name;
@@ -1122,8 +1124,8 @@ aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWe
 // 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
 
 #include "StringComparison.h"
+
 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>
@@ -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;
 }
+
 // ---------------------------------------------------------------------------------
 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>
 AI_FORCE_INLINE bool IsUpper( char_t in)
 {
 	return (in >= (char_t)'A' && in <= (char_t)'Z');
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 AI_FORCE_INLINE bool IsLower( char_t in)
 {
 	return (in >= (char_t)'a' && in <= (char_t)'z');
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 AI_FORCE_INLINE bool IsSpace( char_t in)
 {
 	return (in == (char_t)' ' || in == (char_t)'\t');
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 AI_FORCE_INLINE bool IsLineEnd( char_t in)
 {
 	return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0');
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in)
 {
 	return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 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;
 	return !IsLineEnd<char_t>(*in);
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 AI_FORCE_INLINE bool SkipSpaces( const char_t** inout)
 {
 	return SkipSpaces<char_t>(*inout,inout);
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 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
-	while (*in == (char_t)'\r' || *in == (char_t)'\n')in++;
+    while( *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
+        ++in;
+    }
 	*out = in;
 	return *in != (char_t)'\0';
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 AI_FORCE_INLINE bool SkipLine( const char_t** inout)
 {
 	return SkipLine<char_t>(*inout,inout);
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 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;
 	return *in != '\0';
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout)
 {
 	return SkipSpacesAndLineEnd<char_t>(*inout,inout);
 }
+
 // ---------------------------------------------------------------------------------
 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* 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';
 
-	while (IsLineEnd( *buffer ) && '\0' != *buffer)++buffer;
-	return true;
+    while( IsLineEnd( *buffer ) && '\0' != *buffer ) {
+        ++buffer;
+    }
+
+    return true;
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 AI_FORCE_INLINE bool IsNumeric( char_t in)
 {
 	return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in;
 }
+
 // ---------------------------------------------------------------------------------
 template <class char_t>
 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;
 		return true;
 	}
+
 	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)
 {
-	if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len]))
-	{
+	if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
 		in += len+1;
 		return true;
 	}
@@ -206,5 +235,9 @@ AI_FORCE_INLINE std::string GetNextToken(const char*& in)
 	while (!IsSpaceOrNewLine(*in))++in;
 	return std::string(cur,(size_t)(in-cur));
 }
+
+// ---------------------------------------------------------------------------------
+
 } // ! namespace Assimp
+
 #endif // ! AI_PARSING_UTILS_H_INC

+ 2 - 0
code/Q3BSPFileImporter.cpp

@@ -73,11 +73,13 @@ static const aiImporterDesc desc = {
 
 namespace Assimp {
 
+/*
 static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) {
     supportedExtensions.push_back( ".jpg" );
     supportedExtensions.push_back( ".png" );
     supportedExtensions.push_back( ".tga" );
 }
+*/
     
 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);
 }
 
-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;
 
 	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;
 
 	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;
 
 	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;
 
 	aiOrigin assimp_origin;
@@ -115,7 +115,7 @@ int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
 	return 0;
 }
 
-int IOSystem2Unzip::testerror(voidpf opaque, voidpf stream) {
+int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
 	return 0;
 }
 

+ 2 - 2
code/STLLoader.cpp

@@ -348,8 +348,8 @@ bool STLImporter::LoadBinaryFile()
 	bool bIsMaterialise = false;
 
 	// 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)	{
 
 		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__
 
 #include <math.h>
-#include <limits.h>
+#include <limits>
+
+#include "StringComparison.h"
 
 namespace Assimp
 {
@@ -229,15 +231,45 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
 template <typename Real>
 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;
 	}
 
-	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;
 
@@ -255,6 +287,10 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma
 		pl *= fast_atof_table[diff];
 		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.
 	// 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 ...
       if (outRec->sides == esNeither && pt.Y == op->pt.Y)
+      {
         if (ToFront)
         {
           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);
       if (outRec->sides == esBoth)

+ 1 - 1
contrib/unzip/unzip.c

@@ -1246,7 +1246,7 @@ extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
         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;
     if (len==0)
         return 0;

+ 29 - 3
include/assimp/ProgressHandler.hpp

@@ -81,13 +81,39 @@ public:
 	 *   all needed cleanup tasks prior to returning control to the
 	 *   caller). If the loading is aborted, #Importer::ReadFile()
 	 *   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;
 
+	// -------------------------------------------------------------------
+	/** @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 
 // ------------------------------------------------------------------------------------

+ 1 - 1
include/assimp/importerdesc.h

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

+ 2 - 1
samples/SimpleOpenGL/CMakeLists.txt

@@ -1,5 +1,6 @@
 FIND_PACKAGE(OpenGL)
 FIND_PACKAGE(GLUT)
+find_library(M_LIB m)
 
 IF ( NOT GLUT_FOUND )
 	IF ( MSVC )
@@ -29,7 +30,7 @@ ADD_EXECUTABLE( assimp_simpleogl
 
 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
 	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.
 // It takes a file name as command line parameter, loads it using standard
 // settings and displays it.
@@ -9,29 +9,30 @@
 // The vc8 solution links against assimp-release-dll_win32 - be sure to
 // have this configuration built.
 // ----------------------------------------------------------------------------
+*/
 
 #include <stdlib.h>
 #include <stdio.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/scene.h>
 #include <assimp/postprocess.h>
 
-// the global Assimp scene object
+/* the global Assimp scene object */
 const struct aiScene* scene = NULL;
 GLuint scene_list = 0;
 struct aiVector3D scene_min, scene_max, scene_center;
 
-// current rotation angle
+/* current rotation angle */
 static float angle = 0.f;
 
 #define aisgl_min(x,y) (x<y?x:y)
 #define aisgl_max(x,y) (y>x?y:x)
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void reshape(int width, int height)
 {
 	const double aspectRatio = (float) width / height, fieldOfView = 45.0;
@@ -43,7 +44,7 @@ void reshape(int width, int height)
 	glViewport(0, 0, width, height);
 }
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void get_bounding_box_for_node (const struct aiNode* nd, 
 	struct aiVector3D* min, 
 	struct aiVector3D* max, 
@@ -78,7 +79,7 @@ void get_bounding_box_for_node (const struct aiNode* nd,
 	*trafo = prev;
 }
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max)
 {
 	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);
 }
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void color4_to_float4(const struct aiColor4D *c, float f[4])
 {
 	f[0] = c->r;
@@ -98,7 +99,7 @@ void color4_to_float4(const struct aiColor4D *c, float f[4])
 	f[3] = c->a;
 }
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void set_float4(float f[4], float a, float b, float c, float d)
 {
 	f[0] = a;
@@ -107,7 +108,7 @@ void set_float4(float f[4], float a, float b, float c, float d)
 	f[3] = d;
 }
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void apply_material(const struct aiMaterial *mtl)
 {
 	float c[4];
@@ -173,19 +174,19 @@ void apply_material(const struct aiMaterial *mtl)
 		glEnable(GL_CULL_FACE);
 }
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
 {
 	unsigned int i;
 	unsigned int n = 0, t;
 	struct aiMatrix4x4 m = nd->mTransformation;
 
-	// update transform
+	/* update transform */
 	aiTransposeMatrix4(&m);
 	glPushMatrix();
 	glMultMatrixf((float*)&m);
 
-	// draw all meshes assigned to this node
+	/* draw all meshes assigned to this node */
 	for (; n < nd->mNumMeshes; ++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) {
 		recursive_render(sc, nd->mChildren[n]);
 	}
@@ -232,7 +233,7 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
 	glPopMatrix();
 }
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void do_motion (void)
 {
 	static GLint prev_time = 0;
@@ -244,7 +245,7 @@ void do_motion (void)
 	prev_time = time;
 
 	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);
         printf("%d fps\n", current_fps);
@@ -256,7 +257,7 @@ void do_motion (void)
 	glutPostRedisplay ();
 }
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 void display(void)
 {
 	float tmp;
@@ -267,27 +268,27 @@ void display(void)
 	glLoadIdentity();
 	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);
 
-	// 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 = aisgl_max(scene_max.y - scene_min.y,tmp);
 	tmp = aisgl_max(scene_max.z - scene_min.z,tmp);
 	tmp = 1.f / tmp;
 	glScalef(tmp, tmp, tmp);
 
-        // center the model
+        /* center the model */
 	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) {
 	    scene_list = glGenLists(1);
 	    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);
 	    glEndList();
 	}
@@ -299,11 +300,11 @@ void display(void)
 	do_motion();
 }
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 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);
 
 	if (scene) {
@@ -316,7 +317,7 @@ int loadasset (const char* path)
 	return 1;
 }
 
-// ----------------------------------------------------------------------------
+/* ---------------------------------------------------------------------------- */
 int main(int argc, char **argv)
 {
 	struct aiLogStream stream;
@@ -330,21 +331,21 @@ int main(int argc, char **argv)
 	glutDisplayFunc(display);
 	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);
 	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");
 	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( argc != 1 || (0 != loadasset( "../../../../test/models-nonbsd/X/dwarf.x") && 0 != loadasset( "../../test/models/X/Testwuson.X"))) { 
 			return -1;
@@ -354,14 +355,14 @@ int main(int argc, char **argv)
 	glClearColor(0.1f,0.1f,0.1f,1.f);
 
 	glEnable(GL_LIGHTING);
-	glEnable(GL_LIGHT0);    // Uses default lighting parameters
+	glEnable(GL_LIGHT0);    /* Uses default lighting parameters */
 
 	glEnable(GL_DEPTH_TEST);
 
 	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
 	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"))  
 		glFrontFace(GL_CW);
 
@@ -370,14 +371,15 @@ int main(int argc, char **argv)
 	glutGet(GLUT_ELAPSED_TIME);
 	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);
 
-	// 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();
 	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! :)
 // http://nehe.gamedev.net/
 // ----------------------------------------------------------------------------
-
-
-
 #include <windows.h>
 #include <stdio.h>
 #include <GL/gl.h>
@@ -36,7 +33,7 @@
 #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";
 
 
@@ -47,7 +44,7 @@ HINSTANCE	hInstance;	// Holds The Instance Of The Application
 
 bool		keys[256];			// Array used for Keyboard Routine;
 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		yrot;
@@ -80,6 +77,7 @@ Assimp::Importer importer;
 
 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::VERBOSE;
 
@@ -101,20 +99,20 @@ void destroyAILogger()
 
 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());
 }
 
 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);
 }
 
 
 bool Import3DFromFile( const std::string& pFile)
 {
-	//check if file exists
+	// Check if file exists
 	std::ifstream fin(pFile.c_str());
 	if(!fin.fail())
 	{
@@ -143,12 +141,14 @@ bool Import3DFromFile( const std::string& pFile)
 	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
@@ -217,9 +217,6 @@ int LoadGLTextures(const aiScene* scene)
 	textureIds = new GLuint[numTextures];
 	glGenTextures(numTextures, textureIds); /* Texture name generation */
 
-	/* define texture path */
-	//std::string texturepath = "../../../test/models/Obj/";
-
 	/* get iterator */
 	std::map<std::string, GLuint*>::iterator itr = textureIdMap.begin();
 
@@ -239,48 +236,50 @@ int LoadGLTextures(const aiScene* scene)
 
 		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)
 			{
 				/* Error occured */
 				abortGLInit("Couldn't convert image");
 				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,
-				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
 		{
 			/* Error occured */
 			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;
 	imageIds = NULL;
 
-	//return success;
 	return TRUE;
 }
 
-
-
-int InitGL()					 // All Setup For OpenGL goes here
+// All Setup For OpenGL goes here
+int InitGL()
 {
 	if (!LoadGLTextures(scene))
 	{
@@ -307,9 +306,6 @@ int InitGL()					 // All Setup For OpenGL goes here
 	glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
 	glEnable(GL_LIGHT1);
 
-	//glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
-
-
 	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);
 		}
 
-
-
 		for (t = 0; t < mesh->mNumFaces; ++t) {
 			const struct aiFace* face = &mesh->mFaces[t];
 			GLenum face_mode;
@@ -480,14 +474,10 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd, float
 					glNormal3fv(&mesh->mNormals[vertexIndex].x);
 					glVertex3fv(&mesh->mVertices[vertexIndex].x);
 			}
-
 			glEnd();
-
 		}
-
 	}
 
-
 	// draw all children
 	for (n = 0; n < nd->mNumChildren; ++n)
 	{
@@ -521,12 +511,11 @@ int DrawGLScene()				//Here's where we do all the drawing
 
 	drawAiScene(scene);
 
-
 	//xrot+=0.3f;
 	yrot+=0.2f;
 	//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.");
 		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
@@ -767,8 +751,8 @@ LRESULT CALLBACK WndProc(HWND hWnd,				// Handles for this Window
 			{
 				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;
 				}
 				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);
 }
 
-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
 				   int nShowCmd )                // Window Show State
 {

+ 14 - 105
test/CMakeLists.txt

@@ -15,7 +15,8 @@ SOURCE_GROUP( unit FILES
 	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/Asserter.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/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.h
 	unit/utFindInvalidData.cpp
@@ -116,114 +118,21 @@ SOURCE_GROUP( tests FILES
 	unit/utVertexTriangleAdjacency.h
 	unit/utNoBoostTest.cpp
 	unit/utNoBoostTest.h
+	unit/BoostWorkaround/tupletest.cpp	
 )
 
+SOURCE_GROUP(tests FILES  ${TEST_SRCS})
+
+
 add_executable(  unit
 	unit/CCompilerTest.c
 	unit/Main.cpp
 	unit/UnitTestPCH.cpp
 	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})
 
-# 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
 Ka 0.000000 0.000000 0.000000
 Kd 0.8 0.8 0.8
-Ks 0.8 0.8 0.8
+Ks 0
 d 1
 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/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
 	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
     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, 
-	IOSystem* pIOHandler, bool test) const
+	IOSystem* /*pIOHandler*/, bool /*test*/) const
 {
 	std::string::size_type pos = pFile.find_last_of('.');
 	// no file extension - can't read
@@ -90,8 +90,8 @@ const aiImporterDesc* TestPlugin :: GetInfo() const
 	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);
 }
@@ -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/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/dwarf.x",flags)); # is in nonbsd
 
 	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
 }

+ 2 - 2
test/unit/utNoBoostTest.h

@@ -4,7 +4,7 @@
 namespace noboost {
 
 #define ASSIMP_FORCE_NOBOOST
-#include "..\..\code\BoostWorkaround\boost\format.hpp"
+#include "../../code/BoostWorkaround/boost/format.hpp"
 	using boost::format;
 	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)
 {
-	char* szTest = 
+	const char* szTest = 
 		"/* comment to be removed */\n"
 		"valid text /* \n "
 		" comment across multiple lines */"
@@ -62,4 +62,4 @@ void RemoveCommentsTest :: testMultiLineComments (void)
 	CPPUNIT_ASSERT(0 == ::strcmp(szTest2,szTestResult));
 
 	delete[] szTest2;
-}
+}

+ 1 - 1
tools/assimp_cmd/WriteDumb.cpp

@@ -656,7 +656,7 @@ uint32_t WriteBinaryScene(const aiScene* scene)
 // -----------------------------------------------------------------------------------
 // Write a binary model dump
 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;
 	shortened = _shortened;

+ 4 - 5
tools/assimp_view/MessageProc.cpp

@@ -1030,18 +1030,17 @@ void PopulateExportMenu()
 //-------------------------------------------------------------------------------
 void DoExport(size_t formatId)
 {
-	if (!g_szFileName) {
+	if (!g_szFileName[0]) {
+		MessageBox(g_hDlg, "No model loaded", "Export", MB_ICONERROR);
 		return;
 	}
-
 	Exporter exp;
 	const aiExportFormatDesc* const e = exp.GetExportFormatDescription(formatId);
 	ai_assert(e);
 
 	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);
 
 		// invent a nice default file name