Selaa lähdekoodia

- ASE loader alpha
- MDL loader stable
- 3ds bugfixes,
- API extensions
- New viewer features - WIP
- Support for C

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@11 67173fc5-114c-0410-ac8e-9d2fd5bffc1f

aramis_acg 17 vuotta sitten
vanhempi
commit
db9c5fef2b
100 muutettua tiedostoa jossa 12827 lisäystä ja 1787 poistoa
  1. 0 5
      README
  2. 79 17
      code/3DSConverter.cpp
  3. 69 67
      code/3DSGenNormals.cpp
  4. 117 40
      code/3DSHelper.h
  5. 41 0
      code/3DSLoader.cpp
  6. 253 204
      code/3DSLoader.h
  7. 81 57
      code/3DSSpatialSort.cpp
  8. 63 15
      code/3DSSpatialSort.h
  9. 720 0
      code/ASELoader.cpp
  10. 147 0
      code/ASELoader.h
  11. 1644 0
      code/ASEParser.cpp
  12. 387 0
      code/ASEParser.h
  13. 114 0
      code/Assimp.cpp
  14. 45 0
      code/BaseImporter.cpp
  15. 90 20
      code/BaseImporter.h
  16. 40 0
      code/BaseProcess.h
  17. 43 2
      code/CalcTangentsProcess.cpp
  18. 41 0
      code/CalcTangentsProcess.h
  19. 40 0
      code/ConvertToLHProcess.h
  20. 40 14
      code/DefaultIOStream.cpp
  21. 40 0
      code/DefaultIOStream.h
  22. 40 0
      code/DefaultIOSystem.cpp
  23. 40 0
      code/DefaultIOSystem.h
  24. 41 0
      code/GenFaceNormalsProcess.cpp
  25. 40 0
      code/GenFaceNormalsProcess.h
  26. 41 0
      code/GenVertexNormalsProcess.cpp
  27. 40 0
      code/GenVertexNormalsProcess.h
  28. 138 11
      code/Importer.cpp
  29. 41 0
      code/JoinVerticesProcess.cpp
  30. 40 0
      code/JoinVerticesProcess.h
  31. 40 0
      code/KillNormalsProcess.cpp
  32. 40 0
      code/KillNormalsProcess.h
  33. 40 0
      code/MD2FileData.h
  34. 122 64
      code/MD2Loader.cpp
  35. 80 30
      code/MD2Loader.h
  36. 49 3
      code/MD2NormalTable.h
  37. 78 38
      code/MD3FileData.h
  38. 69 28
      code/MD3Loader.cpp
  39. 79 29
      code/MD3Loader.h
  40. 218 0
      code/MD4FileData.h
  41. 115 0
      code/MD4Loader.cpp
  42. 80 30
      code/MD4Loader.h
  43. 81 30
      code/MD5Loader.h
  44. 118 0
      code/MDLDefaultColorMap.h
  45. 706 0
      code/MDLFileData.h
  46. 1715 0
      code/MDLLoader.cpp
  47. 241 0
      code/MDLLoader.h
  48. 182 48
      code/MaterialSystem.cpp
  49. 85 4
      code/MaterialSystem.h
  50. 44 3
      code/ObjFileData.h
  51. 2 2
      code/ObjFileImporter.cpp
  52. 48 0
      code/ObjFileImporter.h
  53. 41 0
      code/ObjFileMtlImporter.h
  54. 2 2
      code/ObjFileParser.cpp
  55. 40 0
      code/ObjTools.h
  56. 279 177
      code/PlyLoader.cpp
  57. 137 60
      code/PlyLoader.h
  58. 138 54
      code/PlyParser.cpp
  59. 136 21
      code/PlyParser.h
  60. 41 0
      code/SpatialSort.cpp
  61. 40 0
      code/SpatialSort.h
  62. 315 26
      code/SplitLargeMeshes.cpp
  63. 110 8
      code/SplitLargeMeshes.h
  64. 43 1
      code/TriangulateProcess.h
  65. 41 0
      code/XFileHelper.h
  66. 41 1
      code/XFileImporter.cpp
  67. 73 13
      code/XFileImporter.h
  68. 41 0
      code/XFileParser.cpp
  69. 40 0
      code/XFileParser.h
  70. 103 0
      code/res/assimp.rc
  71. 14 0
      code/res/resource.h
  72. 43 2
      include/ObjFileParser.h
  73. 49 8
      include/aiAnim.h
  74. 59 6
      include/aiFileIO.h
  75. 166 86
      include/aiMaterial.h
  76. 2 2
      include/aiMatrix3x3.h
  77. 2 2
      include/aiMatrix4x4.h
  78. 164 29
      include/aiMesh.h
  79. 69 2
      include/aiPostProcess.h
  80. 40 38
      include/aiQuaternion.h
  81. 64 7
      include/aiScene.h
  82. 149 0
      include/aiTexture.h
  83. 79 17
      include/aiTypes.h
  84. 5 8
      include/aiVector3D.h
  85. 79 9
      include/assimp.h
  86. 78 12
      include/assimp.hpp
  87. 39 8
      tools/assimp_view/Background.cpp
  88. 1 0
      tools/assimp_view/Display.cpp
  89. 0 0
      tools/assimp_view/Display.h
  90. 39 8
      tools/assimp_view/HelpDialog.cpp
  91. 39 8
      tools/assimp_view/Input.cpp
  92. 39 8
      tools/assimp_view/LogDisplay.cpp
  93. 39 8
      tools/assimp_view/LogDisplay.h
  94. 103 0
      tools/assimp_view/LogWindow.cpp
  95. 78 0
      tools/assimp_view/LogWindow.h
  96. 302 188
      tools/assimp_view/Material.cpp
  97. 181 109
      tools/assimp_view/MessageProc.cpp
  98. 39 57
      tools/assimp_view/Shaders.cpp
  99. BIN
      tools/assimp_view/assimp_view.aps
  100. 418 41
      tools/assimp_view/assimp_view.cpp

+ 0 - 5
README

@@ -1,5 +0,0 @@
-		 AssetImporter
-		---------------
-To use the asset importer lbrary just compile it with visual-c++ 8.0 (at this 
-moment no other build enviroments are supported).
-	

+ 79 - 17
code/3DSConverter.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the 3ds importer class */
 #include "3DSLoader.h"
 #include "MaterialSystem.h"
@@ -207,48 +248,67 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
 	}
 	mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
 
+	if (Dot3DS::Dot3DSFile::Wire == oldMat.mShading)
+	{
+		// set the wireframe flag
+		unsigned int iWire = 1;
+		mat.AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
+	}
+
 	// texture, if there is one
 	if( oldMat.sTexDiffuse.mMapName.length() > 0)
 	{
 		aiString tex;
 		tex.Set( oldMat.sTexDiffuse.mMapName);
 		mat.AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
-		mat.AddProperty<float>( &oldMat.sTexDiffuse.mTextureBlend, 1, AI_MATKEY_TEXBLEND_DIFFUSE(0));
+
+		if (is_not_qnan(oldMat.sTexDiffuse.mTextureBlend))
+			mat.AddProperty<float>( &oldMat.sTexDiffuse.mTextureBlend, 1, AI_MATKEY_TEXBLEND_DIFFUSE(0));
 	}
 	if( oldMat.sTexSpecular.mMapName.length() > 0)
 	{
 		aiString tex;
 		tex.Set( oldMat.sTexSpecular.mMapName);
 		mat.AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(0));
-		mat.AddProperty<float>( &oldMat.sTexSpecular.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SPECULAR(0));
+
+		if (is_not_qnan(oldMat.sTexSpecular.mTextureBlend))
+			mat.AddProperty<float>( &oldMat.sTexSpecular.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SPECULAR(0));
 	}
 	if( oldMat.sTexOpacity.mMapName.length() > 0)
 	{
 		aiString tex;
 		tex.Set( oldMat.sTexOpacity.mMapName);
 		mat.AddProperty( &tex, AI_MATKEY_TEXTURE_OPACITY(0));
-		mat.AddProperty<float>( &oldMat.sTexOpacity.mTextureBlend, 1,AI_MATKEY_TEXBLEND_OPACITY(0));
+
+		if (is_not_qnan(oldMat.sTexOpacity.mTextureBlend))
+			mat.AddProperty<float>( &oldMat.sTexOpacity.mTextureBlend, 1,AI_MATKEY_TEXBLEND_OPACITY(0));
 	}
 	if( oldMat.sTexEmissive.mMapName.length() > 0)
 	{
 		aiString tex;
 		tex.Set( oldMat.sTexEmissive.mMapName);
 		mat.AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(0));
-		mat.AddProperty<float>( &oldMat.sTexEmissive.mTextureBlend, 1, AI_MATKEY_TEXBLEND_EMISSIVE(0));
+
+		if (is_not_qnan(oldMat.sTexEmissive.mTextureBlend))
+			mat.AddProperty<float>( &oldMat.sTexEmissive.mTextureBlend, 1, AI_MATKEY_TEXBLEND_EMISSIVE(0));
 	}
 	if( oldMat.sTexBump.mMapName.length() > 0)
 	{
 		aiString tex;
 		tex.Set( oldMat.sTexBump.mMapName);
-		mat.AddProperty( &tex, AI_MATKEY_TEXTURE_BUMP(0));
-		mat.AddProperty<float>( &oldMat.sTexBump.mTextureBlend, 1, AI_MATKEY_TEXBLEND_BUMP(0));
+		mat.AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(0));
+
+		if (is_not_qnan(oldMat.sTexBump.mTextureBlend))
+			mat.AddProperty<float>( &oldMat.sTexBump.mTextureBlend, 1, AI_MATKEY_TEXBLEND_HEIGHT(0));
 	}
 	if( oldMat.sTexShininess.mMapName.length() > 0)
 	{
 		aiString tex;
 		tex.Set( oldMat.sTexShininess.mMapName);
 		mat.AddProperty( &tex, AI_MATKEY_TEXTURE_SHININESS(0));
-		mat.AddProperty<float>( &oldMat.sTexBump.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SHININESS(0));
+
+		if (is_not_qnan(oldMat.sTexShininess.mTextureBlend))
+			mat.AddProperty<float>( &oldMat.sTexShininess.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SHININESS(0));
 	}
 
 	// store the name of the material itself, too
@@ -267,7 +327,7 @@ void SetupMatUVSrc (aiMaterial* pcMat, const Dot3DS::Material* pcMatIn)
 	pcHelper->AddProperty<int>(&pcMatIn->sTexDiffuse.iUVSrc,1,AI_MATKEY_UVWSRC_DIFFUSE(0));
 	pcHelper->AddProperty<int>(&pcMatIn->sTexSpecular.iUVSrc,1,AI_MATKEY_UVWSRC_SPECULAR(0));
 	pcHelper->AddProperty<int>(&pcMatIn->sTexEmissive.iUVSrc,1,AI_MATKEY_UVWSRC_EMISSIVE(0));
-	pcHelper->AddProperty<int>(&pcMatIn->sTexBump.iUVSrc,1,AI_MATKEY_UVWSRC_BUMP(0));
+	pcHelper->AddProperty<int>(&pcMatIn->sTexBump.iUVSrc,1,AI_MATKEY_UVWSRC_HEIGHT(0));
 	pcHelper->AddProperty<int>(&pcMatIn->sTexShininess.iUVSrc,1,AI_MATKEY_UVWSRC_SHININESS(0));
 	pcHelper->AddProperty<int>(&pcMatIn->sTexOpacity.iUVSrc,1,AI_MATKEY_UVWSRC_OPACITY(0));
 	}
@@ -331,14 +391,16 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
 				p_pcOut->mNumVertices = aiSplit[p].size()*3;
 				p_pcOut->mNumFaces = aiSplit[p].size();
 
+				// allocate enough storage for faces
+				p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
 				iFaceCnt += p_pcOut->mNumFaces;
+
 				if (p_pcOut->mNumVertices != 0)
 				{
 					p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices];
 					p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices];
 					unsigned int iBase = 0;
 
-					p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
 					for (unsigned int q = 0; q < aiSplit[p].size();++q)
 					{
 						unsigned int iIndex = aiSplit[p][q];
@@ -617,8 +679,8 @@ void Dot3DSImporter::BakeScaleNOffset(
 			{
 			for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
 				{
-				pcMesh->mTextureCoords[0][i].x *= pcSrc->pcSingleTexture->mScaleU;
-				pcMesh->mTextureCoords[0][i].y *= pcSrc->pcSingleTexture->mScaleV;
+				pcMesh->mTextureCoords[0][i].x /= pcSrc->pcSingleTexture->mScaleU;
+				pcMesh->mTextureCoords[0][i].y /= pcSrc->pcSingleTexture->mScaleV;
 
 				pcMesh->mTextureCoords[0][i].x += pcSrc->pcSingleTexture->mOffsetU;
 				pcMesh->mTextureCoords[0][i].y += pcSrc->pcSingleTexture->mOffsetV;
@@ -630,8 +692,8 @@ void Dot3DSImporter::BakeScaleNOffset(
 			const float fCos = cosf(pcSrc->pcSingleTexture->mRotation);
 			for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
 				{
-				pcMesh->mTextureCoords[0][i].x *= pcSrc->pcSingleTexture->mScaleU;
-				pcMesh->mTextureCoords[0][i].y *= pcSrc->pcSingleTexture->mScaleV;
+				pcMesh->mTextureCoords[0][i].x /= pcSrc->pcSingleTexture->mScaleU;
+				pcMesh->mTextureCoords[0][i].y /= pcSrc->pcSingleTexture->mScaleV;
 
 				pcMesh->mTextureCoords[0][i].x *= fCos;
 				pcMesh->mTextureCoords[0][i].y *= fSin;
@@ -694,8 +756,8 @@ void Dot3DSImporter::BakeScaleNOffset(
 				{
 				for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
 					{
-					pcMesh->mTextureCoords[iCnt][n].x = pvBase->x * (*i).fScaleU;
-					pcMesh->mTextureCoords[iCnt][n].y = pvBase->y * (*i).fScaleV;
+					pcMesh->mTextureCoords[iCnt][n].x = pvBase->x / (*i).fScaleU;
+					pcMesh->mTextureCoords[iCnt][n].y = pvBase->y / (*i).fScaleV;
 
 					pcMesh->mTextureCoords[iCnt][n].x += (*i).fOffsetU;
 					pcMesh->mTextureCoords[iCnt][n].y += (*i).fOffsetV;
@@ -709,8 +771,8 @@ void Dot3DSImporter::BakeScaleNOffset(
 				const float fCos = cosf((*i).fRotation);
 				for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
 					{
-					pcMesh->mTextureCoords[iCnt][n].x = pvBase->x * (*i).fScaleU;
-					pcMesh->mTextureCoords[iCnt][n].y = pvBase->y * (*i).fScaleV;
+					pcMesh->mTextureCoords[iCnt][n].x = pvBase->x / (*i).fScaleU;
+					pcMesh->mTextureCoords[iCnt][n].y = pvBase->y / (*i).fScaleV;
 
 					pcMesh->mTextureCoords[iCnt][n].x *= fCos;
 					pcMesh->mTextureCoords[iCnt][n].y *= fSin;

+ 69 - 67
code/3DSGenNormals.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the 3ds importer class */
 #include "3DSLoader.h"
 #include "MaterialSystem.h"
@@ -14,7 +55,6 @@ using namespace Assimp;
 // ------------------------------------------------------------------------------------------------
 void Dot3DSImporter::GenNormals(Dot3DS::Mesh* sMesh)
 {
-	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 	// First generate face normals
 	sMesh->mNormals.resize(sMesh->mPositions.size(),aiVector3D());
 	for( unsigned int a = 0; a < sMesh->mFaces.size(); a++)
@@ -29,17 +69,12 @@ void Dot3DSImporter::GenNormals(Dot3DS::Mesh* sMesh)
 		aiVector3D pDelta1 = *pV2 - *pV1;
 		aiVector3D pDelta2 = *pV3 - *pV1;
 		aiVector3D vNor = pDelta1 ^ pDelta2;
-		
-		//float fLength = vNor.Length();
-		//if (0.0f != fLength)vNor /= fLength;
-
 
 		sMesh->mNormals[face.i1] = vNor;
 		sMesh->mNormals[face.i2] = vNor;
 		sMesh->mNormals[face.i3] = vNor;
 	}
 
-	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 	// calculate the position bounds so we have a reliable epsilon to 
 	// check position differences against 
 	// @Schrompf: This is the 6th time this snippet is repeated!
@@ -54,81 +89,48 @@ void Dot3DSImporter::GenNormals(Dot3DS::Mesh* sMesh)
 		maxVec.z = std::max( maxVec.z, sMesh->mPositions[a].z);
 	}
 	const float posEpsilon = (maxVec - minVec).Length() * 1e-5f;
-
-
 	std::vector<aiVector3D> avNormals;
 	avNormals.resize(sMesh->mNormals.size());
 	
-	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 	// now generate the spatial sort tree
-	D3DSSpatialSorter sSort(sMesh);
+	D3DSSpatialSorter sSort;
+	for( std::vector<Dot3DS::Face>::iterator
+		i =  sMesh->mFaces.begin();
+		i != sMesh->mFaces.end();++i)
+	{
+		sSort.AddFace(&(*i),sMesh->mPositions);
+	}
+	sSort.Prepare();
 
 	for( std::vector<Dot3DS::Face>::iterator
 		i =  sMesh->mFaces.begin();
 		i != sMesh->mFaces.end();++i)
-		{
+	{
 		std::vector<unsigned int> poResult;
-		// need to repeat the code for all three vertices of the triangle
 
-		// vertex 1
-		sSort.FindPositions(sMesh->mPositions[(*i).i1],(*i).iSmoothGroup,
-			posEpsilon,poResult);
+		for (unsigned int c = 0; c < 3;++c)
+		{
 
-		aiVector3D vNormals;
-		float fDiv = 0.0f;
-		for (std::vector<unsigned int>::const_iterator
-			a =  poResult.begin();
-			a != poResult.end();++a)
-			{
-			vNormals += sMesh->mNormals[(*a)];
-			fDiv += 1.0f;
-			}
-		vNormals.x /= fDiv;
-		vNormals.y /= fDiv;
-		vNormals.z /= fDiv;
-		vNormals.Normalize();
-		avNormals[(*i).i1] = vNormals;
-		poResult.clear();
-
-		// vertex 2
-		sSort.FindPositions(sMesh->mPositions[(*i).i2],(*i).iSmoothGroup,
-			posEpsilon,poResult);
-
-		vNormals = aiVector3D();
-		fDiv = 0.0f;
-		for (std::vector<unsigned int>::const_iterator
-			a =  poResult.begin();
-			a != poResult.end();++a)
-			{
-			vNormals += sMesh->mNormals[(*a)];
-			fDiv += 1.0f;
-			}
-		vNormals.x /= fDiv;
-		vNormals.y /= fDiv;
-		vNormals.z /= fDiv;
-		vNormals.Normalize();
-		avNormals[(*i).i2] = vNormals;
-		poResult.clear();
-
-		// vertex 3
-		sSort.FindPositions(sMesh->mPositions[(*i).i3],(*i).iSmoothGroup,
-			posEpsilon ,poResult);
-
-		vNormals = aiVector3D();
-		fDiv = 0.0f;
-		for (std::vector<unsigned int>::const_iterator
-			a =  poResult.begin();
-			a != poResult.end();++a)
+			sSort.FindPositions(sMesh->mPositions[(*i).mIndices[c]],(*i).iSmoothGroup,
+				posEpsilon,poResult);
+
+			aiVector3D vNormals;
+			float fDiv = 0.0f;
+			for (std::vector<unsigned int>::const_iterator
+				a =  poResult.begin();
+				a != poResult.end();++a)
 			{
-			vNormals += sMesh->mNormals[(*a)];
-			fDiv += 1.0f;
+				vNormals += sMesh->mNormals[(*a)];
+				fDiv += 1.0f;
 			}
-		vNormals.x /= fDiv;
-		vNormals.y /= fDiv;
-		vNormals.z /= fDiv;
-		vNormals.Normalize();
-		avNormals[(*i).i3] = vNormals;
+			vNormals.x /= fDiv;
+			vNormals.y /= fDiv;
+			vNormals.z /= fDiv;
+			vNormals.Normalize();
+			avNormals[(*i).mIndices[c]] = vNormals;
+			poResult.clear();
 		}
+	}
 	sMesh->mNormals = avNormals;
 	return;
 }

+ 117 - 40
code/3DSHelper.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 helper data structures for importing XFiles */
 #ifndef AI_3DSFILEHELPER_H_INC
 #define AI_3DSFILEHELPER_H_INC
@@ -35,27 +75,30 @@ class Dot3DSFile
 public:
 	inline Dot3DSFile() {}
 
-	// data structure for a single chunk in a .3ds file
+	//! data structure for a single chunk in a .3ds file
 	struct Chunk
 	{
 		unsigned short	Flag;
 		long			Size;
 	} PACK_STRUCT;
 
-	// source for this used own structures,
-	// replaced it with out standard math helpers
+	//! source for this used own structures,
+	//! replaced it with out standard math helpers
 	typedef aiMatrix3x3 MatTransform;
 	typedef aiVector3D MatTranslate;
 
-	// Used for shading field in material3ds structure
-	// From AutoDesk 3ds SDK
+	//! Used for shading field in material3ds structure
+	//! From AutoDesk 3ds SDK
 	typedef enum
 	{
 		Wire = 0,
 		Flat = 1,
 		Gouraud = 2,
 		Phong = 3,
-		Metal = 4
+		Metal = 4,
+
+		// required by the ASE loader
+		Blinn = 5
 	} shadetype3ds;
 
 	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -261,30 +304,38 @@ public:
 /** Helper structure representing a 3ds mesh face */
 struct Face
 {
-	Face() : iSmoothGroup(0), bDirection(true)
+	Face() : iSmoothGroup(0), bDirection(true), i1(0), i2(0), i3(0)
 	{
 		// let the rest uninitialized for performance
 	}
 
 	
-	// Indices. .3ds is using uint16. However, after
-	// an unique vrtex set has been geneerated it might
-	// be an index becomes > 2^16
-	uint32_t i1;
-	uint32_t i2;
-	uint32_t i3;
-
-	// specifies to which smoothing group the face belongs to
+	//! Indices. .3ds is using uint16. However, after
+	//! an unique vrtex set has been geneerated it might
+	//! be an index becomes > 2^16
+	union
+	{
+		struct
+		{
+			uint32_t i1;
+			uint32_t i2;
+			uint32_t i3;
+		};
+		uint32_t mIndices[3];
+	};
+
+	//! specifies to which smoothing group the face belongs to
 	uint32_t iSmoothGroup;
 
-	// Direction the normal vector of the face 
-	// will be pointing to
+	//! Direction the normal vector of the face 
+	//! will be pointing to
 	bool bDirection;
 };
 // ---------------------------------------------------------------------------
 /** Helper structure representing a texture */
 struct Texture
 {
+	//! Default constructor
 	Texture()
 		: 
 		mScaleU(1.0f),
@@ -296,20 +347,20 @@ struct Texture
 	{
 		mTextureBlend = std::numeric_limits<float>::quiet_NaN();
 	}
-	// Specifies the blending factor for the texture
+	//! Specifies the blending factor for the texture
 	float mTextureBlend;
 
-	// Specifies the filename of the texture
+	//! Specifies the filename of the texture
 	std::string mMapName;
 
-	// Specifies texture coordinate offsets/scaling/rotations
+	//! Specifies texture coordinate offsets/scaling/rotations
 	float mScaleU;
 	float mScaleV;
 	float mOffsetU;
 	float mOffsetV;
 	float mRotation;
 
-	// Used internally
+	//! Used internally
 	bool bPrivate;
 	int iUVSrc;
 };
@@ -317,6 +368,7 @@ struct Texture
 /** Helper structure representing a 3ds material */
 struct Material
 {
+	//! Default constructor. Builds a default name for the material
 	Material()
 		: 
 	mSpecularExponent	(0.0f),
@@ -331,27 +383,32 @@ struct Material
 		ss << "%%_UNNAMED_" << iCnt++ << "_%%"; 
 	}
 
-	// Name of the material
+	//! Name of the material
 	std::string mName;
-	// Diffuse color of the material
+	//! Diffuse color of the material
 	aiColor3D mDiffuse;
-	// Specular exponent
+	//! Specular exponent
 	float mSpecularExponent;
-	// Specular color of the material
+	//! Specular color of the material
 	aiColor3D mSpecular;
-	// Ambient color of the material
+	//! Ambient color of the material
 	aiColor3D mAmbient;
-	// Shading type to be used
+	//! Shading type to be used
 	Dot3DSFile::shadetype3ds mShading;
-	// Opacity of the material
+	//! Opacity of the material
 	float mTransparency;
 
-	// Different texture channels
+	//! Diffuse texture channel
 	Texture sTexDiffuse;
+	//! Opacity texture channel
 	Texture sTexOpacity;
+	//! Specular texture channel
 	Texture sTexSpecular;
+	//! Bump texture channel
 	Texture sTexBump;
+	//! Emissive texture channel
 	Texture sTexEmissive;
+	//! Shininess texture channel
 	Texture sTexShininess;
 	
 	/*
@@ -360,10 +417,10 @@ struct Material
 	*/
 	float mBumpHeight;
 
-	// Emissive color
+	//! Emissive color
 	aiColor3D mEmissive;
 
-	// Used internally
+	//! Used internally
 	unsigned int iBakeUVTransform;
 	Texture* pcSingleTexture;
 };
@@ -371,28 +428,33 @@ struct Material
 /** Helper structure to represent a 3ds file mesh */
 struct Mesh
 {
+	//! Default constructor
 	Mesh()
 	{
 		static int iCnt = 0;
 		std::stringstream ss(mName);
 		ss << "%%_UNNAMED_" << iCnt++ << "_%%"; 
-#if 0
-		for (unsigned int i = 0; i < 32;++i)
-			bSmoothGroupRequired[i] = false;
-#endif
 	}
+
+	//! Name of the mesh
 	std::string mName;
 
+	//! Vertex positions
 	std::vector<aiVector3D> mPositions;
+
+	//! Face lists
 	std::vector<Face> mFaces;
+
+	//! Texture coordinates
 	std::vector<aiVector2D> mTexCoords;
+
+	//! Face materials
 	std::vector<unsigned int> mFaceMaterials;
-	std::vector<aiVector3D> mNormals;
 
-#if 0
-	bool bSmoothGroupRequired[32];
-#endif
+	//! Normal vectors
+	std::vector<aiVector3D> mNormals;
 
+	//! Local transformation matrix
 	aiMatrix4x4 mMat;
 };
 // ---------------------------------------------------------------------------
@@ -412,10 +474,19 @@ struct Node
 		mHierarchyIndex = 0;
 	}
 
+	//! Pointer to the parent node
 	Node* mParent;
+
+	//! Holds all child nodes
 	std::vector<Node*> mChildren;
+
+	//! Name of the node
 	std::string mName;
+
+	//! Position of the node in the hierarchy (tree depth)
 	int16_t mHierarchyPos;
+
+	//! Index of the node
 	int16_t mHierarchyIndex;
 
 #if 0
@@ -425,6 +496,8 @@ struct Node
 	aiVector3D vPosition;
 #endif
 
+	//! Add a child node, setup the right parent node for it
+	//! \param pc Node to be 'adopted'
 	inline Node& push_back(Node* pc)
 	{
 		mChildren.push_back(pc);
@@ -438,10 +511,14 @@ struct Node
 struct Scene
 {
 
-	// NOTE: 3ds references materials globally
+	//! List of all materials loaded
+	//! NOTE: 3ds references materials globally
 	std::vector<Material> mMaterials;
+
+	//! List of all meshes loaded
 	std::vector<Mesh> mMeshes;
 
+	//! Pointer to the root node of the scene
 	Node* pcRootNode;
 };
 

+ 41 - 0
code/3DSLoader.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the 3ds importer class */
 #include "3DSLoader.h"
 #include "MaterialSystem.h"

+ 253 - 204
code/3DSLoader.h

@@ -1,3 +1,44 @@
+
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definition of the .3ds importer class. */
 #ifndef AI_3DSIMPORTER_H_INC
 #define AI_3DSIMPORTER_H_INC
@@ -5,230 +46,238 @@
 #include <map>
 
 #include "BaseImporter.h"
-
 #include "../include/aiTypes.h"
 
 struct aiNode;
-
 #include "3DSHelper.h"
+
 namespace Assimp
 {
-	class MaterialHelper;
+class MaterialHelper;
 
-	using namespace Dot3DS;
+using namespace Dot3DS;
 
-	// ---------------------------------------------------------------------------
-	/** The Dot3DSImporter is a worker class capable of importing a scene from a
-	* 3ds Max 4/5 File (.3ds)
-	*/
-	class Dot3DSImporter : public BaseImporter
+// ---------------------------------------------------------------------------
+/** The Dot3DSImporter is a worker class capable of importing a scene from a
+* 3ds Max 4/5 Files (.3ds)
+*/
+class Dot3DSImporter : public BaseImporter
+{
+	friend class Importer;
+
+protected:
+	/** Constructor to be privately used by Importer */
+	Dot3DSImporter();
+
+	/** Destructor, private as well */
+	~Dot3DSImporter();
+
+public:
+	// -------------------------------------------------------------------
+	/** Returns whether the class can handle the format of the given file. 
+	* See BaseImporter::CanRead() for details.	*/
+	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+
+protected:
+
+	// -------------------------------------------------------------------
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 * See BaseImporter::GetExtensionList() for details
+	 */
+	void GetExtensionList(std::string& append)
 	{
-		friend class Importer;
-
-	protected:
-		/** Constructor to be privately used by Importer */
-		Dot3DSImporter();
-
-		/** Destructor, private as well */
-		~Dot3DSImporter();
-
-	public:
-		// -------------------------------------------------------------------
-		/** Returns whether the class can handle the format of the given file. 
-		* See BaseImporter::CanRead() for details.	*/
-		bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
-
-	protected:
-		// -------------------------------------------------------------------
-		/** Imports the given file into the given scene structure. 
-		* See BaseImporter::InternReadFile() for details
-		*/
-		void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
-
-
-		// -------------------------------------------------------------------
-		/** Converts a temporary material to the outer representation 
-		*/
-		void ConvertMaterial(Dot3DS::Material& p_cMat,
-			MaterialHelper& p_pcOut);
-
-
-		// -------------------------------------------------------------------
-		/** Read a chunk, get a pointer to it
-		*  The mCurrent pointer will be increased by sizeof(Dot3DSFile::Chunk),
-		* thus pointing directly to the data of the chunk
-		*/
-		void ReadChunk(const Dot3DSFile::Chunk** p_ppcOut);
-
-		// -------------------------------------------------------------------
-		/** Parse a percentage chunk. mCurrent will point to the next
-		* chunk behind afterwards. If no percentage chunk is found
-		* QNAN is returned.
-		*/
-		float ParsePercentageChunk();
-
-		// -------------------------------------------------------------------
-		/** Parse a color chunk. mCurrent will point to the next
-		* chunk behind afterwards. If no color chunk is found
-		* QNAN is returned in all members.
-		*/
-		void ParseColorChunk(aiColor3D* p_pcOut,
-			bool p_bAcceptPercent = true);
-
-
-		// -------------------------------------------------------------------
-		/** Skip a chunk in the file
-		*/
-		void SkipChunk();
-
-		// -------------------------------------------------------------------
-		/** Generate the nodegraph
-		*/
-		void GenerateNodeGraph(aiScene* pcOut);
-
-		// -------------------------------------------------------------------
-		/** Parse a main top-level chunk in the file
-		*/
-		void ParseMainChunk(int* piRemaining);
-
-		// -------------------------------------------------------------------
-		/** Parse a top-level chunk in the file
-		*/
-		void ParseChunk(int* piRemaining);
-
-		// -------------------------------------------------------------------
-		/** Parse a top-level editor chunk in the file
-		*/
-		void ParseEditorChunk(int* piRemaining);
-
-		// -------------------------------------------------------------------
-		/** Parse a top-level object chunk in the file
-		*/
-		void ParseObjectChunk(int* piRemaining);
-
-		// -------------------------------------------------------------------
-		/** Parse a material chunk in the file
-		*/
-		void ParseMaterialChunk(int* piRemaining);
-
-		// -------------------------------------------------------------------
-		/** Apply texture coordinate offsets
-		*/
-		void ApplyScaleNOffset();
-		void BakeScaleNOffset(aiMesh* pcMesh, Dot3DS::Material* pcSrc);
-
-		// -------------------------------------------------------------------
-		/** Parse a mesh chunk in the file
-		*/
-		void ParseMeshChunk(int* piRemaining);
-
-		// -------------------------------------------------------------------
-		/** Parse a face list chunk in the file
-		*/
-		void ParseFaceChunk(int* piRemaining);
-
-		// -------------------------------------------------------------------
-		/** Parse a keyframe chunk in the file
-		*/
-		void ParseKeyframeChunk(int* piRemaining);
-
-		// -------------------------------------------------------------------
-		/** Parse a hierarchy chunk in the file
-		*/
-		void ParseHierarchyChunk(int* piRemaining);
-
-		// -------------------------------------------------------------------
-		/** Parse a texture chunk in the file
-		*/
-		void ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut);
-
-		// -------------------------------------------------------------------
-		/** Convert the meshes in the file
-		*/
-		void ConvertMeshes(aiScene* pcOut);
-
-		// -------------------------------------------------------------------
-		/** Replace the default material in the scene
-		*/
-		void ReplaceDefaultMaterial();
-
-		// -------------------------------------------------------------------
-		/** Convert the whole scene
-		*/
-		void ConvertScene(aiScene* pcOut);
-
-		// -------------------------------------------------------------------
-		/** U/V Scaling/Offset handling
-		*/
-		void GenTexCoord (Dot3DS::Texture* pcTexture,
-			const std::vector<aiVector2D>& p_vIn,
-			std::vector<aiVector2D>& p_vOut);
-
-		// -------------------------------------------------------------------
-		/** generate normal vectors for a given mesh
-		*/
-		void GenNormals(Dot3DS::Mesh* sMesh);
-
-
-		// -------------------------------------------------------------------
-		/** generate unique vertices for a mesh
-		*/
-		void MakeUnique(Dot3DS::Mesh* sMesh);
+		append.append("*.3ds");
+	}
+
+	// -------------------------------------------------------------------
+	/** Imports the given file into the given scene structure. 
+	* See BaseImporter::InternReadFile() for details
+	*/
+	void InternReadFile( const std::string& pFile, aiScene* pScene, 
+		IOSystem* pIOHandler);
+
+	// -------------------------------------------------------------------
+	/** Converts a temporary material to the outer representation 
+	*/
+	void ConvertMaterial(Dot3DS::Material& p_cMat,
+		MaterialHelper& p_pcOut);
+
+	// -------------------------------------------------------------------
+	/** Read a chunk, get a pointer to it
+	*  The mCurrent pointer will be increased by sizeof(Dot3DSFile::Chunk),
+	* thus pointing directly to the data of the chunk
+	*/
+	void ReadChunk(const Dot3DSFile::Chunk** p_ppcOut);
+
+	// -------------------------------------------------------------------
+	/** Parse a percentage chunk. mCurrent will point to the next
+	* chunk behind afterwards. If no percentage chunk is found
+	* QNAN is returned.
+	*/
+	float ParsePercentageChunk();
+
+	// -------------------------------------------------------------------
+	/** Parse a color chunk. mCurrent will point to the next
+	* chunk behind afterwards. If no color chunk is found
+	* QNAN is returned in all members.
+	*/
+	void ParseColorChunk(aiColor3D* p_pcOut,
+		bool p_bAcceptPercent = true);
+
+
+	// -------------------------------------------------------------------
+	/** Skip a chunk in the file
+	*/
+	void SkipChunk();
+
+	// -------------------------------------------------------------------
+	/** Generate the nodegraph
+	*/
+	void GenerateNodeGraph(aiScene* pcOut);
+
+	// -------------------------------------------------------------------
+	/** Parse a main top-level chunk in the file
+	*/
+	void ParseMainChunk(int* piRemaining);
+
+	// -------------------------------------------------------------------
+	/** Parse a top-level chunk in the file
+	*/
+	void ParseChunk(int* piRemaining);
+
+	// -------------------------------------------------------------------
+	/** Parse a top-level editor chunk in the file
+	*/
+	void ParseEditorChunk(int* piRemaining);
+
+	// -------------------------------------------------------------------
+	/** Parse a top-level object chunk in the file
+	*/
+	void ParseObjectChunk(int* piRemaining);
+
+	// -------------------------------------------------------------------
+	/** Parse a material chunk in the file
+	*/
+	void ParseMaterialChunk(int* piRemaining);
+
+	// -------------------------------------------------------------------
+	/** Apply texture coordinate offsets
+	*/
+	void ApplyScaleNOffset();
+	void BakeScaleNOffset(aiMesh* pcMesh, Dot3DS::Material* pcSrc);
+
+	// -------------------------------------------------------------------
+	/** Parse a mesh chunk in the file
+	*/
+	void ParseMeshChunk(int* piRemaining);
+
+	// -------------------------------------------------------------------
+	/** Parse a face list chunk in the file
+	*/
+	void ParseFaceChunk(int* piRemaining);
+
+	// -------------------------------------------------------------------
+	/** Parse a keyframe chunk in the file
+	*/
+	void ParseKeyframeChunk(int* piRemaining);
+
+	// -------------------------------------------------------------------
+	/** Parse a hierarchy chunk in the file
+	*/
+	void ParseHierarchyChunk(int* piRemaining);
+
+	// -------------------------------------------------------------------
+	/** Parse a texture chunk in the file
+	*/
+	void ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut);
+
+	// -------------------------------------------------------------------
+	/** Convert the meshes in the file
+	*/
+	void ConvertMeshes(aiScene* pcOut);
+
+	// -------------------------------------------------------------------
+	/** Replace the default material in the scene
+	*/
+	void ReplaceDefaultMaterial();
+
+	// -------------------------------------------------------------------
+	/** Convert the whole scene
+	*/
+	void ConvertScene(aiScene* pcOut);
+
+	// -------------------------------------------------------------------
+	/** U/V Scaling/Offset handling
+	*/
+	void GenTexCoord (Dot3DS::Texture* pcTexture,
+		const std::vector<aiVector2D>& p_vIn,
+		std::vector<aiVector2D>& p_vOut);
+
+	// -------------------------------------------------------------------
+	/** generate normal vectors for a given mesh
+	*/
+	void GenNormals(Dot3DS::Mesh* sMesh);
+
+
+	// -------------------------------------------------------------------
+	/** generate unique vertices for a mesh
+	*/
+	void MakeUnique(Dot3DS::Mesh* sMesh);
+
 
-
-		// -------------------------------------------------------------------
-		/** Add a node to the node graph
-		*/
-		void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node* pcIn);
-
-		// -------------------------------------------------------------------
-		/** Search for a node in the graph.
-		* Called recursively
-		*/
-		void InverseNodeSearch(Dot3DS::Node* pcNode,Dot3DS::Node* pcCurrent);
-
-
-		// -------------------------------------------------------------------
-		/** Apply the master scaling factor to the mesh
-		*/
-		void ApplyMasterScale(aiScene* pScene);
-
-
-		// -------------------------------------------------------------------
-		/** Clamp all indices in the file to a valid range
-		*/
-		void Dot3DSImporter::CheckIndices(Dot3DS::Mesh* sMesh);
+	// -------------------------------------------------------------------
+	/** Add a node to the node graph
+	*/
+	void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node* pcIn);
+
+	// -------------------------------------------------------------------
+	/** Search for a node in the graph.
+	* Called recursively
+	*/
+	void InverseNodeSearch(Dot3DS::Node* pcNode,Dot3DS::Node* pcCurrent);
+
+
+	// -------------------------------------------------------------------
+	/** Apply the master scaling factor to the mesh
+	*/
+	void ApplyMasterScale(aiScene* pScene);
+
+
+	// -------------------------------------------------------------------
+	/** Clamp all indices in the file to a valid range
+	*/
+	void Dot3DSImporter::CheckIndices(Dot3DS::Mesh* sMesh);
 
 
-	protected:
-		/** Buffer to hold the loaded file */
-		unsigned char* mBuffer;
+protected:
+	/** Buffer to hold the loaded file */
+	unsigned char* mBuffer;
 
-		/** Pointer to the current read position */
-		const unsigned char* mCurrent;
+	/** Pointer to the current read position */
+	const unsigned char* mCurrent;
 
-		/** Used to store old chunk addresses to jump back in the file*/
-		const unsigned char* mLast;
+	/** Used to store old chunk addresses to jump back in the file*/
+	const unsigned char* mLast;
 
-		/** Last touched node index */
-		short mLastNodeIndex;
+	/** Last touched node index */
+	short mLastNodeIndex;
 
-		/** Current node, root node */
-		Dot3DS::Node* mCurrentNode, *mRootNode;
+	/** Current node, root node */
+	Dot3DS::Node* mCurrentNode, *mRootNode;
 
-		/** Scene under construction */
-		Dot3DS::Scene* mScene;
+	/** Scene under construction */
+	Dot3DS::Scene* mScene;
 
-		/** Ambient base color of the scene */
-		aiColor3D mClrAmbient;
+	/** Ambient base color of the scene */
+	aiColor3D mClrAmbient;
 
-		/** Master scaling factor of the scene */
-		float mMasterScale;
+	/** Master scaling factor of the scene */
+	float mMasterScale;
 
-		/** Path to the background image of the scene */
-		std::string mBackgroundImage;
-		bool bHasBG;
-	};
+	/** Path to the background image of the scene */
+	std::string mBackgroundImage;
+	bool bHasBG;
+};
 
 } // end of namespace Assimp
 

+ 81 - 57
code/3DSSpatialSort.cpp

@@ -1,67 +1,64 @@
-/** @file Implementation of the helper class to quickly find vertices close to a given position */
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the helper class to quickly find 
+ vertices close to a given position. Special implementation for 
+ the 3ds loader handling smooth groups correctly  */
+
 #include <algorithm>
 #include "3DSSpatialSort.h"
 
+#include "aiAssert.h"
+
 using namespace Assimp;
 using namespace Assimp::Dot3DS;
 
-// ------------------------------------------------------------------------------------------------
-// Constructs a spatially sorted representation from the given position array.
-D3DSSpatialSorter::D3DSSpatialSorter( const aiVector3D* pPositions,
-									 unsigned int pNumPositions, unsigned int pElementOffset)
-	{
-	// define the reference plane. We choose some arbitrary vector away from all basic axises 
-	// in the hope that no model spreads all its vertices along this plane.
-	mPlaneNormal.Set( 0.8523f, 0.34321f, 0.5736f);
-	mPlaneNormal.Normalize();
-
-	// store references to all given positions along with their distance to the reference plane
-	mPositions.reserve( pNumPositions);
-	for( unsigned int a = 0; a < pNumPositions; a++)
-		{
-		const char* tempPointer = reinterpret_cast<const char*> (pPositions);
-		const aiVector3D* vec = reinterpret_cast<const aiVector3D*> (tempPointer + a * pElementOffset);
 
-		// store position by index and distance
-		float distance = *vec * mPlaneNormal;
-		mPositions.push_back( Entry( a, *vec, distance,0));
-		}
-
-	// now sort the array ascending by distance.
-	std::sort( mPositions.begin(), mPositions.end());
-	}
 // ------------------------------------------------------------------------------------------------
-D3DSSpatialSorter::D3DSSpatialSorter( const Dot3DS::Mesh* p_pcMesh)
+D3DSSpatialSorter::D3DSSpatialSorter()
 	{
 	// define the reference plane. We choose some arbitrary vector away from all basic axises 
 	// in the hope that no model spreads all its vertices along this plane.
 	mPlaneNormal.Set( 0.8523f, 0.34321f, 0.5736f);
 	mPlaneNormal.Normalize();
-
-	// store references to all given positions along with their distance to the reference plane
-	mPositions.reserve( p_pcMesh->mPositions.size());
-	for( std::vector<Dot3DS::Face>::const_iterator
-		i =  p_pcMesh->mFaces.begin();
-		i != p_pcMesh->mFaces.end();++i)
-		{
-		// store position by index and distance
-		float distance = p_pcMesh->mPositions[(*i).i1] * mPlaneNormal;
-		mPositions.push_back( Entry( (*i).i1, p_pcMesh->mPositions[(*i).i1], 
-			distance, (*i).iSmoothGroup));
-
-		// triangle vertex 2
-		distance = p_pcMesh->mPositions[(*i).i2] * mPlaneNormal;
-		mPositions.push_back( Entry( (*i).i2, p_pcMesh->mPositions[(*i).i2], 
-			distance, (*i).iSmoothGroup));
-
-		// triangle vertex 3
-		distance = p_pcMesh->mPositions[(*i).i3] * mPlaneNormal;
-		mPositions.push_back( Entry( (*i).i3, p_pcMesh->mPositions[(*i).i3], 
-			distance, (*i).iSmoothGroup));
-		}
-
-	// now sort the array ascending by distance.
-	std::sort( this->mPositions.begin(), this->mPositions.end());
 	}
 // ------------------------------------------------------------------------------------------------
 // Destructor
@@ -69,11 +66,39 @@ D3DSSpatialSorter::~D3DSSpatialSorter()
 	{
 	// nothing to do here, everything destructs automatically
 	}
-
+// ------------------------------------------------------------------------------------------------
+void D3DSSpatialSorter::AddFace(const Dot3DS::Face* pcFace,
+	const std::vector<aiVector3D>& vPositions)
+{
+	ai_assert(NULL != pcFace);
+
+	// store position by index and distance
+	float distance = vPositions[pcFace->i1] * mPlaneNormal;
+	mPositions.push_back( Entry( pcFace->i1, vPositions[pcFace->i1], 
+		distance, pcFace->iSmoothGroup));
+
+	// triangle vertex 2
+	distance = vPositions[pcFace->i2] * mPlaneNormal;
+	mPositions.push_back( Entry( pcFace->i2, vPositions[pcFace->i2], 
+		distance, pcFace->iSmoothGroup));
+
+	// triangle vertex 3
+	distance = vPositions[pcFace->i3] * mPlaneNormal;
+	mPositions.push_back( Entry( pcFace->i3, vPositions[pcFace->i3], 
+		distance, pcFace->iSmoothGroup));
+}
+// ------------------------------------------------------------------------------------------------
+void D3DSSpatialSorter::Prepare()
+{
+	// now sort the array ascending by distance.
+	std::sort( this->mPositions.begin(), this->mPositions.end());
+}
 // ------------------------------------------------------------------------------------------------
 // Returns an iterator for all positions close to the given position.
 void D3DSSpatialSorter::FindPositions( const aiVector3D& pPosition, 
-									  uint32_t pSG,float pRadius, std::vector<unsigned int>& poResults) const
+	uint32_t pSG,
+	float pRadius,
+	std::vector<unsigned int>& poResults) const
 	{
 	float dist = pPosition * mPlaneNormal;
 	float minDist = dist - pRadius, maxDist = dist + pRadius;
@@ -113,10 +138,10 @@ void D3DSSpatialSorter::FindPositions( const aiVector3D& pPosition,
 	// Mow start iterating from there until the first position lays outside of the distance range.
 	// Add all positions inside the distance range within the given radius to the result aray
 
+	float squareEpsilon = pRadius * pRadius;
+	std::vector<Entry>::const_iterator it = mPositions.begin() + index;
 	if (0 == pSG)
 		{
-		std::vector<Entry>::const_iterator it = mPositions.begin() + index;
-		float squareEpsilon = pRadius * pRadius;
 		while( it->mDistance < maxDist)
 			{
 			if((it->mPosition - pPosition).SquareLength() < squareEpsilon)
@@ -130,8 +155,6 @@ void D3DSSpatialSorter::FindPositions( const aiVector3D& pPosition,
 		}
 	else
 		{
-		std::vector<Entry>::const_iterator it = mPositions.begin() + index;
-		float squareEpsilon = pRadius * pRadius;
 		while( it->mDistance < maxDist)
 			{
 			if((it->mPosition - pPosition).SquareLength() < squareEpsilon &&
@@ -144,5 +167,6 @@ void D3DSSpatialSorter::FindPositions( const aiVector3D& pPosition,
 				break;
 			}
 		}
+	return;
 	}
 

+ 63 - 15
code/3DSSpatialSort.h

@@ -1,10 +1,55 @@
-/** Small helper classes to optimise finding vertizes close to a given location */
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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.
+
+----------------------------------------------------------------------
+*/
+
+/** Small helper classes to optimise finding vertizes close to a given location
+ */
 #ifndef AI_D3DSSPATIALSORT_H_INC
 #define AI_D3DSSPATIALSORT_H_INC
 
 #include <vector>
 #include "../include/aiVector3D.h"
-#include "3DSHelper.h"
+
+
+#if (!defined AI_BUILD_NO_ASE_IMPORTER)
+#	include "3DSHelper.h"
+#endif
 
 namespace Assimp
 {
@@ -19,28 +64,30 @@ class D3DSSpatialSorter
 {
 public:
 
-	D3DSSpatialSorter() {/* This is unintialized. This is evil. This is OK. */}
+	D3DSSpatialSorter();
 
-	/** Constructs a spatially sorted representation from the given position array.
-	 * Supply the positions in its layout in memory, the class will only refer to them
-	 * by index.
-	 * @param pPositions Pointer to the first position vector of the array.
-	 * @param pNumPositions Number of vectors to expect in that array.
-	 * @param pElementOffset Offset in bytes from the beginning of one vector in memory to the beginning of the next vector.
-	 * @note Smoothing groups are ignored
+	// -------------------------------------------------------------------
+	/** Construction from a given face array, handling smoothing groups properly
 	 */
-	D3DSSpatialSorter( const aiVector3D* pPositions,
-		unsigned int pNumPositions, unsigned int pElementOffset);
+	D3DSSpatialSorter(const std::vector<aiVector3D>& vPositions);
 
-	/** Construction from a given face array, handling smoothing groups properly
-	 * @param p_pcMesh Input mesh.
+	// -------------------------------------------------------------------
+	/** Add a face to the spatial sorter
+	 * @param pcFace Face to be added
+	 * @param vPositions Input position list
 	 */
-	D3DSSpatialSorter( const Dot3DS::Mesh* p_pcMesh);
+	void AddFace(const Dot3DS::Face* pcFace,
+		const std::vector<aiVector3D>& vPositions);
 
+	// -------------------------------------------------------------------
+	/** Prepare the spatial sorter for use
+	 */
+	void Prepare();
 
 	/** Destructor */
 	~D3DSSpatialSorter();
 
+	// -------------------------------------------------------------------
 	/** Returns an iterator for all positions close to the given position.
 	 * @param pPosition The position to look for vertices.
 	 * @param pSG Only included vertices with at least one shared smooth group
@@ -56,6 +103,7 @@ protected:
 	/** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */
 	aiVector3D mPlaneNormal;
 
+	// -------------------------------------------------------------------
 	/** An entry in a spatially sorted position array. Consists of a vertex index,
 	 * its position and its precalculated distance from the reference plane */
 	struct Entry

+ 720 - 0
code/ASELoader.cpp

@@ -0,0 +1,720 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the ASE importer class */
+#include "ASELoader.h"
+#include "3DSSpatialSort.h"
+#include "MaterialSystem.h"
+
+#include "../include/IOStream.h"
+#include "../include/IOSystem.h"
+#include "../include/aiMesh.h"
+#include "../include/aiScene.h"
+#include "../include/aiAssert.h"
+
+#include <boost/scoped_ptr.hpp>
+
+using namespace Assimp;
+using namespace Assimp::ASE;
+
+#define LOGOUT_WARN(x)
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+ASEImporter::ASEImporter()
+{
+}
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well 
+ASEImporter::~ASEImporter()
+{
+}
+// ------------------------------------------------------------------------------------------------
+// Returns whether the class can handle the format of the given file. 
+bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
+{
+	// simple check of file extension is enough for the moment
+	std::string::size_type pos = pFile.find_last_of('.');
+	// no file extension - can't read
+	if( pos == std::string::npos)
+		return false;
+	std::string extension = pFile.substr( pos);
+
+	if (extension.length() < 4)return false;
+	if (extension[0] != '.')return false;
+
+	if (extension[1] != 'a' && extension[1] != 'A')return false;
+	if (extension[2] != 's' && extension[2] != 'S')return false;
+
+	// NOTE: Sometimes the extension .ASK is also used
+	if (extension[3] != 'e' && extension[3] != 'E' &&
+		extension[3] != 'k' && extension[3] != 'K')return false;
+
+	return true;
+}
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure. 
+void ASEImporter::InternReadFile( 
+	const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
+{
+	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+	// Check whether we can read from the file
+	if( file.get() == NULL)
+	{
+		throw new ImportErrorException( "Failed to open ASE file " + pFile + ".");
+	}
+
+	size_t fileSize = file->FileSize();
+
+	// allocate storage and copy the contents of the file to a memory buffer
+	// (terminate it with zero)
+	this->mBuffer = new unsigned char[fileSize+1];
+	file->Read( (void*)mBuffer, 1, fileSize);
+	this->mBuffer[fileSize] = '\0';
+
+	// construct an ASE parser and parse the file
+	this->mParser = new ASE::Parser((const char*)this->mBuffer);
+	this->mParser->Parse();
+
+	// process all meshes
+	for (std::vector<ASE::Mesh>::iterator
+		i =  this->mParser->m_vMeshes.begin();
+		i != this->mParser->m_vMeshes.end();++i)
+	{
+		// need to generate proper vertex normals if necessary
+		this->GenerateNormals(*i);
+
+		// now we need to create proper meshes from the import
+		// we need to split them by materials, build valid vertex/face lists ...
+		this->BuildUniqueRepresentation(*i);
+		this->ConvertMeshes(*i,pScene);
+	}
+	// buil final material indices (remove submaterials and make the final list)
+	this->BuildMaterialIndices(pScene);
+
+	// build the final node graph
+	this->BuildNodes(pScene);
+
+	// delete the ASE parser
+	delete this->mParser;
+	this->mParser = NULL;
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void ASEImporter::BuildNodes(aiScene* pcScene)
+{
+	ai_assert(NULL != pcScene);
+
+	pcScene->mRootNode = new aiNode();
+	pcScene->mRootNode->mNumMeshes = pcScene->mNumMeshes;
+	pcScene->mRootNode->mMeshes = new unsigned int[pcScene->mRootNode->mNumMeshes];
+
+	for (unsigned int i = 0; i < pcScene->mRootNode->mNumMeshes;++i)
+		pcScene->mRootNode->mMeshes[i] = i;
+
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
+{
+	// allocate output storage
+	std::vector<aiVector3D> mPositions;
+	std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+	std::vector<aiColor4D> mVertexColors;
+	std::vector<aiVector3D> mNormals;
+
+	unsigned int iSize = mesh.mFaces.size() * 3;
+	mPositions.resize(iSize);
+
+	// optional texture coordinates
+	for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+	{
+		if (!mesh.amTexCoords[i].empty())
+		{
+			amTexCoords[i].resize(iSize);
+		}
+	}
+	// optional vertex colors
+	if (!mesh.mVertexColors.empty())
+	{
+		mVertexColors.resize(iSize);
+	}
+
+	// optional vertex normals (vertex normals can simply be copied)
+	if (!mesh.mNormals.empty())
+	{
+		mNormals.resize(iSize);
+	}
+
+	// iterate through all faces in the mesh
+	unsigned int iCurrent = 0;
+	for (std::vector<ASE::Face>::iterator
+		i =  mesh.mFaces.begin();
+		i != mesh.mFaces.end();++i)
+	{
+		for (unsigned int n = 0; n < 3;++n,++iCurrent)
+		{
+			mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]];
+
+			// add texture coordinates
+			for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+			{
+				if (!mesh.amTexCoords[c].empty())
+				{
+					amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]];
+				}
+			}
+			// add vertex colors
+			if (!mesh.mVertexColors.empty())
+			{
+				mVertexColors[iCurrent] = mesh.mVertexColors[(*i).mColorIndices[n]];
+			}
+			// add normal vectors
+			if (!mesh.mNormals.empty())
+			{
+				mNormals[iCurrent] = mesh.mNormals[(*i).mIndices[n]];
+			}
+			// assign a new valid index to the face
+			(*i).mIndices[n] = iCurrent;
+		}
+	}
+
+	// replace the old arrays
+	mesh.mNormals = mNormals;
+	mesh.mPositions = mPositions;
+	mesh.mVertexColors = mVertexColors;
+
+	for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+		mesh.amTexCoords[c] = amTexCoords[c];
+
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void ASEImporter::ConvertMaterial(ASE::Material& mat)
+{
+	// allocate the output material
+	mat.pcInstance = new MaterialHelper();
+
+	// At first add the base ambient color of the
+	// scene to	the material
+	mat.mAmbient.r += this->mParser->m_clrAmbient.r;
+	mat.mAmbient.g += this->mParser->m_clrAmbient.g;
+	mat.mAmbient.b += this->mParser->m_clrAmbient.b;
+
+	aiString name;
+	name.Set( mat.mName);
+	mat.pcInstance->AddProperty( &name, AI_MATKEY_NAME);
+
+	// material colors
+	mat.pcInstance->AddProperty( &mat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
+	mat.pcInstance->AddProperty( &mat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+	mat.pcInstance->AddProperty( &mat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
+	mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
+	mat.pcInstance->AddProperty( &mat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
+
+	// opacity
+	mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY);
+
+
+	// shading mode
+	aiShadingMode eShading = aiShadingMode_NoShading;
+	switch (mat.mShading)
+	{
+		case Dot3DS::Dot3DSFile::Flat:
+			eShading = aiShadingMode_Flat; break;
+		case Dot3DS::Dot3DSFile::Phong :
+			eShading = aiShadingMode_Phong; break;
+
+		// I don't know what "Wire" shading should be,
+		// assume it is simple lambertian diffuse (L dot N) shading
+		case Dot3DS::Dot3DSFile::Wire:
+		case Dot3DS::Dot3DSFile::Gouraud:
+			eShading = aiShadingMode_Gouraud; break;
+		case Dot3DS::Dot3DSFile::Metal :
+			eShading = aiShadingMode_CookTorrance; break;
+	}
+	mat.pcInstance->AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
+
+	if (Dot3DS::Dot3DSFile::Wire == mat.mShading)
+	{
+		// set the wireframe flag
+		unsigned int iWire = 1;
+		mat.pcInstance->AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
+	}
+
+	// texture, if there is one
+	if( mat.sTexDiffuse.mMapName.length() > 0)
+	{
+		aiString tex;
+		tex.Set( mat.sTexDiffuse.mMapName);
+		mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
+
+		if (is_not_qnan(mat.sTexDiffuse.mTextureBlend))
+			mat.pcInstance->AddProperty<float>( &mat.sTexDiffuse.mTextureBlend, 1, 
+			AI_MATKEY_TEXBLEND_DIFFUSE(0));
+	}
+	if( mat.sTexSpecular.mMapName.length() > 0)
+	{
+		aiString tex;
+		tex.Set( mat.sTexSpecular.mMapName);
+		mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(0));
+
+		if (is_not_qnan(mat.sTexSpecular.mTextureBlend))
+			mat.pcInstance->AddProperty<float>( &mat.sTexSpecular.mTextureBlend, 1,
+			AI_MATKEY_TEXBLEND_SPECULAR(0));
+	}
+	if( mat.sTexOpacity.mMapName.length() > 0)
+	{
+		aiString tex;
+		tex.Set( mat.sTexOpacity.mMapName);
+		mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_OPACITY(0));
+
+		if (is_not_qnan(mat.sTexOpacity.mTextureBlend))
+			mat.pcInstance->AddProperty<float>( &mat.sTexOpacity.mTextureBlend, 1,
+			AI_MATKEY_TEXBLEND_OPACITY(0));
+	}
+	if( mat.sTexEmissive.mMapName.length() > 0)
+	{
+		aiString tex;
+		tex.Set( mat.sTexEmissive.mMapName);
+		mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(0));
+
+		if (is_not_qnan(mat.sTexEmissive.mTextureBlend))
+			mat.pcInstance->AddProperty<float>( &mat.sTexEmissive.mTextureBlend, 1, 
+			AI_MATKEY_TEXBLEND_EMISSIVE(0));
+	}
+	if( mat.sTexAmbient.mMapName.length() > 0)
+	{
+		aiString tex;
+		tex.Set( mat.sTexAmbient.mMapName);
+		mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(0));
+
+		if (is_not_qnan(mat.sTexAmbient.mTextureBlend))
+			mat.pcInstance->AddProperty<float>( &mat.sTexAmbient.mTextureBlend, 1, 
+			AI_MATKEY_TEXBLEND_AMBIENT(0));
+	}
+	if( mat.sTexBump.mMapName.length() > 0)
+	{
+		aiString tex;
+		tex.Set( mat.sTexBump.mMapName);
+		mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(0));
+
+		if (is_not_qnan(mat.sTexBump.mTextureBlend))
+			mat.pcInstance->AddProperty<float>( &mat.sTexBump.mTextureBlend, 1,
+			AI_MATKEY_TEXBLEND_HEIGHT(0));
+	}
+	if( mat.sTexShininess.mMapName.length() > 0)
+	{
+		aiString tex;
+		tex.Set( mat.sTexShininess.mMapName);
+		mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_SHININESS(0));
+
+		if (is_not_qnan(mat.sTexShininess.mTextureBlend))
+			mat.pcInstance->AddProperty<float>( &mat.sTexBump.mTextureBlend, 1, 
+			AI_MATKEY_TEXBLEND_SHININESS(0));
+	}
+
+	// store the name of the material itself, too
+	if( mat.mName.length() > 0)
+	{
+		aiString tex;
+		tex.Set( mat.mName);
+		mat.pcInstance->AddProperty( &tex, AI_MATKEY_NAME);
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
+{
+	ai_assert(NULL != pcScene);
+
+	// validate the material index of the mesh
+	if (mesh.iMaterialIndex >= this->mParser->m_vMaterials.size())
+	{
+		mesh.iMaterialIndex = this->mParser->m_vMaterials.size()-1;
+		LOGOUT_WARN("Material index is out of range");
+	}
+
+	// List of all output meshes
+	std::vector<aiMesh*> avOutMeshes;
+
+	// if the material the mesh is assigned to is consisting of submeshes
+	// we'll need to split it ... Quak.
+	if (!this->mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty())
+	{
+		std::vector<ASE::Material> vSubMaterials = this->mParser->
+			m_vMaterials[mesh.iMaterialIndex].avSubMaterials;
+
+		std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[
+			vSubMaterials.size()];
+
+		// build a list of all faces per submaterial
+		unsigned int iNum = 0;
+		for (unsigned int i = 0; i < mesh.mFaces.size();++i)
+		{
+			// check range
+			if (mesh.mFaces[i].iMaterial >= vSubMaterials.size())
+				{
+					LOGOUT_WARN("Submaterial index is out of range");
+
+					// use the last material instead
+					aiSplit[vSubMaterials.size()-1].push_back(i);
+				}
+			else aiSplit[mesh.mFaces[i].iMaterial].push_back(i);
+		}
+
+		// now generate submeshes
+		for (unsigned int p = 0; p < vSubMaterials.size();++p)
+		{
+			if (aiSplit[p].size() != 0)
+			{
+				aiMesh* p_pcOut = new aiMesh();
+
+				// let the sub material index
+				p_pcOut->mMaterialIndex = p;
+
+				// we will need this material
+				this->mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials[p].bNeed = true;
+
+				// store the real index here ...
+				p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
+				avOutMeshes.push_back(p_pcOut);
+
+				// convert vertices
+				p_pcOut->mNumVertices = aiSplit[p].size()*3;
+				p_pcOut->mNumFaces = aiSplit[p].size();
+
+				// allocate enough storage for faces
+				p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
+
+				if (p_pcOut->mNumVertices != 0)
+				{
+					p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices];
+					p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices];
+					unsigned int iBase = 0;
+
+					for (unsigned int q = 0; q < aiSplit[p].size();++q)
+					{
+						unsigned int iIndex = aiSplit[p][q];
+
+						p_pcOut->mFaces[q].mIndices = new unsigned int[3];
+						p_pcOut->mFaces[q].mNumIndices = 3;
+
+						for (unsigned int t = 0; t < 3;++t)
+						{
+							p_pcOut->mFaces[q].mIndices[t] = iBase;
+							p_pcOut->mVertices[iBase] = mesh.mPositions[mesh.mFaces[iIndex].mIndices[t]];
+							p_pcOut->mNormals[iBase++] = mesh.mNormals[mesh.mFaces[iIndex].mIndices[t]];
+						}
+					}
+				}
+				// convert texture coordinates
+				for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+				{
+					if (!mesh.amTexCoords[c].empty())
+					{
+						p_pcOut->mTextureCoords[c] = new aiVector3D[p_pcOut->mNumVertices];
+						unsigned int iBase = 0;
+						for (unsigned int q = 0; q < aiSplit[p].size();++q)
+						{
+							unsigned int iIndex = aiSplit[p][q];
+							for (unsigned int t = 0; t < 3;++t)
+							{
+								p_pcOut->mTextureCoords[c][iBase++] = mesh.amTexCoords[c][mesh.mFaces[iIndex].mIndices[t]];
+							}
+						}
+						// setup the number of valid vertex components
+						p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c];
+					}
+				}
+
+				// convert vertex colors (only one set supported)
+				if (!mesh.mVertexColors.empty())
+				{
+					p_pcOut->mColors[0] = new aiColor4D[p_pcOut->mNumVertices];
+					unsigned int iBase = 0;
+					for (unsigned int q = 0; q < aiSplit[p].size();++q)
+					{
+						unsigned int iIndex = aiSplit[p][q];
+						for (unsigned int t = 0; t < 3;++t)
+						{
+							p_pcOut->mColors[0][iBase++] = mesh.mVertexColors[mesh.mFaces[iIndex].mIndices[t]];
+						}
+					}
+				}
+			}
+		}
+		// delete storage
+		delete[] aiSplit;
+	}
+	else
+	{
+		// otherwise we can simply copy the data to one output mesh
+		aiMesh* p_pcOut = new aiMesh();
+
+		// set an empty sub material index
+		p_pcOut->mMaterialIndex = ASE::Face::DEFAULT_MATINDEX;
+		this->mParser->m_vMaterials[mesh.iMaterialIndex].bNeed = true;
+
+		// store the real index here ...
+		p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
+		avOutMeshes.push_back(p_pcOut);
+
+		// convert vertices
+		p_pcOut->mNumVertices = mesh.mPositions.size();
+		p_pcOut->mNumFaces = mesh.mFaces.size();
+
+		// allocate enough storage for faces
+		p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
+
+		// copy vertices
+		p_pcOut->mVertices = new aiVector3D[mesh.mPositions.size()];
+		memcpy(p_pcOut->mVertices,&mesh.mPositions[0],
+			mesh.mPositions.size() * sizeof(aiVector3D));
+
+		// copy normals
+		p_pcOut->mNormals = new aiVector3D[mesh.mNormals.size()];
+		memcpy(p_pcOut->mNormals,&mesh.mNormals[0],
+			mesh.mNormals.size() * sizeof(aiVector3D));
+
+		// copy texture coordinates
+		for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+		{
+			if (!mesh.amTexCoords[c].empty())
+			{
+				p_pcOut->mTextureCoords[c] = new aiVector3D[mesh.amTexCoords[c].size()];
+				memcpy(p_pcOut->mTextureCoords[c],&mesh.amTexCoords[c][0],
+					mesh.amTexCoords[c].size() * sizeof(aiVector3D));
+
+				// setup the number of valid vertex components
+				p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c];
+			}
+		}
+
+		// copy vertex colors
+		if (!mesh.mVertexColors.empty())
+		{
+			p_pcOut->mColors[0] = new aiColor4D[mesh.mVertexColors.size()];
+			memcpy(p_pcOut->mColors[0],&mesh.mVertexColors[0],
+				mesh.mVertexColors.size() * sizeof(aiColor4D));
+		}
+
+		// copy faces
+		for (unsigned int iFace = 0; iFace < p_pcOut->mNumFaces;++iFace)
+		{
+			p_pcOut->mFaces[iFace].mNumIndices = 3;
+			p_pcOut->mFaces[iFace].mIndices = new unsigned int[3];
+
+			// copy indices
+			p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[0];
+			p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1];
+			p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[2];
+		}
+	}
+
+	// now build the output mesh list
+	pcScene->mNumMeshes = avOutMeshes.size();
+	pcScene->mMeshes = new aiMesh*[pcScene->mNumMeshes];
+	for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
+		pcScene->mMeshes[i] = avOutMeshes[i];
+
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void ASEImporter::BuildMaterialIndices(aiScene* pcScene)
+{
+	ai_assert(NULL != pcScene);
+
+	// iterate through all materials and check whether we need them
+	unsigned int iNum = 0;
+	for (unsigned int iMat = 0; iMat < this->mParser->m_vMaterials.size();++iMat)
+	{
+		if (this->mParser->m_vMaterials[iMat].bNeed)
+		{
+			// convert it to the aiMaterial layout
+			this->ConvertMaterial(this->mParser->m_vMaterials[iMat]);
+			iNum++;
+		}
+		for (unsigned int iSubMat = 0; iSubMat < this->mParser->m_vMaterials[
+			iMat].avSubMaterials.size();++iSubMat)
+		{
+			if (this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].bNeed)
+			{
+				// convert it to the aiMaterial layout
+				this->ConvertMaterial(this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat]);
+				iNum++;
+			}
+		}
+	}
+
+	// allocate the output material array
+	pcScene->mNumMaterials = iNum;
+	pcScene->mMaterials = new aiMaterial*[pcScene->mNumMaterials];
+
+	iNum = 0;
+	for (unsigned int iMat = 0; iMat < this->mParser->m_vMaterials.size();++iMat)
+	{
+		if (this->mParser->m_vMaterials[iMat].bNeed)
+		{
+			ai_assert(NULL != this->mParser->m_vMaterials[iMat].pcInstance);
+			pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat].pcInstance;
+
+			// iterate through all meshes and search for one which is using
+			// this top-level material index
+			for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
+			{
+				if (ASE::Face::DEFAULT_MATINDEX == pcScene->mMeshes[iMesh]->mMaterialIndex &&
+					iMat == (uintptr_t)pcScene->mMeshes[iMesh]->mColors[3])
+				{
+					pcScene->mMeshes[iMesh]->mMaterialIndex = iNum;
+					pcScene->mMeshes[iMesh]->mColors[3] = NULL;
+				}
+			}
+			iNum++;
+		}
+		for (unsigned int iSubMat = 0; iSubMat < this->mParser->m_vMaterials[iMat].avSubMaterials.size();++iSubMat)
+		{
+			if (this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].bNeed)
+			{
+				ai_assert(NULL != this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].pcInstance);
+				pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat].
+					avSubMaterials[iSubMat].pcInstance;
+
+				// iterate through all meshes and search for one which is using
+				// this sub-level material index
+				for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
+				{
+					if (iSubMat == pcScene->mMeshes[iMesh]->mMaterialIndex &&
+						iMat == (uintptr_t)pcScene->mMeshes[iMesh]->mColors[3])
+					{
+						pcScene->mMeshes[iMesh]->mMaterialIndex = iNum;
+						pcScene->mMeshes[iMesh]->mColors[3] = NULL;
+					}
+				}
+				iNum++;
+			}
+		}
+	}
+	// finished!
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+// Generate normal vectors basing on smoothing groups
+void ASEImporter::GenerateNormals(ASE::Mesh& mesh)
+{
+	if (mesh.mNormals.empty())
+	{
+		// need to calculate normals ... 
+		// TODO: Find a way to merge this with the code in 3DSGenNormals.cpp
+		mesh.mNormals.resize(mesh.mPositions.size(),aiVector3D());
+		for( unsigned int a = 0; a < mesh.mFaces.size(); a++)
+		{
+			const ASE::Face& face = mesh.mFaces[a];
+
+			// assume it is a triangle
+			aiVector3D* pV1 = &mesh.mPositions[face.i1];
+			aiVector3D* pV2 = &mesh.mPositions[face.i2];
+			aiVector3D* pV3 = &mesh.mPositions[face.i3];
+
+			aiVector3D pDelta1 = *pV2 - *pV1;
+			aiVector3D pDelta2 = *pV3 - *pV1;
+			aiVector3D vNor = pDelta1 ^ pDelta2;
+
+			mesh.mNormals[face.i1] = vNor;
+			mesh.mNormals[face.i2] = vNor;
+			mesh.mNormals[face.i3] = vNor;
+		}
+
+		// calculate the position bounds so we have a reliable epsilon to 
+		// check position differences against 
+		// @Schrompf: This is the 7th time this snippet is repeated!
+		aiVector3D minVec( 1e10f, 1e10f, 1e10f), maxVec( -1e10f, -1e10f, -1e10f);
+		for( unsigned int a = 0; a < mesh.mPositions.size(); a++)
+		{
+			minVec.x = std::min( minVec.x, mesh.mPositions[a].x);
+			minVec.y = std::min( minVec.y, mesh.mPositions[a].y);
+			minVec.z = std::min( minVec.z, mesh.mPositions[a].z);
+			maxVec.x = std::max( maxVec.x, mesh.mPositions[a].x);
+			maxVec.y = std::max( maxVec.y, mesh.mPositions[a].y);
+			maxVec.z = std::max( maxVec.z, mesh.mPositions[a].z);
+		}
+		const float posEpsilon = (maxVec - minVec).Length() * 1e-5f;
+
+		std::vector<aiVector3D> avNormals;
+		avNormals.resize(mesh.mNormals.size());
+
+		// now generate the spatial sort tree
+		D3DSSpatialSorter sSort;
+		for( std::vector<ASE::Face>::iterator
+			i =  mesh.mFaces.begin();
+			i != mesh.mFaces.end();++i){sSort.AddFace(&(*i),mesh.mPositions);}
+		sSort.Prepare();
+
+		for( std::vector<ASE::Face>::iterator
+			i =  mesh.mFaces.begin();
+			i != mesh.mFaces.end();++i)
+		{
+			std::vector<unsigned int> poResult;
+			for (unsigned int c = 0; c < 3;++c)
+			{
+				sSort.FindPositions(mesh.mPositions[(*i).mIndices[c]],(*i).iSmoothGroup,
+					posEpsilon,poResult);
+
+				aiVector3D vNormals;
+				float fDiv = 0.0f;
+				for (std::vector<unsigned int>::const_iterator
+					a =  poResult.begin();
+					a != poResult.end();++a)
+				{
+					vNormals += mesh.mNormals[(*a)];
+					fDiv += 1.0f;
+				}
+				vNormals.x /= fDiv;vNormals.y /= fDiv;vNormals.z /= fDiv;
+				vNormals.Normalize();
+				avNormals[(*i).mIndices[c]] = vNormals;
+				poResult.clear();
+			}
+		}
+		mesh.mNormals = avNormals;
+	}
+	return;
+}

+ 147 - 0
code/ASELoader.h

@@ -0,0 +1,147 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definition of the .ASE importer class. */
+#ifndef AI_ASELOADER_H_INCLUDED
+#define AI_ASELOADER_H_INCLUDED
+
+#include "BaseImporter.h"
+#include "../include/aiTypes.h"
+
+struct aiNode;
+#include "ASEParser.h"
+
+namespace Assimp
+{
+class MaterialHelper;
+
+using namespace ASE;
+
+// ---------------------------------------------------------------------------
+/** Used to load ASE files
+*/
+class ASEImporter : public BaseImporter
+{
+	friend class Importer;
+
+protected:
+	/** Constructor to be privately used by Importer */
+	ASEImporter();
+
+	/** Destructor, private as well */
+	~ASEImporter();
+
+public:
+
+	// -------------------------------------------------------------------
+	/** Returns whether the class can handle the format of the given file. 
+	* See BaseImporter::CanRead() for details.	*/
+	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+
+protected:
+
+	// -------------------------------------------------------------------
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 * See BaseImporter::GetExtensionList() for details
+	 */
+	void GetExtensionList(std::string& append)
+	{
+		append.append("*.ase;*.ask");
+	}
+
+	// -------------------------------------------------------------------
+	/** Imports the given file into the given scene structure. 
+	* See BaseImporter::InternReadFile() for details
+	*/
+	void InternReadFile( const std::string& pFile, aiScene* pScene,
+		IOSystem* pIOHandler);
+
+	// -------------------------------------------------------------------
+	/** Generate normal vectors basing on smoothing groups
+	 * (in some cases the normal are already contained in the file)
+	 * \param mesh Mesh to work on
+	 */
+	void GenerateNormals(ASE::Mesh& mesh);
+
+	// -------------------------------------------------------------------
+	/** Create valid vertex/normal/UV/color/face lists.
+	 *  All elements are unique, faces have only one set of indices
+	 *  after this step occurs.
+	 * \param mesh Mesh to work on
+	 */
+	void BuildUniqueRepresentation(ASE::Mesh& mesh);
+
+	// -------------------------------------------------------------------
+	/** Create one-material-per-mesh meshes ;-)
+	 * \param mesh Mesh to work with
+	 *  \param pcScene Scene object to be filled
+	 */
+	void ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene);
+
+	// -------------------------------------------------------------------
+	/** Convert a material to a MaterialHelper object
+	 * \param mat Input material
+	 */
+	void ConvertMaterial(ASE::Material& mat);
+
+	// -------------------------------------------------------------------
+	/** Setup the final material indices for each mesh
+	 *  \param pcScene Scene object to be filled
+	 */
+	void BuildMaterialIndices(aiScene* pcScene);
+
+	// -------------------------------------------------------------------
+	/** Build the node graph
+	 *  \param pcScene Scene object to be filled
+	 */
+	void BuildNodes(aiScene* pcScene);
+
+protected:
+
+	/** Parser instance */
+	ASE::Parser* mParser;
+
+	/** Buffer to hold the loaded file */
+	unsigned char* mBuffer;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_3DSIMPORTER_H_INC

+ 1644 - 0
code/ASEParser.cpp

@@ -0,0 +1,1644 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the ASE parser class */
+
+#include "ASELoader.h"
+#include "MaterialSystem.h"
+#include "DefaultLogger.h"
+#include "fast_atof.h"
+
+#include "../include/IOStream.h"
+#include "../include/IOSystem.h"
+#include "../include/aiMesh.h"
+#include "../include/aiScene.h"
+#include "../include/aiAssert.h"
+
+#include <boost/scoped_ptr.hpp>
+
+using namespace Assimp;
+using namespace Assimp::ASE;
+
+#if (defined BLUBB)
+#	undef BLUBB
+#endif
+#define BLUBB(_message_) \
+	{this->LogError(_message_);return;}
+
+// ------------------------------------------------------------------------------------------------
+Parser::Parser (const char* szFile)
+{
+	ai_assert(NULL != szFile);
+	this->m_szFile = szFile;
+
+	// makre sure that the color values are invalid
+	this->m_clrBackground.r = std::numeric_limits<float>::quiet_NaN();
+	this->m_clrAmbient.r = std::numeric_limits<float>::quiet_NaN();
+
+	this->iLineNumber = 0;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::LogWarning(const char* szWarn)
+{
+	ai_assert(NULL != szWarn);
+	ai_assert(strlen(szWarn) < 950);
+
+	char szTemp[1024];
+	sprintf(szTemp,"Line %i: %s",this->iLineNumber,szWarn);
+
+	// output the warning to the logger ...
+	DefaultLogger::get()->warn(szTemp);
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::LogError(const char* szWarn)
+{
+	ai_assert(NULL != szWarn);
+	ai_assert(strlen(szWarn) < 950);
+
+	char szTemp[1024];
+	sprintf(szTemp,"Line %i: %s",this->iLineNumber,szWarn);
+
+	// throw an exception
+	throw new ImportErrorException(szTemp);
+}
+// ------------------------------------------------------------------------------------------------
+bool Parser::SkipToNextToken()
+{
+	while (true)
+	{
+		if ('*' == *this->m_szFile)return true;
+		if ('\0' == *this->m_szFile)return false;
+
+		++this->m_szFile;
+	}
+}
+// ------------------------------------------------------------------------------------------------
+bool Parser::SkipOpeningBracket()
+{
+	if (!SkipSpaces(this->m_szFile,&this->m_szFile))return false;
+	if ('{' != *this->m_szFile)
+	{
+		this->LogWarning("Unable to parse block: Unexpected character, \'{\' expected [#1]");
+		return false;
+	}
+	this->SkipToNextToken();
+	return true;
+}
+// ------------------------------------------------------------------------------------------------
+bool Parser::SkipSection()
+{
+	// must handle subsections ...
+	unsigned int iCnt = 1;
+	while (true)
+	{
+		if ('}' == *this->m_szFile)
+		{
+			--iCnt;
+			if (0 == iCnt)
+			{
+				// go to the next valid token ...
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return true;
+			}
+		}
+		else if ('{' == *this->m_szFile)
+		{
+			++iCnt;
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			this->LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]");	
+			return false;
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::Parse()
+{
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// version should be 200. Validate this ...
+			if (0 == strncmp(this->m_szFile,"*3DSMAX_ASCIIEXPORT",19) &&
+				IsSpaceOrNewLine(*(this->m_szFile+19)))
+			{
+				this->m_szFile+=20;
+
+				unsigned int iVersion;
+				this->ParseLV4MeshLong(iVersion);
+
+				if (200 != iVersion)
+				{
+					this->LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \
+						be 200. Continuing happily ...");
+				}
+			}
+			// main scene information
+			else if (0 == strncmp(this->m_szFile,"*SCENE",6) &&
+				IsSpaceOrNewLine(*(this->m_szFile+6)))
+			{
+				this->m_szFile+=7;
+				this->ParseLV1SceneBlock();
+			}
+			// material list
+			else if (0 == strncmp(this->m_szFile,"*MATERIAL_LIST",14) &&
+				IsSpaceOrNewLine(*(this->m_szFile+14)))
+			{
+				this->m_szFile+=15;
+				this->ParseLV1MaterialListBlock();
+			}
+			// geometric object (mesh)
+			else if (0 == strncmp(this->m_szFile,"*GEOMOBJECT",11) &&
+				IsSpaceOrNewLine(*(this->m_szFile+11)))
+			{
+				this->m_szFile+=12;
+
+				this->m_vMeshes.push_back(Mesh());
+				this->ParseLV1GeometryObjectBlock(this->m_vMeshes.back());
+			}
+			// ignore comments, lights and cameras
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... why not?
+			return;
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV1SceneBlock()
+{
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			if (0 == strncmp(this->m_szFile,"*SCENE_BACKGROUND_STATIC",24) &&
+				IsSpaceOrNewLine(*(this->m_szFile+24)))
+			{
+				this->m_szFile+=25;
+
+				// parse a color triple and assume it is really the bg color
+				this->ParseLV4MeshFloatTriple( &this->m_clrBackground.r );
+			}
+			else if (0 == strncmp(this->m_szFile,"*SCENE_AMBIENT_STATIC",21) &&
+				IsSpaceOrNewLine(*(this->m_szFile+21)))
+			{
+				this->m_szFile+=22;
+
+				// parse a color triple and assume it is really the bg color
+				this->ParseLV4MeshFloatTriple( &this->m_clrAmbient.r );
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... why not?
+			return;
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV1MaterialListBlock()
+{
+	unsigned int iDepth = 1;
+	unsigned int iMaterialCount = 0;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			if (0 == strncmp(this->m_szFile,"*MATERIAL_COUNT",15) &&
+				IsSpaceOrNewLine(*(this->m_szFile+15)))
+			{
+				this->m_szFile+=16;
+				this->ParseLV4MeshLong(iMaterialCount);
+
+				// now allocate enough storage to hold all materials
+				this->m_vMaterials.resize(iMaterialCount);
+			}
+			else if (0 == strncmp(this->m_szFile,"*MATERIAL",9) &&
+				IsSpaceOrNewLine(*(this->m_szFile+9)))
+			{
+				this->m_szFile+=10;
+				unsigned int iIndex = 0;
+				this->ParseLV4MeshLong(iIndex);
+
+				if (iIndex >= iMaterialCount)
+				{
+					this->LogWarning("Out of range: material index is too large");
+					iIndex = iMaterialCount-1;
+				}
+
+				// get a reference to the material
+				Material& sMat = this->m_vMaterials[iIndex];
+
+				// skip the '{'
+				this->SkipOpeningBracket();
+
+				// parse the material block
+				this->ParseLV2MaterialBlock(sMat);
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... why not?
+			return;
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
+{
+	unsigned int iDepth = 1;
+	unsigned int iNumSubMaterials = 0;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			if (0 == strncmp(this->m_szFile,"*MATERIAL_NAME",14) &&
+				IsSpaceOrNewLine(*(this->m_szFile+14)))
+			{
+				this->m_szFile+=15;
+			
+				// NOTE: The name could also be the texture in some cases
+				// be prepared that this might occur ...
+				if (!SkipSpaces(this->m_szFile,&this->m_szFile))
+					BLUBB("Unable to parse *MATERIAL_NAME block: Unexpected EOL")
+
+				const char* sz = this->m_szFile;
+				while (!IsSpaceOrNewLine(*sz))sz++;
+				mat.mName = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile);
+				this->m_szFile = sz;
+			}
+			// ambient material color
+			else if (0 == strncmp(this->m_szFile,"*MATERIAL_AMBIENT",17) &&
+				IsSpaceOrNewLine(*(this->m_szFile+17)))
+			{
+				this->m_szFile+=18;
+				this->ParseLV4MeshFloatTriple(&mat.mAmbient.r);
+			}
+			// diffuse material color
+			else if (0 == strncmp(this->m_szFile,"*MATERIAL_DIFFUSE",17) &&
+				IsSpaceOrNewLine(*(this->m_szFile+17)))
+			{
+				this->m_szFile+=18;
+				this->ParseLV4MeshFloatTriple(&mat.mDiffuse.r);
+			}
+			// specular material color
+			else if (0 == strncmp(this->m_szFile,"*MATERIAL_SPECULAR",18) &&
+				IsSpaceOrNewLine(*(this->m_szFile+18)))
+			{
+				this->m_szFile+=19;
+				this->ParseLV4MeshFloatTriple(&mat.mSpecular.r);
+			}
+			// material shading type
+			else if (0 == strncmp(this->m_szFile,"*MATERIAL_SHADING",17) &&
+				IsSpaceOrNewLine(*(this->m_szFile+17)))
+			{
+				this->m_szFile+=18;
+				
+				if (0 == strncmp(this->m_szFile,"Blinn",5) && 
+					IsSpaceOrNewLine(*(this->m_szFile+5)))
+				{
+					mat.mShading = Dot3DSFile::Blinn;
+					this->m_szFile+=6;
+				}
+				else if (0 == strncmp(this->m_szFile,"Phong",5) && 
+					IsSpaceOrNewLine(*(this->m_szFile+5)))
+				{
+					mat.mShading = Dot3DSFile::Phong;
+					this->m_szFile+=6;
+				}
+				else if (0 == strncmp(this->m_szFile,"Flat",4) && 
+					IsSpaceOrNewLine(*(this->m_szFile+4)))
+				{
+					mat.mShading = Dot3DSFile::Flat;
+					this->m_szFile+=5;
+				}
+				else if (0 == strncmp(this->m_szFile,"Wire",4) && 
+					IsSpaceOrNewLine(*(this->m_szFile+4)))
+				{
+					mat.mShading = Dot3DSFile::Wire;
+					this->m_szFile+=5;
+				}
+				else
+				{
+					// assume gouraud shading
+					mat.mShading = Dot3DSFile::Gouraud;
+					this->SkipToNextToken();
+				}
+			}
+			// material transparency
+			else if (0 == strncmp(this->m_szFile,"*MATERIAL_TRANSPARENCY",22) &&
+				IsSpaceOrNewLine(*(this->m_szFile+22)))
+			{
+				this->m_szFile+=23;
+				this->ParseLV4MeshFloat(mat.mTransparency);
+				mat.mTransparency = 1.0f - mat.mTransparency;
+			}
+			// material self illumination
+			else if (0 == strncmp(this->m_szFile,"*MATERIAL_SELFILLUM",19) &&
+				IsSpaceOrNewLine(*(this->m_szFile+19)))
+			{
+				this->m_szFile+=20;
+				float f = 0.0f;
+				this->ParseLV4MeshFloat(f);
+
+				mat.mEmissive.r = f;
+				mat.mEmissive.g = f;
+				mat.mEmissive.b = f;
+			}
+			// material shininess
+			else if (0 == strncmp(this->m_szFile,"*MATERIAL_SHINE",15) &&
+				IsSpaceOrNewLine(*(this->m_szFile+15)))
+			{
+				this->m_szFile+=16;
+				this->ParseLV4MeshFloat(mat.mSpecularExponent);
+				mat.mSpecularExponent *= 15;
+			}
+			// diffuse color map
+			else if (0 == strncmp(this->m_szFile,"*MAP_DIFFUSE",12) &&
+				IsSpaceOrNewLine(*(this->m_szFile+12)))
+			{
+				this->m_szFile+=13;
+				// skip the opening bracket
+				this->SkipOpeningBracket();
+				// parse the texture block
+				this->ParseLV3MapBlock(mat.sTexDiffuse);
+			}
+			// ambient color map
+			else if (0 == strncmp(this->m_szFile,"*MAP_AMBIENT",12) &&
+				IsSpaceOrNewLine(*(this->m_szFile+12)))
+			{
+				this->m_szFile+=13;
+				// skip the opening bracket
+				this->SkipOpeningBracket();
+				// parse the texture block
+				this->ParseLV3MapBlock(mat.sTexAmbient);
+			}
+			// specular color map
+			else if (0 == strncmp(this->m_szFile,"*MAP_SPECULAR",13) &&
+				IsSpaceOrNewLine(*(this->m_szFile+13)))
+			{
+				this->m_szFile+=14;
+				// skip the opening bracket
+				this->SkipOpeningBracket();
+				// parse the texture block
+				this->ParseLV3MapBlock(mat.sTexSpecular);
+			}
+			// opacity map
+			else if (0 == strncmp(this->m_szFile,"*MAP_OPACITY",12) &&
+				IsSpaceOrNewLine(*(this->m_szFile+12)))
+			{
+				this->m_szFile+=13;
+				// skip the opening bracket
+				this->SkipOpeningBracket();
+				// parse the texture block
+				this->ParseLV3MapBlock(mat.sTexOpacity);
+			}
+			// emissive map
+			else if (0 == strncmp(this->m_szFile,"*MAP_SELFILLUM",14) &&
+				IsSpaceOrNewLine(*(this->m_szFile+14)))
+			{
+				this->m_szFile+=15;
+				// skip the opening bracket
+				this->SkipOpeningBracket();
+				// parse the texture block
+				this->ParseLV3MapBlock(mat.sTexEmissive);
+			}
+			// bump map
+			else if (0 == strncmp(this->m_szFile,"*MAP_BUMP",9) &&
+				IsSpaceOrNewLine(*(this->m_szFile+9)))
+			{
+				this->m_szFile+=10;
+				// skip the opening bracket
+				this->SkipOpeningBracket();
+				// parse the texture block
+				this->ParseLV3MapBlock(mat.sTexBump);
+			}
+			// specular/shininess map
+			else if (0 == strncmp(this->m_szFile,"*MAP_SHINE",10) &&
+				IsSpaceOrNewLine(*(this->m_szFile+10)))
+			{
+				this->m_szFile+=11;
+				// skip the opening bracket
+				this->SkipOpeningBracket();
+				// parse the texture block
+				this->ParseLV3MapBlock(mat.sTexShininess);
+			}
+			// number of submaterials
+			else if (0 == strncmp(this->m_szFile,"*NUMSUBMTLS",11) &&
+				IsSpaceOrNewLine(*(this->m_szFile+11)))
+			{
+				this->m_szFile+=12;
+				this->ParseLV4MeshLong(iNumSubMaterials);
+
+				// allocate enough storage
+				mat.avSubMaterials.resize(iNumSubMaterials);
+			}
+			// submaterial chunks
+			else if (0 == strncmp(this->m_szFile,"*SUBMATERIAL",12) &&
+				IsSpaceOrNewLine(*(this->m_szFile+12)))
+			{
+				this->m_szFile+=13;
+				
+				unsigned int iIndex = 0;
+				this->ParseLV4MeshLong(iIndex);
+
+				if (iIndex >= iNumSubMaterials)
+				{
+					this->LogWarning("Out of range: submaterial index is too large");
+					iIndex = iNumSubMaterials-1;
+				}
+
+				// get a reference to the material
+				Material& sMat = mat.avSubMaterials[iIndex];
+
+				// skip the '{'
+				this->SkipOpeningBracket();
+
+				// parse the material block
+				this->ParseLV2MaterialBlock(sMat);
+			}
+
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level2 block, this can't be
+			BLUBB("Unable to finish parsing a lv2 material block. Unexpected EOF")
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV3MapBlock(Texture& map)
+{
+	unsigned int iDepth = 1;
+	unsigned int iNumSubMaterials = 0;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// path to the texture
+			if (0 == strncmp(this->m_szFile,"*BITMAP" ,7) &&
+				IsSpaceOrNewLine(*(this->m_szFile+7)))
+			{
+				this->m_szFile+=8;
+
+				// NOTE: The name could also be the texture in some cases
+				// be prepared that this might occur ...
+				if (!SkipSpaces(this->m_szFile,&this->m_szFile))
+					BLUBB("Unable to parse *BITMAP block: Unexpected EOL")
+
+				// there must be "
+				if ('\"' != *this->m_szFile)
+					BLUBB("Unable to parse *BITMAP block: Path is expected to be enclosed in double quotation marks")
+
+				++this->m_szFile;
+				const char* sz = this->m_szFile;
+				while (true)
+				{
+					if ('\"' == *sz)break;
+					else if ('\0' == sz)
+					{
+						BLUBB("Unable to parse *BITMAP block: Path is expected to be enclosed in double quotation marks \
+							  but EOF was reached before a closing quotation mark was found")
+					}
+					sz++;
+				}
+
+				map.mMapName = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile);
+				this->m_szFile = sz;
+			}
+			// offset on the u axis
+			if (0 == strncmp(this->m_szFile,"*UVW_U_OFFSET" ,13) &&
+				IsSpaceOrNewLine(*(this->m_szFile+13)))
+			{
+				this->m_szFile+=14;
+				this->ParseLV4MeshFloat(map.mOffsetU);
+			}
+			// offset on the v axis
+			if (0 == strncmp(this->m_szFile,"*UVW_V_OFFSET" ,13) &&
+				IsSpaceOrNewLine(*(this->m_szFile+13)))
+			{
+				this->m_szFile+=14;
+				this->ParseLV4MeshFloat(map.mOffsetV);
+			}
+			// tiling on the u axis
+			if (0 == strncmp(this->m_szFile,"*UVW_U_TILING" ,13) &&
+				IsSpaceOrNewLine(*(this->m_szFile+13)))
+			{
+				this->m_szFile+=14;
+				this->ParseLV4MeshFloat(map.mScaleU);
+			}
+			// tiling on the v axis
+			if (0 == strncmp(this->m_szFile,"*UVW_V_TILING" ,13) &&
+				IsSpaceOrNewLine(*(this->m_szFile+13)))
+			{
+				this->m_szFile+=14;
+				this->ParseLV4MeshFloat(map.mScaleV);
+			}
+			// rotation around the z-axis
+			if (0 == strncmp(this->m_szFile,"*UVW_ANGLE" ,10) &&
+				IsSpaceOrNewLine(*(this->m_szFile+10)))
+			{
+				this->m_szFile+=11;
+				this->ParseLV4MeshFloat(map.mRotation);
+			}
+			// map blending factor
+			if (0 == strncmp(this->m_szFile,"*MAP_AMOUNT" ,11) &&
+				IsSpaceOrNewLine(*(this->m_szFile+11)))
+			{
+				this->m_szFile+=12;
+				this->ParseLV4MeshFloat(map.mTextureBlend);
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level3 block, this can't be
+			BLUBB("Unable to finish parsing a lv3 map block. Unexpected EOF")
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV1GeometryObjectBlock(ASE::Mesh& mesh)
+{
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// name of the mesh/node
+			if (0 == strncmp(this->m_szFile,"*NODE_NAME" ,10) &&
+				IsSpaceOrNewLine(*(this->m_szFile+10)))
+			{
+				this->m_szFile+=11;
+
+				// NOTE: The name could also be the texture in some cases
+				// be prepared that this might occur ...
+				if (!SkipSpaces(this->m_szFile,&this->m_szFile))
+					BLUBB("Unable to parse *NODE_NAME block: Unexpected EOL")
+
+				// there must be "
+				if ('\"' != *this->m_szFile)
+					BLUBB("Unable to parse *NODE_NAME block: Name is expected to be enclosed in double quotation marks")
+
+				++this->m_szFile;
+				const char* sz = this->m_szFile;
+				while (true)
+				{
+					if ('\"' == *sz)break;
+					else if ('\0' == sz)
+					{
+						BLUBB("Unable to parse *NODE_NAME block: Name is expected to be enclosed in double quotation marks \
+							  but EOF was reached before a closing quotation mark was found")
+					}
+					sz++;
+				}
+
+				mesh.mName = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile);
+				this->m_szFile = sz;
+			}
+			// transformation matrix of the node
+			else if (0 == strncmp(this->m_szFile,"*NODE_TM" ,8) &&
+				IsSpaceOrNewLine(*(this->m_szFile+8)))
+			{
+				this->m_szFile+=9;
+				this->ParseLV2NodeTransformBlock(mesh);
+			}
+			// mesh data
+			else if (0 == strncmp(this->m_szFile,"*MESH" ,5) &&
+				IsSpaceOrNewLine(*(this->m_szFile+5)))
+			{
+				this->m_szFile+=6;
+				this->ParseLV2MeshBlock(mesh);
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level1 block, this can be
+			return;
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV2NodeTransformBlock(ASE::Mesh& mesh)
+{
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// first row of the transformation matrix
+			if (0 == strncmp(this->m_szFile,"*TM_ROW0" ,8) &&
+				IsSpaceOrNewLine(*(this->m_szFile+8)))
+			{
+				this->m_szFile+=9;
+				this->ParseLV4MeshFloatTriple(mesh.mTransform[0]);
+			}
+			// second row of the transformation matrix
+			else if (0 == strncmp(this->m_szFile,"*TM_ROW1" ,8) &&
+				IsSpaceOrNewLine(*(this->m_szFile+8)))
+			{
+				this->m_szFile+=9;
+				this->ParseLV4MeshFloatTriple(mesh.mTransform[1]);
+			}
+			// third row of the transformation matrix
+			else if (0 == strncmp(this->m_szFile,"*TM_ROW2" ,8) &&
+				IsSpaceOrNewLine(*(this->m_szFile+8)))
+			{
+				this->m_szFile+=9;
+				this->ParseLV4MeshFloatTriple(mesh.mTransform[2]);
+			}
+			// fourth row of the transformation matrix
+			else if (0 == strncmp(this->m_szFile,"*TM_ROW3" ,8) &&
+				IsSpaceOrNewLine(*(this->m_szFile+8)))
+			{
+				this->m_szFile+=9;
+				this->ParseLV4MeshFloatTriple(mesh.mTransform[3]);
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level2 block, this can't be
+			BLUBB("Unable to finish parsing a lv2 node transform block. Unexpected EOF")
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
+{
+	unsigned int iNumVertices = 0;
+	unsigned int iNumFaces = 0;
+	unsigned int iNumTVertices = 0;
+	unsigned int iNumTFaces = 0;
+	unsigned int iNumCVertices = 0;
+	unsigned int iNumCFaces = 0;
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// Number of vertices in the mesh
+			if (0 == strncmp(this->m_szFile,"*MESH_NUMVERTEX" ,15) &&
+				IsSpaceOrNewLine(*(this->m_szFile+15)))
+			{
+				this->m_szFile+=16;
+				this->ParseLV4MeshLong(iNumVertices);
+			}
+			// Number of texture coordinates in the mesh
+			else if (0 == strncmp(this->m_szFile,"*MESH_NUMTVERTEX" ,16) &&
+				IsSpaceOrNewLine(*(this->m_szFile+16)))
+			{
+				this->m_szFile+=17;
+				this->ParseLV4MeshLong(iNumTVertices);
+			}
+			// Number of vertex colors in the mesh
+			else if (0 == strncmp(this->m_szFile,"*MESH_NUMCVERTEX" ,16) &&
+				IsSpaceOrNewLine(*(this->m_szFile+16)))
+			{
+				this->m_szFile+=17;
+				this->ParseLV4MeshLong(iNumCVertices);
+			}
+			// Number of regular faces in the mesh
+			else if (0 == strncmp(this->m_szFile,"*MESH_NUMFACES" ,14) &&
+				IsSpaceOrNewLine(*(this->m_szFile+14)))
+			{
+				this->m_szFile+=15;
+				this->ParseLV4MeshLong(iNumFaces);
+			}
+			// Number of UVWed faces in the mesh
+			else if (0 == strncmp(this->m_szFile,"*MESH_NUMTVFACES" ,16) &&
+				IsSpaceOrNewLine(*(this->m_szFile+16)))
+			{
+				this->m_szFile+=17;
+				this->ParseLV4MeshLong(iNumTFaces);
+			}
+			// Number of colored faces in the mesh
+			else if (0 == strncmp(this->m_szFile,"*MESH_NUMCVFACES" ,16) &&
+				IsSpaceOrNewLine(*(this->m_szFile+16)))
+			{
+				this->m_szFile+=17;
+				this->ParseLV4MeshLong(iNumCFaces);
+			}
+			// mesh vertex list block
+			else if (0 == strncmp(this->m_szFile,"*MESH_VERTEX_LIST" ,17) &&
+				IsSpaceOrNewLine(*(this->m_szFile+17)))
+			{
+				this->m_szFile+=18;
+				this->ParseLV3MeshVertexListBlock(iNumVertices,mesh);
+			}
+			// mesh face list block
+			else if (0 == strncmp(this->m_szFile,"*MESH_FACE_LIST" ,15) &&
+				IsSpaceOrNewLine(*(this->m_szFile+15)))
+			{
+				this->m_szFile+=16;
+				this->SkipOpeningBracket();
+				this->ParseLV3MeshFaceListBlock(iNumFaces,mesh);
+			}
+			// mesh texture vertex list block
+			else if (0 == strncmp(this->m_szFile,"*MESH_TVERTLIST" ,15) &&
+				IsSpaceOrNewLine(*(this->m_szFile+15)))
+			{
+				this->m_szFile+=16;
+				this->SkipOpeningBracket();
+				this->ParseLV3MeshTListBlock(iNumTVertices,mesh);
+			}
+			// mesh texture face block
+			else if (0 == strncmp(this->m_szFile,"*MESH_TFACELIST" ,15) &&
+				IsSpaceOrNewLine(*(this->m_szFile+15)))
+			{
+				this->m_szFile+=16;
+				this->SkipOpeningBracket();
+				this->ParseLV3MeshTFaceListBlock(iNumTFaces,mesh);
+			}
+			// mesh color vertex list block
+			else if (0 == strncmp(this->m_szFile,"*MESH_CVERTLIST" ,15) &&
+				IsSpaceOrNewLine(*(this->m_szFile+15)))
+			{
+				this->m_szFile+=16;
+				this->SkipOpeningBracket();
+				this->ParseLV3MeshCListBlock(iNumCVertices,mesh);
+			}
+			// mesh color face block
+			else if (0 == strncmp(this->m_szFile,"*MESH_CFACELIST" ,15) &&
+				IsSpaceOrNewLine(*(this->m_szFile+15)))
+			{
+				this->m_szFile+=16;
+				this->SkipOpeningBracket();
+				this->ParseLV3MeshCFaceListBlock(iNumCFaces,mesh);
+			}
+			// another mesh UV channel ...
+			else if (0 == strncmp(this->m_szFile,"*MESH_MAPPINGCHANNEL" ,20) &&
+				IsSpaceOrNewLine(*(this->m_szFile+20)))
+			{
+				this->m_szFile+=21;
+
+				unsigned int iIndex = 0;
+				this->ParseLV4MeshLong(iIndex);
+
+				if (iIndex < 2)
+				{
+					this->LogWarning("Mapping channel has an invalid index. Skipping UV channel");
+					// skip it ...
+					this->SkipOpeningBracket();
+					this->SkipSection();
+				}
+				if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
+				{
+					this->LogWarning("Too many UV channels specified. Skipping channel ..");
+					// skip it ...
+					this->SkipOpeningBracket();
+					this->SkipSection();
+				}
+				else
+				{
+					// skip the '{'
+					this->SkipOpeningBracket();
+
+					// parse the mapping channel
+					this->ParseLV3MappingChannel(iIndex-1,mesh);
+				}
+			}
+			// mesh material index
+			else if (0 == strncmp(this->m_szFile,"*MATERIAL_REF" ,13) &&
+				IsSpaceOrNewLine(*(this->m_szFile+13)))
+			{
+				this->m_szFile+=14;
+				this->ParseLV4MeshLong(mesh.iMaterialIndex);
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level2 block, this can't be
+			BLUBB("Unable to finish parsing a lv2 mesh block. Unexpected EOF")
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV3MeshVertexListBlock(
+	unsigned int iNumVertices, ASE::Mesh& mesh)
+{
+	// allocate enough storage in the array
+	mesh.mPositions.resize(iNumVertices);
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// Vertex entry
+			if (0 == strncmp(this->m_szFile,"*MESH_VERTEX" ,12) &&
+				IsSpaceOrNewLine(*(this->m_szFile+12)))
+			{
+				this->m_szFile+=13;
+
+				aiVector3D vTemp;
+				unsigned int iIndex;
+				this->ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
+
+				if (iIndex >= iNumVertices)
+				{
+					this->LogWarning("Vertex has an invalid index. It will be ignored");
+				}
+				else mesh.mPositions[iIndex] = vTemp;
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level3 block, this can't be
+			BLUBB("Unable to finish parsing a lv3 vertex list block. Unexpected EOF")
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
+{
+	// allocate enough storage in the face array
+	mesh.mFaces.resize(iNumFaces);
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// Face entry
+			if (0 == strncmp(this->m_szFile,"*MESH_FACE" ,10) &&
+				IsSpaceOrNewLine(*(this->m_szFile+10)))
+			{
+				this->m_szFile+=11;
+
+				ASE::Face mFace;
+				this->ParseLV4MeshFace(mFace);
+
+				if (mFace.iFace >= iNumFaces)
+				{
+					this->LogWarning("Face has an invalid index. It will be ignored");
+				}
+				else mesh.mFaces[mFace.iFace] = mFace;
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level3 block, this can't be
+			BLUBB("Unable to finish parsing LV3 *MESH_FACE_LIST block. Unexpected EOF")
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
+	ASE::Mesh& mesh, unsigned int iChannel)
+{
+	// allocate enough storage in the array
+	mesh.amTexCoords[iChannel].resize(iNumVertices);
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// Vertex entry
+			if (0 == strncmp(this->m_szFile,"*MESH_TVERT" ,11) &&
+				IsSpaceOrNewLine(*(this->m_szFile+11)))
+			{
+				this->m_szFile+=12;
+
+				aiVector3D vTemp;
+				unsigned int iIndex;
+				this->ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
+
+				if (iIndex >= iNumVertices)
+				{
+					this->LogWarning("Tvertex has an invalid index. It will be ignored");
+				}
+				else mesh.amTexCoords[iChannel][iIndex] = vTemp;
+
+				if (0.0f != vTemp.z)
+				{
+					// we need 3 coordinate channels
+					mesh.mNumUVComponents[iChannel] = 3;
+				}
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level3 block, this can't be
+			BLUBB("Unable to finish parsing LV3 *MESH_VERTEX_LIST block. Unexpected EOF")
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
+	ASE::Mesh& mesh, unsigned int iChannel)
+{
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// Face entry
+			if (0 == strncmp(this->m_szFile,"*MESH_TFACE" ,12) &&
+				IsSpaceOrNewLine(*(this->m_szFile+12)))
+			{
+				this->m_szFile+=13;
+
+				unsigned int aiValues[3];
+				unsigned int iIndex = 0;
+
+				this->ParseLV4MeshLongTriple(aiValues,iIndex);
+				if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
+				{
+					this->LogWarning("UV-Face has an invalid index. It will be ignored");
+				}
+				else
+				{
+					// copy UV indices
+					mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0];
+					mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1];
+					mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2];
+				}
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level3 block, this can't be
+			BLUBB("Unable to finish parsing LV3 *MESH_TFACELIST block. Unexpected EOF")
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
+{
+	unsigned int iNumTVertices = 0;
+	unsigned int iNumTFaces = 0;
+
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// Number of texture coordinates in the mesh
+			if (0 == strncmp(this->m_szFile,"*MESH_NUMTVERTEX" ,16) &&
+				IsSpaceOrNewLine(*(this->m_szFile+16)))
+			{
+				this->m_szFile+=17;
+				this->ParseLV4MeshLong(iNumTVertices);
+			}
+			// Number of UVWed faces in the mesh
+			else if (0 == strncmp(this->m_szFile,"*MESH_NUMTVFACES" ,16) &&
+				IsSpaceOrNewLine(*(this->m_szFile+16)))
+			{
+				this->m_szFile+=17;
+				this->ParseLV4MeshLong(iNumTFaces);
+			}
+			// mesh texture vertex list block
+			else if (0 == strncmp(this->m_szFile,"*MESH_TVERTLIST" ,15) &&
+				IsSpaceOrNewLine(*(this->m_szFile+15)))
+			{
+				this->m_szFile+=16;
+				this->SkipOpeningBracket();
+				this->ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel);
+			}
+			// mesh texture face block
+			else if (0 == strncmp(this->m_szFile,"*MESH_TFACELIST" ,15) &&
+				IsSpaceOrNewLine(*(this->m_szFile+15)))
+			{
+				this->m_szFile+=16;
+				this->SkipOpeningBracket();
+				this->ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel);
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level2 block, this can't be
+			BLUBB("Unable to finish parsing a LV3 *MESH_MAPPINGCHANNEL block. Unexpected EOF")
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh)
+{
+	// allocate enough storage in the array
+	mesh.mVertexColors.resize(iNumVertices);
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// Vertex entry
+			if (0 == strncmp(this->m_szFile,"*MESH_VERTCOL" ,13) &&
+				IsSpaceOrNewLine(*(this->m_szFile+13)))
+			{
+				this->m_szFile+=14;
+
+				aiColor4D vTemp;
+				vTemp.a = 1.0f;
+				unsigned int iIndex;
+				this->ParseLV4MeshFloatTriple(&vTemp.r,iIndex);
+
+				if (iIndex >= iNumVertices)
+				{
+					this->LogWarning("Vertex color has an invalid index. It will be ignored");
+				}
+				else mesh.mVertexColors[iIndex] = vTemp;
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level3 block, this can't be
+			BLUBB("Unable to finish parsing LV3 *MESH_CVERTLIST block. Unexpected EOF")
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
+{
+	unsigned int iDepth = 1;
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			// Face entry
+			if (0 == strncmp(this->m_szFile,"*MESH_CFACE" ,12) &&
+				IsSpaceOrNewLine(*(this->m_szFile+12)))
+			{
+				this->m_szFile+=13;
+
+				unsigned int aiValues[3];
+				unsigned int iIndex = 0;
+
+				this->ParseLV4MeshLongTriple(aiValues,iIndex);
+				if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
+				{
+					this->LogWarning("UV-Face has an invalid index. It will be ignored");
+				}
+				else
+				{
+					// copy color indices
+					mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0];
+					mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1];
+					mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2];
+				}
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		else if ('\0' == *this->m_szFile)
+		{
+			// END OF FILE ... this is a level3 block, this can't be
+			BLUBB("Unable to finish parsing LV3 *MESH_CFACELIST block. Unexpected EOF")
+		}
+		else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
+		++this->m_szFile;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
+{
+	// allocate enough storage for the normals
+	sMesh.mNormals.resize(sMesh.mPositions.size());
+	unsigned int iDepth = 1;
+
+	// we need the *MESH_VERTEXNORMAL blocks, ignore the face normals
+	// if there are only face normals we calculate them outselfes using the SGs
+	while (true)
+	{
+		if ('*' == *this->m_szFile)
+		{
+			if (0 == strncmp(this->m_szFile,"*MESH_VERTEXNORMAL",18) && IsSpaceOrNewLine(*(this->m_szFile+18)))
+			{
+				this->m_szFile += 19;
+
+				// parse a simple float triple
+				aiVector3D vNormal;
+				unsigned int iIndex = 0;
+				this->ParseLV4MeshFloatTriple(&vNormal.x,iIndex);
+
+				if (iIndex >= sMesh.mNormals.size())
+				{
+					this->LogWarning("Normal index is too large");
+					iIndex = sMesh.mNormals.size()-1;
+				}
+
+				// important: this->m_szFile might now point to '}' ...
+				sMesh.mNormals[iIndex] = vNormal;
+			}
+		}
+		if ('{' == *this->m_szFile)iDepth++;
+		if ('}' == *this->m_szFile)
+		{
+			if (0 == --iDepth)
+			{
+				++this->m_szFile;
+				this->SkipToNextToken();
+				return;
+			}
+		}
+		// seems we have reached the end of the file ... 
+		else if ('\0' == *this->m_szFile)
+		{
+			BLUBB("Unable to parse *MESH_NORMALS Element: Unexpected EOL [#1]")
+		}
+		this->m_szFile++;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV4MeshFace(ASE::Face& out)
+{
+	// skip spaces and tabs
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+		BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]")
+
+	// parse the face index
+	out.iFace = strtol10(this->m_szFile,&this->m_szFile);
+
+	// next character should be ':'
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile) || ':' != *this->m_szFile)
+		BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]")
+
+	// parse all mesh indices
+	++this->m_szFile;
+	for (unsigned int i = 0; i < 3;++i)
+	{
+		unsigned int iIndex = 0;
+		if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+		{
+			// LOG 
+__EARTHQUAKE_XXL:
+			BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. A,B or C expected [#3]")
+		}
+		switch (*this->m_szFile)
+		{
+		case 'A':
+		case 'a':
+			break;
+		case 'B':
+		case 'b':
+			iIndex = 1;
+			break;
+		case 'C':
+		case 'c':
+			iIndex = 2;
+			break;
+		default: goto __EARTHQUAKE_XXL;
+		};
+		++this->m_szFile;
+
+		// next character should be ':'
+		if(!SkipSpaces(this->m_szFile,&this->m_szFile) || ':' != *this->m_szFile)
+			BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]")
+
+		++this->m_szFile;
+
+		if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+			BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. Vertex index ecpected [#4]")
+
+		out.mIndices[iIndex] = strtol10(this->m_szFile,&this->m_szFile);
+	}
+
+	// now we need to skip the AB, BC, CA blocks. 
+	while (true)
+	{
+		if ('*' == *this->m_szFile)break;
+		if (IsLineEnd(*this->m_szFile))
+		{
+			this->iLineNumber++;
+			return;
+		}
+		this->m_szFile++;
+	}
+
+	// parse the smoothing group of the face
+	if (0 == strncmp(this->m_szFile,"*MESH_SMOOTHING",15) && IsSpaceOrNewLine(*(this->m_szFile+15)))
+	{
+		this->m_szFile+=16;
+		if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+			BLUBB("Unable to parse *MESH_SMOOTHING Element: Unexpected EOL. Smoothing group(s) expected [#5]")
+		
+		// parse smoothing groups until we don_t anymore see commas
+		while (true)
+		{
+			out.iSmoothGroup |= (1 << strtol10(this->m_szFile,&this->m_szFile));
+			SkipSpaces(this->m_szFile,&this->m_szFile);
+			if (',' != *this->m_szFile)
+			{
+				break;
+			}
+			++this->m_szFile;
+			SkipSpaces(this->m_szFile,&this->m_szFile);
+		}
+	}
+
+	// *MESH_MTLID  is optional, too
+	while (true)
+	{
+		if ('*' == *this->m_szFile)break;
+		if (IsLineEnd(*this->m_szFile))
+		{
+			this->iLineNumber++;
+			return;
+		}
+		this->m_szFile++;
+	}
+
+	if (0 == strncmp(this->m_szFile,"*MESH_MTLID",11) && IsSpaceOrNewLine(*(this->m_szFile+11)))
+	{
+		this->m_szFile+=12;
+		if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+			BLUBB("Unable to parse *MESH_MTLID Element: Unexpected EOL. Material index expected [#6]")
+		out.iMaterial = strtol10(this->m_szFile,&this->m_szFile);
+	}
+	this->SkipToNextToken();
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV4MeshLongTriple(unsigned int* apOut)
+{
+	ai_assert(NULL != apOut);
+
+	// skip spaces and tabs
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+	{
+		// LOG 
+		this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#1]");
+		++this->iLineNumber;
+		apOut[0] = apOut[1] = apOut[2] = 0;
+		return;
+	}
+	apOut[0] = strtol10(this->m_szFile,&this->m_szFile);
+
+	// skip spaces and tabs
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+	{
+		// LOG 
+		this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#2]");
+		++this->iLineNumber;
+		apOut[1] = apOut[2] = 0;
+		return;
+	}
+	apOut[1] = strtol10(this->m_szFile,&this->m_szFile);
+
+	// skip spaces and tabs
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+	{
+		// LOG 
+		this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#3]");
+		apOut[2] = 0;
+		++this->iLineNumber;
+		return;
+	}
+	apOut[2] = strtol10(this->m_szFile,&this->m_szFile);
+	// go to the next valid sequence
+	SkipSpacesAndLineEnd(this->m_szFile,&this->m_szFile);
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut)
+{
+	ai_assert(NULL != apOut);
+
+	// skip spaces and tabs
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+	{
+		// LOG 
+		this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#4]");
+		rIndexOut = 0;
+		apOut[0] = apOut[1] = apOut[2] = 0;
+		++this->iLineNumber;
+		return;
+	}
+	// parse the index
+	rIndexOut = strtol10(this->m_szFile,&this->m_szFile);
+
+	// parse the three others
+	this->ParseLV4MeshLongTriple(apOut);
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
+{
+	ai_assert(NULL != apOut);
+
+	// skip spaces and tabs
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+	{
+		// LOG 
+		this->LogWarning("Unable to parse indexable float triple: unexpected EOL [#1]");
+		rIndexOut = 0;
+		apOut[0] = apOut[1] = apOut[2] = 0.0f;
+		++this->iLineNumber;
+		return;
+	}
+	// parse the index
+	rIndexOut = strtol10(this->m_szFile,&this->m_szFile);
+	
+	// parse the three others
+	this->ParseLV4MeshFloatTriple(apOut);
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV4MeshFloatTriple(float* apOut)
+{
+	ai_assert(NULL != apOut);
+	// skip spaces and tabs
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+	{
+		// LOG 
+		this->LogWarning("Unable to parse float triple: unexpected EOL [#5]");
+		apOut[0] = apOut[1] = apOut[2] = 0.0f;
+		++this->iLineNumber;
+		return;
+	}
+	// parse the first float
+	this->m_szFile = fast_atof_move(this->m_szFile,apOut[0]);
+	// skip spaces and tabs
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+	{
+		// LOG 
+		this->LogWarning("Unable to parse float triple: unexpected EOL [#6]");
+		apOut[1] = apOut[2] = 0.0f;
+		++this->iLineNumber;
+		return;
+	}
+	// parse the second float
+	this->m_szFile = fast_atof_move(this->m_szFile,apOut[1]);
+	// skip spaces and tabs
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+	{
+		// LOG 
+		this->LogWarning("Unable to parse float triple: unexpected EOL [#7]");
+		apOut[2] = 0.0f;
+		++this->iLineNumber;
+		return;
+	}
+	// parse the third float
+	this->m_szFile = fast_atof_move(this->m_szFile,apOut[2]);
+	// go to the next valid sequence
+	this->SkipToNextToken();
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV4MeshFloat(float& fOut)
+{
+	// skip spaces and tabs
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+	{
+		// LOG 
+		this->LogWarning("Unable to parse float: unexpected EOL [#1]");
+		fOut = 0.0f;
+		++this->iLineNumber;
+		return;
+	}
+	// parse the first float
+	this->m_szFile = fast_atof_move(this->m_szFile,fOut);
+	// go to the next valid sequence
+	this->SkipToNextToken();
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void Parser::ParseLV4MeshLong(unsigned int& iOut)
+{
+	// skip spaces and tabs
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+	{
+		// LOG 
+		this->LogWarning("Unable to parse long: unexpected EOL [#1]");
+		iOut = 0;
+		++this->iLineNumber;
+		return;
+	}
+	// parse the value
+	iOut = strtol10(this->m_szFile,&this->m_szFile);
+	// go to the next valid sequence
+	this->SkipToNextToken();
+	return;
+}

+ 387 - 0
code/ASEParser.h

@@ -0,0 +1,387 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 helper data structures for importing ASE files  */
+#ifndef AI_ASEFILEHELPER_H_INC
+#define AI_ASEFILEHELPER_H_INC
+
+#include <string>
+#include <vector>
+#include <list>
+#include <sstream>
+
+#include "../include/aiTypes.h"
+#include "../include/aiMesh.h"
+#include "../include/aiAnim.h"
+
+// for some helper routines like IsSpace()
+#include "PlyParser.h"
+
+// ASE is quite similar to 3ds. We can reuse some structures
+#include "3DSLoader.h"
+
+namespace Assimp
+{
+
+// http://wiki.beyondunreal.com/Legacy:ASE_File_Format
+namespace ASE
+{
+	using namespace Dot3DS;
+
+// ---------------------------------------------------------------------------
+/** Helper structure representing an ASE material */
+struct Material : public Dot3DS::Material
+{
+	//! Default constructor
+	Material() : pcInstance(NULL), bNeed (false)
+	{}
+
+	//! Ambient texture channel
+	Texture sTexAmbient;
+
+	//! Contains all sub materials of this material
+	std::vector<Material> avSubMaterials;
+
+	//! MaterialHelper object
+	MaterialHelper* pcInstance;
+
+	//! Can we remove this material?
+	bool bNeed;
+};
+// ---------------------------------------------------------------------------
+/** Helper structure to represent an ASE file face */
+struct Face : public Dot3DS::Face
+{
+	//! Default constructor. Initializes everything with 0
+	Face()
+	{
+		mColorIndices[0] = mColorIndices[1] = mColorIndices[2] = 0;
+		for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+		{
+			amUVIndices[i][0] = amUVIndices[i][1] = amUVIndices[i][2] = 0;
+		}
+
+		iMaterial = DEFAULT_MATINDEX;
+		iFace = 0;
+	}
+
+	//! special value to indicate that no material index has
+	//! been assigned to a face. The default material index
+	//! will replace this value later.
+	static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF;
+
+
+	//! Indices into the list of vertices
+	unsigned int mIndices[3];
+
+	//! Indices into each list of texture coordinates
+	unsigned int amUVIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS][3];
+
+	//! Index into the list of vertex colors
+	unsigned int mColorIndices[3];
+
+	//! (Sub)Material index to be assigned to this face
+	unsigned int iMaterial;
+
+	//! Index of the face. It is not specified whether it is
+	//! a requirement of the file format that all faces are
+	//! written in sequential order, so we have to expect this case
+	unsigned int iFace;
+};
+
+// ---------------------------------------------------------------------------
+/** Helper structure to represent an ASE file mesh */
+struct Mesh
+{
+	//! Constructor. Creates a default name for the mesh
+	Mesh()
+	{
+		static int iCnt = 0;
+		std::stringstream ss(mName);
+		ss << "%%_UNNAMED_" << iCnt++ << "_%%"; 
+
+		// use 2 texture vertex components by default
+		for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+			this->mNumUVComponents[c] = 2;
+	}
+	std::string mName;
+
+	//! vertex positions
+	std::vector<aiVector3D> mPositions;
+
+	//! List of all faces loaded
+	std::vector<ASE::Face> mFaces;
+
+	//! List of all texture coordinate sets
+	std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+
+	//! List of all vertex color sets.
+	std::vector<aiColor4D> mVertexColors;
+
+	//! List of normal vectors
+	std::vector<aiVector3D> mNormals;
+
+	//! Transformation matrix of the mesh
+	aiMatrix4x4 mTransform;
+
+	//! Material index of the mesh
+	unsigned int iMaterialIndex;
+
+	//! Number of vertex components for each UVW set
+	unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+};
+
+// ---------------------------------------------------------------------------------
+/** \brief Class to parse ASE files
+ */
+class Parser
+{
+
+private:
+
+	Parser() {}
+
+public:
+
+	//! Construct a parser from a given input file which is
+	//! guaranted to be terminated with zero.
+	Parser (const char* szFile);
+
+	// -------------------------------------------------------------------
+	//! Parses the file into the parsers internal representation
+	void Parse();
+
+
+private:
+
+	// -------------------------------------------------------------------
+	//! Parse the *SCENE block in a file
+	void ParseLV1SceneBlock();
+
+	// -------------------------------------------------------------------
+	//! Parse the *MATERIAL_LIST block in a file
+	void ParseLV1MaterialListBlock();
+
+	// -------------------------------------------------------------------
+	//! Parse a *GEOMOBJECT block in a file
+	//! \param mesh Mesh object to be filled
+	void ParseLV1GeometryObjectBlock(Mesh& mesh);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MATERIAL blocks in a material list
+	//! \param mat Material structure to be filled
+	void ParseLV2MaterialBlock(Material& mat);
+
+	// -------------------------------------------------------------------
+	//! Parse a *NODE_TM block in a file
+	//! \param mesh Mesh object to be filled
+	void ParseLV2NodeTransformBlock(Mesh& mesh);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH block in a file
+	//! \param mesh Mesh object to be filled
+	void ParseLV2MeshBlock(Mesh& mesh);
+
+	// -------------------------------------------------------------------
+	//! Parse the *MAP_XXXXXX blocks in a material
+	//! \param map Texture structure to be filled
+	void ParseLV3MapBlock(Texture& map);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_VERTEX_LIST block in a file
+	//! \param iNumVertices Value of *MESH_NUMVERTEX, if present.
+	//! Otherwise zero. This is used to check the consistency of the file.
+	//! A warning is sent to the logger if the validations fails.
+	//! \param mesh Mesh object to be filled
+	void ParseLV3MeshVertexListBlock(
+		unsigned int iNumVertices,Mesh& mesh);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_FACE_LIST block in a file
+	//! \param iNumFaces Value of *MESH_NUMFACES, if present.
+	//! Otherwise zero. This is used to check the consistency of the file.
+	//! A warning is sent to the logger if the validations fails.
+	//! \param mesh Mesh object to be filled
+	void ParseLV3MeshFaceListBlock(
+		unsigned int iNumFaces,Mesh& mesh);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_TVERT_LIST block in a file
+	//! \param iNumVertices Value of *MESH_NUMTVERTEX, if present.
+	//! Otherwise zero. This is used to check the consistency of the file.
+	//! A warning is sent to the logger if the validations fails.
+	//! \param mesh Mesh object to be filled
+	//! \param iChannel Output UVW channel
+	void ParseLV3MeshTListBlock(
+		unsigned int iNumVertices,Mesh& mesh, unsigned int iChannel = 0);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_TFACELIST block in a file
+	//! \param iNumFaces Value of *MESH_NUMTVFACES, if present.
+	//! Otherwise zero. This is used to check the consistency of the file.
+	//! A warning is sent to the logger if the validations fails.
+	//! \param mesh Mesh object to be filled
+	//! \param iChannel Output UVW channel
+	void ParseLV3MeshTFaceListBlock(
+		unsigned int iNumFaces,Mesh& mesh, unsigned int iChannel = 0);
+
+	// -------------------------------------------------------------------
+	//! Parse an additional mapping channel 
+	//! (specified via *MESH_MAPPINGCHANNEL)
+	//! \param iChannel Channel index to be filled
+	//! \param mesh Mesh object to be filled
+	void ParseLV3MappingChannel(
+		unsigned int iChannel, Mesh& mesh);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_CVERTLIST block in a file
+	//! \param iNumVertices Value of *MESH_NUMCVERTEX, if present.
+	//! Otherwise zero. This is used to check the consistency of the file.
+	//! A warning is sent to the logger if the validations fails.
+	//! \param mesh Mesh object to be filled
+	void ParseLV3MeshCListBlock(
+		unsigned int iNumVertices, Mesh& mesh);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_CFACELIST block in a file
+	//! \param iNumFaces Value of *MESH_NUMCVFACES, if present.
+	//! Otherwise zero. This is used to check the consistency of the file.
+	//! A warning is sent to the logger if the validations fails.
+	//! \param mesh Mesh object to be filled
+	void ParseLV3MeshCFaceListBlock(
+		unsigned int iNumFaces, Mesh& mesh);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_NORMALS block in a file
+	//! \param mesh Mesh object to be filled
+	void ParseLV3MeshNormalListBlock(Mesh& mesh);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_FACE block in a file
+	//! \param out receive the face data
+	void ParseLV4MeshFace(ASE::Face& out);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_VERT block in a file
+	//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
+	//! \param apOut Output buffer (3 floats)
+	//! \param rIndexOut Output index
+	void ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_VERT block in a file
+	//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
+	//! \param apOut Output buffer (3 floats)
+	void ParseLV4MeshFloatTriple(float* apOut);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_TFACE block in a file
+	//! (also works for MESH_CFACE)
+	//! \param apOut Output buffer (3 ints)
+	//! \param rIndexOut Output index
+	void ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut);
+
+	// -------------------------------------------------------------------
+	//! Parse a *MESH_TFACE block in a file
+	//! (also works for MESH_CFACE)
+	//! \param apOut Output buffer (3 ints)
+	void ParseLV4MeshLongTriple(unsigned int* apOut);
+
+	// -------------------------------------------------------------------
+	//! Parse a single float element 
+	//! \param fOut Output float
+	void ParseLV4MeshFloat(float& fOut);
+
+	// -------------------------------------------------------------------
+	//! Parse a single int element 
+	//! \param iOut Output integer
+	void ParseLV4MeshLong(unsigned int& iOut);
+
+	// -------------------------------------------------------------------
+	//! Skip the opening bracket at the beginning of a complex statement
+	bool SkipOpeningBracket();
+
+	// -------------------------------------------------------------------
+	//! Skip everything to the next: '*' or '\0'
+	bool SkipToNextToken();
+
+	// -------------------------------------------------------------------
+	//! Skip the current section until the token after the closing }.
+	//! This function handles embedded subsections correctly
+	bool SkipSection();
+
+	// -------------------------------------------------------------------
+	//! Output a warning to the logger
+	//! \param szWarn Warn message
+	void LogWarning(const char* szWarn);
+
+	// -------------------------------------------------------------------
+	//! Output an error to the logger
+	//! \param szWarn Error message
+	void LogError(const char* szWarn);
+
+public:
+
+	//! Pointer to current data
+	const char* m_szFile;
+
+	//! background color to be passed to the viewer
+	//! QNAN if none was found
+	aiColor3D m_clrBackground;
+
+	//! Base ambient color to be passed to all materials
+	//! QNAN if none was found
+	aiColor3D m_clrAmbient;
+
+	//! List of all materials found in the file
+	std::vector<Material> m_vMaterials;
+
+	//! List of all meshes found in the file
+	std::vector<Mesh> m_vMeshes;
+
+	//! Current line in the file
+	unsigned int iLineNumber;
+};
+
+
+};};
+
+#endif // !! include guard

+ 114 - 0
code/Assimp.cpp

@@ -1,22 +1,77 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the Plain-C API */
 #include <map>
 
 #include "../include/assimp.h"
 #include "../include/assimp.hpp"
 
+#include "../include/aiassert.h"
+using namespace Assimp;
+
+#if (defined AI_C_THREADSAFE)
+#	include <boost/thread/thread.hpp>
+#	include <boost/thread/mutex.hpp>
+#endif
+
 /** Stores the importer objects for all active import processes */
 typedef std::map< const aiScene*, Assimp::Importer* > ImporterMap;
+
 /** Local storage of all active import processes */
 static ImporterMap gActiveImports;
 
 /** Error message of the last failed import process */
 static std::string gLastErrorString;
 
+#if (defined AI_C_THREADSAFE)
+/** Global mutex to manage the access to the importer map */
+static boost::mutex gMutex;
+#endif
 
 // ------------------------------------------------------------------------------------------------
 // Reads the given file and returns its content. 
 const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
 {
+	ai_assert(NULL != pFile);
+
 	// create an Importer for this file
 	Assimp::Importer* imp = new Assimp::Importer;
 	// and have it read the file
@@ -25,6 +80,9 @@ const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
 	// if succeeded, place it in the collection of active processes
 	if( scene)
 	{
+#if (defined AI_C_THREADSAFE)
+		boost::mutex::scoped_lock lock(gMutex);
+#endif
 		gActiveImports[scene] = imp;
 	} 
 	else
@@ -42,6 +100,13 @@ const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
 // Releases all resources associated with the given import process. 
 void aiReleaseImport( const aiScene* pScene)
 {
+	if (!pScene)return;
+
+	// lock the mutex
+#if (defined AI_C_THREADSAFE)
+	boost::mutex::scoped_lock lock(gMutex);
+#endif
+
 	// find the importer associated with this data
 	ImporterMap::iterator it = gActiveImports.find( pScene);
 	// it should be there... else the user is playing fools with us
@@ -59,3 +124,52 @@ const char* aiGetErrorString()
 {
 	return gLastErrorString.c_str();
 }
+// ------------------------------------------------------------------------------------------------
+// Returns the error text of the last failed import process. 
+int aiIsExtensionSupported(const char* szExtension)
+{
+	ai_assert(NULL != szExtension);
+
+	// lock the mutex
+#if (defined AI_C_THREADSAFE)
+	boost::mutex::scoped_lock lock(gMutex);
+#endif
+
+	if (!gActiveImports.empty())
+	{
+		return (int)((*(gActiveImports.begin())).second->IsExtensionSupported(
+			std::string ( szExtension )));
+	}
+	// need to create a temporary Importer instance.
+	// TODO: Find a better solution ...
+	Assimp::Importer* pcTemp = new Assimp::Importer();
+	int i = (int)pcTemp->IsExtensionSupported(std::string ( szExtension ));
+	delete pcTemp;
+	return i;
+}
+// ------------------------------------------------------------------------------------------------
+// Get a list of all file extensions supported by ASSIMP
+void aiGetExtensionList(aiString* szOut)
+{
+	ai_assert(NULL != szOut);
+
+	// lock the mutex
+#if (defined AI_C_THREADSAFE)
+	boost::mutex::scoped_lock lock(gMutex);
+#endif
+
+	std::string szTemp;
+	if (!gActiveImports.empty())
+	{
+		(*(gActiveImports.begin())).second->GetExtensionList(szTemp);
+		szOut->Set ( szTemp );
+		return;
+	}
+	// need to create a temporary Importer instance.
+	// TODO: Find a better solution ...
+	Assimp::Importer* pcTemp = new Assimp::Importer();
+	pcTemp->GetExtensionList(szTemp);
+	szOut->Set ( szTemp );
+	delete pcTemp;
+}
+

+ 45 - 0
code/BaseImporter.cpp

@@ -1,5 +1,47 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the few default functions of the base importer class */
 #include "BaseImporter.h"
+#include "DefaultLogger.h"
 #include "../include/aiScene.h"
 #include "aiAssert.h"
 using namespace Assimp;
@@ -33,6 +75,9 @@ aiScene* BaseImporter::ReadFile( const std::string& pFile, IOSystem* pIOHandler)
 	{
 		// extract error description
 		mErrorText = exception->GetErrorText();
+
+		DefaultLogger::get()->error(mErrorText);
+
 		delete exception;
 
 		// and kill the partially imported data

+ 90 - 20
code/BaseImporter.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definition of the base class for all importer worker classes. */
 #ifndef AI_BASEIMPORTER_H_INC
 #define AI_BASEIMPORTER_H_INC
@@ -22,8 +62,10 @@ public:
 		mErrorText = pErrorText;
 	}
 
+	// -------------------------------------------------------------------
 	/** Returns the error text provided when throwing the exception */
-	const std::string& GetErrorText() const { return mErrorText; }
+	inline const std::string& GetErrorText() const 
+	{ return mErrorText; }
 
 private:
 	std::string mErrorText;
@@ -36,15 +78,16 @@ private:
  * The interface defines two functions: CanRead() is used to check if the 
  * importer can handle the format of the given file. If an implementation of 
  * this function returns true, the importer then calls ReadFile() which 
- * imports the given file. ReadFile is not overridable, it just calls InternReadFile() 
- * and catches any ImportErrorException that might occur.
+ * imports the given file. ReadFile is not overridable, it just calls 
+ * InternReadFile() and catches any ImportErrorException that might occur.
  */
 class BaseImporter
 {
 	friend class Importer;
 
 protected:
-	/** Constructor to be privately used by Importer */
+
+	/** Constructor to be privately used by #Importer */
 	BaseImporter();
 
 	/** Destructor, private as well */
@@ -56,46 +99,73 @@ public:
 	* @param pFile Path and file name of the file to be examined.
 	* @param pIOHandler The IO handler to use for accessing any file.
 	* @return true if the class can read this file, false if not.
+	*
+	* @note Sometimes ASSIMP uses this method to determine whether a
+	* a given file extension is generally supported. In this case the
+	* file extension is passed in the pFile parameter, pIOHandler is NULL
 	*/
-	virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const = 0;
+	virtual bool CanRead( const std::string& pFile, 
+		IOSystem* pIOHandler) const = 0;
+
 
 	// -------------------------------------------------------------------
 	/** Imports the given file and returns the imported data.
-	* If the import succeeds, ownership of the data is transferred to the caller. 
-	* If the import failes, NULL is returned. The function takes care that any
-	* partially constructed data is destroyed beforehand.
+	* If the import succeeds, ownership of the data is transferred to 
+	* the caller. If the import failes, NULL is returned. The function
+	* takes care that any partially constructed data is destroyed
+	* beforehand.
 	*
 	* @param pFile Path of the file to be imported. 
 	* @param pIOHandler IO-Handler used to open this and possible other files.
-	* @return The imported data or NULL if failed. If it failed a human-readable
-	*   error description can be retrieved by calling GetErrorText()
+	* @return The imported data or NULL if failed. If it failed a 
+	* human-readable error description can be retrieved by calling 
+	* GetErrorText()
 	*
-	* @note This function is not intended to be overridden. Implement InternReadFile()
-	*   to do the import. If an exception is thrown somewhere in InternReadFile(),
-	*   this function will catch it and transform it into a suitable response to the caller.
+	* @note This function is not intended to be overridden. Implement 
+	* InternReadFile() to do the import. If an exception is thrown somewhere 
+	* in InternReadFile(), this function will catch it and transform it into
+	*  a suitable response to the caller.
 	*/
 	aiScene* ReadFile( const std::string& pFile, IOSystem* pIOHandler);
 
+
 	// -------------------------------------------------------------------
 	/** Returns the error description of the last error that occured. 
-	 * @return A description of the last error that occured. An empty string if no error.
+	 * @return A description of the last error that occured. An empty
+	 * string if there was no error.
 	 */
-	const std::string& GetErrorText() const { return mErrorText; }
+	inline const std::string& GetErrorText() const 
+		{ return mErrorText; }
 
 protected:
+
 	// -------------------------------------------------------------------
-	/** Imports the given file into the given scene structure. The function is 
-	 * expected to throw an ImportErrorException if there is an error. If it
-	 * terminates normally, the data in aiScene is expected to be correct.
-	 * Override this function to implement the actual importing.
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 *  Importer implementations should append all file extensions
+	 *  which they supported to the passed string.
+	 *  Example: "*.blabb;*.quak;*.gug;*.foo" (no comma after the last!)
+	 * @param append Output string
+	 */
+	virtual void GetExtensionList(std::string& append) = 0;
+
+	// -------------------------------------------------------------------
+	/** Imports the given file into the given scene structure. The 
+	 * function is expected to throw an ImportErrorException if there is 
+	 * an error. If it terminates normally, the data in aiScene is 
+	 * expected to be correct. Override this function to implement the 
+	 * actual importing.
 	 * 
 	 * @param pFile Path of the file to be imported.
 	 * @param pScene The scene object to hold the imported data.
+	 * NULL is not a valid parameter.
 	 * @param pIOHandler The IO handler to use for any file access.
+	 * NULL is not a valid parameter.
 	 */
-	virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) = 0;
+	virtual void InternReadFile( const std::string& pFile, 
+		aiScene* pScene, IOSystem* pIOHandler) = 0;
 
 protected:
+
 	/** Error description in case there was one. */
 	std::string mErrorText;
 };

+ 40 - 0
code/BaseProcess.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Base class of all import post processing steps */
 #ifndef AI_BASEPROCESS_H_INC
 #define AI_BASEPROCESS_H_INC

+ 43 - 2
code/CalcTangentsProcess.cpp

@@ -1,5 +1,46 @@
-/** @file Implementation of the post processing step to calculate tangents and bitangents
- * for all imported meshes
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the post processing step to calculate 
+ *  tangents and bitangents for all imported meshes
  */
 
 #include <vector>

+ 41 - 0
code/CalcTangentsProcess.h

@@ -1,3 +1,44 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 a post processing step to calculate tangents and bitangents on all imported meshes.*/
 #ifndef AI_CALCTANGENTSPROCESS_H_INC
 #define AI_CALCTANGENTSPROCESS_H_INC

+ 40 - 0
code/ConvertToLHProcess.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 a post processing step to convert all data to a left-handed coordinate system.*/
 #ifndef AI_CONVERTTOLHPROCESS_H_INC
 #define AI_CONVERTTOLHPROCESS_H_INC

+ 40 - 14
code/DefaultIOStream.cpp

@@ -1,3 +1,43 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Default File I/O implementation for #Importer */
 
 #include "DefaultIOStream.h"
@@ -8,7 +48,6 @@
 using namespace Assimp;
 
 
-// ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 DefaultIOStream::~DefaultIOStream()
 {
@@ -17,8 +56,6 @@ DefaultIOStream::~DefaultIOStream()
 		fclose(this->mFile);
 	}	
 }
-
-// ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 size_t DefaultIOStream::Read(void* pvBuffer, 
 								size_t pSize, 
@@ -29,9 +66,6 @@ size_t DefaultIOStream::Read(void* pvBuffer,
 
 	return fread(pvBuffer, pSize, pCount, this->mFile);
 }
-
-
-// ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 size_t DefaultIOStream::Write(const void* pvBuffer, 
 								 size_t pSize,
@@ -42,9 +76,6 @@ size_t DefaultIOStream::Write(const void* pvBuffer,
 	fseek(mFile, 0, SEEK_SET);
 	return fwrite(pvBuffer, pSize, pCount, this->mFile);
 }
-
-
-// ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 aiReturn DefaultIOStream::Seek(size_t pOffset,
 						   aiOrigin pOrigin)
@@ -56,9 +87,6 @@ aiReturn DefaultIOStream::Seek(size_t pOffset,
 		(aiOrigin_END == pOrigin ? SEEK_END : SEEK_SET))) 
 		? AI_SUCCESS : AI_FAILURE);
 }
-
-
-// ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 size_t DefaultIOStream::Tell() const
 {
@@ -66,8 +94,6 @@ size_t DefaultIOStream::Tell() const
 
 	return ftell(this->mFile);
 }
-
-// ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 size_t DefaultIOStream::FileSize() const
 {

+ 40 - 0
code/DefaultIOStream.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Default file I/O using fXXX()-family of functions */
 #ifndef AI_DEFAULTIOSTREAM_H_INC
 #define AI_DEFAULTIOSTREAM_H_INC

+ 40 - 0
code/DefaultIOSystem.cpp

@@ -1,3 +1,43 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Default implementation of IOSystem using the standard C file functions */
 #include <stdlib.h>
 #include <string>

+ 40 - 0
code/DefaultIOSystem.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Default implementation of IOSystem using the standard C file functions */
 #ifndef AI_DEFAULTIOSYSTEM_H_INC
 #define AI_DEFAULTIOSYSTEM_H_INC

+ 41 - 0
code/GenFaceNormalsProcess.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the post processing step to generate face
 * normals for all imported faces.
 */

+ 40 - 0
code/GenFaceNormalsProcess.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 a post processing step to compute face normals for all loaded faces*/
 #ifndef AI_GENFACENORMALPROCESS_H_INC
 #define AI_GENFACENORMALPROCESS_H_INC

+ 41 - 0
code/GenVertexNormalsProcess.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the post processing step to generate face
 * normals for all imported faces.
 */

+ 40 - 0
code/GenVertexNormalsProcess.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 a post processing step to compute vertex normals for all loaded vertizes */
 #ifndef AI_GENVERTEXNORMALPROCESS_H_INC
 #define AI_GENVERTEXNORMALPROCESS_H_INC

+ 138 - 11
code/Importer.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the CPP-API class #Importer */
 #include <fstream>
 #include <string>
@@ -8,12 +49,35 @@
 #include "BaseProcess.h"
 #include "DefaultIOStream.h"
 #include "DefaultIOSystem.h"
-#include "XFileImporter.h"
-#include "3DSLoader.h"
-#include "MD3Loader.h"
-#include "MD2Loader.h"
-#include "PlyLoader.h"
-#include "ObjFileImporter.h"
+
+#if (!defined AI_BUILD_NO_X_IMPORTER)
+#	include "XFileImporter.h"
+#endif
+#if (!defined AI_BUILD_NO_3DS_IMPORTER)
+#	include "3DSLoader.h"
+#endif
+#if (!defined AI_BUILD_NO_MD3_IMPORTER)
+#	include "MD3Loader.h"
+#endif
+#if (!defined AI_BUILD_NO_MD4_IMPORTER)
+#	include "MD4Loader.h"
+#endif
+#if (!defined AI_BUILD_NO_MDL_IMPORTER)
+#	include "MDLLoader.h"
+#endif
+#if (!defined AI_BUILD_NO_MD2_IMPORTER)
+#	include "MD2Loader.h"
+#endif
+#if (!defined AI_BUILD_NO_PLY_IMPORTER)
+#	include "PlyLoader.h"
+#endif
+#if (!defined AI_BUILD_NO_ASE_IMPORTER)
+#	include "ASELoader.h"
+#endif
+#if (!defined AI_BUILD_NO_OBJ_IMPORTER)
+#	include "ObjFileImporter.h"
+#endif
+
 #include "CalcTangentsProcess.h"
 #include "JoinVerticesProcess.h"
 #include "ConvertToLHProcess.h"
@@ -32,25 +96,47 @@ Importer::Importer() :
 	mScene(NULL),
 	mErrorString("")	
 {
-	// default IO handler
+	// allocate a default IO handler
 	mIOHandler = new DefaultIOSystem;
 
 	// add an instance of each worker class here
+#if (!defined AI_BUILD_NO_X_IMPORTER)
 	mImporter.push_back( new XFileImporter());
+#endif
+#if (!defined AI_BUILD_NO_OBJ_IMPORTER)
 	mImporter.push_back( new ObjFileImporter());
+#endif
+#if (!defined AI_BUILD_NO_3DS_IMPORTER)
 	mImporter.push_back( new Dot3DSImporter());
+#endif
+#if (!defined AI_BUILD_NO_MD3_IMPORTER)
 	mImporter.push_back( new MD3Importer());
+#endif
+#if (!defined AI_BUILD_NO_MD2_IMPORTER)
 	mImporter.push_back( new MD2Importer());
+#endif
+#if (!defined AI_BUILD_NO_PLY_IMPORTER)
 	mImporter.push_back( new PLYImporter());
+#endif
+#if (!defined AI_BUILD_NO_MDL_IMPORTER)
+	mImporter.push_back( new MDLImporter());
+#endif
+#if (!defined AI_BUILD_NO_MD4_IMPORTER)
+	mImporter.push_back( new MD4Importer());
+#endif
+#if (!defined AI_BUILD_NO_ASE_IMPORTER)
+	mImporter.push_back( new ASEImporter());
+#endif
 
 	// add an instance of each post processing step here in the order of sequence it is executed
 	mPostProcessingSteps.push_back( new TriangulateProcess());
-	mPostProcessingSteps.push_back( new SplitLargeMeshesProcess());
+	mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Triangle());
 	mPostProcessingSteps.push_back( new KillNormalsProcess());
 	mPostProcessingSteps.push_back( new GenFaceNormalsProcess());
 	mPostProcessingSteps.push_back( new GenVertexNormalsProcess());
 	mPostProcessingSteps.push_back( new CalcTangentsProcess());
 	mPostProcessingSteps.push_back( new JoinVerticesProcess());
+	mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Vertex());
 	mPostProcessingSteps.push_back( new ConvertToLHProcess());
 }
 
@@ -63,6 +149,7 @@ Importer::~Importer()
 	for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++)
 		delete mPostProcessingSteps[a];
 
+	// delete the assigned IO handler
 	delete mIOHandler;
 
 	// kill imported scene. Destructors should do that recursivly
@@ -73,8 +160,17 @@ Importer::~Importer()
 // Supplies a custom IO handler to the importer to open and access files.
 void Importer::SetIOHandler( IOSystem* pIOHandler)
 {
-	delete mIOHandler;
-	mIOHandler = pIOHandler;
+	if (NULL == pIOHandler)
+	{
+		delete mIOHandler;
+		mIOHandler = new DefaultIOSystem();
+	}
+	else if (mIOHandler != pIOHandler)
+	{
+		delete mIOHandler;
+		mIOHandler = pIOHandler;
+	}
+	return;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -128,9 +224,40 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
 }
 
 // ------------------------------------------------------------------------------------------------
-//	Empty and rpivate copy constructor
+//	Empty and private copy constructor
 Importer::Importer(const Importer &other)
 {
 	// empty
 }
 
+// ------------------------------------------------------------------------------------------------
+// Helper function to check whether an extension is supported by ASSIMP
+bool Importer::IsExtensionSupported(const std::string& szExtension)
+{
+	for (std::vector<BaseImporter*>::const_iterator
+		i =  this->mImporter.begin();
+		i != this->mImporter.end();++i)
+	{
+		// pass the file extension to the CanRead(..,NULL)-method
+		if ((*i)->CanRead(szExtension,NULL))return true;
+	}
+	return false;
+}
+// ------------------------------------------------------------------------------------------------
+// Helper function to build a list of all file extensions supported by ASSIMP
+void Importer::GetExtensionList(std::string& szOut)
+{
+	unsigned int iNum = 0;
+	for (std::vector<BaseImporter*>::const_iterator
+		i =  this->mImporter.begin();
+		i != this->mImporter.end();++i,++iNum)
+	{
+		// insert a comma as delimiter character
+		if (0 != iNum)
+			szOut.append(";");
+
+		(*i)->GetExtensionList(szOut);
+	}
+	return;
+}
+

+ 41 - 0
code/JoinVerticesProcess.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the post processing step to join identical vertices
  * for all imported meshes
  */

+ 40 - 0
code/JoinVerticesProcess.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 a post processing step to join identical vertices on all imported meshes.*/
 #ifndef AI_JOINVERTICESPROCESS_H_INC
 #define AI_CALCTANGENTSPROCESS_H_INC

+ 40 - 0
code/KillNormalsProcess.cpp

@@ -1,3 +1,43 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the post processing step tokill mesh normals
 */
 #include "KillNormalsProcess.h"

+ 40 - 0
code/KillNormalsProcess.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 a post processing step to kill all loaded normals */
 #ifndef AI_KILLNORMALPROCESS_H_INC
 #define AI_KILLNORMALPROCESS_H_INC

+ 40 - 0
code/MD2FileData.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 helper data structures for importing MD2 files  */
 #ifndef AI_MD2FILEHELPER_H_INC
 #define AI_MD2FILEHELPER_H_INC

+ 122 - 64
code/MD2Loader.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the MD2 importer class */
 #include "MD2Loader.h"
 #include "MaterialSystem.h"
@@ -150,11 +191,11 @@ void MD2Importer::InternReadFile(
 	std::vector<aiVector3D> vTexCoords;
 	std::vector<aiVector3D> vNormals;
 
-	vPositions.resize(this->m_pcHeader->numVertices,aiVector3D());
-	vTexCoords.resize(this->m_pcHeader->numVertices,aiVector3D(
+	vPositions.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
+	vTexCoords.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D(
 		std::numeric_limits<float>::quiet_NaN(),
 		std::numeric_limits<float>::quiet_NaN(),0.0f));
-	vNormals.resize(this->m_pcHeader->numVertices,aiVector3D());
+	vNormals.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
 
 	// not sure whether there are MD2 files without texture coordinates
 	if (0 != this->m_pcHeader->numTexCoords && 0 != this->m_pcHeader->numSkins)
@@ -198,32 +239,9 @@ void MD2Importer::InternReadFile(
 		pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
 	}
 
-	// now read all vertices of the frame
-	for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->numVertices;++i)
-	{
-		// read x,y, and z component of the vertex
-
-		aiVector3D& vec = vPositions[i];
-
-		vec.x = (float)pcVerts[i].vertex[0] * pcFrame->scale[0];
-		vec.x += pcFrame->translate[0];
-
-		// (flip z and y component)
-		vec.z = (float)pcVerts[i].vertex[1] * pcFrame->scale[1];
-		vec.z += pcFrame->translate[1];
-
-		vec.y = (float)pcVerts[i].vertex[2] * pcFrame->scale[2];
-		vec.y += pcFrame->translate[2];
-
-		// read the normal vector from the precalculated normal table
-		vNormals[i] = *((const aiVector3D*)(&g_avNormals[std::min(
-			int(pcVerts[i].lightNormalIndex),
-			int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
-
-		std::swap ( vNormals[i].y,vNormals[i].z );
-	}
 
 	// now read all triangles of the first frame, apply scaling and translation
+	unsigned int iCurrent = 0;
 	if (0 != this->m_pcHeader->numTexCoords)
 	{
 		for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->numTriangles;++i)
@@ -235,40 +253,47 @@ void MD2Importer::InternReadFile(
 			// copy texture coordinates
 			// check whether they are different from the previous value at this index.
 			// In this case, create a full separate set of vertices/normals/texcoords
-			for (unsigned int c = 0; c < 3;++c)
+			for (unsigned int c = 0; c < 3;++c,++iCurrent)
 			{
+				pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent;
+
 				// validate vertex indices
 				if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices)
 					pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1;
 
 				// copy face indices
-				pScene->mMeshes[0]->mFaces[i].mIndices[c] = (unsigned int)pcTriangles[i].vertexIndices[c];
+				unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
+
+				// read x,y, and z component of the vertex
+				aiVector3D& vec = vPositions[iCurrent];
+
+				vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0];
+				vec.x += pcFrame->translate[0];
+
+				// (flip z and y component)
+				vec.z = (float)pcVerts[iIndex].vertex[1] * pcFrame->scale[1];
+				vec.z += pcFrame->translate[1];
+
+				vec.y = (float)pcVerts[iIndex].vertex[2] * pcFrame->scale[2];
+				vec.y += pcFrame->translate[2];
+
+				// read the normal vector from the precalculated normal table
+				vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min(
+					int(pcVerts[iIndex].lightNormalIndex),
+					int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
+
+				std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z );
 
 				// validate texture coordinates
-				if (pcTriangles[i].textureIndices[c] >= this->m_pcHeader->numTexCoords)
-					pcTriangles[i].textureIndices[c] = this->m_pcHeader->numTexCoords-1;
+				if (pcTriangles[iIndex].textureIndices[c] >= this->m_pcHeader->numTexCoords)
+					pcTriangles[iIndex].textureIndices[c] = this->m_pcHeader->numTexCoords-1;
 
-				aiVector3D* pcOut = &vTexCoords[pScene->mMeshes[0]->mFaces[i].mIndices[c]];
+				aiVector3D* pcOut = &vTexCoords[iCurrent];
 				float u,v;
 				u = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / this->m_pcHeader->skinWidth;
 				v = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / this->m_pcHeader->skinHeight;
-
-				if ( is_not_qnan ( pcOut->x ) && (pcOut->x != u || pcOut->y != v))
-				{
-					// generate a separate vertex/index set
-					vTexCoords.push_back(aiVector3D(u,v,0.0f));
-					vPositions.push_back(vPositions[pcTriangles[i].vertexIndices[c]]);
-					vNormals.push_back(vPositions[pcTriangles[i].vertexIndices[c]]);
-					unsigned int iPos = vTexCoords.size()-1;
-
-					pScene->mMeshes[0]->mFaces[i].mIndices[c] = iPos;
-				}
-				else
-				{
-					pcOut->x = u;
-					pcOut->y = v;
-			
-				}
+				pcOut->x = u;
+				pcOut->y = v;
 			}
 		}
 	}
@@ -280,18 +305,44 @@ void MD2Importer::InternReadFile(
 			pScene->mMeshes[0]->mFaces[i].mIndices = new unsigned int[3];
 			pScene->mMeshes[0]->mFaces[i].mNumIndices = 3;
 
-			// validate vertex indices
-			if (pcTriangles[i].vertexIndices[0] >= this->m_pcHeader->numVertices)
-				pcTriangles[i].vertexIndices[0] = this->m_pcHeader->numVertices-1;
-			if (pcTriangles[i].vertexIndices[1] >= this->m_pcHeader->numVertices)
-				pcTriangles[i].vertexIndices[1] = this->m_pcHeader->numVertices-1;
-			if (pcTriangles[i].vertexIndices[2] >= this->m_pcHeader->numVertices)
-				pcTriangles[i].vertexIndices[2] = this->m_pcHeader->numVertices-1;
-
-			// copy face indices
-			pScene->mMeshes[0]->mFaces[i].mIndices[0] = (unsigned int)pcTriangles[i].vertexIndices[0];
-			pScene->mMeshes[0]->mFaces[i].mIndices[1] = (unsigned int)pcTriangles[i].vertexIndices[1];
-			pScene->mMeshes[0]->mFaces[i].mIndices[2] = (unsigned int)pcTriangles[i].vertexIndices[2];
+			// copy texture coordinates
+			// check whether they are different from the previous value at this index.
+			// In this case, create a full separate set of vertices/normals/texcoords
+			for (unsigned int c = 0; c < 3;++c,++iCurrent)
+			{
+				pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent;
+
+				// validate vertex indices
+				if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices)
+					pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1;
+
+				// copy face indices
+				unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
+
+				// read x,y, and z component of the vertex
+				aiVector3D& vec = vPositions[iCurrent];
+
+				vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0];
+				vec.x += pcFrame->translate[0];
+
+				// (flip z and y component)
+				vec.z = (float)pcVerts[iIndex].vertex[1] * pcFrame->scale[1];
+				vec.z += pcFrame->translate[1];
+
+				vec.y = (float)pcVerts[iIndex].vertex[2] * pcFrame->scale[2];
+				vec.y += pcFrame->translate[2];
+
+				// read the normal vector from the precalculated normal table
+				vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min(
+					int(pcVerts[iIndex].lightNormalIndex),
+					int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
+
+				std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z );
+			
+				aiVector3D* pcOut = &vTexCoords[iCurrent];
+				pcOut->x = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / this->m_pcHeader->skinWidth;
+				pcOut->y = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / this->m_pcHeader->skinHeight;
+			}
 		}
 	}
 
@@ -302,9 +353,16 @@ void MD2Importer::InternReadFile(
 	pScene->mMeshes[0]->mTextureCoords[0] = new aiVector3D[vPositions.size()];
 
 	// memcpy() the data to the c-syle arrays
-	memcpy(pScene->mMeshes[0]->mVertices,			&vPositions[0],	vPositions.size() * sizeof(aiVector3D));
-	memcpy(pScene->mMeshes[0]->mNormals,			&vNormals[0],	vPositions.size() * sizeof(aiVector3D));
-	memcpy(pScene->mMeshes[0]->mTextureCoords[0],	&vTexCoords[0],	vPositions.size() * sizeof(aiVector3D));
+	memcpy(pScene->mMeshes[0]->mVertices,	&vPositions[0],	
+		vPositions.size() * sizeof(aiVector3D));
+	memcpy(pScene->mMeshes[0]->mNormals,	&vNormals[0],	
+		vPositions.size() * sizeof(aiVector3D));
+	
+	if (0 != this->m_pcHeader->numTexCoords)
+	{
+		memcpy(pScene->mMeshes[0]->mTextureCoords[0],	&vTexCoords[0],	
+			vPositions.size() * sizeof(aiVector3D));
+	}
 
 	return;
 }

+ 80 - 30
code/MD2Loader.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definition of the .MD2 importer class. */
 #ifndef AI_MD2LOADER_H_INCLUDED
 #define AI_MD2LOADER_H_INCLUDED
@@ -10,47 +50,57 @@ struct aiNode;
 
 namespace Assimp
 {
-	class MaterialHelper;
+class MaterialHelper;
 
-	using namespace MD2;
+using namespace MD2;
 
-	// ---------------------------------------------------------------------------
-	/** Used to load MD2 files
-	*/
-	class MD2Importer : public BaseImporter
-	{
-		friend class Importer;
+// ---------------------------------------------------------------------------
+/** Used to load MD2 files
+*/
+class MD2Importer : public BaseImporter
+{
+	friend class Importer;
 
-	protected:
-		/** Constructor to be privately used by Importer */
-		MD2Importer();
+protected:
+	/** Constructor to be privately used by Importer */
+	MD2Importer();
 
-		/** Destructor, private as well */
-		~MD2Importer();
+	/** Destructor, private as well */
+	~MD2Importer();
 
-	public:
+public:
 
-		// -------------------------------------------------------------------
-		/** Returns whether the class can handle the format of the given file. 
-		* See BaseImporter::CanRead() for details.	*/
-		bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+	// -------------------------------------------------------------------
+	/** Returns whether the class can handle the format of the given file. 
+	* See BaseImporter::CanRead() for details.	*/
+	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
 
-	protected:
+protected:
 
-		// -------------------------------------------------------------------
-		/** Imports the given file into the given scene structure. 
-		* See BaseImporter::InternReadFile() for details
-		*/
-		void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+	// -------------------------------------------------------------------
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 * See BaseImporter::GetExtensionList() for details
+	 */
+	void GetExtensionList(std::string& append)
+	{
+		append.append("*.md2");
+	}
+
+	// -------------------------------------------------------------------
+	/** Imports the given file into the given scene structure. 
+	* See BaseImporter::InternReadFile() for details
+	*/
+	void InternReadFile( const std::string& pFile, aiScene* pScene, 
+		IOSystem* pIOHandler);
 
-	protected:
+protected:
 
-		/** Header of the MD2 file */
-		const MD2::Header* m_pcHeader;
+	/** Header of the MD2 file */
+	const MD2::Header* m_pcHeader;
 
-		/** Buffer to hold the loaded file */
-		const unsigned char* mBuffer;
-	};
+	/** Buffer to hold the loaded file */
+	const unsigned char* mBuffer;
+};
 
 } // end of namespace Assimp
 

+ 49 - 3
code/MD2NormalTable.h

@@ -1,11 +1,55 @@
 /*
- *	Slightly modified version of the anorms.h header file released by
- *	ID software with the Quake 2 source code.
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Slightly modified version of the anorms.h header file 
+ *  released by ID software with the Quake 2 source code.
  *
  *	Table of normals used by MD2 models
  */
 
-float g_avNormals[][3] = {
+#ifndef AI_MDL_NORMALTABLE_H_INC
+#define AI_MDL_NORMALTABLE_H_INC
+
+
+float g_avNormals[162][3] = {
 { -0.525731f,  0.000000f,  0.850651f }, 
 { -0.442863f,  0.238856f,  0.864188f }, 
 { -0.295242f,  0.000000f,  0.955423f }, 
@@ -169,3 +213,5 @@ float g_avNormals[][3] = {
 { -0.587785f, -0.425325f, -0.688191f }, 
 { -0.688191f, -0.587785f, -0.425325f }
 };
+
+#endif // !! include guard

+ 78 - 38
code/MD3FileData.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 helper data structures for importing MD3 files  */
 #ifndef AI_MD3FILEHELPER_H_INC
 #define AI_MD3FILEHELPER_H_INC
@@ -43,51 +83,51 @@ namespace MD3
 #define AI_MD3_XYZ_SCALE		(1.0f/64.0f)
 
 // ---------------------------------------------------------------------------
-/**	\brief Data structure for the MD3 main header
+/** \brief Data structure for the MD3 main header
  */
 // ---------------------------------------------------------------------------
 struct Header
 {
-	// magic number
+	//! magic number
 	int32_t IDENT;
 
-	// file format version
+	//! file format version
 	int32_t VERSION;
 
-	// original name in .pak archive
+	//! original name in .pak archive
 	unsigned char NAME[ AI_MD3_MAXQPATH ];
 
-	// unknown
+	//! unknown
 	int32_t FLAGS;
 
-	// number of frames in the file
+	//! number of frames in the file
 	int32_t NUM_FRAMES;
 
-	// number of tags in the file
+	//! number of tags in the file
 	int32_t NUM_TAGS;
 
-	// number of surfaces in the file
+	//! number of surfaces in the file
 	int32_t NUM_SURFACES;
 
-	// number of skins in the file
+	//! number of skins in the file
 	int32_t NUM_SKINS;
 
-	// offset of the first frame
+	//! offset of the first frame
 	int32_t OFS_FRAMES;
 
-	// offset of the first tag
+	//! offset of the first tag
 	int32_t OFS_TAGS;
 
-	// offset of the first surface
+	//! offset of the first surface
 	int32_t OFS_SURFACES;
 
-	// end of file
+	//! end of file
 	int32_t OFS_EOF;
 } PACK_STRUCT;
 
 
 // ---------------------------------------------------------------------------
-/**	\brief Data structure for the frame header
+/** \brief Data structure for the frame header
  */
 // ---------------------------------------------------------------------------
 struct Frame
@@ -97,7 +137,7 @@ struct Frame
 
 
 // ---------------------------------------------------------------------------
-/**	\brief Data structure for the tag header
+/** \brief Data structure for the tag header
  */
 // ---------------------------------------------------------------------------
 struct Tag
@@ -107,95 +147,95 @@ struct Tag
 
 
 // ---------------------------------------------------------------------------
-/**	\brief Data structure for the surface header
+/** \brief Data structure for the surface header
  */
 // ---------------------------------------------------------------------------
 struct Surface
 {
-	// magic number
+	//! magic number
 	int32_t IDENT;
 
-	// original name of the surface
+	//! original name of the surface
 	unsigned char NAME[ AI_MD3_MAXQPATH ];
 
-	// unknown
+	//! unknown
 	int32_t FLAGS;
 
-	// number of frames in the surface
+	//! number of frames in the surface
 	int32_t NUM_FRAMES;
 
-	// number of shaders in the surface
+	//! number of shaders in the surface
 	int32_t NUM_SHADER;
 
-	// number of vertices in the surface
+	//! number of vertices in the surface
 	int32_t NUM_VERTICES;
 
-	// number of triangles in the surface
+	//! number of triangles in the surface
 	int32_t NUM_TRIANGLES;
 
 
-	// offset to the triangle data 
+	//! offset to the triangle data 
 	int32_t OFS_TRIANGLES;
 
-	// offset to the shader data
+	//! offset to the shader data
 	int32_t OFS_SHADERS;
 
-	// offset to the texture coordinate data
+	//! offset to the texture coordinate data
 	int32_t OFS_ST;
 
-	// offset to the vertex/normal data
+	//! offset to the vertex/normal data
 	int32_t OFS_XYZNORMAL;
 
-	// offset to the end of the Surface object
+	//! offset to the end of the Surface object
 	int32_t OFS_END;
 } PACK_STRUCT;
 
 // ---------------------------------------------------------------------------
-/**	\brief Data structure for a shader
+/** \brief Data structure for a shader
  */
 // ---------------------------------------------------------------------------
 struct Shader
 {
-	// filename of the shader
+	//! filename of the shader
 	unsigned char NAME[ AI_MD3_MAXQPATH ];
 
-	// index of the shader
+	//! index of the shader
 	int32_t SHADER_INDEX;
 } PACK_STRUCT;
 
 
 // ---------------------------------------------------------------------------
-/**	\brief Data structure for a triangle
+/** \brief Data structure for a triangle
  */
 // ---------------------------------------------------------------------------
 struct Triangle
 {
-	// triangle indices
+	//! triangle indices
 	int32_t INDEXES[3];
 } PACK_STRUCT;
 
 
 // ---------------------------------------------------------------------------
-/**	\brief Data structure for an UV coord
+/** \brief Data structure for an UV coord
  */
 // ---------------------------------------------------------------------------
 struct TexCoord
 {
-	// UV coordinates
+	//! UV coordinates
 	float U,V;
 } PACK_STRUCT;
 
 
 // ---------------------------------------------------------------------------
-/**	\brief Data structure for a vertex
+/** \brief Data structure for a vertex
  */
 // ---------------------------------------------------------------------------
 struct Vertex
 {
-	// X/Y/Z coordinates
+	//! X/Y/Z coordinates
 	int16_t X,Y,Z;
 
-	// encoded normal vector
+	//! encoded normal vector
 	int16_t  NORMAL;
 } PACK_STRUCT;
 

+ 69 - 28
code/MD3Loader.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the MD3 importer class */
 #include "MD3Loader.h"
 #include "MaterialSystem.h"
@@ -142,7 +183,7 @@ void MD3Importer::InternReadFile(
 		pScene->mMeshes[iNum] = new aiMesh();
 		aiMesh* pcMesh = pScene->mMeshes[iNum];
 
-		pcMesh->mNumVertices = pcSurfaces->NUM_VERTICES;
+		pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3;
 		pcMesh->mNumBones = 0;
 		pcMesh->mColors[0] = pcMesh->mColors[1] = pcMesh->mColors[2] = pcMesh->mColors[3] = NULL;
 		pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES;
@@ -153,35 +194,32 @@ void MD3Importer::InternReadFile(
 		pcMesh->mTextureCoords[1] = pcMesh->mTextureCoords[2] = pcMesh->mTextureCoords[3] = NULL;
 		pcMesh->mNumUVComponents[0] = 2;
 
-		// fill in all vertices and normals
-		// fill in all texture coordinates
-		for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_VERTICES;++i)
-		{
-			pcMesh->mVertices[i].x = pcVertices->X;
-			pcMesh->mVertices[i].y = pcVertices->Y;
-			pcMesh->mVertices[i].z = -1.0f*pcVertices->Z;
-
-			// convert the normal vector to uncompressed float3 format
-			LatLngNormalToVec3(pcVertices->NORMAL,(float*)&pcMesh->mNormals[i]);
-
-			// read texture coordinates
-			pcMesh->mTextureCoords[0][i].x = pcUVs->U;
-			pcMesh->mTextureCoords[0][i].y = 1.0f - pcUVs->V;
-
-			pcVertices++;
-			pcUVs++;
-		}
-
 		// fill in all triangles
+		unsigned int iCurrent = 0;
 		for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_TRIANGLES;++i)
 		{
 			pcMesh->mFaces[i].mIndices = new unsigned int[3];
 			pcMesh->mFaces[i].mNumIndices = 3;
 
-			pcMesh->mFaces[i].mIndices[0] = pcTriangles->INDEXES[0];
-			pcMesh->mFaces[i].mIndices[1] = pcTriangles->INDEXES[1];
-			pcMesh->mFaces[i].mIndices[2] = pcTriangles->INDEXES[2];
+			for (unsigned int c = 0; c < 3;++c,++iCurrent)
+			{
+				pcMesh->mFaces[i].mIndices[c] = iCurrent;
+
+				// read vertices
+				pcMesh->mVertices[iCurrent].x = pcVertices[ pcTriangles->INDEXES[c]].X;
+				pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y;
+				pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z * -1.0f;
+
+				// convert the normal vector to uncompressed float3 format
+				LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,
+					(float*)&pcMesh->mNormals[iCurrent]);
+
+				std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z );
 
+				// read texture coordinates
+				pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U;
+				pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[ pcTriangles->INDEXES[c]].V;
+			}
 			pcTriangles++;
 		}
 
@@ -250,12 +288,15 @@ void MD3Importer::InternReadFile(
 			{
 				MaterialHelper* pcHelper = new MaterialHelper();
 
-				aiString szString;
-				const size_t iLen = strlen(szEndDir2);
-				memcpy(szString.data,szEndDir2,iLen+1);
-				szString.length = iLen-1;
+				if (szEndDir2)
+				{
+					aiString szString;
+					const size_t iLen = strlen(szEndDir2);
+					memcpy(szString.data,szEndDir2,iLen+1);
+					szString.length = iLen-1;
 
-				pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
+					pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
+				}
 
 				int iMode = (int)aiShadingMode_Gouraud;
 				pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);

+ 79 - 29
code/MD3Loader.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definition of the .MD3 importer class. */
 #ifndef AI_MD3LOADER_H_INCLUDED
 #define AI_MD3LOADER_H_INCLUDED
@@ -13,46 +53,56 @@ struct aiNode;
 #include "MD3FileData.h"
 namespace Assimp
 {
-	class MaterialHelper;
+class MaterialHelper;
 
-	using namespace MD3;
+using namespace MD3;
 
-	// ---------------------------------------------------------------------------
-	/** Used to load MD3 files
-	*/
-	class MD3Importer : public BaseImporter
-	{
-		friend class Importer;
+// ---------------------------------------------------------------------------
+/** Used to load MD3 files
+*/
+class MD3Importer : public BaseImporter
+{
+	friend class Importer;
 
-	protected:
-		/** Constructor to be privately used by Importer */
-		MD3Importer();
+protected:
+	/** Constructor to be privately used by Importer */
+	MD3Importer();
 
-		/** Destructor, private as well */
-		~MD3Importer();
+	/** Destructor, private as well */
+	~MD3Importer();
 
-	public:
+public:
 
-		// -------------------------------------------------------------------
-		/** Returns whether the class can handle the format of the given file. 
-		* See BaseImporter::CanRead() for details.	*/
-		bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+	// -------------------------------------------------------------------
+	/** Returns whether the class can handle the format of the given file. 
+	* See BaseImporter::CanRead() for details.	*/
+	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
 
-	protected:
+protected:
 
-		// -------------------------------------------------------------------
-		/** Imports the given file into the given scene structure. 
-		* See BaseImporter::InternReadFile() for details
-		*/
-		void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+	// -------------------------------------------------------------------
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 * See BaseImporter::GetExtensionList() for details
+	 */
+	void GetExtensionList(std::string& append)
+	{
+		append.append("*.md3");
+	}
+
+	// -------------------------------------------------------------------
+	/** Imports the given file into the given scene structure. 
+	* See BaseImporter::InternReadFile() for details
+	*/
+	void InternReadFile( const std::string& pFile, aiScene* pScene, 
+		IOSystem* pIOHandler);
 
-	protected:
+protected:
 
-		/** Header of the MD3 file */
-		const MD3::Header* m_pcHeader;
+	/** Header of the MD3 file */
+	const MD3::Header* m_pcHeader;
 
-		/** Buffer to hold the loaded file */
-		const unsigned char* mBuffer;
+	/** Buffer to hold the loaded file */
+	const unsigned char* mBuffer;
 	};
 
 } // end of namespace Assimp

+ 218 - 0
code/MD4FileData.h

@@ -0,0 +1,218 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 helper data structures for importing MD4 files  */
+#ifndef AI_MD4FILEHELPER_H_INC
+#define AI_MD4FILEHELPER_H_INC
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include "../include/aiTypes.h"
+#include "../include/aiMesh.h"
+#include "../include/aiAnim.h"
+
+#if defined(_MSC_VER) ||  defined(__BORLANDC__) ||	defined (__BCPLUSPLUS__)
+#	pragma pack(push,1)
+#	define PACK_STRUCT
+#elif defined( __GNUC__ )
+#	define PACK_STRUCT	__attribute__((packed))
+#else
+#	error Compiler not supported
+#endif
+
+
+namespace Assimp
+{
+// http://gongo.quakedev.com/md4.html
+namespace MD4
+{
+
+#define AI_MD4_MAGIC_NUMBER_BE	'IDP4'
+#define AI_MD4_MAGIC_NUMBER_LE	'4PDI'
+
+// common limitations
+#define AI_MD4_VERSION			4
+#define AI_MD4_MAXQPATH			64
+#define AI_MD4_MAX_FRAMES		2028
+#define AI_MD4_MAX_SURFACES		32
+#define AI_MD4_MAX_BONES		256
+#define AI_MD4_MAX_VERTS		4096	
+#define AI_MD4_MAX_TRIANGLES	8192	
+
+// ---------------------------------------------------------------------------
+/** \brief Data structure for the MD4 main header
+ */
+// ---------------------------------------------------------------------------
+struct Header
+{
+	//! magic number
+	int32_t magic;
+
+	//! file format version
+	int32_t version;
+
+	//! original name in .pak archive
+	unsigned char name[ AI_MD4_MAXQPATH ];
+
+	//! number of frames in the file
+	int32_t NUM_FRAMES;
+
+	//! number of bones in the file
+	int32_t NUM_BONES;
+
+	//! number of surfaces in the file
+	int32_t NUM_SURFACES;
+
+	//! offset of the first frame
+	int32_t OFS_FRAMES;
+
+	//! offset of the first bone
+	int32_t OFS_BONES;
+
+	//! offset of the first surface
+	int32_t OFS_SURFACES;
+
+	//! end of file
+	int32_t OFS_EOF;
+} PACK_STRUCT;
+
+// ---------------------------------------------------------------------------
+/** \brief Stores the local transformation matrix of a bone
+ */
+// ---------------------------------------------------------------------------
+struct BoneFrame
+{  
+	float matrix[3][4]; 
+} PACK_STRUCT;
+
+// ---------------------------------------------------------------------------
+/** \brief Stores the name / parent index / flag of a node
+ */
+// ---------------------------------------------------------------------------
+struct  BoneName
+{  
+	char name[32] ; 
+	int parent ;
+	int flags ;
+}  PACK_STRUCT;
+
+// ---------------------------------------------------------------------------
+/** \brief Data structure for a surface in a MD4 file
+ */
+// ---------------------------------------------------------------------------
+struct Surface
+{  
+	int32_t ident;
+	char name[64];
+	char shader[64];
+	int32_t shaderIndex;
+	int32_t lodBias;
+	int32_t minLod;
+	int32_t ofsHeader;
+	int32_t numVerts;
+	int32_t ofsVerts;
+	int32_t numTris;
+	int32_t ofsTris;
+	int32_t numBoneRefs;
+	int32_t ofsBoneRefs;
+	int32_t ofsCollapseMap;
+	int32_t ofsEnd;
+} PACK_STRUCT;
+
+
+// ---------------------------------------------------------------------------
+/** \brief Data structure for a MD4 vertex' weight
+ */
+// ---------------------------------------------------------------------------
+struct Weight
+{  
+	int32_t boneIndex; 
+	float boneWeight; 
+	float offset[3]; 
+} PACK_STRUCT; 
+
+// ---------------------------------------------------------------------------
+/** \brief Data structure for a vertex in a MD4 file
+ */
+// ---------------------------------------------------------------------------
+struct Vertex
+{  
+	float vertex[3];
+	float normal[3];
+	float texCoords[2];
+	int32_t numWeights;
+	Weight weights[1];
+} PACK_STRUCT; 
+
+// ---------------------------------------------------------------------------
+/** \brief Data structure for a triangle in a MD4 file
+ */
+// ---------------------------------------------------------------------------
+struct Triangle 
+{  
+	int32_t indexes[3]; 
+} PACK_STRUCT;
+
+// ---------------------------------------------------------------------------
+/** \brief Data structure for a MD4 frame
+ */
+// ---------------------------------------------------------------------------
+struct Frame
+{  
+	float bounds[3][2];
+	float localOrigin[3]; 
+	float radius;
+	BoneFrame bones[1]; 
+} PACK_STRUCT; 
+
+
+// reset packing to the original value
+#if defined(_MSC_VER) ||  defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
+#	pragma pack( pop )
+#endif
+#undef PACK_STRUCT
+
+
+};
+};
+
+#endif // !! AI_MD4FILEHELPER_H_INC

+ 115 - 0
code/MD4Loader.cpp

@@ -0,0 +1,115 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the MD4 importer class */
+#include "MD4Loader.h"
+#include "MaterialSystem.h"
+
+#include "../include/IOStream.h"
+#include "../include/IOSystem.h"
+#include "../include/aiMesh.h"
+#include "../include/aiScene.h"
+#include "../include/aiAssert.h"
+
+#include <boost/scoped_ptr.hpp>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+MD4Importer::MD4Importer()
+{
+}
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well 
+MD4Importer::~MD4Importer()
+{
+}
+// ------------------------------------------------------------------------------------------------
+// Returns whether the class can handle the format of the given file. 
+bool MD4Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
+{
+	// simple check of file extension is enough for the moment
+	std::string::size_type pos = pFile.find_last_of('.');
+	// no file extension - can't read
+	if( pos == std::string::npos)
+		return false;
+	std::string extension = pFile.substr( pos);
+
+	if (extension.length() < 4)return false;
+	if (extension[0] != '.')return false;
+
+	// not brilliant but working ;-)
+	if( extension == ".md4" || extension == ".MD4" || 
+		extension == ".mD4" || extension == ".Md4")
+	{
+		return true;
+	}
+#if (!defined AI_MD4_DONT_SUPPORT_RAVENSOFT_MDR)
+	if (extension[1] != 'm' && extension[1] != 'M')return false;
+	if (extension[2] != 'd' && extension[2] != 'D')return false;
+	if (extension[3] != 'r' && extension[3] != 'R')return false;
+#endif
+
+	return true;
+}
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure. 
+void MD4Importer::InternReadFile( 
+	const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
+{
+	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+	// Check whether we can read from the file
+	if( file.get() == NULL)
+	{
+		throw new ImportErrorException( "Failed to open md4/mdr file " + pFile + ".");
+	}
+
+	// check whether the md4 file is large enough to contain
+	// at least the file header
+	size_t fileSize = file->FileSize();
+	if( fileSize < sizeof(MD4::Header))
+	{
+		throw new ImportErrorException( ".mdd File is too small.");
+	}
+	return;
+}

+ 80 - 30
code/MD4Loader.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definition of the .MD4 importer class. */
 #ifndef AI_MD4LOADER_H_INCLUDED
 #define AI_MD4LOADER_H_INCLUDED
@@ -10,47 +50,57 @@ struct aiNode;
 
 namespace Assimp
 {
-	class MaterialHelper;
+class MaterialHelper;
 
-	using namespace MD4;
+using namespace MD4;
 
-	// ---------------------------------------------------------------------------
-	/** Used to load MD4 files
-	*/
-	class MD4Importer : public BaseImporter
-	{
-		friend class Importer;
+// ---------------------------------------------------------------------------
+/** Used to load MD4 files
+*/
+class MD4Importer : public BaseImporter
+{
+	friend class Importer;
 
-	protected:
-		/** Constructor to be privately used by Importer */
-		MD4Importer();
+protected:
+	/** Constructor to be privately used by Importer */
+	MD4Importer();
 
-		/** Destructor, private as well */
-		~MD4Importer();
+	/** Destructor, private as well */
+	~MD4Importer();
 
-	public:
+public:
 
-		// -------------------------------------------------------------------
-		/** Returns whether the class can handle the format of the given file. 
-		* See BaseImporter::CanRead() for details.	*/
-		bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+	// -------------------------------------------------------------------
+	/** Returns whether the class can handle the format of the given file. 
+	* See BaseImporter::CanRead() for details.	*/
+	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
 
-	protected:
+protected:
 
-		// -------------------------------------------------------------------
-		/** Imports the given file into the given scene structure. 
-		* See BaseImporter::InternReadFile() for details
-		*/
-		void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+	// -------------------------------------------------------------------
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 * See BaseImporter::GetExtensionList() for details
+	 */
+	void GetExtensionList(std::string& append)
+	{
+		append.append("*.md4;*.mdr");
+	}
+
+	// -------------------------------------------------------------------
+	/** Imports the given file into the given scene structure. 
+	* See BaseImporter::InternReadFile() for details
+	*/
+	void InternReadFile( const std::string& pFile, aiScene* pScene,
+		IOSystem* pIOHandler);
 
-	protected:
+protected:
 
-		/** Header of the MD4 file */
-		const MD4::Header* m_pcHeader;
+	/** Header of the MD4 file */
+	const MD4::Header* m_pcHeader;
 
-		/** Buffer to hold the loaded file */
-		const unsigned char* mBuffer;
-	};
+	/** Buffer to hold the loaded file */
+	const unsigned char* mBuffer;
+};
 
 } // end of namespace Assimp
 

+ 81 - 30
code/MD5Loader.h

@@ -1,3 +1,44 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definition of the .MD5 importer class. */
 #ifndef AI_MD5LOADER_H_INCLUDED
 #define AI_MD5LOADER_H_INCLUDED
@@ -10,47 +51,57 @@ struct aiNode;
 
 namespace Assimp
 {
-	class MaterialHelper;
+class MaterialHelper;
 
-	using namespace MD5;
+using namespace MD5;
 
-	// ---------------------------------------------------------------------------
-	/** Used to load MD5 files
-	*/
-	class MD5Importer : public BaseImporter
-	{
-		friend class Importer;
+// ---------------------------------------------------------------------------
+/** Used to load MD5 files
+*/
+class MD5Importer : public BaseImporter
+{
+	friend class Importer;
+
+protected:
+	/** Constructor to be privately used by Importer */
+	MD5Importer();
 
-	protected:
-		/** Constructor to be privately used by Importer */
-		MD5Importer();
+	/** Destructor, private as well */
+	~MD5Importer();
 
-		/** Destructor, private as well */
-		~MD5Importer();
+public:
 
-	public:
+	// -------------------------------------------------------------------
+	/** Returns whether the class can handle the format of the given file. 
+	* See BaseImporter::CanRead() for details.	*/
+	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
 
-		// -------------------------------------------------------------------
-		/** Returns whether the class can handle the format of the given file. 
-		* See BaseImporter::CanRead() for details.	*/
-		bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+protected:
 
-	protected:
+	// -------------------------------------------------------------------
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 * See BaseImporter::GetExtensionList() for details
+	 */
+	void GetExtensionList(std::string& append)
+	{
+		append.append("*.md5");
+	}
 
-		// -------------------------------------------------------------------
-		/** Imports the given file into the given scene structure. 
-		* See BaseImporter::InternReadFile() for details
-		*/
-		void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+	// -------------------------------------------------------------------
+	/** Imports the given file into the given scene structure. 
+	* See BaseImporter::InternReadFile() for details
+	*/
+	void InternReadFile( const std::string& pFile, aiScene* pScene, 
+		IOSystem* pIOHandler);
 
-	protected:
+protected:
 
-		/** Header of the MD5 file */
-		const MD5::Header* m_pcHeader;
+	/** Header of the MD5 file */
+	const MD5::Header* m_pcHeader;
 
-		/** Buffer to hold the loaded file */
-		const unsigned char* mBuffer;
-	};
+	/** Buffer to hold the loaded file */
+	const unsigned char* mBuffer;
+};
 
 } // end of namespace Assimp
 

+ 118 - 0
code/MDLDefaultColorMap.h

@@ -0,0 +1,118 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 default color map used for Quake 1 model textures
+ *
+ * The lib tries to load colormap.lmp from the model's directory.
+ * This table is only used when required.
+ */
+
+#ifndef AI_MDL_DEFAULTLMP_H_INC
+#define AI_MDL_DEFAULTLMP_H_INC
+
+const unsigned char g_aclrDefaultColorMap[256][3] = {
+{  0,   0,   0}, { 15,  15,  15}, { 31,  31,  31}, { 47,  47,  47}, 
+{ 63,  63,  63}, { 75,  75,  75}, { 91,  91,  91}, {107, 107, 107}, 
+{123, 123, 123}, {139, 139, 139}, {155, 155, 155}, {171, 171, 171}, 
+{187, 187, 187}, {203, 203, 203}, {219, 219, 219}, {235, 235, 235}, 
+{ 15,  11,   7}, { 23,  15,  11}, { 31,  23,  11}, { 39,  27,  15}, 
+{ 47,  35,  19}, { 55,  43,  23}, { 63,  47,  23}, { 75,  55,  27}, 
+{ 83,  59,  27}, { 91,  67,  31}, { 99,  75,  31}, {107,  83,  31}, 
+{115,  87,  31}, {123,  95,  35}, {131, 103,  35}, {143, 111,  35}, 
+{ 11,  11,  15}, { 19,  19,  27}, { 27,  27,  39}, { 39,  39,  51}, 
+{ 47,  47,  63}, { 55,  55,  75}, { 63,  63,  87}, { 71,  71, 103}, 
+{ 79,  79, 115}, { 91,  91, 127}, { 99,  99, 139}, {107, 107, 151}, 
+{115, 115, 163}, {123, 123, 175}, {131, 131, 187}, {139, 139, 203}, 
+{  0,   0,   0}, {  7,   7,   0}, { 11,  11,   0}, { 19,  19,   0}, 
+{ 27,  27,   0}, { 35,  35,   0}, { 43,  43,   7}, { 47,  47,   7}, 
+{ 55,  55,   7}, { 63,  63,   7}, { 71,  71,   7}, { 75,  75,  11}, 
+{ 83,  83,  11}, { 91,  91,  11}, { 99,  99,  11}, {107, 107,  15}, 
+{  7,   0,   0}, { 15,   0,   0}, { 23,   0,   0}, { 31,   0,   0}, 
+{ 39,   0,   0}, { 47,   0,   0}, { 55,   0,   0}, { 63,   0,   0}, 
+{ 71,   0,   0}, { 79,   0,   0}, { 87,   0,   0}, { 95,   0,   0}, 
+{103,   0,   0}, {111,   0,   0}, {119,   0,   0}, {127,   0,   0}, 
+{ 19,  19,   0}, { 27,  27,   0}, { 35,  35,   0}, { 47,  43,   0}, 
+{ 55,  47,   0}, { 67,  55,   0}, { 75,  59,   7}, { 87,  67,   7}, 
+{ 95,  71,   7}, {107,  75,  11}, {119,  83,  15}, {131,  87,  19}, 
+{139,  91,  19}, {151,  95,  27}, {163,  99,  31}, {175, 103,  35}, 
+{ 35,  19,   7}, { 47,  23,  11}, { 59,  31,  15}, { 75,  35,  19}, 
+{ 87,  43,  23}, { 99,  47,  31}, {115,  55,  35}, {127,  59,  43}, 
+{143,  67,  51}, {159,  79,  51}, {175,  99,  47}, {191, 119,  47}, 
+{207, 143,  43}, {223, 171,  39}, {239, 203,  31}, {255, 243,  27}, 
+{ 11,   7,   0}, { 27,  19,   0}, { 43,  35,  15}, { 55,  43,  19}, 
+{ 71,  51,  27}, { 83,  55,  35}, { 99,  63,  43}, {111,  71,  51}, 
+{127,  83,  63}, {139,  95,  71}, {155, 107,  83}, {167, 123,  95}, 
+{183, 135, 107}, {195, 147, 123}, {211, 163, 139}, {227, 179, 151}, 
+{171, 139, 163}, {159, 127, 151}, {147, 115, 135}, {139, 103, 123}, 
+{127,  91, 111}, {119,  83,  99}, {107,  75,  87}, { 95,  63,  75}, 
+{ 87,  55,  67}, { 75,  47,  55}, { 67,  39,  47}, { 55,  31,  35}, 
+{ 43,  23,  27}, { 35,  19,  19}, { 23,  11,  11}, { 15,   7,   7}, 
+{187, 115, 159}, {175, 107, 143}, {163,  95, 131}, {151,  87, 119}, 
+{139,  79, 107}, {127,  75,  95}, {115,  67,  83}, {107,  59,  75}, 
+{ 95,  51,  63}, { 83,  43,  55}, { 71,  35,  43}, { 59,  31,  35}, 
+{ 47,  23,  27}, { 35,  19,  19}, { 23,  11,  11}, { 15,   7,   7}, 
+{219, 195, 187}, {203, 179, 167}, {191, 163, 155}, {175, 151, 139}, 
+{163, 135, 123}, {151, 123, 111}, {135, 111,  95}, {123,  99,  83}, 
+{107,  87,  71}, { 95,  75,  59}, { 83,  63,  51}, { 67,  51,  39}, 
+{ 55,  43,  31}, { 39,  31,  23}, { 27,  19,  15}, { 15,  11,   7}, 
+{111, 131, 123}, {103, 123, 111}, { 95, 115, 103}, { 87, 107,  95}, 
+{ 79,  99,  87}, { 71,  91,  79}, { 63,  83,  71}, { 55,  75,  63}, 
+{ 47,  67,  55}, { 43,  59,  47}, { 35,  51,  39}, { 31,  43,  31}, 
+{ 23,  35,  23}, { 15,  27,  19}, { 11,  19,  11}, {  7,  11,   7}, 
+{255, 243,  27}, {239, 223,  23}, {219, 203,  19}, {203, 183,  15}, 
+{187, 167,  15}, {171, 151,  11}, {155, 131,   7}, {139, 115,   7}, 
+{123,  99,   7}, {107,  83,   0}, { 91,  71,   0}, { 75,  55,   0}, 
+{ 59,  43,   0}, { 43,  31,   0}, { 27,  15,   0}, { 11,   7,   0}, 
+{  0,   0, 255}, { 11,  11, 239}, { 19,  19, 223}, { 27,  27, 207}, 
+{ 35,  35, 191}, { 43,  43, 175}, { 47,  47, 159}, { 47,  47, 143}, 
+{ 47,  47, 127}, { 47,  47, 111}, { 47,  47,  95}, { 43,  43,  79}, 
+{ 35,  35,  63}, { 27,  27,  47}, { 19,  19,  31}, { 11,  11,  15}, 
+{ 43,   0,   0}, { 59,   0,   0}, { 75,   7,   0}, { 95,   7,   0}, 
+{111,  15,   0}, {127,  23,   7}, {147,  31,   7}, {163,  39,  11}, 
+{183,  51,  15}, {195,  75,  27}, {207,  99,  43}, {219, 127,  59}, 
+{227, 151,  79}, {231, 171,  95}, {239, 191, 119}, {247, 211, 139}, 
+{167, 123,  59}, {183, 155,  55}, {199, 195,  55}, {231, 227,  87}, 
+{127, 191, 255}, {171, 231, 255}, {215, 255, 255}, {103,   0,   0}, 
+{139,   0,   0}, {179,   0,   0}, {215,   0,   0}, {255,   0,   0}, 
+{255, 243, 147}, {255, 247, 199}, {255, 255, 255}, {159,  91,  83} };
+
+
+#endif // !! AI_MDL_DEFAULTLMP_H_INC

+ 706 - 0
code/MDLFileData.h

@@ -0,0 +1,706 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definition of in-memory structures for the MDL file format. 
+//
+// The specification has been taken from various sources on the internet.
+// http://tfc.duke.free.fr/coding/mdl-specs-en.html
+
+
+#ifndef AI_MDLFILEHELPER_H_INC
+#define AI_MDLFILEHELPER_H_INC
+
+#include <string>
+#include <vector>
+
+#include "../include/aiTypes.h"
+#include "../include/aiMesh.h"
+#include "../include/aiAnim.h"
+#include "../include/aiMaterial.h"
+
+// ugly compiler dependent packing stuff
+#if defined(_MSC_VER) ||  defined(__BORLANDC__) ||	defined (__BCPLUSPLUS__)
+#	pragma pack(push,1)
+#	define PACK_STRUCT
+#elif defined( __GNUC__ )
+#	define PACK_STRUCT	__attribute__((packed))
+#else
+#	error Compiler not supported. Never do this again.
+#endif
+
+
+namespace Assimp
+{
+namespace MDL
+{
+
+// magic bytes used in Quake 1 MDL meshes
+#define AI_MDL_MAGIC_NUMBER_BE	'IDPO'
+#define AI_MDL_MAGIC_NUMBER_LE	'OPDI'
+
+// magic bytes used in GameStudio A4 MDL meshes
+#define AI_MDL_MAGIC_NUMBER_BE_GS4	'MDL3'
+#define AI_MDL_MAGIC_NUMBER_LE_GS4	'3LDM'
+
+// magic bytes used in GameStudio A5+ MDL meshes
+#define AI_MDL_MAGIC_NUMBER_BE_GS5a	'MDL4'
+#define AI_MDL_MAGIC_NUMBER_LE_GS5a	'4LDM'
+#define AI_MDL_MAGIC_NUMBER_BE_GS5b	'MDL5'
+#define AI_MDL_MAGIC_NUMBER_LE_GS5b	'5LDM'
+
+// magic bytes used in GameStudio A6+ MDL meshes
+#define AI_MDL_MAGIC_NUMBER_BE_GS6	'MDL6'
+#define AI_MDL_MAGIC_NUMBER_LE_GS6	'6LDM'
+
+// magic bytes used in GameStudio A7+ MDL meshes
+#define AI_MDL_MAGIC_NUMBER_BE_GS7	'MDL7'
+#define AI_MDL_MAGIC_NUMBER_LE_GS7	'7LDM'
+
+// common limitations for Quake1 meshes. The loader does not check them,
+// but models should not exceed these limits.
+#if (!defined AI_MDL_VERSION)
+#	define AI_MDL_VERSION				6
+#endif
+#if (!defined AI_MDL_MAX_FRAMES)
+#	define AI_MDL_MAX_FRAMES			256
+#endif
+#if (!defined AI_MDL_MAX_UVS)
+#	define AI_MDL_MAX_UVS				1024	
+#endif
+#if (!defined AI_MDL_MAX_VERTS)
+#	define AI_MDL_MAX_VERTS				1024
+#endif
+#if (!defined AI_MDL_MAX_TRIANGLES)
+#	define AI_MDL_MAX_TRIANGLES			2048	
+#endif
+
+// ---------------------------------------------------------------------------
+/** \struct Header
+ *  \brief Data structure for the MDL main header
+ */
+// ---------------------------------------------------------------------------
+struct Header
+{
+	//! magic number: "IDPO"
+	int32_t ident;          
+
+	//! version number: 6
+	int32_t version;          
+
+	//! scale factors for each axis
+	aiVector3D scale;				
+
+	//! translation factors for each axis
+	aiVector3D translate;	
+
+	//! bounding radius of the mesh
+	float boundingradius;
+	 
+	//! Position of the viewer's exe. Ignored
+	aiVector3D vEyePos;
+
+	//! Number of textures
+	int32_t num_skins;       
+
+	//! Texture width in pixels
+	int32_t skinwidth;        
+
+	//! Texture height in pixels
+	int32_t skinheight;       
+
+	//! Number of vertices contained in the file
+	int32_t num_verts;       
+
+	//! Number of triangles contained in the file
+	int32_t num_tris;         
+
+	//! Number of frames contained in the file
+	int32_t num_frames;      
+
+	//! 0 = synchron, 1 = random . Ignored
+	int32_t synctype;         
+
+	//! State flag
+	int32_t flags;     
+
+	//! ???
+	float size;
+} PACK_STRUCT;
+
+
+// ---------------------------------------------------------------------------
+/** \struct Header_MDL7
+ *  \brief Data structure for the MDL 7 main header
+ */
+// ---------------------------------------------------------------------------
+struct Header_MDL7
+{
+	//! magic number: "MDL7"
+	char	ident[4];		
+
+	//! Version number. Ignored
+	int32_t	version;		
+
+	//! Number of bones in file
+	int32_t	bones_num;
+
+	//! Number of groups in file
+	int32_t	groups_num;
+
+	//! Size of data in the file
+	int32_t	data_size;	
+
+	//! Ignored. Used to store entity specific information
+	int32_t	entlump_size;	
+
+	//! Ignored. Used to store MED related data
+	int32_t	medlump_size;	
+
+	// -------------------------------------------------------
+	// Sizes of some file parts
+
+	uint16_t bone_stc_size;
+	uint16_t skin_stc_size;
+	uint16_t colorvalue_stc_size;
+	uint16_t material_stc_size;
+	uint16_t skinpoint_stc_size;
+	uint16_t triangle_stc_size;
+	uint16_t mainvertex_stc_size;
+	uint16_t framevertex_stc_size;
+	uint16_t bonetrans_stc_size;
+	uint16_t frame_stc_size;
+} PACK_STRUCT;
+
+#define AI_MDL7_MAX_BONENAMESIZE	20 
+
+// ---------------------------------------------------------------------------
+/** \struct Bone_MDL7
+ *  \brief Bone in a MDL7 file
+ */
+// ---------------------------------------------------------------------------
+struct Bone_MDL7
+{
+	uint16_t parent_index;
+	uint8_t _unused_[2]; // 
+	float x,y,z;
+
+	char name[AI_MDL7_MAX_BONENAMESIZE];
+};
+
+#define AI_MDL7_MAX_GROUPNAMESIZE	16
+
+// ---------------------------------------------------------------------------
+/** \struct Group_MDL7
+ *  \brief Group in a MDL7 file
+ */
+// ---------------------------------------------------------------------------
+struct Group_MDL7
+{
+	//! = '1' -> triangle based Mesh
+	unsigned char	typ;		
+
+	int8_t	deformers;
+	int8_t	max_weights;
+	int8_t	_unused_;
+
+	//! size of data for this group in bytes ( MD7_GROUP stc. included).
+	int32_t	groupdata_size; 
+	char	name[AI_MDL7_MAX_GROUPNAMESIZE];
+
+	//! Number of skins
+	int32_t	numskins;
+
+	//! Number of texture coordinates
+	int32_t	num_stpts;	
+
+	//! Number of triangles
+	int32_t	numtris;
+
+	//! Number of vertices
+	int32_t	numverts;
+
+	//! Number of frames
+	int32_t	numframes;
+} PACK_STRUCT;
+
+#define	AI_MDL7_SKINTYPE_MIPFLAG				0x08
+#define	AI_MDL7_SKINTYPE_MATERIAL				0x10
+#define	AI_MDL7_SKINTYPE_MATERIAL_ASCDEF		0x20
+#define	AI_MDL7_SKINTYPE_RGBFLAG				0x80
+
+
+#define AI_MDL7_MAX_BONENAMESIZE 20
+
+// ---------------------------------------------------------------------------
+/** \struct Deformer_MDL7
+ *  \brief Deformer in a MDL7 file
+ */
+// ---------------------------------------------------------------------------
+struct Deformer_MDL7
+{
+	int8_t	deformer_version;		// 0
+	int8_t	deformer_typ;			// 0 - bones
+	int8_t	_unused_[2];
+	int32_t	group_index;
+	int32_t	elements;
+	int32_t	deformerdata_size;
+} PACK_STRUCT;
+
+struct DeformerElement_MDL7
+{
+	//! bei deformer_typ==0 (==bones) element_index == bone index
+	int32_t	element_index;		
+	char	element_name[AI_MDL7_MAX_BONENAMESIZE];
+	int32_t	weights;
+} PACK_STRUCT;
+
+struct DeformerWeight_MDL7
+{
+	//! for deformer_typ==0 (==bones) index == vertex index
+	int32_t	index;				
+	float	weight;
+} PACK_STRUCT;
+
+#define AI_MDL7_MAX_TEXNAMESIZE		0x10
+
+typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
+
+// ---------------------------------------------------------------------------
+/** \struct Skin_MDL7
+ *  \brief Skin in a MDL7 file
+ */
+// ---------------------------------------------------------------------------
+struct Skin_MDL7
+{
+	uint8_t			typ;
+	int8_t			_unused_[3];
+	int32_t			width;
+	int32_t			height;
+	char			texture_name[AI_MDL7_MAX_TEXNAMESIZE];	
+} PACK_STRUCT;
+
+struct ColorValue_MDL7
+{
+	float r,g,b,a;
+} PACK_STRUCT;
+
+// ---------------------------------------------------------------------------
+/** \struct Material_MDL7
+ *  \brief Material in a MDL7 file
+ */
+// ---------------------------------------------------------------------------
+struct Material_MDL7
+{
+	//! Diffuse base color of the material
+	ColorValue_MDL7	Diffuse;        
+
+	//! Ambient base color of the material
+    ColorValue_MDL7	Ambient;  
+
+	//! Specular base color of the material
+    ColorValue_MDL7	Specular;  
+
+	//! Emissive base color of the material
+    ColorValue_MDL7	Emissive; 
+
+	//! Phong power
+    float			Power;         
+} PACK_STRUCT;
+
+
+// ---------------------------------------------------------------------------
+/** \struct Skin
+ *  \brief Skin data structure #1
+ */
+// ---------------------------------------------------------------------------
+struct Skin
+{
+	//! 0 = single (Skin), 1 = group (GroupSkin)
+	//! For MDL3-5: Defines the type of the skin and there
+	//! fore the size of the data to skip:
+	//-------------------------------------------------------
+	//! 2 for 565 RGB,
+	//! 3 for 4444 ARGB, 
+	//! 10 for 565 mipmapped, 
+	//! 11 for 4444 mipmapped (bpp = 2),
+	//! 12 for 888 RGB mipmapped (bpp = 3), 
+	//! 13 for 8888 ARGB mipmapped (bpp = 4)
+	//-------------------------------------------------------
+	int32_t group;      
+
+	//! Texture data
+	uint8_t *data;  
+} PACK_STRUCT;
+
+struct Skin_MDL5
+{
+	int32_t size, width, height;      
+	uint8_t *data;  
+} PACK_STRUCT;
+
+struct RGB565
+{
+	uint16_t r : 5;
+	uint16_t g : 6;
+	uint16_t b : 5;
+} PACK_STRUCT;
+
+struct ARGB4
+{
+	uint16_t a : 4;
+	uint16_t r : 4;
+	uint16_t g : 4;
+	uint16_t b : 4;
+} PACK_STRUCT;
+
+// ---------------------------------------------------------------------------
+/** \struct GroupSkin
+ *  \brief Skin data structure #2 (group of pictures)
+ */
+// ---------------------------------------------------------------------------
+struct GroupSkin
+{
+	//! 0 = single (Skin), 1 = group (GroupSkin)
+    int32_t group;     
+
+	//! Number of images
+	int32_t nb;       
+
+	//! Time for each image
+    float *time;   
+
+	//! Data of each image
+	uint8_t **data;  
+} PACK_STRUCT;
+
+// ---------------------------------------------------------------------------
+/** \struct TexCoord
+ *  \brief Texture coordinate data structure
+ */
+// ---------------------------------------------------------------------------
+struct TexCoord
+{
+	//! Is the vertex on the noundary between front and back piece?
+	int32_t onseam;
+
+	//! Texture coordinate in the tx direction
+	int32_t s;
+
+	//! Texture coordinate in the ty direction
+	int32_t t;
+} PACK_STRUCT;
+
+
+struct TexCoord_MDL3
+{
+	//! position, horizontally in range 0..skinwidth-1
+	int16_t u; 
+
+	//! position, vertically in range 0..skinheight-1
+	int16_t v; 
+} PACK_STRUCT;
+
+struct TexCoord_MDL7
+{
+	//! position, horizontally in range 0..1
+	float u; 
+
+	//! position, vertically in range 0..1
+	float v; 
+} PACK_STRUCT;
+
+
+// ---------------------------------------------------------------------------
+/** \struct Triangle
+ *  \brief Triangle data structure
+ */
+// ---------------------------------------------------------------------------
+struct Triangle
+{
+	//! 0 = backface, 1 = frontface
+	int32_t facesfront;  
+
+	//! Vertex indices
+	int32_t vertex[3];   
+} PACK_STRUCT;
+
+
+struct Triangle_MDL3
+{
+	//!  Index of 3 3D vertices in range 0..numverts
+	uint16_t index_xyz[3];
+
+	//! Index of 3 skin vertices in range 0..numskinverts
+	uint16_t index_uv[3]; 
+} PACK_STRUCT;
+
+
+struct SkinSet_MDL7
+{
+	//! Index into the UV coordinate list
+	uint16_t	st_index[3]; // size 6	
+
+	//! Material index
+	int32_t		material;	 // size 4				
+} PACK_STRUCT;
+
+
+struct Triangle_MDL7
+{
+	//! Vertex indices
+	uint16_t   v_index[3]; 	// size 6
+
+	//! Two skinsets. The second will be used for multi-texturing
+	SkinSet_MDL7  skinsets[2];
+} PACK_STRUCT; 
+
+
+// Helper constants for Triangle::facesfront
+#if (!defined AI_MDL_BACKFACE)
+#	define AI_MDL_BACKFACE			0x0
+#endif
+#if (!defined  AI_MDL_FRONTFACE)
+#	define AI_MDL_FRONTFACE			0x1
+#endif
+
+// ---------------------------------------------------------------------------
+/** \struct Vertex
+ *  \brief Vertex data structure
+ */
+// ---------------------------------------------------------------------------
+struct Vertex
+{
+	uint8_t v[3];
+	uint8_t normalIndex;
+} PACK_STRUCT;
+
+
+struct Vertex_MDL4
+{
+	uint16_t v[3];
+	uint8_t normalIndex;
+	uint8_t unused;
+} PACK_STRUCT;
+
+#define AI_MDL7_FRAMEVERTEX120503_STCSIZE		16
+#define AI_MDL7_FRAMEVERTEX030305_STCSIZE		26
+
+// ---------------------------------------------------------------------------
+/** \struct Vertex_MDL7
+ *  \brief Vertex data structure used in MDL7 files
+ */
+// ---------------------------------------------------------------------------
+struct Vertex_MDL7
+{
+	float	x,y,z;
+	uint16_t vertindex;	
+	union {
+		uint16_t norm162index;
+		float norm[3];
+	};
+} PACK_STRUCT;
+
+
+// ---------------------------------------------------------------------------
+/** \struct BoneTransform_MDL7
+ *  \brief bone transformation matrix structure used in MDL7 files
+ */
+// ---------------------------------------------------------------------------
+struct BoneTransform_MDL7
+{
+	//! 4*3
+	float	m [4*4];				
+
+	//! the index of this vertex, 0.. header::bones_num - 1
+	uint16_t bone_index;		
+
+	//! I HATE 3DGS AND THE SILLY DEVELOPER WHO DESIGNED
+	//! THIS STUPID FILE FORMAT!
+	int8_t _unused_[2];
+} PACK_STRUCT;
+
+
+#define AI_MDL7_MAX_FRAMENAMESIZE		16
+
+
+// ---------------------------------------------------------------------------
+/** \struct Frame_MDL7
+ *  \brief Frame data structure used by MDL7 files
+ */
+// ---------------------------------------------------------------------------
+struct Frame_MDL7
+{
+	char	frame_name[AI_MDL7_MAX_FRAMENAMESIZE];
+	uint32_t	vertices_count;			
+	uint32_t	transmatrix_count;		
+};
+
+
+// ---------------------------------------------------------------------------
+/** \struct SimpleFrame
+ *  \brief Data structure for a simple frame
+ */
+// ---------------------------------------------------------------------------
+struct SimpleFrame
+{
+	//! Minimum vertex of the bounding box
+	Vertex bboxmin; 
+
+	//! Maximum vertex of the bounding box
+	Vertex bboxmax; 
+
+	//! Name of the frame
+	char name[16];
+
+	//! Vertex list of the frame
+	Vertex *verts; 
+} PACK_STRUCT;
+
+// ---------------------------------------------------------------------------
+/** \struct Frame
+ *  \brief Model frame data structure
+ */
+// ---------------------------------------------------------------------------
+struct Frame
+{
+	//! 0 = simple frame, !0 = group frame
+	int32_t type;       
+
+	//! Frame data
+	SimpleFrame frame;  	      
+} PACK_STRUCT;
+
+
+struct SimpleFrame_MDLn_SP
+{
+	//! Minimum vertex of the bounding box
+	Vertex_MDL4 bboxmin; 
+
+	//! Maximum vertex of the bounding box
+	Vertex_MDL4 bboxmax; 
+
+	//! Name of the frame
+	char name[16];
+
+	//! Vertex list of the frame
+	Vertex_MDL4 *verts; 
+} PACK_STRUCT;
+
+// ---------------------------------------------------------------------------
+/** \struct GroupFrame
+ *  \brief Data structure for a group of frames
+ */
+// ---------------------------------------------------------------------------
+struct GroupFrame
+{
+	//! 0 = simple frame, !0 = group frame
+	int32_t type;                         
+
+	//! Minimum vertex for all single frames
+	Vertex min;         
+
+	//! Maximum vertex for all single frames
+	Vertex max;         
+
+	//! Time for all single frames
+	float *time;                  
+
+	//! List of single frames
+	SimpleFrame *frames; 
+} PACK_STRUCT;
+
+// reset packing to the original value
+#if defined(_MSC_VER) ||  defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
+#	pragma pack( pop )
+#endif
+#undef PACK_STRUCT
+
+
+// ---------------------------------------------------------------------------
+/** \struct IntFace_MDL7
+ *  \brief Internal data structure to temporarily represent a face
+ */
+// ---------------------------------------------------------------------------
+struct IntFace_MDL7
+{
+	// provide a constructor for our own convenience
+	IntFace_MDL7()
+	{
+		// set everything to zero
+		mIndices[0] = mIndices[1] = mIndices[2] = 0;
+		iMatIndex[0] = iMatIndex[1] = 0;
+	}
+
+	//! Vertex indices
+	uint32_t mIndices[3];
+
+	//! Material index (maximally two channels, which are joined later)
+	unsigned int iMatIndex[2];
+}; 
+
+
+// ---------------------------------------------------------------------------
+/** \struct IntMaterial_MDL7
+ *  \brief Internal data structure to temporarily represent a material
+ *  which has been created from two single materials along with the
+ *  original material indices.
+ */
+// ---------------------------------------------------------------------------
+struct IntMaterial_MDL7
+{
+	// provide a constructor for our own convenience
+	IntMaterial_MDL7()
+	{
+		pcMat = NULL;
+		iOldMatIndices[0] = iOldMatIndices[1] = 0;
+	}
+
+	//! Material instance
+	MaterialHelper* pcMat;
+
+	//! Old material indices
+	unsigned int iOldMatIndices[2];
+};
+
+};}; // end namespaces
+
+#endif // !! AI_MDLFILEHELPER_H_INC

+ 1715 - 0
code/MDLLoader.cpp

@@ -0,0 +1,1715 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the MDL importer class */
+
+#include "MaterialSystem.h"
+#include "MDLLoader.h"
+#include "MDLDefaultColorMap.h"
+
+#include "../include/IOStream.h"
+#include "../include/IOSystem.h"
+#include "../include/aiMesh.h"
+#include "../include/aiScene.h"
+#include "../include/aiAssert.h"
+
+#include <boost/scoped_ptr.hpp>
+
+using namespace Assimp;
+
+extern float g_avNormals[162][3];
+
+
+// ------------------------------------------------------------------------------------------------
+inline bool is_qnan(float p_fIn)
+{
+	// NOTE: Comparison against qnan is generally problematic
+	// because qnan == qnan is false AFAIK
+	union FTOINT
+	{
+		float fFloat;
+		int32_t iInt;
+	} one, two;
+	one.fFloat = std::numeric_limits<float>::quiet_NaN();
+	two.fFloat = p_fIn;
+
+	return (one.iInt == two.iInt);
+}
+// ------------------------------------------------------------------------------------------------
+inline bool is_not_qnan(float p_fIn)
+{
+	return !is_qnan(p_fIn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+MDLImporter::MDLImporter()
+{
+	// nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well 
+MDLImporter::~MDLImporter()
+{
+	// nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the class can handle the format of the given file. 
+bool MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
+{
+	// simple check of file extension is enough for the moment
+	std::string::size_type pos = pFile.find_last_of('.');
+	// no file extension - can't read
+	if( pos == std::string::npos)
+		return false;
+	std::string extension = pFile.substr( pos);
+
+	if (extension.length() < 4)return false;
+	if (extension[0] != '.')return false;
+	if (extension[1] != 'm' && extension[1] != 'M')return false;
+	if (extension[2] != 'd' && extension[2] != 'D')return false;
+	if (extension[3] != 'l' && extension[3] != 'L')return false;
+
+	return true;
+}
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure. 
+void MDLImporter::InternReadFile( 
+	const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
+{
+	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+	// Check whether we can read from the file
+	if( file.get() == NULL)
+	{
+		throw new ImportErrorException( "Failed to open MDL file " + pFile + ".");
+	}
+
+	// check whether the ply file is large enough to contain
+	// at least the file header
+	size_t fileSize = file->FileSize();
+	if( fileSize < sizeof(MDL::Header))
+	{
+		throw new ImportErrorException( ".mdl File is too small.");
+	}
+
+	// allocate storage and copy the contents of the file to a memory buffer
+	this->pScene = pScene;
+	this->pIOHandler = pIOHandler;
+	this->mBuffer = new unsigned char[fileSize+1];
+	file->Read( (void*)mBuffer, 1, fileSize);
+
+	// determine the file subtype and call the appropriate member function
+
+	// Original Quake1 format
+	this->m_pcHeader = (const MDL::Header*)this->mBuffer;
+	if (AI_MDL_MAGIC_NUMBER_BE == this->m_pcHeader->ident ||
+		AI_MDL_MAGIC_NUMBER_LE == this->m_pcHeader->ident)
+	{
+		this->InternReadFile_Quake1();
+	}
+	// GameStudio A4 MDL3 format
+	else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == this->m_pcHeader->ident ||
+			 AI_MDL_MAGIC_NUMBER_LE_GS4 == this->m_pcHeader->ident)
+	{
+		this->iGSFileVersion = 3;
+		this->InternReadFile_GameStudio();
+	}
+	// GameStudio A5+ MDL4 format
+	else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == this->m_pcHeader->ident ||
+			 AI_MDL_MAGIC_NUMBER_LE_GS5a == this->m_pcHeader->ident)
+	{
+		this->iGSFileVersion = 4;
+		this->InternReadFile_GameStudio();
+	}
+	// GameStudio A5+ MDL5 format
+	else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == this->m_pcHeader->ident ||
+			 AI_MDL_MAGIC_NUMBER_LE_GS5b == this->m_pcHeader->ident)
+	{
+		this->iGSFileVersion = 5;
+		this->InternReadFile_GameStudio();
+	}
+	// GameStudio A6+ MDL6 format
+	else if (AI_MDL_MAGIC_NUMBER_BE_GS6 == this->m_pcHeader->ident ||
+			 AI_MDL_MAGIC_NUMBER_LE_GS6 == this->m_pcHeader->ident)
+	{
+		this->iGSFileVersion = 6;
+		this->InternReadFile_GameStudio();
+	}
+	// GameStudio A7 MDL7 format
+	else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == this->m_pcHeader->ident ||
+			 AI_MDL_MAGIC_NUMBER_LE_GS7 == this->m_pcHeader->ident)
+	{
+		this->iGSFileVersion = 7;
+		this->InternReadFile_GameStudioA7();
+	}
+	else
+	{
+		// we're definitely unable to load this file
+		throw new ImportErrorException( "Unknown MDL subformat " + pFile +
+			". Magic word is not known");
+	}
+
+	// delete the file buffer
+	delete[] this->mBuffer;
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::SearchPalette(const unsigned char** pszColorMap)
+{
+	// now try to find the color map in the current directory
+	IOStream* pcStream = this->pIOHandler->Open("colormap.lmp","rb");
+
+	const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap;
+	if(pcStream)
+	{
+		if (pcStream->FileSize() >= 768)
+		{
+			szColorMap = new unsigned char[256*3];
+			pcStream->Read(const_cast<unsigned char*>(szColorMap),256*3,1);
+		}
+		delete pcStream;
+		pcStream = NULL;
+	}
+	*pszColorMap = szColorMap;
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::FreePalette(const unsigned char* szColorMap)
+{
+	if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap)
+	{
+		delete[] szColorMap;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::CreateTextureARGB8(const unsigned char* szData)
+{
+	// allocate a new texture object
+	aiTexture* pcNew = new aiTexture();
+	pcNew->mWidth = this->m_pcHeader->skinwidth;
+	pcNew->mHeight = this->m_pcHeader->skinheight;
+
+	pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
+
+	const unsigned char* szColorMap;
+	this->SearchPalette(&szColorMap);
+
+	// copy texture data
+	for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+	{
+		const unsigned char val = szData[i];
+		const unsigned char* sz = &szColorMap[val*3];
+
+		pcNew->pcData[i].a = 0xFF;
+		pcNew->pcData[i].r = *sz++;
+		pcNew->pcData[i].g = *sz++;
+		pcNew->pcData[i].b = *sz;
+	}
+
+	this->FreePalette(szColorMap);
+
+	// store the texture
+	aiTexture** pc = this->pScene->mTextures;
+	this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
+	for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
+		this->pScene->mTextures[i] = pc[i];
+
+	this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
+	this->pScene->mNumTextures++;
+	delete[] pc;
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::CreateTextureARGB8_GS4(const unsigned char* szData, 
+	unsigned int iType,
+	unsigned int* piSkip)
+{
+	ai_assert(NULL != piSkip);
+
+	// allocate a new texture object
+	aiTexture* pcNew = new aiTexture();
+	pcNew->mWidth = this->m_pcHeader->skinwidth;
+	pcNew->mHeight = this->m_pcHeader->skinheight;
+
+	pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
+
+	// 8 Bit paletized. Use Q1 default palette.
+	if (0 == iType)
+	{
+		const unsigned char* szColorMap;
+		this->SearchPalette(&szColorMap);
+
+		// copy texture data
+		unsigned int i = 0;
+		for (; i < pcNew->mWidth*pcNew->mHeight;++i)
+		{
+			const unsigned char val = szData[i];
+			const unsigned char* sz = &szColorMap[val*3];
+
+			pcNew->pcData[i].a = 0xFF;
+			pcNew->pcData[i].r = *sz++;
+			pcNew->pcData[i].g = *sz++;
+			pcNew->pcData[i].b = *sz;
+		}
+		*piSkip = i;
+
+		this->FreePalette(szColorMap);
+	}
+	// R5G6B5 format
+	else if (2 == iType)
+	{
+		// copy texture data
+		unsigned int i = 0;
+		for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+		{
+			MDL::RGB565 val = ((MDL::RGB565*)szData)[i];
+
+			pcNew->pcData[i].a = 0xFF;
+			pcNew->pcData[i].r = (unsigned char)val.b << 3;
+			pcNew->pcData[i].g = (unsigned char)val.g << 2;
+			pcNew->pcData[i].b = (unsigned char)val.r << 3;
+		}
+		*piSkip = i * 2;
+	}
+	// ARGB4 format
+	else if (3 == iType)
+	{
+		// copy texture data
+		unsigned int i = 0;
+		for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+		{
+			MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i];
+
+			pcNew->pcData[i].a = (unsigned char)val.a << 4;
+			pcNew->pcData[i].r = (unsigned char)val.r << 4;
+			pcNew->pcData[i].g = (unsigned char)val.g << 4;
+			pcNew->pcData[i].b = (unsigned char)val.b << 4;
+		}
+		*piSkip = i * 2;
+	}
+	// store the texture
+	aiTexture** pc = this->pScene->mTextures;
+	this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
+	for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
+		this->pScene->mTextures[i] = pc[i];
+
+	this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
+	this->pScene->mNumTextures++;
+	delete[] pc;
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::ParseTextureColorData(const unsigned char* szData, 
+	unsigned int iType,
+	unsigned int* piSkip,
+	aiTexture* pcNew)
+{
+	// allocate storage for the texture image
+	pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
+
+	// R5G6B5 format (with or without MIPs)
+	if (2 == iType || 10 == iType)
+	{
+		// copy texture data
+		unsigned int i = 0;
+		for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+		{
+			MDL::RGB565 val = ((MDL::RGB565*)szData)[i];
+
+			pcNew->pcData[i].a = 0xFF;
+			pcNew->pcData[i].r = (unsigned char)val.b << 3;
+			pcNew->pcData[i].g = (unsigned char)val.g << 2;
+			pcNew->pcData[i].b = (unsigned char)val.r << 3;
+		}
+		*piSkip = i * 2;
+
+		// apply MIP maps
+		if (10 == iType)
+		{
+			*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
+		}
+	}
+	// ARGB4 format (with or without MIPs)
+	else if (3 == iType || 11 == iType)
+	{
+		// copy texture data
+		unsigned int i = 0;
+		for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+		{
+			MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i];
+
+			pcNew->pcData[i].a = (unsigned char)val.a << 4;
+			pcNew->pcData[i].r = (unsigned char)val.r << 4;
+			pcNew->pcData[i].g = (unsigned char)val.g << 4;
+			pcNew->pcData[i].b = (unsigned char)val.b << 4;
+		}
+		*piSkip = i * 2;
+
+		// apply MIP maps
+		if (11 == iType)
+		{
+			*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
+		}
+	}
+	// RGB8 format (with or without MIPs)
+	else if (4 == iType || 12 == iType)
+	{
+		// copy texture data
+		unsigned int i = 0;
+		for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+		{
+			const unsigned char* _szData = &szData[i*3];
+
+			pcNew->pcData[i].a = 0xFF;
+			pcNew->pcData[i].b = *_szData++;
+			pcNew->pcData[i].g = *_szData++;
+			pcNew->pcData[i].r = *_szData;
+		}
+		// apply MIP maps
+		*piSkip = i * 3;
+		if (12 == iType)
+		{
+			*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3;
+		}
+	}
+	// ARGB8 format (with ir without MIPs)
+	else if (5 == iType || 13 == iType)
+	{
+		// copy texture data
+		unsigned int i = 0;
+		for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+		{
+			const unsigned char* _szData = &szData[i*4];
+
+			pcNew->pcData[i].b = *_szData++;
+			pcNew->pcData[i].g = *_szData++;
+			pcNew->pcData[i].r = *_szData++;
+			pcNew->pcData[i].a = *_szData;
+		}
+		// apply MIP maps
+		*piSkip = i << 2;
+		if (13 == iType)
+		{
+			*piSkip += (i + (i >> 2) + (i >> 4) + (i >> 6)) << 2;
+		}
+	}
+	// palletized 8 bit texture. As for Quake 1
+	else if (0 == iType)
+	{
+		const unsigned char* szColorMap;
+		this->SearchPalette(&szColorMap);
+
+		// copy texture data
+		unsigned int i = 0;
+		for (; i < pcNew->mWidth*pcNew->mHeight;++i)
+		{
+			const unsigned char val = szData[i];
+			const unsigned char* sz = &szColorMap[val*3];
+
+			pcNew->pcData[i].a = 0xFF;
+			pcNew->pcData[i].r = *sz++;
+			pcNew->pcData[i].g = *sz++;
+			pcNew->pcData[i].b = *sz;
+		}
+		*piSkip = i;
+
+		this->FreePalette(szColorMap);
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::CreateTextureARGB8_GS5(const unsigned char* szData, 
+	unsigned int iType,
+	unsigned int* piSkip)
+{
+	ai_assert(NULL != piSkip);
+
+	// allocate a new texture object
+	aiTexture* pcNew = new aiTexture();
+
+	// first read the size of the texture
+	pcNew->mWidth = *((uint32_t*)szData);
+	szData += sizeof(uint32_t);
+
+	pcNew->mHeight = *((uint32_t*)szData);
+	szData += sizeof(uint32_t);
+
+	if (6 == iType)
+	{
+		// this is a compressed texture in DDS format
+		*piSkip = pcNew->mWidth;
+
+		pcNew->mHeight = 0;
+		pcNew->achFormatHint[0] = 'd';
+		pcNew->achFormatHint[1] = 'd';
+		pcNew->achFormatHint[2] = 's';
+		pcNew->achFormatHint[3] = '\0';
+
+		pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
+		memcpy(pcNew->pcData,szData,pcNew->mWidth);
+	}
+	else
+	{
+		// parse the color data of the texture
+		this->ParseTextureColorData(szData,iType,
+			piSkip,pcNew);
+	}
+	*piSkip += sizeof(uint32_t) * 2;
+
+	// store the texture
+	aiTexture** pc = this->pScene->mTextures;
+	this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
+	for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
+		this->pScene->mTextures[i] = pc[i];
+
+	this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
+	this->pScene->mNumTextures++;
+	delete[] pc;
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::InternReadFile_Quake1( )
+{
+	ai_assert(NULL != pScene);
+
+	if(0 == this->m_pcHeader->num_frames)
+	{
+		throw new ImportErrorException( "[Quake 1 MDL] No frames found");
+	}
+
+	// allocate enough storage to hold all vertices and triangles
+	aiMesh* pcMesh = new aiMesh();
+
+	// current cursor position in the file
+	const unsigned char* szCurrent = (const unsigned char*)(this->m_pcHeader+1);
+
+	// need to read all textures
+	for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->num_skins;++i)
+	{
+		union{const MDL::Skin* pcSkin;const MDL::GroupSkin* pcGroupSkin;};
+		pcSkin = (const MDL::Skin*)szCurrent;
+		if (0 == pcSkin->group)
+		{
+			// create one output image
+			this->CreateTextureARGB8((unsigned char*)pcSkin + sizeof(uint32_t));
+
+			// need to skip one image
+			szCurrent += this->m_pcHeader->skinheight * this->m_pcHeader->skinwidth+ sizeof(uint32_t);
+		}
+		else
+		{
+			// need to skip multiple images
+			const unsigned int iNumImages = (unsigned int)pcGroupSkin->nb;
+			szCurrent += sizeof(uint32_t) * 2;
+
+			if (0 != iNumImages)
+			{
+				// however, create only one output image (the first)
+				this->CreateTextureARGB8(szCurrent + iNumImages * sizeof(float));
+
+				for (unsigned int a = 0; a < iNumImages;++a)
+				{
+					szCurrent += this->m_pcHeader->skinheight * this->m_pcHeader->skinwidth +
+						sizeof(float);
+				}
+			}
+		}
+	}
+	// get a pointer to the texture coordinates
+	const MDL::TexCoord* pcTexCoords = (const MDL::TexCoord*)szCurrent;
+	szCurrent += sizeof(MDL::TexCoord) * this->m_pcHeader->num_verts;
+
+	// get a pointer to the triangles
+	const MDL::Triangle* pcTriangles = (const MDL::Triangle*)szCurrent;
+	szCurrent += sizeof(MDL::Triangle) * this->m_pcHeader->num_tris;
+
+	// now get a pointer to the first frame in the file
+	const MDL::Frame* pcFrames = (const MDL::Frame*)szCurrent;
+	const MDL::SimpleFrame* pcFirstFrame;
+
+	if (0 == pcFrames->type)
+	{
+		// get address of single frame
+		pcFirstFrame = &pcFrames->frame;
+	}
+	else
+	{
+		// get the first frame in the group
+		const MDL::GroupFrame* pcFrames2 = (const MDL::GroupFrame*)pcFrames;
+		pcFirstFrame = (const MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type);
+	}
+	const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) +
+		sizeof(pcFirstFrame->name));
+
+	pcMesh->mNumVertices = this->m_pcHeader->num_tris * 3;
+	pcMesh->mNumFaces = this->m_pcHeader->num_tris;
+	pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+	pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+	pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+	pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+	pcMesh->mNumUVComponents[0] = 2;
+
+	// there won't be more than one mesh inside the file
+	pScene->mNumMaterials = 1;
+	pScene->mRootNode = new aiNode();
+	pScene->mRootNode->mNumMeshes = 1;
+	pScene->mRootNode->mMeshes = new unsigned int[1];
+	pScene->mRootNode->mMeshes[0] = 0;
+	pScene->mMaterials = new aiMaterial*[1];
+	pScene->mMaterials[0] = new MaterialHelper();
+	pScene->mNumMeshes = 1;
+	pScene->mMeshes = new aiMesh*[1];
+	pScene->mMeshes[0] = pcMesh;
+
+	// setup the material properties
+	const int iMode = (int)aiShadingMode_Gouraud;
+	MaterialHelper* pcHelper = (MaterialHelper*)pScene->mMaterials[0];
+	pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+	aiColor3D clr;
+	clr.b = clr.g = clr.r = 1.0f;
+	pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+	pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+	clr.b = clr.g = clr.r = 0.05f;
+	pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+
+	if (0 != this->m_pcHeader->num_skins)
+	{
+		aiString szString;
+		memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3);
+		szString.length = 2;
+		pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
+	}
+
+	// now iterate through all triangles
+	unsigned int iCurrent = 0;
+	for (unsigned int i = 0; i < (unsigned int) this->m_pcHeader->num_tris;++i)
+	{
+		pcMesh->mFaces[i].mIndices = new unsigned int[3];
+		pcMesh->mFaces[i].mNumIndices = 3;
+
+		for (unsigned int c = 0; c < 3;++c,++iCurrent)
+		{
+			pcMesh->mFaces[i].mIndices[c] = iCurrent;
+
+			// read vertices
+			unsigned int iIndex = pcTriangles->vertex[c];
+			if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
+			{
+				iIndex = this->m_pcHeader->num_verts-1;
+				// LOG
+			}
+
+			aiVector3D& vec = pcMesh->mVertices[iCurrent];
+			vec.x = (float)pcVertices[iIndex].v[0] * this->m_pcHeader->scale[0];
+			vec.x += this->m_pcHeader->translate[0];
+
+			// (flip z and y component)
+			vec.z = (float)pcVertices[iIndex].v[1] * this->m_pcHeader->scale[1];
+			vec.z += this->m_pcHeader->translate[1];
+
+			vec.y = (float)pcVertices[iIndex].v[2] * this->m_pcHeader->scale[2];
+			vec.y += this->m_pcHeader->translate[2];
+
+			// flip the Z-axis
+			//pcMesh->mVertices[iBase+c].z *= -1.0f;
+
+			// read the normal vector from the precalculated normal table
+			pcMesh->mNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min(
+				int(pcVertices[iIndex].normalIndex),
+				int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
+
+			//pcMesh->mNormals[iBase+c].z *= -1.0f;
+			std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z );
+
+			// read texture coordinates
+			float s = (float)pcTexCoords[iIndex].s;
+			float t = (float)pcTexCoords[iIndex].t;
+
+			// translate texture coordinates
+			if (0 == pcTriangles->facesfront &&
+				0 != pcTexCoords[iIndex].onseam)
+			{
+				s += this->m_pcHeader->skinwidth * 0.5f; 
+			}
+
+			// Scale s and t to range from 0.0 to 1.0 
+			pcMesh->mTextureCoords[0][iCurrent].x = (s + 0.5f) / this->m_pcHeader->skinwidth;
+			pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-(t + 0.5f) / this->m_pcHeader->skinheight;
+
+		}
+		pcTriangles++;
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::InternReadFile_GameStudio( )
+{
+	ai_assert(NULL != pScene);
+
+	if(0 == this->m_pcHeader->num_frames)
+	{
+		throw new ImportErrorException( "[3DGS MDL] No frames found");
+	}
+
+	// allocate enough storage to hold all vertices and triangles
+	aiMesh* pcMesh = new aiMesh();
+
+	// current cursor position in the file
+	const unsigned char* szCurrent = (const unsigned char*)(this->m_pcHeader+1);
+
+	// need to read all textures
+	for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->num_skins;++i)
+	{
+		union{const MDL::Skin* pcSkin;const MDL::GroupSkin* pcGroupSkin;};
+		pcSkin = (const MDL::Skin*)szCurrent;
+		
+		// create one output image
+		unsigned int iSkip = 0;
+		if (5 <= this->iGSFileVersion)
+		{
+			// MDL5 format could contain MIPmaps
+			this->CreateTextureARGB8_GS5((unsigned char*)pcSkin + sizeof(uint32_t),
+				pcSkin->group,&iSkip);
+		}
+		else
+		{
+			this->CreateTextureARGB8_GS4((unsigned char*)pcSkin + sizeof(uint32_t),
+				pcSkin->group,&iSkip);
+		}
+		// need to skip one image
+		szCurrent += iSkip + sizeof(uint32_t);
+		
+	}
+	// get a pointer to the texture coordinates
+	const MDL::TexCoord_MDL3* pcTexCoords = (const MDL::TexCoord_MDL3*)szCurrent;
+	szCurrent += sizeof(MDL::TexCoord_MDL3) * this->m_pcHeader->synctype;
+
+	// NOTE: for MDLn formats syntype corresponds to the number of UV coords
+
+	// get a pointer to the triangles
+	const MDL::Triangle_MDL3* pcTriangles = (const MDL::Triangle_MDL3*)szCurrent;
+	szCurrent += sizeof(MDL::Triangle_MDL3) * this->m_pcHeader->num_tris;
+
+	pcMesh->mNumVertices = this->m_pcHeader->num_tris * 3;
+	pcMesh->mNumFaces = this->m_pcHeader->num_tris;
+	pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+	pcMesh->mNumUVComponents[0] = 2;
+
+	// there won't be more than one mesh inside the file
+	pScene->mNumMaterials = 1;
+	pScene->mRootNode = new aiNode();
+	pScene->mRootNode->mNumMeshes = 1;
+	pScene->mRootNode->mMeshes = new unsigned int[1];
+	pScene->mRootNode->mMeshes[0] = 0;
+	pScene->mMaterials = new aiMaterial*[1];
+	pScene->mMaterials[0] = new MaterialHelper();
+	pScene->mNumMeshes = 1;
+	pScene->mMeshes = new aiMesh*[1];
+	pScene->mMeshes[0] = pcMesh;
+
+	std::vector<aiVector3D> vPositions;
+	std::vector<aiVector3D> vTexCoords;
+	std::vector<aiVector3D> vNormals;
+
+	vPositions.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
+	vTexCoords.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
+	vNormals.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
+
+	// setup the material properties
+	const int iMode = (int)aiShadingMode_Gouraud;
+	MaterialHelper* pcHelper = (MaterialHelper*)pScene->mMaterials[0];
+	pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+	aiColor3D clr;
+	clr.b = clr.g = clr.r = 1.0f;
+	pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+	pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+	clr.b = clr.g = clr.r = 0.05f;
+	pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+
+	if (0 != this->m_pcHeader->num_skins)
+	{
+		aiString szString;
+		memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3);
+		szString.length = 2;
+		pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
+	}
+
+	// now get a pointer to the first frame in the file
+	const MDL::Frame* pcFrames = (const MDL::Frame*)szCurrent;
+
+	// byte packed vertices
+	if (0 == pcFrames->type || 3 == this->iGSFileVersion)
+	{
+		const MDL::SimpleFrame* pcFirstFrame = (const MDL::SimpleFrame*)
+			(szCurrent + sizeof(uint32_t));
+
+		// get a pointer to the vertices
+		const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) +
+			sizeof(pcFirstFrame->name));
+
+		// now iterate through all triangles
+		unsigned int iCurrent = 0;
+		for (unsigned int i = 0; i < (unsigned int) this->m_pcHeader->num_tris;++i)
+		{
+			pcMesh->mFaces[i].mIndices = new unsigned int[3];
+			pcMesh->mFaces[i].mNumIndices = 3;
+
+			for (unsigned int c = 0; c < 3;++c,++iCurrent)
+			{
+				pcMesh->mFaces[i].mIndices[c] = iCurrent;
+
+				// read vertices
+				unsigned int iIndex = pcTriangles->index_xyz[c];
+				if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
+				{
+					iIndex = this->m_pcHeader->num_verts-1;
+					// LOG
+				}
+
+				aiVector3D& vec = vPositions[iCurrent];
+				vec.x = (float)pcVertices[iIndex].v[0] * this->m_pcHeader->scale[0];
+				vec.x += this->m_pcHeader->translate[0];
+
+				// (flip z and y component)
+				vec.z = (float)pcVertices[iIndex].v[1] * this->m_pcHeader->scale[1];
+				vec.z += this->m_pcHeader->translate[1];
+
+				vec.y = (float)pcVertices[iIndex].v[2] * this->m_pcHeader->scale[2];
+				vec.y += this->m_pcHeader->translate[2];
+
+				// read the normal vector from the precalculated normal table
+				vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min(
+					int(pcVertices[iIndex].normalIndex),
+					int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
+
+				//vNormals[iBase+c].z *= -1.0f;
+				std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z );
+
+				// read texture coordinates
+				iIndex = pcTriangles->index_uv[c];
+
+				// validate UV indices
+				if (iIndex >= (unsigned int)this->m_pcHeader->synctype)
+				{
+					iIndex = this->m_pcHeader->synctype-1;
+					// LOG
+				}
+
+				float s = (float)pcTexCoords[iIndex].u;
+				float t = (float)pcTexCoords[iIndex].v;
+
+				// Scale s and t to range from 0.0 to 1.0 
+				if (5 != this->iGSFileVersion && 
+					this->m_pcHeader->skinwidth && this->m_pcHeader->skinheight)
+				{
+					s = (s + 0.5f) / this->m_pcHeader->skinwidth;
+					t = 1.0f-(t + 0.5f) / this->m_pcHeader->skinheight;
+				}
+				
+				vTexCoords[iCurrent].x = s;
+				vTexCoords[iCurrent].y = t;
+			}
+			pcTriangles++;
+		}
+
+	}
+	// short packed vertices
+	else
+	{
+		// now get a pointer to the first frame in the file
+		const MDL::SimpleFrame_MDLn_SP* pcFirstFrame = (const MDL::SimpleFrame_MDLn_SP*)
+			(szCurrent + sizeof(uint32_t));
+
+		// get a pointer to the vertices
+		const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*) ((pcFirstFrame->name) +
+			sizeof(pcFirstFrame->name));
+
+		// now iterate through all triangles
+		unsigned int iCurrent = 0;
+		for (unsigned int i = 0; i < (unsigned int) this->m_pcHeader->num_tris;++i)
+		{
+			pcMesh->mFaces[i].mIndices = new unsigned int[3];
+			pcMesh->mFaces[i].mNumIndices = 3;
+
+			for (unsigned int c = 0; c < 3;++c,++iCurrent)
+			{
+				pcMesh->mFaces[i].mIndices[c] = iCurrent;
+
+				// read vertices
+				unsigned int iIndex = pcTriangles->index_xyz[c];
+				if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
+				{
+					iIndex = this->m_pcHeader->num_verts-1;
+					// LOG
+				}
+
+				aiVector3D& vec = vPositions[iCurrent];
+				vec.x = (float)pcVertices[iIndex].v[0] * this->m_pcHeader->scale[0];
+				vec.x += this->m_pcHeader->translate[0];
+
+				// (flip z and y component)
+				vec.z = (float)pcVertices[iIndex].v[1] * this->m_pcHeader->scale[1];
+				vec.z += this->m_pcHeader->translate[1];
+
+				vec.y = (float)pcVertices[iIndex].v[2] * this->m_pcHeader->scale[2];
+				vec.y += this->m_pcHeader->translate[2];
+
+				// read the normal vector from the precalculated normal table
+				vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min(
+					int(pcVertices[iIndex].normalIndex),
+					int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
+
+				std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z );
+
+				// read texture coordinates
+				iIndex = pcTriangles->index_uv[c];
+
+				// validate UV indices
+				if (iIndex >= (unsigned int) this->m_pcHeader->synctype)
+				{
+					iIndex = this->m_pcHeader->synctype-1;
+					// LOG
+				}
+
+				float s = (float)pcTexCoords[iIndex].u;
+				float t = (float)pcTexCoords[iIndex].v;
+
+				
+				// Scale s and t to range from 0.0 to 1.0 
+				if (5 != this->iGSFileVersion && 
+					this->m_pcHeader->skinwidth && this->m_pcHeader->skinheight)
+				{
+					s = (s + 0.5f) / this->m_pcHeader->skinwidth;
+					t = 1.0f-(t + 0.5f) / this->m_pcHeader->skinheight;
+				}
+
+				vTexCoords[iCurrent].x = s;
+				vTexCoords[iCurrent].y = t;
+			}
+			pcTriangles++;
+		}
+	}
+
+	// For MDL5 we will need to build valid texture coordinates
+	// basing upon the file loaded (only support one file as skin)
+	if (5 == this->iGSFileVersion)
+	{
+		if (0 != this->m_pcHeader->num_skins && 0 != this->pScene->mNumTextures)
+		{
+			aiTexture* pcTex = this->pScene->mTextures[0];
+
+			// if the file is loaded in DDS format: get the size of the
+			// texture from the header of the DDS file
+			// skip three DWORDs and read first height, then the width
+			unsigned int iWidth, iHeight;
+			if (0 == pcTex->mHeight)
+			{
+				uint32_t* piPtr = (uint32_t*)pcTex->pcData;
+				
+				piPtr += 3;
+				iHeight = (unsigned int)*piPtr++;
+				iWidth = (unsigned int)*piPtr;
+			}
+			else
+			{
+				iWidth = pcTex->mWidth;
+				iHeight = pcTex->mHeight;
+			}
+
+			for (std::vector<aiVector3D>::iterator
+				i =  vTexCoords.begin();
+				i != vTexCoords.end();++i)
+			{
+				(*i).x /= iWidth;
+				(*i).y /= iHeight;
+				(*i).y = 1.0f- (*i).y;
+			}
+		}
+	}
+
+	// allocate output storage
+	pScene->mMeshes[0]->mNumVertices = vPositions.size();
+	pScene->mMeshes[0]->mVertices = new aiVector3D[vPositions.size()];
+	pScene->mMeshes[0]->mNormals = new aiVector3D[vPositions.size()];
+	pScene->mMeshes[0]->mTextureCoords[0] = new aiVector3D[vPositions.size()];
+
+	// memcpy() the data to the c-syle arrays
+	memcpy(pScene->mMeshes[0]->mVertices,	&vPositions[0],	
+		vPositions.size() * sizeof(aiVector3D));
+	memcpy(pScene->mMeshes[0]->mNormals,	&vNormals[0],	
+		vPositions.size() * sizeof(aiVector3D));
+	memcpy(pScene->mMeshes[0]->mTextureCoords[0],	&vTexCoords[0],	
+		vPositions.size() * sizeof(aiVector3D));
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::ParseSkinLump_GameStudioA7(
+	const unsigned char* szCurrent,
+	const unsigned char** szCurrentOut,
+	std::vector<MaterialHelper*>& pcMats)
+{
+	ai_assert(NULL != szCurrent);
+	ai_assert(NULL != szCurrentOut);
+
+	*szCurrentOut = szCurrent;
+	const MDL::Skin_MDL7* pcSkin = (const MDL::Skin_MDL7*)szCurrent;
+	szCurrent += 12;
+
+	// allocate an output material
+	MaterialHelper* pcMatOut = new MaterialHelper();
+	pcMats.push_back(pcMatOut);
+
+	aiTexture* pcNew = NULL;
+
+	// get the type of the skin
+	unsigned int iMasked = (unsigned int)(pcSkin->typ & 0xF);
+
+	// skip length of file name
+	szCurrent += AI_MDL7_MAX_TEXNAMESIZE;
+
+	if (0x1 ==  iMasked)
+	{
+		// ***** REFERENCE TO ANOTHER SKIN INDEX *****
+
+		// NOTE: Documentation - if you can call it a documentation, I prefer
+		// the expression "rubbish" - states it is currently unused. However,
+		// I don't know what ideas the terrible developers of Conitec will
+		// have tomorrow, so Im going to implement it.
+		int referrer = pcSkin->width;
+		pcMatOut->AddProperty<int>(&referrer,1,"quakquakquak");
+	}
+	else if (0x6 == iMasked)
+	{
+		// ***** EMBEDDED DDS FILE *****
+		if (1 != pcSkin->height)
+		{
+			// LOG
+		}
+
+		pcNew = new aiTexture();
+		pcNew->mHeight = 0;
+		pcNew->achFormatHint[0] = 'd';
+		pcNew->achFormatHint[1] = 'd';
+		pcNew->achFormatHint[2] = 's';
+		pcNew->achFormatHint[3] = '\0';
+
+		pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
+		memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
+		szCurrent += pcSkin->width;
+	}
+	if (0x7 == iMasked)
+	{
+		// ***** REFERENCE TO EXTERNAL FILE FILE *****
+		if (1 != pcSkin->height)
+		{
+			// LOG
+		}
+
+		aiString szFile;
+		const size_t iLen = strlen((const char*)szCurrent);
+		size_t iLen2 = iLen+1;
+		iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
+		memcpy(szFile.data,(const char*)szCurrent,iLen2);
+		szFile.length = iLen;
+
+		// place this as diffuse texture
+		pcMatOut->AddProperty<aiString>(&szFile,1,AI_MATKEY_TEXTURE_DIFFUSE(0));
+	}
+	else if (0 != iMasked)
+	{
+		// ***** STANDARD COLOR TEXTURE *****
+		if (0 == pcSkin->height || 0 == pcSkin->width)
+		{
+			// LOG
+		}
+
+		// it is a standard color texture. Fill in width and height
+		// and call the same function we used for loading MDL5 files
+
+		pcNew = new aiTexture();
+		pcNew->mWidth = pcSkin->width;
+		pcNew->mHeight = pcSkin->height;
+
+		unsigned int iSkip = 0;
+		this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew);
+
+		// skip length of texture data
+		szCurrent += iSkip;
+	}
+	
+	// check whether a material definition is contained in the skin
+	if (pcSkin->typ & AI_MDL7_SKINTYPE_MATERIAL)
+	{
+		const MDL::Material_MDL7* pcMatIn = (const MDL::Material_MDL7*)szCurrent;
+		szCurrent = (unsigned char*)(pcMatIn+1);
+
+		aiColor4D clrTemp;
+
+		// read diffuse color
+		clrTemp.a = 1.0f; //pcMatIn->Diffuse.a;
+		clrTemp.r = pcMatIn->Diffuse.r;
+		clrTemp.g = pcMatIn->Diffuse.g;
+		clrTemp.b = pcMatIn->Diffuse.b;
+		pcMatOut->AddProperty<aiColor4D>(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE);
+
+		// read specular color
+		clrTemp.a = 1.0f; //pcMatIn->Specular.a;
+		clrTemp.r = pcMatIn->Specular.r;
+		clrTemp.g = pcMatIn->Specular.g;
+		clrTemp.b = pcMatIn->Specular.b;
+		pcMatOut->AddProperty<aiColor4D>(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR);
+
+		// read ambient color
+		clrTemp.a = 1.0f; //pcMatIn->Ambient.a;
+		clrTemp.r = pcMatIn->Ambient.r;
+		clrTemp.g = pcMatIn->Ambient.g;
+		clrTemp.b = pcMatIn->Ambient.b;
+		pcMatOut->AddProperty<aiColor4D>(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT);
+
+		// read emissive color
+		clrTemp.a = 1.0f; //pcMatIn->Emissive.a;
+		clrTemp.r = pcMatIn->Emissive.r;
+		clrTemp.g = pcMatIn->Emissive.g;
+		clrTemp.b = pcMatIn->Emissive.b;
+		pcMatOut->AddProperty<aiColor4D>(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE);
+
+		// FIX: Take the opacity from the ambient color
+		clrTemp.a = pcMatIn->Ambient.a;
+		pcMatOut->AddProperty<float>(&clrTemp.a,1,AI_MATKEY_OPACITY);
+
+		// read phong power
+		int iShadingMode = (int)aiShadingMode_Gouraud;
+		if (0.0f != pcMatIn->Power)
+		{
+			iShadingMode = (int)aiShadingMode_Phong;
+			pcMatOut->AddProperty<float>(&pcMatIn->Power,1,AI_MATKEY_SHININESS);
+		}
+		pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL);
+	}
+
+	// if an ASCII effect description (HLSL?) is contained in the file,
+	// we can simply ignore it ...
+	if (pcSkin->typ & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
+	{
+		int32_t iMe = *((int32_t*)szCurrent);
+		szCurrent += sizeof(char) * iMe + sizeof(int32_t);
+	}
+
+	// if an embedded texture has been loaded setup the corresponding
+	// data structures in the aiScene instance
+	if (NULL != pcNew)
+	{
+		// place this as diffuse texture
+		char szCurrent[5];
+		sprintf(szCurrent,"*%i",this->pScene->mNumTextures);
+	
+		aiString szFile;
+		const size_t iLen = strlen((const char*)szCurrent);
+		size_t iLen2 = iLen+1;
+		iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
+		memcpy(szFile.data,(const char*)szCurrent,iLen2);
+		szFile.length = iLen;
+
+		pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
+
+		// store the texture
+		aiTexture** pc = this->pScene->mTextures;
+		this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
+		for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
+			this->pScene->mTextures[i] = pc[i];
+
+		this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
+		this->pScene->mNumTextures++;
+		delete[] pc;
+	}
+
+	*szCurrentOut = szCurrent;
+	return;
+}
+
+#define _AI_MDL7_ACCESS(_data, _index, _limit, _type) \
+	(*((const _type*)(((const char*)_data) + _index * _limit)))
+
+#define _AI_MDL7_ACCESS_VERT(_data, _index, _limit) \
+	_AI_MDL7_ACCESS(_data,_index,_limit,MDL::Vertex_MDL7)
+
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::ValidateHeader_GameStudioA7(const MDL::Header_MDL7* pcHeader)
+{
+	ai_assert(NULL != pcHeader);
+
+	if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size)
+	{
+		// LOG
+		throw new ImportErrorException( 
+			"[3DGS MDL7] sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size");
+	}
+	if (sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size)
+	{
+		// LOG
+		throw new ImportErrorException( 
+			"[3DGS MDL7] sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size");
+	}
+	if (sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size)
+	{
+		// LOG
+		throw new ImportErrorException( 
+			"sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size");
+	}
+
+	// if there are no groups ... how should we load such a file?
+	if(0 == pcHeader->groups_num)
+	{
+		// LOG
+		throw new ImportErrorException( "[3DGS MDL7] No frames found");
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::InternReadFile_GameStudioA7( )
+{
+	ai_assert(NULL != pScene);
+
+	// current cursor position in the file
+	const MDL::Header_MDL7* pcHeader = (const MDL::Header_MDL7*)this->m_pcHeader;
+	const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
+
+	// validate the header of the file. There are some structure
+	// sizes that are expected by the loader to be constant 
+	this->ValidateHeader_GameStudioA7(pcHeader);
+
+	// skip all bones
+	szCurrent += sizeof(MDL::Bone_MDL7) * pcHeader->bones_num;
+
+	// allocate a material list
+	std::vector<MaterialHelper*> pcMats;
+
+	// vector to hold all created meshes
+	std::vector<aiMesh*> avOutList;
+	avOutList.reserve(pcHeader->groups_num);
+
+	// read all groups
+	for (unsigned int iGroup = 0; iGroup < (unsigned int)pcHeader->groups_num;++iGroup)
+	{
+		const MDL::Group_MDL7* pcGroup = (const MDL::Group_MDL7*)szCurrent;
+		szCurrent = (const unsigned char*)(pcGroup+1);
+
+		if (1 != pcGroup->typ)
+		{
+			// Not a triangle-based mesh
+			// LOGWRITE("[3DGS MDL7] Mesh group is no basing in triangles. Continuing happily");
+		}
+
+		// read all skins
+		pcMats.reserve(pcMats.size() + pcGroup->numskins);
+		for (unsigned int iSkin = 0; iSkin < (unsigned int)pcGroup->numskins;++iSkin)
+		{
+			this->ParseSkinLump_GameStudioA7(szCurrent,&szCurrent,pcMats);
+		}
+		// if we have absolutely no skin loaded we need to generate a default material
+		if (pcMats.empty())
+		{
+			const int iMode = (int)aiShadingMode_Gouraud;
+			pcMats.push_back(new MaterialHelper());
+			MaterialHelper* pcHelper = (MaterialHelper*)pcMats[0];
+			pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+			aiColor3D clr;
+			clr.b = clr.g = clr.r = 0.6f;
+			pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+			pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+			clr.b = clr.g = clr.r = 0.05f;
+			pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+		}
+
+		// now get a pointer to all texture coords in the group
+		const MDL::TexCoord_MDL7* pcGroupUVs = (const MDL::TexCoord_MDL7*)szCurrent;
+		szCurrent += pcHeader->skinpoint_stc_size * pcGroup->num_stpts;
+
+		// now get a pointer to all triangle in the group
+		const MDL::Triangle_MDL7* pcGroupTris = (const MDL::Triangle_MDL7*)szCurrent;
+		szCurrent += pcHeader->triangle_stc_size * pcGroup->numtris;
+
+		// now get a pointer to all vertices in the group
+		const MDL::Vertex_MDL7* pcGroupVerts = (const MDL::Vertex_MDL7*)szCurrent;
+		szCurrent += pcHeader->mainvertex_stc_size * pcGroup->numverts;
+
+		// build output vectors
+		std::vector<aiVector3D> vPositions;
+		vPositions.resize(pcGroup->numtris * 3);
+
+		std::vector<aiVector3D> vNormals;
+		vNormals.resize(pcGroup->numtris * 3);
+
+		std::vector<aiVector3D> vTextureCoords1;
+		vTextureCoords1.resize(pcGroup->numtris * 3,
+			aiVector3D(std::numeric_limits<float>::quiet_NaN(),0.0f,0.0f));
+
+		std::vector<aiVector3D> vTextureCoords2;
+		
+		bool bNeed2UV = false;
+		if (pcHeader->triangle_stc_size >= sizeof(MDL::Triangle_MDL7))
+		{
+			vTextureCoords2.resize(pcGroup->numtris * 3,
+			aiVector3D(std::numeric_limits<float>::quiet_NaN(),0.0f,0.0f));
+			bNeed2UV = true;
+		}
+		MDL::IntFace_MDL7* pcFaces = new MDL::IntFace_MDL7[pcGroup->numtris];
+
+		// iterate through all triangles and build valid display lists
+		for (unsigned int iTriangle = 0; iTriangle < (unsigned int)pcGroup->numtris; ++iTriangle)
+		{
+			// iterate through all indices of the current triangle
+			for (unsigned int c = 0; c < 3;++c)
+			{
+				// validate the vertex index
+				unsigned int iIndex = pcGroupTris->v_index[c];
+				if(iIndex > (unsigned int)pcGroup->numverts)
+				{
+					// LOG
+					iIndex = pcGroup->numverts-1;
+				}
+				unsigned int iOutIndex = iTriangle * 3 + c;
+
+				// write the output face index
+				pcFaces[iTriangle].mIndices[c] = iOutIndex;
+
+				// swap z and y axis
+				vPositions[iOutIndex].x = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .x;
+				vPositions[iOutIndex].z = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y;
+				vPositions[iOutIndex].y = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z;
+
+				// now read the normal vector
+				if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size)
+				{
+					// read the full normal vector
+					vNormals[iOutIndex].x = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[0];
+					vNormals[iOutIndex].z = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1];
+					vNormals[iOutIndex].y = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2];
+
+					// FIX: It seems to be necessary to invert all normals
+					vNormals[iOutIndex].x *= -1.0f;
+					vNormals[iOutIndex].y *= -1.0f;
+					vNormals[iOutIndex].z *= -1.0f;
+				}
+				else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size)
+				{
+					// read the normal vector from Quake2's smart table
+					vNormals[iOutIndex] = *((const aiVector3D*)(&g_avNormals[std::min(
+						int(_AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm162index),
+						int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
+
+					std::swap(vNormals[iOutIndex].z,vNormals[iOutIndex].y);
+				}
+
+			
+				// validate and process the first uv coordinate set
+				// *************************************************************
+				const unsigned int iMin =  sizeof(MDL::Triangle_MDL7)-
+					sizeof(MDL::SkinSet_MDL7)-sizeof(uint32_t);
+
+				const unsigned int iMin2 =  sizeof(MDL::Triangle_MDL7)-
+					sizeof(MDL::SkinSet_MDL7);
+
+				if (pcHeader->triangle_stc_size >= iMin)
+				{
+					iIndex = pcGroupTris->skinsets[0].st_index[c];
+					if(iIndex > (unsigned int)pcGroup->num_stpts)
+					{
+						iIndex = pcGroup->num_stpts-1;
+					}
+
+					float u = pcGroupUVs[iIndex].u;
+					float v = 1.0f-pcGroupUVs[iIndex].v;
+				
+					vTextureCoords1[iOutIndex].x = u;
+					vTextureCoords1[iOutIndex].y = v;
+					
+					// assign the material index, but only if it is existing
+					if (pcHeader->triangle_stc_size >= iMin2)
+					{
+						pcFaces[iTriangle].iMatIndex[0] = pcGroupTris->skinsets[0].material;
+					}
+				}
+				// validate and process the second uv coordinate set
+				// *************************************************************
+				if (pcHeader->triangle_stc_size >= sizeof(MDL::Triangle_MDL7))
+				{
+					iIndex = pcGroupTris->skinsets[1].st_index[c];
+					if(iIndex > (unsigned int)pcGroup->num_stpts)
+					{
+						iIndex = pcGroup->num_stpts-1;
+					}
+
+					float u = pcGroupUVs[iIndex].u;
+					float v = 1.0f-pcGroupUVs[iIndex].v;
+
+					vTextureCoords2[iOutIndex].x = u;
+					vTextureCoords2[iOutIndex].y = v;
+				
+					// check whether we do really need the second texture
+					// coordinate set ... wastes memory and loading time
+					if (0 != iIndex && (u != vTextureCoords1[iOutIndex].x ||
+						v != vTextureCoords1[iOutIndex].y))
+					{
+						bNeed2UV = true;
+					}
+					// if the material differs, we need a second skin, too
+					if (pcGroupTris->skinsets[1].material != pcGroupTris->skinsets[0].material)
+					{
+						bNeed2UV = true;
+					}
+
+					// assign the material index
+					pcFaces[iTriangle].iMatIndex[1] = pcGroupTris->skinsets[1].material;
+				}
+			}
+
+			// get the next triangle in the list
+			pcGroupTris = (const MDL::Triangle_MDL7*)((const char*)pcGroupTris + pcHeader->triangle_stc_size);
+		}
+
+		// if we don't need a second set of texture coordinates there is no reason to keep it in memory ...
+		std::vector<unsigned int>** aiSplit;
+		unsigned int iNumMaterials = 0;
+		if (!bNeed2UV)
+		{
+			vTextureCoords2.clear();
+
+			// allocate the array
+			aiSplit = new std::vector<unsigned int>*[pcMats.size()];
+			iNumMaterials = pcMats.size();
+
+			for (unsigned int m = 0; m < pcMats.size();++m)
+				aiSplit[m] = new std::vector<unsigned int>();
+
+			// iterate through all faces and sort by material
+			for (unsigned int iFace = 0; iFace < (unsigned int)pcGroup->numtris;++iFace)
+			{
+				// check range
+				if (pcFaces[iFace].iMatIndex[0] >= iNumMaterials)
+				{
+					// use the last material instead
+					aiSplit[iNumMaterials-1]->push_back(iFace);
+
+					// LOG
+				}
+				else aiSplit[pcFaces[iFace].iMatIndex[0]]->push_back(iFace);
+			}
+		}
+		else
+		{
+			// we need to build combined materials for each combination of
+			std::vector<MDL::IntMaterial_MDL7> avMats;
+			avMats.reserve(pcMats.size()*2);
+
+			std::vector<std::vector<unsigned int>* > aiTempSplit;
+			aiTempSplit.reserve(pcMats.size()*2);
+
+			for (unsigned int m = 0; m < pcMats.size();++m)
+				aiTempSplit[m] = new std::vector<unsigned int>();
+
+			// iterate through all faces and sort by material
+			for (unsigned int iFace = 0; iFace < (unsigned int)pcGroup->numtris;++iFace)
+			{
+				// check range
+				unsigned int iMatIndex = pcFaces[iFace].iMatIndex[0];
+				if (iMatIndex >= iNumMaterials)
+				{
+					iMatIndex = iNumMaterials-1;
+					// LOG
+				}
+				unsigned int iMatIndex2 = pcFaces[iFace].iMatIndex[1];
+				if (iMatIndex2 >= iNumMaterials)
+				{
+					iMatIndex2 = iNumMaterials-1;
+					// LOG
+				}
+
+				// do a slow O(log(n)*n) seach in the list ...
+				unsigned int iNum = 0;
+				bool bFound = false;
+				for (std::vector<MDL::IntMaterial_MDL7>::iterator
+					i =  avMats.begin();
+					i != avMats.end();++i,++iNum)
+				{
+					if ((*i).iOldMatIndices[0] == iMatIndex &&
+						(*i).iOldMatIndices[1] == iMatIndex2)
+					{
+						// reuse this material
+						bFound = true;
+						break;
+					}
+				}
+				if (!bFound)
+				{
+					//  build a new material ...
+					MDL::IntMaterial_MDL7 sHelper;
+					sHelper.pcMat = new MaterialHelper();
+					sHelper.iOldMatIndices[0] = iMatIndex;
+					sHelper.iOldMatIndices[1] = iMatIndex2;
+					this->JoinSkins_GameStudioA7(pcMats[iMatIndex],pcMats[iMatIndex2],sHelper.pcMat);
+
+					// and add it to the list
+					avMats.push_back(sHelper);
+					iNum = avMats.size()-1;
+				}
+				// adjust the size of the file array
+				if (iNum == aiTempSplit.size())
+				{
+					aiTempSplit.push_back(new std::vector<unsigned int>());
+				}
+				aiTempSplit[iNum]->push_back(iFace);
+			}
+
+			// now add the newly created materials to the old list
+			if (0 == iGroup)
+			{
+				pcMats.resize(avMats.size());
+				for (unsigned int o = 0; o < avMats.size();++o)
+					pcMats[o] = avMats[o].pcMat;
+			}
+			else
+			{
+				// TODO: This might result in redundant materials ...
+				unsigned int iOld = pcMats.size();
+				pcMats.resize(pcMats.size() + avMats.size());
+				for (unsigned int o = iOld; o < avMats.size();++o)
+					pcMats[o] = avMats[o].pcMat;
+			}
+			iNumMaterials = pcMats.size();
+
+			// and build the final face-to-material array
+			aiSplit = new std::vector<unsigned int>*[aiTempSplit.size()];
+			for (unsigned int m = 0; m < iNumMaterials;++m)
+				aiSplit[m] = aiTempSplit[m];
+
+			// no need to delete the member of aiTempSplit
+		}
+
+		// now generate output meshes
+		unsigned int iOldSize = avOutList.size();
+		this->GenerateOutputMeshes_GameStudioA7(
+			(const std::vector<unsigned int>**)aiSplit,pcMats,
+			avOutList,pcFaces,vPositions,vNormals, vTextureCoords1,vTextureCoords2);
+
+		// store the group index temporarily
+		ai_assert(AI_MAX_NUMBER_OF_TEXTURECOORDS >= 3);
+		for (unsigned int l = iOldSize;l < avOutList.size();++l)
+		{
+			avOutList[l]->mNumUVComponents[2] = iGroup;
+		}
+
+		// delete the face-to-material helper array
+		for (unsigned int m = 0; m < iNumMaterials;++m)
+			delete aiSplit[m];
+		delete[] aiSplit;
+
+		// now we need to skip all faces
+		for(unsigned int iFrame = 0; iFrame < (unsigned int)pcGroup->numframes;++iFrame)
+		{
+			const MDL::Frame_MDL7* pcFrame = (const MDL::Frame_MDL7*)szCurrent;
+
+			unsigned int iAdd = pcHeader->frame_stc_size + 
+				pcFrame->vertices_count * pcHeader->framevertex_stc_size +
+				pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size;
+
+			if (((unsigned int)szCurrent -  (unsigned int)pcHeader) + iAdd > (unsigned int)pcHeader->data_size)
+			{
+				// LOG
+				// don't parse more groups if we can't even read one
+				goto __BREAK_OUT;
+			}
+
+			szCurrent += iAdd;
+		}
+	}
+__BREAK_OUT: // EVIL ;-)
+
+	// now we need to build a final mesh list
+	this->pScene->mNumMeshes = avOutList.size();
+	this->pScene->mMeshes = new aiMesh*[avOutList.size()];
+
+	for (unsigned int i = 0; i < avOutList.size();++i)
+	{
+		this->pScene->mMeshes[i] = avOutList[i];
+	}
+
+	// build a final material list. Offset all mesh material indices
+	this->pScene->mNumMaterials = pcMats.size();
+	this->pScene->mMaterials = new aiMaterial*[this->pScene->mNumMaterials];
+	for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i)
+		this->pScene->mMaterials[i] = pcMats[i];
+	
+	// search for referrer materials
+	for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i)
+	{
+		int iIndex = 0;
+		if (AI_SUCCESS == aiGetMaterialInteger(this->pScene->mMaterials[i],
+			"quakquakquak", &iIndex) )
+		{
+			for (unsigned int a = 0; a < avOutList.size();++a)
+			{
+				if (i == avOutList[a]->mMaterialIndex)
+				{
+					avOutList[a]->mMaterialIndex = iIndex;
+				}
+			}
+			// TODO: Remove the material from the list
+		}
+	}
+
+	// now generate a nodegraph whose rootnode references all meshes
+	this->pScene->mRootNode = new aiNode();
+	this->pScene->mRootNode->mNumMeshes = this->pScene->mNumMeshes;
+	this->pScene->mRootNode->mMeshes = new unsigned int[this->pScene->mRootNode->mNumMeshes];
+	for (unsigned int i = 0; i < this->pScene->mRootNode->mNumMeshes;++i)
+		this->pScene->mRootNode->mMeshes[i] = i;
+
+	// seems we're finished now
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::GenerateOutputMeshes_GameStudioA7(
+	const std::vector<unsigned int>** aiSplit,
+	const std::vector<MaterialHelper*>& pcMats,
+	std::vector<aiMesh*>& avOutList,
+	const MDL::IntFace_MDL7* pcFaces,
+	const std::vector<aiVector3D>& vPositions,
+	const std::vector<aiVector3D>& vNormals, 
+	const std::vector<aiVector3D>& vTextureCoords1,
+	const std::vector<aiVector3D>& vTextureCoords2)
+{
+	for (unsigned int i = 0; i < pcMats.size();++i)
+	{
+		if (!aiSplit[i]->empty())
+		{
+			// allocate the output mesh
+			aiMesh* pcMesh = new aiMesh();
+			pcMesh->mNumUVComponents[0] = 2;
+			pcMesh->mMaterialIndex = i;
+
+			// allocate output storage
+			pcMesh->mNumFaces = aiSplit[i]->size();
+			pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+
+			pcMesh->mNumVertices = pcMesh->mNumFaces*3;
+			pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+			pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+
+			pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+			if (!vTextureCoords2.empty())
+			{
+				pcMesh->mNumUVComponents[1] = 2;
+				pcMesh->mTextureCoords[1] = new aiVector3D[pcMesh->mNumVertices];
+			}
+
+			// iterate through all faces and build an unique set of vertices
+			unsigned int iCurrent = 0;
+			for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace)
+			{
+				pcMesh->mFaces[iFace].mNumIndices = 3;
+				pcMesh->mFaces[iFace].mIndices = new unsigned int[3];
+
+				unsigned int iSrcFace = aiSplit[i]->operator[](iFace);
+				const MDL::IntFace_MDL7& oldFace = pcFaces[iSrcFace];
+
+				// iterate through all face indices
+				for (unsigned int c = 0; c < 3;++c)
+				{
+					pcMesh->mVertices[iCurrent] = vPositions[oldFace.mIndices[c]];
+					pcMesh->mNormals[iCurrent] = vNormals[oldFace.mIndices[c]];
+					pcMesh->mTextureCoords[0][iCurrent] = vTextureCoords1[oldFace.mIndices[c]];
+
+					if (!vTextureCoords2.empty())
+					{
+						pcMesh->mTextureCoords[1][iCurrent] = vTextureCoords2[oldFace.mIndices[c]];
+					}
+
+					pcMesh->mFaces[iFace].mIndices[c] = iCurrent;
+					++iCurrent;
+				}
+			}
+
+			// add the mesh to the list of output meshes
+			avOutList.push_back(pcMesh);
+		}
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void MDLImporter::JoinSkins_GameStudioA7(
+	MaterialHelper* pcMat1,
+	MaterialHelper* pcMat2,
+	MaterialHelper* pcMatOut)
+{
+	ai_assert(NULL != pcMat1);
+	ai_assert(NULL != pcMat2);
+	ai_assert(NULL != pcMatOut);
+
+	// first create a full copy of the first skin property set
+	// and assign it to the output material
+	MaterialHelper::CopyPropertyList(pcMatOut,pcMat1);
+
+	int iVal = 0;
+	pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(0));
+
+	// then extract the diffuse texture from the second skin,
+	// setup 1 as UV source and we have it
+
+	aiString sString;
+	if(AI_SUCCESS == aiGetMaterialString ( pcMat2, AI_MATKEY_TEXTURE_DIFFUSE(0),&sString ))
+	{
+		iVal = 1;
+		pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(1));
+		pcMatOut->AddProperty(&sString,AI_MATKEY_TEXTURE_DIFFUSE(1));
+	}
+	return;
+}

+ 241 - 0
code/MDLLoader.h

@@ -0,0 +1,241 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definition of MDL importer class
+//!
+
+#ifndef AI_MDLLOADER_H_INCLUDED
+#define AI_MDLLOADER_H_INCLUDED
+
+#include "BaseImporter.h"
+#include "../include/aiTypes.h"
+#include "../include/aiTexture.h"
+#include "../include/aiMaterial.h"
+
+struct aiNode;
+#include "MDLFileData.h"
+
+namespace Assimp
+{
+class MaterialHelper;
+
+using namespace MDL;
+
+// ---------------------------------------------------------------------------
+/** Used to load MDL files
+*/
+class MDLImporter : public BaseImporter
+{
+	friend class Importer;
+
+protected:
+	/** Constructor to be privately used by Importer */
+	MDLImporter();
+
+	/** Destructor, private as well */
+	~MDLImporter();
+
+public:
+
+	// -------------------------------------------------------------------
+	/** Returns whether the class can handle the format of the given file. 
+	* See BaseImporter::CanRead() for details.	*/
+	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+
+protected:
+
+
+	// -------------------------------------------------------------------
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 * See BaseImporter::GetExtensionList() for details
+	 */
+	void GetExtensionList(std::string& append)
+	{
+		append.append("*.mdl");
+	}
+
+	// -------------------------------------------------------------------
+	/** Imports the given file into the given scene structure. 
+	* See BaseImporter::InternReadFile() for details
+	*/
+	void InternReadFile( const std::string& pFile, aiScene* pScene, 
+		IOSystem* pIOHandler);
+
+protected:
+
+	// -------------------------------------------------------------------
+	/** Import a quake 1 MDL file
+	*/
+	void InternReadFile_Quake1( );
+
+	// -------------------------------------------------------------------
+	/** Import a GameStudio A4/A5 file
+	*/
+	void InternReadFile_GameStudio( );
+
+	// -------------------------------------------------------------------
+	/** Import a GameStudio A7 file
+	*/
+	void InternReadFile_GameStudioA7( );
+
+	// -------------------------------------------------------------------
+	/** Load a paletized texture from the file and convert it to 32bpp
+	*/
+	void CreateTextureARGB8(const unsigned char* szData);
+
+
+	// -------------------------------------------------------------------
+	/** Used to load textures from MDL3/4
+	 * \param szData Input data
+	 * \param iType Color data type
+	 * \param piSkip Receive: Size to skip
+	*/
+	void CreateTextureARGB8_GS4(const unsigned char* szData, 
+		unsigned int iType,
+		unsigned int* piSkip);
+
+	// -------------------------------------------------------------------
+	/** Used to load textures from MDL5
+	 * \param szData Input data
+	 * \param iType Color data type
+	 * \param piSkip Receive: Size to skip
+	*/
+	void CreateTextureARGB8_GS5(const unsigned char* szData, 
+		unsigned int iType,
+		unsigned int* piSkip);
+
+	// -------------------------------------------------------------------
+	/** Parse a skin lump in a MDL7 file with all of its features
+	 * \param szCurrent Current data pointer
+	 * \param szCurrentOut Output data pointer
+	 * \param pcMats Material list for this group. To be filled ...
+	 */
+	void ParseSkinLump_GameStudioA7(
+		const unsigned char* szCurrent,
+		const unsigned char** szCurrentOut,
+		std::vector<MaterialHelper*>& pcMats);
+
+	// -------------------------------------------------------------------
+	/** Parse texture color data for MDL5, MDL6 and MDL7 formats
+	 * \param szData Current data pointer
+	 * \param iType type of the texture data. No DDS or external
+	 * \param piSkip Receive the number of bytes to skip
+	 * \param pcNew Must point to fully initialized data. Width and 
+	 *        height must be set.
+	 */
+	void ParseTextureColorData(const unsigned char* szData, 
+		unsigned int iType,
+		unsigned int* piSkip,
+		aiTexture* pcNew);
+
+	// -------------------------------------------------------------------
+	/** Validate the header data structure of a game studio MDL7 file
+	 * \param pcHeader Input header to be validated
+	 */
+	void ValidateHeader_GameStudioA7(const MDL::Header_MDL7* pcHeader);
+
+	// -------------------------------------------------------------------
+	/** Join two materials / skins. Setup UV source ... etc
+	 * \param pcMat1 First input material
+	 * \param pcMat2 Second input material
+	 * \param pcMatOut Output material instance to be filled. Must be empty
+	 */
+	void JoinSkins_GameStudioA7(MaterialHelper* pcMat1,
+		MaterialHelper* pcMat2,
+		MaterialHelper* pcMatOut);
+
+	// -------------------------------------------------------------------
+	/** Generate the final output meshes for a7 models
+	 * \param aiSplit Face-per-material list
+	 * \param pcMats List of all materials
+	 * \param avOutList Output: List of all meshes
+	 * \param pcFaces List of all input faces
+	 * \param vPositions List of all input vectors
+	 * \param vNormals List of all input normal vectors
+	 * \param vTextureCoords1 List of all input UV coords #1
+	 * \param vTextureCoords2 List of all input UV coords #2
+	 */
+	void GenerateOutputMeshes_GameStudioA7(
+		const std::vector<unsigned int>** aiSplit,
+		const std::vector<MaterialHelper*>& pcMats,
+		std::vector<aiMesh*>& avOutList,
+		const MDL::IntFace_MDL7* pcFaces,
+		const std::vector<aiVector3D>& vPositions,
+		const std::vector<aiVector3D>& vNormals, 
+		const std::vector<aiVector3D>& vTextureCoords1,
+		const std::vector<aiVector3D>& vTextureCoords2);
+
+
+	// -------------------------------------------------------------------
+	/** Try to load a  palette from the current directory (colormap.lmp)
+	 *  If it is not found the default palette of Quake1 is returned
+	 */
+	void SearchPalette(const unsigned char** pszColorMap);
+
+	// -------------------------------------------------------------------
+	/** Free a palette created with a previous call to SearchPalette()
+	 */
+	void FreePalette(const unsigned char* pszColorMap);
+
+private:
+
+	/** Header of the MDL file */
+	const MDL::Header* m_pcHeader;
+
+	/** Buffer to hold the loaded file */
+	unsigned char* mBuffer;
+
+	/** For GameStudio MDL files: The number in the magic 
+	word, either 3,4 or 5*/
+	unsigned int iGSFileVersion;
+
+	/** Output I/O handler. used to load external lmp files
+	*/
+	IOSystem* pIOHandler;
+
+	/** Output scene to be filled
+	*/
+	aiScene* pScene;
+};
+}; // end of namespace Assimp
+
+#endif // AI_3DSIMPORTER_H_INC

+ 182 - 48
code/MaterialSystem.cpp

@@ -1,4 +1,42 @@
-
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 "assimp.h"
 #include "aiMaterial.h"
@@ -11,20 +49,15 @@
 using namespace Assimp;
 
 
-// ---------------------------------------------------------------------------
-// ---------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
 aiReturn aiGetMaterialProperty(const aiMaterial* pMat, 
 	const char* pKey,
 	const aiMaterialProperty** pPropOut)
 {
-#if (defined DEBUG)
-
 	ai_assert (pMat != NULL);
 	ai_assert (pKey != NULL);
 	ai_assert (pPropOut != NULL);
 
-#endif // ASSIMP_DEBUG
-
 	for (unsigned int i = 0; i < pMat->mNumProperties;++i)
 		{
 		if (NULL != pMat->mProperties[i])
@@ -39,23 +72,16 @@ aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
 	*pPropOut = NULL;
 	return AI_FAILURE;
 }
-
-
-// ---------------------------------------------------------------------------
-// ---------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
 aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, 
 	const char* pKey,
 	float* pOut,
 	unsigned int* pMax)
 {
-#if (defined DEBUG)
-
 	ai_assert (pMat != NULL);
 	ai_assert (pKey != NULL);
 	ai_assert (pOut != NULL);
 
-#endif // ASSIMP_DEBUG
-
 	for (unsigned int i = 0; i < pMat->mNumProperties;++i)
 	{
 		if (NULL != pMat->mProperties[i])
@@ -106,23 +132,15 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
 	}
 	return AI_FAILURE;
 }
-
-
-// ---------------------------------------------------------------------------
-// ---------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
 aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, 
 	const char* pKey,
 	int* pOut,
 	unsigned int* pMax)
 {
-#if (defined DEBUG)
-
 	ai_assert (pMat != NULL);
 	ai_assert (pKey != NULL);
 	ai_assert (pOut != NULL);
-
-#endif // ASSIMP_DEBUG
-
 	for (unsigned int i = 0; i < pMat->mNumProperties;++i)
 	{
 		if (NULL != pMat->mProperties[i])
@@ -173,10 +191,7 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
 	}
 	return AI_FAILURE;
 }
-
-
-// ---------------------------------------------------------------------------
-// ---------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
 aiReturn aiGetMaterialColor(const aiMaterial* pMat, 
 	const char* pKey,
 	aiColor4D* pOut)
@@ -188,22 +203,15 @@ aiReturn aiGetMaterialColor(const aiMaterial* pMat,
 	if (3 == iMax)pOut->a = 1.0f;
 	return eRet;
 }
-
-
-// ---------------------------------------------------------------------------
-// ---------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
 aiReturn aiGetMaterialString(const aiMaterial* pMat, 
 	const char* pKey,
 	aiString* pOut)
 {
-#if (defined DEBUG)
-
 	ai_assert (pMat != NULL);
 	ai_assert (pKey != NULL);
 	ai_assert (pOut != NULL);
 
-#endif // ASSIMP_DEBUG
-
 	for (unsigned int i = 0; i < pMat->mNumProperties;++i)
 	{
 		if (NULL != pMat->mProperties[i])
@@ -223,23 +231,16 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat,
 	}
 	return AI_FAILURE;
 }
-
-
-// ---------------------------------------------------------------------------
-// ---------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
 aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
 	const unsigned int pSizeInBytes,
 	const char* pKey,
 	aiPropertyTypeInfo pType)
 {
-#if (defined DEBUG)
-
 	ai_assert (pInput != NULL);
 	ai_assert (pKey != NULL);
 	ai_assert (0 != pSizeInBytes);
 
-#endif // ASSIMP_DEBUG
-
 	aiMaterialProperty* pcNew = new aiMaterialProperty();
 
 	// fill this
@@ -273,13 +274,146 @@ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
 	this->mProperties[this->mNumProperties++] = pcNew;
 	return AI_SUCCESS;
 }
-
-
-// ---------------------------------------------------------------------------
-// ---------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
 aiReturn MaterialHelper::AddProperty (const aiString* pInput,
 	const char* pKey)
 {
 	return this->AddBinaryProperty(pInput,
 		sizeof(aiString),pKey,aiPTI_String);
 }
+// ------------------------------------------------------------------------------------------------
+void MaterialHelper::CopyPropertyList(MaterialHelper* pcDest, 
+	const MaterialHelper* pcSrc)
+{
+	ai_assert(NULL != pcDest);
+	ai_assert(NULL != pcSrc);
+
+	unsigned int iOldNum = pcDest->mNumProperties;
+	pcDest->mNumAllocated += pcSrc->mNumAllocated;
+	pcDest->mNumProperties += pcSrc->mNumProperties;
+
+	aiMaterialProperty** pcOld = pcDest->mProperties;
+	pcDest->mProperties = new aiMaterialProperty*[pcDest->mNumAllocated];
+
+	if (pcOld)
+	{
+		for (unsigned int i = 0; i < iOldNum;++i)
+			pcDest->mProperties[i] = pcOld[i];
+
+		delete[] pcDest->mProperties;
+	}
+	for (unsigned int i = iOldNum; i< pcDest->mNumProperties;++i)
+	{
+		pcDest->mProperties[i]->mKey = new aiString(*pcSrc->mProperties[i]->mKey);
+		pcDest->mProperties[i]->mDataLength = pcSrc->mProperties[i]->mDataLength;
+		pcDest->mProperties[i]->mType = pcSrc->mProperties[i]->mType;
+		pcDest->mProperties[i]->mData = new char[pcDest->mProperties[i]->mDataLength];
+		memcpy(pcDest->mProperties[i]->mData,pcSrc->mProperties[i]->mData,
+			pcDest->mProperties[i]->mDataLength);
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
+	unsigned int iIndex,
+	unsigned int iTexType,
+	aiString* szOut,
+	unsigned int* piUVIndex,
+	float* pfBlendFactor,
+	aiTextureOp* peTextureOp)
+{
+	ai_assert(NULL != pcMat);
+	ai_assert(NULL != szOut);
+
+	const char* szPathBase;
+	const char* szUVBase;
+	const char* szBlendBase;
+	const char* szOpBase;
+	switch (iTexType)
+	{
+	case AI_TEXTYPE_DIFFUSE:
+		szPathBase = AI_MATKEY_TEXTURE_DIFFUSE_;
+		szUVBase = AI_MATKEY_UVWSRC_DIFFUSE_;
+		szBlendBase = AI_MATKEY_TEXBLEND_DIFFUSE_;
+		szOpBase = AI_MATKEY_TEXOP_DIFFUSE_;
+		break;
+	case AI_TEXTYPE_SPECULAR:
+		szPathBase = AI_MATKEY_TEXTURE_SPECULAR_;
+		szUVBase = AI_MATKEY_UVWSRC_SPECULAR_;
+		szBlendBase = AI_MATKEY_TEXBLEND_SPECULAR_;
+		szOpBase = AI_MATKEY_TEXOP_SPECULAR_;
+		break;
+	case AI_TEXTYPE_AMBIENT:
+		szPathBase = AI_MATKEY_TEXTURE_AMBIENT_;
+		szUVBase = AI_MATKEY_UVWSRC_AMBIENT_;
+		szBlendBase = AI_MATKEY_TEXBLEND_AMBIENT_;
+		szOpBase = AI_MATKEY_TEXOP_AMBIENT_;
+		break;
+	case AI_TEXTYPE_EMISSIVE:
+		szPathBase = AI_MATKEY_TEXTURE_EMISSIVE_;
+		szUVBase = AI_MATKEY_UVWSRC_EMISSIVE_;
+		szBlendBase = AI_MATKEY_TEXBLEND_EMISSIVE_;
+		szOpBase = AI_MATKEY_TEXOP_EMISSIVE_;
+		break;
+	case AI_TEXTYPE_HEIGHT:
+		szPathBase = AI_MATKEY_TEXTURE_HEIGHT_;
+		szUVBase = AI_MATKEY_UVWSRC_HEIGHT_;
+		szBlendBase = AI_MATKEY_TEXBLEND_HEIGHT_;
+		szOpBase = AI_MATKEY_TEXOP_HEIGHT_;
+		break;
+	case AI_TEXTYPE_NORMALS:
+		szPathBase = AI_MATKEY_TEXTURE_NORMALS_;
+		szUVBase = AI_MATKEY_UVWSRC_NORMALS_;
+		szBlendBase = AI_MATKEY_TEXBLEND_NORMALS_;
+		szOpBase = AI_MATKEY_TEXOP_NORMALS_;
+		break;
+	case AI_TEXTYPE_SHININESS:
+		szPathBase = AI_MATKEY_TEXTURE_SHININESS_;
+		szUVBase = AI_MATKEY_UVWSRC_SHININESS_;
+		szBlendBase = AI_MATKEY_TEXBLEND_SHININESS_;
+		szOpBase = AI_MATKEY_TEXOP_SHININESS_;
+		break;
+	default: return AI_FAILURE;
+	};
+
+	char szKey[256];
+
+	// get the path to the texture
+	sprintf(szKey,"%s[%i]",szPathBase,iIndex);
+	if (AI_SUCCESS != aiGetMaterialString(pcMat,szKey,szOut))
+	{
+		return AI_FAILURE;
+	}
+	// get the UV index of the texture
+	if (piUVIndex)
+	{
+		int iUV;
+		sprintf(szKey,"%s[%i]",szUVBase,iIndex);
+		if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,&iUV))
+			iUV = 0;
+
+		*piUVIndex = iUV;
+	}
+	// get the blend factor of the texture
+	if (pfBlendFactor)
+	{
+		float fBlend;
+		sprintf(szKey,"%s[%i]",szBlendBase,iIndex);
+		if (AI_SUCCESS != aiGetMaterialFloat(pcMat,szKey,&fBlend))
+			fBlend = 1.0f;
+
+		*pfBlendFactor = fBlend;
+	}
+	// get the texture operation of the texture
+	if (peTextureOp)
+	{
+		aiTextureOp op;
+		sprintf(szKey,"%s[%i]",szOpBase,iIndex);
+		if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,(int*)&op))
+			op = aiTextureOp_Multiply;
+
+		*peTextureOp = op;
+	}
+	return AI_SUCCESS;
+}
+

+ 85 - 4
code/MaterialSystem.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definition of the base class for all importer worker classes. */
 #ifndef AI_MATERIALSYSTEM_H_INC
 #define AI_MATERIALSYSTEM_H_INC
@@ -8,6 +48,15 @@ namespace Assimp
 {
 
 // ---------------------------------------------------------------------------
+/** \brief Helper function to do platform independent string comparison.
+ *
+ *  This is required since stricmp() is not consistently available on
+ *  all platforms. Some platforms use the '_' prefix, others don't even
+ *  have such a function. Yes, this is called an ISO standard.
+ *
+ *  \param s1 First input string
+ *  \param s2 Second input string
+ */
 // ---------------------------------------------------------------------------
 inline int ASSIMP_stricmp(const char *s1, const char *s2)
 {
@@ -28,6 +77,16 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
 }
 
 // ---------------------------------------------------------------------------
+/** \brief Helper function to do platform independent string comparison.
+ *
+ *  This is required since strincmp() is not consistently available on
+ *  all platforms. Some platforms use the '_' prefix, others don't even
+ *  have such a function. Yes, this is called an ISO standard.
+ *
+ *  \param s1 First input string
+ *  \param s2 Second input string
+ *  \param n Macimum number of characters to compare
+ */
 // ---------------------------------------------------------------------------
 inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
 {
@@ -58,14 +117,20 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
     structure easily. */
 class MaterialHelper : public ::aiMaterial
 {
-	public:
+public:
 
 	inline MaterialHelper();
 	inline ~MaterialHelper();
 
 	// -------------------------------------------------------------------
 	/** Add a property with a given key and type info to the material
-	    structure  */
+	 *  structure 
+	 *
+	 *  \param pInput Pointer to input data
+	 *  \param pSizeInBytes Size of input data
+	 *  \param pKey Key/Usage of the property (AI_MATKEY_XXX)
+	 *  \param pType Type information hint
+     */
 	aiReturn AddBinaryProperty (const void* pInput,
 		const unsigned int pSizeInBytes,
 		const char* pKey,
@@ -74,17 +139,33 @@ class MaterialHelper : public ::aiMaterial
 
 	// -------------------------------------------------------------------
 	/** Add a string property with a given key and type info to the 
-	    material structure  */
+	 *  material structure 
+	 *
+	 *  \param pInput Input string
+	 *  \param pKey Key/Usage of the property (AI_MATKEY_XXX)
+	 */
 	aiReturn AddProperty (const aiString* pInput,
 		const char* pKey);
 
 
 	// -------------------------------------------------------------------
-	/** Add a property with a given key to the material structure  */
+	/** Add a property with a given key to the material structure 
+	 *  \param pInput Pointer to the input data
+	 *  \param pNumValues Number of values in the array
+	 *  \param pKey Key/Usage of the property (AI_MATKEY_XXX)
+	 */
 	template<class TYPE>
 	aiReturn AddProperty (const TYPE* pInput,
 		const unsigned int pNumValues,
 		const char* pKey);
+
+	// -------------------------------------------------------------------
+	/** Copy the property list of a material
+	 *  \param pcDest Destination material
+	 *  \param pcSrc Source material
+	 */
+	static void CopyPropertyList(MaterialHelper* pcDest, 
+		const MaterialHelper* pcSrc);
 };
 
 

+ 44 - 3
code/ObjFileData.h

@@ -1,3 +1,44 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 OBJ_FILEDATA_H_INC
 #define OBJ_FILEDATA_H_INC
 
@@ -128,16 +169,16 @@ struct Model
 	//!	Vector with all generated group
 	std::vector<std::string> m_GroupLib;
 	//!	Vector with all generated vertices
-	std::vector<aiVector3D_t*> m_Vertices;
+	std::vector<aiVector3D*> m_Vertices;
 	//!	vector with all generated normals
-	std::vector<aiVector3D_t*> m_Normals;
+	std::vector<aiVector3D*> m_Normals;
 	//!	Groupmap
 	GroupMap m_Groups;
 	std::vector<unsigned int> *m_pGroupFaceIDs;
 	//!	Active group
 	std::string m_strActiveGroup;
 	//!	Vector with generated texture coordinates
-	std::vector<aiVector2D_t*> m_TextureCoord;
+	std::vector<aiVector2D*> m_TextureCoord;
 	//!	Material map
 	std::map<std::string, Material*> m_MaterialMap;
 

+ 2 - 2
code/ObjFileImporter.cpp

@@ -260,7 +260,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
 	
 	// Copy all stored vertices, normals and so on
 	pMesh->mNumVertices = pModel->m_Vertices.size();
-	pMesh->mVertices = new aiVector3D_t[pMesh->mNumVertices];
+	pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
 	for (size_t index=0; index < pModel->m_Vertices.size(); index++)
 	{
 		pMesh->mVertices[ index ] = *pModel->m_Vertices[ index ];
@@ -268,7 +268,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
 	
 	if (!pModel->m_Normals.empty())
 	{
-		pMesh->mNormals = new aiVector3D_t[pModel->m_Normals.size()];
+		pMesh->mNormals = new aiVector3D[pModel->m_Normals.size()];
 		for (size_t index = 0; index < pModel->m_Normals.size(); index++)
 		{
 			pMesh->mNormals[ index ] = *pModel->m_Normals[ index ];

+ 48 - 0
code/ObjFileImporter.h

@@ -1,3 +1,44 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 OBJ_FILE_IMPORTER_H_INC
 #define OBJ_FILE_IMPORTER_H_INC
 
@@ -39,6 +80,13 @@ public:
 	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
 
 private:
+
+	//! brief
+	void GetExtensionList(std::string& append)
+	{
+		append.append("*.obj");
+	}
+
 	//!	\brief
 	void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
 	

+ 41 - 0
code/ObjFileMtlImporter.h

@@ -1,3 +1,44 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 OBJFILEMTLIMPORTER_H_INC
 #define OBJFILEMTLIMPORTER_H_INC
 

+ 2 - 2
code/ObjFileParser.cpp

@@ -161,7 +161,7 @@ void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
 
 // -------------------------------------------------------------------
 //	Get values for a new 3D vector instance
-void ObjFileParser::getVector3(std::vector<aiVector3D_t*> &point3d_array)
+void ObjFileParser::getVector3(std::vector<aiVector3D*> &point3d_array)
 {
 	float x, y, z;
 	copyNextWord(m_buffer, BUFFERSIZE);
@@ -179,7 +179,7 @@ void ObjFileParser::getVector3(std::vector<aiVector3D_t*> &point3d_array)
 
 // -------------------------------------------------------------------
 //	Get values for a new 2D vector instance
-void ObjFileParser::getVector2(std::vector<aiVector2D_t*> &point2d_array)
+void ObjFileParser::getVector2(std::vector<aiVector2D*> &point2d_array)
 {
 	float x, y;
 	copyNextWord(m_buffer, BUFFERSIZE);

+ 40 - 0
code/ObjTools.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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	ObjTools.h
  *	@brief	Some helpful templates for text parsing
  */

+ 279 - 177
code/PlyLoader.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the PLY importer class */
 #include "PLYLoader.h"
 #include "MaterialSystem.h"
@@ -172,13 +213,17 @@ void PLYImporter::InternReadFile(
 	std::vector<aiColor4D> avColors;
 	this->LoadVertexColor(&avColors);
 
+	// now try to load texture coordinates
+	std::vector<aiVector2D> avTexCoords;
+	this->LoadTextureCoordinates(&avTexCoords);
+
 	// now replace the default material in all faces and validate all material indices
 	this->ReplaceDefaultMaterial(&avFaces,&avMaterials);
 
 	// now convert this to a list of aiMesh instances
 	std::vector<aiMesh*> avMeshes;
 	this->ConvertMeshes(&avFaces,&avPositions,&avNormals,
-		&avColors,&avMaterials,&avMeshes);
+		&avColors,&avTexCoords,&avMaterials,&avMeshes);
 
 	if (avMeshes.empty())
 	{
@@ -216,6 +261,7 @@ void PLYImporter::ConvertMeshes(std::vector<PLY::Face>* avFaces,
 	const std::vector<aiVector3D>*			avPositions,
 	const std::vector<aiVector3D>*			avNormals,
 	const std::vector<aiColor4D>*			avColors,
+	const std::vector<aiVector2D>*			avTexCoords,
 	const std::vector<MaterialHelper*>*		avMaterials,
 	std::vector<aiMesh*>* avOut)
 {
@@ -258,6 +304,11 @@ void PLYImporter::ConvertMeshes(std::vector<PLY::Face>* avFaces,
 
 			if (!avColors->empty())
 				p_pcOut->mColors[0] = new aiColor4D[iNum];
+			if (!avTexCoords->empty())
+			{
+				p_pcOut->mNumUVComponents[0] = 2;
+				p_pcOut->mTextureCoords[0] = new aiVector3D[iNum];
+			}
 			if (!avNormals->empty())
 				p_pcOut->mNormals = new aiVector3D[iNum];
 
@@ -272,53 +323,26 @@ void PLYImporter::ConvertMeshes(std::vector<PLY::Face>* avFaces,
 				p_pcOut->mFaces[iNum].mIndices = new unsigned int[p_pcOut->mFaces[iNum].mNumIndices];
 
 				// build an unique set of vertices/colors for this face
-				// hardcode all combinations to speedup this piece of code
-				if (!avColors->empty())
+				for (unsigned int q = 0; q <  p_pcOut->mFaces[iNum].mNumIndices;++q)
 				{
-					if (!avNormals->empty())
-					{
-						for (unsigned int q = 0; q <  p_pcOut->mFaces[iNum].mNumIndices;++q)
-						{
-							p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
-							p_pcOut->mVertices[iVertex]		= (*avPositions)[(*avFaces)[*i].mIndices[q]];
-							p_pcOut->mColors[0][iVertex]	= (*avColors)[(*avFaces)[*i].mIndices[q]];
-							p_pcOut->mNormals[iVertex]		= (*avNormals)[(*avFaces)[*i].mIndices[q]];
-							iVertex++;
-						}
-					}
-					else
+					p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
+					p_pcOut->mVertices[iVertex] = (*avPositions)[(*avFaces)[*i].mIndices[q]];
+
+					if (!avColors->empty())
+						p_pcOut->mColors[0][iVertex] = (*avColors)[(*avFaces)[*i].mIndices[q]];
+
+					if (!avTexCoords->empty())
 					{
-						for (unsigned int q = 0; q <  p_pcOut->mFaces[iNum].mNumIndices;++q)
-						{
-							p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
-							p_pcOut->mVertices[iVertex]		= (*avPositions)[(*avFaces)[*i].mIndices[q]];
-							p_pcOut->mColors[0][iVertex]	= (*avColors)[(*avFaces)[*i].mIndices[q]];
-							iVertex++;
-						}
+						const aiVector2D& vec = (*avTexCoords)[(*avFaces)[*i].mIndices[q]];
+						p_pcOut->mTextureCoords[0][iVertex].x = vec.x;
+						p_pcOut->mTextureCoords[0][iVertex].y = vec.y;
 					}
-				}
-				else
-				{
+
 					if (!avNormals->empty())
-					{
-						for (unsigned int q = 0; q <  p_pcOut->mFaces[iNum].mNumIndices;++q)
-						{
-							p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
-							p_pcOut->mVertices[iVertex]		= (*avPositions)[(*avFaces)[*i].mIndices[q]];
-							p_pcOut->mNormals[iVertex]		= (*avNormals)[(*avFaces)[*i].mIndices[q]];
-							iVertex++;
-						}
-					}
-					else
-					{
-						for (unsigned int q = 0; q <  p_pcOut->mFaces[iNum].mNumIndices;++q)
-						{
-							p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
-							p_pcOut->mVertices[iVertex]		= (*avPositions)[(*avFaces)[*i].mIndices[q]];
-							iVertex++;
-						}
-					}
+						p_pcOut->mNormals[iVertex] = (*avNormals)[(*avFaces)[*i].mIndices[q]];
+					iVertex++;
 				}
+
 			}
 			// add the mesh to the output list
 			avOut->push_back(p_pcOut);
@@ -370,8 +394,79 @@ void PLYImporter::ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
 	return;
 }
 // ------------------------------------------------------------------------------------------------
+void PLYImporter::LoadTextureCoordinates(std::vector<aiVector2D>* pvOut)
+{
+	ai_assert(NULL != pvOut);
+
+	unsigned int aiPositions[2] = {0xFFFFFFFF,0xFFFFFFFF};
+	PLY::EDataType aiTypes[2];
+	PLY::ElementInstanceList* pcList = NULL;
+	unsigned int cnt = 0;
+
+	// serach in the DOM for a vertex entry
+	unsigned int _i = 0;
+	for (std::vector<PLY::Element*>::const_iterator
+		i =  this->pcDOM->alElements.begin();
+		i != this->pcDOM->alElements.end();++i,++_i)
+	{
+		if (PLY::EEST_Vertex == (*i)->eSemantic)
+		{
+			pcList = this->pcDOM->alElementData[_i];
+
+			// now check whether which normal components are available
+			unsigned int _a = 0;
+			for (std::vector<PLY::Property*>::const_iterator
+				a =  (*i)->alProperties.begin();
+				a != (*i)->alProperties.end();++a,++_a)
+			{
+				if ((*a)->bIsList)continue;
+				if (PLY::EST_UTextureCoord == (*a)->Semantic)
+				{
+					cnt++;
+					aiPositions[0] = _a;
+					aiTypes[0] = (*a)->eType;
+				}
+				else if (PLY::EST_VTextureCoord == (*a)->Semantic)
+				{
+					cnt++;
+					aiPositions[1] = _a;
+					aiTypes[1] = (*a)->eType;
+				}
+			}
+		}
+	}
+	// check whether we have a valid source for the texture coordinates data
+	if (NULL != pcList && 0 != cnt)
+	{
+		pvOut->reserve(pcList->alInstances.size());
+		for (std::vector<ElementInstance*>::const_iterator
+			i =  pcList->alInstances.begin();
+			i != pcList->alInstances.end();++i)
+		{
+			// convert the vertices to sp floats
+			aiVector2D vOut;
+
+			if (0xFFFFFFFF != aiPositions[0])
+			{
+				vOut.x = PLY::PropertyInstance::ConvertTo<float>(
+					(*i)->alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
+			}
+
+			if (0xFFFFFFFF != aiPositions[1])
+			{
+				vOut.y = PLY::PropertyInstance::ConvertTo<float>(
+					(*i)->alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
+			}
+			// and add them to our nice list
+			pvOut->push_back(vOut);
+		}
+	}
+}
+// ------------------------------------------------------------------------------------------------
 void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
 {
+	ai_assert(NULL != pvOut);
+
 	unsigned int aiPositions[3] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
 	PLY::EDataType aiTypes[3];
 	PLY::ElementInstanceList* pcList = NULL;
@@ -379,43 +474,42 @@ void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
 
 	// serach in the DOM for a vertex entry
 	unsigned int _i = 0;
-	for (std::vector<PLY::Element>::const_iterator
+	for (std::vector<PLY::Element*>::const_iterator
 		i =  this->pcDOM->alElements.begin();
 		i != this->pcDOM->alElements.end();++i,++_i)
 	{
-		if (PLY::EEST_Vertex == (*i).eSemantic)
+		if (PLY::EEST_Vertex == (*i)->eSemantic)
 		{
-			pcList = &this->pcDOM->alElementData[_i];
+			pcList = this->pcDOM->alElementData[_i];
 
 			// load normal vectors?
 			if (p_bNormals)
 			{
 				// now check whether which normal components are available
 				unsigned int _a = 0;
-				for (std::vector<PLY::Property>::const_iterator
-					a =  (*i).alProperties.begin();
-					a != (*i).alProperties.end();++a,++_a)
+				for (std::vector<PLY::Property*>::const_iterator
+					a =  (*i)->alProperties.begin();
+					a != (*i)->alProperties.end();++a,++_a)
 				{
-					if ((*a).bIsList)continue;
-					if (PLY::EST_XNormal == (*a).Semantic)
+					if ((*a)->bIsList)continue;
+					if (PLY::EST_XNormal == (*a)->Semantic)
 					{
 						cnt++;
 						aiPositions[0] = _a;
-						aiTypes[0] = (*a).eType;
+						aiTypes[0] = (*a)->eType;
 					}
-					else if (PLY::EST_YNormal == (*a).Semantic)
+					else if (PLY::EST_YNormal == (*a)->Semantic)
 					{
 						cnt++;
 						aiPositions[1] = _a;
-						aiTypes[1] = (*a).eType;
+						aiTypes[1] = (*a)->eType;
 					}
-					else if (PLY::EST_ZNormal == (*a).Semantic)
+					else if (PLY::EST_ZNormal == (*a)->Semantic)
 					{
 						cnt++;
 						aiPositions[2] = _a;
-						aiTypes[2] = (*a).eType;
+						aiTypes[2] = (*a)->eType;
 					}
-					if (3 == cnt)break; 
 				}
 			}
 			// load vertex coordinates
@@ -423,28 +517,28 @@ void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
 			{
 				// now check whether which coordinate sets are available
 				unsigned int _a = 0;
-				for (std::vector<PLY::Property>::const_iterator
-					a =  (*i).alProperties.begin();
-					a != (*i).alProperties.end();++a,++_a)
+				for (std::vector<PLY::Property*>::const_iterator
+					a =  (*i)->alProperties.begin();
+					a != (*i)->alProperties.end();++a,++_a)
 				{
-					if ((*a).bIsList)continue;
-					if (PLY::EST_XCoord == (*a).Semantic)
+					if ((*a)->bIsList)continue;
+					if (PLY::EST_XCoord == (*a)->Semantic)
 					{
 						cnt++;
 						aiPositions[0] = _a;
-						aiTypes[0] = (*a).eType;
+						aiTypes[0] = (*a)->eType;
 					}
-					else if (PLY::EST_YCoord == (*a).Semantic)
+					else if (PLY::EST_YCoord == (*a)->Semantic)
 					{
 						cnt++;
 						aiPositions[1] = _a;
-						aiTypes[1] = (*a).eType;
+						aiTypes[1] = (*a)->eType;
 					}
-					else if (PLY::EST_ZCoord == (*a).Semantic)
+					else if (PLY::EST_ZCoord == (*a)->Semantic)
 					{
 						cnt++;
 						aiPositions[2] = _a;
-						aiTypes[2] = (*a).eType;
+						aiTypes[2] = (*a)->eType;
 					}
 					if (3 == cnt)break; 
 				}
@@ -456,32 +550,29 @@ void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
 	if (NULL != pcList && 0 != cnt)
 	{
 		pvOut->reserve(pcList->alInstances.size());
-		for (std::vector<ElementInstance>::const_iterator
+		for (std::vector<ElementInstance*>::const_iterator
 			i =  pcList->alInstances.begin();
 			i != pcList->alInstances.end();++i)
 		{
 			// convert the vertices to sp floats
 			aiVector3D vOut;
 
-			if (0xFFFFFFFF == aiPositions[0])vOut.x = 0.0f;
-			else
+			if (0xFFFFFFFF != aiPositions[0])
 			{
 				vOut.x = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
+					(*i)->alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
 			}
 
-			if (0xFFFFFFFF == aiPositions[1])vOut.y = 0.0f;
-			else
+			if (0xFFFFFFFF != aiPositions[1])
 			{
 				vOut.y = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
+					(*i)->alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
 			}
 
-			if (0xFFFFFFFF == aiPositions[2])vOut.z = 0.0f;
-			else
+			if (0xFFFFFFFF != aiPositions[2])
 			{
 				vOut.z = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[aiPositions[2]].avList.front(),aiTypes[2]);
+					(*i)->alProperties[aiPositions[2]].avList.front(),aiTypes[2]);
 			}
 
 			// and add them to our nice list
@@ -491,7 +582,8 @@ void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
 	return;
 }
 // ------------------------------------------------------------------------------------------------
-float NormalizeColorValue (PLY::PropertyInstance::ValueUnion val,PLY::EDataType eType)
+float PLYImporter::NormalizeColorValue (PLY::PropertyInstance::ValueUnion val,
+	PLY::EDataType eType)
 {
 	switch (eType)
 	{
@@ -518,6 +610,8 @@ float NormalizeColorValue (PLY::PropertyInstance::ValueUnion val,PLY::EDataType
 // ------------------------------------------------------------------------------------------------
 void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
 {
+	ai_assert(NULL != pvOut);
+
 	unsigned int aiPositions[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
 	PLY::EDataType aiTypes[4];
 	unsigned int cnt = 0;
@@ -525,44 +619,44 @@ void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
 
 	// serach in the DOM for a vertex entry
 	unsigned int _i = 0;
-	for (std::vector<PLY::Element>::const_iterator
+	for (std::vector<PLY::Element*>::const_iterator
 		i =  this->pcDOM->alElements.begin();
 		i != this->pcDOM->alElements.end();++i,++_i)
 	{
-		if (PLY::EEST_Vertex == (*i).eSemantic)
+		if (PLY::EEST_Vertex == (*i)->eSemantic)
 		{
-			pcList = &this->pcDOM->alElementData[_i];
+			pcList = this->pcDOM->alElementData[_i];
 
 			// now check whether which coordinate sets are available
 			unsigned int _a = 0;
-			for (std::vector<PLY::Property>::const_iterator
-				a =  (*i).alProperties.begin();
-				a != (*i).alProperties.end();++a,++_a)
+			for (std::vector<PLY::Property*>::const_iterator
+				a =  (*i)->alProperties.begin();
+				a != (*i)->alProperties.end();++a,++_a)
 			{
-				if ((*a).bIsList)continue;
-				if (PLY::EST_Red == (*a).Semantic)
+				if ((*a)->bIsList)continue;
+				if (PLY::EST_Red == (*a)->Semantic)
 				{
 					cnt++;
 					aiPositions[0] = _a;
-					aiTypes[0] = (*a).eType;
+					aiTypes[0] = (*a)->eType;
 				}
-				else if (PLY::EST_Green == (*a).Semantic)
+				else if (PLY::EST_Green == (*a)->Semantic)
 				{
 					cnt++;
 					aiPositions[1] = _a;
-					aiTypes[1] = (*a).eType;
+					aiTypes[1] = (*a)->eType;
 				}
-				else if (PLY::EST_Blue == (*a).Semantic)
+				else if (PLY::EST_Blue == (*a)->Semantic)
 				{
 					cnt++;
 					aiPositions[2] = _a;
-					aiTypes[2] = (*a).eType;
+					aiTypes[2] = (*a)->eType;
 				}
-				else if (PLY::EST_Alpha == (*a).Semantic)
+				else if (PLY::EST_Alpha == (*a)->Semantic)
 				{
 					cnt++;
 					aiPositions[3] = _a;
-					aiTypes[3] = (*a).eType;
+					aiTypes[3] = (*a)->eType;
 				}
 				if (4 == cnt)break; 
 			}
@@ -573,31 +667,28 @@ void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
 	if (NULL != pcList && 0 != cnt)
 	{
 		pvOut->reserve(pcList->alInstances.size());
-		for (std::vector<ElementInstance>::const_iterator
+		for (std::vector<ElementInstance*>::const_iterator
 			i =  pcList->alInstances.begin();
 			i != pcList->alInstances.end();++i)
 		{
 			// convert the vertices to sp floats
 			aiColor4D vOut;
 			
-			if (0xFFFFFFFF == aiPositions[0])vOut.r = 0.0f;
-			else
+			if (0xFFFFFFFF != aiPositions[0])
 			{
-				vOut.r = NormalizeColorValue((*i).alProperties[
+				vOut.r = NormalizeColorValue((*i)->alProperties[
 					aiPositions[0]].avList.front(),aiTypes[0]);
 			}
 
-			if (0xFFFFFFFF == aiPositions[1])vOut.g = 0.0f;
-			else
+			if (0xFFFFFFFF != aiPositions[1])
 			{
-				vOut.g = NormalizeColorValue((*i).alProperties[
+				vOut.g = NormalizeColorValue((*i)->alProperties[
 					aiPositions[1]].avList.front(),aiTypes[1]);
 			}
 
-			if (0xFFFFFFFF == aiPositions[2])vOut.b = 0.0f;
-			else
+			if (0xFFFFFFFF != aiPositions[2])
 			{
-				vOut.b = NormalizeColorValue((*i).alProperties[
+				vOut.b = NormalizeColorValue((*i)->alProperties[
 					aiPositions[2]].avList.front(),aiTypes[2]);
 			}
 
@@ -605,7 +696,7 @@ void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
 			if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f;
 			else
 			{
-				vOut.a = NormalizeColorValue((*i).alProperties[
+				vOut.a = NormalizeColorValue((*i)->alProperties[
 					aiPositions[3]].avList.front(),aiTypes[3]);
 			}
 
@@ -619,6 +710,8 @@ void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
 // ------------------------------------------------------------------------------------------------
 void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 {
+	ai_assert(NULL != pvOut);
+
 	PLY::ElementInstanceList* pcList = NULL;
 	bool bOne = false;
 
@@ -633,54 +726,54 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 
 	// serach in the DOM for a face entry
 	unsigned int _i = 0;
-	for (std::vector<PLY::Element>::const_iterator 
+	for (std::vector<PLY::Element*>::const_iterator 
 		i =  this->pcDOM->alElements.begin();
 		i != this->pcDOM->alElements.end();++i,++_i)
 	{
 		// face = unique number of vertex indices
-		if (PLY::EEST_Face == (*i).eSemantic)
+		if (PLY::EEST_Face == (*i)->eSemantic)
 		{
-			pcList = &this->pcDOM->alElementData[_i];
+			pcList = this->pcDOM->alElementData[_i];
 			unsigned int _a = 0;
-			for (std::vector<PLY::Property>::const_iterator 
-				a =  (*i).alProperties.begin();
-				a != (*i).alProperties.end();++a,++_a)
+			for (std::vector<PLY::Property*>::const_iterator 
+				a =  (*i)->alProperties.begin();
+				a != (*i)->alProperties.end();++a,++_a)
 			{
-				if (PLY::EST_VertexIndex == (*a).Semantic)
+				if (PLY::EST_VertexIndex == (*a)->Semantic)
 				{
 					// must be a dynamic list!
-					if (!(*a).bIsList)continue;
+					if (!(*a)->bIsList)continue;
 					iProperty	= _a;
 					bOne		= true;
-					eType		= (*a).eType;		
+					eType		= (*a)->eType;		
 				}
-				else if (PLY::EST_MaterialIndex == (*a).Semantic)
+				else if (PLY::EST_MaterialIndex == (*a)->Semantic)
 				{
-					if ((*a).bIsList)continue;
+					if ((*a)->bIsList)continue;
 					iMaterialIndex	= _a;
 					bOne			= true;
-					eType2		= (*a).eType;		
+					eType2		= (*a)->eType;		
 				}
 			}
 			break;
 		}
 		// triangle strip
 		// TODO: triangle strip and material index support???
-		else if (PLY::EEST_TriStrip == (*i).eSemantic)
+		else if (PLY::EEST_TriStrip == (*i)->eSemantic)
 		{
 			// find a list property in this ...
-			pcList = &this->pcDOM->alElementData[_i];
+			pcList = this->pcDOM->alElementData[_i];
 			unsigned int _a = 0;
-			for (std::vector<PLY::Property>::const_iterator 
-				a =  (*i).alProperties.begin();
-				a != (*i).alProperties.end();++a,++_a)
+			for (std::vector<PLY::Property*>::const_iterator 
+				a =  (*i)->alProperties.begin();
+				a != (*i)->alProperties.end();++a,++_a)
 			{
 				// must be a dynamic list!
-				if (!(*a).bIsList)continue;
+				if (!(*a)->bIsList)continue;
 				iProperty	= _a;
 				bOne		= true;
 				bIsTristrip	= true;
-				eType		= (*a).eType;	
+				eType		= (*a)->eType;	
 				break;
 			}
 			break;
@@ -692,7 +785,7 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 		if (!bIsTristrip)
 		{
 			pvOut->reserve(pcList->alInstances.size());
-			for (std::vector<ElementInstance>::const_iterator 
+			for (std::vector<ElementInstance*>::const_iterator 
 				i =  pcList->alInstances.begin();
 				i != pcList->alInstances.end();++i)
 			{
@@ -701,11 +794,19 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 				// parse the list of vertex indices
 				if (0xFFFFFFFF != iProperty)
 				{
-					const unsigned int iNum = (*i).alProperties[iProperty].avList.size();
+					const unsigned int iNum = (*i)->alProperties[iProperty].avList.size();
 					sFace.mIndices.resize(iNum);
 
+					if (3 > iNum)
+					{
+						// We must filter out all degenerates. Leave a message
+						// in the log ...
+						// LOG
+						continue;
+					}
+
 					std::list<PLY::PropertyInstance::ValueUnion>::const_iterator p = 
-						(*i).alProperties[iProperty].avList.begin();
+						(*i)->alProperties[iProperty].avList.begin();
 
 					for (unsigned int a = 0; a < iNum;++a,++p)
 					{
@@ -717,7 +818,7 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 				if (0xFFFFFFFF != iMaterialIndex)
 				{
 					sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
-						(*i).alProperties[iMaterialIndex].avList.front(),eType2);
+						(*i)->alProperties[iMaterialIndex].avList.front(),eType2);
 				}
 				pvOut->push_back(sFace);
 			}
@@ -726,14 +827,14 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 		{
 			// normally we have only one triangle strip instance where
 			// a value of -1 indicates a restart of the strip
-			for (std::vector<ElementInstance>::const_iterator
+			for (std::vector<ElementInstance*>::const_iterator
 				i =  pcList->alInstances.begin();
 				i != pcList->alInstances.end();++i)
 			{
 				int aiTable[2] = {-1,-1};
 				for (std::list<PLY::PropertyInstance::ValueUnion>::const_iterator 
-					a =  (*i).alProperties[iProperty].avList.begin();
-					a != (*i).alProperties[iProperty].avList.end();++a)
+					a =  (*i)->alProperties[iProperty].avList.begin();
+					a != (*i)->alProperties[iProperty].avList.end();++a)
 				{
 					int p = PLY::PropertyInstance::ConvertTo<int>(*a,eType);
 					if (-1 == p)
@@ -768,10 +869,10 @@ void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
 	return;
 }
 // ------------------------------------------------------------------------------------------------
-void GetMaterialColor(const std::vector<PLY::PropertyInstance>& avList,
-					  unsigned int aiPositions[4], 
-					  PLY::EDataType aiTypes[4],
-					  aiColor4D* clrOut)
+void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avList,
+	unsigned int aiPositions[4], 
+	PLY::EDataType aiTypes[4],
+	 aiColor4D* clrOut)
 {
 	ai_assert(NULL != clrOut);
 
@@ -809,6 +910,8 @@ void GetMaterialColor(const std::vector<PLY::PropertyInstance>& avList,
 // ------------------------------------------------------------------------------------------------
 void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut)
 {
+	ai_assert(NULL != pvOut);
+
 	// diffuse[4], specular[4], ambient[4]
 	// rgba order
 	unsigned int aaiPositions[3][4] = {
@@ -830,98 +933,98 @@ void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut)
 
 	// serach in the DOM for a vertex entry
 	unsigned int _i = 0;
-	for (std::vector<PLY::Element>::const_iterator
+	for (std::vector<PLY::Element*>::const_iterator
 		i =  this->pcDOM->alElements.begin();
 		i != this->pcDOM->alElements.end();++i,++_i)
 	{
-		if (PLY::EEST_Material == (*i).eSemantic)
+		if (PLY::EEST_Material == (*i)->eSemantic)
 		{
-			pcList = &this->pcDOM->alElementData[_i];
+			pcList = this->pcDOM->alElementData[_i];
 
 			// now check whether which coordinate sets are available
 			unsigned int _a = 0;
-			for (std::vector<PLY::Property>::const_iterator
-				a =  (*i).alProperties.begin();
-				a != (*i).alProperties.end();++a,++_a)
+			for (std::vector<PLY::Property*>::const_iterator
+				a =  (*i)->alProperties.begin();
+				a != (*i)->alProperties.end();++a,++_a)
 			{
-				if ((*a).bIsList)continue;
+				if ((*a)->bIsList)continue;
 
 				// pohng specularity      -----------------------------------
-				if (PLY::EST_PhongPower == (*a).Semantic)
+				if (PLY::EST_PhongPower == (*a)->Semantic)
 				{
 					iPhong		= _a;
-					ePhong		= (*a).eType;
+					ePhong		= (*a)->eType;
 				}
 
 				// general opacity        -----------------------------------
-				if (PLY::EST_Opacity == (*a).Semantic)
+				if (PLY::EST_Opacity == (*a)->Semantic)
 				{
 					iOpacity		= _a;
-					eOpacity		= (*a).eType;
+					eOpacity		= (*a)->eType;
 				}
 
 				// diffuse color channels -----------------------------------
-				if (PLY::EST_DiffuseRed == (*a).Semantic)
+				if (PLY::EST_DiffuseRed == (*a)->Semantic)
 				{
 					aaiPositions[0][0]	= _a;
-					aaiTypes[0][0]		= (*a).eType;
+					aaiTypes[0][0]		= (*a)->eType;
 				}
-				else if (PLY::EST_DiffuseGreen == (*a).Semantic)
+				else if (PLY::EST_DiffuseGreen == (*a)->Semantic)
 				{
 					aaiPositions[0][1]	= _a;
-					aaiTypes[0][1]		= (*a).eType;
+					aaiTypes[0][1]		= (*a)->eType;
 				}
-				else if (PLY::EST_DiffuseBlue == (*a).Semantic)
+				else if (PLY::EST_DiffuseBlue == (*a)->Semantic)
 				{
 					aaiPositions[0][2]	= _a;
-					aaiTypes[0][2]		= (*a).eType;
+					aaiTypes[0][2]		= (*a)->eType;
 				}
-				else if (PLY::EST_DiffuseAlpha == (*a).Semantic)
+				else if (PLY::EST_DiffuseAlpha == (*a)->Semantic)
 				{
 					aaiPositions[0][3]	= _a;
-					aaiTypes[0][3]		= (*a).eType;
+					aaiTypes[0][3]		= (*a)->eType;
 				}
 				// specular color channels -----------------------------------
-				else if (PLY::EST_SpecularRed == (*a).Semantic)
+				else if (PLY::EST_SpecularRed == (*a)->Semantic)
 				{
 					aaiPositions[1][0]	= _a;
-					aaiTypes[1][0]		= (*a).eType;
+					aaiTypes[1][0]		= (*a)->eType;
 				}
-				else if (PLY::EST_SpecularGreen == (*a).Semantic)
+				else if (PLY::EST_SpecularGreen == (*a)->Semantic)
 				{
 					aaiPositions[1][1]	= _a;
-					aaiTypes[1][1]		= (*a).eType;
+					aaiTypes[1][1]		= (*a)->eType;
 				}
-				else if (PLY::EST_SpecularBlue == (*a).Semantic)
+				else if (PLY::EST_SpecularBlue == (*a)->Semantic)
 				{
 					aaiPositions[1][2]	= _a;
-					aaiTypes[1][2]		= (*a).eType;
+					aaiTypes[1][2]		= (*a)->eType;
 				}
-				else if (PLY::EST_SpecularAlpha == (*a).Semantic)
+				else if (PLY::EST_SpecularAlpha == (*a)->Semantic)
 				{
 					aaiPositions[1][3]	= _a;
-					aaiTypes[1][3]		= (*a).eType;
+					aaiTypes[1][3]		= (*a)->eType;
 				}
 				// ambient color channels -----------------------------------
-				else if (PLY::EST_AmbientRed == (*a).Semantic)
+				else if (PLY::EST_AmbientRed == (*a)->Semantic)
 				{
 					aaiPositions[2][0]	= _a;
-					aaiTypes[2][0]		= (*a).eType;
+					aaiTypes[2][0]		= (*a)->eType;
 				}
-				else if (PLY::EST_AmbientGreen == (*a).Semantic)
+				else if (PLY::EST_AmbientGreen == (*a)->Semantic)
 				{
 					aaiPositions[2][1]	= _a;
-					aaiTypes[2][1]		= (*a).eType;
+					aaiTypes[2][1]		= (*a)->eType;
 				}
-				else if (PLY::EST_AmbientBlue == (*a).Semantic)
+				else if (PLY::EST_AmbientBlue == (*a)->Semantic)
 				{
 					aaiPositions[22][2]	= _a;
-					aaiTypes[2][2]		= (*a).eType;
+					aaiTypes[2][2]		= (*a)->eType;
 				}
-				else if (PLY::EST_AmbientAlpha == (*a).Semantic)
+				else if (PLY::EST_AmbientAlpha == (*a)->Semantic)
 				{
 					aaiPositions[2][3]	= _a;
-					aaiTypes[2][3]		= (*a).eType;
+					aaiTypes[2][3]		= (*a)->eType;
 				}
 			}
 			break;
@@ -930,7 +1033,7 @@ void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut)
 	// check whether we have a valid source for the material data
 	if (NULL != pcList)
 	{
-		for (std::vector<ElementInstance>::const_iterator
+		for (std::vector<ElementInstance*>::const_iterator
 			i =  pcList->alInstances.begin();
 			i != pcList->alInstances.end();++i)
 		{
@@ -938,15 +1041,15 @@ void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut)
 			MaterialHelper* pcHelper = new MaterialHelper();
 	
 			// build the diffuse material color
-			GetMaterialColor((*i).alProperties,aaiPositions[0],aaiTypes[0],&clrOut);
+			GetMaterialColor((*i)->alProperties,aaiPositions[0],aaiTypes[0],&clrOut);
 			pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_DIFFUSE);
 
 			// build the specular material color
-			GetMaterialColor((*i).alProperties,aaiPositions[1],aaiTypes[1],&clrOut);
+			GetMaterialColor((*i)->alProperties,aaiPositions[1],aaiTypes[1],&clrOut);
 			pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_SPECULAR);
 
 			// build the ambient material color
-			GetMaterialColor((*i).alProperties,aaiPositions[2],aaiTypes[2],&clrOut);
+			GetMaterialColor((*i)->alProperties,aaiPositions[2],aaiTypes[2],&clrOut);
 			pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_AMBIENT);
 
 			// handle phong power and shading mode
@@ -954,7 +1057,7 @@ void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut)
 			if (0xFFFFFFFF != iPhong)
 			{
 				float fSpec = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[iPhong].avList.front(),ePhong);
+					(*i)->alProperties[iPhong].avList.front(),ePhong);
 
 				// if shininess is 0 (and the pow() calculation would therefore always
 				// become 1, not depending on the angle) use gouraud lighting
@@ -962,8 +1065,7 @@ void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut)
 				{
 
 					// scale this with 15 ... hopefully this is correct
-					fSpec += 15;
-
+					fSpec *= 15;
 					pcHelper->AddProperty<float>(&fSpec, 1, AI_MATKEY_SHININESS);
 
 					iMode = (int)aiShadingMode_Phong;
@@ -977,7 +1079,7 @@ void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut)
 			if (0xFFFFFFFF != iOpacity)
 			{
 				float fOpacity = PLY::PropertyInstance::ConvertTo<float>(
-					(*i).alProperties[iPhong].avList.front(),eOpacity);
+					(*i)->alProperties[iPhong].avList.front(),eOpacity);
 
 				pcHelper->AddProperty<float>(&fOpacity, 1, AI_MATKEY_OPACITY);
 			}

+ 137 - 60
code/PlyLoader.h

@@ -1,4 +1,45 @@
-/** @file Definition of the .ply importer class. */
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Declaration of the .ply importer class. */
 #ifndef AI_PLYLOADER_H_INCLUDED
 #define AI_PLYLOADER_H_INCLUDED
 
@@ -11,88 +52,124 @@ struct aiNode;
 
 namespace Assimp
 {
-	class MaterialHelper;
+class MaterialHelper;
 
 
-	using namespace PLY;
+using namespace PLY;
 
-	// ---------------------------------------------------------------------------
-	/** Used to load PLY files
-	*/
-	class PLYImporter : public BaseImporter
+// ---------------------------------------------------------------------------
+/** Used to load PLY files
+*/
+class PLYImporter : public BaseImporter
+{
+	friend class Importer;
+
+protected:
+	/** Constructor to be privately used by Importer */
+	PLYImporter();
+
+	/** Destructor, private as well */
+	~PLYImporter();
+
+public:
+
+	// -------------------------------------------------------------------
+	/** Returns whether the class can handle the format of the given file. 
+	* See BaseImporter::CanRead() for details.	*/
+	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+
+protected:
+
+	// -------------------------------------------------------------------
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 * See BaseImporter::GetExtensionList() for details
+	 */
+	void GetExtensionList(std::string& append)
 	{
-		friend class Importer;
+		append.append("*.ply");
+	}
 
-	protected:
-		/** Constructor to be privately used by Importer */
-		PLYImporter();
+	// -------------------------------------------------------------------
+	/** Imports the given file into the given scene structure. 
+	* See BaseImporter::InternReadFile() for details
+	*/
+	void InternReadFile( const std::string& pFile, aiScene* pScene,
+		IOSystem* pIOHandler);
 
-		/** Destructor, private as well */
-		~PLYImporter();
+protected:
 
-	public:
 
-		// -------------------------------------------------------------------
-		/** Returns whether the class can handle the format of the given file. 
-		* See BaseImporter::CanRead() for details.	*/
-		bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+	// -------------------------------------------------------------------
+	/** Extract vertices from the DOM
+	*/
+	void LoadVertices(std::vector<aiVector3D>* pvOut,
+		bool p_bNormals = false);
 
-	protected:
+	// -------------------------------------------------------------------
+	/** Extract vertex color channels from the DOM
+	*/
+	void LoadVertexColor(std::vector<aiColor4D>* pvOut);
 
-		// -------------------------------------------------------------------
-		/** Imports the given file into the given scene structure. 
-		* See BaseImporter::InternReadFile() for details
-		*/
-		void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+	// -------------------------------------------------------------------
+	/** Extract texture coordinate channels from the DOM
+	*/
+	void LoadTextureCoordinates(std::vector<aiVector2D>* pvOut);
 
-	protected:
+	// -------------------------------------------------------------------
+	/** Extract a face list from the DOM
+	*/
+	void LoadFaces(std::vector<PLY::Face>* pvOut);
 
+	// -------------------------------------------------------------------
+	/** Extract a material list from the DOM
+	*/
+	void LoadMaterial(std::vector<MaterialHelper*>* pvOut);
 
-		// -------------------------------------------------------------------
-		/** Extract vertices from the DOM
-		*/
-		void LoadVertices(std::vector<aiVector3D>* pvOut,bool p_bNormals = false);
 
-		// -------------------------------------------------------------------
-		/** Extract vertex color channels
-		*/
-		void LoadVertexColor(std::vector<aiColor4D>* pvOut);
+	// -------------------------------------------------------------------
+	/** Validate material indices, replace default material identifiers
+	*/
+	void ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
+		std::vector<MaterialHelper*>* avMaterials);
 
-		// -------------------------------------------------------------------
-		/** Extract a face list from the DOM
-		*/
-		void LoadFaces(std::vector<PLY::Face>* pvOut);
 
-		// -------------------------------------------------------------------
-		/** Extract a material list from the DOM
-		*/
-		void LoadMaterial(std::vector<MaterialHelper*>* pvOut);
+	// -------------------------------------------------------------------
+	/** Convert all meshes into our ourer representation
+	*/
+	void ConvertMeshes(std::vector<PLY::Face>* avFaces,
+		const std::vector<aiVector3D>* avPositions,
+		const std::vector<aiVector3D>* avNormals,
+		const std::vector<aiColor4D>* avColors,
+		const std::vector<aiVector2D>* avTexCoords,
+		const std::vector<MaterialHelper*>* avMaterials,
+		std::vector<aiMesh*>* avOut);
 
 
-		// -------------------------------------------------------------------
-		/** Validate material indices, replace default material identifiers
-		*/
-		void ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
-			std::vector<MaterialHelper*>* avMaterials);
+	// -------------------------------------------------------------------
+	/** Static helper to parse a color from four single channels in
+	*/
+	static void GetMaterialColor(
+		const std::vector<PLY::PropertyInstance>& avList,
+		unsigned int aiPositions[4], 
+		PLY::EDataType aiTypes[4],
+		aiColor4D* clrOut);
 
 
-		// -------------------------------------------------------------------
-		/** Convert all meshes into our ourer representation
-		*/
-		void ConvertMeshes(std::vector<PLY::Face>* avFaces,
-			const std::vector<aiVector3D>* avPositions,
-			const std::vector<aiVector3D>* avNormals,
-			const std::vector<aiColor4D>* avColors,
-			const std::vector<MaterialHelper*>* avMaterials,
-			std::vector<aiMesh*>* avOut);
+	// -------------------------------------------------------------------
+	/** Static helper to parse a color channel value. The input value
+	*  is normalized to 0-1.
+	*/
+	static float NormalizeColorValue (
+		PLY::PropertyInstance::ValueUnion val,
+		PLY::EDataType eType);
 
 
-		/** Buffer to hold the loaded file */
-		unsigned char* mBuffer;
+	/** Buffer to hold the loaded file */
+	unsigned char* mBuffer;
 
-		/** Document object model representation extracted from the file */
-		PLY::DOM* pcDOM;
-	};
+	/** Document object model representation extracted from the file */
+	PLY::DOM* pcDOM;
+};
 
 } // end of namespace Assimp
 

+ 138 - 54
code/PlyParser.cpp

@@ -1,4 +1,46 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the PLY parser class */
+
 #include "PLYLoader.h"
 #include "MaterialSystem.h"
 #include "fast_atof.h"
@@ -13,7 +55,6 @@
 
 using namespace Assimp;
 
-
 // ------------------------------------------------------------------------------------------------
 PLY::EDataType PLY::Property::ParseDataType(const char* p_szIn,const char** p_szOut)
 {
@@ -100,22 +141,7 @@ PLY::EDataType PLY::Property::ParseDataType(const char* p_szIn,const char** p_sz
 PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_szOut)
 {
 	PLY::ESemantic eOut = PLY::EST_INVALID;
-	if (0 == ASSIMP_strincmp(p_szIn,"x",1))
-	{
-		p_szIn++;
-		eOut = PLY::EST_XCoord;
-	}
-	else if (0 == ASSIMP_strincmp(p_szIn,"y",1))
-	{
-		p_szIn++;
-		eOut = PLY::EST_YCoord;
-	}
-	else if (0 == ASSIMP_strincmp(p_szIn,"z",1))
-	{
-		p_szIn++;
-		eOut = PLY::EST_ZCoord;
-	}
-	else if (0 == ASSIMP_strincmp(p_szIn,"red",3))
+	if (0 == ASSIMP_strincmp(p_szIn,"red",3))
 	{
 		p_szIn+=3;
 		eOut = PLY::EST_Red;
@@ -235,6 +261,41 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_sz
 		p_szIn++;
 		eOut = PLY::EST_Blue;
 	}
+	else if (0 == ASSIMP_strincmp(p_szIn,"tx",2))
+	{
+		p_szIn+=2;
+		eOut = PLY::EST_UTextureCoord;
+	}
+	else if (0 == ASSIMP_strincmp(p_szIn,"ty",2))
+	{
+		p_szIn+=2;
+		eOut = PLY::EST_VTextureCoord;
+	}
+	else if (0 == ASSIMP_strincmp(p_szIn,"u",1))
+	{
+		p_szIn++;
+		eOut = PLY::EST_UTextureCoord;
+	}
+	else if (0 == ASSIMP_strincmp(p_szIn,"v",1))
+	{
+		p_szIn++;
+		eOut = PLY::EST_VTextureCoord;
+	}
+	else if (0 == ASSIMP_strincmp(p_szIn,"x",1))
+	{
+		p_szIn++;
+		eOut = PLY::EST_XCoord;
+	}
+	else if (0 == ASSIMP_strincmp(p_szIn,"y",1))
+	{
+		p_szIn++;
+		eOut = PLY::EST_YCoord;
+	}
+	else if (0 == ASSIMP_strincmp(p_szIn,"z",1))
+	{
+		p_szIn++;
+		eOut = PLY::EST_ZCoord;
+	}
 	else
 	{
 		// ... find the next space or new line
@@ -250,7 +311,9 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_sz
 	return eOut;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::Property::ParseProperty (const char* p_szIn, const char** p_szOut, PLY::Property* pOut)
+bool PLY::Property::ParseProperty (const char* p_szIn,
+	const char** p_szOut,
+	PLY::Property* pOut)
 {
 	// Forms supported:
 	// "property float x"
@@ -320,7 +383,8 @@ bool PLY::Property::ParseProperty (const char* p_szIn, const char** p_szOut, PLY
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
-PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn,const char** p_szOut)
+PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn,
+	const char** p_szOut)
 {
 	PLY::EElementSemantic eOut = PLY::EEST_INVALID;
 	if (0 == ASSIMP_strincmp(p_szIn,"vertex",6))
@@ -365,8 +429,9 @@ PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn,const char*
 	return eOut;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::Element::ParseElement (const char* p_szIn, const char** p_szOut,
-								 PLY::Element* pOut)
+bool PLY::Element::ParseElement (const char* p_szIn, 
+	const char** p_szOut,
+	PLY::Element* pOut)
 {
 	// Example format: "element vertex 8"
 	*p_szOut = p_szIn;
@@ -410,8 +475,8 @@ bool PLY::Element::ParseElement (const char* p_szIn, const char** p_szOut,
 		// skip all comments
 		PLY::DOM::SkipComments(p_szIn,&p_szIn);
 
-		Property prop;
-		if(!PLY::Property::ParseProperty(p_szIn,&p_szIn,&prop))break;
+		PLY::Property* prop = new PLY::Property();
+		if(!PLY::Property::ParseProperty(p_szIn,&p_szIn,prop))break;
 
 		// add the property to the property list
 		pOut->alProperties.push_back(prop);
@@ -420,7 +485,8 @@ bool PLY::Element::ParseElement (const char* p_szIn, const char** p_szOut,
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::DOM::SkipComments (const char* p_szIn,const char** p_szOut)
+bool PLY::DOM::SkipComments (const char* p_szIn,
+	const char** p_szOut)
 {
 	*p_szOut = p_szIn;
 
@@ -451,8 +517,8 @@ bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut)
 		// skip all comments
 		PLY::DOM::SkipComments(p_szIn,&p_szIn);
 
-		Element out;
-		if(PLY::Element::ParseElement(p_szIn,&p_szIn,&out))
+		PLY::Element* out = new PLY::Element();
+		if(PLY::Element::ParseElement(p_szIn,&p_szIn,out))
 		{
 			// add the element to the list of elements
 			this->alElements.push_back(out);
@@ -470,34 +536,39 @@ bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut)
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseElementInstanceLists (const char* p_szIn,const char** p_szOut)
+bool PLY::DOM::ParseElementInstanceLists (
+	const char* p_szIn,
+	const char** p_szOut)
 {
 	this->alElementData.resize(this->alElements.size());
 
-	std::vector<PLY::Element>::const_iterator i			=  this->alElements.begin();
-	std::vector<PLY::ElementInstanceList>::iterator a	=  this->alElementData.begin();
+	std::vector<PLY::Element*>::const_iterator i = this->alElements.begin();
+	std::vector<PLY::ElementInstanceList*>::iterator a = this->alElementData.begin();
 
 	// parse all element instances
 	for (;i != this->alElements.end();++i,++a)
 	{
-		*a = PLY::ElementInstanceList(&(*i)); // reserve enough storage
-		PLY::ElementInstanceList::ParseInstanceList(p_szIn,&p_szIn,&(*i),&(*a));
+		*a = new PLY::ElementInstanceList((*i)); // reserve enough storage
+		PLY::ElementInstanceList::ParseInstanceList(p_szIn,&p_szIn,(*i),(*a));
 	}
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseElementInstanceListsBinary (const char* p_szIn,const char** p_szOut,bool p_bBE)
+bool PLY::DOM::ParseElementInstanceListsBinary (
+	const char* p_szIn,
+	const char** p_szOut,
+	bool p_bBE)
 {
 	this->alElementData.resize(this->alElements.size());
 
-	std::vector<PLY::Element>::const_iterator i			=  this->alElements.begin();
-	std::vector<PLY::ElementInstanceList>::iterator a	=  this->alElementData.begin();
+	std::vector<PLY::Element*>::const_iterator i = this->alElements.begin();
+	std::vector<PLY::ElementInstanceList*>::iterator a = this->alElementData.begin();
 
 	// parse all element instances
 	for (;i != this->alElements.end();++i,++a)
 	{
-		*a = PLY::ElementInstanceList(&(*i)); // reserve enough storage
-		PLY::ElementInstanceList::ParseInstanceListBinary(p_szIn,&p_szIn,&(*i),&(*a),p_bBE);
+		*a = new PLY::ElementInstanceList((*i)); // reserve enough storage
+		PLY::ElementInstanceList::ParseInstanceListBinary(p_szIn,&p_szIn,(*i),(*a),p_bBE);
 	}
 	return true;
 }
@@ -549,8 +620,8 @@ bool PLY::ElementInstanceList::ParseInstanceList (const char* p_szIn,const char*
 		{
 			PLY::DOM::SkipComments(p_szIn,&p_szIn);
 
-			PLY::ElementInstance out;
-			PLY::ElementInstance::ParseInstance(p_szIn, &p_szIn,pcElement, &out);
+			PLY::ElementInstance* out = new PLY::ElementInstance();
+			PLY::ElementInstance::ParseInstance(p_szIn, &p_szIn,pcElement, out);
 			// add it to the list
 			p_pcOut->alInstances[i] = out;
 		}
@@ -559,8 +630,12 @@ bool PLY::ElementInstanceList::ParseInstanceList (const char* p_szIn,const char*
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstanceList::ParseInstanceListBinary (const char* p_szIn,const char** p_szOut,
-	 const PLY::Element* pcElement, PLY::ElementInstanceList* p_pcOut,bool p_bBE)
+bool PLY::ElementInstanceList::ParseInstanceListBinary (
+	const char* p_szIn,
+	const char** p_szOut,
+	const PLY::Element* pcElement,
+	PLY::ElementInstanceList* p_pcOut,
+	bool p_bBE /* = false */)
 {
 	// we can add special handling code for unknown element semantics since
 	// we can't skip it as a whole block (we don't know its exact size
@@ -568,8 +643,8 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary (const char* p_szIn,const
 	// of the unknown element)
 	for (unsigned int i = 0; i < pcElement->NumOccur;++i)
 	{
-		PLY::ElementInstance out;
-		PLY::ElementInstance::ParseInstanceBinary(p_szIn, &p_szIn,pcElement, &out, p_bBE);
+		PLY::ElementInstance* out = new PLY::ElementInstance();
+		PLY::ElementInstance::ParseInstanceBinary(p_szIn, &p_szIn,pcElement, out, p_bBE);
 		// add it to the list
 		p_pcOut->alInstances[i] = out;
 	}
@@ -577,24 +652,28 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary (const char* p_szIn,const
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstance::ParseInstance (const char* p_szIn,const char** p_szOut,
-	const PLY::Element* pcElement, PLY::ElementInstance* p_pcOut)
+bool PLY::ElementInstance::ParseInstance (
+	const char* p_szIn,
+	const char** p_szOut,
+	const PLY::Element* pcElement,
+	PLY::ElementInstance* p_pcOut)
 {
 	if (!SkipSpaces(p_szIn, &p_szIn))return false;
 
+	// allocate enough storage
 	p_pcOut->alProperties.resize(pcElement->alProperties.size());
 
 	*p_szOut = p_szIn;
-	std::vector<PLY::PropertyInstance>::iterator		i =  p_pcOut->alProperties.begin();
-	std::vector<PLY::Property>::const_iterator			a =  pcElement->alProperties.begin();
+	std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
+	std::vector<PLY::Property*>::const_iterator a = pcElement->alProperties.begin();
 	for (;i != p_pcOut->alProperties.end();++i,++a)
 	{
-		if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,&(*a),&(*i))))
+		if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,(*a),&(*i))))
 		{
 			// skip the rest of the instance
 			SkipLine(p_szIn, &p_szIn);
 
-			PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType);
+			PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a)->eType);
 			(*i).avList.push_back(v);
 		}
 	}
@@ -602,19 +681,24 @@ bool PLY::ElementInstance::ParseInstance (const char* p_szIn,const char** p_szOu
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstance::ParseInstanceBinary (const char* p_szIn,const char** p_szOut,
-	const PLY::Element* pcElement, PLY::ElementInstance* p_pcOut, bool p_bBE)
+bool PLY::ElementInstance::ParseInstanceBinary (
+	const char* p_szIn,
+	const char** p_szOut,
+	const PLY::Element* pcElement,
+	PLY::ElementInstance* p_pcOut,
+	bool p_bBE /* = false */)
 {
+	// allocate enough storage
 	p_pcOut->alProperties.resize(pcElement->alProperties.size());
 
 	*p_szOut = p_szIn;
-	std::vector<PLY::PropertyInstance>::iterator		i =  p_pcOut->alProperties.begin();
-	std::vector<PLY::Property>::const_iterator			a =  pcElement->alProperties.begin();
+	std::vector<PLY::PropertyInstance>::iterator i =  p_pcOut->alProperties.begin();
+	std::vector<PLY::Property*>::const_iterator a =  pcElement->alProperties.begin();
 	for (;i != p_pcOut->alProperties.end();++i,++a)
 	{
-		if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,&(*a),&(*i))))
+		if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,(*a),&(*i))))
 		{
-			PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType);
+			PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a)->eType);
 			(*i).avList.push_back(v);
 		}
 	}

+ 136 - 21
code/PlyParser.h

@@ -1,3 +1,44 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 helper data structures for importing PLY files  */
 #ifndef AI_PLYFILEHELPER_H_INC
 #define AI_PLYFILEHELPER_H_INC
@@ -54,9 +95,9 @@ enum EDataType
 };
 
 // ---------------------------------------------------------------------------------
-/**	\brief Specifies semantics for PLY element properties
+/** \brief Specifies semantics for PLY element properties
  *
- *	Semantics define the usage of a property, e.g. x coordinate
+ * Semantics define the usage of a property, e.g. x coordinate
 */
 enum ESemantic
 {
@@ -73,6 +114,11 @@ enum ESemantic
 	EST_YNormal,
 	//! vertex normal z coordinate
 	EST_ZNormal,
+
+	//! u texture coordinate
+	EST_UTextureCoord,
+	//! v texture coordinate
+	EST_VTextureCoord,
 	
 	//! vertex colors, red channel
 	EST_Red,		
@@ -133,9 +179,9 @@ enum ESemantic
 };
 
 // ---------------------------------------------------------------------------------
-/**	\brief Specifies semantics for PLY elements
+/** \brief Specifies semantics for PLY elements
  *
- *	Semantics define the usage of an element, e.g. vertex or material
+ * Semantics define the usage of an element, e.g. vertex or material
 */
 enum EElementSemantic
 {
@@ -159,9 +205,9 @@ enum EElementSemantic
 };
 
 // ---------------------------------------------------------------------------------
-/**	\brief Helper class for a property in a PLY file.
+/** \brief Helper class for a property in a PLY file.
  *
- *	This can e.g. be a part of the vertex declaration
+ * This can e.g. be a part of the vertex declaration
  */
 class Property
 {
@@ -187,6 +233,7 @@ public:
 	bool bIsList;
 	EDataType eFirstType;
 
+	// -------------------------------------------------------------------
 	//! Parse a property from a string. The end of the
 	//! string is either '\n', '\r' or '\0'. Return valie is false
 	//! if the input string is NOT a valid property (E.g. does
@@ -194,18 +241,20 @@ public:
 	static bool ParseProperty (const char* p_szIn, const char** p_szOut, 
 		Property* pOut);
 
+	// -------------------------------------------------------------------
 	//! Parse a data type from a string
 	static EDataType ParseDataType(const char* p_szIn,const char** p_szOut);
 
+	// -------------------------------------------------------------------
 	//! Parse a semantic from a string
 	static ESemantic ParseSemantic(const char* p_szIn,const char** p_szOut);
 };
 
 // ---------------------------------------------------------------------------------
-/**	\brief Helper class for an element in a PLY file.
+/** \brief Helper class for an element in a PLY file.
  *
- *	This can e.g. be the vertex declaration. Elements contain a
- *	well-defined number of properties.
+ * This can e.g. be the vertex declaration. Elements contain a
+ * well-defined number of properties.
  */
 class Element
 {
@@ -216,9 +265,22 @@ public:
 		: NumOccur(0), eSemantic (EEST_INVALID)
 	{}
 
+	//! Destructor. Dallocates all storage
+	~Element()
+	{
+		// delete all elements
+		for (std::vector<Property*>::const_iterator
+			i =  this->alProperties.begin();
+			i != this->alProperties.end();++i)
+		{
+			delete (*i);
+		}
+		return;
+	}
+
 	//! List of properties assigned to the element
 	//! std::vector to support operator[]
-	std::vector<Property> alProperties;
+	std::vector<Property*> alProperties;
 
 	//! Semantic of the element
 	EElementSemantic eSemantic;
@@ -230,19 +292,22 @@ public:
 	//! How many times will the element occur?
 	unsigned int NumOccur;
 
+
+	// -------------------------------------------------------------------
 	//! Parse an element from a string. 
 	//! The function will parse all properties contained in the
 	//! element, too.
 	static bool ParseElement (const char* p_szIn, const char** p_szOut, 
 		Element* pOut);
 
+	// -------------------------------------------------------------------
 	//! Parse a semantic from a string
 	static EElementSemantic ParseSemantic(const char* p_szIn,
 		const char** p_szOut);
 };
 
 // ---------------------------------------------------------------------------------
-/**	\brief Instance of a property in a PLY file
+/** \brief Instance of a property in a PLY file
  */
 class PropertyInstance 
 {
@@ -271,36 +336,43 @@ public:
 
 	};
 
+	// -------------------------------------------------------------------
 	//! List of all values parsed. Contains only one value
 	// for non-list propertys
 	std::list<ValueUnion> avList;
 
+	// -------------------------------------------------------------------
 	//! Parse a property instance 
 	static bool ParseInstance (const char* p_szIn,const char** p_szOut,
 		const Property* prop, PropertyInstance* p_pcOut);
 
+	// -------------------------------------------------------------------
 	//! Parse a property instance in binary format
 	static bool ParseInstanceBinary (const char* p_szIn,const char** p_szOut,
 		const Property* prop, PropertyInstance* p_pcOut,bool p_bBE);
 
+	// -------------------------------------------------------------------
 	//! Get the default value for a given data type
 	static ValueUnion DefaultValue(EDataType eType);
 
+	// -------------------------------------------------------------------
 	//! Parse a value
 	static bool ParseValue(const char* p_szIn,const char** p_szOut,
 		EDataType eType,ValueUnion* out);
 
+	// -------------------------------------------------------------------
 	//! Parse a binary value
 	static bool ParseValueBinary(const char* p_szIn,const char** p_szOut,
 		EDataType eType,ValueUnion* out,bool p_bBE);
 
+	// -------------------------------------------------------------------
 	//! Convert a property value to a given type TYPE
 	template <typename TYPE>
 	static TYPE ConvertTo(ValueUnion v, EDataType eType);
 };
 
 // ---------------------------------------------------------------------------------
-/**	\brief Class for an element instance in a PLY file
+/** \brief Class for an element instance in a PLY file
  */
 class ElementInstance 
 {
@@ -313,17 +385,19 @@ public:
 	//! List of all parsed properties
 	std::vector< PropertyInstance > alProperties;
 
+	// -------------------------------------------------------------------
 	//! Parse an element instance
 	static bool ParseInstance (const char* p_szIn,const char** p_szOut,
 		const Element* pcElement, ElementInstance* p_pcOut);
 
+	// -------------------------------------------------------------------
 	//! Parse a binary element instance
 	static bool ParseInstanceBinary (const char* p_szIn,const char** p_szOut,
 		const Element* pcElement, ElementInstance* p_pcOut,bool p_bBE);
 };
 
 // ---------------------------------------------------------------------------------
-/**	\brief Class for an element instance list in a PLY file
+/** \brief Class for an element instance list in a PLY file
  */
 class ElementInstanceList 
 {
@@ -333,25 +407,42 @@ public:
 	ElementInstanceList ()
 	{}
 
+	//! Construction from a given element description
 	ElementInstanceList (const Element* pc)
 	{
+		// reserve enough storage to speedup the process
 		alInstances.reserve(pc->NumOccur);
 	}
 
+	//! Destructor. Dallocates all storage
+	~ElementInstanceList()
+	{
+		// delete all elements
+		for (std::vector<ElementInstance*>::const_iterator
+			i =  this->alInstances.begin();
+			i != this->alInstances.end();++i)
+		{
+			delete (*i);
+		}
+		return;
+	}
+
 	//! List of all element instances
-	std::vector< ElementInstance > alInstances;
+	std::vector< ElementInstance* > alInstances;
 
+	// -------------------------------------------------------------------
 	//! Parse an element instance list
 	static bool ParseInstanceList (const char* p_szIn,const char** p_szOut,
 		const Element* pcElement, ElementInstanceList* p_pcOut);
 
+	// -------------------------------------------------------------------
 	//! Parse a binary element instance list
 	static bool ParseInstanceListBinary (const char* p_szIn,const char** p_szOut,
 		const Element* pcElement, ElementInstanceList* p_pcOut,bool p_bBE);
 };
 // ---------------------------------------------------------------------------------
-/**	\brief Class to represent the document object model of an ASCII or binary 
- *		  (both little and big-endian) PLY file
+/** \brief Class to represent the document object model of an ASCII or binary 
+ * (both little and big-endian) PLY file
  */
 class DOM
 {
@@ -361,9 +452,30 @@ public:
 	DOM()
 	{}
 
+	//! Destructor. Dallocates all storage
+	~DOM()
+	{
+		// delete all elements
+		for (std::vector<Element*>::const_iterator
+			i =  this->alElements.begin();
+			i != this->alElements.end();++i)
+		{
+			delete (*i);
+		}
+		// delete all instance lists
+		for (std::vector<ElementInstanceList*>::const_iterator
+			i =  this->alElementData.begin();
+			i != this->alElementData.end();++i)
+		{
+			delete (*i);
+		}
+		return;
+	}
 
-	std::vector<Element> alElements;
-	std::vector<ElementInstanceList> alElementData;
+	//! Contains all elements of the file format
+	std::vector<Element*> alElements;
+	//! Contains the real data of each element's instance list
+	std::vector<ElementInstanceList*> alElementData;
 
 	//! Parse the DOM for a PLY file. The input string is assumed
 	//! to be terminated with zero
@@ -376,19 +488,22 @@ public:
 
 private:
 
+	// -------------------------------------------------------------------
 	//! Handle the file header and read all element descriptions
 	bool ParseHeader (const char* p_szIn,const char** p_szOut);
 
+	// -------------------------------------------------------------------
 	//! Read in all element instance lists
 	bool ParseElementInstanceLists (const char* p_szIn,const char** p_szOut);
 
+	// -------------------------------------------------------------------
 	//! Read in all element instance lists for a binary file format
 	bool ParseElementInstanceListsBinary (const char* p_szIn,
 		const char** p_szOut,bool p_bBE);
 };
 
 // ---------------------------------------------------------------------------------
-/**	\brief Helper class to represent a loaded face
+/** \brief Helper class to represent a loaded PLY face
  */
 class Face
 {
@@ -434,6 +549,8 @@ TYPE PLY::PropertyInstance::ConvertTo(
 	};
 	return (TYPE)0;
 }
+};
+
 // ---------------------------------------------------------------------------------
 inline bool IsSpace( const char in)
 {
@@ -476,8 +593,6 @@ inline void SkipSpacesAndLineEnd( const char* in, const char** out)
 	while (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n')in++;
 	*out = in;
 }
-
-};
 };
 
 #endif // !! include guard

+ 41 - 0
code/SpatialSort.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the helper class to quickly find vertices close to a given position */
 #include <algorithm>
 #include "SpatialSort.h"

+ 40 - 0
code/SpatialSort.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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.
+
+----------------------------------------------------------------------
+*/
+
 /** Small helper classes to optimise finding vertizes close to a given location */
 #ifndef AI_SPATIALSORT_H_INC
 #define AI_SPATIALSORT_H_INC

+ 315 - 26
code/SplitLargeMeshes.cpp

@@ -1,3 +1,44 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the SplitLargeMeshes postprocessing step
 */
 #include "SplitLargeMeshes.h"
@@ -7,27 +48,56 @@
 
 using namespace Assimp;
 
-// Constructor to be privately used by Importer
-SplitLargeMeshesProcess::SplitLargeMeshesProcess()
+/*static*/ unsigned int SplitLargeMeshesProcess_Triangle::LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES;
+/*static*/ unsigned int SplitLargeMeshesProcess_Vertex::LIMIT = AI_SLM_DEFAULT_MAX_VERTICES;
+
+extern "C" {
+
+// ------------------------------------------------------------------------------------------------
+aiReturn aiSetVertexSplitLimit(unsigned int pLimit)
+{
+	if (0 == pLimit)
 	{
+		SplitLargeMeshesProcess_Vertex::LIMIT = 0xFFFFFFFF;
+		return AI_FAILURE;
 	}
 
-// Destructor, private as well
-SplitLargeMeshesProcess::~SplitLargeMeshesProcess()
+	SplitLargeMeshesProcess_Vertex::LIMIT = pLimit;
+	return AI_SUCCESS;
+}
+// ------------------------------------------------------------------------------------------------
+aiReturn aiSetTriangleSplitLimit(unsigned int pLimit)
+{
+	if (0 == pLimit)
 	{
-	// nothing to do here
+		SplitLargeMeshesProcess_Triangle::LIMIT = 0xFFFFFFFF;
+		return AI_FAILURE;
 	}
 
+	SplitLargeMeshesProcess_Triangle::LIMIT = pLimit;
+	return AI_SUCCESS;
+}
+}; //! extern "C"
+
+// ------------------------------------------------------------------------------------------------
+SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle()
+	{
+		// nothing to do here
+	}
+// ------------------------------------------------------------------------------------------------
+SplitLargeMeshesProcess_Triangle::~SplitLargeMeshesProcess_Triangle()
+	{
+	// nothing to do here
+	}
 // ------------------------------------------------------------------------------------------------
 // Returns whether the processing step is present in the given flag field.
-bool SplitLargeMeshesProcess::IsActive( unsigned int pFlags) const
+bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const
 {
-	return (pFlags & aiProcess_SplitLargeMeshes) != 0;
+	return (pFlags & aiProcess_SplitLargeMeshes) != 0 && (0xFFFFFFFF != LIMIT);
 }
-
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
-void SplitLargeMeshesProcess::Execute( aiScene* pScene)
+void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene)
 {
 	std::vector<std::pair<aiMesh*, unsigned int> > avList;
 
@@ -51,12 +121,10 @@ void SplitLargeMeshesProcess::Execute( aiScene* pScene)
 }
 // ------------------------------------------------------------------------------------------------
 // Update a node after some meshes have been split
-void SplitLargeMeshesProcess::UpdateNode(aiNode* pcNode,
+void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode,
 	const std::vector<std::pair<aiMesh*, unsigned int> >& avList)
 {
 	// for every index in out list build a new entry
-	// TODO: Currently O(n^2)
-
 	std::vector<unsigned int> aiEntries;
 	aiEntries.reserve(pcNode->mNumMeshes + 1);
 	for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
@@ -81,25 +149,22 @@ void SplitLargeMeshesProcess::UpdateNode(aiNode* pcNode,
 	// recusively update all other nodes
 	for (unsigned int i = 0; i < pcNode->mNumChildren;++i)
 	{
-		this->UpdateNode ( pcNode->mChildren[i], avList );
+		UpdateNode ( pcNode->mChildren[i], avList );
 	}
 	return;
 }
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
-void SplitLargeMeshesProcess::SplitMesh(
+void SplitLargeMeshesProcess_Triangle::SplitMesh(
 	unsigned int a,
 	aiMesh* pMesh,
 	std::vector<std::pair<aiMesh*, unsigned int> >& avList)
 {
-	// TODO: Mesh splitting is currently not supported for meshes
-	// containing bones
-
-	if (pMesh->mNumVertices > AI_SLM_MAX_VERTICES && 0 == pMesh->mNumBones)
+	if (pMesh->mNumFaces > LIMIT)
 	{
 		// we need to split this mesh into sub meshes
 		// determine the size of a submesh
-		const unsigned int iSubMeshes = (pMesh->mNumVertices / AI_SLM_MAX_VERTICES) + 1;
+		const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1;
 
 		const unsigned int iOutFaceNum = pMesh->mNumFaces / iSubMeshes;
 		const unsigned int iOutVertexNum = iOutFaceNum * 3;
@@ -162,19 +227,25 @@ void SplitLargeMeshesProcess::SplitMesh(
 			}
 
 			// (we will also need to copy the array of indices)
+			unsigned int iCurrent = 0;
 			for (unsigned int p = 0; p < pcMesh->mNumFaces;++p)
 			{
 				pcMesh->mFaces[p].mNumIndices = 3;
-
 				// allocate a new array
-				unsigned int* pi = pMesh->mFaces[p + iBase].mIndices;
-				pcMesh->mFaces[p].mIndices = new unsigned int[3];
+				const unsigned int iTemp = p + iBase;
+				const unsigned int iNumIndices = pMesh->mFaces[iTemp].mNumIndices;
+
+				// setup face type and number of indices
+				pcMesh->mFaces[p].mNumIndices = iNumIndices;
+				unsigned int* pi = pMesh->mFaces[iTemp].mIndices;
+
+				pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices];
 
 				// and copy the contents of the old array, offset by current base
-				for (unsigned int v = 0; v < 3;++v)
+				for (unsigned int v = 0; v < iNumIndices;++v)
 				{
-					unsigned int iIndex = pMesh->mFaces[p+iBase].mIndices[v];
-					unsigned int iIndexOut = p*3 + v;
+					unsigned int iIndex = pMesh->mFaces[iTemp].mIndices[v];
+					unsigned int iIndexOut = iCurrent++;
 					pcMesh->mFaces[p].mIndices[v] = iIndexOut;
 
 					// copy positions
@@ -224,4 +295,222 @@ void SplitLargeMeshesProcess::SplitMesh(
 	}
 	else avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
 	return;
-}
+}
+// ------------------------------------------------------------------------------------------------
+SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex()
+	{
+		// nothing to do here
+	}
+// ------------------------------------------------------------------------------------------------
+SplitLargeMeshesProcess_Vertex::~SplitLargeMeshesProcess_Vertex()
+	{
+	// nothing to do here
+	}
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool SplitLargeMeshesProcess_Vertex::IsActive( unsigned int pFlags) const
+{
+	return (pFlags & aiProcess_SplitLargeMeshes) != 0 && (0xFFFFFFFF != LIMIT);
+}
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene)
+{
+	std::vector<std::pair<aiMesh*, unsigned int> > avList;
+
+	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+		this->SplitMesh(a, pScene->mMeshes[a],avList);
+
+	if (avList.size() != pScene->mNumMeshes)
+	{
+		// it seems something has been splitted. rebuild the mesh list
+		delete[] pScene->mMeshes;
+		pScene->mNumMeshes = avList.size();
+		pScene->mMeshes = new aiMesh*[avList.size()];
+
+		for (unsigned int i = 0; i < avList.size();++i)
+			pScene->mMeshes[i] = avList[i].first;
+
+		// now we need to update all nodes
+		SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList);
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void SplitLargeMeshesProcess_Vertex::SplitMesh(
+	unsigned int a,
+	aiMesh* pMesh,
+	std::vector<std::pair<aiMesh*, unsigned int> >& avList)
+{
+	if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT)
+	{
+		// we need to split this mesh into sub meshes
+		// determine the estimated size of a submesh
+		// (this could be too large. Max waste is a single digit percentage)
+		const unsigned int iSubMeshes = (pMesh->mNumVertices / SplitLargeMeshesProcess_Vertex::LIMIT) + 1;
+		const unsigned int iOutVertexNum2 = pMesh->mNumVertices /iSubMeshes;
+
+		// create a std::vector<unsigned int> to indicate which vertices
+		// have already been copied
+		std::vector<unsigned int> avWasCopied;
+		avWasCopied.resize(pMesh->mNumVertices,0xFFFFFFFF);
+
+		// try to find a good estimate for the number of output faces
+		// per mesh. Add 12.5% as buffer
+		unsigned int iEstimatedSize = pMesh->mNumFaces / iSubMeshes;
+		iEstimatedSize += iEstimatedSize >> 3;
+
+		// now generate all submeshes
+		unsigned int iBase = 0;
+		while (true)
+		{
+			const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT;
+
+			aiMesh* pcMesh			= new aiMesh;			
+			pcMesh->mNumVertices	= 0;
+			pcMesh->mMaterialIndex	= pMesh->mMaterialIndex;
+
+			// clear the temporary helper array
+			if (0 != iBase)
+			{
+				memset(&avWasCopied[0],0xFF,pMesh->mNumVertices * sizeof(unsigned int));
+			}
+
+			// output vectors
+			std::vector<aiFace> vFaces;
+
+			// reserve enough storage for most cases
+			if (pMesh->HasPositions())
+			{
+				pcMesh->mVertices = new aiVector3D[iOutVertexNum];
+			}
+			if (pMesh->HasNormals())
+			{
+				pcMesh->mNormals = new aiVector3D[iOutVertexNum];
+			}
+			if (pMesh->HasTangentsAndBitangents())
+			{
+				pcMesh->mTangents = new aiVector3D[iOutVertexNum];
+				pcMesh->mBitangents = new aiVector3D[iOutVertexNum];
+			}
+			for (unsigned int c = 0; pMesh->HasVertexColors(c);++c)
+			{
+				pcMesh->mColors[c] = new aiColor4D[iOutVertexNum];
+			}
+			for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c)
+			{
+				pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
+				pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum];
+			}
+			vFaces.reserve(iEstimatedSize);
+
+			// (we will also need to copy the array of indices)
+			while (iBase < pMesh->mNumFaces)
+			{
+				// allocate a new array
+				const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices;
+
+				// doesn't catch degenerates but is quite fast
+				unsigned int iNeed = 0;
+				for (unsigned int v = 0; v < iNumIndices;++v)
+				{
+					unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
+
+					// check whether we do already have this vertex
+					if (0xFFFFFFFF == avWasCopied[iIndex])
+					{
+						iNeed++; 
+					}
+				}
+				if (pcMesh->mNumVertices + iNeed > iOutVertexNum)
+				{
+					// don't use this face
+					break;
+				}
+
+				vFaces.push_back(aiFace());
+				aiFace& rFace = vFaces.back();
+
+				// setup face type and number of indices
+				rFace.mNumIndices = iNumIndices;
+				rFace.mIndices = new unsigned int[iNumIndices];
+
+				// and copy the contents of the old array, offset by current base
+				for (unsigned int v = 0; v < iNumIndices;++v)
+				{
+					unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
+
+					// check whether we do already have this vertex
+					if (0xFFFFFFFF != avWasCopied[iIndex])
+					{
+						rFace.mIndices[v] = avWasCopied[iIndex];
+						continue;
+					}
+
+					// copy positions
+					pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]);
+
+					// copy normals
+					if (pMesh->HasNormals())
+					{
+						pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]);
+					}
+
+					// copy tangents/bitangents
+					if (pMesh->HasTangentsAndBitangents())
+					{
+						pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]);
+						pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]);
+					}
+
+					// texture coordinates
+					for (unsigned int c = 0;  c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+					{
+						if (pMesh->HasTextureCoords( c))
+						{
+							pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex];
+						}
+					}
+					// vertex colors 
+					for (unsigned int c = 0;  c < AI_MAX_NUMBER_OF_COLOR_SETS;++c)
+					{
+						if (pMesh->HasVertexColors( c))
+						{
+							pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex];
+						}
+					}
+					rFace.mIndices[v] = pcMesh->mNumVertices;
+					avWasCopied[iIndex] = pcMesh->mNumVertices;
+					pcMesh->mNumVertices++;
+				}
+				iBase++;
+				if(pcMesh->mNumVertices == iOutVertexNum)
+				{
+					// break here. The face is only added if it was complete
+					break;
+				}
+			}
+			// copy the face list to the mesh
+			pcMesh->mFaces = new aiFace[vFaces.size()];
+			pcMesh->mNumFaces = vFaces.size();
+
+			for (unsigned int p = 0; p < pcMesh->mNumFaces;++p)
+				pcMesh->mFaces[p] = vFaces[p];
+
+			// add the newly created mesh to the list
+			avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
+
+			if (iBase == pMesh->mNumFaces)
+			{
+				// have all faces ... finish the outer loop, too
+				break;
+			}
+		}
+
+		// now delete the old mesh data
+		delete pMesh;
+	}
+	else avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
+	return;
+}

+ 110 - 8
code/SplitLargeMeshes.h

@@ -1,4 +1,45 @@
-/** @file Defines a post processing step to split large meshes into submeshes*/
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 a post processing step to split large meshes into submeshes
+ */
 #ifndef AI_SPLITLARGEMESHES_H_INC
 #define AI_SPLITLARGEMESHES_H_INC
 
@@ -10,21 +51,32 @@
 namespace Assimp
 {
 
-#define AI_SLM_MAX_VERTICES	1000000
+class SplitLargeMeshesProcess_Triangle; 
+class SplitLargeMeshesProcess_Vertex; 
+
+// default limit for vertices
+#define AI_SLM_DEFAULT_MAX_VERTICES		1000000
+
+// default limit for triangles
+#define AI_SLM_DEFAULT_MAX_TRIANGLES	1000000
 
 // ---------------------------------------------------------------------------
 /** Postprocessing filter to split large meshes into submeshes
+ *
+ * Applied BEFORE the JoinVertices-Step occurs.
+ * Returns NON-UNIQUE vertices, splits by triangle number.
 */
-class SplitLargeMeshesProcess : public BaseProcess
+class SplitLargeMeshesProcess_Triangle : public BaseProcess
 {
 	friend class Importer;
+	friend class SplitLargeMeshesProcess_Vertex;
 
 protected:
 	/** Constructor to be privately used by Importer */
-	SplitLargeMeshesProcess();
+	SplitLargeMeshesProcess_Triangle();
 
 	/** Destructor, private as well */
-	~SplitLargeMeshesProcess();
+	~SplitLargeMeshesProcess_Triangle();
 
 public:
 	// -------------------------------------------------------------------
@@ -49,10 +101,60 @@ private:
 	void SplitMesh (unsigned int a, aiMesh* pcMesh,
 		std::vector<std::pair<aiMesh*, unsigned int> >& avList);
 
-	//! Update a node in the asset after a few of its meshes
-	//! have been split
-	void UpdateNode(aiNode* pcNode,
+	//! Update a node in the asset after a few of its meshes have been split
+	static void UpdateNode(aiNode* pcNode,
 		const std::vector<std::pair<aiMesh*, unsigned int> >& avList);
+
+public:
+	//! Triangle limit set via aiSetTriangleSplitLimit()
+	static unsigned int LIMIT;
+};
+
+
+// ---------------------------------------------------------------------------
+/** Postprocessing filter to split large meshes into submeshes
+ *
+ * Applied AFTER the JoinVertices-Step occurs.
+ * Returns UNIQUE vertices, splits by vertex number.
+*/
+class SplitLargeMeshesProcess_Vertex : public BaseProcess
+{
+	friend class Importer;
+
+protected:
+	/** Constructor to be privately used by Importer */
+	SplitLargeMeshesProcess_Vertex();
+
+	/** Destructor, private as well */
+	~SplitLargeMeshesProcess_Vertex();
+
+public:
+	// -------------------------------------------------------------------
+	/** Returns whether the processing step is present in the given flag field.
+	* @param pFlags The processing flags the importer was called with. A bitwise
+	*   combination of #aiPostProcessSteps.
+	* @return true if the process is present in this flag fields, false if not.
+	*/
+	bool IsActive( unsigned int pFlags) const;
+
+	// -------------------------------------------------------------------
+	/** Executes the post processing step on the given imported data.
+	* At the moment a process is not supposed to fail.
+	* @param pScene The imported data to work at.
+	*/
+	void Execute( aiScene* pScene);
+
+private:
+
+	//! Apply the algorithm to a given mesh
+	void SplitMesh (unsigned int a, aiMesh* pcMesh,
+		std::vector<std::pair<aiMesh*, unsigned int> >& avList);
+
+	// NOTE: Reuse SplitLargeMeshesProcess_Triangle::UpdateNode()
+
+public:
+	//! Triangle limit set via aiSetTriangleSplitLimit()
+	static unsigned int LIMIT;
 };
 
 } // end of namespace Assimp

+ 43 - 1
code/TriangulateProcess.h

@@ -1,4 +1,46 @@
-/** @file Defines a post processing step to triangulate all faces with more than three vertices.*/
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 a post processing step to triangulate all faces 
+          with more than three vertices.
+ */
 #ifndef AI_TRIANGULATEPROCESS_H_INC
 #define AI_TRIANGULATEPROCESS_H_INC
 

+ 41 - 0
code/XFileHelper.h

@@ -1,3 +1,44 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 helper data structures for importing XFiles */
 #ifndef AI_XFILEHELPER_H_INC
 #define AI_XFILEHELPER_H_INC

+ 41 - 1
code/XFileImporter.cpp

@@ -1,3 +1,43 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the XFile importer class */
 #include "XFileImporter.h"
 #include "XFileParser.h"
@@ -586,7 +626,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
 					}
 				if (std::string::npos != s2)
 					{
-					sprintf(key,AI_MATKEY_TEXTURE_BUMP_ "[%i]",iHM++);
+					sprintf(key,AI_MATKEY_TEXTURE_HEIGHT_ "[%i]",iHM++);
 					}
 				else
 					{

+ 73 - 13
code/XFileImporter.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definition of the XFile importer class. */
 #ifndef AI_XFILEIMPORTER_H_INC
 #define AI_XFILEIMPORTER_H_INC
@@ -38,51 +78,71 @@ public:
 	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
 
 protected:
+
+	// -------------------------------------------------------------------
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 * See BaseImporter::GetExtensionList() for details
+	 */
+	void GetExtensionList(std::string& append)
+	{
+		append.append("*.x");
+	}
+
 	// -------------------------------------------------------------------
 	/** Imports the given file into the given scene structure. 
 	 * See BaseImporter::InternReadFile() for details
 	 */
-	void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+	void InternReadFile( const std::string& pFile, aiScene* pScene, 
+		IOSystem* pIOHandler);
 
 	// -------------------------------------------------------------------
 	/** Constructs the return data structure out of the imported data.
 	 * @param pScene The scene to construct the return data in.
-	 * @param pData The imported data in the internal temporary representation.
+	 * @param pData The imported data in the internal temporary 
+	 *   representation.
 	 */
-	void CreateDataRepresentationFromImport( aiScene* pScene, const XFile::Scene* pData);
+	void CreateDataRepresentationFromImport( aiScene* pScene, 
+		const XFile::Scene* pData);
 
 	// -------------------------------------------------------------------
-	/** Recursively creates scene nodes from the imported hierarchy. The meshes and materials
-	 * of the nodes will be extracted on the way.
+	/** Recursively creates scene nodes from the imported hierarchy.
+	 * The meshes and materials of the nodes will be extracted on the way.
 	 * @param pScene The scene to construct the return data in.
 	 * @param pParent The parent node where to create new child nodes
 	 * @param pNode The temporary node to copy.
 	 * @return The created node 
 	 */
-	aiNode* CreateNodes( aiScene* pScene, aiNode* pParent, const XFile::Node* pNode);
+	aiNode* CreateNodes( aiScene* pScene, aiNode* pParent, 
+		const XFile::Node* pNode);
 
 	// -------------------------------------------------------------------
-	/** Converts all meshes in the given mesh array. Each mesh is splitted up per material,
-	 * the indices of the generated meshes are stored in the node structure.
+	/** Converts all meshes in the given mesh array. Each mesh is splitted 
+	 * up per material, the indices of the generated meshes are stored in 
+	 * the node structure.
 	 * @param pScene The scene to construct the return data in.
-	 * @param pNode The target node structure that references the constructed meshes.
+	 * @param pNode The target node structure that references the
+	 *   constructed meshes.
 	 * @param pMeshes The array of meshes to convert
 	 */
-	void CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector<XFile::Mesh*>& pMeshes);
+	void CreateMeshes( aiScene* pScene, aiNode* pNode, 
+		const std::vector<XFile::Mesh*>& pMeshes);
 
 	// -------------------------------------------------------------------
-	/** Converts the animations from the given imported data and creates them in the scene.
+	/** Converts the animations from the given imported data and creates 
+	*  them in the scene.
 	 * @param pScene The scene to hold to converted animations
 	 * @param pData The data to read the animations from
 	 */
 	void CreateAnimations( aiScene* pScene, const XFile::Scene* pData);
 
 	// -------------------------------------------------------------------
-	/** Converts all materials in the given array and stores them in the scene's material list.
+	/** Converts all materials in the given array and stores them in the
+	 *  scene's material list.
 	 * @param pScene The scene to hold the converted materials.
 	 * @param pMaterials The material array to convert.
 	 */
-	void ConvertMaterials( aiScene* pScene, const std::vector<XFile::Material>& pMaterials);
+	void ConvertMaterials( aiScene* pScene, 
+		const std::vector<XFile::Material>& pMaterials);
 
 protected:
 	/** Buffer to hold the loaded file */

+ 41 - 0
code/XFileParser.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Implementation of the XFile parser helper class */
 #include "XFileParser.h"
 #include "XFileHelper.h"

+ 40 - 0
code/XFileParser.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Helper class to parse a XFile into a temporary structure */
 #ifndef AI_XFILEPARSER_H_INC
 #define AI_XFILEPARSER_H_INC

+ 103 - 0
code/res/assimp.rc

@@ -0,0 +1,103 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Deutsch (Deutschland) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+#ifdef _WIN32
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x7L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040704b0"
+        BEGIN
+            VALUE "Comments", "Licensed under a 3-clause BSD license"
+            VALUE "CompanyName", "ASSIMP Development Team"
+            VALUE "FileDescription", "Free Asset Import Library "
+            VALUE "FileVersion", "1, 0, 0, 0"
+            VALUE "InternalName", "assimp"
+            VALUE "LegalCopyright", "Copyright (C) 2008"
+            VALUE "OriginalFilename", "assimp32.dll"
+            VALUE "ProductName", "Free Asset Import Library "
+            VALUE "ProductVersion", "1, 0, 0, 0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x407, 1200
+    END
+END
+
+#endif    // Deutsch (Deutschland) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+

+ 14 - 0
code/res/resource.h

@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by assimp.rc
+
+// Nächste Standardwerte für neue Objekte
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif

+ 43 - 2
include/ObjFileParser.h

@@ -1,3 +1,44 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 OBJ_FILEPARSER_H_INC
 #define OBJ_FILEPARSER_H_INC
 
@@ -38,8 +79,8 @@ private:
 	void parseFile();
 	void copyNextWord(char *pBuffer, size_t length);
 	void copyNextLine(char *pBuffer, size_t length);
-	void getVector3(std::vector<aiVector3D_t*> &point3d_array);
-	void getVector2(std::vector<aiVector2D_t*> &point2d_array);
+	void getVector3(std::vector<aiVector3D*> &point3d_array);
+	void getVector2(std::vector<aiVector2D*> &point2d_array);
 	void skipLine();
 	void getFace();
 	void getMaterialDesc();

+ 49 - 8
include/aiAnim.h

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 data structures in which the imported animations are returned. */
 #ifndef AI_ANIM_H_INC
 #define AI_ANIM_H_INC
@@ -13,7 +54,7 @@ extern "C" {
 struct aiVectorKey
 {
 	double mTime;      ///< The time of this key
-	aiVector3D_t mValue; ///< The value of this key
+	C_STRUCT aiVector3D mValue; ///< The value of this key
 };
 
 /** A time-value pair specifying a rotation for the given time. For joint animations
@@ -22,7 +63,7 @@ struct aiVectorKey
 struct aiQuatKey
 {
 	double mTime;      ///< The time of this key
-	aiQuaternion_t mValue; ///< The value of this key
+	C_STRUCT aiQuaternion mValue; ///< The value of this key
 };
 
 /** Describes the animation of a single bone. The name specifies the bone which is affected by this
@@ -32,28 +73,28 @@ struct aiQuatKey
 struct aiBoneAnim
 {
 	/** The name of the bone affected by this animation. */
-	aiString mBoneName;
+	C_STRUCT aiString mBoneName;
 
 	/** The number of position keys */
 	unsigned int mNumPositionKeys;
 	/** The position keys of this animation channel. Positions are specified as 3D vector. 
 	* The array is mNumPositionKeys in size.
 	*/
-	aiVectorKey* mPositionKeys;
+	C_STRUCT aiVectorKey* mPositionKeys;
 
 	/** The number of rotation keys */
 	unsigned int mNumRotationKeys;
 	/** The rotation keys of this animation channel. Rotations are given as quaternions, 
 	* which are 4D vectors. The array is mNumRotationKeys in size.
 	*/
-	aiQuatKey* mRotationKeys;
+	C_STRUCT aiQuatKey* mRotationKeys;
 
 	/** The number of scaling keys */
 	unsigned int mNumScalingKeys;
 	/** The scaling keys of this animation channel. Scalings are specified as 3D vector. 
 	* The array is mNumScalingKeys in size.
 	*/
-	aiVectorKey* mScalingKeys;
+	C_STRUCT aiVectorKey* mScalingKeys;
 
 #ifdef __cplusplus
 	aiBoneAnim()
@@ -80,7 +121,7 @@ struct aiAnimation
 	/** The name of the animation. If the modelling package this data was exported from does support 
 	* only a single animation channel, this name is usually empty (length is zero).
 	*/
-	aiString mName;
+	C_STRUCT aiString mName;
 
 	/** Duration of the animation in ticks. */
 	double mDuration;
@@ -92,7 +133,7 @@ struct aiAnimation
 	/** The bone animation channels. Each channel affects a single bone. The array
 	* is mNumBones in size.
 	*/
-	aiBoneAnim** mBones;
+	C_STRUCT aiBoneAnim** mBones;
 
 #ifdef __cplusplus
 	aiAnimation()

+ 59 - 6
include/aiFileIO.h

@@ -1,6 +1,45 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 generic routines to access memory-mapped files
- *
  */
 
 #ifndef AI_FILEIO_H_INC
@@ -14,11 +53,11 @@ extern "C" {
 
 
 struct aiFileIO;
-//enum aiOrigin;
-typedef aiFileIO (*aiFileOpenProc)(aiFileIO*, const char*, const char*);
-typedef aiReturn (*aiFileCloseProc)(aiFileIO*);
-typedef unsigned long (*aiFileReadWriteProc)(aiFileIO*, char*, unsigned int, unsigned int);
-typedef unsigned long (*aiFileTellProc)(aiFileIO*);
+
+typedef aiFileIO (*aiFileOpenProc)(C_STRUCT aiFileIO*, const char*, const char*);
+typedef aiReturn (*aiFileCloseProc)(C_STRUCT aiFileIO*);
+typedef unsigned long (*aiFileReadWriteProc)(C_STRUCT aiFileIO*, char*, unsigned int, unsigned int);
+typedef unsigned long (*aiFileTellProc)(C_STRUCT aiFileIO*);
 
 // ---------------------------------------------------------------------------
 /** Define seek origins in fseek()-style.
@@ -44,13 +83,27 @@ typedef char* aiUserData;
 // ---------------------------------------------------------------------------
 struct aiFileIO
 {
+	//! User data assigned to the structure
 	aiUserData UserData;
 
+	//! Function used to open a new file
 	aiFileOpenProc OpenFunc;
+
+	//! Function used to close an existing file
 	aiFileCloseProc CloseFunc;
+
+	//! Function used to read from a file
 	aiFileReadWriteProc ReadFunc;
+
+	//! Function used to write to a file
 	aiFileReadWriteProc WriteFunc;
+
+	//! Function used to retrieve the current
+	//! position of the file cursor (ftell())
 	aiFileTellProc TellProc;
+
+	//! Function used to set the current position
+	//! of the file cursor (fseek())
 	aiFileSeek SeekProc;
 };
 

+ 166 - 86
include/aiMaterial.h

@@ -1,4 +1,43 @@
-
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 material system of the library
  *
@@ -24,56 +63,50 @@ enum aiPropertyTypeInfo
 	*/
 	aiPTI_Float = 0x1,
 
-
 	/** aiString data structure
 	*/
 	aiPTI_String = 0x3,
 
-
 	/** Array of Integers
 	*/
 	aiPTI_Integer = 0x4,
 
-
 	/** Simple binary buffer
 	*/
 	aiPTI_Buffer = 0x5,
 };
 
-
 // ---------------------------------------------------------------------------
-/** Defines algorithms for generating UVW-coords (for texture sampling)
-*  procedurally.
+/** Defines texture operations like add, mul ...
+*
 */
 // ---------------------------------------------------------------------------
-enum aiTexUVWGen
+enum aiTextureOp
 {
-	/** The view vector will be reflected to a pixel's normal. 
-	*
-	*  The result is used as UVW-coordinate for 
-	*  accessing a cubemap
-	*/
-	aiTexUVWGen_VIEWREFLEFT = 0x800001,
+	/** T = T1 * T2
+	 */
+	aiTextureOp_Multiply = 0x0,
 
+	/** T = T1 + T2
+	 */
+	aiTextureOp_Add = 0x1,
 
-	/** The view vector will be used as UVW-src
-	*
-	*  The view vector is used as UVW-coordinate for 
-	*  accessing a cubemap
-	*/
-	aiTexUVWGen_VIEW = 0x800002,
+	/** T = T1 - T2
+	 */
+	aiTextureOp_Subtract = 0x2,
 
+	/** T = T1 / T2
+	 */
+	aiTextureOp_Divide = 0x3,
 
-	/** The view vector will be refracted to the pixel's normal. 
-	*
-	*  If this is used, the refraction index to be applied should
-	*  also be contained in the material description.
-	*  The result is used as UVW-coordinate for 
-	*  accessing a cubemap.
-	*/
-	aiTexUVWGen_VIEWREFRACT = 0x800003
-};
+	/** T = (T1 + T2) - (T1 * T2)
+	 */
+	aiTextureOp_SmoothAdd = 0x4,
 
+	/** T = T1 + (T2-0.5)
+	 */
+	aiTextureOp_SignedAdd = 0x5
+};
 
 // ---------------------------------------------------------------------------
 /** Defines all shading models supported by the library
@@ -92,12 +125,10 @@ enum aiShadingMode
 	*/
 	aiShadingMode_Flat = 0x1,
 
-
 	/** Diffuse gouraud shading. Shading on per-vertex base
 	*/
 	aiShadingMode_Gouraud =	0x2,
 
-
 	/** Diffuse/Specular Phong-Shading
 	*
 	*  Shading is applied on per-pixel base. This is the
@@ -105,7 +136,6 @@ enum aiShadingMode
 	*/
 	aiShadingMode_Phong = 0x3,
 
-
 	/** Diffuse/Specular Phong-Blinn-Shading
 	*
 	*  Shading is applied on per-pixel base. This is a little
@@ -114,7 +144,6 @@ enum aiShadingMode
 	*/
 	aiShadingMode_Blinn	= 0x4,
 
-
 	/** Toon-Shading per pixel
 	*
 	*  Shading is applied on per-pixel base. The output looks
@@ -122,7 +151,6 @@ enum aiShadingMode
 	*/
 	aiShadingMode_Toon = 0x5,
 
-
 	/** OrenNayar-Shading per pixel
 	*
 	*  Extension to standard lambertian shading, taking the
@@ -131,7 +159,6 @@ enum aiShadingMode
 	*/
 	aiShadingMode_OrenNayar = 0x6,
 
-
 	/** Minnaert-Shading per pixel
 	*
 	*  Extension to standard lambertian shading, taking the
@@ -139,12 +166,10 @@ enum aiShadingMode
 	*/
 	aiShadingMode_Minnaert = 0x7,
 
-
 	/** CookTorrance-Shading per pixel
 	*/
 	aiShadingMode_CookTorrance = 0x8,
 
-
 	/** No shading at all
 	*/
 	aiShadingMode_NoShading = 0x8
@@ -163,14 +188,12 @@ struct aiMaterialProperty
 	*
 	*	Keys are case insensitive.
 	*/
-	aiString* mKey;
-
+	C_STRUCT aiString* mKey;
 
 	/**	Size of the buffer mData is pointing to, in bytes
 	*/
 	unsigned int mDataLength;
 
-
 	/** Type information for the property.
 	*
 	*  Defines the data layout inside the
@@ -179,7 +202,6 @@ struct aiMaterialProperty
 	*/
 	aiPropertyTypeInfo mType;
 
-
 	/**	Binary buffer to hold the property's value
 	*
 	*  The buffer has no terminal character. However,
@@ -199,19 +221,17 @@ struct aiMaterialProperty
 *  for nearly all purposes. 
 */
 // ---------------------------------------------------------------------------
-#ifdef __cplusplus
-class aiMaterial
+struct aiMaterial
 {
+#ifdef __cplusplus
 protected:
 	aiMaterial() {}
 public:
-#else
-struct aiMaterial
-{
 #endif // __cplusplus
+
 	/** List of all material properties loaded.
 	*/
-	aiMaterialProperty** mProperties;
+	C_STRUCT aiMaterialProperty** mProperties;
 
 	/** Number of properties loaded
 	*/
@@ -231,6 +251,11 @@ struct aiMaterial
 */
 #define AI_MATKEY_SHADING_MODEL "$mat.shadingm"
 
+/** @def AI_MATKEY_ENABLE_WIREFRAM
+*  Integer property. 1 to enable wireframe for rendering
+*/
+#define AI_MATKEY_ENABLE_WIREFRAME "$mat.wireframe"
+
 /** @def AI_MATKEY_OPACITY
 *  Defines the base opacity of the material
 */
@@ -297,15 +322,15 @@ struct aiMaterial
 #define AI_MATKEY_TEXTURE_NORMALS(N) "$tex.file.normals["#N"]"
 #define AI_MATKEY_TEXTURE_NORMALS_   "$tex.file.normals"
 
-/** @def AI_MATKEY_TEXTURE_BUMP
+/** @def AI_MATKEY_TEXTURE_HEIGHT
 * Defines a specified bumpmap texture (=heightmap) channel of the material
 * This is very similar to #AI_MATKEY_TEXTURE_NORMALS. It is provided
 * to allow applications to determine whether the input data for
-* normal mapping is already a normal map or needs to be converted to
-* a heightmap.
+* normal mapping is already a normal map or needs to be converted from
+* a heightmap to a normal map.
 */
-#define AI_MATKEY_TEXTURE_BUMP(N) "$tex.file.bump["#N"]"
-#define AI_MATKEY_TEXTURE_BUMP_   "$tex.file.bump"
+#define AI_MATKEY_TEXTURE_HEIGHT(N) "$tex.file.bump["#N"]"
+#define AI_MATKEY_TEXTURE_HEIGHT_   "$tex.file.bump"
 
 /** @def AI_MATKEY_TEXTURE_SHININESS
 *  Defines a specified shininess texture channel of the material
@@ -325,37 +350,55 @@ struct aiMaterial
 #define AI_MATKEY_TEXOP_SPECULAR(N)		"$tex.op.specular["#N"]"
 #define AI_MATKEY_TEXOP_EMISSIVE(N)		"$tex.op.emissive["#N"]"
 #define AI_MATKEY_TEXOP_NORMALS(N)		"$tex.op.normals["#N"]"
-#define AI_MATKEY_TEXOP_BUMP(N)			"$tex.op.bump["#N"]"
+#define AI_MATKEY_TEXOP_HEIGHT(N)			"$tex.op.bump["#N"]"
 #define AI_MATKEY_TEXOP_SHININESS(N)	"$tex.op.shininess["#N"]"
 #define AI_MATKEY_TEXOP_OPACITY(N)		"$tex.op.opacity["#N"]"
 
+#define AI_MATKEY_TEXOP_DIFFUSE_		"$tex.op.diffuse"
+#define AI_MATKEY_TEXOP_AMBIENT_		"$tex.op.ambient"
+#define AI_MATKEY_TEXOP_SPECULAR_		"$tex.op.specular"
+#define AI_MATKEY_TEXOP_EMISSIVE_		"$tex.op.emissive"
+#define AI_MATKEY_TEXOP_NORMALS_		"$tex.op.normals"
+#define AI_MATKEY_TEXOP_HEIGHT_			"$tex.op.bump"
+#define AI_MATKEY_TEXOP_SHININESS_		"$tex.op.shininess"
+#define AI_MATKEY_TEXOP_OPACITY_		"$tex.op.opacity"
+
 #define AI_MATKEY_UVWSRC_DIFFUSE(N)		"$tex.uvw.diffuse["#N"]"
 #define AI_MATKEY_UVWSRC_AMBIENT(N)		"$tex.uvw.ambient["#N"]"
 #define AI_MATKEY_UVWSRC_SPECULAR(N)	"$tex.uvw.specular["#N"]"
 #define AI_MATKEY_UVWSRC_EMISSIVE(N)	"$tex.uvw.emissive["#N"]"
 #define AI_MATKEY_UVWSRC_NORMALS(N)		"$tex.uvw.normals["#N"]"
-#define AI_MATKEY_UVWSRC_BUMP(N)		"$tex.uvw.bump["#N"]"
+#define AI_MATKEY_UVWSRC_HEIGHT(N)		"$tex.uvw.bump["#N"]"
 #define AI_MATKEY_UVWSRC_SHININESS(N)	"$tex.uvw.shininess["#N"]"
 #define AI_MATKEY_UVWSRC_OPACITY(N)		"$tex.uvw.opacity["#N"]"
 
-#define AI_MATKEY_REFRACTI_DIFFUSE(N)	"$tex.refracti.diffuse["#N"]"
-#define AI_MATKEY_REFRACTI_AMBIENT(N)	"$tex.refracti.ambient["#N"]"
-#define AI_MATKEY_REFRACTI_SPECULAR(N)	"$tex.refracti.specular["#N"]"
-#define AI_MATKEY_REFRACTI_EMISSIVE(N)	"$tex.refracti.emissive["#N"]"
-#define AI_MATKEY_REFRACTI_NORMALS(N)	"$tex.refracti.normals["#N"]"
-#define AI_MATKEY_REFRACTI_BUMP(N)		"$tex.refracti.bump["#N"]"
-#define AI_MATKEY_REFRACTI_SHININESS(N)	"$tex.refracti.shininess["#N"]"
-#define AI_MATKEY_REFRACTI_OPACITY(N)	"$tex.refracti.opacity["#N"]"
+#define AI_MATKEY_UVWSRC_DIFFUSE_		"$tex.uvw.diffuse"
+#define AI_MATKEY_UVWSRC_AMBIENT_		"$tex.uvw.ambient"
+#define AI_MATKEY_UVWSRC_SPECULAR_		"$tex.uvw.specular"
+#define AI_MATKEY_UVWSRC_EMISSIVE_		"$tex.uvw.emissive"
+#define AI_MATKEY_UVWSRC_NORMALS_		"$tex.uvw.normals"
+#define AI_MATKEY_UVWSRC_HEIGHT_			"$tex.uvw.bump"
+#define AI_MATKEY_UVWSRC_SHININESS_		"$tex.uvw.shininess"
+#define AI_MATKEY_UVWSRC_OPACITY_		"$tex.uvw.opacity"
 
 #define AI_MATKEY_TEXBLEND_DIFFUSE(N)	"$tex.blend.diffuse["#N"]"
 #define AI_MATKEY_TEXBLEND_AMBIENT(N)	"$tex.blend.ambient["#N"]"
 #define AI_MATKEY_TEXBLEND_SPECULAR(N)	"$tex.blend.specular["#N"]"
 #define AI_MATKEY_TEXBLEND_EMISSIVE(N)	"$tex.blend.emissive["#N"]"
 #define AI_MATKEY_TEXBLEND_NORMALS(N)	"$tex.blend.normals["#N"]"
-#define AI_MATKEY_TEXBLEND_BUMP(N)		"$tex.blend.bump["#N"]"
+#define AI_MATKEY_TEXBLEND_HEIGHT(N)		"$tex.blend.bump["#N"]"
 #define AI_MATKEY_TEXBLEND_SHININESS(N)	"$tex.blend.shininess["#N"]"
 #define AI_MATKEY_TEXBLEND_OPACITY(N)	"$tex.blend.opacity["#N"]"
 
+#define AI_MATKEY_TEXBLEND_DIFFUSE_		"$tex.blend.diffuse"
+#define AI_MATKEY_TEXBLEND_AMBIENT_		"$tex.blend.ambient"
+#define AI_MATKEY_TEXBLEND_SPECULAR_	"$tex.blend.specular"
+#define AI_MATKEY_TEXBLEND_EMISSIVE_	"$tex.blend.emissive"
+#define AI_MATKEY_TEXBLEND_NORMALS_		"$tex.blend.normals"
+#define AI_MATKEY_TEXBLEND_HEIGHT_		"$tex.blend.bump"
+#define AI_MATKEY_TEXBLEND_SHININESS_	"$tex.blend.shininess"
+#define AI_MATKEY_TEXBLEND_OPACITY_		"$tex.blend.opacity"
+
 
 #define AI_MATKEY_ORENNAYAR_ROUGHNESS	 "$shading.orennayar.roughness"
 #define AI_MATKEY_MINNAERT_DARKNESS		 "$shading.minnaert.darkness"
@@ -379,9 +422,9 @@ struct aiMaterial
 *         structure or NULL if the key has not been found. 
 */
 // ---------------------------------------------------------------------------
-aiReturn aiGetMaterialProperty(const aiMaterial* pMat, 
-							   const char* pKey,
-							   const aiMaterialProperty** pPropOut);
+aiReturn aiGetMaterialProperty(const C_STRUCT aiMaterial* pMat, 
+	const char* pKey,
+	const C_STRUCT aiMaterialProperty** pPropOut);
 
 
 // ---------------------------------------------------------------------------
@@ -395,16 +438,16 @@ aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
 *        Receives the number of values (not bytes!) read. 
 */
 // ---------------------------------------------------------------------------
-aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, 
-								 const char* pKey,
-								 float* pOut,
-								 unsigned int* pMax);
+aiReturn aiGetMaterialFloatArray(const C_STRUCT aiMaterial* pMat, 
+	const char* pKey,
+	float* pOut,
+	unsigned int* pMax);
 
 #ifdef __cplusplus
 // inline it
-inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat, 
-								   const char* pKey,
-								   float* pOut)
+inline aiReturn aiGetMaterialFloat(const C_STRUCT aiMaterial* pMat, 
+	 const char* pKey,
+	 float* pOut)
 	{return aiGetMaterialFloatArray(pMat,pKey,pOut,(unsigned int*)0x0);}
 #else 
 // use our friend, the C preprocessor
@@ -424,16 +467,16 @@ inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat,
 *        Receives the number of values (not bytes!) read. 
 */
 // ---------------------------------------------------------------------------
-aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, 
-								   const char* pKey,
-								   int* pOut,
-								   unsigned int* pMax);
+aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat, 
+	const char* pKey,
+	int* pOut,
+	unsigned int* pMax);
 
 #ifdef __cplusplus
 // inline it
-inline aiReturn aiGetMaterialInteger(const aiMaterial* pMat, 
-									 const char* pKey,
-									 int* pOut)
+inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat, 
+	const char* pKey,
+	int* pOut)
 	{return aiGetMaterialIntegerArray(pMat,pKey,pOut,(unsigned int*)0x0);}
 #else 
 // use our friend, the C preprocessor
@@ -451,9 +494,9 @@ inline aiReturn aiGetMaterialInteger(const aiMaterial* pMat,
 *	@param pOut Pointer to a buffer to receive the result. 
 */
 // ---------------------------------------------------------------------------
-aiReturn aiGetMaterialColor(const aiMaterial* pMat, 
-							const char* pKey,
-							aiColor4D* pOut);
+aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat, 
+	const char* pKey,
+	aiColor4D* pOut);
 
 
 // ---------------------------------------------------------------------------
@@ -464,9 +507,46 @@ aiReturn aiGetMaterialColor(const aiMaterial* pMat,
 *	@param pOut Pointer to a buffer to receive the result. 
 */
 // ---------------------------------------------------------------------------
-aiReturn aiGetMaterialString(const aiMaterial* pMat, 
-							 const char* pKey,
-							 aiString* pOut);
+aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat, 
+	const char* pKey,
+	aiString* pOut);
+
+
+#define AI_TEXTYPE_DIFFUSE		0x0
+#define AI_TEXTYPE_SPECULAR		0x1
+#define AI_TEXTYPE_AMBIENT		0x2
+#define AI_TEXTYPE_EMISSIVE		0x3
+#define AI_TEXTYPE_HEIGHT		0x4
+#define AI_TEXTYPE_NORMALS		0x5
+#define AI_TEXTYPE_SHININESS	0x6
+
+// ---------------------------------------------------------------------------
+/** Helper function to get a diffuse texture from a material
+ *
+ *  This function is provided just for convinience. 
+ *  @param pMat Pointer to the input material. May not be NULL
+ *  @param iIndex Index of the texture to retrieve. If the index is too 
+ *     large the function fails.
+ *  @param iTexType One of the AI_TEXTYPE constants. Specifies the type of
+ *     the texture to retrieve (e.g. diffuse, specular, height map ...)
+ *  @param szPath Receives the output path
+ *     NULL is no allowed as value
+ *  @param piUVIndex Receives the UV index of the texture. 
+ *     NULL is allowed as value.
+ *  @param pfBlendFactor Receives the blend factor for the texture
+ *     NULL is allowed as value.
+ *  @param peTextureOp Receives the texture operation to perform between
+ *     this texture and the previous texture.
+ *     NULL is allowed as value.
+ */
+// ---------------------------------------------------------------------------
+aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* pMat,
+	unsigned int iIndex,
+	unsigned int iTexType,
+	C_STRUCT aiString* szPath,
+	unsigned int* piUVIndex,
+	float* pfBlendFactor,
+	aiTextureOp* peTextureOp); 
 
 
 #ifdef __cplusplus

+ 2 - 2
include/aiMatrix3x3.h

@@ -12,7 +12,7 @@ struct aiMatrix4x4;
 /** Represents a column-major 3x3 matrix 
 */
 // ---------------------------------------------------------------------------
-typedef struct aiMatrix3x3
+struct aiMatrix3x3
 {
 #ifdef __cplusplus
 	aiMatrix3x3 () :	
@@ -41,7 +41,7 @@ typedef struct aiMatrix3x3
 	float a1, a2, a3;
 	float b1, b2, b3;
 	float c1, c2, c3;
-} aiMatrix3x3_t;
+};
 
 #ifdef __cplusplus
 } // end of extern C

+ 2 - 2
include/aiMatrix4x4.h

@@ -23,7 +23,7 @@ struct aiMatrix3x3;
 *  use this for homogenious coordinates 
 */
 // ---------------------------------------------------------------------------
-typedef struct aiMatrix4x4
+struct aiMatrix4x4
 {
 #ifdef __cplusplus
 	aiMatrix4x4 () :	
@@ -60,7 +60,7 @@ typedef struct aiMatrix4x4
 	float c1, c2, c3, c4;
 	float d1, d2, d3, d4;
 
-} PACK_STRUCT aiMatrix4x4_t;
+} PACK_STRUCT;
 
 
 // Reset packing

+ 164 - 29
include/aiMesh.h

@@ -1,4 +1,46 @@
-/** @file Defines the data structures in which the imported geometry is returned. */
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 data structures in which the imported geometry is 
+    returned by ASSIMP */
 #ifndef AI_MESH_H_INC
 #define AI_MESH_H_INC
 
@@ -10,31 +52,43 @@ extern "C" {
 
 // ---------------------------------------------------------------------------
 /** A single face in a mesh, referring to multiple vertices. 
-*  If mNumIndices is 3, the face is a triangle, for mNumIndices > 3 it's a polygon.
+*
+* If mNumIndices is 3, the face is a triangle, 
+* for mNumIndices > 3 it's a polygon.
+* Point and line primitives are rarely used and are NOT supported. However,
+* a load could pass them as degenerated triangles.
 */
 // ---------------------------------------------------------------------------
 struct aiFace
 {
-	unsigned int mNumIndices; ///< Number of indices defining this face. 3 for a triangle, >3 for polygon
-	unsigned int* mIndices;   ///< Pointer to the indices array. Size of the array is given in numIndices.
+	//! Number of indices defining this face. 3 for a triangle, >3 for polygon
+	unsigned int mNumIndices; 
+
+	//! Pointer to the indices array. Size of the array is given in numIndices.
+	unsigned int* mIndices;   
 
 #ifdef __cplusplus
+
+	//! Default constructor
 	aiFace()
 	{
 		mNumIndices = 0; mIndices = NULL;
 	}
 
+	//! Default destructor. Delete the index array
 	~aiFace()
 	{
 		delete [] mIndices;
 	}
 
+	//! Copy constructor. Copy the index array
 	aiFace( const aiFace& o)
 	{
 		mIndices = NULL;
 		*this = o;
 	}
 
+	//! Assignment operator. Copy the index array
 	const aiFace& operator = ( const aiFace& o)
 	{
 		if (&o == this)
@@ -47,21 +101,58 @@ struct aiFace
 		return *this;
 	}
 
+	//! Comparison operator. Checks whether the index array 
+	//! of two faces is identical
+	bool operator== (const aiFace& o) const
+	{
+		if (this->mIndices == o.mIndices)return true;
+		else if (this->mIndices && this->mNumIndices == o.mNumIndices)
+		{
+			for (unsigned int i = 0;i < this->mNumIndices;++i)
+			{
+				if (this->mIndices[i] != o.mIndices[i])return false;
+			}
+			return true;
+		}
+		return false;
+	}
+
+	//! Inverse comparison operator. Checks whether the index 
+	//! array of two faces is NOT identical
+	bool operator != (const aiFace& o) const
+	{
+		return !(*this == o);
+	}
+
 #endif // __cplusplus
 };
 
 
 // ---------------------------------------------------------------------------
-/** A single influence of a bone on a vertex. */
+/** A single influence of a bone on a vertex.
+ */
 // ---------------------------------------------------------------------------
 struct aiVertexWeight
 {
-	unsigned int mVertexId; ///< Index of the vertex which is influenced by the bone.
-	float mWeight;     ///< The strength of the influence in the range (0...1). The influence from all bones at one vertex amounts to 1.
+	//! Index of the vertex which is influenced by the bone.
+	unsigned int mVertexId;
+
+	//! The strength of the influence in the range (0...1).
+	//! The influence from all bones at one vertex amounts to 1.
+	float mWeight;     
 
 #ifdef __cplusplus
+
+	//! Default constructor
 	aiVertexWeight() { }
-	aiVertexWeight( unsigned int pID, float pWeight) : mVertexId( pID), mWeight( pWeight) { }
+
+	//! Initialisation from a given index and vertex weight factor
+	//! \param pID ID
+	//! \param pWeight Vertex weight factor
+	aiVertexWeight( unsigned int pID, float pWeight) 
+		: mVertexId( pID), mWeight( pWeight) 
+	{ /* nothing to do here */ }
+
 #endif // __cplusplus
 };
 
@@ -74,17 +165,27 @@ struct aiVertexWeight
 // ---------------------------------------------------------------------------
 struct aiBone
 {
-	aiString mName; ///< The name of the bone. 
-	unsigned int mNumWeights; ///< The number of vertices affected by this bone
-	aiVertexWeight* mWeights; ///< The vertices affected by this bone
-	aiMatrix4x4 mOffsetMatrix; ///< Matrix that transforms from mesh space to bone space in bind pose
+	//! The name of the bone. 
+	C_STRUCT aiString mName;
+
+	//! The number of vertices affected by this bone
+	unsigned int mNumWeights;
+
+	//! The vertices affected by this bone
+	C_STRUCT aiVertexWeight* mWeights;
+
+	//! Matrix that transforms from mesh space to bone space in bind pose
+	C_STRUCT aiMatrix4x4 mOffsetMatrix;
 
 #ifdef __cplusplus
+
+	//! Default constructor
 	aiBone()
 	{
 		mNumWeights = 0; mWeights = NULL;
 	}
 
+	//! Destructor to delete the array of vertex weights
 	~aiBone()
 	{
 		delete [] mWeights;
@@ -92,31 +193,48 @@ struct aiBone
 #endif // __cplusplus
 };
 
+#if (!defined AI_MAX_NUMBER_OF_COLOR_SETS)
 
 /** Maximum number of vertex color sets per mesh.
 *
-* Diffuse, specular, ambient and emissive
+* Normally: Diffuse, specular, ambient and emissive
+* However, one could use the vertex color sets for any other purpose, too.
+*
+* \note Some internal structures expect (and assert) this value
+*   to be at least 4
 */
 #define AI_MAX_NUMBER_OF_COLOR_SETS 0x4
 
+#endif // !! AI_MAX_NUMBER_OF_COLOR_SETS
+#if (!defined AI_MAX_NUMBER_OF_TEXTURECOORDS)
 
-/** Maximum number of texture coord sets (UV channels) per mesh 
+/** Maximum number of texture coord sets (UV(W) channels) per mesh 
+*
+* The material system uses the AI_MATKEY_UVWSRC_XXX keys to specify 
+* which UVW channel serves as data source for a texture,
+*
+* \note Some internal structures expect (and assert) this value
+*   to be at least 4
 */
 #define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x4
 
+#endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS
+
 // ---------------------------------------------------------------------------
 /** A mesh represents a geometry or model with a single material. 
 *
 * It usually consists of a number of vertices and a series of primitives/faces 
 * referencing the vertices. In addition there might be a series of bones, each 
-* of them addressing a number of vertices with a certain weight. Vertex data is
-* presented in channels with each channel containing a single per-vertex 
+* of them addressing a number of vertices with a certain weight. Vertex data 
+* is presented in channels with each channel containing a single per-vertex 
 * information such as a set of texture coords or a normal vector.
 * If a data pointer is non-null, the corresponding data stream is present.
 * From C++-programs you can also use the comfort functions Has*() to
 * test for the presence of various data streams.
 *
 * A Mesh uses only a single material which is referenced by a material ID.
+* \note The mPositions member is not optional, although a Has()-Method is
+* provided for it.
 */
 struct aiMesh
 {
@@ -134,13 +252,13 @@ struct aiMesh
 	* This array is always present in a mesh. The array is 
 	* mNumVertices in size. 
 	*/
-	aiVector3D_t* mVertices;
+	C_STRUCT aiVector3D* mVertices;
 
 	/** Vertex normals. 
 	* The array contains normalized vectors, NULL if not present. 
 	* The array is mNumVertices in size. 
 	*/
-	aiVector3D_t* mNormals;
+	C_STRUCT aiVector3D* mNormals;
 
 	/** Vertex tangents. 
 	* The tangent of a vertex points in the direction of the positive 
@@ -149,7 +267,7 @@ struct aiMesh
 	* @note If the mesh contains tangents, it automatically also 
 	* contains bitangents. 
 	*/
-	aiVector3D_t* mTangents;
+	C_STRUCT aiVector3D* mTangents;
 
 	/** Vertex bitangents. 
 	* The bitangent of a vertex points in the direction of the positive 
@@ -158,20 +276,20 @@ struct aiMesh
 	* @note If the mesh contains tangents, it automatically also contains
 	* bitangents. 
 	*/
-	aiVector3D_t* mBitangents;
+	C_STRUCT aiVector3D* mBitangents;
 
 	/** Vertex color sets. 
 	* A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex 
 	* colors per vertex. NULL if not present. Each array is
 	* mNumVertices in size if present.
 	*/
-	aiColor4D_t* mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
+	C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
 
 	/** Vertex texture coords, also known as UV channels.
 	* A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per
 	* vertex. NULL if not present. The array is mNumVertices in size. 
 	*/
-	aiVector3D_t* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+	C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
 
 	/** Specifies the number of components for a given UV channel.
 	* Up to three channels are supported (UVW, for accessing volume
@@ -187,7 +305,7 @@ struct aiMesh
 	* This array is always present in a mesh, its size is given 
 	* in mNumFaces.
 	*/
-	aiFace* mFaces;
+	C_STRUCT aiFace* mFaces;
 
 	/** The number of bones this mesh contains. 
 	* Can be 0, in which case the mBones array is NULL. 
@@ -198,7 +316,7 @@ struct aiMesh
 	* A bone consists of a name by which it can be found in the
 	* frame hierarchy and a set of vertex weights.
 	*/
-	aiBone** mBones;
+	C_STRUCT aiBone** mBones;
 
 	/** The material used by this mesh. 
 	 * A mesh does use only a single material. If an imported model uses multiple materials,
@@ -240,23 +358,40 @@ struct aiMesh
 		delete [] mBones;
 	}
 
-	bool HasNormals() const { return mNormals != NULL; }
-	bool HasTangentsAndBitangents() const { return mTangents != NULL && mBitangents != NULL; }
-	bool HasVertexColors( unsigned int pIndex) 
+	//! Check whether the mesh contains positions. Should always return true
+	inline bool HasPositions() const 
+		{ return mVertices != NULL; }
+
+	//! Check whether the mesh contains normal vectors
+	inline bool HasNormals() const 
+		{ return mNormals != NULL; }
+
+	//! Check whether the mesh contains tangent and bitangent vectors
+	inline bool HasTangentsAndBitangents() const 
+		{ return mTangents != NULL && mBitangents != NULL; }
+
+	//! Check whether the mesh contains a vertex color set
+	//! \param pIndex Index of the vertex color set
+	inline bool HasVertexColors( unsigned int pIndex) 
 	{ 
 		if( pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS) 
 			return false; 
 		else 
 			return mColors[pIndex] != NULL; 
 	}
-	bool HasTextureCoords( unsigned int pIndex) 
+
+	//! Check whether the mesh contains a texture coordinate set
+	//! \param pIndex Index of the texture coordinates set
+	inline bool HasTextureCoords( unsigned int pIndex) 
 	{ 
 		if( pIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS) 
 			return false; 
 		else 
 			return mTextureCoords[pIndex] != NULL; 
 	}
-	bool HasBones() const { return mBones != NULL; }
+	//! Check whether the mesh contains bones
+	inline bool HasBones() const
+		{ return mBones != NULL; }
 
 #endif // __cplusplus
 };

+ 69 - 2
include/aiPostProcess.h

@@ -1,7 +1,49 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 Definitions for import post processing steps */
 #ifndef AI_POSTPROCESS_H_INC
 #define AI_POSTPROCESS_H_INC
 
+#include "aiTypes.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -65,12 +107,37 @@ enum aiPostProcessSteps
 	* This is quite useful for realtime rendering where the number of vertices
 	* is usually limited by the video driver.
 	*
-	* A mesh is split if it consists of more than 1 * 10^6 vertices. This is defined
-	* in the internal SplitLargeMeshes.h header as AI_SLM_MAX_VERTICES.
+	* The split limits can be set through aiSetVertexSplitLimit() and
+	* aiSetTriangleSplitLimit(). The default values for this are defined
+	* in the internal SplitLargeMeshes.h header as AI_SLM_DEFAULT_MAX_VERTICES
+	* and AI_SLM_DEFAULT_MAX_TRIANGLES. 
 	*/
 	aiProcess_SplitLargeMeshes = 0x80
 };
 
+// ---------------------------------------------------------------------------
+/** \brief Set the maximum number of vertices in a mesh.
+ *
+ * This is used by the SplitLargeMeshes PostProcess-Step to determine
+ * whether a mesh must be splitted or not.
+ * \param pLimit Vertex limit. 
+ * \note The default value is AI_SLM_DEFAULT_MAX_VERTICES, defined in
+ *       the internal header file SplitLargeMeshes.h
+ */
+aiReturn aiSetVertexSplitLimit(unsigned int pLimit);
+
+
+// ---------------------------------------------------------------------------
+/** \brief Set the maximum number of triangles in a mesh.
+ *
+ * This is used by the SplitLargeMeshes PostProcess-Step to determine
+ * whether a mesh must be splitted or not.
+ * \param pLimit Triangle limit
+ * \note The default value is AI_SLM_DEFAULT_MAX_TRIANGLES, defined in
+ *       the internal header file SplitLargeMeshes.h
+ */
+aiReturn aiSetTriangleSplitLimit(unsigned int pLimit);
+
 #ifdef __cplusplus
 } // end of extern "C"
 #endif

+ 40 - 38
include/aiQuaternion.h

@@ -11,7 +11,7 @@ extern "C" {
 
 // ---------------------------------------------------------------------------
 /** Represents a quaternion in a 4D vector. */
-typedef struct aiQuaternion
+struct aiQuaternion
 {
 #ifdef __cplusplus
 	aiQuaternion() : w(0.0f), x(0.0f), y(0.0f), z(0.0f) {}
@@ -23,8 +23,9 @@ typedef struct aiQuaternion
 	aiMatrix3x3 GetMatrix() const;
 #endif // __cplusplus
 
+	//! w,x,y,z components of the quaternion
 	float w, x, y, z;	
-} aiQuaternion_t;
+} ;
 
 
 #ifdef __cplusplus
@@ -33,43 +34,44 @@ typedef struct aiQuaternion
 // Constructs a quaternion from a rotation matrix
 inline aiQuaternion::aiQuaternion( const aiMatrix3x3 &pRotMatrix)
 {
-  float t = 1 + pRotMatrix.a1 + pRotMatrix.b2 + pRotMatrix.c3;
+	float t = 1 + pRotMatrix.a1 + pRotMatrix.b2 + pRotMatrix.c3;
 
-  // large enough
-  if( t > 0.00001f)
-  {
-    float s = sqrt( t) * 2.0f;
-    x = (pRotMatrix.b3 - pRotMatrix.c2) / s;
-    y = (pRotMatrix.c1 - pRotMatrix.a3) / s;
-    z = (pRotMatrix.a2 - pRotMatrix.b1) / s;
-    w = 0.25f * s;
-  } // else we have to check several cases
-  else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 )  
-  {	
-    // Column 0: 
-    float s = sqrt( 1.0f + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * 2.0f;
-    x = 0.25f * s;
-    y = (pRotMatrix.a2 + pRotMatrix.b1) / s;
-    z = (pRotMatrix.c1 + pRotMatrix.a3) / s;
-    w = (pRotMatrix.b3 - pRotMatrix.c2) / s;
-  } else 
-  if( pRotMatrix.b2 > pRotMatrix.c3) 
-  { 
-    // Column 1: 
-    float s = sqrt( 1.0f + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * 2.0f;
-    x = (pRotMatrix.a2 + pRotMatrix.b1) / s;
-    y = 0.25f * s;
-    z = (pRotMatrix.b3 + pRotMatrix.c2) / s;
-    w = (pRotMatrix.c1 - pRotMatrix.a3) / s;
-  } else 
-  { 
-    // Column 2:
-    float s = sqrt( 1.0f + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * 2.0f;
-    x = (pRotMatrix.c1 + pRotMatrix.a3) / s;
-    y = (pRotMatrix.b3 + pRotMatrix.c2) / s;
-    z = 0.25f * s;
-    w = (pRotMatrix.a2 - pRotMatrix.b1) / s;
-  }
+	// large enough
+	if( t > 0.00001f)
+	{
+		float s = sqrt( t) * 2.0f;
+		x = (pRotMatrix.b3 - pRotMatrix.c2) / s;
+		y = (pRotMatrix.c1 - pRotMatrix.a3) / s;
+		z = (pRotMatrix.a2 - pRotMatrix.b1) / s;
+		w = 0.25f * s;
+	} // else we have to check several cases
+	else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 )  
+	{	
+		// Column 0: 
+		float s = sqrt( 1.0f + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * 2.0f;
+		x = 0.25f * s;
+		y = (pRotMatrix.a2 + pRotMatrix.b1) / s;
+		z = (pRotMatrix.c1 + pRotMatrix.a3) / s;
+		w = (pRotMatrix.b3 - pRotMatrix.c2) / s;
+	} 
+	else if( pRotMatrix.b2 > pRotMatrix.c3) 
+	{ 
+		// Column 1: 
+		float s = sqrt( 1.0f + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * 2.0f;
+		x = (pRotMatrix.a2 + pRotMatrix.b1) / s;
+		y = 0.25f * s;
+		z = (pRotMatrix.b3 + pRotMatrix.c2) / s;
+		w = (pRotMatrix.c1 - pRotMatrix.a3) / s;
+	} 
+	else 
+	{ 
+		// Column 2:
+		float s = sqrt( 1.0f + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * 2.0f;
+		x = (pRotMatrix.c1 + pRotMatrix.a3) / s;
+		y = (pRotMatrix.b3 + pRotMatrix.c2) / s;
+		z = 0.25f * s;
+		w = (pRotMatrix.a2 - pRotMatrix.b1) / s;
+	}
 }
 
 // ---------------------------------------------------------------------------

+ 64 - 7
include/aiScene.h

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 data structures in which the imported scene is returned. */
 #ifndef AI_SCENE_H_INC
 #define AI_SCENE_H_INC
@@ -5,6 +46,7 @@
 #include "aiTypes.h"
 #include "aiMesh.h"
 #include "aiMaterial.h"
+#include "aiTexture.h"
 #include "aiAnim.h"
 
 #ifdef __cplusplus
@@ -28,19 +70,19 @@ struct aiNode
 	* The name might be empty (length of zero) but all nodes which 
 	* need to be accessed afterwards by bones or anims are usually named.
 	*/
-	aiString mName;
+	C_STRUCT aiString mName;
 
 	/** The transformation relative to the node's parent. */
 	aiMatrix4x4 mTransformation;
 
 	/** Parent node. NULL if this node is the root node. */
-	aiNode* mParent;
+	C_STRUCT aiNode* mParent;
 
 	/** The number of child nodes of this node. */
 	unsigned int mNumChildren;
 	/** The child nodes of this node. NULL if mNumChildren is 0. */
 
-	aiNode** mChildren;
+	C_STRUCT aiNode** mChildren;
 
 	/** The number of meshes of this node. */
 	unsigned int mNumMeshes;
@@ -83,7 +125,7 @@ struct aiScene
 	* was successful. Presence of further nodes depends on the 
 	* format and content of the imported file.
 	*/
-	aiNode* mRootNode;
+	C_STRUCT aiNode* mRootNode;
 
 	/** The number of meshes in the scene. */
 	unsigned int mNumMeshes;
@@ -93,7 +135,7 @@ struct aiScene
 	* Use the indices given in the aiNode structure to access 
 	* this array. The array is mNumMeshes in size.
 	*/
-	aiMesh** mMeshes;
+	C_STRUCT aiMesh** mMeshes;
 
 	/** The number of materials in the scene. */
 	unsigned int mNumMaterials;
@@ -103,7 +145,7 @@ struct aiScene
 	* Use the index given in each aiMesh structure to access this
 	* array. The array is mNumMaterials in size.
 	*/
-	aiMaterial** mMaterials;
+	C_STRUCT aiMaterial** mMaterials;
 
 	/** The number of animations in the scene. */
 	unsigned int mNumAnimations; 
@@ -113,7 +155,18 @@ struct aiScene
 	* All animations imported from the given file are listed here.
 	* The array is mNumAnimations in size.
 	*/
-	aiAnimation** mAnimations;
+	C_STRUCT aiAnimation** mAnimations;
+
+	/** The number of textures embedded into the file */
+	unsigned int mNumTextures;
+
+	/** The array of embedded textures.
+	* 
+	* Not many file formats embedd their textures into the file.
+	* Examples include Quake's MDL format (which is also used by
+	* some GameStudio™ versions)
+	*/
+	C_STRUCT aiTexture** mTextures;
 
 #ifdef __cplusplus
 	aiScene()
@@ -122,6 +175,7 @@ struct aiScene
 		mNumMeshes = 0; mMeshes = NULL;
 		mNumMaterials = 0; mMaterials = NULL;
 		mNumAnimations = 0; mAnimations = NULL;
+		mNumTextures = 0; mTextures = NULL;
 	}
 
 	~aiScene()
@@ -136,6 +190,9 @@ struct aiScene
 		for( unsigned int a = 0; a < mNumAnimations; a++)
 			delete mAnimations[a];
 		delete [] mAnimations;
+		for( unsigned int a = 0; a < mNumTextures; a++)
+			delete mTextures[a];
+		delete [] mTextures;
 	}
 #endif // __cplusplus
 };

+ 149 - 0
include/aiTexture.h

@@ -0,0 +1,149 @@
+
+/** 
+ ** This file is part of the Free Asset Import Library ASSIMP.
+ ** -------------------------------------------------------------------------
+ **
+ ** ASSIMP is free software: you can redistribute it and/or modify it 
+ ** under the terms of the GNU Lesser General Public License as published 
+ ** by the Free Software Foundation, either version 3 of the License, or
+ ** (at your option) any later version.
+ **
+ ** ASSIMP is distributed in the hope that it will be useful,
+ ** but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ ** GNU Lesser General Public License for more details.
+ **
+ ** You should have received a copy of the GNU Lesser General Public License
+ ** along with ASSIMP. If not, see <http://www.gnu.org/licenses/>.
+ **
+ ** -------------------------------------------------------------------------
+ **/
+
+/** @file Defines texture helper structures for the library
+ *
+ * Used for file formats that embedd their textures into the file
+ */
+
+#ifndef AI_TEXTURE_H_INC
+#define AI_TEXTURE_H_INC
+
+#include "aiTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// ---------------------------------------------------------------------------
+/** \def AI_MAKE_EMBEDDED_TEXNAME
+ *  Used to build the reserved path name used by the material system to 
+ *  reference textures that are embedded into their corresponding
+ *  model files. The parameter specifies the index of the texture
+ *  (zero-based, in the aiScene::mTextures array)
+ */
+// ---------------------------------------------------------------------------
+#if (!defined AI_MAKE_EMBEDDED_TEXNAME)
+#	define AI_MAKE_EMBEDDED_TEXNAME(_n_) "*" # _n_
+#endif
+
+// ugly compiler dependent packing stuff
+#if defined(_MSC_VER) ||  defined(__BORLANDC__) ||	defined (__BCPLUSPLUS__)
+#	pragma pack(push,1)
+#	define PACK_STRUCT
+#elif defined( __GNUC__ )
+#	define PACK_STRUCT	__attribute__((packed))
+#else
+#	error Compiler not supported. Never do this again.
+#endif
+
+// ---------------------------------------------------------------------------
+/** Helper structure to represent a texel in ARGB8888 format
+* 
+* Used by aiTexture
+*/
+// ---------------------------------------------------------------------------
+struct aiTexel
+{
+	unsigned char b;
+	unsigned char g;
+	unsigned char r;
+	unsigned char a;
+} PACK_STRUCT;
+
+// reset packing to the original value
+#if defined(_MSC_VER) ||  defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
+#	pragma pack( pop )
+#endif
+#undef PACK_STRUCT
+
+// ---------------------------------------------------------------------------
+/** Helper structure to describe an embedded texture
+* 
+* Normally textures are contained in external files but some file formats
+* do embedd them. Embedded
+*/
+// ---------------------------------------------------------------------------
+struct aiTexture
+{
+	/** Width of the texture, in pixels
+	 *
+	 * If mHeight is zero the texture is compressedin a format
+	 * like JPEG. In this case mWidth specifies the size of the
+	 * memory area pcData is pointing to, in bytes.
+	 */
+	unsigned int mWidth;
+
+	/** Height of the texture, in pixels
+	 *
+	 * If this value is zero, pcData points to an compressed texture
+	 * in an unknown format (e.g. JPEG).
+	 */
+	unsigned int mHeight;
+
+	/** A hint from the loader to make it easier for applications
+	 *  to determine the type of embedded compressed textures.
+	 *
+	 * If mHeight != 0 this member is undefined. Otherwise it
+	 * will be set to '\0\0\0\0' if the loader has no additional
+	 * information about the texture file format used OR the
+	 * file extension of the format without a leading dot.
+	 * E.g. 'dds\0', 'pcx\0'
+	 */
+	char achFormatHint[4];
+
+	/** Data of the texture.
+	 *
+	 * Points to an array of mWidth * mHeight aiTexel's.
+	 * The format of the texture data is always ARGB8888 to
+	 * make the implementation for user of the library as easy
+	 * as possible. If mHeight = 0 this is a pointer to a memory
+	 * buffer of size mWidth containing the compressed texture
+	 * data. Good luck, have fun!
+	 */
+	aiTexel* pcData;
+
+#ifdef __cplusplus
+
+	// Construction
+	aiTexture ()
+		: mHeight(0), mWidth(0), pcData(NULL)
+	{
+		achFormatHint[0] = '\0';
+		achFormatHint[1] = '\0';
+		achFormatHint[2] = '\0';
+		achFormatHint[3] = '\0';
+	}
+
+	// Destruction
+	~aiTexture ()
+	{
+		delete[] pcData;
+	}
+#endif
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AI_TEXTURE_H_INC

+ 79 - 17
include/aiTypes.h

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
 #ifndef AI_TYPES_H_INC
 #define AI_TYPES_H_INC
 
@@ -16,50 +57,57 @@
 #include "aiMatrix4x4.inl"
 
 #ifdef __cplusplus
-#include <string>
+#	include <string>
 extern "C" {
+#	define C_STRUCT
+#else
+#	define C_STRUCT struct
 #endif
 
 /** Maximum dimension for strings, ASSIMP strings are zero terminated */
+#ifdef __cplusplus
 const size_t MAXLEN = 1024;
+#else
+#	define MAXLEN 1024
+#endif
 
 // ---------------------------------------------------------------------------
 /** Represents a two-dimensional vector. 
 */
 // ---------------------------------------------------------------------------
-typedef struct aiVector2D
+struct aiVector2D
 {
 #ifdef __cplusplus
 	aiVector2D () : x(0.0f), y(0.0f) {}
 	aiVector2D (float _x, float _y) : x(_x), y(_y) {}
 	aiVector2D (const aiVector2D& o) : x(o.x), y(o.y) {}
 	
-#endif // __cplusplus
+#endif // !__cplusplus
 
+	//! X and y coordinates
 	float x, y;
-} aiVector2D_t;
+} ;
 
 // aiVector3D type moved to separate header due to size of operators
-
 // aiQuaternion type moved to separate header due to size of operators
-
 // aiMatrix4x4 type moved to separate header due to size of operators
 
 // ---------------------------------------------------------------------------
 /** Represents a color in Red-Green-Blue space. 
 */
 // ---------------------------------------------------------------------------
-typedef struct aiColor3D
+struct aiColor3D
 {
 #ifdef __cplusplus
 	aiColor3D () : r(0.0f), g(0.0f), b(0.0f) {}
 	aiColor3D (float _r, float _g, float _b) : r(_r), g(_g), b(_b) {}
 	aiColor3D (const aiColor3D& o) : r(o.r), g(o.g), b(o.b) {}
 	
-#endif // __cplusplus
+#endif // !__cplusplus
 
+	//! Red, green and blue color values
 	float r, g, b;
-} aiColor3D_t;
+};
 
 
 // ---------------------------------------------------------------------------
@@ -67,7 +115,7 @@ typedef struct aiColor3D
 *   alpha component. 
 */
 // ---------------------------------------------------------------------------
-typedef struct aiColor4D
+struct aiColor4D
 {
 #ifdef __cplusplus
 	aiColor4D () : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {}
@@ -76,17 +124,18 @@ typedef struct aiColor4D
 	aiColor4D (const aiColor4D& o) 
 		: r(o.r), g(o.g), b(o.b), a(o.a) {}
 	
-#endif // __cplusplus
+#endif // !__cplusplus
 
+	//! Red, green, blue and alpha color values
 	float r, g, b, a;
-} aiColor4D_t;
+};
 
 
 // ---------------------------------------------------------------------------
 /** Represents a string, zero byte terminated 
 */
 // ---------------------------------------------------------------------------
-typedef struct aiString
+struct aiString
 {
 #ifdef __cplusplus
 	inline aiString() :
@@ -110,11 +159,14 @@ typedef struct aiString
 		memcpy( data, pString.c_str(), length);
 		data[length] = 0;
 	}
-#endif // __cplusplus
+#endif // !__cplusplus
 
+	//! Length of the string excluding the terminal 0
 	size_t length;
+
+	//! String buffer. Size limit is MAXLEN
 	char data[MAXLEN];
-} aiString_t;
+} ;
 
 
 // ---------------------------------------------------------------------------
@@ -124,17 +176,27 @@ typedef struct aiString
 * AI_SUCCESS.
 */
 // ---------------------------------------------------------------------------
+
 enum aiReturn
 {
+	//! Indicates that a function was successful
 	AI_SUCCESS = 0x0,
+	//! Indicates that a function failed
 	AI_FAILURE = -0x1,
+	//! Indicates that a file was invalid
 	AI_INVALIDFILE = -0x2,
+	//! Indicates that not enough memory was available
+	//! to perform the requested operation
 	AI_OUTOFMEMORY = -0x3,
+	//! Indicates that an illegal argument has been
+	//! passed to a function. This is rarely used,
+	//! most functions assert in this case.
 	AI_INVALIDARG = -0x4
 };
 
+
 #ifdef __cplusplus
 }
-#endif
-#endif
+#endif //!  __cplusplus
+#endif //!! include guard
 

+ 5 - 8
include/aiVector3D.h

@@ -4,15 +4,13 @@
 
 #include <math.h>
 
-#include "aiAssert.h"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 // ---------------------------------------------------------------------------
 /** Represents a three-dimensional vector. */
-typedef struct aiVector3D
+struct aiVector3D
 {
 #ifdef __cplusplus
 	aiVector3D () : x(0.0f), y(0.0f), z(0.0f) {}
@@ -33,7 +31,7 @@ typedef struct aiVector3D
 #endif // __cplusplus
 
 	float x, y, z;	
-} aiVector3D_t;
+};
 
 #ifdef __cplusplus
 } // end extern "C"
@@ -71,16 +69,15 @@ inline aiVector3D operator * ( const aiVector3D& v, float f)
 // scalar division
 inline aiVector3D operator / ( const aiVector3D& v, float f)
 {
-	//ai_assert(0.0f != f);
+	
 	return v * (1/f);
 }
 
 // vector division
 inline aiVector3D operator / ( const aiVector3D& v, const aiVector3D& v2)
-	{
-	//ai_assert(0.0f != v2.x && 0.0f != v2.y && 0.0f != v2.z);
+{
 	return aiVector3D(v.x / v2.x,v.y / v2.y,v.z / v2.z);
-	}
+}
 
 // cross product
 inline aiVector3D operator ^ ( const aiVector3D& v1, const aiVector3D& v2)

+ 79 - 9
include/assimp.h

@@ -1,14 +1,58 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 C-API to the Asset Import Library. */
 #ifndef AI_ASSIMP_H_INC
 #define AI_ASSIMP_H_INC
 
+#include "aiTypes.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 struct aiScene;
 struct aiFileIO;
-//enum aiOrigin;
+struct aiString;
+
 
 // ---------------------------------------------------------------------------
 /** Reads the given file and returns its content.
@@ -20,14 +64,14 @@ struct aiFileIO;
 * this file. If the import fails, NULL is returned instead. Call 
 * aiGetErrorString() to retrieve a human-readable error text.
 * @param pFile Path and filename of the file to be imported, 
-*        expected to be a null-terminated c-string.
+*   expected to be a null-terminated c-string. NULL is not a valid value.
 * @param pFlags Optional post processing steps to be executed after 
 *   a successful import. Provide a bitwise combination of the #aiPostProcessSteps
 *   flags.
 * @return Pointer to the imported data or NULL if the import failed. 
 */
 // ---------------------------------------------------------------------------
-const aiScene* aiImportFile( const char* pFile, unsigned int pFlags);
+const C_STRUCT aiScene* aiImportFile( const char* pFile, unsigned int pFlags);
 
 
 // ---------------------------------------------------------------------------
@@ -41,13 +85,16 @@ const aiScene* aiImportFile( const char* pFile, unsigned int pFlags);
 * this file. If the import fails, NULL is returned instead. Call 
 * aiGetErrorString() to retrieve a human-readable error text.
 * @param pFile aiFileIO structure.  All functions pointers must be
-*        initialized. aiFileIO::OpenFunc() and aiFileIO::CloseFunc()
-*        will be used to open other files in the fs if the asset to be 
-*        loaded depends on them.
+*   initialized. aiFileIO::OpenFunc() and aiFileIO::CloseFunc()
+*   will be used to open other files in the fs if the asset to be 
+*   loaded depends on them. NULL is not a valid value.
 * @return Pointer to the imported data or NULL if the import failed. 
+*
+* @note The C-API creates a new Importer instance internally for each call 
+* to this function. Therefore the C-API is thread-safe. 
 */
 // ---------------------------------------------------------------------------
-const aiScene* aiImportFileEx( const aiFileIO* pFile);
+const C_STRUCT aiScene* aiImportFileEx( const C_STRUCT aiFileIO* pFile);
 
 
 
@@ -55,10 +102,10 @@ const aiScene* aiImportFileEx( const aiFileIO* pFile);
 /** Releases all resources associated with the given import process.
 *
 * Call this function after you're done with the imported data.
-* @param pScene The imported data to release.
+* @param pScene The imported data to release. NULL is a valid value.
 */
 // ---------------------------------------------------------------------------
-void aiReleaseImport( const aiScene* pScene);
+void aiReleaseImport( const C_STRUCT aiScene* pScene);
 
 
 // ---------------------------------------------------------------------------
@@ -70,6 +117,29 @@ void aiReleaseImport( const aiScene* pScene);
 // ---------------------------------------------------------------------------
 const char* aiGetErrorString();
 
+
+// ---------------------------------------------------------------------------
+/** Returns whether a given file extension is supported by ASSIMP
+*
+* @param szExtension Extension for which the function queries support.
+* Must include a leading dot '.'. Example: ".3ds", ".md3"
+* @return 1 if the extension is supported, 0 otherwise
+*/
+// ---------------------------------------------------------------------------
+int aiIsExtensionSupported(const char* szExtension);
+
+
+// ---------------------------------------------------------------------------
+/** Get a full list of all file extensions generally supported by ASSIMP.
+ *
+ * If a file extension is contained in the list this does, of course, not
+ * mean that ASSIMP is able to load all files with this extension.
+ * @param szOut String to receive the extension list.
+ * Format of the list: "*.3ds;*.obj;*.dae". NULL is not a valid parameter.
+*/
+// ---------------------------------------------------------------------------
+void aiGetExtensionList(C_STRUCT aiString* szOut);
+
 #ifdef __cplusplus
 }
 #endif

+ 78 - 12
include/assimp.hpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 CPP-API to the Asset Import Library. */
 #ifndef AI_ASSIMP_HPP_INC
 #define AI_ASSIMP_HPP_INC
@@ -32,10 +73,13 @@ class IOSystem;
 * GetErrorString().
 *
 * If you need the Importer to do custom file handling to access the files,
-* implement IOSystem and IOStream and supply an instance of your custom IOSystem
-* implementation by calling SetIOHandler() before calling ReadFile(). If you
-* do not assign a custion IO handler, a default handler using the standard C++
-* IO logic will be used.
+* implement IOSystem and IOStream and supply an instance of your custom 
+* IOSystem implementation by calling SetIOHandler() before calling ReadFile().
+* If you do not assign a custion IO handler, a default handler using the 
+* standard C++ IO logic will be used.
+*
+* @note One Importer instance is not thread-safe. If you use multiple
+* threads for loading each thread should manage its own Importer instance.
 */
 class Importer
 {
@@ -55,16 +99,17 @@ public:
 	~Importer();
 
 	// -------------------------------------------------------------------
-	/** Supplies a custom IO handler to the importer to open and access files.
-	 * If you need the importer to use custion IO logic to access the files,
-	 * you need to provide a custom implementation of IOSystem and IOFile
-	 * to the importer. Then create an instance of your custion IOSystem
-	 * implementation and supply it by this function.
+	/** Supplies a custom IO handler to the importer to use to open and
+	 * access files. If you need the importer to use custion IO logic to 
+	 * access the files, you need to provide a custom implementation of 
+	 * IOSystem and IOFile to the importer. Then create an instance of 
+	 * your custion IOSystem implementation and supply it by this function.
 	 *
-	 * The Importer takes ownership of the object and will destroy it afterwards.
-	 * The previously assigned handler will be deleted.
+	 * The Importer takes ownership of the object and will destroy it 
+	 * afterwards. The previously assigned handler will be deleted.
 	 *
-	 * @param pIOHandler The IO handler to be used in all file accesses of the Importer.
+	 * @param pIOHandler The IO handler to be used in all file accesses 
+	 * of the Importer. NULL resets it to the default handler.
 	 */
 	void SetIOHandler( IOSystem* pIOHandler);
 
@@ -95,6 +140,27 @@ public:
 	inline const std::string& GetErrorString() const 
 		{ return mErrorString; }
 
+
+	// -------------------------------------------------------------------
+	/** Returns whether a given file extension is supported by ASSIMP
+	*
+	* @param szExtension Extension for which the function queries support.
+	* Must include a leading dot '.'. Example: ".3ds", ".md3"
+	* @return true if the extension is supported, false otherwise
+	*/
+	bool IsExtensionSupported(const std::string& szExtension);
+
+
+	// -------------------------------------------------------------------
+	/** Get a full list of all file extensions generally supported by ASSIMP.
+	*
+	* If a file extension is contained in the list this does, of course, not
+	* mean that ASSIMP is able to load all files with this extension.
+	* @param szOut String to receive the extension list.
+	* Format of the list: "*.3ds;*.obj;*.dae". NULL is not a valid parameter.
+	*/
+	void GetExtensionList(std::string& szOut);
+
 private:
 	/** Empty copy constructor. */
 	Importer(const Importer &other);

+ 39 - 8
tools/assimp_view/Background.cpp

@@ -1,12 +1,43 @@
-//-------------------------------------------------------------------------------
-/**
-*	This program is distributed under the terms of the GNU Lesser General
-*	Public License (LGPL). 
-*
-*	ASSIMP Viewer Utility
-*
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 "stdafx.h"
 #include "assimp_view.h"

+ 1 - 0
tools/assimp_view/Display.cpp

@@ -0,0 +1 @@
+#include "stdafx.h"

+ 0 - 0
tools/assimp_view/Display.h


+ 39 - 8
tools/assimp_view/HelpDialog.cpp

@@ -1,12 +1,43 @@
-//-------------------------------------------------------------------------------
-/**
-*	This program is distributed under the terms of the GNU Lesser General
-*	Public License (LGPL). 
-*
-*	ASSIMP Viewer Utility
-*
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 "stdafx.h"
 #include "assimp_view.h"

+ 39 - 8
tools/assimp_view/Input.cpp

@@ -1,12 +1,43 @@
-//-------------------------------------------------------------------------------
-/**
-*	This program is distributed under the terms of the GNU Lesser General
-*	Public License (LGPL). 
-*
-*	ASSIMP Viewer Utility
-*
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 "stdafx.h"
 #include "assimp_view.h"

+ 39 - 8
tools/assimp_view/LogDisplay.cpp

@@ -1,12 +1,43 @@
-//-------------------------------------------------------------------------------
-/**
-*	This program is distributed under the terms of the GNU Lesser General
-*	Public License (LGPL). 
-*
-*	ASSIMP Viewer Utility
-*
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 "stdafx.h"
 #include "assimp_view.h"

+ 39 - 8
tools/assimp_view/LogDisplay.h

@@ -1,12 +1,43 @@
-//-------------------------------------------------------------------------------
-/**
-*	This program is distributed under the terms of the GNU Lesser General
-*	Public License (LGPL). 
-*
-*	ASSIMP Viewer Utility
-*
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
 */
-//-------------------------------------------------------------------------------
 
 #if (!defined AV_LOG_DISPLAY_H_INCLUDED)
 #define AV_LOG_DISPLAY_H_INCLUDE

+ 103 - 0
tools/assimp_view/LogWindow.cpp

@@ -0,0 +1,103 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 "stdafx.h"
+#include "assimp_view.h"
+
+
+namespace AssimpView {
+
+/* extern */ CLogWindow CLogWindow::s_cInstance;
+
+//-------------------------------------------------------------------------------
+// Message procedure for the log window
+//-------------------------------------------------------------------------------
+INT_PTR CALLBACK LogDialogProc(HWND hwndDlg,UINT uMsg,
+	WPARAM wParam,LPARAM lParam)
+	{
+	lParam;
+	switch (uMsg)
+		{
+		case WM_INITDIALOG:
+			{
+			
+			return TRUE;
+			}
+
+		case WM_SIZE:
+			{
+			int x = LOWORD(lParam);
+			int y = HIWORD(lParam);
+
+			SetWindowPos(GetDlgItem(hwndDlg,IDC_EDIT1),NULL,0,0,
+				x,y,SWP_NOMOVE|SWP_NOZORDER);
+
+			return TRUE;
+			}
+		case WM_CLOSE:
+			EndDialog(hwndDlg,0);
+			return TRUE;
+		};
+	return FALSE;
+	}
+
+//-------------------------------------------------------------------------------
+void CLogWindow::Init ()
+{
+	this->hwnd = ::CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_LOGVIEW),
+		NULL,&LogDialogProc);
+
+	if (!this->hwnd)
+	{
+		CLogDisplay::Instance().AddEntry("[ERROR] Unable to create logger window",
+			D3DCOLOR_ARGB(0xFF,0,0xFF,0));
+	}
+}
+//-------------------------------------------------------------------------------
+void CLogWindow::Show()
+{
+	if (this->hwnd)
+	{
+		ShowWindow(this->hwnd,SW_SHOW);
+	}
+}
+
+}; //! AssimpView

+ 78 - 0
tools/assimp_view/LogWindow.h

@@ -0,0 +1,78 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+#if (!defined AV_LOG_WINDOW_H_INCLUDED)
+#define AV_LOG_WINDOW_H_INCLUDE
+
+//-------------------------------------------------------------------------------
+/**	\brief Class to display log strings in a separate window
+*/
+//-------------------------------------------------------------------------------
+class CLogWindow
+	{
+private:
+
+	CLogWindow() : hwnd(NULL)  {}
+
+public:
+
+
+	// Singleton accessors
+	static CLogWindow s_cInstance;
+	inline static CLogWindow& Instance ()
+		{
+		return s_cInstance;
+		}
+
+	// initializes the log window
+	void Init ();
+
+	// Shows the log window
+	void Show();
+
+private:
+
+	// Window handle
+	HWND hwnd;
+
+	};
+
+#endif // AV_LOG_DISPLA

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 302 - 188
tools/assimp_view/Material.cpp


+ 181 - 109
tools/assimp_view/MessageProc.cpp

@@ -1,12 +1,43 @@
-//-------------------------------------------------------------------------------
-/**
-*	This program is distributed under the terms of the GNU Lesser General
-*	Public License (LGPL). 
-*
-*	ASSIMP Viewer Utility
-*
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 "stdafx.h"
 #include "assimp_view.h"
@@ -15,9 +46,7 @@
 namespace AssimpView {
 
 // Static array to keep custom color values
-COLORREF g_aclCustomColors[16] =
-	{0};
-
+COLORREF g_aclCustomColors[16] = {0};
 
 //-------------------------------------------------------------------------------
 // Setup file associations for all formats supported by the library
@@ -27,12 +56,6 @@ COLORREF g_aclCustomColors[16] =
 //-------------------------------------------------------------------------------
 void MakeFileAssociations()
 	{
-	/*
-	; .wscript
-	root: HKCR; Flags: deletekey; Subkey: ".uscript";  ValueType: string; ValueData: "UE_WSCRIPT_CLASS"; Components: rt
-	root: HKCR; Flags: deletekey; Subkey: "UE_WSCRIPT_CLASS";  ValueName:; ValueType: string; ValueData: "UtopicEngine Console Script"; Components: rt
-	root: HKCR; Flags: deletekey; Subkey: "UE_WSCRIPT_CLASS\shell\open\command";   ValueName:; ValueType: string; ValueData: "notepad.exe %1"; Components: rt
-	*/
 	char szTemp2[MAX_PATH];
 	char szTemp[MAX_PATH + 10];
 
@@ -45,130 +68,105 @@ void MakeFileAssociations()
 	// .3ds
 	// -------------------------------------------------
 	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.3ds",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AV3DSCLASS",(DWORD)strlen("AV3DSCLASS")+1);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
 	RegCloseKey(hTemp);
 
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AV3DSCLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AV3DSCLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1);
-	RegCloseKey(hTemp);
 
 	// ------------------------------------------------- 
 	// .x
 	// -------------------------------------------------
 	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.x",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVXCLASS",(DWORD)strlen("AVXCLASS")+1);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVXCLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVXCLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
 	RegCloseKey(hTemp);
 
 	// ------------------------------------------------- 
 	// .obj
 	// -------------------------------------------------
 	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.obj",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVOBJCLASS",(DWORD)strlen("AVOBJCLASS")+1);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVOBJCLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVOBJCLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
 	RegCloseKey(hTemp);
 
 	// ------------------------------------------------- 
 	// .ms3d
 	// -------------------------------------------------
 	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ms3d",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVMS3DCLASS",(DWORD)strlen("AVMS3DCLASS")+1);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMS3DCLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMS3DCLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
 	RegCloseKey(hTemp);
 
 	// ------------------------------------------------- 
 	// .md3
 	// -------------------------------------------------
 	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md3",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVMD3CLASS",(DWORD)strlen("AVMD3CLASS")+1);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD3CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD3CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
 	RegCloseKey(hTemp);
 
 	// ------------------------------------------------- 
 	// .md2
 	// -------------------------------------------------
 	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md2",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVMD2CLASS",(DWORD)strlen("AVMD2CLASS")+1);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD3CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD2CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
 	RegCloseKey(hTemp);
 
 	// ------------------------------------------------- 
-	// .md4
+	// .md4/mdr
 	// -------------------------------------------------
 	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md4",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVMD4CLASS",(DWORD)strlen("AVMD4CLASS")+1);
-	RegCloseKey(hTemp);
-
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD4CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
 	RegCloseKey(hTemp);
 
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD4CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1);
+	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.mdr",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
 	RegCloseKey(hTemp);
 
 	// ------------------------------------------------- 
 	// .md5
 	// -------------------------------------------------
 	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md5",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVMD5CLASS",(DWORD)strlen("AVMD5CLASS")+1);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
 	RegCloseKey(hTemp);
 
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD5CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
+	// ------------------------------------------------- 
+	// .mdl
+	// -------------------------------------------------
+	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.mdl",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
 	RegCloseKey(hTemp);
 
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD5CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1);
-	RegCloseKey(hTemp);
 
 	// ------------------------------------------------- 
 	// .ply
 	// -------------------------------------------------
 	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ply",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
-	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVPLYCLASS",(DWORD)strlen("AVPLYCLASS")+1);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
+	RegCloseKey(hTemp);
+
+
+	// ------------------------------------------------- 
+	// .ase/.ask
+	// -------------------------------------------------
+	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ase",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
+	RegCloseKey(hTemp);
+	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ask",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
+	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1);
 	RegCloseKey(hTemp);
 
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVPLYCLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
+
+
+	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
 	RegCloseKey(hTemp);
 
-	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVPLYCLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
+	RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
 	RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1);
 	RegCloseKey(hTemp);
 
 	CLogDisplay::Instance().AddEntry("[OK] File assocations have been registered",
 		D3DCOLOR_ARGB(0xFF,0,0xFF,0));
+
+	aiString sz;
+	aiGetExtensionList(&sz);
+	CLogDisplay::Instance().AddEntry(sz.data,
+		D3DCOLOR_ARGB(0xFF,0,0xFF,0));
 	}
 
 
@@ -248,6 +246,47 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
 			SetDlgItemText(hwndDlg,IDC_EFACE,"0");
 			SetDlgItemText(hwndDlg,IDC_EMAT,"0");
 			SetDlgItemText(hwndDlg,IDC_ESHADER,"0");
+			SetDlgItemText(hwndDlg,IDC_ENODE,"0");
+			SetDlgItemText(hwndDlg,IDC_ETEX,"0");
+
+			// setup the default window title
+			SetWindowText(hwndDlg,AI_VIEW_CAPTION_BASE);
+			{
+			// read some UI properties from the registry and apply them
+			DWORD dwValue;
+			DWORD dwTemp = sizeof( DWORD );
+			HKEY hTemp;
+			RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ASSIMP\\Viewer",
+				NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
+
+			if(ERROR_SUCCESS != RegQueryValueEx(hTemp,"LastUIState",NULL,NULL,
+				(BYTE*)&dwValue,&dwTemp))
+			{
+				dwValue = 1;
+			}
+			if (0 == dwValue)
+			{
+				// collapse the viewer
+				// adjust the size
+				RECT sRect;
+				GetWindowRect(hwndDlg,&sRect);
+				sRect.right -= sRect.left;
+				sRect.bottom -= sRect.top;
+
+				RECT sRect2;
+				GetWindowRect(GetDlgItem ( hwndDlg, IDC_BLUBB ),&sRect2);
+				sRect2.left -= sRect.left;
+				sRect2.top -= sRect.top;
+
+				SetWindowPos(hwndDlg,NULL,0,0,sRect.right-188,sRect.bottom,
+						SWP_NOMOVE | SWP_NOZORDER);
+				SetWindowText(GetDlgItem(hwndDlg,IDC_BLUBB),">>");
+			}
+			else
+			{
+				CheckDlgButton(hwndDlg,IDC_BLUBB,BST_CHECKED);
+			}
+			RegCloseKey(hTemp);}
 			return TRUE;
 
 		case WM_MOUSEWHEEL:
@@ -365,34 +404,6 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
 					g_eClick = EClickPos_CircleVert;
 					}
 				}
-
-			// OLD version of this code. Not using a texture lookup to
-			// determine the exact position, but using maths and the fact
-			// that we have a circle f(x) = m +rx ;-)
-#if 0
-			g_eClick = EClickPos_Circle;
-			if (yPos < 10 && yPos > -10)
-				{
-				if ((xPos2 > fHalfX-5 && xPos2 < fHalfX+15) ||
-					(xPos2 > fHalfX+(int)sDesc.Width-10 && xPos2 < fHalfX+(int)sDesc.Width+10))
-					{
-					g_eClick = EClickPos_CircleHor;
-					}
-				}
-			else if (xPos < 10 && xPos > -10)
-				{
-				if ((yPos2 > fHalfY-5 && yPos2 < fHalfY+15) ||
-					(yPos2 > fHalfY+(int)sDesc.Height-10 && yPos2 < fHalfY+(int)sDesc.Height+10))
-					{
-					g_eClick = EClickPos_CircleVert;
-					}
-				}
-			else if (sqrtf((float)(xPos * xPos  + yPos * yPos)) > (float)(sDesc.Width/2))
-				{
-				g_eClick = EClickPos_Outside;
-				}
-#endif
-
 			return TRUE;
 
 		case WM_RBUTTONDOWN:
@@ -467,6 +478,10 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
 				DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_ABOUTBOX),
 					hwndDlg,&AboutMessageProc);
 				}
+			else if (ID_TOOLS_LOGWINDOW == LOWORD(wParam))
+				{
+					CLogWindow::Instance().Show();
+				}
 			else if (ID_VIEWER_H == LOWORD(wParam))
 				{
 				MakeFileAssociations();
@@ -657,10 +672,24 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
 					if (!sz)sz = strrchr(szFileName,'/');
 					if (!sz)*sz = 0;
 					}
+
+				// get a list of all file extensions supported by ASSIMP
+				aiString sz;
+				aiGetExtensionList(&sz);
+
+				char szList[MAXLEN + 100];
+				strcpy(szList,"ASSIMP assets");
+				char* szCur = szList + 14;
+				strcpy(szCur,sz.data);
+				szCur += sz.length+1;
+				strcpy(szCur,"All files");
+				szCur += 10;
+				strcpy(szCur,"*.*");
+				szCur[4] = 0;
+
 				OPENFILENAME sFilename1 = {
 					sizeof(OPENFILENAME),
-					g_hDlg,GetModuleHandle(NULL), 
-					"ASSIMP assets\0*.x;*.obj;*.ms3d;*.3ds;*.md3;*.md1;*.md2;*.md4;*.md5;*.ply\0All files\0*.*", NULL, 0, 1, 
+					g_hDlg,GetModuleHandle(NULL), szList, NULL, 0, 1, 
 					szFileName, MAX_PATH, NULL, 0, NULL, 
 					"Import Asset into ASSIMP",
 					OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, 
@@ -728,6 +757,44 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
 
 					SetupFPSView();
 					}
+				else if (IDC_BLUBB == LOWORD(wParam))
+					{
+					// adjust the size
+					RECT sRect;
+					GetWindowRect(hwndDlg,&sRect);
+					sRect.right -= sRect.left;
+					sRect.bottom -= sRect.top;
+
+					RECT sRect2;
+					GetWindowRect(GetDlgItem ( hwndDlg, IDC_BLUBB ),&sRect2);
+					sRect2.left -= sRect.left;
+					sRect2.top -= sRect.top;
+
+					HKEY hTemp;
+					DWORD dwValue;
+					RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ASSIMP\\Viewer",
+						NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL);
+
+					if (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg,IDC_BLUBB))
+						{
+						SetWindowPos(hwndDlg,NULL,0,0,sRect.right-188,sRect.bottom,
+							SWP_NOMOVE | SWP_NOZORDER);
+
+						dwValue = 0;
+						SetWindowText(GetDlgItem(hwndDlg,IDC_BLUBB),">>");
+						RegSetValueExA(hTemp,"LastUIState",0,REG_DWORD,(const BYTE*)&dwValue,4);
+						}
+					else
+						{
+						SetWindowPos(hwndDlg,NULL,0,0,sRect.right+188,sRect.bottom,
+							SWP_NOMOVE | SWP_NOZORDER);
+
+						dwValue = 1;
+						SetWindowText(GetDlgItem(hwndDlg,IDC_BLUBB),"<<");
+						RegSetValueExA(hTemp,"LastUIState",0,REG_DWORD,(const BYTE*)&dwValue,4);
+						}
+					RegCloseKey(hTemp);
+					}
 				else if (IDC_TOGGLENORMALS == LOWORD(wParam))
 					{
 					g_sOptions.bRenderNormals = !g_sOptions.bRenderNormals; 
@@ -898,6 +965,11 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
 
 	CLogDisplay::Instance().AddEntry("[OK] The viewer has been initialized successfully");
 
+	// create the log window
+	CLogWindow::Instance().Init();
+	// set the focus to the main window
+	SetFocus(g_hDlg);
+
 	// recover background skyboxes/textures from the last session
 	HKEY hTemp;
 	union

+ 39 - 57
tools/assimp_view/Shaders.cpp

@@ -1,12 +1,43 @@
-//-------------------------------------------------------------------------------
-/**
-*	This program is distributed under the terms of the GNU Lesser General
-*	Public License (LGPL). 
-*
-*	ASSIMP Viewer Utility
-*
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 "stdafx.h"
 #include "assimp_view.h"
@@ -15,16 +46,6 @@
 namespace AssimpView {
 
 std::string g_szNormalsShader = std::string(
-	//-------------------------------------------------------------------------------\n"
-	/**\n"
-	*	This program is distributed under the terms of the GNU Lesser General\n
-	*	Public License (LGPL). \n
-	*\n
-	*	ASSIMP Viewer Utility\n
-	*\n"
-	*/
-	//-------------------------------------------------------------------------------\n"
-
 
 	// World * View * Projection matrix\n"
 	// NOTE: Assume that the material uses a WorldViewProjection matrix\n"
@@ -90,16 +111,6 @@ std::string g_szNormalsShader = std::string(
 	);
 
 std::string g_szSkyboxShader = std::string(
-	//-------------------------------------------------------------------------------\n"
-	/**\n"
-	*	This program is distributed under the terms of the GNU Lesser General\n
-	*	Public License (LGPL). \n
-	*\n
-	*	ASSIMP Viewer Utility\n
-	*\n"
-	*/
-	//-------------------------------------------------------------------------------\n"
-
 
 	// ----------------------------------------------------------------------------\n"
 	// Sampler and texture for the skybox\n"
@@ -252,16 +263,6 @@ std::string g_szSkyboxShader = std::string(
 		);
 
 std::string g_szDefaultShader = std::string(
-	//-------------------------------------------------------------------------------\n"
-	/**\n"
-	*	This program is distributed under the terms of the GNU Lesser General\n
-	*	Public License (LGPL). \n
-	*\n
-	*	ASSIMP Viewer Utility\n
-	*\n"
-	*/
-	//-------------------------------------------------------------------------------\n"
-
 
 	// World * View * Projection matrix\n"
 	// NOTE: Assume that the material uses a WorldViewProjection matrix\n"
@@ -453,16 +454,6 @@ std::string g_szDefaultShader = std::string(
 
 
 std::string g_szMaterialShader = std::string(
-	//-------------------------------------------------------------------------------\n"
-	/**\n"
-	*	This program is distributed under the terms of the GNU Lesser General\n
-	*	Public License (LGPL). \n
-	*\n
-	*	ASSIMP Viewer Utility\n
-	*\n"
-	*/
-	//-------------------------------------------------------------------------------\n"
-
 
 	// World * View * Projection matrix\n"
 	// NOTE: Assume that the material uses a WorldViewProjection matrix\n"
@@ -1143,15 +1134,6 @@ std::string g_szMaterialShader = std::string(
 		);
 
 std::string g_szPassThroughShader = std::string(
-		//-------------------------------------------------------------------------------\n"
-		/**\n"
-		*	This program is distributed under the terms of the GNU Lesser General\n
-		*	Public License (LGPL). \n
-		*\n
-		*	ASSIMP Viewer Utility\n
-		*\n"
-		*/
-		//-------------------------------------------------------------------------------\n"
 
 		"texture TEXTURE_2D;\n"
 		"sampler TEXTURE_SAMPLER = sampler_state\n"

BIN
tools/assimp_view/assimp_view.aps


+ 418 - 41
tools/assimp_view/assimp_view.cpp

@@ -67,7 +67,7 @@ AssetHelper *g_pcAsset				= NULL;
 unsigned char* g_szImageMask		= NULL;
 
 //-------------------------------------------------------------------------------
-// table of colors used for normal vectors. 
+// Table of colors used for normal vectors. 
 //-------------------------------------------------------------------------------
 D3DXVECTOR4 g_aclNormalColors[14] = 
 	{
@@ -94,27 +94,41 @@ D3DXVECTOR4 g_aclNormalColors[14] =
 
 
 //-------------------------------------------------------------------------------
-//!	\brief Entry point for loader thread
+// Entry point for the loader thread
+// The laoder thread loads the asset while the progress dialog displays the
+// smart progress bar
 //-------------------------------------------------------------------------------
 DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
 	{
 	UNREFERENCED_PARAMETER(lpParameter);
+
+	// get current time
 	double fCur = (double)timeGetTime();
 
+	// call ASSIMPs C-API to load the file
 	g_pcAsset->pcScene = aiImportFile(g_szFileName,
-		aiProcess_CalcTangentSpace | aiProcess_JoinIdenticalVertices | aiProcess_Triangulate |
-		aiProcess_GenSmoothNormals | aiProcess_ConvertToLeftHanded	 | aiProcess_SplitLargeMeshes);
-
+		aiProcess_CalcTangentSpace		| // calculate tangents and bitangents
+		aiProcess_JoinIdenticalVertices | // join identical vertices
+		aiProcess_Triangulate			| // triangulate n-polygons
+		aiProcess_GenSmoothNormals		| // generate smooth normal vectors if not existing
+		aiProcess_ConvertToLeftHanded	| // convert everything to D3D left handed space
+		aiProcess_SplitLargeMeshes);      // split large, unrenderable meshes into submeshes
+
+	// get the end time of zje operation, calculate delta t
 	double fEnd = (double)timeGetTime();
 	double dTime = (fEnd - fCur) / 1000;
 	char szTemp[128];
 	sprintf(szTemp,"%.5f",(float)dTime);
 	SetDlgItemText(g_hDlg,IDC_ELOAD,szTemp);
 	g_bLoadingFinished = true;
+
+	// check whether the loading process has failed ...
 	if (NULL == g_pcAsset->pcScene)
 		{
 		CLogDisplay::Instance().AddEntry("[ERROR] Unable to load this asset:",
 			D3DCOLOR_ARGB(0xFF,0xFF,0,0));
+
+		// print ASSIMPs error string to the log display
 		CLogDisplay::Instance().AddEntry(aiGetErrorString(),
 			D3DCOLOR_ARGB(0xFF,0xFF,0,0));
 		return 1;
@@ -123,42 +137,72 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
 	}
 
 //-------------------------------------------------------------------------------
+// Recursivly count the number of nodes in an asset's node graph
+// Used by LoadAsset()
+//-------------------------------------------------------------------------------
+void GetNodeCount(aiNode* pcNode, unsigned int* piCnt)
+{
+	*piCnt = *piCnt+1;
+	for (unsigned int i = 0; i < pcNode->mNumChildren;++i)
+		GetNodeCount(pcNode->mChildren[i],piCnt);
+}
+
+//-------------------------------------------------------------------------------
+// load the current asset
+// THe path to the asset is specified in the global path variable
 //-------------------------------------------------------------------------------
 int LoadAsset(void)
-	{
+{
+	// set the world and world rotation matrices to the identuty
 	g_mWorldRotate = aiMatrix4x4();
 	g_mWorld = aiMatrix4x4();
 
+	// create a helper thread to load the asset
 	DWORD dwID;
 	g_bLoadingCanceled = false;
 	g_pcAsset = new AssetHelper();
 	g_hThreadHandle = CreateThread(NULL,0,&LoadThreadProc,NULL,0,&dwID);
+
+	if (!g_hThreadHandle)
+	{
+		CLogDisplay::Instance().AddEntry(
+			"[ERROR] Unable to create helper thread for loading",
+			D3DCOLOR_ARGB(0xFF,0xFF,0,0));
+		return 0;
+	}
+
+	// show the progress bar dialog
 	DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_LOADDIALOG),
 		g_hDlg,&ProgressMessageProc);
 
+	// now we should have loaded the asset. Check this ...
 	g_bLoadingFinished = false;
 	if (!g_pcAsset || !g_pcAsset->pcScene)
-		{
+	{
 		if (g_pcAsset)
-			{
+		{
 			delete g_pcAsset;
 			g_pcAsset = NULL;
-			}
-		return 0;
 		}
+		return 0;
+	}
 
+	// allocate a new MeshHelper array and build a new instance
+	// for each mesh in the original asset
 	g_pcAsset->apcMeshes = new AssetHelper::MeshHelper*[
 		g_pcAsset->pcScene->mNumMeshes]();
 
+	// get the number of vertices/faces in the model
 	unsigned int iNumVert = 0;
 	unsigned int iNumFaces = 0;
 	for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
-		{
+	{
 		iNumVert += g_pcAsset->pcScene->mMeshes[i]->mNumVertices;
 		iNumFaces += g_pcAsset->pcScene->mMeshes[i]->mNumFaces;
 		g_pcAsset->apcMeshes[i] = new AssetHelper::MeshHelper();
-		}
-	char szOut[120];
+	}
+	// and fill the statistic edit controls
+	char szOut[1024];
 	sprintf(szOut,"%i",(int)iNumVert);
 	SetDlgItemText(g_hDlg,IDC_EVERT,szOut);
 	sprintf(szOut,"%i",(int)iNumFaces);
@@ -166,25 +210,41 @@ int LoadAsset(void)
 	sprintf(szOut,"%i",(int)g_pcAsset->pcScene->mNumMaterials);
 	SetDlgItemText(g_hDlg,IDC_EMAT,szOut);
 
+	// need to get the number of nodes
+	iNumVert = 0;
+	GetNodeCount(g_pcAsset->pcScene->mRootNode,&iNumVert);
+	sprintf(szOut,"%i",(int)iNumVert);
+	SetDlgItemText(g_hDlg,IDC_ENODE,szOut);
+
+	// build a new caption string for the viewer
+	sprintf(szOut,AI_VIEW_CAPTION_BASE " [%s]",g_szFileName);
+	SetWindowText(g_hDlg,szOut);
+
+	// scale the asset vertices to fit into the viewer window
 	ScaleAsset();
 
+	// reset the camera view to the default position
 	g_sCamera.vPos = aiVector3D(0.0f,0.0f,-10.0f);
 	g_sCamera.vLookAt = aiVector3D(0.0f,0.0f,1.0f);
 	g_sCamera.vUp = aiVector3D(0.0f,1.0f,0.0f);
 	g_sCamera.vRight = aiVector3D(0.0f,1.0f,0.0f);
 
+	// build native D3D vertex/index buffers, textures, materials
 	return CreateAssetData();
-	}
+}
 
 
 //-------------------------------------------------------------------------------
+// Delete the loaded asset
 //-------------------------------------------------------------------------------
 int DeleteAsset(void)
 	{
 	if (!g_pcAsset)return 0;
 
+	// don't anymore know why this was necessary ...
 	Render();
 
+	// delete everything
 	DeleteAssetData();
 	for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
 		{
@@ -195,9 +255,16 @@ int DeleteAsset(void)
 	delete g_pcAsset;
 	g_pcAsset = NULL;
 
+	// clear all stats edit controls
 	SetDlgItemText(g_hDlg,IDC_EVERT,"0");
 	SetDlgItemText(g_hDlg,IDC_EFACE,"0");
 	SetDlgItemText(g_hDlg,IDC_EMAT,"0");
+	SetDlgItemText(g_hDlg,IDC_ENODE,"0");
+	SetDlgItemText(g_hDlg,IDC_ESHADER,"0");
+	SetDlgItemText(g_hDlg,IDC_ETEX,"0");
+
+	// reset the caption of the viewer window
+	SetWindowText(g_hDlg,AI_VIEW_CAPTION_BASE);
 	return 1;
 	}
 
@@ -357,12 +424,12 @@ int GenerateNormalsAsLineList(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSo
 // The animations are added in order
 //-------------------------------------------------------------------------------
 int FillAnimList(void)
-	{
+{
 	// clear the combo box
 	SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_RESETCONTENT,0,0);
 
 	if (0 == g_pcAsset->pcScene->mNumAnimations)
-		{
+	{
 		// disable all UI components related to animations
 		EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),FALSE);
 		EnableWindow(GetDlgItem(g_hDlg,IDC_SPEED),FALSE);
@@ -374,7 +441,7 @@ int FillAnimList(void)
 		EnableWindow(GetDlgItem(g_hDlg,IDC_COMBO1),FALSE);
 		}
 	else
-		{
+	{
 		// reenable all animation components if they have been
 		// disabled for a previous mesh
 		EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),TRUE);
@@ -388,14 +455,277 @@ int FillAnimList(void)
 
 		// now fill in all animation names
 		for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumAnimations;++i)
-			{
+		{
 			SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_ADDSTRING,0,
 				( LPARAM ) g_pcAsset->pcScene->mAnimations[i]->mName.data);
+		}
+	}
+	return 1;
+}
+
+
+//-------------------------------------------------------------------------------
+// Add a node to the display list
+// Recusrivly add all subnodes
+// iNode - Index of the node image in the tree view's image lust
+// iIndex - Index of the node in the parent's child list
+// iDepth - Current depth of the node
+// pcNode - Node object
+// hRoot - Parent tree view node
+//-------------------------------------------------------------------------------
+int AddNodeToDisplayList(unsigned int iNode,
+	unsigned int iIndex, 
+	unsigned int iDepth,
+	const aiNode* pcNode,
+	HTREEITEM hRoot)
+{
+	ai_assert(NULL != pcNode);
+
+	char chTemp[512];
+
+	if(0 == pcNode->mName.length)
+	{
+		if (iNode >= 100)
+		{
+			iNode += iDepth  * 1000;
+		}
+		else if (iNode >= 10)
+		{
+			iNode += iDepth  * 100;
+		}
+		else iNode += iDepth  * 10;
+		sprintf(chTemp,"Node %i",iNode);
+	}
+	else strcpy(chTemp,pcNode->mName.data);
+
+	TVITEMEX tvi; 
+	TVINSERTSTRUCT sNew;
+	tvi.pszText = chTemp;
+	tvi.cchTextMax = (int)strlen(chTemp);
+	tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE;
+	tvi.iImage = iNode;
+	tvi.iSelectedImage = iNode;
+	tvi.lParam = (LPARAM)0; 
+
+	sNew.itemex = tvi; 
+	sNew.hInsertAfter = TVI_LAST; 
+	sNew.hParent = hRoot;
+
+	// add the item to the list
+	HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), 
+		TVM_INSERTITEM, 
+		0,
+		(LPARAM)(LPTVINSERTSTRUCT)&sNew);
+
+	// recursively add all child nodes
+	++iDepth;
+	for (unsigned int i = 0; i< pcNode->mNumChildren;++i)
+	{
+		AddNodeToDisplayList(iNode,i,iDepth,pcNode->mChildren[i],hTexture);
+	}
+	return 1;
+}
+
+
+//-------------------------------------------------------------------------------
+// Add a texture to the display list
+// pcMat - material containing the texture
+// hTexture - Handle to the material tree item
+// iTexture - Index of the texture image in the image list of the tree view
+// szPath - Path to the texture
+// iUVIndex - UV index to be used for the texture
+// fBlendFactor - Blend factor to be used for the texture
+// eTextureOp - texture operation to be used for the texture
+//-------------------------------------------------------------------------------
+int AddTextureToDisplayList(unsigned int iType,
+	unsigned int iIndex,
+	const aiString* szPath,
+	HTREEITEM hFX, 
+	const aiMaterial* pcMat,
+	unsigned int iTexture = 0,
+	unsigned int iUVIndex = 0,
+	const float fBlendFactor = 0.0f,
+	aiTextureOp eTextureOp = aiTextureOp_Multiply)
+{
+	char chTemp[512];
+	const char* sz = strrchr(szPath->data,'\\');
+	if (!sz)sz = strrchr(szPath->data,'/');
+	if (!sz)sz = szPath->data;
+
+	const char* szType;
+	switch (iType)
+	{
+	case AI_TEXTYPE_DIFFUSE:
+		szType = "Diffuse";break;
+	case AI_TEXTYPE_SPECULAR:
+		szType = "Specular";break;
+	case AI_TEXTYPE_AMBIENT:
+		szType = "Ambient";break;
+	case AI_TEXTYPE_EMISSIVE:
+		szType = "Emissive";break;
+	case AI_TEXTYPE_HEIGHT:
+		szType = "HeightMap";break;
+	case AI_TEXTYPE_NORMALS:
+		szType = "NormalMap";break;
+	case AI_TEXTYPE_SHININESS:
+		szType = "Shininess";break;
+	};
+	sprintf(chTemp,"%s %i (%s)",szType,iIndex+1,sz);
+
+	TVITEMEX tvi; 
+	TVINSERTSTRUCT sNew;
+	tvi.pszText = chTemp;
+	tvi.cchTextMax = (int)strlen(chTemp);
+	tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE;
+	tvi.iImage = iTexture;
+	tvi.iSelectedImage = iTexture;
+	tvi.lParam = (LPARAM)0; 
+
+	sNew.itemex = tvi; 
+	sNew.hInsertAfter = TVI_LAST; 
+	sNew.hParent = hFX;
+
+	// add the item to the list
+	HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), 
+		TVM_INSERTITEM, 
+		0,
+		(LPARAM)(LPTVINSERTSTRUCT)&sNew);
+	return 1;
+}
+
+
+//-------------------------------------------------------------------------------
+// Add a material and all sub textures to the display mode list
+// pcMat - material to be added
+// hRoot - Handle to the root of the tree view
+// iFX - Index of the material image in the image list of the tree view
+// iTexture - Index of the texture image in the image list of the tree view
+// iIndex - Material index
+//-------------------------------------------------------------------------------
+int AddMaterialToDisplayList(HTREEITEM hRoot, const aiMaterial* pcMat,
+	unsigned int iFX, unsigned int iTexture, unsigned int iIndex)
+{
+	// use the name of the material, if possible
+	char chTemp[512];
+	aiString szOut;
+	if (AI_SUCCESS != aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szOut))
+	{
+		sprintf(chTemp,"Material %i",iIndex+1);
+	}
+	else
+	{
+		sprintf(chTemp,"%s (%i)",szOut.data,iIndex+1);
+	}
+	TVITEMEX tvi; 
+	TVINSERTSTRUCT sNew;
+	tvi.pszText = chTemp;
+	tvi.cchTextMax = (int)strlen(chTemp);
+	tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_STATE;
+	tvi.iImage = iFX;
+	tvi.iSelectedImage = iFX;
+	tvi.lParam = (LPARAM)0; 
+	tvi.state = TVIS_EXPANDED | TVIS_EXPANDEDONCE ;
+
+	sNew.itemex = tvi; 
+	sNew.hInsertAfter = TVI_LAST; 
+	sNew.hParent = hRoot;
+
+	// add the item to the list
+	HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), 
+		TVM_INSERTITEM, 
+		0,
+		(LPARAM)(LPTVINSERTSTRUCT)&sNew);
+
+	// for each texture in the list ... add it
+	unsigned int iUV;
+	float fBlend;
+	aiTextureOp eOp;
+	aiString szPath;
+	for (unsigned int i = 0; i < 7;++i)
+	{
+		unsigned int iNum = 0;
+		while (true)
+		{
+			if (AI_SUCCESS != aiGetMaterialTexture(pcMat,iNum,i,
+				&szPath,&iUV,&fBlend,&eOp))
+			{
+				break;
 			}
+			AddTextureToDisplayList(i,iNum,&szPath,hTexture,
+				pcMat,iTexture,iUV,fBlend,eOp);
+			++iNum;
 		}
+	}
 	return 1;
+}
+
+//-------------------------------------------------------------------------------
+// Fill the UI combobox with a list of all supported view modi
+//
+// The display modes are added in order
+//-------------------------------------------------------------------------------
+int FillDisplayList(void)
+{
+	// Initialize the tree view window.
+
+	// First, create the image list we will need.
+#define NUM_BITMAPS 4
+	HIMAGELIST hIml = ImageList_Create( 16,16,ILC_COLOR24, NUM_BITMAPS, 0 );
+
+
+	// Load the bitmaps and add them to the image lists.
+	HBITMAP hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BFX));
+	int iFX = ImageList_Add(hIml, hBmp, NULL);
+	DeleteObject(hBmp);
+
+	hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BNODE));
+	int iNode = ImageList_Add(hIml, hBmp, NULL);
+	DeleteObject(hBmp);
+
+	hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTX));
+	int iTexture = ImageList_Add(hIml, hBmp, NULL);
+	DeleteObject(hBmp);
+
+	hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BROOT));
+	int iRoot = ImageList_Add(hIml, hBmp, NULL);
+	DeleteObject(hBmp);
+
+	// Associate the image list with the tree.
+	TreeView_SetImageList(GetDlgItem(g_hDlg,IDC_TREE1), hIml, TVSIL_NORMAL);
+
+	// fill in the first entry
+	TVITEMEX tvi; 
+	TVINSERTSTRUCT sNew;
+	tvi.pszText = "Model";
+	tvi.cchTextMax = (int)strlen(tvi.pszText);
+	tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_STATE;
+	tvi.state = TVIS_EXPANDED ;
+	tvi.iImage = iRoot;
+	tvi.iSelectedImage = iRoot;
+	tvi.lParam = (LPARAM)0; 
+
+	sNew.itemex = tvi; 
+    sNew.hInsertAfter = TVI_ROOT; 
+	sNew.hParent = 0;
+
+	HTREEITEM hRoot = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), 
+		TVM_INSERTITEM, 
+		0,
+		(LPARAM)(LPTVINSERTSTRUCT)&sNew);
+
+
+	// add each loaded material
+	for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMaterials;++i)
+	{
+		AddMaterialToDisplayList(hRoot,g_pcAsset->pcScene->mMaterials[i],
+			iFX,iTexture,i);
 	}
 
+	// now add all loaded nodes recursively
+	AddNodeToDisplayList(iNode,0,0,g_pcAsset->pcScene->mRootNode,hRoot);
+	return 1;
+}
+
 //-------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------
 int CreateAssetData(void)
@@ -416,29 +746,59 @@ int CreateAssetData(void)
 			MessageBox(g_hDlg,"Failed to create vertex buffer",
 				"ASSIMP Viewer Utility",MB_OK);
 			return 2;
+		}
+
+		// check whether we can use 16 bit indices
+		if (g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3 >= 65536)
+		{
+			// create 32 bit index buffer
+			if(FAILED( g_piDevice->CreateIndexBuffer( 4 *
+				g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3,
+				D3DUSAGE_WRITEONLY,
+				D3DFMT_INDEX32,
+				D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piIB,NULL)))
+			{
+				MessageBox(g_hDlg,"Failed to create 32 Bit index buffer",
+					"ASSIMP Viewer Utility",MB_OK);
+				return 2;
 			}
-		// create index buffer
-		if(FAILED( g_piDevice->CreateIndexBuffer( 4 *
-			g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3,
-			D3DUSAGE_WRITEONLY,
-			D3DFMT_INDEX32,
-			D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piIB,NULL)))
+
+			// now fill the index buffer
+			unsigned int* pbData;
+			g_pcAsset->apcMeshes[i]->piIB->Lock(0,0,(void**)&pbData,0);
+			for (unsigned int x = 0; x < g_pcAsset->pcScene->mMeshes[i]->mNumFaces;++x)
 			{
-			MessageBox(g_hDlg,"Failed to create index buffer",
-				"ASSIMP Viewer Utility",MB_OK);
-			return 2;
+				for (unsigned int a = 0; a < 3;++a)
+				{
+					*pbData++ = g_pcAsset->pcScene->mMeshes[i]->mFaces[x].mIndices[a];
+				}
+			}
+		}
+		else
+		{
+			// create 16 bit index buffer
+			if(FAILED( g_piDevice->CreateIndexBuffer( 2 *
+				g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3,
+				D3DUSAGE_WRITEONLY,
+				D3DFMT_INDEX16,
+				D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piIB,NULL)))
+			{
+				MessageBox(g_hDlg,"Failed to create 16 Bit index buffer",
+					"ASSIMP Viewer Utility",MB_OK);
+				return 2;
 			}
 
-		// now fill the index buffer
-		unsigned int* pbData;
-		g_pcAsset->apcMeshes[i]->piIB->Lock(0,0,(void**)&pbData,0);
-		for (unsigned int x = 0; x < g_pcAsset->pcScene->mMeshes[i]->mNumFaces;++x)
+			// now fill the index buffer
+			uint16_t* pbData;
+			g_pcAsset->apcMeshes[i]->piIB->Lock(0,0,(void**)&pbData,0);
+			for (unsigned int x = 0; x < g_pcAsset->pcScene->mMeshes[i]->mNumFaces;++x)
 			{
-			for (unsigned int a = 0; a < 3;++a)
+				for (unsigned int a = 0; a < 3;++a)
 				{
-				*pbData++ = g_pcAsset->pcScene->mMeshes[i]->mFaces[x].mIndices[a];
+					*pbData++ = (uint16_t)g_pcAsset->pcScene->mMeshes[i]->mFaces[x].mIndices[a];
 				}
 			}
+		}
 		g_pcAsset->apcMeshes[i]->piIB->Unlock();
 
 		// now fill the vertex buffer
@@ -504,6 +864,7 @@ int CreateAssetData(void)
 	sprintf(szTemp,"%i", g_iShaderCount);
 	SetDlgItemText(g_hDlg,IDC_ESHADER,szTemp);
 
+	FillDisplayList();
 	return FillAnimList();
 	}
 
@@ -755,6 +1116,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/)
 	{
 	D3DDEVTYPE eType = bHW ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
 
+	// get the client rectangle of the window.
 	RECT sRect;
 	GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
 	sRect.right -= sRect.left;
@@ -763,17 +1125,26 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/)
 	D3DPRESENT_PARAMETERS sParams;
 	memset(&sParams,0,sizeof(D3DPRESENT_PARAMETERS));
 
+	// get the current display mode
 	D3DDISPLAYMODE sMode;
 	g_piD3D->GetAdapterDisplayMode(0,&sMode);
 
-	sParams.Windowed = TRUE;
-	sParams.hDeviceWindow = GetDlgItem( g_hDlg, IDC_RT );
-	sParams.EnableAutoDepthStencil = TRUE;
-	sParams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
-	sParams.BackBufferWidth = (UINT)sRect.right;
-	sParams.BackBufferHeight = (UINT)sRect.bottom;
-	sParams.AutoDepthStencilFormat = D3DFMT_D24X8;
-	sParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
+	// fill the presentation parameter structure
+	sParams.Windowed				= TRUE;
+	sParams.hDeviceWindow			= GetDlgItem( g_hDlg, IDC_RT );
+	sParams.EnableAutoDepthStencil	= TRUE;
+	sParams.PresentationInterval	= D3DPRESENT_INTERVAL_ONE;
+	sParams.BackBufferWidth			= (UINT)sRect.right;
+	sParams.BackBufferHeight		= (UINT)sRect.bottom;
+	sParams.SwapEffect				= D3DSWAPEFFECT_DISCARD;
+
+	// check whether we can use a D32 depth buffer format
+	if (SUCCEEDED ( g_piD3D->CheckDepthStencilMatch(0,eType,
+		D3DFMT_X8R8G8B8,D3DFMT_X8R8G8B8,D3DFMT_D32)))
+	{
+		sParams.AutoDepthStencilFormat = D3DFMT_D32;
+	}
+	else sParams.AutoDepthStencilFormat = D3DFMT_D24X8;
 
 	// find the highest multisample type available on this device
 	D3DMULTISAMPLE_TYPE sMS = D3DMULTISAMPLE_2_SAMPLES;
@@ -797,6 +1168,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/)
 		sParams.MultiSampleType = sMSOut;
 		}
 
+	// create the D3D9 device object
 	if(FAILED(g_piD3D->CreateDevice(0,eType,
 		g_hDlg,D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,&sParams,&g_piDevice)))
 		{
@@ -810,6 +1182,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/)
 		}
 	g_piDevice->SetFVF(AssetHelper::Vertex::GetFVF());
 
+	// compile the default material shader (gray gouraud/phong)
 	ID3DXBuffer* piBuffer = NULL;
 	if(FAILED( D3DXCreateEffect(g_piDevice,
 		g_szDefaultShader.c_str(),
@@ -833,6 +1206,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/)
 		piBuffer = NULL;
 		}
 
+	// create the shader used to draw the HUD
 	if(FAILED( D3DXCreateEffect(g_piDevice,
 		g_szPassThroughShader.c_str(),(UINT)g_szPassThroughShader.length(),
 		NULL,NULL,D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,NULL,&g_piPassThroughEffect,&piBuffer)))
@@ -850,6 +1224,8 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/)
 		piBuffer->Release();
 		piBuffer = NULL;
 		}
+
+	// create the shader used to visualize normal vectors
 	if(FAILED( D3DXCreateEffect(g_piDevice,
 		g_szNormalsShader.c_str(),(UINT)g_szNormalsShader.length(),
 		NULL,NULL,D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,NULL,&g_piNormalsEffect, &piBuffer)))
@@ -868,6 +1244,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/)
 		piBuffer = NULL;
 		}
 
+	// get the capabilities of the device object
 	g_piDevice->GetDeviceCaps(&g_sCaps);
 	if(g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0))
 		{

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä