Parcourir la source

Added first working version of a MDC loader; no further features like compressed frames tested at the moment. Added config options for keyframe loading, this has been tested with MDL7 only (atm). Some refactoring, a few files are much cleaner and smaller now. RemoveRedundantMats step does now remove unreferenced materials.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@103 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg il y a 17 ans
Parent
commit
6f49c4518c

+ 43 - 70
code/3DSConverter.cpp

@@ -59,6 +59,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
+#ifdef _MSC_VER
+#	define sprintf sprintf_s
+#endif
 
 // ------------------------------------------------------------------------------------------------
 void Dot3DSImporter::ReplaceDefaultMaterial()
@@ -113,8 +116,7 @@ void Dot3DSImporter::ReplaceDefaultMaterial()
 			{
 				(*a) = iIndex;
 				++iCnt;
-				DefaultLogger::get()->warn("Material index overflow in 3DS file. Assigning "
-					"default material ...");
+				DefaultLogger::get()->warn("Material index overflow in 3DS file. Using default material");
 			}
 		}
 	}
@@ -157,58 +159,36 @@ void Dot3DSImporter::CheckIndices(Dot3DS::Mesh* sMesh)
 // ------------------------------------------------------------------------------------------------
 void Dot3DSImporter::MakeUnique(Dot3DS::Mesh* sMesh)
 {
-	std::vector<aiVector3D> vNew;
-	vNew.resize(sMesh->mFaces.size() * 3);
+	unsigned int iBase = 0;
 
+	std::vector<aiVector3D> vNew;
 	std::vector<aiVector2D> vNew2;
 
-	// TODO: Remove this step. By maintaining a small LUT it
-	// would be possible to do this directly in the parsing step
-	unsigned int iBase = 0;
+	vNew.resize(sMesh->mFaces.size() * 3);
+	if (sMesh->mTexCoords.size())vNew2.resize(sMesh->mFaces.size() * 3);
 
-	if (0 != sMesh->mTexCoords.size())
+	for (unsigned int i = 0; i < sMesh->mFaces.size();++i)
 	{
-		vNew2.resize(sMesh->mFaces.size() * 3);
-		for (unsigned int i = 0; i < sMesh->mFaces.size();++i)
-		{
-			uint32_t iTemp1,iTemp2;
-
-			// position and texture coordinates
-			vNew[iBase]   = sMesh->mPositions[sMesh->mFaces[i].mIndices[2]];
-			vNew2[iBase]   = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[2]];
-			iTemp1 = iBase++;
+		uint32_t iTemp1,iTemp2;
 
-			vNew[iBase]   = sMesh->mPositions[sMesh->mFaces[i].mIndices[1]];
-			vNew2[iBase]   = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[1]];
-			iTemp2 = iBase++;
+		// positions
+		vNew[iBase]   = sMesh->mPositions[sMesh->mFaces[i].mIndices[2]];
+		iTemp1 = iBase++;
+		vNew[iBase]   = sMesh->mPositions[sMesh->mFaces[i].mIndices[1]];
+		iTemp2 = iBase++;
+		vNew[iBase]   = sMesh->mPositions[sMesh->mFaces[i].mIndices[0]];
 
-			vNew[iBase]   = sMesh->mPositions[sMesh->mFaces[i].mIndices[0]];
-			vNew2[iBase]   = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[0]];
-			sMesh->mFaces[i].mIndices[2] = iBase++;
-
-			sMesh->mFaces[i].mIndices[0] = iTemp1;
-			sMesh->mFaces[i].mIndices[1] = iTemp2;
-		}
-	}
-	else
-	{
-		for (unsigned int i = 0; i < sMesh->mFaces.size();++i)
+		// texture coordinates
+		if (sMesh->mTexCoords.size())
 		{
-			uint32_t iTemp1,iTemp2;
-
-			// position only
-			vNew[iBase]   = sMesh->mPositions[sMesh->mFaces[i].mIndices[2]];
-			iTemp1 = iBase++;
-
-			vNew[iBase]   = sMesh->mPositions[sMesh->mFaces[i].mIndices[1]];
-			iTemp2 = iBase++;
-
-			vNew[iBase]   = sMesh->mPositions[sMesh->mFaces[i].mIndices[0]];
-			sMesh->mFaces[i].mIndices[2] = iBase++;
-
-			sMesh->mFaces[i].mIndices[0] = iTemp1;
-			sMesh->mFaces[i].mIndices[1] = iTemp2;
+			vNew2[iTemp1]   = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[2]];
+			vNew2[iTemp2]   = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[1]];
+			vNew2[iBase]    = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[0]];
 		}
+
+		sMesh->mFaces[i].mIndices[2] = iBase++;
+		sMesh->mFaces[i].mIndices[0] = iTemp1;
+		sMesh->mFaces[i].mIndices[1] = iTemp2;
 	}
 	sMesh->mPositions = vNew;
 	sMesh->mTexCoords = vNew2;
@@ -400,7 +380,7 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
 	}
 
 	// store the name of the material itself, too
-	if( oldMat.mName.length() > 0)
+	if( oldMat.mName.length())
 	{
 		aiString tex;
 		tex.Set( oldMat.mName);
@@ -430,14 +410,19 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
 			a != (*i).mFaceMaterials.end();++a,++iNum)
 		{
 			// check range
+			// FIX: shouldn't be necessary anymore, has been moved to ReplaceDefaultMaterial()
+#if 0
 			if ((*a) >= this->mScene->mMaterials.size())
 			{
 				DefaultLogger::get()->error("3DS face material index is out of range");
 
 				// use the last material instead
+				// TODO: assign the default material index
 				aiSplit[this->mScene->mMaterials.size()-1].push_back(iNum);
 			}
-		else aiSplit[*a].push_back(iNum);
+			else
+#endif	
+		aiSplit[*a].push_back(iNum);
 		}
 		// now generate submeshes
 		bool bFirst = true;
@@ -455,14 +440,14 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
 				avOutMeshes.push_back(p_pcOut);
 				
 				// convert vertices
-				p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3;
 				p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
+				p_pcOut->mNumVertices = p_pcOut->mNumFaces*3;
 
 				// allocate enough storage for faces
 				p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
 				iFaceCnt += p_pcOut->mNumFaces;
 
-				if (p_pcOut->mNumVertices != 0)
+				if (p_pcOut->mNumVertices)
 				{
 					p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices];
 					p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices];
@@ -489,7 +474,7 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
 					}
 				}
 				// convert texture coordinates
-				if ((*i).mTexCoords.size() != 0)
+				if ((*i).mTexCoords.size())
 				{
 					p_pcOut->mTextureCoords[0] = new aiVector3D[p_pcOut->mNumVertices];
 
@@ -525,17 +510,13 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
 		pcOut->mMeshes[a] = avOutMeshes[a];
 	}
 
-	if (0 == iFaceCnt)
-	{
+	if (!iFaceCnt)
 		throw new ImportErrorException("No faces loaded. The mesh is empty");
-	}
 
 	// for each material in the scene we need to setup the UV source
 	// set for each texture
 	for (unsigned int a = 0; a < pcOut->mNumMaterials;++a)
-	{
 		TextureTransform::SetupMatUVSrc( pcOut->mMaterials[a], &this->mScene->mMaterials[a] );
-	}
 	return;
 }
 // ------------------------------------------------------------------------------------------------
@@ -551,7 +532,9 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
 			const Dot3DS::Mesh* pcMesh = (const Dot3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0];
 			ai_assert(NULL != pcMesh);
 
-			if (0 == ASSIMP_stricmp(pcIn->mName.c_str(),pcMesh->mName.c_str()))
+			// do case independent comparisons here, just for safety
+			if (pcIn->mName.length() == pcMesh->mName.length() &&
+				!ASSIMP_stricmp(pcIn->mName.c_str(),pcMesh->mName.c_str()))
 			{
 				iArray.push_back(a);
 			}
@@ -560,7 +543,8 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
 		{
 			aiMatrix4x4& mTrafo = ((Dot3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0])->mMat;
 			aiMatrix4x4 mInv = mTrafo;
-			mInv.Inverse();
+			if (!this->configSkipPivot)
+				mInv.Inverse();
 
 			pcOut->mName.Set(pcIn->mName);
 			pcOut->mNumMeshes = (unsigned int)iArray.size();
@@ -575,7 +559,7 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
 				const aiVector3D* const pvEnd = mesh->mVertices+mesh->mNumVertices;
 				aiVector3D* pvCurrent = mesh->mVertices;
 
-				if(pivot.x || pivot.y || pivot.z)
+				if(pivot.x || pivot.y || pivot.z && !this->configSkipPivot)
 				{
 					while (pvCurrent != pvEnd)
 					{
@@ -593,18 +577,12 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
 					while (pvCurrent != pvEnd)
 					{
 						std::swap( pvCurrent->y, pvCurrent->z );
-						//pvCurrent->y *= -1.0f;
 						++pvCurrent;
 					}
 				}
 				pcOut->mMeshes[i] = iIndex;
 			}
 		}
-		/*else
-		{
-			DefaultLogger::get()->warn("A node that is not a dummy does not "
-				"reference a valid mesh.");
-		}*/
 	}
 	pcOut->mTransformation = aiMatrix4x4(); 
 	pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
@@ -636,8 +614,7 @@ void Dot3DSImporter::GenerateNodeGraph(aiScene* pcOut)
 		//
 		unsigned int iCnt = 0;
 
-		DefaultLogger::get()->warn("No hierarchy information has been "
-			"found in the file. A flat hierarchy tree is built ...");
+		DefaultLogger::get()->warn("No hierarchy information has been found in the file. ");
 
 		pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes;
 		pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mNumMeshes ];
@@ -654,11 +631,7 @@ void Dot3DSImporter::GenerateNodeGraph(aiScene* pcOut)
 
 			char szBuffer[128];
 			int iLen;
-#if _MSC_VER >= 1400
-			iLen = sprintf_s(szBuffer,"UNNAMED_%i",i);
-#else
 			iLen = sprintf(szBuffer,"UNNAMED_%i",i);
-#endif
 			ai_assert(0 < iLen);
 			::memcpy(pcNode->mName.data,szBuffer,iLen);
 			pcNode->mName.data[iLen] = '\0';

+ 9 - 9
code/3DSHelper.h

@@ -120,8 +120,8 @@ public:
 	enum 
 	{
 
-		// **************************************************************
-		// Base chunks which can be found everywhere in the file
+		// ********************************************************************
+		// Basic chunks which can be found everywhere in the file
 		CHUNK_VERSION	= 0x0002,
 		CHUNK_RGBF      = 0x0010,		// float4 R; float4 G; float4 B
 		CHUNK_RGBB      = 0x0011,		// int1 R; int1 G; int B
@@ -132,7 +132,7 @@ public:
 
 		CHUNK_PERCENTW	= 0x0030,		// int2   percentage
 		CHUNK_PERCENTF	= 0x0031,		// float4  percentage
-		// **************************************************************
+		// ********************************************************************
 
 		// Unknown and ignored. Possibly a chunk used by PROJ (
 		// Discreet 3DS max Project File)?
@@ -162,7 +162,7 @@ public:
 		CHUNK_BIT_MAP   = 0x1100,
 		CHUNK_BIT_MAP_EXISTS  = 0x1101,
 
-		// **************************************************************
+		// ********************************************************************
 		// Viewport related stuff. Ignored
 		CHUNK_DEFAULT_VIEW = 0x3000,
 		CHUNK_VIEW_TOP = 0x3010,
@@ -173,7 +173,7 @@ public:
 		CHUNK_VIEW_BACK = 0x3060,
 		CHUNK_VIEW_USER = 0x3070,
 		CHUNK_VIEW_CAMERA = 0x3080,
-		// **************************************************************
+		// ********************************************************************
 
 		// Mesh chunks
 		CHUNK_OBJBLOCK  = 0x4000,
@@ -196,7 +196,7 @@ public:
 		// to the root node's transformation matrix
 		CHUNK_MASTER_SCALE    = 0x0100,
 
-		// **************************************************************
+		// ********************************************************************
 		// Material chunks
 		CHUNK_MAT_MATERIAL  = 0xAFFF,
 
@@ -280,7 +280,7 @@ public:
 
 			// Specifies whether a materail requires two-sided rendering
 			CHUNK_MAT_TWO_SIDE = 0xA081,  
-		// **************************************************************
+		// ********************************************************************
 
 		// Main keyframer chunk. Contains translation/rotation/scaling data
 		CHUNK_KEYFRAMER		= 0xB000,
@@ -293,7 +293,7 @@ public:
 		CHUNK_TRACKROTATE   = 0xB021,
 		CHUNK_TRACKSCALE    = 0xB022,
 
-		// **************************************************************
+		// ********************************************************************
 		// Keyframes for various other stuff in the file
 		// Ignored
 		CHUNK_AMBIENTKEY    = 0xB001,
@@ -308,7 +308,7 @@ public:
 		CHUNK_TRACKLIGTGT	= 0xB006,
 		CHUNK_TRACKSPOTL	= 0xB007,
 		CHUNK_FRAMES		= 0xB008
-		// **************************************************************
+		// ********************************************************************
 	};
 };
 

+ 40 - 35
code/3DSLoader.cpp

@@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "../include/aiMesh.h"
 #include "../include/aiScene.h"
 #include "../include/aiAssert.h"
+#include "../include/assimp.hpp"
 
 // boost headers
 #include <boost/scoped_ptr.hpp>
@@ -99,6 +100,12 @@ bool Dot3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) co
 	return false;
 }
 // ------------------------------------------------------------------------------------------------
+// Setup configuration properties
+void Dot3DSImporter::SetupProperties(const Importer* pImp)
+{
+	this->configSkipPivot = pImp->GetProperty(AI_CONFIG_IMPORT_3DS_IGNORE_PIVOT,0) ? true : false;
+}
+// ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure. 
 void Dot3DSImporter::InternReadFile( 
 	const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
@@ -144,48 +151,46 @@ void Dot3DSImporter::InternReadFile(
 	try
 	{
 		this->ParseMainChunk(iRemaining);
-	}
-	catch ( ImportErrorException* ex)
-	{
-		delete[] this->mBuffer;
-		throw ex;
-	};
 
-	// Generate an unique set of vertices/indices for
-	// all meshes contained in the file
-	for (std::vector<Dot3DS::Mesh>::iterator
-		i =  this->mScene->mMeshes.begin();
-		i != this->mScene->mMeshes.end();++i)
-	{
-		// TODO: see function body
-		this->CheckIndices(&(*i));
-		this->MakeUnique(&(*i));
+		// Generate an unique set of vertices/indices for
+		// all meshes contained in the file
+		for (std::vector<Dot3DS::Mesh>::iterator
+			i =  this->mScene->mMeshes.begin();
+			i != this->mScene->mMeshes.end();++i)
+		{
+			// TODO: see function body
+			this->CheckIndices(&(*i));
+			this->MakeUnique(&(*i));
 
-		// first generate normals for the mesh
-		this->GenNormals(&(*i));
-	}
+			// first generate normals for the mesh
+			this->GenNormals(&(*i));
+		}
 
-	// Apply scaling and offsets to all texture coordinates
-	TextureTransform::ApplyScaleNOffset(this->mScene->mMaterials);
+		// Apply scaling and offsets to all texture coordinates
+		TextureTransform::ApplyScaleNOffset(this->mScene->mMaterials);
 
-	// Replace all occurences of the default material with a valid material.
-	// Generate it if no material containing DEFAULT in its name has been
-	// found in the file
-	this->ReplaceDefaultMaterial();
-	
-	// Convert the scene from our internal representation to an aiScene object
-	this->ConvertScene(pScene);
+		// Replace all occurences of the default material with a valid material.
+		// Generate it if no material containing DEFAULT in its name has been
+		// found in the file
+		this->ReplaceDefaultMaterial();
 
-	// Generate the node graph for the scene. This is a little bit
-	// tricky since we'll need to split some meshes into submeshes
-	this->GenerateNodeGraph(pScene);
+		// Convert the scene from our internal representation to an aiScene object
+		this->ConvertScene(pScene);
 
-	// Now apply a master scaling factor to the scene
-	this->ApplyMasterScale(pScene);
+		// Generate the node graph for the scene. This is a little bit
+		// tricky since we'll need to split some meshes into submeshes
+		this->GenerateNodeGraph(pScene);
 
-	delete[] this->mBuffer;
-	delete this->mScene;
-	return;
+		// Now apply a master scaling factor to the scene
+		this->ApplyMasterScale(pScene);
+
+	}
+	catch ( ImportErrorException* ex)
+	{
+		delete[] this->mBuffer;AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
+		throw ex;
+	}
+	delete[] this->mBuffer;AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
 }
 // ------------------------------------------------------------------------------------------------
 void Dot3DSImporter::ApplyMasterScale(aiScene* pScene)

+ 12 - 2
code/3DSLoader.h

@@ -43,8 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_3DSIMPORTER_H_INC
 #define AI_3DSIMPORTER_H_INC
 
-#include <map>
-
 #include "BaseImporter.h"
 #include "../include/aiTypes.h"
 
@@ -73,11 +71,19 @@ protected:
 	~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;
 
+	// -------------------------------------------------------------------
+	/** Called prior to ReadFile().
+	* The function is a request to the importer to update its configuration
+	* basing on the Importer's configuration property list.
+	*/
+	void SetupProperties(const Importer* pImp);
+
 protected:
 
 	// -------------------------------------------------------------------
@@ -233,6 +239,10 @@ protected:
 
 
 protected:
+
+	/** Configuration option: skip pivot chunks */
+	bool configSkipPivot;
+
 	/** Buffer to hold the loaded file */
 	unsigned char* mBuffer;
 

+ 5 - 43
code/ASELoader.cpp

@@ -109,14 +109,11 @@ void ASEImporter::InternReadFile(
 
 	// 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();
 	std::string::size_type pos = pFile.find_last_of('.');
 	std::string extension = pFile.substr( pos);
-	this->mIsAsk = (extension[3] == 'k' || extension[3] == 'K');
 
 	// allocate storage and copy the contents of the file to a memory buffer
 	// (terminate it with zero)
@@ -144,11 +141,7 @@ void ASEImporter::InternReadFile(
 		{
 			if ((*i).bSkip)continue;
 
-			// transform all vertices into worldspace
-			// world2obj transform is specified in the
-			// transformation matrix of a scenegraph node
 			this->TransformVertices(*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);
@@ -215,7 +208,7 @@ void ASEImporter::GenerateDefaultMaterial()
 		this->mParser->m_vMaterials.push_back ( ASE::Material() );
 		ASE::Material& mat = this->mParser->m_vMaterials.back();
 
-	mat.mDiffuse = aiColor3D(0.6f,0.6f,0.6f);
+		mat.mDiffuse = aiColor3D(0.6f,0.6f,0.6f);
 		mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
 		mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f);
 		mat.mShading = Dot3DSFile::Gouraud;
@@ -449,21 +442,6 @@ void ASEImporter::BuildNodes()
 			std::string* szMyName = (std::string*)pcScene->mMeshes[*i]->mColors[1];
 			if (!szMyName)continue;
 
-#if 0 // moved to the scope above
-			for (std::vector<unsigned int>::iterator
-				a =  i+1;
-				a != aiList.end();++a)
-			{
-				std::string* szMyName2 = (std::string*)pcScene->mMeshes[*i]->mColors[1];
-				if (!szMyName)continue;
-				if (0 == ASSIMP_stricmp(szMyName2->c_str(),szMyName->c_str()))
-				{
-					a = aiList.erase(a);
-					if (a == aiList.end())break;
-				}
-			}
-#endif
-
 			DefaultLogger::get()->info("Generating dummy node: " + szMyName[1] + ". "
 				"This node is not defined in the ASE file, but referenced as "
 				"parent node.");
@@ -604,19 +582,6 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
 
 	for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
 		mesh.amTexCoords[c] = amTexCoords[c];
-
-	// now need to transform all vertices with the inverse of their
-	// transformation matrix ...
-	//aiMatrix4x4 mInverse = mesh.mTransform;
-	//mInverse.Inverse();
-
-	//for (std::vector<aiVector3D>::iterator
-	//	i =  mesh.mPositions.begin();
-	//	i != mesh.mPositions.end();++i)
-	//{
-	//	(*i) = mInverse * (*i);
-	//}
-
 	return;
 }
 // ------------------------------------------------------------------------------------------------
@@ -1066,7 +1031,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
 					pc->mName.Set(mesh.mBones[jfkennedy].mName);
 					pc->mNumWeights = (unsigned int)avBonesOut[jfkennedy].size();
 					pc->mWeights = new aiVertexWeight[pc->mNumWeights];
-					memcpy(pc->mWeights,&avBonesOut[jfkennedy][0],
+					::memcpy(pc->mWeights,&avBonesOut[jfkennedy][0],
 						sizeof(aiVertexWeight) * pc->mNumWeights);
 					++pcBone;
 				}
@@ -1246,9 +1211,8 @@ void ASEImporter::GenerateNormals(ASE::Mesh& mesh)
 			aiVector3D pDelta2 = *pV3 - *pV1;
 			aiVector3D vNor = pDelta1 ^ pDelta2;
 
-			mesh.mNormals[face.mIndices[0]] = vNor;
-			mesh.mNormals[face.mIndices[1]] = vNor;
-			mesh.mNormals[face.mIndices[2]] = vNor;
+			for (unsigned int i = 0; i < 3;++i)
+				mesh.mNormals[face.mIndices[i]] = vNor;
 		}
 
 		// calculate the position bounds so we have a reliable epsilon to 
@@ -1287,15 +1251,13 @@ void ASEImporter::GenerateNormals(ASE::Mesh& mesh)
 					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 /= fDiv;
+				vNormals.Normalize();
 				avNormals[(*i).mIndices[c]] = vNormals;
 				poResult.clear();
 			}

+ 1 - 6
code/ASELoader.h

@@ -114,8 +114,6 @@ protected:
 	 * \param mesh Mesh to work on
 	 */
 	void TransformVertices(ASE::Mesh& mesh);
-
-	// -------------------------------------------------------------------
 	/** Create one-material-per-mesh meshes ;-)
 	 * \param mesh Mesh to work with
 	 *  \param Receives the list of all created meshes
@@ -168,13 +166,10 @@ protected:
 	/** Buffer to hold the loaded file */
 	unsigned char* mBuffer;
 
-	/** true if this is an .ask file */
-	bool mIsAsk;
-
 	/** Scene to be filled */
 	aiScene* pcScene;
 };
 
 } // end of namespace Assimp
 
-#endif // AI_3DSIMPORTER_H_INC
+#endif // AI_3DSIMPORTER_H_INC

+ 1 - 0
code/ASEParser.cpp

@@ -794,6 +794,7 @@ void Parser::ParseLV1GeometryObjectBlock(ASE::Mesh& mesh)
 			{
 				this->m_szFile+=9;
 				this->ParseLV2NodeTransformBlock(mesh);continue;
+				//mesh.mTransform.Transpose();
 			}
 			// mesh data
 			if (0 == strncmp(this->m_szFile,"*MESH" ,5) &&

+ 13 - 3
code/CalcTangentsProcess.cpp

@@ -56,6 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "../include/aiPostProcess.h"
 #include "../include/aiMesh.h"
 #include "../include/aiScene.h"
+#include "../include/assimp.hpp"
 
 using namespace Assimp;
 
@@ -80,6 +81,16 @@ bool CalcTangentsProcess::IsActive( unsigned int pFlags) const
 	return (pFlags & aiProcess_CalcTangentSpace) != 0;
 }
 
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void CalcTangentsProcess::SetupProperties(const Importer* pImp)
+{
+	// get the current value of the property
+	this->configMaxAngle = pImp->GetProperty(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45000) / 1000.0f;
+	this->configMaxAngle = std::max(std::min(this->configMaxAngle,180.0f),0.0f);
+	this->configMaxAngle *= 0.0174532925f;
+}
+
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
 void CalcTangentsProcess::Execute( aiScene* pScene)
@@ -213,7 +224,6 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh)
 		vertexFinder.FindPositions( origPos, posEpsilon, verticesFound);
 
 		// look among them for other vertices sharing the same normal and a close-enough tangent/bitangent
-		static const float MAX_DIFF_ANGLE = 0.701f;
 		for( unsigned int b = 0; b < verticesFound.size(); b++)
 		{
 			unsigned int idx = verticesFound[b];
@@ -221,9 +231,9 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh)
 				continue;
 			if( meshNorm[idx] * origNorm < angleEpsilon)
 				continue;
-			if( meshTang[idx] * origTang < MAX_DIFF_ANGLE)
+			if( acosf( meshTang[idx] * origTang) > this->configMaxAngle)
 				continue;
-			if( meshBitang[idx] * origBitang < MAX_DIFF_ANGLE)
+			if( acosf( meshBitang[idx] * origBitang) > this->configMaxAngle)
 				continue;
 
 			// it's similar enough -> add it to the smoothing group

+ 24 - 11
code/CalcTangentsProcess.h

@@ -70,26 +70,39 @@ protected:
 
 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.
+	/** Returns whether the processing step is present in the given flag.
+	* @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.
+	/** Called prior to ExecuteOnScene().
+	* The function is a request to the process to update its configuration
+	* basing on the Importer's configuration property list.
 	*/
-	void Execute( aiScene* pScene);
+	void SetupProperties(const Importer* pImp);
 
 protected:
+
 	// -------------------------------------------------------------------
-	/** Calculates tangents and bitangents for the given mesh
-	 * @param pMesh The mesh to process.
-	 */
+	/** Calculates tangents and bitangents for a specific mesh.
+	* @param pMesh The mesh to process.
+	*/
 	bool ProcessMesh( aiMesh* pMesh);
+
+	// -------------------------------------------------------------------
+	/** Executes the post processing step on the given imported data.
+	* @param pScene The imported data to work at.
+	*/
+	void Execute( aiScene* pScene);
+
+private:
+
+	/** Configuration option: maximum smoothing angle, in radians*/
+	float configMaxAngle;
 };
 
 } // end of namespace Assimp

+ 23 - 7
code/GenVertexNormalsProcess.cpp

@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "../include/aiPostProcess.h"
 #include "../include/aiMesh.h"
 #include "../include/aiScene.h"
+#include "../include/assimp.hpp"
 
 using namespace Assimp;
 
@@ -70,7 +71,15 @@ bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
 {
 	return (pFlags & aiProcess_GenSmoothNormals) != 0;
 }
-
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void GenVertexNormalsProcess::SetupProperties(const Importer* pImp)
+{
+	// get the current value of the property
+	this->configMaxAngle = pImp->GetProperty(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,180000) / 1000.0f;
+	this->configMaxAngle = std::max(std::min(this->configMaxAngle,180.0f),0.0f);
+	this->configMaxAngle *= 0.0174532925f;
+}
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
 void GenVertexNormalsProcess::Execute( aiScene* pScene)
@@ -111,14 +120,10 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
 		aiVector3D pDelta1 = *pV2 - *pV1;
 		aiVector3D pDelta2 = *pV3 - *pV1;
 		aiVector3D vNor = pDelta1 ^ pDelta2;
-
-		/*if (face.mIndices[1] > face.mIndices[2])
-			vNor *= -1.0f;*/
+		vNor.Normalize();
 
 		for (unsigned int i = 0;i < face.mNumIndices;++i)
-		{
 			pMesh->mNormals[face.mIndices[i]] = vNor;
-		}
 	}
 
 	// calculate the position bounds so we have a reliable epsilon to 
@@ -135,10 +140,14 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
 	}
 
 	const float posEpsilon = (maxVec - minVec).Length() * 1e-5f;
+
 	// set up a SpatialSort to quickly find all vertices close to a given position
 	SpatialSort vertexFinder( pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
 	std::vector<unsigned int> verticesFound;
 
+	const float fLimit = (AI_MESH_SMOOTHING_ANGLE_NOT_SET == pMesh->mMaxSmoothingAngle
+		? this->configMaxAngle : pMesh->mMaxSmoothingAngle);
+
 	aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices];
 	for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
 	{
@@ -148,12 +157,19 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
 		vertexFinder.FindPositions( posThis, posEpsilon, verticesFound);
 
 		aiVector3D pcNor; 
+		unsigned int div = 0;
 		for (unsigned int a = 0; a < verticesFound.size(); ++a)
 		{
 			unsigned int vidx = verticesFound[a];
+
+			// check whether the angle between the two normals is not too large
+			if (acosf(pMesh->mNormals[vidx] * pMesh->mNormals[i]) > fLimit)
+				continue;
+
 			pcNor += pMesh->mNormals[vidx];
+			++div;
 		}
-		pcNor /= (float) verticesFound.size();
+		pcNor.Normalize();
 		pcNew[i] = pcNor;
 	}
 	delete[] pMesh->mNormals;

+ 26 - 7
code/GenVertexNormalsProcess.h

@@ -38,7 +38,8 @@ 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 */
+/** @file Defines a post processing step to compute vertex normals 
+    for all loaded vertizes */
 #ifndef AI_GENVERTEXNORMALPROCESS_H_INC
 #define AI_GENVERTEXNORMALPROCESS_H_INC
 
@@ -48,7 +49,7 @@ class GenNormalsTest;
 namespace Assimp {
 
 // ---------------------------------------------------------------------------
-/** The GenFaceNormalsProcess computes vertex normals for all vertizes of all meshes
+/** The GenFaceNormalsProcess computes vertex normals for all vertizes
 */
 class ASSIMP_API GenVertexNormalsProcess : public BaseProcess
 {
@@ -64,12 +65,20 @@ protected:
 
 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.
+	/** Returns whether the processing step is present in the given flag.
+	* @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;
+	
+	// -------------------------------------------------------------------
+	/** Called prior to ExecuteOnScene().
+	* The function is a request to the process to update its configuration
+	* basing on the Importer's configuration property list.
+	*/
+	void SetupProperties(const Importer* pImp);
 
 	// -------------------------------------------------------------------
 	/** Executes the post processing step on the given imported data.
@@ -78,9 +87,19 @@ public:
 	*/
 	void Execute( aiScene* pScene);
 
+protected:
 
-private:
+	// -------------------------------------------------------------------
+	/** Computes normals for a specific mesh
+	*  @param pcMesh Mesh
+	*  @return true if vertex normals have been computed
+	*/
 	bool GenMeshVertexNormals (aiMesh* pcMesh);
+
+private:
+
+	/** Configuration option: maximum smoothing angle, in radians*/
+	float configMaxAngle;
 };
 
 }; // end of namespace Assimp

+ 2 - 2
code/Importer.cpp

@@ -93,10 +93,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #if (!defined AI_BUILD_NO_MDR_IMPORTER)
 #	include "MDRLoader.h"
 #endif
+#endif
 #if (!defined AI_BUILD_NO_MDC_IMPORTER)
 #	include "MDCLoader.h"
 #endif
-#endif
 #if (!defined AI_BUILD_NO_MD5_IMPORTER)
 #	include "MD5Loader.h"
 #endif
@@ -202,10 +202,10 @@ Importer::Importer() :
 #if (!defined AI_BUILD_NO_MDR_IMPORTER)
 	mImporter.push_back( new MDRImporter());
 #endif
+#endif
 #if (!defined AI_BUILD_NO_MDC_IMPORTER)
 	mImporter.push_back( new MDCImporter());
 #endif
-#endif
 #if (!defined AI_BUILD_NO_MD5_IMPORTER)
 	mImporter.push_back( new MD5Importer());
 #endif

+ 1 - 5
code/LimitBoneWeightsProcess.cpp

@@ -88,11 +88,7 @@ void LimitBoneWeightsProcess::Execute( aiScene* pScene)
 void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp)
 {
 	// get the current value of the property
-	if(0xffffffff == (this->mMaxWeights = pImp->GetProperty(
-		AI_CONFIG_PP_LBW_MAX_WEIGHTS,0xffffffff)))
-	{
-		this->mMaxWeights = AI_LMW_MAX_WEIGHTS;
-	}
+	this->mMaxWeights = pImp->GetProperty(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS);
 }
 
 // ------------------------------------------------------------------------------------------------

+ 6 - 5
code/LimitBoneWeightsProcess.h

@@ -83,10 +83,11 @@ protected:
 
 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.
+	/** Returns whether the processing step is present in the given flag.
+	* @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;
 
@@ -95,7 +96,7 @@ public:
 	* The function is a request to the process to update its configuration
 	* basing on the Importer's configuration property list.
 	*/
-	virtual void SetupProperties(const Importer* pImp);
+	void SetupProperties(const Importer* pImp);
 
 protected:
 

+ 1 - 1
code/MD2Loader.cpp

@@ -169,7 +169,7 @@ void MD2Importer::ValidateHeader( )
 	if (this->m_pcHeader->numVertices > AI_MD2_MAX_VERTS)
 		DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports");
 
-	if (this->m_pcHeader->numFrames >= this->configFrameID )
+	if (this->m_pcHeader->numFrames <= this->configFrameID )
 		throw new ImportErrorException("The requested frame is not existing the file");
 
 }

+ 225 - 258
code/MD3Loader.cpp

@@ -93,28 +93,26 @@ bool MD3Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
 void MD3Importer::ValidateHeaderOffsets()
 {
 	// check magic number
-	if (this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE &&
-		this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE)
+	if (pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE &&
+		pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE)
 			throw new ImportErrorException( "Invalid MD3 file: Magic bytes not found");
 
 	// check file format version
-	if (this->m_pcHeader->VERSION > 15)
+	if (pcHeader->VERSION > 15)
 		DefaultLogger::get()->warn( "Unsupported MD3 file version. Continuing happily ...");
 
 	// check some values whether they are valid
-	if (!this->m_pcHeader->NUM_FRAMES)
-		throw new ImportErrorException( "Invalid MD3 file: NUM_FRAMES is 0");
-	if (!this->m_pcHeader->NUM_SURFACES)
+	if (!pcHeader->NUM_SURFACES)
 		throw new ImportErrorException( "Invalid md3 file: NUM_SURFACES is 0");
 
-	if (this->m_pcHeader->OFS_FRAMES	>= this->fileSize ||
-		this->m_pcHeader->OFS_SURFACES	>= this->fileSize || 
-		this->m_pcHeader->OFS_EOF		> this->fileSize)
+	if (pcHeader->OFS_FRAMES	>= fileSize ||
+		pcHeader->OFS_SURFACES	>= fileSize || 
+		pcHeader->OFS_EOF		> fileSize)
 	{
 		throw new ImportErrorException("Invalid MD3 header: some offsets are outside the file");
 	}
 
-	if (this->m_pcHeader->NUM_FRAMES >= this->configFrameID )
+	if (pcHeader->NUM_FRAMES <= this->configFrameID )
 		throw new ImportErrorException("The requested frame is not existing the file");
 }
 // ------------------------------------------------------------------------------------------------
@@ -123,10 +121,10 @@ void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf)
 	// calculate the relative offset of the surface
 	int32_t ofs = int32_t((const unsigned char*)pcSurf-this->mBuffer);
 
-	if (pcSurf->OFS_TRIANGLES	+ ofs + pcSurf->NUM_TRIANGLES * sizeof(MD3::Triangle)	> this->fileSize ||
-		pcSurf->OFS_SHADERS		+ ofs + pcSurf->NUM_SHADER * sizeof(MD3::Shader)		> this->fileSize ||
-		pcSurf->OFS_ST			+ ofs + pcSurf->NUM_VERTICES * sizeof(MD3::TexCoord)	> this->fileSize ||
-		pcSurf->OFS_XYZNORMAL	+ ofs + pcSurf->NUM_VERTICES * sizeof(MD3::Vertex)		> this->fileSize)
+	if (pcSurf->OFS_TRIANGLES	+ ofs + pcSurf->NUM_TRIANGLES * sizeof(MD3::Triangle)	> fileSize ||
+		pcSurf->OFS_SHADERS		+ ofs + pcSurf->NUM_SHADER * sizeof(MD3::Shader)		> fileSize ||
+		pcSurf->OFS_ST			+ ofs + pcSurf->NUM_VERTICES * sizeof(MD3::TexCoord)	> fileSize ||
+		pcSurf->OFS_XYZNORMAL	+ ofs + pcSurf->NUM_VERTICES * sizeof(MD3::Vertex)		> fileSize)
 	{
 		throw new ImportErrorException("Invalid MD3 surface header: some offsets are outside the file");
 	}
@@ -170,310 +168,279 @@ void MD3Importer::InternReadFile(
 		throw new ImportErrorException( "MD3 File is too small.");
 
 	// allocate storage and copy the contents of the file to a memory buffer
-	this->mBuffer = new unsigned char[fileSize];
-	file->Read( (void*)mBuffer, 1, fileSize);
+	std::vector<unsigned char> mBuffer2 (fileSize);
+	file->Read( &mBuffer2[0], 1, fileSize);
+	mBuffer = &mBuffer2[0];
 
-	try
-	{
-
-		this->m_pcHeader = (const MD3::Header*)this->mBuffer;
+	pcHeader = (BE_NCONST MD3::Header*)mBuffer;
 
 #ifdef AI_BUILD_BIG_ENDIAN
 
-		ByteSwap::Swap4(&m_pcHeader->VERSION);
-		ByteSwap::Swap4(&m_pcHeader->FLAGS);
-		ByteSwap::Swap4(&m_pcHeader->IDENT);
-		ByteSwap::Swap4(&m_pcHeader->NUM_FRAMES);
-		ByteSwap::Swap4(&m_pcHeader->NUM_SKINS);
-		ByteSwap::Swap4(&m_pcHeader->NUM_SURFACES);
-		ByteSwap::Swap4(&m_pcHeader->NUM_TAGS);
-		ByteSwap::Swap4(&m_pcHeader->OFS_EOF);
-		ByteSwap::Swap4(&m_pcHeader->OFS_FRAMES);
-		ByteSwap::Swap4(&m_pcHeader->OFS_SURFACES);
-		ByteSwap::Swap4(&m_pcHeader->OFS_TAGS);
+	ByteSwap::Swap4(&pcHeader->VERSION);
+	ByteSwap::Swap4(&pcHeader->FLAGS);
+	ByteSwap::Swap4(&pcHeader->IDENT);
+	ByteSwap::Swap4(&pcHeader->NUM_FRAMES);
+	ByteSwap::Swap4(&pcHeader->NUM_SKINS);
+	ByteSwap::Swap4(&pcHeader->NUM_SURFACES);
+	ByteSwap::Swap4(&pcHeader->NUM_TAGS);
+	ByteSwap::Swap4(&pcHeader->OFS_EOF);
+	ByteSwap::Swap4(&pcHeader->OFS_FRAMES);
+	ByteSwap::Swap4(&pcHeader->OFS_SURFACES);
+	ByteSwap::Swap4(&pcHeader->OFS_TAGS);
 
 #endif
 
-		// validate the header
-		this->ValidateHeaderOffsets();
+	// validate the header
+	this->ValidateHeaderOffsets();
 
-		// now navigate to the list of surfaces
-		const MD3::Surface* pcSurfaces = (const MD3::Surface*)
-			(this->mBuffer + this->m_pcHeader->OFS_SURFACES);
+	// now navigate to the list of surfaces
+	const MD3::Surface* pcSurfaces = (const MD3::Surface*)(mBuffer + pcHeader->OFS_SURFACES);
 
-		// allocate output storage
-		pScene->mNumMeshes = this->m_pcHeader->NUM_SURFACES;
-		pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+	// allocate output storage
+	pScene->mNumMeshes = pcHeader->NUM_SURFACES;
+	pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
 
-		pScene->mNumMaterials = this->m_pcHeader->NUM_SURFACES;
-		pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes];
+	pScene->mNumMaterials = pcHeader->NUM_SURFACES;
+	pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes];
 
-		// if an exception is thrown before the meshes are allocated ->
-		// otherwise the pointer value would be invalid and delete would crash
-		::memset(pScene->mMeshes,0,pScene->mNumMeshes*sizeof(aiMesh*));
-		::memset(pScene->mMaterials,0,pScene->mNumMaterials*sizeof(aiMaterial*));
+	// if an exception is thrown before the meshes are allocated ->
+	// otherwise the pointer value would be invalid and delete would crash
+	::memset(pScene->mMeshes,0,pScene->mNumMeshes*sizeof(aiMesh*));
+	::memset(pScene->mMaterials,0,pScene->mNumMaterials*sizeof(aiMaterial*));
+
+	unsigned int iNum = pcHeader->NUM_SURFACES;
+	unsigned int iNumMaterials = 0;
+	unsigned int iDefaultMatIndex = 0xFFFFFFFF;
+	while (iNum-- > 0)
+	{
 
-		unsigned int iNum = this->m_pcHeader->NUM_SURFACES;
-		unsigned int iNumMaterials = 0;
-		unsigned int iDefaultMatIndex = 0xFFFFFFFF;
-		while (iNum-- > 0)
-		{
-		
 #ifdef AI_BUILD_BIG_ENDIAN
 
-			ByteSwap::Swap4(pcSurfaces->FLAGS);
-			ByteSwap::Swap4(pcSurfaces->IDENT);
-			ByteSwap::Swap4(pcSurfaces->NUM_FRAMES);
-			ByteSwap::Swap4(pcSurfaces->NUM_SHADER);
-			ByteSwap::Swap4(pcSurfaces->NUM_TRIANGLES);
-			ByteSwap::Swap4(pcSurfaces->NUM_VERTICES);
-			ByteSwap::Swap4(pcSurfaces->OFS_END);
-			ByteSwap::Swap4(pcSurfaces->OFS_SHADERS);
-			ByteSwap::Swap4(pcSurfaces->OFS_ST);
-			ByteSwap::Swap4(pcSurfaces->OFS_TRIANGLES);
-			ByteSwap::Swap4(pcSurfaces->OFS_XYZNORMAL);
+		ByteSwap::Swap4(pcSurfaces->FLAGS);
+		ByteSwap::Swap4(pcSurfaces->IDENT);
+		ByteSwap::Swap4(pcSurfaces->NUM_FRAMES);
+		ByteSwap::Swap4(pcSurfaces->NUM_SHADER);
+		ByteSwap::Swap4(pcSurfaces->NUM_TRIANGLES);
+		ByteSwap::Swap4(pcSurfaces->NUM_VERTICES);
+		ByteSwap::Swap4(pcSurfaces->OFS_END);
+		ByteSwap::Swap4(pcSurfaces->OFS_SHADERS);
+		ByteSwap::Swap4(pcSurfaces->OFS_ST);
+		ByteSwap::Swap4(pcSurfaces->OFS_TRIANGLES);
+		ByteSwap::Swap4(pcSurfaces->OFS_XYZNORMAL);
 
 #endif
 
-			// validate the surface
-			this->ValidateSurfaceHeaderOffsets(pcSurfaces);
+		// validate the surface
+		this->ValidateSurfaceHeaderOffsets(pcSurfaces);
 
-			// navigate to the vertex list of the surface
-			const MD3::Vertex* pcVertices = (const MD3::Vertex*)
-				(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL);
+		// navigate to the vertex list of the surface
+		const MD3::Vertex* pcVertices = (const MD3::Vertex*)
+			(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL);
 
-			// navigate to the triangle list of the surface
-			const MD3::Triangle* pcTriangles = (const MD3::Triangle*)
-				(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_TRIANGLES);
+		// navigate to the triangle list of the surface
+		const MD3::Triangle* pcTriangles = (const MD3::Triangle*)
+			(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_TRIANGLES);
 
-			// navigate to the texture coordinate list of the surface
-			const MD3::TexCoord* pcUVs = (const MD3::TexCoord*)
-				(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_ST);
+		// navigate to the texture coordinate list of the surface
+		const MD3::TexCoord* pcUVs = (const MD3::TexCoord*)
+			(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_ST);
 
-			// navigate to the shader list of the surface
-			const MD3::Shader* pcShaders = (const MD3::Shader*)
-				(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_SHADERS);
+		// navigate to the shader list of the surface
+		const MD3::Shader* pcShaders = (const MD3::Shader*)
+			(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_SHADERS);
 
-			// if the submesh is empty ignore it
-			if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES)
-			{
-				pcSurfaces = (const MD3::Surface*)(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_END);
-				pScene->mNumMeshes--;
-				continue;
-			}
+		// if the submesh is empty ignore it
+		if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES)
+		{
+			pcSurfaces = (const MD3::Surface*)(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_END);
+			pScene->mNumMeshes--;
+			continue;
+		}
 
 #ifdef AI_BUILD_BIG_ENDIAN
 
-			for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i)
-			{
-				ByteSwap::Swap2( & pcVertices[i].NORMAL );
-				ByteSwap::Swap2( & pcVertices[i].X );
-				ByteSwap::Swap2( & pcVertices[i].Y );
-				ByteSwap::Swap2( & pcVertices[i].Z );
+		for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i)
+		{
+			ByteSwap::Swap2( & pcVertices[i].NORMAL );
+			ByteSwap::Swap2( & pcVertices[i].X );
+			ByteSwap::Swap2( & pcVertices[i].Y );
+			ByteSwap::Swap2( & pcVertices[i].Z );
 
-				ByteSwap::Swap4( & pcUVs[i].U );
-				ByteSwap::Swap4( & pcUVs[i].U );
-			}
-			for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES;++i)
-			{
-				ByteSwap::Swap4(pcTriangles[i].INDEXES[0]);
-				ByteSwap::Swap4(pcTriangles[i].INDEXES[1]);
-				ByteSwap::Swap4(pcTriangles[i].INDEXES[2]);
-			}
+			ByteSwap::Swap4( & pcUVs[i].U );
+			ByteSwap::Swap4( & pcUVs[i].U );
+		}
+		for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES;++i)
+		{
+			ByteSwap::Swap4(pcTriangles[i].INDEXES[0]);
+			ByteSwap::Swap4(pcTriangles[i].INDEXES[1]);
+			ByteSwap::Swap4(pcTriangles[i].INDEXES[2]);
+		}
 
 #endif
 
-			// allocate the output mesh
-			pScene->mMeshes[iNum] = new aiMesh();
-			aiMesh* pcMesh = pScene->mMeshes[iNum];
-
-			pcMesh->mNumVertices		= pcSurfaces->NUM_TRIANGLES*3;
-			pcMesh->mNumFaces			= pcSurfaces->NUM_TRIANGLES;
-			pcMesh->mFaces				= new aiFace[pcSurfaces->NUM_TRIANGLES];
-			pcMesh->mNormals			= new aiVector3D[pcMesh->mNumVertices];
-			pcMesh->mVertices			= new aiVector3D[pcMesh->mNumVertices];
-			pcMesh->mTextureCoords[0]	= new aiVector3D[pcMesh->mNumVertices];
-			pcMesh->mNumUVComponents[0] = 2;
-
-			// 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;
+		// allocate the output mesh
+		pScene->mMeshes[iNum] = new aiMesh();
+		aiMesh* pcMesh = pScene->mMeshes[iNum];
+
+		pcMesh->mNumVertices		= pcSurfaces->NUM_TRIANGLES*3;
+		pcMesh->mNumFaces			= pcSurfaces->NUM_TRIANGLES;
+		pcMesh->mFaces				= new aiFace[pcSurfaces->NUM_TRIANGLES];
+		pcMesh->mNormals			= new aiVector3D[pcMesh->mNumVertices];
+		pcMesh->mVertices			= new aiVector3D[pcMesh->mNumVertices];
+		pcMesh->mTextureCoords[0]	= new aiVector3D[pcMesh->mNumVertices];
+		pcMesh->mNumUVComponents[0] = 2;
+
+		// 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;
 
-				unsigned int iTemp = iCurrent;
-				for (unsigned int c = 0; c < 3;++c,++iCurrent)
-				{
-					// read vertices
-					pcMesh->mVertices[iCurrent].x = pcVertices[ pcTriangles->INDEXES[c]].X;
-					pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y*-1.0f;
-					pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z;
+			unsigned int iTemp = iCurrent;
+			for (unsigned int c = 0; c < 3;++c,++iCurrent)
+			{
+				// read vertices
+				pcMesh->mVertices[iCurrent].x = pcVertices[ pcTriangles->INDEXES[c]].X;
+				pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y*-1.0f;
+				pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z;
 
-					// convert the normal vector to uncompressed float3 format
-					LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,
-						(float*)&pcMesh->mNormals[iCurrent]);
+				// convert the normal vector to uncompressed float3 format
+				LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,
+					(float*)&pcMesh->mNormals[iCurrent]);
 
-					pcMesh->mNormals[iCurrent].y *= -1.0f;
+				pcMesh->mNormals[iCurrent].y *= -1.0f;
 
-					// 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;
-				}
-				// FIX: flip the face ordering for use with OpenGL
-				pcMesh->mFaces[i].mIndices[0] = iTemp+2;
-				pcMesh->mFaces[i].mIndices[1] = iTemp+1;
-				pcMesh->mFaces[i].mIndices[2] = iTemp+0;
-				pcTriangles++;
+				// 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;
 			}
+			// FIX: flip the face ordering for use with OpenGL
+			pcMesh->mFaces[i].mIndices[0] = iTemp+2;
+			pcMesh->mFaces[i].mIndices[1] = iTemp+1;
+			pcMesh->mFaces[i].mIndices[2] = iTemp+0;
+			pcTriangles++;
+		}
 
-			// get the first shader (= texture?) assigned to the surface
-			if (0 != pcSurfaces->NUM_SHADER)
-			{
-				// make a relative path.
-				// if the MD3's internal path itself and the given path are using
-				// the same directory remove it
-				const char* szEndDir1 = ::strrchr((const char*)this->m_pcHeader->NAME,'\\');
-				if (!szEndDir1)szEndDir1 = ::strrchr((const char*)this->m_pcHeader->NAME,'/');
+		// get the first shader (= texture?) assigned to the surface
+		if (pcSurfaces->NUM_SHADER)
+		{
+			// make a relative path.
+			// if the MD3's internal path itself and the given path are using
+			// the same directory remove it
+			const char* szEndDir1 = ::strrchr((const char*)pcHeader->NAME,'\\');
+			if (!szEndDir1)szEndDir1 = ::strrchr((const char*)pcHeader->NAME,'/');
 
-				const char* szEndDir2 = ::strrchr((const char*)pcShaders->NAME,'\\');
-				if (!szEndDir2)szEndDir2 = ::strrchr((const char*)pcShaders->NAME,'/');
+			const char* szEndDir2 = ::strrchr((const char*)pcShaders->NAME,'\\');
+			if (!szEndDir2)szEndDir2 = ::strrchr((const char*)pcShaders->NAME,'/');
 
-				if (szEndDir1 && szEndDir2)
-				{
-					// both of them are valid
-					const unsigned int iLen1 = (unsigned int)(szEndDir1 - (const char*)this->m_pcHeader->NAME);
-					const unsigned int iLen2 = std::min (iLen1, (unsigned int)(szEndDir2 - (const char*)pcShaders->NAME) );
+			if (szEndDir1 && szEndDir2)
+			{
+				// both of them are valid
+				const unsigned int iLen1 = (unsigned int)(szEndDir1 - (const char*)pcHeader->NAME);
+				const unsigned int iLen2 = std::min (iLen1, (unsigned int)(szEndDir2 - (const char*)pcShaders->NAME) );
 
-					bool bSuccess = true;
-					for (unsigned int a = 0; a  < iLen2;++a)
-					{
-						char sz = ::tolower ( pcShaders->NAME[a] );
-						char sz2 = ::tolower ( this->m_pcHeader->NAME[a] );
-						if (sz != sz2)
-						{
-							bSuccess = false;
-							break;
-						}
-					}
-					if (bSuccess)
-					{
-						// use the file name only
-						szEndDir2++;
-					}
-					else
+				bool bSuccess = true;
+				for (unsigned int a = 0; a  < iLen2;++a)
+				{
+					char sz = ::tolower ( pcShaders->NAME[a] );
+					char sz2 = ::tolower ( pcHeader->NAME[a] );
+					if (sz != sz2)
 					{
-						// use the full path
-						szEndDir2 = (const char*)pcShaders->NAME;
+						bSuccess = false;
+						break;
 					}
 				}
+				if (bSuccess)
+				{
+					// use the file name only
+					szEndDir2++;
+				}
+				else
+				{
+					// use the full path
+					szEndDir2 = (const char*)pcShaders->NAME;
+				}
+			}
+			MaterialHelper* pcHelper = new MaterialHelper();
 
-				// now try to find out whether we have this shader already
-				bool bHave = false;
-				for (unsigned int p = 0; p < iNumMaterials;++p)
+			if (szEndDir2)
+			{
+				if (szEndDir2[0])
 				{
-					if (iDefaultMatIndex == p)continue;
+					aiString szString;
+					const size_t iLen = ::strlen(szEndDir2);
+					::memcpy(szString.data,szEndDir2,iLen);
+					szString.data[iLen] = '\0';
+					szString.length = iLen;
 
-					aiString szOut;
-					if(AI_SUCCESS == aiGetMaterialString ( (aiMaterial*)pScene->mMaterials[p],
-						AI_MATKEY_TEXTURE_DIFFUSE(0),&szOut))
-					{
-						if (0 == ASSIMP_stricmp(szOut.data,szEndDir2))
-						{
-							// equal. reuse this material (texture)
-							bHave = true;
-							pcMesh->mMaterialIndex = p;
-							break;
-						}
-					}
+					pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
 				}
-
-				if (!bHave)
+				else 
 				{
-					MaterialHelper* pcHelper = new MaterialHelper();
+					DefaultLogger::get()->warn("Texture file name has zero length. "
+						"It will be skipped.");
+				}
+			}
 
-					if (szEndDir2)
-					{
-						if (szEndDir2[0])
-						{
-							aiString szString;
-							const size_t iLen = ::strlen(szEndDir2);
-							::memcpy(szString.data,szEndDir2,iLen);
-							szString.data[iLen] = '\0';
-							szString.length = iLen;
-
-							pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
-						}
-						else 
-						{
-							DefaultLogger::get()->warn("Texture file name has zero length. "
-								"It will be skipped.");
-						}
-					}
+			int iMode = (int)aiShadingMode_Gouraud;
+			pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
 
-					int iMode = (int)aiShadingMode_Gouraud;
-					pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+			// add a small ambient color value - Quake 3 seems to have one
+			aiColor3D clr;
+			clr.b = clr.g = clr.r = 0.05f;
+			pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
 
-					// add a small ambient color value - Quake 3 seems to have one
-					aiColor3D clr;
-					clr.b = clr.g = clr.r = 0.05f;
-					pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+			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);
 
-					aiString szName;
-					szName.Set(AI_DEFAULT_MATERIAL_NAME);
-					pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
+			aiString szName;
+			szName.Set(AI_DEFAULT_MATERIAL_NAME);
+			pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
 
-					pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
-					iDefaultMatIndex = pcMesh->mMaterialIndex = iNumMaterials++;
-				}
+			pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
+			pcMesh->mMaterialIndex = iNumMaterials++;
+		}
+		else
+		{
+			if (0xFFFFFFFF != iDefaultMatIndex)
+			{
+				pcMesh->mMaterialIndex = iDefaultMatIndex;
 			}
 			else
 			{
-				if (0xFFFFFFFF != iDefaultMatIndex)
-				{
-					pcMesh->mMaterialIndex = iDefaultMatIndex;
-				}
-				else
-				{
-					MaterialHelper* pcHelper = new MaterialHelper();
+				MaterialHelper* pcHelper = new MaterialHelper();
 
-					// fill in a default material
-					int iMode = (int)aiShadingMode_Gouraud;
-					pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+				// fill in a default material
+				int iMode = (int)aiShadingMode_Gouraud;
+				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);
+				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);
+				clr.b = clr.g = clr.r = 0.05f;
+				pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
 
-					pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
-					iDefaultMatIndex = pcMesh->mMaterialIndex = iNumMaterials++;
-				}
+				pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
+				iDefaultMatIndex = pcMesh->mMaterialIndex = iNumMaterials++;
 			}
-			// go to the next surface
-			pcSurfaces = (const MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END);
 		}
+		// go to the next surface
+		pcSurfaces = (const MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END);
+	}
 
-		if (0 == pScene->mNumMeshes)
-			throw new ImportErrorException( "Invalid md3 file: File contains no valid mesh");
-		pScene->mNumMaterials = iNumMaterials;
-
-		// now we need to generate an empty node graph
-		pScene->mRootNode = new aiNode();
-		pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
-		pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
+	if (!pScene->mNumMeshes)
+		throw new ImportErrorException( "Invalid MD3 file: File contains no valid mesh");
+	pScene->mNumMaterials = iNumMaterials;
 
-		for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
-			pScene->mRootNode->mMeshes[i] = i;
+	// now we need to generate an empty node graph
+	pScene->mRootNode = new aiNode();
+	pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
+	pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
 
-	}
-	catch (ImportErrorException* ex)
-	{
-		delete[] this->mBuffer; AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
-		throw ex;
-	}
-	delete[] this->mBuffer; AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
-}
+	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+		pScene->mRootNode->mMeshes[i] = i;
+}

+ 5 - 7
code/MD3Loader.h

@@ -42,17 +42,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_MD3LOADER_H_INCLUDED
 #define AI_MD3LOADER_H_INCLUDED
 
-#include <map>
-
 #include "BaseImporter.h"
+#include "ByteSwap.h"
 
 #include "../include/aiTypes.h"
 
 struct aiNode;
 
 #include "MD3FileData.h"
-namespace Assimp
-{
+namespace Assimp	{
 class MaterialHelper;
 
 using namespace MD3;
@@ -117,10 +115,10 @@ protected:
 	unsigned int configFrameID;
 
 	/** Header of the MD3 file */
-	const MD3::Header* m_pcHeader;
+	BE_NCONST MD3::Header* pcHeader;
 
-	/** Buffer to hold the loaded file */
-	const unsigned char* mBuffer;
+	/** File buffer  */
+	BE_NCONST unsigned char* mBuffer;
 
 	/** Size of the file, in bytes */
 	unsigned int fileSize;

+ 2 - 13
code/MDCFileData.h

@@ -53,14 +53,7 @@ http://themdcfile.planetwolfenstein.gamespy.com/MDC_File_Format.pdf
 #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
+#include "./Compiler/pushpack1.h"
 
 
 namespace Assimp {
@@ -188,11 +181,7 @@ struct Shader
 
 } PACK_STRUCT;
 
-// reset packing to the original value
-#if defined(_MSC_VER) ||  defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
-#	pragma pack( pop )
-#endif
-#undef PACK_STRUCT
+#include "./Compiler/poppack1.h"
 
 
 // ---------------------------------------------------------------------------

+ 476 - 0
code/MDCLoader.cpp

@@ -0,0 +1,476 @@
+/*
+---------------------------------------------------------------------------
+Open 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 MDC importer class */
+
+// internal headers
+#include "MDCLoader.h"
+#include "MD3FileData.h"
+#include "MaterialSystem.h"
+#include "StringComparison.h"
+#include "MDCNormalTable.h" // shouldn't be included by other units
+#include "ByteSwap.h"
+
+// public ASSIMP headers
+#include "../include/IOStream.h"
+#include "../include/IOSystem.h"
+#include "../include/aiMesh.h"
+#include "../include/aiScene.h"
+#include "../include/aiAssert.h"
+#include "../include/DefaultLogger.h"
+#include "../include/assimp.hpp"
+
+// boost headers
+#include <boost/scoped_ptr.hpp>
+
+using namespace Assimp;
+using namespace Assimp::MDC;
+
+
+// ------------------------------------------------------------------------------------------------
+void MDC::BuildVertex(const Frame& frame,
+	const BaseVertex& bvert,
+	const CompressedVertex& cvert,
+	aiVector3D& vXYZOut, 
+	aiVector3D& vNorOut)
+{
+	// compute the position
+	const float xd = (cvert.xd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
+	const float yd = (cvert.yd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
+	const float zd = (cvert.zd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
+	vXYZOut.x = frame.localOrigin.x + AI_MDC_BASE_SCALING * (bvert.x + xd);
+	vXYZOut.y = frame.localOrigin.y + AI_MDC_BASE_SCALING * (bvert.y + yd);
+	vXYZOut.z = frame.localOrigin.z + AI_MDC_BASE_SCALING * (bvert.z + zd);
+
+	// compute the normal vector .. ehm ... lookup it in the table :-)
+	vNorOut.x = mdcNormals[cvert.nd][0];
+	vNorOut.y = mdcNormals[cvert.nd][1];
+	vNorOut.z = mdcNormals[cvert.nd][2];
+}
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+MDCImporter::MDCImporter()
+{
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well 
+MDCImporter::~MDCImporter()
+{
+}
+// ------------------------------------------------------------------------------------------------
+// Returns whether the class can handle the format of the given file. 
+bool MDCImporter::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] != 'C' && extension[3] != 'c')return false; 
+
+	return true;
+}
+// ------------------------------------------------------------------------------------------------
+// Validate the header of the given MDC file
+void MDCImporter::ValidateHeader()
+{
+	AI_SWAP4( this->pcHeader->ulVersion );
+	AI_SWAP4( this->pcHeader->ulFlags );
+	AI_SWAP4( this->pcHeader->ulNumFrames );
+	AI_SWAP4( this->pcHeader->ulNumTags );
+	AI_SWAP4( this->pcHeader->ulNumSurfaces );
+	AI_SWAP4( this->pcHeader->ulNumSkins );
+	AI_SWAP4( this->pcHeader->ulOffsetBorderFrames );
+
+	if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE &&
+		pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE)
+	{
+		char szBuffer[5];
+		szBuffer[0] = ((char*)&pcHeader->ulIdent)[0];
+		szBuffer[1] = ((char*)&pcHeader->ulIdent)[1];
+		szBuffer[2] = ((char*)&pcHeader->ulIdent)[2];
+		szBuffer[3] = ((char*)&pcHeader->ulIdent)[3];
+		szBuffer[4] = '\0';
+
+		throw new ImportErrorException("Invalid MDC magic word: should be IDPC, the "
+			"magic word found is " + std::string( szBuffer ));
+	}
+
+	if (pcHeader->ulVersion != AI_MDC_VERSION)
+		DefaultLogger::get()->warn("Unsupported MDC file version (2 (AI_MDC_VERSION) was expected)");
+
+	if (pcHeader->ulOffsetBorderFrames + pcHeader->ulNumFrames * sizeof(MDC::Frame) > this->fileSize ||
+		pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize)
+	{
+		throw new ImportErrorException("Some of the offset values in the MDC header are invalid "
+			"and point to something behind the file.");
+	}
+
+	if (this->configFrameID >= this->pcHeader->ulNumFrames)
+		throw new ImportErrorException("The requested frame is not available");
+}
+// ------------------------------------------------------------------------------------------------
+// Validate the header of a given MDC file surface
+void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf)
+{
+	AI_SWAP4(pcSurf->ulFlags);
+	AI_SWAP4(pcSurf->ulNumCompFrames);
+	AI_SWAP4(pcSurf->ulNumBaseFrames);
+	AI_SWAP4(pcSurf->ulNumShaders);
+	AI_SWAP4(pcSurf->ulNumVertices);
+	AI_SWAP4(pcSurf->ulNumTriangles);
+	AI_SWAP4(pcSurf->ulOffsetTriangles);
+	AI_SWAP4(pcSurf->ulOffsetTexCoords);
+	AI_SWAP4(pcSurf->ulOffsetBaseVerts);
+	AI_SWAP4(pcSurf->ulOffsetCompVerts);
+	AI_SWAP4(pcSurf->ulOffsetFrameBaseFrames);
+	AI_SWAP4(pcSurf->ulOffsetFrameCompFrames);
+	AI_SWAP4(pcSurf->ulOffsetEnd);
+
+    const unsigned int iMax = this->fileSize - (unsigned int)((int8_t*)pcSurf-(int8_t*)pcHeader);
+
+    if (pcSurf->ulOffsetBaseVerts + pcSurf->ulNumVertices * sizeof(MDC::BaseVertex)			> iMax ||
+        (pcSurf->ulNumCompFrames && pcSurf->ulOffsetCompVerts + pcSurf->ulNumVertices * sizeof(MDC::CompressedVertex)	> iMax) ||
+        pcSurf->ulOffsetTriangles + pcSurf->ulNumTriangles * sizeof(MDC::Triangle)			> iMax ||
+        pcSurf->ulOffsetTexCoords + pcSurf->ulNumVertices * sizeof(MDC::TexturCoord)		> iMax ||
+        pcSurf->ulOffsetShaders + pcSurf->ulNumShaders * sizeof(MDC::Shader)				> iMax ||
+        pcSurf->ulOffsetFrameBaseFrames + pcSurf->ulNumBaseFrames * 2						> iMax ||
+        (pcSurf->ulNumCompFrames && pcSurf->ulOffsetFrameCompFrames + pcSurf->ulNumCompFrames * 2	> iMax))
+    {
+        throw new ImportErrorException("Some of the offset values in the MDC surface header "
+            "are invalid and point somewhere behind the file.");
+    }
+}
+// ------------------------------------------------------------------------------------------------
+// Setup configuration properties
+void MDCImporter::SetupProperties(const Importer* pImp)
+{
+	// The AI_CONFIG_IMPORT_MDC_KEYFRAME option overrides the
+	// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
+	if(0xffffffff == (this->configFrameID = pImp->GetProperty(
+		AI_CONFIG_IMPORT_MDC_KEYFRAME,0xffffffff)))
+	{
+		this->configFrameID = pImp->GetProperty(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
+	}
+}
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure. 
+void MDCImporter::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 MDC file " + pFile + ".");
+
+	// check whether the mdc file is large enough to contain the file header
+	fileSize = (unsigned int)file->FileSize();
+	if( fileSize < sizeof(MDC::Header))
+		throw new ImportErrorException( "MDC File is too small.");
+
+	std::vector<unsigned char> mBuffer2(fileSize);
+	file->Read( &mBuffer2[0], 1, fileSize);
+	mBuffer = &mBuffer2[0];
+
+	// validate the file header
+	this->pcHeader = (BE_NCONST MDC::Header*)this->mBuffer;
+	this->ValidateHeader();
+
+	std::vector<std::string> aszShaders;
+
+	// get a pointer to the frame we want to read
+	BE_NCONST MDC::Frame* pcFrame = (BE_NCONST MDC::Frame*)(this->mBuffer+
+		this->pcHeader->ulOffsetBorderFrames);
+
+	// no need to swap the other members, we won't need them
+	pcFrame += configFrameID;
+	AI_SWAP4( pcFrame->localOrigin[0] );
+	AI_SWAP4( pcFrame->localOrigin[1] );
+	AI_SWAP4( pcFrame->localOrigin[2] );
+
+	// get the number of valid surfaces
+	BE_NCONST MDC::Surface* pcSurface, *pcSurface2;
+	pcSurface = pcSurface2 = (BE_NCONST MDC::Surface*)(mBuffer + pcHeader->ulOffsetSurfaces);
+	unsigned int iNumShaders = 0;
+	for (unsigned int i = 0; i < pcHeader->ulNumSurfaces;++i)
+	{
+		// validate the surface header
+		this->ValidateSurfaceHeader(pcSurface2);
+
+		if (pcSurface2->ulNumVertices && pcSurface2->ulNumTriangles)++pScene->mNumMeshes;
+		iNumShaders += pcSurface2->ulNumShaders;
+		pcSurface2 = (const MDC::Surface*)((int8_t*)pcSurface2 + pcSurface2->ulOffsetEnd);
+	}
+	aszShaders.reserve(iNumShaders);
+	pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+
+	// necessary that we don't crash if an exception occurs
+	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+		pScene->mMeshes[i] = NULL;
+
+	// now read all surfaces
+	unsigned int iDefaultMatIndex = 0xffffffff;
+	for (unsigned int i = 0, iNum = 0; i < pcHeader->ulNumSurfaces;++i)
+	{
+		if (!pcSurface->ulNumVertices || !pcSurface->ulNumTriangles)continue;
+		aiMesh* pcMesh = pScene->mMeshes[iNum++] = new aiMesh();
+
+		pcMesh->mNumFaces = pcSurface->ulNumTriangles;
+		pcMesh->mNumVertices = pcMesh->mNumFaces * 3;
+
+		// store the name of the surface for use as node name.
+		// FIX: make sure there is a 0 termination
+		const_cast<char&>(pcSurface->ucName[AI_MDC_MAXQPATH-1]) = '\0';
+		pcMesh->mTextureCoords[3] = (aiVector3D*)pcSurface->ucName;
+
+		// go to the first shader in the file. ignore the others.
+		if (pcSurface->ulNumShaders)
+		{
+			const MDC::Shader* pcShader = (const MDC::Shader*)((int8_t*)pcSurface + pcSurface->ulOffsetShaders);
+			pcMesh->mMaterialIndex = (unsigned int)aszShaders.size();
+			
+			// create a new shader
+			aszShaders.push_back(std::string( pcShader->ucName, std::min(
+				::strlen(pcShader->ucName),sizeof(pcShader->ucName)) ));
+		}
+		// need to create a default material
+		else if (0xffffffff == iDefaultMatIndex)
+		{
+			pcMesh->mMaterialIndex = iDefaultMatIndex = (unsigned int)aszShaders.size();
+			aszShaders.push_back(std::string());
+		}
+		// otherwise assign a reference to the default material
+		else pcMesh->mMaterialIndex = iDefaultMatIndex;
+
+		// allocate output storage for the mesh
+		aiVector3D* pcVertCur	= pcMesh->mVertices			= new aiVector3D[pcMesh->mNumVertices];
+		aiVector3D* pcNorCur	= pcMesh->mNormals			= new aiVector3D[pcMesh->mNumVertices];
+		aiVector3D* pcUVCur		= pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+		aiFace* pcFaceCur		= pcMesh->mFaces			= new aiFace[pcMesh->mNumFaces];
+
+		// create all vertices/faces
+		BE_NCONST MDC::Triangle* pcTriangle = (BE_NCONST MDC::Triangle*)
+			((int8_t*)pcSurface+pcSurface->ulOffsetTriangles);
+
+		BE_NCONST MDC::TexturCoord* const pcUVs = (BE_NCONST MDC::TexturCoord*)
+			((int8_t*)pcSurface+pcSurface->ulOffsetTexCoords);
+
+		// get a pointer to the uncompressed vertices
+		int16_t iOfs = *((int16_t*) ((int8_t*) pcSurface +
+			pcSurface->ulOffsetFrameBaseFrames) +  this->configFrameID);
+
+		AI_SWAP2(iOfs);
+
+		BE_NCONST MDC::BaseVertex* const pcVerts = (BE_NCONST MDC::BaseVertex*)
+			((int8_t*)pcSurface+pcSurface->ulOffsetBaseVerts) +
+			((int)iOfs * pcSurface->ulNumVertices * 4);
+
+		// do the main swapping stuff ...
+#if (defined AI_BUILD_BIG_ENDIAN)
+
+		// swap all triangles
+		for (unsigned int i = 0; i < pcSurface->ulNumTriangles;++i)
+		{
+			AI_SWAP4( pcTriangle[i].aiIndices[0] );
+			AI_SWAP4( pcTriangle[i].aiIndices[1] );
+			AI_SWAP4( pcTriangle[i].aiIndices[2] );
+		}
+
+		// swap all vertices
+		for (unsigned int i = 0; i < pcSurface->ulNumVertices*pcSurface->ulNumBaseFrames;++i)
+		{
+			AI_SWAP2( pcVerts->normal );
+			AI_SWAP2( pcVerts->x );
+			AI_SWAP2( pcVerts->y );
+			AI_SWAP2( pcVerts->z );
+		}
+
+		// swap all texture coordinates
+		for (unsigned int i = 0; i < pcSurface->ulNumVertices;++i)
+		{
+			AI_SWAP4( pcUVs->v );
+			AI_SWAP4( pcUVs->v );
+		}
+
+#endif
+
+		const MDC::CompressedVertex* pcCVerts;
+		int16_t* mdcCompVert = NULL;
+
+		// access compressed frames for large frame numbers, but never for the first
+		if( this->configFrameID && pcSurface->ulNumCompFrames > 0 )
+		{
+			mdcCompVert = (int16_t*) ((int8_t*)pcSurface+pcSurface->ulOffsetFrameCompFrames) + this->configFrameID;
+			AI_SWAP2P(mdcCompVert);
+			if( *mdcCompVert >= 0 )
+			{
+				pcCVerts = (const MDC::CompressedVertex*)((int8_t*)pcSurface +
+					pcSurface->ulOffsetCompVerts) + *mdcCompVert * pcSurface->ulNumVertices;
+			}
+			else mdcCompVert = NULL;
+		}
+
+		// copy all faces
+		for (unsigned int iFace = 0; iFace < pcSurface->ulNumTriangles;++iFace,
+			++pcTriangle,++pcFaceCur)
+		{
+			const unsigned int iOutIndex = iFace*3;
+			pcFaceCur->mNumIndices = 3;
+			pcFaceCur->mIndices = new unsigned int[3];
+
+			for (unsigned int iIndex = 0; iIndex < 3;++iIndex,
+				++pcVertCur,++pcUVCur,++pcNorCur)
+			{
+				uint32_t quak = pcTriangle->aiIndices[iIndex];
+				if (quak >= pcSurface->ulNumVertices)
+				{
+					DefaultLogger::get()->error("MDC vertex index is out of range");
+					quak = pcSurface->ulNumVertices-1;
+				}
+
+				// compressed vertices?
+				if (mdcCompVert)
+				{
+					MDC::BuildVertex(*pcFrame,pcVerts[quak],pcCVerts[quak],
+						*pcVertCur,*pcNorCur);
+				}
+				else
+				{
+					// copy position
+					pcVertCur->x = pcVerts[quak].x * AI_MDC_BASE_SCALING;
+					pcVertCur->y = pcVerts[quak].y * AI_MDC_BASE_SCALING;
+					pcVertCur->z = pcVerts[quak].z * AI_MDC_BASE_SCALING;
+
+					// copy normals
+					MD3::LatLngNormalToVec3( pcVerts[quak].normal, &pcNorCur->x );
+
+					// copy texture coordinates
+					pcUVCur->x = pcUVs[quak].u;
+					pcUVCur->y = 1.0f-pcUVs[quak].v; // DX to OGL
+				}
+				pcVertCur->x += pcFrame->localOrigin[0] ;
+				pcVertCur->y += pcFrame->localOrigin[1] ;
+				pcVertCur->z += pcFrame->localOrigin[2] ;
+			}
+
+			// swap the face order - DX to OGL
+			pcFaceCur->mIndices[0] = iOutIndex + 2;
+			pcFaceCur->mIndices[1] = iOutIndex + 1;
+			pcFaceCur->mIndices[2] = iOutIndex + 0;
+		}
+
+		pcSurface = (BE_NCONST MDC::Surface*)((int8_t*)pcSurface + pcSurface->ulOffsetEnd);
+	}
+
+	// create a flat node graph with a root node and one child for each surface
+	if (!pScene->mNumMeshes)
+		throw new ImportErrorException( "Invalid MDC file: File contains no valid mesh");
+	else if (1 == pScene->mNumMeshes)
+	{
+		pScene->mRootNode = new aiNode();
+		pScene->mRootNode->mName.Set(std::string((const char*)pScene->mMeshes[0]->mTextureCoords[3]));
+		pScene->mRootNode->mNumMeshes = 1;
+		pScene->mRootNode->mMeshes = new unsigned int[1];
+		pScene->mRootNode->mMeshes[0] = 0;
+	}
+	else
+	{
+		pScene->mRootNode = new aiNode();
+		pScene->mRootNode->mNumChildren = pScene->mNumMeshes;
+		pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes];
+		pScene->mRootNode->mName.Set("<root>");
+		for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+		{
+			aiNode* pcNode = pScene->mRootNode->mChildren[i] = new aiNode();
+			pcNode->mParent = pScene->mRootNode;
+			pcNode->mName.Set(std::string((const char*)pScene->mMeshes[i]->mTextureCoords[3]));
+			pcNode->mNumMeshes = 1;
+			pcNode->mMeshes = new unsigned int[1];
+			pcNode->mMeshes[0] = i;
+		}
+	}
+
+	// make sure we invalidate the pointer to the mesh name
+	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+		pScene->mMeshes[i]->mTextureCoords[3] = NULL;
+
+	// create materials
+	pScene->mNumMaterials = aszShaders.size();
+	pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+	for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+	{
+		MaterialHelper* pcMat = new MaterialHelper();
+		pScene->mMaterials[i] = pcMat;
+
+		const std::string& name = aszShaders[i];
+
+		int iMode = (int)aiShadingMode_Gouraud;
+		pcMat->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+		// add a small ambient color value - RtCW seems to have one
+		aiColor3D clr;
+		clr.b = clr.g = clr.r = 0.05f;
+		pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+
+		if (name.length())clr.b = clr.g = clr.r = 1.0f;
+		else clr.b = clr.g = clr.r = 0.6f;
+
+		pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+		pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+		if (name.length())
+		{
+			aiString path;
+			path.Set(name);
+			pcMat->AddProperty(&path,AI_MATKEY_TEXTURE_DIFFUSE(0));
+		}
+	}
+}

+ 132 - 0
code/MDCLoader.h

@@ -0,0 +1,132 @@
+/*
+Open 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 MDC importer class. */
+#ifndef AI_MDCLOADER_H_INCLUDED
+#define AI_MDCLOADER_H_INCLUDED
+
+#include "../include/aiTypes.h"
+
+#include "BaseImporter.h"
+#include "MDCFileData.h"
+#include "ByteSwap.h"
+
+namespace Assimp
+{
+using namespace MDC;
+
+// ---------------------------------------------------------------------------
+/** Used to load MDC files
+*/
+class MDCImporter : public BaseImporter
+{
+	friend class Importer;
+
+protected:
+	/** Constructor to be privately used by Importer */
+	MDCImporter();
+
+	/** Destructor, private as well */
+	~MDCImporter();
+
+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;
+
+	// -------------------------------------------------------------------
+	/** Called prior to ReadFile().
+	* The function is a request to the importer to update its configuration
+	* basing on the Importer's configuration property list.
+	*/
+	void SetupProperties(const Importer* pImp);
+
+protected:
+
+	// -------------------------------------------------------------------
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 * See BaseImporter::GetExtensionList() for details
+	 */
+	void GetExtensionList(std::string& append)
+	{
+		append.append("*.mdc");
+	}
+
+	// -------------------------------------------------------------------
+	/** 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:
+
+
+	// -------------------------------------------------------------------
+	/** Validate the header of the file
+	*/
+	void ValidateHeader();
+
+	// -------------------------------------------------------------------
+	/** Validate the header of a MDC surface
+	*/
+	void ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf);
+
+protected:
+
+
+	/** Configuration option: frame to be loaded */
+	unsigned int configFrameID;
+
+	/** Header of the MDC file */
+	BE_NCONST MDC::Header* pcHeader;
+
+	/** Buffer to hold the loaded file */
+	unsigned char* mBuffer;
+
+	/** size of the file, in bytes */
+	unsigned int fileSize;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_3DSIMPORTER_H_INC

+ 299 - 0
code/MDCNormalTable.h

@@ -0,0 +1,299 @@
+/* -----------------------------------------------------------------------------
+
+PicoModel Library 
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use 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 names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission. 
+
+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 MDC_NORMAL_TABLE_INCLUDED)
+#define MDC_NORMAL_TABLE_INCLUDED
+
+/* mdc decoding normal table */
+float mdcNormals[ 256 ][ 3 ] =
+{
+	{ 1.000000f, 0.000000f, 0.000000f },
+	{ 0.980785f, 0.195090f, 0.000000f },
+	{ 0.923880f, 0.382683f, 0.000000f },
+	{ 0.831470f, 0.555570f, 0.000000f },
+	{ 0.707107f, 0.707107f, 0.000000f },
+	{ 0.555570f, 0.831470f, 0.000000f },
+	{ 0.382683f, 0.923880f, 0.000000f },
+	{ 0.195090f, 0.980785f, 0.000000f },
+	{ -0.000000f, 1.000000f, 0.000000f },
+	{ -0.195090f, 0.980785f, 0.000000f },
+	{ -0.382683f, 0.923880f, 0.000000f },
+	{ -0.555570f, 0.831470f, 0.000000f },
+	{ -0.707107f, 0.707107f, 0.000000f },
+	{ -0.831470f, 0.555570f, 0.000000f },
+	{ -0.923880f, 0.382683f, 0.000000f },
+	{ -0.980785f, 0.195090f, 0.000000f },
+	{ -1.000000f, -0.000000f, 0.000000f },
+	{ -0.980785f, -0.195090f, 0.000000f },
+	{ -0.923880f, -0.382683f, 0.000000f },
+	{ -0.831470f, -0.555570f, 0.000000f },
+	{ -0.707107f, -0.707107f, 0.000000f },
+	{ -0.555570f, -0.831469f, 0.000000f },
+	{ -0.382684f, -0.923880f, 0.000000f },
+	{ -0.195090f, -0.980785f, 0.000000f },
+	{ 0.000000f, -1.000000f, 0.000000f },
+	{ 0.195090f, -0.980785f, 0.000000f },
+	{ 0.382684f, -0.923879f, 0.000000f },
+	{ 0.555570f, -0.831470f, 0.000000f },
+	{ 0.707107f, -0.707107f, 0.000000f },
+	{ 0.831470f, -0.555570f, 0.000000f },
+	{ 0.923880f, -0.382683f, 0.000000f },
+	{ 0.980785f, -0.195090f, 0.000000f },
+	{ 0.980785f, 0.000000f, -0.195090f },
+	{ 0.956195f, 0.218245f, -0.195090f },
+	{ 0.883657f, 0.425547f, -0.195090f },
+	{ 0.766809f, 0.611510f, -0.195090f },
+	{ 0.611510f, 0.766809f, -0.195090f },
+	{ 0.425547f, 0.883657f, -0.195090f },
+	{ 0.218245f, 0.956195f, -0.195090f },
+	{ -0.000000f, 0.980785f, -0.195090f },
+	{ -0.218245f, 0.956195f, -0.195090f },
+	{ -0.425547f, 0.883657f, -0.195090f },
+	{ -0.611510f, 0.766809f, -0.195090f },
+	{ -0.766809f, 0.611510f, -0.195090f },
+	{ -0.883657f, 0.425547f, -0.195090f },
+	{ -0.956195f, 0.218245f, -0.195090f },
+	{ -0.980785f, -0.000000f, -0.195090f },
+	{ -0.956195f, -0.218245f, -0.195090f },
+	{ -0.883657f, -0.425547f, -0.195090f },
+	{ -0.766809f, -0.611510f, -0.195090f },
+	{ -0.611510f, -0.766809f, -0.195090f },
+	{ -0.425547f, -0.883657f, -0.195090f },
+	{ -0.218245f, -0.956195f, -0.195090f },
+	{ 0.000000f, -0.980785f, -0.195090f },
+	{ 0.218245f, -0.956195f, -0.195090f },
+	{ 0.425547f, -0.883657f, -0.195090f },
+	{ 0.611510f, -0.766809f, -0.195090f },
+	{ 0.766809f, -0.611510f, -0.195090f },
+	{ 0.883657f, -0.425547f, -0.195090f },
+	{ 0.956195f, -0.218245f, -0.195090f },
+	{ 0.923880f, 0.000000f, -0.382683f },
+	{ 0.892399f, 0.239118f, -0.382683f },
+	{ 0.800103f, 0.461940f, -0.382683f },
+	{ 0.653281f, 0.653281f, -0.382683f },
+	{ 0.461940f, 0.800103f, -0.382683f },
+	{ 0.239118f, 0.892399f, -0.382683f },
+	{ -0.000000f, 0.923880f, -0.382683f },
+	{ -0.239118f, 0.892399f, -0.382683f },
+	{ -0.461940f, 0.800103f, -0.382683f },
+	{ -0.653281f, 0.653281f, -0.382683f },
+	{ -0.800103f, 0.461940f, -0.382683f },
+	{ -0.892399f, 0.239118f, -0.382683f },
+	{ -0.923880f, -0.000000f, -0.382683f },
+	{ -0.892399f, -0.239118f, -0.382683f },
+	{ -0.800103f, -0.461940f, -0.382683f },
+	{ -0.653282f, -0.653281f, -0.382683f },
+	{ -0.461940f, -0.800103f, -0.382683f },
+	{ -0.239118f, -0.892399f, -0.382683f },
+	{ 0.000000f, -0.923880f, -0.382683f },
+	{ 0.239118f, -0.892399f, -0.382683f },
+	{ 0.461940f, -0.800103f, -0.382683f },
+	{ 0.653281f, -0.653282f, -0.382683f },
+	{ 0.800103f, -0.461940f, -0.382683f },
+	{ 0.892399f, -0.239117f, -0.382683f },
+	{ 0.831470f, 0.000000f, -0.555570f },
+	{ 0.790775f, 0.256938f, -0.555570f },
+	{ 0.672673f, 0.488726f, -0.555570f },
+	{ 0.488726f, 0.672673f, -0.555570f },
+	{ 0.256938f, 0.790775f, -0.555570f },
+	{ -0.000000f, 0.831470f, -0.555570f },
+	{ -0.256938f, 0.790775f, -0.555570f },
+	{ -0.488726f, 0.672673f, -0.555570f },
+	{ -0.672673f, 0.488726f, -0.555570f },
+	{ -0.790775f, 0.256938f, -0.555570f },
+	{ -0.831470f, -0.000000f, -0.555570f },
+	{ -0.790775f, -0.256938f, -0.555570f },
+	{ -0.672673f, -0.488726f, -0.555570f },
+	{ -0.488725f, -0.672673f, -0.555570f },
+	{ -0.256938f, -0.790775f, -0.555570f },
+	{ 0.000000f, -0.831470f, -0.555570f },
+	{ 0.256938f, -0.790775f, -0.555570f },
+	{ 0.488725f, -0.672673f, -0.555570f },
+	{ 0.672673f, -0.488726f, -0.555570f },
+	{ 0.790775f, -0.256938f, -0.555570f },
+	{ 0.707107f, 0.000000f, -0.707107f },
+	{ 0.653281f, 0.270598f, -0.707107f },
+	{ 0.500000f, 0.500000f, -0.707107f },
+	{ 0.270598f, 0.653281f, -0.707107f },
+	{ -0.000000f, 0.707107f, -0.707107f },
+	{ -0.270598f, 0.653282f, -0.707107f },
+	{ -0.500000f, 0.500000f, -0.707107f },
+	{ -0.653281f, 0.270598f, -0.707107f },
+	{ -0.707107f, -0.000000f, -0.707107f },
+	{ -0.653281f, -0.270598f, -0.707107f },
+	{ -0.500000f, -0.500000f, -0.707107f },
+	{ -0.270598f, -0.653281f, -0.707107f },
+	{ 0.000000f, -0.707107f, -0.707107f },
+	{ 0.270598f, -0.653281f, -0.707107f },
+	{ 0.500000f, -0.500000f, -0.707107f },
+	{ 0.653282f, -0.270598f, -0.707107f },
+	{ 0.555570f, 0.000000f, -0.831470f },
+	{ 0.481138f, 0.277785f, -0.831470f },
+	{ 0.277785f, 0.481138f, -0.831470f },
+	{ -0.000000f, 0.555570f, -0.831470f },
+	{ -0.277785f, 0.481138f, -0.831470f },
+	{ -0.481138f, 0.277785f, -0.831470f },
+	{ -0.555570f, -0.000000f, -0.831470f },
+	{ -0.481138f, -0.277785f, -0.831470f },
+	{ -0.277785f, -0.481138f, -0.831470f },
+	{ 0.000000f, -0.555570f, -0.831470f },
+	{ 0.277785f, -0.481138f, -0.831470f },
+	{ 0.481138f, -0.277785f, -0.831470f },
+	{ 0.382683f, 0.000000f, -0.923880f },
+	{ 0.270598f, 0.270598f, -0.923880f },
+	{ -0.000000f, 0.382683f, -0.923880f },
+	{ -0.270598f, 0.270598f, -0.923880f },
+	{ -0.382683f, -0.000000f, -0.923880f },
+	{ -0.270598f, -0.270598f, -0.923880f },
+	{ 0.000000f, -0.382683f, -0.923880f },
+	{ 0.270598f, -0.270598f, -0.923880f },
+	{ 0.195090f, 0.000000f, -0.980785f },
+	{ -0.000000f, 0.195090f, -0.980785f },
+	{ -0.195090f, -0.000000f, -0.980785f },
+	{ 0.000000f, -0.195090f, -0.980785f },
+	{ 0.980785f, 0.000000f, 0.195090f },
+	{ 0.956195f, 0.218245f, 0.195090f },
+	{ 0.883657f, 0.425547f, 0.195090f },
+	{ 0.766809f, 0.611510f, 0.195090f },
+	{ 0.611510f, 0.766809f, 0.195090f },
+	{ 0.425547f, 0.883657f, 0.195090f },
+	{ 0.218245f, 0.956195f, 0.195090f },
+	{ -0.000000f, 0.980785f, 0.195090f },
+	{ -0.218245f, 0.956195f, 0.195090f },
+	{ -0.425547f, 0.883657f, 0.195090f },
+	{ -0.611510f, 0.766809f, 0.195090f },
+	{ -0.766809f, 0.611510f, 0.195090f },
+	{ -0.883657f, 0.425547f, 0.195090f },
+	{ -0.956195f, 0.218245f, 0.195090f },
+	{ -0.980785f, -0.000000f, 0.195090f },
+	{ -0.956195f, -0.218245f, 0.195090f },
+	{ -0.883657f, -0.425547f, 0.195090f },
+	{ -0.766809f, -0.611510f, 0.195090f },
+	{ -0.611510f, -0.766809f, 0.195090f },
+	{ -0.425547f, -0.883657f, 0.195090f },
+	{ -0.218245f, -0.956195f, 0.195090f },
+	{ 0.000000f, -0.980785f, 0.195090f },
+	{ 0.218245f, -0.956195f, 0.195090f },
+	{ 0.425547f, -0.883657f, 0.195090f },
+	{ 0.611510f, -0.766809f, 0.195090f },
+	{ 0.766809f, -0.611510f, 0.195090f },
+	{ 0.883657f, -0.425547f, 0.195090f },
+	{ 0.956195f, -0.218245f, 0.195090f },
+	{ 0.923880f, 0.000000f, 0.382683f },
+	{ 0.892399f, 0.239118f, 0.382683f },
+	{ 0.800103f, 0.461940f, 0.382683f },
+	{ 0.653281f, 0.653281f, 0.382683f },
+	{ 0.461940f, 0.800103f, 0.382683f },
+	{ 0.239118f, 0.892399f, 0.382683f },
+	{ -0.000000f, 0.923880f, 0.382683f },
+	{ -0.239118f, 0.892399f, 0.382683f },
+	{ -0.461940f, 0.800103f, 0.382683f },
+	{ -0.653281f, 0.653281f, 0.382683f },
+	{ -0.800103f, 0.461940f, 0.382683f },
+	{ -0.892399f, 0.239118f, 0.382683f },
+	{ -0.923880f, -0.000000f, 0.382683f },
+	{ -0.892399f, -0.239118f, 0.382683f },
+	{ -0.800103f, -0.461940f, 0.382683f },
+	{ -0.653282f, -0.653281f, 0.382683f },
+	{ -0.461940f, -0.800103f, 0.382683f },
+	{ -0.239118f, -0.892399f, 0.382683f },
+	{ 0.000000f, -0.923880f, 0.382683f },
+	{ 0.239118f, -0.892399f, 0.382683f },
+	{ 0.461940f, -0.800103f, 0.382683f },
+	{ 0.653281f, -0.653282f, 0.382683f },
+	{ 0.800103f, -0.461940f, 0.382683f },
+	{ 0.892399f, -0.239117f, 0.382683f },
+	{ 0.831470f, 0.000000f, 0.555570f },
+	{ 0.790775f, 0.256938f, 0.555570f },
+	{ 0.672673f, 0.488726f, 0.555570f },
+	{ 0.488726f, 0.672673f, 0.555570f },
+	{ 0.256938f, 0.790775f, 0.555570f },
+	{ -0.000000f, 0.831470f, 0.555570f },
+	{ -0.256938f, 0.790775f, 0.555570f },
+	{ -0.488726f, 0.672673f, 0.555570f },
+	{ -0.672673f, 0.488726f, 0.555570f },
+	{ -0.790775f, 0.256938f, 0.555570f },
+	{ -0.831470f, -0.000000f, 0.555570f },
+	{ -0.790775f, -0.256938f, 0.555570f },
+	{ -0.672673f, -0.488726f, 0.555570f },
+	{ -0.488725f, -0.672673f, 0.555570f },
+	{ -0.256938f, -0.790775f, 0.555570f },
+	{ 0.000000f, -0.831470f, 0.555570f },
+	{ 0.256938f, -0.790775f, 0.555570f },
+	{ 0.488725f, -0.672673f, 0.555570f },
+	{ 0.672673f, -0.488726f, 0.555570f },
+	{ 0.790775f, -0.256938f, 0.555570f },
+	{ 0.707107f, 0.000000f, 0.707107f },
+	{ 0.653281f, 0.270598f, 0.707107f },
+	{ 0.500000f, 0.500000f, 0.707107f },
+	{ 0.270598f, 0.653281f, 0.707107f },
+	{ -0.000000f, 0.707107f, 0.707107f },
+	{ -0.270598f, 0.653282f, 0.707107f },
+	{ -0.500000f, 0.500000f, 0.707107f },
+	{ -0.653281f, 0.270598f, 0.707107f },
+	{ -0.707107f, -0.000000f, 0.707107f },
+	{ -0.653281f, -0.270598f, 0.707107f },
+	{ -0.500000f, -0.500000f, 0.707107f },
+	{ -0.270598f, -0.653281f, 0.707107f },
+	{ 0.000000f, -0.707107f, 0.707107f },
+	{ 0.270598f, -0.653281f, 0.707107f },
+	{ 0.500000f, -0.500000f, 0.707107f },
+	{ 0.653282f, -0.270598f, 0.707107f },
+	{ 0.555570f, 0.000000f, 0.831470f },
+	{ 0.481138f, 0.277785f, 0.831470f },
+	{ 0.277785f, 0.481138f, 0.831470f },
+	{ -0.000000f, 0.555570f, 0.831470f },
+	{ -0.277785f, 0.481138f, 0.831470f },
+	{ -0.481138f, 0.277785f, 0.831470f },
+	{ -0.555570f, -0.000000f, 0.831470f },
+	{ -0.481138f, -0.277785f, 0.831470f },
+	{ -0.277785f, -0.481138f, 0.831470f },
+	{ 0.000000f, -0.555570f, 0.831470f },
+	{ 0.277785f, -0.481138f, 0.831470f },
+	{ 0.481138f, -0.277785f, 0.831470f },
+	{ 0.382683f, 0.000000f, 0.923880f },
+	{ 0.270598f, 0.270598f, 0.923880f },
+	{ -0.000000f, 0.382683f, 0.923880f },
+	{ -0.270598f, 0.270598f, 0.923880f },
+	{ -0.382683f, -0.000000f, 0.923880f },
+	{ -0.270598f, -0.270598f, 0.923880f },
+	{ 0.000000f, -0.382683f, 0.923880f },
+	{ 0.270598f, -0.270598f, 0.923880f },
+	{ 0.195090f, 0.000000f, 0.980785f },
+	{ -0.000000f, 0.195090f, 0.980785f },
+	{ -0.195090f, -0.000000f, 0.980785f },
+	{ 0.000000f, -0.195090f, 0.980785f }
+};
+
+#endif // !! MDC_NORMAL_TABLE_INCLUDED

+ 242 - 285
code/MDLLoader.cpp

@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "MDLDefaultColorMap.h"
 #include "MD2FileData.h" 
 #include "qnan.h" 
+#include "ByteSwap.h" 
 
 // public ASSIMP headers
 #include "../include/DefaultLogger.h"
@@ -62,8 +63,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-extern float g_avNormals[162][3];
-
 
 // ------------------------------------------------------------------------------------------------
 // macros used by the MDL7 loader
@@ -81,7 +80,6 @@ extern float g_avNormals[162][3];
 	_AI_MDL7_ACCESS(_data,_index,_limit,MDL::Vertex_MDL7)
 #endif
 
-
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 MDLImporter::MDLImporter()
@@ -116,36 +114,34 @@ bool MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
+// Setup configuration properties
+void MDLImporter::SetupProperties(const Importer* pImp)
+{
+	// The AI_CONFIG_IMPORT_MDL_KEYFRAME option overrides the
+	// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
+	if(0xffffffff == (this->configFrameID = pImp->GetProperty(
+		AI_CONFIG_IMPORT_MDL_KEYFRAME,0xffffffff)))
+	{
+		this->configFrameID =  pImp->GetProperty(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
+	}
+}
+// ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure. 
-void MDLImporter::InternReadFile( 
-	const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
+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 + ".");
-	}
 
-	// The AI_CONFIG_IMPORT_MDL_KEYFRAME option overrides the
-	// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
-#if 0
-	if(0xffffffff == (this->configFrameID = this->mImporter->GetProperty(
-		AI_CONFIG_IMPORT_MDL_KEYFRAME,0xffffffff)))
-	{
-		this->configFrameID = this->mImporter->GetProperty(
-			AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
-	}
-#endif
 
 	// this should work for all other types of MDL files, too ...
 	// the quake header is one of the smallest, afaik
 	this->iFileSize = (unsigned int)file->FileSize();
 	if( this->iFileSize < 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;
@@ -162,89 +158,93 @@ void MDLImporter::InternReadFile(
 	// determine the file subtype and call the appropriate member function
 	try {
 
-	// Original Quake1 format
-	if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord ||
-		AI_MDL_MAGIC_NUMBER_LE == iMagicWord)
-	{
-		DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO");
-		this->iGSFileVersion = 0;
-		this->InternReadFile_Quake1();
-	}
-	// GameStudio A<old> MDL2 format - used by some test models that come with 3DGS
-	else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord ||
-			 AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord)
-	{
-		DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A2, magic word is MDL2");
-		this->iGSFileVersion = 2;
-		this->InternReadFile_Quake1();
-	}
-	// GameStudio A4 MDL3 format
-	else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord ||
-			 AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord)
-	{
-		DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3");
-		this->iGSFileVersion = 3;
-		this->InternReadFile_3DGS_MDL345();
-	}
-	// GameStudio A5+ MDL4 format
-	else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord ||
-			 AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord)
-	{
-		DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4");
-		this->iGSFileVersion = 4;
-		this->InternReadFile_3DGS_MDL345();
-	}
-	// GameStudio A5+ MDL5 format
-	else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord ||
-			 AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord)
-	{
-		DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5");
-		this->iGSFileVersion = 5;
-		this->InternReadFile_3DGS_MDL345();
-	}
-	// GameStudio A6+ MDL6 format (not sure whether it is really existing ... )
-	else if (AI_MDL_MAGIC_NUMBER_BE_GS6 == iMagicWord ||
-			 AI_MDL_MAGIC_NUMBER_LE_GS6 == iMagicWord)
-	{
-		DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A6, magic word is MDL6");
-		this->iGSFileVersion = 6;
-		this->InternReadFile_3DGS_MDL345();
-	}
-	// GameStudio A7 MDL7 format
-	else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord ||
-			 AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord)
-	{
-		DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7");
-		this->iGSFileVersion = 7;
-		this->InternReadFile_3DGS_MDL7();
-	}
-	// IDST/IDSQ Format (CS:S/HL², etc ...)
-	else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord ||
-			 AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
-			 AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord ||
-			 AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord)
-	{
-		DefaultLogger::get()->debug("MDL subtype: CS:S\\HL², magic word is IDST/IDSQ");
-		this->iGSFileVersion = 0;
-		this->InternReadFile_HL2();
-	}
-	else
-	{
-		// print the magic word to the logger
-		char szBuffer[5];
-		szBuffer[0] = ((char*)&iMagicWord)[0];
-		szBuffer[1] = ((char*)&iMagicWord)[1];
-		szBuffer[2] = ((char*)&iMagicWord)[2];
-		szBuffer[3] = ((char*)&iMagicWord)[3];
-		szBuffer[4] = '\0';
-
-		// we're definitely unable to load this file
-		throw new ImportErrorException( "Unknown MDL subformat " + pFile +
-			". Magic word (" + szBuffer + ") is not known");
-	}
+		// Original Quake1 format
+		if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord ||
+			AI_MDL_MAGIC_NUMBER_LE == iMagicWord)
+		{
+			DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO");
+			this->iGSFileVersion = 0;
+			this->InternReadFile_Quake1();
+		}
+		// GameStudio A<old> MDL2 format - used by some test models that come with 3DGS
+		else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord ||
+			AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord)
+		{
+			DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A2, magic word is MDL2");
+			this->iGSFileVersion = 2;
+			this->InternReadFile_Quake1();
+		}
+		// GameStudio A4 MDL3 format
+		else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord ||
+			AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord)
+		{
+			DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3");
+			this->iGSFileVersion = 3;
+			this->InternReadFile_3DGS_MDL345();
+		}
+		// GameStudio A5+ MDL4 format
+		else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord ||
+			AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord)
+		{
+			DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4");
+			this->iGSFileVersion = 4;
+			this->InternReadFile_3DGS_MDL345();
+		}
+		// GameStudio A5+ MDL5 format
+		else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord ||
+			AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord)
+		{
+			DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5");
+			this->iGSFileVersion = 5;
+			this->InternReadFile_3DGS_MDL345();
+		}
+		// GameStudio A6+ MDL6 format (not sure whether it is really existing ... )
+		else if (AI_MDL_MAGIC_NUMBER_BE_GS6 == iMagicWord ||
+			AI_MDL_MAGIC_NUMBER_LE_GS6 == iMagicWord)
+		{
+			DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A6, magic word is MDL6");
+			this->iGSFileVersion = 6;
+			this->InternReadFile_3DGS_MDL345();
+		}
+		// GameStudio A7 MDL7 format
+		else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord ||
+			AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord)
+		{
+			DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7");
+			this->iGSFileVersion = 7;
+			this->InternReadFile_3DGS_MDL7();
+		}
+		// IDST/IDSQ Format (CS:S/HL², etc ...)
+		else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord ||
+			AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
+			AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord ||
+			AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord)
+		{
+			DefaultLogger::get()->debug("MDL subtype: CS:S\\HL², magic word is IDST/IDSQ");
+			this->iGSFileVersion = 0;
+			this->InternReadFile_HL2();
+		}
+		else
+		{
+			// print the magic word to the logger
+			char szBuffer[5];
+			szBuffer[0] = ((char*)&iMagicWord)[0];
+			szBuffer[1] = ((char*)&iMagicWord)[1];
+			szBuffer[2] = ((char*)&iMagicWord)[2];
+			szBuffer[3] = ((char*)&iMagicWord)[3];
+			szBuffer[4] = '\0';
+
+			// we're definitely unable to load this file
+			throw new ImportErrorException( "Unknown MDL subformat " + pFile +
+				". Magic word (" + szBuffer + ") is not known");
+		}
 
-	} catch (ImportErrorException* ex) {
+	} 
+	catch (ImportErrorException* ex) {
 		delete[] this->mBuffer;
+		AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
+		AI_DEBUG_INVALIDATE_PTR(this->pIOHandler);
+		AI_DEBUG_INVALIDATE_PTR(this->pScene);
 		throw ex;
 	}
 
@@ -253,7 +253,6 @@ void MDLImporter::InternReadFile(
 	AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
 	AI_DEBUG_INVALIDATE_PTR(this->pIOHandler);
 	AI_DEBUG_INVALIDATE_PTR(this->pScene);
-	return;
 }
 // ------------------------------------------------------------------------------------------------
 void MDLImporter::SizeCheck(const void* szPos)
@@ -279,12 +278,7 @@ void MDLImporter::SizeCheck(const void* szPos, const char* szFile, unsigned int
 		if (szFilePtr)++szFilePtr;
 
 		char szBuffer[1024];
-#if _MSC_VER >= 1400
-		::sprintf_s(szBuffer,
-#else
-		::sprintf(szBuffer,
-#endif
-			"Invalid MDL file. The file is too small "
+		::sprintf(szBuffer,"Invalid MDL file. The file is too small "
 			"or contains invalid data (File: %s Line: %i)",szFilePtr,iLine);
 
 		throw new ImportErrorException(szBuffer);
@@ -295,56 +289,67 @@ void MDLImporter::ValidateHeader_Quake1(const MDL::Header* pcHeader)
 {
 	// some values may not be NULL
 	if (!pcHeader->num_frames)
-	{
 		throw new ImportErrorException( "[Quake 1 MDL] There are no frames in the file");
-	}
+
 	if (!pcHeader->num_verts)
-	{
 		throw new ImportErrorException( "[Quake 1 MDL] There are no vertices in the file");
-	}
+
 	if (!pcHeader->num_tris)
-	{
 		throw new ImportErrorException( "[Quake 1 MDL] There are no triangles in the file");
-	}
 
 	// check whether the maxima are exceeded ...however, this applies for Quake 1 MDLs only
 	if (!this->iGSFileVersion)
 	{
 		if (pcHeader->num_verts > AI_MDL_MAX_VERTS)
-		{
 			DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices");
-		}
+
 		if (pcHeader->num_tris > AI_MDL_MAX_TRIANGLES)
-		{
 			DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_TRIANGLES triangles");
-		}
+
 		if (pcHeader->num_frames > AI_MDL_MAX_FRAMES)
-		{
 			DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_FRAMES frames");
-		}
+
 		// (this does not apply for 3DGS MDLs)
 		if (!this->iGSFileVersion && pcHeader->version != AI_MDL_VERSION)
-		{
 			DefaultLogger::get()->warn("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is "
 				"the expected file format version");
-		}
-
-		if (pcHeader->num_skins)
-		{
-			if(!pcHeader->skinwidth || !pcHeader->skinheight)
-			{
-				DefaultLogger::get()->warn("Skin width or height are 0. Division through "
-					"zero would occur ...");
-			}
-		}
+		if(pcHeader->num_skins && (!pcHeader->skinwidth || !pcHeader->skinheight))
+			DefaultLogger::get()->warn("Skin width or height are 0");
 	}
 }
+#ifdef AI_BUILD_BIG_ENDIAN
+// ------------------------------------------------------------------------------------------------
+void FlipQuakeHeader(BE_NCONST MDL::Header* pcHeader)
+{
+	ByteSwap::Swap4(& pcHeader->ident);
+	ByteSwap::Swap4(& pcHeader->version);
+	ByteSwap::Swap4(& pcHeader->boundingradius);
+	ByteSwap::Swap4(& pcHeader->flags);
+	ByteSwap::Swap4(& pcHeader->num_frames);
+	ByteSwap::Swap4(& pcHeader->num_skins);
+	ByteSwap::Swap4(& pcHeader->num_tris);
+	ByteSwap::Swap4(& pcHeader->num_verts);
+	for (unsigned int i = 0; i < 3;++i)
+	{
+		ByteSwap::Swap4(& pcHeader->scale[i]);
+		ByteSwap::Swap4(& pcHeader->translate[i]);
+	}
+	ByteSwap::Swap4(& pcHeader->size);
+	ByteSwap::Swap4(& pcHeader->skinheight);
+	ByteSwap::Swap4(& pcHeader->skin);
+}
+#endif
 // ------------------------------------------------------------------------------------------------
 void MDLImporter::InternReadFile_Quake1( )
 {
 	ai_assert(NULL != pScene);
 
-	const MDL::Header* pcHeader = (const MDL::Header*)this->mBuffer;
+	BE_NCONST MDL::Header* pcHeader = (BE_NCONST MDL::Header*)this->mBuffer;
+
+#ifdef AI_BUILD_BIG_ENDIAN
+	FlipQuakeHeader(pcHeader);
+#endif
+
 	ValidateHeader_Quake1(pcHeader);
 
 	// current cursor position in the file
@@ -353,13 +358,16 @@ void MDLImporter::InternReadFile_Quake1( )
 	// need to read all textures
 	for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i)
 	{
-		union{const MDL::Skin* pcSkin;const MDL::GroupSkin* pcGroupSkin;};
-		pcSkin = (const MDL::Skin*)szCurrent;
+		union{BE_NCONST MDL::Skin* pcSkin;BE_NCONST MDL::GroupSkin* pcGroupSkin;};
+		pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
 
+		AI_SWAP4( pcSkin->group );
 
 		// Quake 1 groupskins
 		if (1 == pcSkin->group)
 		{
+			AI_SWAP4( pcGroupSkin->nb );
+
 			// need to skip multiple images
 			const unsigned int iNumImages = (unsigned int)pcGroupSkin->nb;
 			szCurrent += sizeof(uint32_t) * 2;
@@ -413,6 +421,25 @@ void MDLImporter::InternReadFile_Quake1( )
 
 	VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts));
 
+#ifdef AI_BUILD_BIG_ENDIAN
+
+	for (unsigned int i = 0; i<pcHeader->num_verts;++i)
+	{
+		AI_SWAP4( pcTexCoords[i].onseam );
+		AI_SWAP4( pcTexCoords[i].s );
+		AI_SWAP4( pcTexCoords[i].t );
+	}
+
+	for (unsigned int i = 0; i<pcHeader->num_tris;++i)
+	{
+		AI_SWAP4( pcTriangles[i].facesfront);
+		AI_SWAP4( pcTriangles[i].vertex[0]);
+		AI_SWAP4( pcTriangles[i].vertex[1]);
+		AI_SWAP4( pcTriangles[i].vertex[2]);
+	}
+
+#endif
+
 	// setup materials
 	this->SetupMaterialProperties_3DGS_MDL5_Quake1();
 
@@ -453,7 +480,6 @@ void MDLImporter::InternReadFile_Quake1( )
 			if (iIndex >= (unsigned int)pcHeader->num_verts)
 			{
 				iIndex = pcHeader->num_verts-1;
-				
 				DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list.");
 			}
 
@@ -461,16 +487,16 @@ void MDLImporter::InternReadFile_Quake1( )
 			vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
 			vec.x += pcHeader->translate[0];
 
-			// (flip z and y component)
-			vec.z = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
-			vec.z += pcHeader->translate[1];
+			vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
+			vec.y += pcHeader->translate[1];
+			vec.y *= -1.0f;
 
-			vec.y = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
-			vec.y += pcHeader->translate[2];
+			vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
+			vec.z += pcHeader->translate[2];
 
 			// read the normal vector from the precalculated normal table
 			MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
-			std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z );
+			pcMesh->mNormals[iCurrent].y *= -1.0f;
 
 			// read texture coordinates
 			float s = (float)pcTexCoords[iIndex].s;
@@ -546,6 +572,9 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
 
 	// the header of MDL 3/4/5 is nearly identical to the original Quake1 header
 	const MDL::Header* pcHeader = (const MDL::Header*)this->mBuffer;
+#ifdef AI_BUILD_BIG_ENDIAN
+	FlipQuakeHeader(pcHeader);
+#endif
 	this->ValidateHeader_Quake1(pcHeader);
 
 	// current cursor position in the file
@@ -584,6 +613,26 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
 	const MDL::Triangle_MDL3* pcTriangles = (const MDL::Triangle_MDL3*)szCurrent;
 	szCurrent += sizeof(MDL::Triangle_MDL3) * pcHeader->num_tris;
 
+#ifdef AI_BUILD_BIG_ENDIAN
+
+	for (unsigned int i = 0; i<pcHeader->synctype;++i)
+	{
+		AI_SWAP2( pcTexCoords[i].u );
+		AI_SWAP2( pcTexCoords[i].v );
+	}
+
+	for (unsigned int i = 0; i<pcHeader->num_tris;++i)
+	{
+		AI_SWAP4( pcTriangles[i].index_xyz[0]);
+		AI_SWAP4( pcTriangles[i].index_xyz[1]);
+		AI_SWAP4( pcTriangles[i].index_xyz[2]);
+		AI_SWAP4( pcTriangles[i].index_uv[0]);
+		AI_SWAP4( pcTriangles[i].index_uv[1]);
+		AI_SWAP4( pcTriangles[i].index_uv[2]);
+	}
+
+#endif
+
 	VALIDATE_FILE_SIZE(szCurrent);
 
 	// setup materials
@@ -620,15 +669,15 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
 	const MDL::Frame* pcFrames = (const MDL::Frame*)szCurrent;
 
 	// byte packed vertices
+	// BIG TODO: these two snippets are nearly totally identical ...
 	// ***********************************************************************
 	if (0 == pcFrames->type || 3 >= this->iGSFileVersion)
 	{
-		const MDL::SimpleFrame* pcFirstFrame = 
-			(const MDL::SimpleFrame*)(szCurrent + sizeof(uint32_t));
+		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));
+		const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) 
+			+ sizeof(pcFirstFrame->name));
 
 		VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
 
@@ -654,16 +703,16 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
 				vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
 				vec.x += pcHeader->translate[0];
 
-				// (flip z and y component)
-				vec.z = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
-				vec.z += pcHeader->translate[1];
+				vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
+				vec.y += pcHeader->translate[1];
+				vec.y *= -1.0f;
 
-				vec.y = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
-				vec.y += pcHeader->translate[2];
+				vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
+				vec.z += pcHeader->translate[2];
 
 				// read the normal vector from the precalculated normal table
 				MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
-				std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z );
+				pcMesh->mNormals[iCurrent].y *= -1.0f;
 
 				// read texture coordinates
 				if (pcHeader->synctype)
@@ -684,12 +733,11 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
 	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));
+		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));
+		const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*) ((pcFirstFrame->name) +
+			sizeof(pcFirstFrame->name));
 
 		VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
 
@@ -715,16 +763,16 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
 				vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
 				vec.x += pcHeader->translate[0];
 
-				// (flip z and y component)
-				vec.z = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
-				vec.z += pcHeader->translate[1];
+				vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
+				vec.y += pcHeader->translate[1];
+				vec.y *= -1.0f;
 
-				vec.y = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
-				vec.y += pcHeader->translate[2];
+				vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
+				vec.z += pcHeader->translate[2];
 
 				// read the normal vector from the precalculated normal table
 				MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
-				std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z );
+				pcMesh->mNormals[iCurrent].y *= -1.0f;
 
 				// read texture coordinates
 				if (pcHeader->synctype)
@@ -920,14 +968,9 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(const MDL::Bone_MDL7* pcBones,
 
 				if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE == pcHeader->bone_stc_size)
 				{
-					// no real name for our poor bone :-(
-#					if (_MSC_VER >= 1400)
-						pcOutBone->mName.length = ::sprintf_s(pcOutBone->mName.data,
-							MAXLEN,"UnnamedBone_%i",iBone);
-#					else
-						pcOutBone->mName.length = ::sprintf(pcOutBone->mName.data,
-							"UnnamedBone_%i",iBone);
-#					endif
+					// no real name for our poor bone is specified :-(	
+					pcOutBone->mName.length = ::sprintf(pcOutBone->mName.data,
+						"UnnamedBone_%i",iBone);
 				}
 				else
 				{
@@ -1012,17 +1055,15 @@ void MDLImporter::ReadFaces_3DGS_MDL7(
 			// write the output face index
 			groupData.pcFaces[iTriangle].mIndices[2-c] = iOutIndex;
 
-			// swap z and y axis
 			aiVector3D& vPosition = groupData.vPositions[ iOutIndex ];
 			vPosition.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .x;
-			vPosition.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y;
-			vPosition.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z;
+			vPosition.y = -1.0f*_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y;
+			vPosition.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z;
 
 			// if we have bones, save the index
 			if (!groupData.aiBones.empty())
-			{
-				groupData.aiBones[iOutIndex] = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size).vertindex;
-			}
+				groupData.aiBones[iOutIndex] = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,
+				iIndex,pcHeader->mainvertex_stc_size).vertindex;
 
 			// now read the normal vector
 			if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size)
@@ -1030,8 +1071,8 @@ void MDLImporter::ReadFaces_3DGS_MDL7(
 				// read the full normal vector
 				aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
 				vNormal.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[0];
-				vNormal.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1];
-				vNormal.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2];
+				vNormal.y = -1.0f*_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1];
+				vNormal.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2];
 			}
 			else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size)
 			{
@@ -1039,8 +1080,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(
 				aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
 				MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,
 					pcHeader->mainvertex_stc_size) .norm162index,vNormal);
-
-				std::swap(groupData.vNormals[iOutIndex].z,groupData.vNormals[iOutIndex].y);
+				vNormal.y *= -1.0f;
 			}
 			// validate and process the first uv coordinate set
 			// *************************************************************
@@ -1063,9 +1103,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(
 				}
 				// assign the material index, but only if it is existing
 				if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX)
-				{
 					groupData.pcFaces[iTriangle].iMatIndex[0] = pcGroupTris->skinsets[0].material;
-				}
 			}
 			// validate and process the second uv coordinate set
 			// *************************************************************
@@ -1090,14 +1128,11 @@ void MDLImporter::ReadFaces_3DGS_MDL7(
 					// coordinate set ... wastes memory and loading time
 					if (0 != iIndex && (u != groupData.vTextureCoords1[ iOutIndex ].x ||
 						v != groupData.vTextureCoords1[ iOutIndex ].y ) )
-					{
 						groupData.bNeed2UV = true;
-					}
+				
 					// if the material differs, we need a second skin, too
 					if (pcGroupTris->skinsets[ 1 ].material != pcGroupTris->skinsets[ 0 ].material)
-					{
 						groupData.bNeed2UV = true;
-					}
 				}
 				// assign the material index
 				groupData.pcFaces[ iTriangle ].iMatIndex[ 1 ] = pcGroupTris->skinsets[ 1 ].material;
@@ -1144,9 +1179,7 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf
 		// our output frame?
 		if (configFrameID == iFrame)
 		{
-			const MDL::Vertex_MDL7* pcFrameVertices = (const MDL::Vertex_MDL7*)
-				(szCurrent + pcHeader->framevertex_stc_size);
-
+			const MDL::Vertex_MDL7* pcFrameVertices = (const MDL::Vertex_MDL7*)(szCurrent+pcHeader->frame_stc_size);
 			for (unsigned int qq = 0; qq < frame.pcFrame->vertices_count;++qq)
 			{
 				// I assume this are simple replacements for normal
@@ -1157,37 +1190,33 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf
 
 				if (iIndex >= groupInfo.pcGroup->numverts)
 				{
-					DefaultLogger::get()->warn("Invalid vertex index in frame vertex section. "
-						"Skipping this frame vertex");
+					DefaultLogger::get()->warn("Invalid vertex index in frame vertex section");
 					continue;
 				}
 
 				aiVector3D vPosition,vNormal;
 					
 				vPosition.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .x;
-				vPosition.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .y;
-				vPosition.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .z;
+				vPosition.y = -1.0f*_AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .y;
+				vPosition.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .z;
 
 				// now read the normal vector
 				if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size)
 				{
 					// read the full normal vector
 					vNormal.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[0];
-					vNormal.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[1];
-					vNormal.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[2];
+					vNormal.y = -1.0f* _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[1];
+					vNormal.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[2];
 				}
 				else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size)
 				{
 					// read the normal vector from Quake2's smart table
 					MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,
 						pcHeader->framevertex_stc_size) .norm162index,vNormal);
-
-					std::swap(vNormal.z,vNormal.y);
+					vNormal.y *= -1.0f;
 				}
 
 				// FIXME: O(n^2) at the moment ...
-				// shouldn't be too worse, frame vertices aren't required more
-				// than once a century ...
 				const MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris;
 				unsigned int iOutIndex = 0;
 				for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle)
@@ -1204,16 +1233,13 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf
 						}
 					}
 					// get the next triangle in the list
-					pcGroupTris = (const MDL::Triangle_MDL7*)((const char*)pcGroupTris + 
-						pcHeader->triangle_stc_size);
+					pcGroupTris = (const MDL::Triangle_MDL7*)((const char*)
+						pcGroupTris + pcHeader->triangle_stc_size);
 				}
 			}
 		}
 		// parse bone trafo matrix keys (only if there are bones ...)
-		if (shared.apcOutBones)
-		{
-			this->ParseBoneTrafoKeys_3DGS_MDL7(groupInfo,frame,shared);
-		}
+		if (shared.apcOutBones)this->ParseBoneTrafoKeys_3DGS_MDL7(groupInfo,frame,shared);
 		szCurrent += iAdd;
 	}
 	*szCurrentOut = szCurrent;
@@ -1371,7 +1397,6 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
 	// load all bones (they are shared by all groups, so
 	// we'll need to add them to all groups/meshes later)
 	// apcBonesOut is a list of all bones or NULL if they could not been loaded 
-	// TODO (aramis): Make apcBonesOut an MDL::IntBone_MDL7*
 	szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size;
 	sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
 
@@ -1493,19 +1518,13 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
 				if (!splittedGroupData.aiSplit[qq]->empty())
 					sharedData.abNeedMaterials[qq] = true;
 			}
-
-			// now generate output meshes
-			this->GenerateOutputMeshes_3DGS_MDL7(groupData,
-				splittedGroupData);
 		}
 		else DefaultLogger::get()->warn("[3DGS MDL7] Mesh group consists of 0 "
 			"vertices or faces. It will be skipped.");
 
-		// process all frames
-		if(!ProcessFrames_3DGS_MDL7(groupInfo,groupData, sharedData,szCurrent,&szCurrent))
-		{
-			break;
-		}
+		// process all frames and generate output meshes
+		this->ProcessFrames_3DGS_MDL7(groupInfo,groupData, sharedData,szCurrent,&szCurrent);
+		this->GenerateOutputMeshes_3DGS_MDL7(groupData,splittedGroupData);
 	}
 
 	// generate a nodegraph and subnodes for each group
@@ -1545,16 +1564,9 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
 
 			// setup the name of the node
 			char* const szBuffer = &aszGroupNameBuffer[i*AI_MDL7_MAX_GROUPNAMESIZE];
-			if ('\0' == *szBuffer)
-			{
-#if _MSC_VER >= 1400
-				::sprintf_s(szBuffer,AI_MDL7_MAX_GROUPNAMESIZE,"Group_%i",p);
-#else
-				::sprintf(szBuffer,"Group_%i",p);
-#endif
-			}
+			if ('\0' == *szBuffer)pcNode->mName.length = ::sprintf(szBuffer,"Group_%i",p);
+			else pcNode->mName.length = ::strlen(szBuffer);
 			::strcpy(pcNode->mName.data,szBuffer);
-			pcNode->mName.length = ::strlen(szBuffer);
 			++p;
 		}
 	}
@@ -1566,10 +1578,9 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
 		this->pScene->mRootNode = pcOldRoot->mChildren[0];
 		pcOldRoot->mChildren[0] = NULL;
 		delete pcOldRoot;
-
 		this->pScene->mRootNode->mParent = NULL;
 	}
-	else this->pScene->mRootNode->mName.Set("mesh_root");
+	else this->pScene->mRootNode->mName.Set("<mesh_root>");
 
 	delete[] avOutList;
 	delete[] aszGroupNameBuffer; 
@@ -1578,8 +1589,6 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
 
 	// build a final material list. 
 	this->CopyMaterials_3DGS_MDL7(sharedData);
-
-	// handle materials that are just referencing another material correctly
 	this->HandleMaterialReferences_3DGS_MDL7();
 
 	// generate output bone animations and add all bones to the scenegraph
@@ -1590,7 +1599,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
 		aiNode* const pc = this->pScene->mRootNode->mChildren[
 			this->pScene->mRootNode->mNumChildren-1] = new aiNode();
 
-		pc->mName.Set("skeleton_root");
+		pc->mName.Set("<skeleton_root>");
 
 		// add bones to the nodegraph
 		this->AddBonesToNodeGraph_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **)
@@ -1604,64 +1613,15 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
 // ------------------------------------------------------------------------------------------------
 void MDLImporter::CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared)
 {
-	unsigned int iNewNumMaterials = 0;
-	unsigned int p = 0;
-	for (;p < shared.pcMats.size();++p)
-		if (shared.abNeedMaterials[p])++iNewNumMaterials;
-
-	this->pScene->mMaterials = new aiMaterial*[iNewNumMaterials];
-	if ((unsigned int)shared.pcMats.size() == iNewNumMaterials)
-	{
-		this->pScene->mNumMaterials = (unsigned int)shared.pcMats.size();
-		for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i)
-			this->pScene->mMaterials[i] = shared.pcMats[i];
-	}
-	else
-	{
-		p = 0;
-		const unsigned int iMSB = 0x1u << (sizeof (unsigned int)*8-1);
-		for (unsigned int i = 0; i < (unsigned int)shared.pcMats.size();++i)
-		{
-			if (!shared.abNeedMaterials[i])
-			{
-				// destruction is done by the destructor of sh
-				delete shared.pcMats[i];
-				AI_DEBUG_INVALIDATE_PTR(shared.pcMats[i]);
-				continue;
-			}
-			this->pScene->mMaterials[p] = shared.pcMats[i];
-
-			if (p != i)
-			{
-				// replace the material index and MSB in all material
-				// indices that have been replaced to make sure they won't be
-				// replaced again (this won't work if there are more than
-				// 2^31 materials in the model - but this shouldn't care :-)).
-				for (unsigned int qq = 0; qq < this->pScene->mNumMeshes;++qq)
-				{
-					aiMesh* const pcMesh = this->pScene->mMeshes[qq];
-					if (i == pcMesh->mMaterialIndex)
-					{
-						pcMesh->mMaterialIndex = p | iMSB;
-					}
-				}
-			}
-			++p;
-		}
-		this->pScene->mNumMaterials = iNewNumMaterials;
-
-		// Remove the MSB from all material indices
-		for (unsigned int qq = 0; qq < this->pScene->mNumMeshes;++qq)
-		{
-			this->pScene->mMeshes[qq]->mMaterialIndex &= ~iMSB;
-		}
-	}
+	this->pScene->mNumMaterials = (unsigned int)shared.pcMats.size();
+	this->pScene->mMaterials = new aiMaterial*[this->pScene->mNumMaterials];
+	for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i)
+		this->pScene->mMaterials[i] = shared.pcMats[i];
 }
 // ------------------------------------------------------------------------------------------------
 void MDLImporter::HandleMaterialReferences_3DGS_MDL7()
 {
 	// search for referrer materials
-	// (there is no test file but Conitec's docs say it is supported ... :cry: )
 	for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i)
 	{
 		int iIndex = 0;
@@ -1672,9 +1632,7 @@ void MDLImporter::HandleMaterialReferences_3DGS_MDL7()
 			{
 				aiMesh* const pcMesh = this->pScene->mMeshes[a];
 				if (i == pcMesh->mMaterialIndex)
-				{
 					pcMesh->mMaterialIndex = iIndex;
-				}
 			}
 			// collapse the rest of the array
 			delete this->pScene->mMaterials[i];
@@ -1731,8 +1689,7 @@ void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7(
 		else
 		{
 			DefaultLogger::get()->warn("Found animation keyframes "
-				"in a group that is not the first. They will be igored, "
-				"the format specification says this should not occur");
+				"in a group that is not the first. They will be igored");
 		}
 	}
 }
@@ -1802,7 +1759,7 @@ void MDLImporter::BuildOutputAnims_3DGS_MDL7(
 				aiBoneAnim* const pcBoneAnim = pcAnim->mBones[iCnt++] = new aiBoneAnim();
 				pcBoneAnim->mBoneName = aiString( intBone->mName );
 
-				// allocate enough storahe for all keys
+				// allocate enough storage for all keys
 				pcBoneAnim->mNumPositionKeys = (unsigned int)intBone->pkeyPositions.size();
 				pcBoneAnim->mNumScalingKeys  = (unsigned int)intBone->pkeyPositions.size();
 				pcBoneAnim->mNumRotationKeys = (unsigned int)intBone->pkeyPositions.size();

+ 8 - 0
code/MDLLoader.h

@@ -87,6 +87,14 @@ public:
 	* See BaseImporter::CanRead() for details.	*/
 	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
 
+
+	// -------------------------------------------------------------------
+	/** Called prior to ReadFile().
+	* The function is a request to the importer to update its configuration
+	* basing on the Importer's configuration property list.
+	*/
+	void SetupProperties(const Importer* pImp);
+
 protected:
 
 

+ 10 - 0
code/RemoveRedundantMaterials.cpp

@@ -88,6 +88,10 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
 		unsigned int* aiMappingTable = new unsigned int[pScene->mNumMaterials];
 		unsigned int iNewNum = 0;
 
+		std::vector<bool> abReferenced(pScene->mNumMaterials,false);
+		for (unsigned int i = 0;i < pScene->mNumMeshes;++i)
+			abReferenced[pScene->mMeshes[i]->mMaterialIndex] = true;
+
 		// iterate through all materials and calculate a hash for them
 		// store all hashes in a list and so a quick search whether
 		// we do already have a specific hash. This allows us to
@@ -96,6 +100,9 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
 		aiHashes = new uint32_t[pScene->mNumMaterials];
 		for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
 		{
+			// if the material is not referenced ... remove it
+			if (!abReferenced[i])continue;
+
 			uint32_t me = aiHashes[i] = ((MaterialHelper*)pScene->mMaterials[i])->ComputeHash();
 			for (unsigned int a = 0; a < i;++a)
 			{
@@ -120,6 +127,9 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
 			::memset(ppcMaterials,0,sizeof(void*)*iNewNum); 
 			for (unsigned int p = 0; p < pScene->mNumMaterials;++p)
 			{
+				// if the material is not referenced ... remove it
+				if (!abReferenced[p])continue;
+
 				// generate new names for all modified materials
 				const unsigned int idx = aiMappingTable[p]; 
 				if (ppcMaterials[idx]) 

+ 11 - 22
code/SplitLargeMeshes.cpp

@@ -101,12 +101,8 @@ void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene)
 // Setup properties
 void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp)
 {
-        // get the current value of the split property
-	if(0xcdcdcdcd == (this->LIMIT = pImp->GetProperty(
-		AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,0xcdcdcdcd)))
-	{
-		this->LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES;
-	}
+    // get the current value of the split property
+	this->LIMIT = pImp->GetProperty(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
 }
 // ------------------------------------------------------------------------------------------------
 // Update a node after some meshes have been split
@@ -291,15 +287,11 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
 
 					// copy positions
 					if (pMesh->mVertices != NULL)
-					{
 						pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex];
-					}
 
 					// copy normals
 					if (pMesh->HasNormals())
-					{
 						pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex];
-					}
 
 					// copy tangents/bitangents
 					if (pMesh->HasTangentsAndBitangents())
@@ -312,17 +304,13 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
 					for (unsigned int c = 0;  c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
 					{
 						if (pMesh->HasTextureCoords( c))
-						{
 							pcMesh->mTextureCoords[c][iIndexOut] = 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][iIndexOut] = pMesh->mColors[c][iIndex];
-						}
 					}
 				}
 			}
@@ -386,12 +374,7 @@ void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene)
 // Setup properties
 void SplitLargeMeshesProcess_Vertex::SetupProperties( const Importer* pImp)
 {
-        // get the current value of the split property
-	if(0xcdcdcdcd == (this->LIMIT = pImp->GetProperty(
-		AI_CONFIG_PP_SLM_VERTEX_LIMIT,0xcdcdcdcd)))
-	{
-		this->LIMIT = AI_SLM_DEFAULT_MAX_VERTICES;
-	}
+	this->LIMIT = pImp->GetProperty(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
 }
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
@@ -455,9 +438,15 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
 			}
 
 			// clear the temporary helper array
-			if (0 != iBase)
+			if (iBase)
 			{
-				memset(&avWasCopied[0],0xFF,pMesh->mNumVertices * sizeof(unsigned int));
+				// we can't use memset here we unsigned int needn' be 32 bits
+				for (std::vector<unsigned int>::iterator
+					iter = avWasCopied.begin(),end = avWasCopied.end();
+					iter != end;++iter)
+				{
+					(*iter) = 0xffffffff;
+				}
 			}
 
 			// output vectors

+ 6 - 6
code/ValidateDataStructure.cpp

@@ -710,10 +710,10 @@ __break_out:
 			}
 			if (pBoneAnim->mPositionKeys[i].mTime <= dLast)
 			{
-				this->ReportError("aiBoneAnim::mPositionKeys[%i].mTime (%.5f) is larger "
+				this->ReportWarning("aiBoneAnim::mPositionKeys[%i].mTime (%.5f) is smaller "
 					"than aiAnimation::mPositionKeys[%i] (which is %.5f)",i,
 					(float)pBoneAnim->mPositionKeys[i].mTime,
-					i, (float)dLast);
+					i-1, (float)dLast);
 			}
 			dLast = pBoneAnim->mPositionKeys[i].mTime;
 		}
@@ -738,10 +738,10 @@ __break_out:
 			}
 			if (pBoneAnim->mRotationKeys[i].mTime <= dLast)
 			{
-				this->ReportError("aiBoneAnim::mRotationKeys[%i].mTime (%.5f) is larger "
+				this->ReportWarning("aiBoneAnim::mRotationKeys[%i].mTime (%.5f) is smaller "
 					"than aiAnimation::mRotationKeys[%i] (which is %.5f)",i,
 					(float)pBoneAnim->mRotationKeys[i].mTime,
-					i, (float)dLast);
+					i-1, (float)dLast);
 			}
 			dLast = pBoneAnim->mRotationKeys[i].mTime;
 		}
@@ -766,10 +766,10 @@ __break_out:
 			}
 			if (pBoneAnim->mScalingKeys[i].mTime <= dLast)
 			{
-				this->ReportError("aiBoneAnim::mScalingKeys[%i].mTime (%.5f) is larger "
+				this->ReportWarning("aiBoneAnim::mScalingKeys[%i].mTime (%.5f) is smaller "
 					"than aiAnimation::mScalingKeys[%i] (which is %.5f)",i,
 					(float)pBoneAnim->mScalingKeys[i].mTime,
-					i, (float)dLast);
+					i-1, (float)dLast);
 			}
 			dLast = pBoneAnim->mScalingKeys[i].mTime;
 		}

+ 21 - 0
include/aiConfig.h

@@ -105,6 +105,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #define AI_CONFIG_IMPORT_3DS_IGNORE_PIVOT	"imp.3ds.nopivot"
 
+// ---------------------------------------------------------------------------
+/** \brief Specifies the maximum angle that may be between two vertex tangents
+ *         that their tangents and bitangents are smoothed.
+ *
+ * This applies to the CalcTangentSpace-Step. The angle is specified
+ * in degrees * 1000, so 180000 is PI. The default value is
+ * 45 degrees. The maximum value is 180000.
+ */
+#define AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE "pp.ct.max_smoothing"
+
+// ---------------------------------------------------------------------------
+/** \brief Specifies the maximum angle that may be between two face normals
+ *         at the same vertex position that their are smoothed.
+ *
+ * This applies to the GenSmoothNormals-Step. The angle is specified
+ * in degrees * 1000, so 180000 is PI. The default value is
+ * 180 degrees (all vertex normals are smoothed). The maximum value is 180000
+ * \note This can be manually overriden by loaders via #aiMesh::mMaxSmoothingAngle;
+ */
+#define AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE "pp.gsn.max_smoothing"
+
 
 #define AI_CONFIG_PP_OG_MAX_DEPTH			"pp.og.max_depth"
 #define AI_CONFIG_PP_OG_MIN_TRIS_PER_NODE	"pp.og.min_tris"

+ 6 - 3
include/aiMesh.h

@@ -248,6 +248,8 @@ struct aiBone
 
 #endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS
 
+#define AI_MESH_SMOOTHING_ANGLE_NOT_SET (10e10f)
+
 // ---------------------------------------------------------------------------
 /** A mesh represents a geometry or model with a single material. 
 *
@@ -358,8 +360,9 @@ struct aiMesh
 	 *  If the angle between two vertex normals is larger,
 	 *  the vertex normals should not be smoothed. The GenVertexNormals-Step
 	 *  takes care of this value. The angle is specified in radians.
-	 *  It is 2PI if the source file didn't contain any additional 
-	 *  information related to the calculation of vertex normals.
+	 *  It is set to AI_MESH_SMOOTHING_ANGLE_NOT_SET if the source file didn't
+	 *  contain any additional information related to the calculation of
+	 *  vertex normals.
 	 */
 	float mMaxSmoothingAngle;
 
@@ -381,7 +384,7 @@ struct aiMesh
 			mColors[a] = NULL;
 		mNumBones = 0; mBones = NULL;
 		mMaterialIndex = 0;
-		mMaxSmoothingAngle = (float)AI_MATH_TWO_PI;
+		mMaxSmoothingAngle = AI_MESH_SMOOTHING_ANGLE_NOT_SET;
 	}
 
 	//! Deletes all storage allocated for the mesh

BIN
tools/assimp_view/assimp_view.aps


+ 13 - 11
tools/assimp_view/assimp_view.rc

@@ -38,21 +38,22 @@ IDI_SMALL               ICON                    "small.ico"
 // Dialog
 //
 
-IDD_ABOUTBOX DIALOGEX 22, 17, 283, 170
+IDD_ABOUTBOX DIALOGEX 22, 17, 283, 169
 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_CAPTION | WS_SYSMENU
-CAPTION "About ASSIMP"
+CAPTION "About Open Asset Import Library"
 FONT 10, "MS Shell Dlg", 400, 0, 0x0
 BEGIN
-    LTEXT           "ASSIMP is the free, OpenSource ASSet IMPort Library",IDC_STATIC,42,12,204,12
-    LTEXT           "Developed by members of the german game development community www.zfx.info",IDC_STATIC,42,30,204,24
-    LTEXT           "Thomas Schulze \t\taka <Schrompf> ",IDC_STATIC,42,66,192,8
-    LTEXT           "Kim Kulling \t\t\taka <Sir Kimmi> ",IDC_STATIC,42,78,186,8
-    LTEXT           "Rainer Schmidt \t\t\taka <Guru>",IDC_STATIC,42,90,180,8
-    LTEXT           "Alexander Gessler\t\taka <Aramis>",IDC_STATIC,42,102,186,8
+    LTEXT           "Open Asset Import Library (Assimp)",IDC_STATIC,77,13,121,12
+    LTEXT           "A free C/C++ library for game && graphics developers. Developed by members of the german game development community www.zfx.info",IDC_STATIC,47,26,204,24
+    LTEXT           "Thomas Schulze \t\taka <Schrompf> ",IDC_STATIC,55,80,192,8
+    LTEXT           "Kim Kulling \t\t\taka <Kimmi> ",IDC_STATIC,55,92,186,8
+    LTEXT           "Rainer Schmidt \t\t\taka <Guru>",IDC_STATIC,55,104,180,8
+    LTEXT           "Alexander Gessler\t\taka <Aramis>",IDC_STATIC,55,68,186,8
     CONTROL         "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,60,282,1
-    LTEXT           "http://zfxce.svn.sourceforge.net/viewvc/zfxce/trunk/ASSIMP",IDC_STATIC,42,120,198,8
-    DEFPUSHBUTTON   "Love this library",IDOK,199,148,67,14
-    CONTROL         "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,138,281,1
+    LTEXT           "assimp.sourceforge.net",IDC_STATIC,7,137,78,8
+    DEFPUSHBUTTON   "Love this library",IDOK,200,128,67,14
+    CONTROL         "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,148,283,1
+    CONTROL         130,IDC_STATIC,"Static",SS_BITMAP,0,149,514,20
 END
 
 IDD_DIALOGMAIN DIALOGEX 0, 0, 594, 384
@@ -233,6 +234,7 @@ GUIDELINES DESIGNINFO
 BEGIN
     IDD_ABOUTBOX, DIALOG
     BEGIN
+        TOPMARGIN, 1
         BOTTOMMARGIN, 158
     END
 

BIN
tools/assimp_view/banner.bmp


BIN
tools/assimp_view/banner_pure.bmp


+ 40 - 4
workspaces/vc8/assimp.vcproj

@@ -582,6 +582,10 @@
 				RelativePath="..\..\include\aiAssert.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\include\aiConfig.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\include\aiDefines.h"
 				>
@@ -674,6 +678,10 @@
 				RelativePath="..\..\include\LogStream.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\include\NullLogger.h"
+				>
+			</File>
 			<Filter
 				Name="Compiler"
 				>
@@ -965,10 +973,6 @@
 			<Filter
 				Name="Logger"
 				>
-				<File
-					RelativePath="..\..\code\DefaultLogger.h"
-					>
-				</File>
 				<File
 					RelativePath="..\..\code\FileLogStream.h"
 					>
@@ -1030,6 +1034,30 @@
 					>
 				</File>
 			</Filter>
+			<Filter
+				Name="MDC"
+				>
+				<File
+					RelativePath="..\..\code\MDCFileData.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\code\MDCLoader.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\code\MDCNormalTable.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="MDR"
+				>
+				<File
+					RelativePath="..\..\code\MDRFileData.h"
+					>
+				</File>
+			</Filter>
 		</Filter>
 		<Filter
 			Name="sources"
@@ -1302,6 +1330,14 @@
 					>
 				</File>
 			</Filter>
+			<Filter
+				Name="MDC"
+				>
+				<File
+					RelativePath="..\..\code\MDCLoader.cpp"
+					>
+				</File>
+			</Filter>
 		</Filter>
 		<Filter
 			Name="doc"