Selaa lähdekoodia

ase/ask loader is quite stable now, loads most models correctly
added pretransformvertices postprocess step
bugfixes in the 3ds material system. transparency is now displayed correctly
Node view in the viewer display the local transformation matrix now
Fixed wrong directory name. "unused" renamed to "extra"
---> all is WIP ...


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

aramis_acg 17 vuotta sitten
vanhempi
commit
69ed883ae0
38 muutettua tiedostoa jossa 1282 lisäystä ja 414 poistoa
  1. 5 3
      code/3DSLoader.cpp
  2. 164 91
      code/ASELoader.cpp
  3. 18 2
      code/ASELoader.h
  4. 120 132
      code/ASEParser.cpp
  5. 4 1
      code/ASEParser.h
  6. 36 4
      code/ConvertToLHProcess.cpp
  7. 4 0
      code/ConvertToLHProcess.h
  8. 161 0
      code/HalfLifeFileData.h
  9. 2 0
      code/Importer.cpp
  10. 15 86
      code/MDLFileData.h
  11. 1 0
      code/MDLLoader.h
  12. 378 0
      code/PretransformVertices.cpp
  13. 88 0
      code/PretransformVertices.h
  14. 0 0
      code/extra/MakeVerboseFormat.cpp
  15. 0 0
      code/extra/MakeVerboseFormat.h
  16. 44 2
      doc/dox.h
  17. 17 1
      include/aiPostProcess.h
  18. 1 1
      include/aiTexture.h
  19. 1 1
      port/jAssimp/src/assimp/Animation.java
  20. 22 15
      port/jAssimp/src/assimp/CompressedTexture.java
  21. 3 0
      port/jAssimp/src/assimp/DefaultLogger.java
  22. 4 2
      port/jAssimp/src/assimp/Importer.java
  23. 1 0
      port/jAssimp/src/assimp/LogStream.java
  24. 19 13
      port/jAssimp/src/assimp/Logger.java
  25. 5 1
      port/jAssimp/src/assimp/Mappable.java
  26. 3 3
      port/jAssimp/src/assimp/Mesh.java
  27. 2 2
      port/jAssimp/src/assimp/NativeError.java
  28. 21 6
      port/jAssimp/src/assimp/PostProcessStep.java
  29. 16 16
      port/jAssimp/src/assimp/Texture.java
  30. 4 5
      port/jAssimp/src/assimp/test/DumpToFile.java
  31. 84 8
      tools/assimp_view/Display.cpp
  32. 12 0
      tools/assimp_view/MessageProc.cpp
  33. 1 1
      tools/assimp_view/Normals.cpp
  34. BIN
      tools/assimp_view/assimp_view.aps
  35. 1 8
      tools/assimp_view/assimp_view.cpp
  36. 8 7
      tools/assimp_view/assimp_view.rc
  37. 3 1
      tools/assimp_view/resource.h
  38. 14 2
      workspaces/vc8/assimp.vcproj

+ 5 - 3
code/3DSLoader.cpp

@@ -1091,9 +1091,9 @@ void Dot3DSImporter::ParseMaterialChunk(int* piRemaining)
 		pcf = &this->mScene->mMaterials.back().mTransparency;
 		*pcf = this->ParsePercentageChunk();
 		// NOTE: transparency, not opacity
-		*pcf = 1.0f - *pcf;
 		if (is_qnan(*pcf))
-			*pcf = 0.0f;
+			*pcf = 1.0f;
+		else *pcf = 1.0f - *pcf * (float)0xFFFF / 100.0f;
 		break;
 
 	case Dot3DSFile::CHUNK_MAT_SHADING:
@@ -1121,10 +1121,12 @@ void Dot3DSImporter::ParseMaterialChunk(int* piRemaining)
 		break;
 
 	case Dot3DSFile::CHUNK_MAT_SELF_ILPCT:
+		// TODO: need to multiply with emissive base color?
 		pcf = &this->mScene->mMaterials.back().sTexEmissive.mTextureBlend;
 		*pcf = this->ParsePercentageChunk();
 		if (is_qnan(*pcf))
-			*pcf = 1.0f;
+			*pcf = 0.0f;
+		else *pcf = *pcf * (float)0xFFFF / 100.0f;
 		break;
 
 	// parse texture chunks

+ 164 - 91
code/ASELoader.cpp

@@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ASELoader.h"
 #include "3DSSpatialSort.h"
 #include "MaterialSystem.h"
+#include "fast_atof.h"
 
 #include "../include/IOStream.h"
 #include "../include/IOSystem.h"
@@ -126,11 +127,23 @@ void ASEImporter::InternReadFile(
 	this->mParser = new ASE::Parser((const char*)this->mBuffer);
 	this->mParser->Parse();
 
+	// the .ask file format contains normally three LODs of
+	// a single object. Named <name>n, where n = 1 designates
+	// the highest level of detail.
+	if (this->mIsAsk)
+	{
+		this->AskFilterLOD(this->mParser->m_vMeshes);
+	}
+
 	// process all meshes
+	std::vector<aiMesh*> avOutMeshes;
+	avOutMeshes.reserve(this->mParser->m_vMeshes.size()*2);
 	for (std::vector<ASE::Mesh>::iterator
 		i =  this->mParser->m_vMeshes.begin();
 		i != this->mParser->m_vMeshes.end();++i)
 	{
+		if ((*i).bSkip)continue;
+
 		// transform all vertices into worldspace
 		// world2obj transform is specified in the
 		// transformation matrix of a scenegraph node
@@ -144,8 +157,15 @@ void ASEImporter::InternReadFile(
 		this->GenerateNormals(*i);
 
 		// convert all meshes to aiMesh objects
-		this->ConvertMeshes(*i,pScene);
+		this->ConvertMeshes(*i,avOutMeshes);
 	}
+	
+	// now build the output mesh list
+	pScene->mNumMeshes = avOutMeshes.size();
+	pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+		pScene->mMeshes[i] = avOutMeshes[i];
+
 	// buil final material indices (remove submaterials and make the final list)
 	this->BuildMaterialIndices(pScene);
 
@@ -158,87 +178,95 @@ void ASEImporter::InternReadFile(
 	return;
 }
 // ------------------------------------------------------------------------------------------------
-void ASEImporter::BuildNodes(aiScene* pcScene)
+void ASEImporter::AddNodes(aiScene* pcScene,aiNode* pcParent,
+	const char* szName)
 {
-	ai_assert(NULL != pcScene);
-
-	pcScene->mRootNode = new aiNode();
-	pcScene->mRootNode->mNumMeshes = 0;
-	pcScene->mRootNode->mMeshes = 0;
-
 	ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
-	std::vector<std::pair<aiMatrix4x4,std::list<unsigned int> > > stack;
-	stack.reserve(pcScene->mNumMeshes);
+	std::vector<aiNode*> apcNodes;
 	for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
 	{
-		// get the transformation matrix of the node
-		aiMatrix4x4* pmTransform = (aiMatrix4x4*)pcScene->mMeshes[i]->mColors[2];
-		
-		// search for an identical matrix in our list
-		for (std::vector<std::pair<aiMatrix4x4,std::list<unsigned int> > >::iterator
-			a =  stack.begin();
-			a != stack.end();++a)
+		// get the name of the mesh ([0] = name, [1] = parent)
+		std::string* szMyName = (std::string*)pcScene->mMeshes[i]->mColors[1];
+		if (!szMyName)
 		{
-			if ((*a).first == *pmTransform)
-			{
-				(*a).second.push_back(i);
-				pmTransform->a1 = std::numeric_limits<float>::quiet_NaN();
-				break;
-			}
+			continue;
 		}
-		if (is_not_qnan(pmTransform->a1))
+		if (szName)
 		{
-			// add a new entry ...
-			stack.push_back(std::pair<aiMatrix4x4,std::list<unsigned int> >(
-				*pmTransform,std::list<unsigned int>()));
-			stack.back().second.push_back(i);
-		}
-		// delete the matrix
+			if(0 != ASSIMP_stricmp ( szName, szMyName[1].c_str() ))
+				continue;
+		} 
+		else if ('\0' != szMyName[1].c_str()[0])continue;
+
+		apcNodes.push_back(new aiNode());
+		aiNode* node = apcNodes.back();
+
+		// get the transformation matrix of the mesh
+		aiMatrix4x4* pmTransform = (aiMatrix4x4*)pcScene->mMeshes[i]->mColors[2];
+
+		node->mName.Set(szMyName[0]);
+		node->mNumMeshes = 1;
+		node->mMeshes = new unsigned int[1];
+		node->mMeshes[0] = i;
+		node->mParent = pcParent;
+		node->mTransformation = *pmTransform;
+		
+		// delete the matrix (a mesh is always the child of ONE node, so this is safe)
 		delete pmTransform;
 		pcScene->mMeshes[i]->mColors[2] = NULL;
+
+		delete[] szMyName;
+		pcScene->mMeshes[i]->mColors[1] = NULL;
+
+		// add sub nodes
+		this->AddNodes(pcScene,node,node->mName.data);
 	}
 
 	// allocate enough space for the child nodes
-	pcScene->mRootNode->mNumChildren = stack.size();
-	pcScene->mRootNode->mChildren = new aiNode*[stack.size()];
+	pcParent->mNumChildren = apcNodes.size();
+	pcParent->mChildren = new aiNode*[apcNodes.size()];
 
 	// now build all nodes
-	for (std::vector<std::pair<aiMatrix4x4,std::list<unsigned int> > >::iterator
-		a =  stack.begin();
-		a != stack.end();++a)
-	{
-		aiNode* pcNode = new aiNode();
-		pcNode->mNumMeshes = (*a).second.size();
-		pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
-		for (std::list<unsigned int>::const_iterator
-			i =  (*a).second.begin();
-			i != (*a).second.end();++i)
-		{
-			*pcNode->mMeshes++ = *i;
-		}
-		pcNode->mMeshes -= pcNode->mNumMeshes;
-		pcNode->mTransformation = (*a).first;
-		*pcScene->mRootNode->mChildren++ = pcNode;
+	for (unsigned int p = 0; p < apcNodes.size();++p)
+	{
+		pcParent->mChildren[p] = apcNodes[p];
 	}
-	pcScene->mRootNode->mChildren -= stack.size();
 	return;
 }
 // ------------------------------------------------------------------------------------------------
-void ASEImporter::TransformVertices(ASE::Mesh& mesh)
+void ASEImporter::BuildNodes(aiScene* pcScene)
 {
-	// the matrix data is stored in column-major format,
-	// but we need row major
-	mesh.mTransform.Transpose();
+	ai_assert(NULL != pcScene);
 
-	aiMatrix4x4 m = mesh.mTransform;
-	m.Inverse();
+	// allocate the root node
+	pcScene->mRootNode = new aiNode();
+	pcScene->mRootNode->mNumMeshes = 0;
+	pcScene->mRootNode->mMeshes = 0;
+	pcScene->mRootNode->mName.Set("<root>");
 
-	for (std::vector<aiVector3D>::iterator
-		i =  mesh.mPositions.begin();
-		i != mesh.mPositions.end();++i)
+	// add all nodes
+	this->AddNodes(pcScene,pcScene->mRootNode,NULL);
+
+	// if there is only one subnode, set it as root node
+	if (1 == pcScene->mRootNode->mNumChildren)
+	{
+		aiNode* pc = pcScene->mRootNode;
+		pcScene->mRootNode = pcScene->mRootNode->mChildren[0];
+		pcScene->mRootNode->mParent = NULL;
+		delete pc;
+	}
+	else if (0 == pcScene->mRootNode->mNumChildren)
 	{
-		(*i) = m * (*i);
+		throw new ImportErrorException("No nodes loaded. The ASE/ASK file is either empty or corrupt");
 	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void ASEImporter::TransformVertices(ASE::Mesh& mesh)
+{
+	// the matrix data is stored in column-major format,
+	// but we need row major
+	mesh.mTransform.Transpose();
 }
 // ------------------------------------------------------------------------------------------------
 void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
@@ -315,10 +343,11 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
 				//  will fix that again ...)
 				mBoneVertices[iCurrent] =  mesh.mBoneVertices[(*i).mIndices[n]];
 			}
-
-			// assign a new valid index to the face
-			(*i).mIndices[n] = iCurrent;
 		}
+		// we need to flip the order of the indices
+		(*i).mIndices[0] = iCurrent-1;
+		(*i).mIndices[1] = iCurrent-2;
+		(*i).mIndices[2] = iCurrent-3;
 	}
 
 	// replace the old arrays
@@ -373,7 +402,8 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
 	}
 	// if there is no shininess, we can disable phong lighting
 	else if (Dot3DS::Dot3DSFile::Metal == mat.mShading ||
-		Dot3DS::Dot3DSFile::Phong == mat.mShading)
+		Dot3DS::Dot3DSFile::Phong == mat.mShading ||
+		Dot3DS::Dot3DSFile::Blinn == mat.mShading)
 	{
 		mat.mShading = Dot3DS::Dot3DSFile::Gouraud;
 	}
@@ -390,6 +420,8 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
 			eShading = aiShadingMode_Flat; break;
 		case Dot3DS::Dot3DSFile::Phong :
 			eShading = aiShadingMode_Phong; break;
+		case Dot3DS::Dot3DSFile::Blinn :
+			eShading = aiShadingMode_Blinn; break;
 
 		// I don't know what "Wire" shading should be,
 		// assume it is simple lambertian diffuse (L dot N) shading
@@ -490,10 +522,8 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
 	return;
 }
 // ------------------------------------------------------------------------------------------------
-void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
+void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMeshes)
 {
-	ai_assert(NULL != pcScene);
-
 	// validate the material index of the mesh
 	if (mesh.iMaterialIndex >= this->mParser->m_vMaterials.size())
 	{
@@ -501,8 +531,6 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
 		LOGOUT_WARN("Material index is out of range");
 	}
 
-	// List of all output meshes
-	std::vector<aiMesh*> avOutMeshes;
 
 	// if the material the mesh is assigned to is consisting of submeshes
 	// we'll need to split it ... Quak.
@@ -544,8 +572,16 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
 
 				// store the real index here ... color channel 3
 				p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
+
 				// store the real transformation matrix in color channel 2
 				p_pcOut->mColors[2] = (aiColor4D*) new aiMatrix4x4(mesh.mTransform);
+
+				// store the name of the mesh and the
+				// name of its parent in color channel 1
+				p_pcOut->mColors[1] = (aiColor4D*) new std::string[2];
+				((std::string*)p_pcOut->mColors[1])[0] = mesh.mName;
+				((std::string*)p_pcOut->mColors[1])[1] = mesh.mParent;
+
 				avOutMeshes.push_back(p_pcOut);
 
 				// convert vertices
@@ -647,24 +683,24 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
 						if (!avOutputBones[mrspock].empty())p_pcOut->mNumBones++;
 
 					p_pcOut->mBones = new aiBone* [ p_pcOut->mNumBones ];
-					aiBone** pcBone = &p_pcOut->mBones[0];
+					aiBone** pcBone = p_pcOut->mBones;
 					for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock)
 					{
 						if (!avOutputBones[mrspock].empty())
 						{
 							// we will need this bone. add it to the output mesh and
 							// add all per-vertex weights
-							*pcBone = new aiBone();
-							(**pcBone).mName.Set(mesh.mBones[mrspock].mName);
+							aiBone* pc = *pcBone = new aiBone();
+							pc->mName.Set(mesh.mBones[mrspock].mName);
 
-							(**pcBone).mNumWeights = avOutputBones[mrspock].size();
-							(**pcBone).mWeights = new aiVertexWeight[(**pcBone).mNumWeights];
+							pc->mNumWeights = avOutputBones[mrspock].size();
+							pc->mWeights = new aiVertexWeight[pc->mNumWeights];
 
-							for (unsigned int captainkirk = 0; captainkirk < (**pcBone).mNumWeights;++captainkirk)
+							for (unsigned int captainkirk = 0; captainkirk < pc->mNumWeights;++captainkirk)
 							{
 								const std::pair<unsigned int,float>& ref = avOutputBones[mrspock][captainkirk];
-								(**pcBone).mWeights[captainkirk].mVertexId = ref.first;
-								(**pcBone).mWeights[captainkirk].mWeight = ref.second;
+								pc->mWeights[captainkirk].mVertexId = ref.first;
+								pc->mWeights[captainkirk].mWeight = ref.second;
 							}
 							++pcBone;
 						}
@@ -688,10 +724,17 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
 
 		// store the real index here ... in color channel 3
 		p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
+
 		// store the transformation matrix in color channel 2
 		p_pcOut->mColors[2] = (aiColor4D*) new aiMatrix4x4(mesh.mTransform);
 		avOutMeshes.push_back(p_pcOut);
 
+		// store the name of the mesh and the
+		// name of its parent in color channel 1
+		p_pcOut->mColors[1] = (aiColor4D*) new std::string[2];
+		((std::string*)p_pcOut->mColors[1])[0] = mesh.mName;
+		((std::string*)p_pcOut->mColors[1])[1] = mesh.mParent;
+
 		// convert vertices
 		p_pcOut->mNumVertices = mesh.mPositions.size();
 		p_pcOut->mNumFaces = mesh.mFaces.size();
@@ -772,29 +815,59 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
 				if (!avBonesOut[jfkennedy].empty())p_pcOut->mNumBones++;
 
 			p_pcOut->mBones = new aiBone*[p_pcOut->mNumBones];
-			aiBone** pcBone = &p_pcOut->mBones[0];
+			aiBone** pcBone = p_pcOut->mBones;
 			for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy)
 			{
 				if (!avBonesOut[jfkennedy].empty())
 				{
-					*pcBone = new aiBone();
-					(**pcBone).mName.Set(mesh.mBones[jfkennedy].mName);
-					(**pcBone).mNumWeights = avBonesOut[jfkennedy].size();
-					(**pcBone).mWeights = new aiVertexWeight[(**pcBone).mNumWeights];
-					memcpy((**pcBone).mWeights,&avBonesOut[jfkennedy][0],
-						sizeof(aiVertexWeight) * (**pcBone).mNumWeights);
+					aiBone* pc = *pcBone = new aiBone();
+					pc->mName.Set(mesh.mBones[jfkennedy].mName);
+					pc->mNumWeights = avBonesOut[jfkennedy].size();
+					pc->mWeights = new aiVertexWeight[pc->mNumWeights];
+					memcpy(pc->mWeights,&avBonesOut[jfkennedy][0],
+						sizeof(aiVertexWeight) * pc->mNumWeights);
 					++pcBone;
 				}
 			}
 		}
 	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+void ASEImporter::AskFilterLOD(std::vector<ASE::Mesh>& meshes)
+{
+	for (std::vector<ASE::Mesh>::iterator
+		i =  meshes.begin();
+		i != meshes.end();++i)
+	{
+		if ((*i).bSkip)continue;
 
-	// now build the output mesh list
-	pcScene->mNumMeshes = avOutMeshes.size();
-	pcScene->mMeshes = new aiMesh*[pcScene->mNumMeshes];
-	for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
-		pcScene->mMeshes[i] = avOutMeshes[i];
-
+		// search for a number in the name of the node
+		const char* sz = (*i).mName.c_str();
+		while (*sz)
+		{
+			if (*sz >= '0' && *sz <= '9')
+			{
+				// check whether there is another mesh with exactly
+				// the same name, but a lower number out there ...
+				unsigned int iLen = (unsigned int)(sz - (*i).mName.c_str());
+				unsigned int iMyNum = strtol10(sz,NULL);
+				for (std::vector<ASE::Mesh>::iterator
+					f =  meshes.begin();
+					f != meshes.end();++f)
+				{
+					const char* sz = (*f).mName.c_str();
+					if (i != f && !(*f).bSkip && 
+						0 == memcmp(sz,(*i).mName.c_str(),iLen) &&
+						iMyNum > strtol10(sz))
+					{	
+						(*f).bSkip = true;
+					}
+				}
+				break;
+			}++sz;
+		}
+	}
 	return;
 }
 // ------------------------------------------------------------------------------------------------
@@ -889,9 +962,9 @@ void ASEImporter::GenerateNormals(ASE::Mesh& mesh)
 			const ASE::Face& face = mesh.mFaces[a];
 
 			// assume it is a triangle
-			aiVector3D* pV1 = &mesh.mPositions[face.mIndices[0]];
+			aiVector3D* pV1 = &mesh.mPositions[face.mIndices[2]];
 			aiVector3D* pV2 = &mesh.mPositions[face.mIndices[1]];
-			aiVector3D* pV3 = &mesh.mPositions[face.mIndices[2]];
+			aiVector3D* pV3 = &mesh.mPositions[face.mIndices[0]];
 
 			aiVector3D pDelta1 = *pV2 - *pV1;
 			aiVector3D pDelta2 = *pV3 - *pV1;

+ 18 - 2
code/ASELoader.h

@@ -115,12 +115,19 @@ protected:
 	 */
 	void TransformVertices(ASE::Mesh& mesh);
 
+	// -------------------------------------------------------------------
+	/** The ASK file format contains LOD nodes.
+	 *  We do only use the highest level of detail, all others
+	 *  are skipped.
+	 */
+	void AskFilterLOD(std::vector<ASE::Mesh>& meshes);
+
 	// -------------------------------------------------------------------
 	/** Create one-material-per-mesh meshes ;-)
 	 * \param mesh Mesh to work with
-	 *  \param pcScene Scene object to be filled
+	 *  \param Receives the list of all created meshes
 	 */
-	void ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene);
+	void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut);
 
 	// -------------------------------------------------------------------
 	/** Convert a material to a MaterialHelper object
@@ -140,6 +147,15 @@ protected:
 	 */
 	void BuildNodes(aiScene* pcScene);
 
+	// -------------------------------------------------------------------
+	/** Add sub nodes to a node
+	 *  \param pcScene Scene object to be filled
+	 *  \param pcParent parent node to be filled
+	 *  \param szName Name of the parent node
+	 */
+	void AddNodes(aiScene* pcScene,aiNode* pcParent,
+		const char* szName);
+
 protected:
 
 	/** Parser instance */

+ 120 - 132
code/ASEParser.cpp

@@ -175,6 +175,7 @@ void Parser::Parse()
 					this->LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \
 						be 200. Continuing happily ...");
 				}
+				continue;
 			}
 			// main scene information
 			if (0 == strncmp(this->m_szFile,"*SCENE",6) &&
@@ -182,6 +183,7 @@ void Parser::Parse()
 			{
 				this->m_szFile+=7;
 				this->ParseLV1SceneBlock();
+				continue;
 			}
 			// material list
 			if (0 == strncmp(this->m_szFile,"*MATERIAL_LIST",14) &&
@@ -189,24 +191,25 @@ void Parser::Parse()
 			{
 				this->m_szFile+=15;
 				this->ParseLV1MaterialListBlock();
+				continue;
 			}
 			// geometric object (mesh)
 			if (0 == strncmp(this->m_szFile,"*GEOMOBJECT",11) &&
 				IsSpaceOrNewLine(*(this->m_szFile+11)))
 			{
 				this->m_szFile+=12;
-
 				this->m_vMeshes.push_back(Mesh());
 				this->ParseLV1GeometryObjectBlock(this->m_vMeshes.back());
+				continue;
 			}
 			// ignore comments, lights and cameras
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
-		if ('\0' == *this->m_szFile)
+		else if ('\0' == *this->m_szFile)
 		{
 			// END OF FILE ... why not?
 			return;
@@ -231,6 +234,7 @@ void Parser::ParseLV1SceneBlock()
 
 				// parse a color triple and assume it is really the bg color
 				this->ParseLV4MeshFloatTriple( &this->m_clrBackground.r );
+				continue;
 			}
 			if (0 == strncmp(this->m_szFile,"*SCENE_AMBIENT_STATIC",21) &&
 				IsSpaceOrNewLine(*(this->m_szFile+21)))
@@ -239,10 +243,11 @@ void Parser::ParseLV1SceneBlock()
 
 				// parse a color triple and assume it is really the bg color
 				this->ParseLV4MeshFloatTriple( &this->m_clrAmbient.r );
+				continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -261,6 +266,7 @@ void Parser::ParseLV1MaterialListBlock()
 {
 	int iDepth = 0;
 	unsigned int iMaterialCount = 0;
+	unsigned int iOldMaterialCount = this->m_vMaterials.size();
 	while (true)
 	{
 		if ('*' == *this->m_szFile)
@@ -272,7 +278,8 @@ void Parser::ParseLV1MaterialListBlock()
 				this->ParseLV4MeshLong(iMaterialCount);
 
 				// now allocate enough storage to hold all materials
-				this->m_vMaterials.resize(iMaterialCount);
+				this->m_vMaterials.resize(iOldMaterialCount+iMaterialCount);
+				continue;
 			}
 			if (0 == strncmp(this->m_szFile,"*MATERIAL",9) &&
 				IsSpaceOrNewLine(*(this->m_szFile+9)))
@@ -288,17 +295,18 @@ void Parser::ParseLV1MaterialListBlock()
 				}
 
 				// get a reference to the material
-				Material& sMat = this->m_vMaterials[iIndex];
+				Material& sMat = this->m_vMaterials[iIndex+iOldMaterialCount];
 
 				// skip the '{'
 				this->SkipOpeningBracket();
 
 				// parse the material block
 				this->ParseLV2MaterialBlock(sMat);
+				continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -326,36 +334,29 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 			{
 				this->m_szFile+=15;
 			
-				// NOTE: The name could also be the texture in some cases
-				// be prepared that this might occur ...
-				if (!SkipSpaces(this->m_szFile,&this->m_szFile))
-					BLUBB("Unable to parse *MATERIAL_NAME block: Unexpected EOL")
-
-				const char* sz = this->m_szFile;
-				while (!IsSpaceOrNewLine(*sz))sz++;
-				mat.mName = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile);
-				this->m_szFile = sz;
+				if (!this->ParseString(mat.mName,"*MATERIAL_NAME"))this->SkipToNextToken();
+				continue;
 			}
 			// ambient material color
 			if (0 == strncmp(this->m_szFile,"*MATERIAL_AMBIENT",17) &&
 				IsSpaceOrNewLine(*(this->m_szFile+17)))
 			{
 				this->m_szFile+=18;
-				this->ParseLV4MeshFloatTriple(&mat.mAmbient.r);
+				this->ParseLV4MeshFloatTriple(&mat.mAmbient.r);continue;
 			}
 			// diffuse material color
 			if (0 == strncmp(this->m_szFile,"*MATERIAL_DIFFUSE",17) &&
 				IsSpaceOrNewLine(*(this->m_szFile+17)))
 			{
 				this->m_szFile+=18;
-				this->ParseLV4MeshFloatTriple(&mat.mDiffuse.r);
+				this->ParseLV4MeshFloatTriple(&mat.mDiffuse.r);continue;
 			}
 			// specular material color
 			if (0 == strncmp(this->m_szFile,"*MATERIAL_SPECULAR",18) &&
 				IsSpaceOrNewLine(*(this->m_szFile+18)))
 			{
 				this->m_szFile+=19;
-				this->ParseLV4MeshFloatTriple(&mat.mSpecular.r);
+				this->ParseLV4MeshFloatTriple(&mat.mSpecular.r);continue;
 			}
 			// material shading type
 			if (0 == strncmp(this->m_szFile,"*MATERIAL_SHADING",17) &&
@@ -393,6 +394,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 					mat.mShading = Dot3DSFile::Gouraud;
 					this->SkipToNextToken();
 				}
+				continue;
 			}
 			// material transparency
 			if (0 == strncmp(this->m_szFile,"*MATERIAL_TRANSPARENCY",22) &&
@@ -400,7 +402,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 			{
 				this->m_szFile+=23;
 				this->ParseLV4MeshFloat(mat.mTransparency);
-				mat.mTransparency = 1.0f - mat.mTransparency;
+				mat.mTransparency = 1.0f - mat.mTransparency;continue;
 			}
 			// material self illumination
 			if (0 == strncmp(this->m_szFile,"*MATERIAL_SELFILLUM",19) &&
@@ -413,6 +415,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 				mat.mEmissive.r = f;
 				mat.mEmissive.g = f;
 				mat.mEmissive.b = f;
+				continue;
 			}
 			// material shininess
 			if (0 == strncmp(this->m_szFile,"*MATERIAL_SHINE",15) &&
@@ -420,14 +423,14 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 			{
 				this->m_szFile+=16;
 				this->ParseLV4MeshFloat(mat.mSpecularExponent);
-				mat.mSpecularExponent *= 15;
+				mat.mSpecularExponent *= 15;continue;
 			}
 			// material shininess strength
 			if (0 == strncmp(this->m_szFile,"*MATERIAL_SHINESTRENGTH",23) &&
 				IsSpaceOrNewLine(*(this->m_szFile+23)))
 			{
 				this->m_szFile+=24;
-				this->ParseLV4MeshFloat(mat.mShininessStrength);
+				this->ParseLV4MeshFloat(mat.mShininessStrength);continue;
 			}
 			// diffuse color map
 			if (0 == strncmp(this->m_szFile,"*MAP_DIFFUSE",12) &&
@@ -437,7 +440,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 				// skip the opening bracket
 				this->SkipOpeningBracket();
 				// parse the texture block
-				this->ParseLV3MapBlock(mat.sTexDiffuse);
+				this->ParseLV3MapBlock(mat.sTexDiffuse);continue;
 			}
 			// ambient color map
 			if (0 == strncmp(this->m_szFile,"*MAP_AMBIENT",12) &&
@@ -447,7 +450,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 				// skip the opening bracket
 				this->SkipOpeningBracket();
 				// parse the texture block
-				this->ParseLV3MapBlock(mat.sTexAmbient);
+				this->ParseLV3MapBlock(mat.sTexAmbient);continue;
 			}
 			// specular color map
 			if (0 == strncmp(this->m_szFile,"*MAP_SPECULAR",13) &&
@@ -457,7 +460,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 				// skip the opening bracket
 				this->SkipOpeningBracket();
 				// parse the texture block
-				this->ParseLV3MapBlock(mat.sTexSpecular);
+				this->ParseLV3MapBlock(mat.sTexSpecular);continue;
 			}
 			// opacity map
 			if (0 == strncmp(this->m_szFile,"*MAP_OPACITY",12) &&
@@ -467,7 +470,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 				// skip the opening bracket
 				this->SkipOpeningBracket();
 				// parse the texture block
-				this->ParseLV3MapBlock(mat.sTexOpacity);
+				this->ParseLV3MapBlock(mat.sTexOpacity);continue;
 			}
 			// emissive map
 			if (0 == strncmp(this->m_szFile,"*MAP_SELFILLUM",14) &&
@@ -477,7 +480,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 				// skip the opening bracket
 				this->SkipOpeningBracket();
 				// parse the texture block
-				this->ParseLV3MapBlock(mat.sTexEmissive);
+				this->ParseLV3MapBlock(mat.sTexEmissive);continue;
 			}
 			// bump map
 			if (0 == strncmp(this->m_szFile,"*MAP_BUMP",9) &&
@@ -497,7 +500,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 				// skip the opening bracket
 				this->SkipOpeningBracket();
 				// parse the texture block
-				this->ParseLV3MapBlock(mat.sTexShininess);
+				this->ParseLV3MapBlock(mat.sTexShininess);continue;
 			}
 			// number of submaterials
 			if (0 == strncmp(this->m_szFile,"*NUMSUBMTLS",11) &&
@@ -532,11 +535,11 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 
 				// parse the material block
 				this->ParseLV2MaterialBlock(sMat);
+				continue;
 			}
-
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -564,77 +567,54 @@ void Parser::ParseLV3MapBlock(Texture& map)
 				IsSpaceOrNewLine(*(this->m_szFile+7)))
 			{
 				this->m_szFile+=8;
-
-				// NOTE: The name could also be the texture in some cases
-				// be prepared that this might occur ...
-				if (!SkipSpaces(this->m_szFile,&this->m_szFile))
-					BLUBB("Unable to parse *BITMAP block: Unexpected EOL")
-
-				// there must be "
-				if ('\"' != *this->m_szFile)
-					BLUBB("Unable to parse *BITMAP block: Path is expected to be enclosed in double quotation marks")
-
-				++this->m_szFile;
-				const char* sz = this->m_szFile;
-				while (true)
-				{
-					if ('\"' == *sz)break;
-					else if ('\0' == sz)
-					{
-						BLUBB("Unable to parse *BITMAP block: Path is expected to be enclosed in double quotation marks \
-							  but EOF was reached before a closing quotation mark was found")
-					}
-					sz++;
-				}
-
-				map.mMapName = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile);
-				this->m_szFile = sz;
+				if(!this->ParseString(map.mMapName,"*BITMAP"))SkipToNextToken();
+				continue;
 			}
 			// offset on the u axis
 			if (0 == strncmp(this->m_szFile,"*UVW_U_OFFSET" ,13) &&
 				IsSpaceOrNewLine(*(this->m_szFile+13)))
 			{
 				this->m_szFile+=14;
-				this->ParseLV4MeshFloat(map.mOffsetU);
+				this->ParseLV4MeshFloat(map.mOffsetU);continue;
 			}
 			// offset on the v axis
 			if (0 == strncmp(this->m_szFile,"*UVW_V_OFFSET" ,13) &&
 				IsSpaceOrNewLine(*(this->m_szFile+13)))
 			{
 				this->m_szFile+=14;
-				this->ParseLV4MeshFloat(map.mOffsetV);
+				this->ParseLV4MeshFloat(map.mOffsetV);continue;
 			}
 			// tiling on the u axis
 			if (0 == strncmp(this->m_szFile,"*UVW_U_TILING" ,13) &&
 				IsSpaceOrNewLine(*(this->m_szFile+13)))
 			{
 				this->m_szFile+=14;
-				this->ParseLV4MeshFloat(map.mScaleU);
+				this->ParseLV4MeshFloat(map.mScaleU);continue;
 			}
 			// tiling on the v axis
 			if (0 == strncmp(this->m_szFile,"*UVW_V_TILING" ,13) &&
 				IsSpaceOrNewLine(*(this->m_szFile+13)))
 			{
 				this->m_szFile+=14;
-				this->ParseLV4MeshFloat(map.mScaleV);
+				this->ParseLV4MeshFloat(map.mScaleV);continue;
 			}
 			// rotation around the z-axis
 			if (0 == strncmp(this->m_szFile,"*UVW_ANGLE" ,10) &&
 				IsSpaceOrNewLine(*(this->m_szFile+10)))
 			{
 				this->m_szFile+=11;
-				this->ParseLV4MeshFloat(map.mRotation);
+				this->ParseLV4MeshFloat(map.mRotation);continue;
 			}
 			// map blending factor
 			if (0 == strncmp(this->m_szFile,"*MAP_AMOUNT" ,11) &&
 				IsSpaceOrNewLine(*(this->m_szFile+11)))
 			{
 				this->m_szFile+=12;
-				this->ParseLV4MeshFloat(map.mTextureBlend);
+				this->ParseLV4MeshFloat(map.mTextureBlend);continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -652,7 +632,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
 bool Parser::ParseString(std::string& out,const char* szName)
 {
 	char szBuffer[1024];
-	ai_assert(strlen(szName < 750));
+	ai_assert(strlen(szName) < 750);
 
 	// NOTE: The name could also be the texture in some cases
 	// be prepared that this might occur ...
@@ -702,47 +682,41 @@ void Parser::ParseLV1GeometryObjectBlock(ASE::Mesh& mesh)
 				IsSpaceOrNewLine(*(this->m_szFile+10)))
 			{
 				this->m_szFile+=11;
-				if(!this->ParseString(mesh.mName,"*NODE_NAME"))
-				{
-					this->SkipToNextToken();
-					continue;
-				}
+				if(!this->ParseString(mesh.mName,"*NODE_NAME"))this->SkipToNextToken();
+				continue;
 			}
 			// name of the parent of the node
 			if (0 == strncmp(this->m_szFile,"*NODE_PARENT" ,12) &&
 				IsSpaceOrNewLine(*(this->m_szFile+12)))
 			{
 				this->m_szFile+=13;
-				if(!this->ParseString(mesh.mParent,"*NODE_PARENT"))
-				{
-					this->SkipToNextToken();
-					continue;
-				}
+				if(!this->ParseString(mesh.mParent,"*NODE_PARENT"))this->SkipToNextToken();
+				continue;
 			}
 			// transformation matrix of the node
 			if (0 == strncmp(this->m_szFile,"*NODE_TM" ,8) &&
 				IsSpaceOrNewLine(*(this->m_szFile+8)))
 			{
 				this->m_szFile+=9;
-				this->ParseLV2NodeTransformBlock(mesh);
+				this->ParseLV2NodeTransformBlock(mesh);continue;
 			}
 			// mesh data
 			if (0 == strncmp(this->m_szFile,"*MESH" ,5) &&
 				IsSpaceOrNewLine(*(this->m_szFile+5)))
 			{
 				this->m_szFile+=6;
-				this->ParseLV2MeshBlock(mesh);
+				this->ParseLV2MeshBlock(mesh);continue;
 			}
 			// mesh material index
-			else if (0 == strncmp(this->m_szFile,"*MATERIAL_REF" ,13) &&
+			if (0 == strncmp(this->m_szFile,"*MATERIAL_REF" ,13) &&
 				IsSpaceOrNewLine(*(this->m_szFile+13)))
 			{
 				this->m_szFile+=14;
-				this->ParseLV4MeshLong(mesh.iMaterialIndex);
+				this->ParseLV4MeshLong(mesh.iMaterialIndex);continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -769,32 +743,32 @@ void Parser::ParseLV2NodeTransformBlock(ASE::Mesh& mesh)
 				IsSpaceOrNewLine(*(this->m_szFile+8)))
 			{
 				this->m_szFile+=9;
-				this->ParseLV4MeshFloatTriple(mesh.mTransform[0]);
+				this->ParseLV4MeshFloatTriple(mesh.mTransform[0]);continue;
 			}
 			// second row of the transformation matrix
 			if (0 == strncmp(this->m_szFile,"*TM_ROW1" ,8) &&
 				IsSpaceOrNewLine(*(this->m_szFile+8)))
 			{
 				this->m_szFile+=9;
-				this->ParseLV4MeshFloatTriple(mesh.mTransform[1]);
+				this->ParseLV4MeshFloatTriple(mesh.mTransform[1]);continue;
 			}
 			// third row of the transformation matrix
 			if (0 == strncmp(this->m_szFile,"*TM_ROW2" ,8) &&
 				IsSpaceOrNewLine(*(this->m_szFile+8)))
 			{
 				this->m_szFile+=9;
-				this->ParseLV4MeshFloatTriple(mesh.mTransform[2]);
+				this->ParseLV4MeshFloatTriple(mesh.mTransform[2]);continue;
 			}
 			// fourth row of the transformation matrix
 			if (0 == strncmp(this->m_szFile,"*TM_ROW3" ,8) &&
 				IsSpaceOrNewLine(*(this->m_szFile+8)))
 			{
 				this->m_szFile+=9;
-				this->ParseLV4MeshFloatTriple(mesh.mTransform[3]);
+				this->ParseLV4MeshFloatTriple(mesh.mTransform[3]);continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -827,42 +801,44 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
 				IsSpaceOrNewLine(*(this->m_szFile+15)))
 			{
 				this->m_szFile+=16;
-				this->ParseLV4MeshLong(iNumVertices);
+				this->ParseLV4MeshLong(iNumVertices);continue;
 			}
 			// Number of texture coordinates in the mesh
 			if (0 == strncmp(this->m_szFile,"*MESH_NUMTVERTEX" ,16) &&
 				IsSpaceOrNewLine(*(this->m_szFile+16)))
 			{
 				this->m_szFile+=17;
-				this->ParseLV4MeshLong(iNumTVertices);
+				this->ParseLV4MeshLong(iNumTVertices);continue;
 			}
 			// Number of vertex colors in the mesh
 			if (0 == strncmp(this->m_szFile,"*MESH_NUMCVERTEX" ,16) &&
 				IsSpaceOrNewLine(*(this->m_szFile+16)))
 			{
 				this->m_szFile+=17;
-				this->ParseLV4MeshLong(iNumCVertices);
+				this->ParseLV4MeshLong(iNumCVertices);continue;
 			}
 			// Number of regular faces in the mesh
 			if (0 == strncmp(this->m_szFile,"*MESH_NUMFACES" ,14) &&
 				IsSpaceOrNewLine(*(this->m_szFile+14)))
 			{
 				this->m_szFile+=15;
-				this->ParseLV4MeshLong(iNumFaces);
+				this->ParseLV4MeshLong(iNumFaces);continue;
+				// fix ...
+				//mesh.mFaces.resize(iNumFaces);
 			}
 			// Number of UVWed faces in the mesh
 			if (0 == strncmp(this->m_szFile,"*MESH_NUMTVFACES" ,16) &&
 				IsSpaceOrNewLine(*(this->m_szFile+16)))
 			{
 				this->m_szFile+=17;
-				this->ParseLV4MeshLong(iNumTFaces);
+				this->ParseLV4MeshLong(iNumTFaces);continue;
 			}
 			// Number of colored faces in the mesh
 			if (0 == strncmp(this->m_szFile,"*MESH_NUMCVFACES" ,16) &&
 				IsSpaceOrNewLine(*(this->m_szFile+16)))
 			{
 				this->m_szFile+=17;
-				this->ParseLV4MeshLong(iNumCFaces);
+				this->ParseLV4MeshLong(iNumCFaces);continue;
 			}
 			// mesh vertex list block
 			if (0 == strncmp(this->m_szFile,"*MESH_VERTEX_LIST" ,17) &&
@@ -870,6 +846,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
 			{
 				this->m_szFile+=18;
 				this->ParseLV3MeshVertexListBlock(iNumVertices,mesh);
+				continue;
 			}
 			// mesh face list block
 			if (0 == strncmp(this->m_szFile,"*MESH_FACE_LIST" ,15) &&
@@ -877,7 +854,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
 			{
 				this->m_szFile+=16;
 				this->SkipOpeningBracket();
-				this->ParseLV3MeshFaceListBlock(iNumFaces,mesh);
+				this->ParseLV3MeshFaceListBlock(iNumFaces,mesh);continue;
 			}
 			// mesh texture vertex list block
 			if (0 == strncmp(this->m_szFile,"*MESH_TVERTLIST" ,15) &&
@@ -885,7 +862,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
 			{
 				this->m_szFile+=16;
 				this->SkipOpeningBracket();
-				this->ParseLV3MeshTListBlock(iNumTVertices,mesh);
+				this->ParseLV3MeshTListBlock(iNumTVertices,mesh);continue;
 			}
 			// mesh texture face block
 			if (0 == strncmp(this->m_szFile,"*MESH_TFACELIST" ,15) &&
@@ -893,7 +870,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
 			{
 				this->m_szFile+=16;
 				this->SkipOpeningBracket();
-				this->ParseLV3MeshTFaceListBlock(iNumTFaces,mesh);
+				this->ParseLV3MeshTFaceListBlock(iNumTFaces,mesh);continue;
 			}
 			// mesh color vertex list block
 			if (0 == strncmp(this->m_szFile,"*MESH_CVERTLIST" ,15) &&
@@ -901,7 +878,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
 			{
 				this->m_szFile+=16;
 				this->SkipOpeningBracket();
-				this->ParseLV3MeshCListBlock(iNumCVertices,mesh);
+				this->ParseLV3MeshCListBlock(iNumCVertices,mesh);continue;
 			}
 			// mesh color face block
 			if (0 == strncmp(this->m_szFile,"*MESH_CFACELIST" ,15) &&
@@ -909,7 +886,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
 			{
 				this->m_szFile+=16;
 				this->SkipOpeningBracket();
-				this->ParseLV3MeshCFaceListBlock(iNumCFaces,mesh);
+				this->ParseLV3MeshCFaceListBlock(iNumCFaces,mesh);continue;
 			}
 			// another mesh UV channel ...
 			if (0 == strncmp(this->m_szFile,"*MESH_MAPPINGCHANNEL" ,20) &&
@@ -942,9 +919,10 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
 					// parse the mapping channel
 					this->ParseLV3MappingChannel(iIndex-1,mesh);
 				}
+				continue;
 			}
 			// mesh animation keyframe. Not supported
-			else if (0 == strncmp(this->m_szFile,"*MESH_ANIMATION" ,15) &&
+			if (0 == strncmp(this->m_szFile,"*MESH_ANIMATION" ,15) &&
 				IsSpaceOrNewLine(*(this->m_szFile+15)))
 			{
 				this->m_szFile+=16;
@@ -952,17 +930,18 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
 				this->LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. "
 					"Keyframe animation is not supported by Assimp, this element "
 					"will be ignored");
+				continue;
 			}
 			// mesh animation keyframe. Not supported
-			else if (0 == strncmp(this->m_szFile,"*MESH_WEIGHTS" ,13) &&
+			if (0 == strncmp(this->m_szFile,"*MESH_WEIGHTS" ,13) &&
 				IsSpaceOrNewLine(*(this->m_szFile+13)))
 			{
 				this->m_szFile+=14;
-				this->ParseLV3MeshWeightsBlock(mesh);
+				this->ParseLV3MeshWeightsBlock(mesh);continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -991,14 +970,14 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
 				IsSpaceOrNewLine(*(this->m_szFile+15)))
 			{
 				this->m_szFile+=16;
-				this->ParseLV4MeshLong(iNumVertices);
+				this->ParseLV4MeshLong(iNumVertices);continue;
 			}
 			// Number of bones
 			if (0 == strncmp(this->m_szFile,"*MESH_NUMBONE" ,13) &&
 				IsSpaceOrNewLine(*(this->m_szFile+13)))
 			{
 				this->m_szFile+=14;
-				this->ParseLV4MeshLong(iNumBones);
+				this->ParseLV4MeshLong(iNumBones);continue;
 			}
 			// parse the list of bones
 			if (0 == strncmp(this->m_szFile,"*MESH_BONE_LIST" ,15) &&
@@ -1006,7 +985,7 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
 			{
 				this->m_szFile+=16;
 				this->SkipOpeningBracket();
-				this->ParseLV4MeshBones(iNumBones,mesh);
+				this->ParseLV4MeshBones(iNumBones,mesh);continue;
 			}
 			// parse the list of bones vertices
 			if (0 == strncmp(this->m_szFile,"*MESH_BONE_VERTEX_LIST" ,22) &&
@@ -1015,10 +994,11 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
 				this->m_szFile+=23;
 				this->SkipOpeningBracket();
 				this->ParseLV4MeshBonesVertices(iNumVertices,mesh);
+				continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -1058,14 +1038,12 @@ void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
 							"bone index instead");
 					}
 					if (!this->ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME"))						
-					{
 						this->SkipToNextToken();
-						continue;
-					}
+					continue;
 				}
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
+		else if ('{' == *this->m_szFile)iDepth++;
 		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
@@ -1127,9 +1105,10 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh
 						mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut);
 					}
 				}
+				continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
+		else if ('{' == *this->m_szFile)iDepth++;
 		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
@@ -1170,9 +1149,10 @@ void Parser::ParseLV3MeshVertexListBlock(
 					this->LogWarning("Vertex has an invalid index. It will be ignored");
 				}
 				else mesh.mPositions[iIndex] = vTemp;
+				continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
+		else if ('{' == *this->m_szFile)iDepth++;
 		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
@@ -1211,10 +1191,11 @@ void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
 					this->LogWarning("Face has an invalid index. It will be ignored");
 				}
 				else mesh.mFaces[mFace.iFace] = mFace;
+				continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -1260,10 +1241,11 @@ void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
 					// we need 3 coordinate channels
 					mesh.mNumUVComponents[iChannel] = 3;
 				}
+				continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -1307,10 +1289,11 @@ void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
 					mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1];
 					mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2];
 				}
+				continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -1340,14 +1323,14 @@ void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
 				IsSpaceOrNewLine(*(this->m_szFile+16)))
 			{
 				this->m_szFile+=17;
-				this->ParseLV4MeshLong(iNumTVertices);
+				this->ParseLV4MeshLong(iNumTVertices);continue;
 			}
 			// Number of UVWed faces in the mesh
 			if (0 == strncmp(this->m_szFile,"*MESH_NUMTVFACES" ,16) &&
 				IsSpaceOrNewLine(*(this->m_szFile+16)))
 			{
 				this->m_szFile+=17;
-				this->ParseLV4MeshLong(iNumTFaces);
+				this->ParseLV4MeshLong(iNumTFaces);continue;
 			}
 			// mesh texture vertex list block
 			if (0 == strncmp(this->m_szFile,"*MESH_TVERTLIST" ,15) &&
@@ -1356,6 +1339,7 @@ void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
 				this->m_szFile+=16;
 				this->SkipOpeningBracket();
 				this->ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel);
+				continue;
 			}
 			// mesh texture face block
 			if (0 == strncmp(this->m_szFile,"*MESH_TFACELIST" ,15) &&
@@ -1364,10 +1348,11 @@ void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
 				this->m_szFile+=16;
 				this->SkipOpeningBracket();
 				this->ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel);
+				continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -1407,10 +1392,11 @@ void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh)
 					this->LogWarning("Vertex color has an invalid index. It will be ignored");
 				}
 				else mesh.mVertexColors[iIndex] = vTemp;
+				continue;
 			}
 		}
 		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -1453,10 +1439,11 @@ void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
 					mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1];
 					mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2];
 				}
+				continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}
@@ -1500,10 +1487,11 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
 
 				// important: this->m_szFile might now point to '}' ...
 				sMesh.mNormals[iIndex] = vNormal;
+				continue;
 			}
 		}
-		if ('{' == *this->m_szFile)iDepth++;
-		if ('}' == *this->m_szFile)
+		else if ('{' == *this->m_szFile)iDepth++;
+		else if ('}' == *this->m_szFile)
 		{
 			if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
 		}

+ 4 - 1
code/ASEParser.h

@@ -160,7 +160,7 @@ struct BoneVertex
 struct Mesh
 {
 	//! Constructor. Creates a default name for the mesh
-	Mesh()
+	Mesh() : bSkip(false)
 	{
 		static int iCnt = 0;
 		std::stringstream ss(mName);
@@ -211,6 +211,9 @@ struct Mesh
 
 	//! Number of vertex components for each UVW set
 	unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+
+	//! used internally
+	bool bSkip;
 };
 
 // ---------------------------------------------------------------------------------

+ 36 - 4
code/ConvertToLHProcess.cpp

@@ -24,7 +24,7 @@ const aiMatrix3x3 Assimp::ConvertToLHProcess::sToDXTransform(
 // Constructor to be privately used by Importer
 ConvertToLHProcess::ConvertToLHProcess()
 {
-	// nothing to do here
+	bTransformVertices = false;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -38,7 +38,13 @@ ConvertToLHProcess::~ConvertToLHProcess()
 // Returns whether the processing step is present in the given flag field.
 bool ConvertToLHProcess::IsActive( unsigned int pFlags) const
 {
-	return (pFlags & aiProcess_ConvertToLeftHanded) != 0;
+	if (pFlags & aiProcess_ConvertToLeftHanded)
+	{
+		if (pFlags & aiProcess_PreTransformVertices)
+			this->bTransformVertices = true;
+		return true;
+	}
+	return false;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -54,8 +60,34 @@ void ConvertToLHProcess::Execute( aiScene* pScene)
 
 	DefaultLogger::get()->debug("ConvertToLHProcess begin");
 
-	// transform the root node of the scene, the other nodes will follow then
-	ConvertToDX( pScene->mRootNode->mTransformation);
+	// transform vertex by vertex or change the root transform?
+	if (this->bTransformVertices)
+	{
+		this->bTransformVertices = false;
+		aiMatrix4x4 mTransform;
+		this->ConvertToDX(mTransform);
+		for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+		{
+			aiMesh* pcMesh = pScene->mMeshes[i];
+			for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
+			{
+				pcMesh->mVertices[n] = mTransform * pcMesh->mVertices[n];
+			}
+			if (pcMesh->HasNormals())
+			{
+				mTransform.Inverse().Transpose();
+				for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
+				{
+					pcMesh->mNormals[n] = mTransform * pcMesh->mNormals[n];
+				}
+			}
+		}
+	}
+	else
+	{
+		// transform the root node of the scene, the other nodes will follow then
+		ConvertToDX( pScene->mRootNode->mTransformation);
+	}
 
 	// transform all meshes accordingly
 	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)

+ 4 - 0
code/ConvertToLHProcess.h

@@ -116,6 +116,10 @@ protected:
 	 */
 	void ProcessAnimation( aiBoneAnim* pAnim);
 
+	//! true if the transformation matrix for the OGL-to-DX is 
+	//! directly used to transform all vertices.
+	mutable bool bTransformVertices;
+
 public:
 	/** The transformation matrix to convert from DirectX coordinates to OpenGL coordinates. */
 	static const aiMatrix3x3 sToOGLTransform;

+ 161 - 0
code/HalfLifeFileData.h

@@ -0,0 +1,161 @@
+/*
+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 in-memory structures for the HL2 MDL file format
+//  and for the HalfLife text format (SMD)
+//
+// The specification has been taken from various sources on the internet.
+
+
+#ifndef AI_MDLFILEHELPER2_H_INC
+#define AI_MDLFILEHELPER2_H_INC
+
+
+// ugly compiler dependent packing stuff
+#if defined(_MSC_VER) ||  defined(__BORLANDC__) ||	defined (__BCPLUSPLUS__)
+#	pragma pack(push,1)
+#	define PACK_STRUCT
+#elif defined( __GNUC__ )
+#	define PACK_STRUCT	__attribute__((packed))
+#else
+#	error Compiler not supported. Never do this again.
+#endif
+
+namespace Assimp
+{
+namespace MDL
+{
+
+// magic bytes used in Half Life 2 MDL models
+#define AI_MDL_MAGIC_NUMBER_BE_HL2a	'IDST'
+#define AI_MDL_MAGIC_NUMBER_LE_HL2a	'TSDI'
+#define AI_MDL_MAGIC_NUMBER_BE_HL2b	'IDSQ'
+#define AI_MDL_MAGIC_NUMBER_LE_HL2b	'QSDI'
+
+// ---------------------------------------------------------------------------
+/** \struct Header_HL2
+ *  \brief Data structure for the HL2 main header
+ */
+// ---------------------------------------------------------------------------
+struct Header_HL2 
+{
+	//! magic number: "IDST"/"IDSQ"
+	char	ident[4];		
+
+	//! Version number
+	int32_t	version;
+
+	//! Original file name in pak ?
+	char		name[64];
+
+	//! Length of file name/length of file?
+	int32_t		length;
+
+	//! For viewer, ignored
+	aiVector3D		eyeposition;	
+	aiVector3D		min;			
+	aiVector3D		max;			
+
+	//! AABB of the model
+	aiVector3D		bbmin;			
+	aiVector3D		bbmax;		
+
+	// File flags
+	int32_t			flags;
+
+	//! NUmber of bones contained in the file
+	int32_t			numbones;			
+	int32_t			boneindex;
+
+	//! Number of bone controllers for bone animation
+	int32_t			numbonecontrollers;		
+	int32_t			bonecontrollerindex;
+
+	//! More bounding boxes ...
+	int32_t			numhitboxes;			
+	int32_t			hitboxindex;			
+	
+	//! Animation sequences in the file
+	int32_t			numseq;				
+	int32_t			seqindex;
+
+	//! Loaded sequences. Ignored
+	int32_t			numseqgroups;		
+	int32_t			seqgroupindex;
+
+	//! Raw texture data
+	int32_t			numtextures;		
+	int32_t			textureindex;
+	int32_t			texturedataindex;
+
+	//! Number of skins (=textures?)
+	int32_t			numskinref;			
+	int32_t			numskinfamilies;
+	int32_t			skinindex;
+
+	//! Number of parts
+	int32_t			numbodyparts;		
+	int32_t			bodypartindex;
+
+	//! attachable points for gameplay and physics
+	int32_t			numattachments;		
+	int32_t			attachmentindex;
+
+	//! Table of sound effects associated with the model
+	int32_t			soundtable;
+	int32_t			soundindex;
+	int32_t			soundgroups;
+	int32_t			soundgroupindex;
+
+	//! Number of animation transitions
+	int32_t			numtransitions;		
+	int32_t			transitionindex;
+} PACK_STRUCT;
+
+// reset packing to the original value
+#if defined(_MSC_VER) ||  defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
+#	pragma pack( pop )
+#endif
+#undef PACK_STRUCT
+
+};}; // end namespaces
+#endif // ! AI_MDLFILEHELPER2_H_INC

+ 2 - 0
code/Importer.cpp

@@ -88,6 +88,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "GenVertexNormalsProcess.h"
 #include "KillNormalsProcess.h"
 #include "SplitLargeMeshes.h"
+#include "PretransformVertices.h"
 #include "../include/DefaultLogger.h"
 
 using namespace Assimp;
@@ -133,6 +134,7 @@ Importer::Importer() :
 
 	// add an instance of each post processing step here in the order of sequence it is executed
 	mPostProcessingSteps.push_back( new TriangulateProcess());
+	mPostProcessingSteps.push_back( new PretransformVertices());
 	mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Triangle());
 	mPostProcessingSteps.push_back( new KillNormalsProcess());
 	mPostProcessingSteps.push_back( new GenFaceNormalsProcess());

+ 15 - 86
code/MDLFileData.h

@@ -67,7 +67,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #	error Compiler not supported. Never do this again.
 #endif
 
-
 namespace Assimp
 {
 namespace MDL
@@ -95,11 +94,6 @@ namespace MDL
 #define AI_MDL_MAGIC_NUMBER_BE_GS7	'MDL7'
 #define AI_MDL_MAGIC_NUMBER_LE_GS7	'7LDM'
 
-// magic bytes used in Half Life 2 MDL models
-#define AI_MDL_MAGIC_NUMBER_BE_HL2a	'IDST'
-#define AI_MDL_MAGIC_NUMBER_LE_HL2a	'TSDI'
-#define AI_MDL_MAGIC_NUMBER_BE_HL2b	'IDSQ'
-#define AI_MDL_MAGIC_NUMBER_LE_HL2b	'QSDI'
 
 // common limitations for Quake1 meshes. The loader does not check them,
 // but models should not exceed these limits.
@@ -217,86 +211,6 @@ struct Header_MDL7
 } PACK_STRUCT;
 
 
-// ---------------------------------------------------------------------------
-/** \struct Header_HL2
- *  \brief Data structure for the HL2 main header
- */
-// ---------------------------------------------------------------------------
-struct Header_HL2 
-{
-	//! magic number: "IDST"/"IDSQ"
-	char	ident[4];		
-
-	//! Version number
-	int32_t	version;
-
-	//! Original file name in pak ?
-	char		name[64];
-
-	//! Length of file name/length of file?
-	int32_t		length;
-
-	//! For viewer, ignored
-	aiVector3D		eyeposition;	
-	aiVector3D		min;			
-	aiVector3D		max;			
-
-	//! AABB of the model
-	aiVector3D		bbmin;			
-	aiVector3D		bbmax;		
-
-	// File flags
-	int32_t			flags;
-
-	//! NUmber of bones contained in the file
-	int32_t			numbones;			
-	int32_t			boneindex;
-
-	//! Number of bone controllers for bone animation
-	int32_t			numbonecontrollers;		
-	int32_t			bonecontrollerindex;
-
-	//! More bounding boxes ...
-	int32_t			numhitboxes;			
-	int32_t			hitboxindex;			
-	
-	//! Animation sequences in the file
-	int32_t			numseq;				
-	int32_t			seqindex;
-
-	//! Loaded sequences. Ignored
-	int32_t			numseqgroups;		
-	int32_t			seqgroupindex;
-
-	//! Raw texture data
-	int32_t			numtextures;		
-	int32_t			textureindex;
-	int32_t			texturedataindex;
-
-	//! Number of skins (=textures?)
-	int32_t			numskinref;			
-	int32_t			numskinfamilies;
-	int32_t			skinindex;
-
-	//! Number of parts
-	int32_t			numbodyparts;		
-	int32_t			bodypartindex;
-
-	//! attachable points for gameplay and physics
-	int32_t			numattachments;		
-	int32_t			attachmentindex;
-
-	//! Table of sound effects associated with the model
-	int32_t			soundtable;
-	int32_t			soundindex;
-	int32_t			soundgroups;
-	int32_t			soundgroupindex;
-
-	//! Number of animation transitions
-	int32_t			numtransitions;		
-	int32_t			transitionindex;
-} PACK_STRUCT;
-
 #define AI_MDL7_MAX_BONENAMESIZE	20 
 
 // ---------------------------------------------------------------------------
@@ -372,6 +286,12 @@ struct Deformer_MDL7
 	int32_t	deformerdata_size;
 } PACK_STRUCT;
 
+
+// ---------------------------------------------------------------------------
+/** \struct DeformerElement_MDL7
+ *  \brief Deformer element in a MDL7 file
+ */
+// ---------------------------------------------------------------------------
 struct DeformerElement_MDL7
 {
 	//! bei deformer_typ==0 (==bones) element_index == bone index
@@ -380,6 +300,12 @@ struct DeformerElement_MDL7
 	int32_t	weights;
 } PACK_STRUCT;
 
+
+// ---------------------------------------------------------------------------
+/** \struct DeformerWeight_MDL7
+ *  \brief Deformer weight in a MDL7 file
+ */
+// ---------------------------------------------------------------------------
 struct DeformerWeight_MDL7
 {
 	//! for deformer_typ==0 (==bones) index == vertex index
@@ -387,8 +313,11 @@ struct DeformerWeight_MDL7
 	float	weight;
 } PACK_STRUCT;
 
+// maximum length of texture file name
 #define AI_MDL7_MAX_TEXNAMESIZE		0x10
 
+// don't know why this was in the original headers ...
+// to be removed in future versions
 typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
 
 // ---------------------------------------------------------------------------

+ 1 - 0
code/MDLLoader.h

@@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 struct aiNode;
 #include "MDLFileData.h"
+#include "HalfLifeFileData.h"
 
 namespace Assimp
 {

+ 378 - 0
code/PretransformVertices.cpp

@@ -0,0 +1,378 @@
+/*
+---------------------------------------------------------------------------
+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 "PretransformVertices" post processing step 
+*/
+#include "PretransformVertices.h"
+#include "../include/DefaultLogger.h"
+#include "../include/aiPostProcess.h"
+#include "../include/aiMesh.h"
+#include "../include/aiScene.h"
+#include "../include/aiAssert.h"
+
+#include <list>
+
+using namespace Assimp;
+
+// Constructor to be privately used by Importer
+PretransformVertices::PretransformVertices()
+	{
+	}
+
+// Destructor, private as well
+PretransformVertices::~PretransformVertices()
+	{
+	// nothing to do here
+	}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool PretransformVertices::IsActive( unsigned int pFlags) const
+{
+	return	(pFlags & aiProcess_PreTransformVertices) != 0;
+}
+// ------------------------------------------------------------------------------------------------
+// Count the number of nodes
+unsigned int CountNodes( aiNode* pcNode )
+{
+	unsigned int iRet = 1;
+	for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
+	{
+		iRet += CountNodes(pcNode->mChildren[i]);
+	}
+	return iRet;
+}
+// ------------------------------------------------------------------------------------------------
+// Get a bitwise combination identifying the vertex format of a mesh
+unsigned int GetMeshVFormat(aiMesh* pcMesh)
+{
+	if (0xdeadbeef == pcMesh->mNumUVComponents[0])
+		return pcMesh->mNumUVComponents[1];
+
+	unsigned int iRet = 0;
+
+	// normals
+	if (pcMesh->HasNormals())iRet |= 0x1;
+	// tangents and bitangents
+	if (pcMesh->HasTangentsAndBitangents())iRet |= 0x2;
+
+	// texture coordinates
+	unsigned int p = 0;
+	ai_assert(4 >= AI_MAX_NUMBER_OF_TEXTURECOORDS);
+	while (pcMesh->HasTextureCoords(p))
+	{
+		iRet |= (0x100 << p++);
+		if (3 == pcMesh->mNumUVComponents[p])
+			iRet |= (0x1000 << p++);
+	}
+	// vertex colors
+	p = 0;
+	while (pcMesh->HasVertexColors(p))iRet |= (0x10000 << p++);
+
+	// store the value for later use
+	pcMesh->mNumUVComponents[0] = 0xdeadbeef;
+	pcMesh->mNumUVComponents[1] = iRet;
+
+	return iRet;
+}
+// ------------------------------------------------------------------------------------------------
+// Count the number of vertices in the whole scene and a given
+// material index
+void CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
+	unsigned int iVFormat, unsigned int* piFaces, unsigned int* piVertices)
+{
+	for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
+	{
+		aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ]; 
+		if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh))
+		{
+			*piVertices += pcMesh->mNumVertices;
+			*piFaces += pcMesh->mNumFaces;
+		}
+	}
+	for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
+	{
+		CountVerticesAndFaces(pcScene,pcNode->mChildren[i],iMat,
+			iVFormat,piFaces,piVertices);
+	}
+	return;
+}
+
+#define AI_PTVS_VERTEX 0x0
+#define AI_PTVS_FACE 0x1
+
+// ------------------------------------------------------------------------------------------------
+// Collect vertex/face data
+void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
+	unsigned int iVFormat, aiMesh* pcMeshOut, 
+	unsigned int aiCurrent[2])
+{
+	for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
+	{
+		aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ]; 
+		if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh))
+		{
+			// copy positions, transform them to worldspace
+			for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
+			{
+				pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX]+n] = 
+					pcNode->mTransformation * pcMesh->mVertices[n];
+			}
+			if (iVFormat & 0x1)
+			{
+				aiMatrix4x4 mWorldIT = pcNode->mTransformation;
+				mWorldIT.Inverse().Transpose();
+
+				// copy normals, transform them to worldspace
+				for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
+				{
+					pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX]+n] = 
+						mWorldIT * pcMesh->mNormals[n];
+				}
+			}
+			if (iVFormat & 0x2)
+			{
+				// copy tangents
+				memcpy(pcMeshOut->mTangents + aiCurrent[AI_PTVS_VERTEX],
+					pcMesh->mTangents,
+					pcMesh->mNumVertices * sizeof(aiVector3D));
+				// copy bitangents
+				memcpy(pcMeshOut->mBitangents + aiCurrent[AI_PTVS_VERTEX],
+					pcMesh->mBitangents,
+					pcMesh->mNumVertices * sizeof(aiVector3D));
+			}
+			unsigned int p = 0;
+			while (iVFormat & (0x100 << p))
+			{
+				// copy texture coordinates
+				memcpy(pcMeshOut->mTextureCoords[p] + aiCurrent[AI_PTVS_VERTEX],
+					pcMesh->mTextureCoords[p],
+					pcMesh->mNumVertices * sizeof(aiVector3D));
+				++p;
+			}
+			p = 0;
+			while (iVFormat & (0x10000 << p))
+			{
+				// copy vertex colors
+				memcpy(pcMeshOut->mColors[p] + aiCurrent[AI_PTVS_VERTEX],
+					pcMesh->mColors[p],
+					pcMesh->mNumVertices * sizeof(aiColor4D));
+				++p;
+			}
+			// now we need to copy all faces
+			// since we will delete the source mesh afterwards,
+			// we don't need to reallocate the array of indices
+			for (unsigned int planck = 0;planck<pcMesh->mNumFaces;++planck)
+			{
+				pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE]+planck].mNumIndices =
+					pcMesh->mFaces[planck].mNumIndices; 
+
+				unsigned int* pi = pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE]+planck].
+					mIndices = pcMesh->mFaces[planck].mIndices; 
+
+				// offset all vrtex indices
+				for (unsigned int hahn = 0; hahn < pcMesh->mFaces[planck].mNumIndices;++hahn)
+				{
+					pi[hahn] += aiCurrent[AI_PTVS_VERTEX];
+				}
+
+				// just make sure the array won't be deleted by the
+				// aiFace destructor ...
+				pcMesh->mFaces[planck].mIndices = NULL;
+			}
+			aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices;
+			aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces;
+		}
+	}
+	for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
+	{
+		CollectData(pcScene,pcNode->mChildren[i],iMat,
+			iVFormat,pcMeshOut,aiCurrent);
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+// Get a list of all vertex formats that occur for a given material index
+// The output list contains duplicate elements
+void GetVFormatList( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
+					std::list<unsigned int>& aiOut)
+{
+	for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
+	{
+		aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ]; 
+		if (iMat == pcMesh->mMaterialIndex)
+		{
+			aiOut.push_back(GetMeshVFormat(pcMesh));
+		}
+	}
+	for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
+	{
+		GetVFormatList(pcScene,pcNode->mChildren[i],iMat,aiOut);
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+// Compute the absolute transformation matrices of each node
+void ComputeAbsoluteTransform( aiNode* pcNode )
+{
+	if (pcNode->mParent)
+	{
+		pcNode->mTransformation =  pcNode->mTransformation*pcNode->mParent->mTransformation;
+	}
+
+	for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
+	{
+		ComputeAbsoluteTransform(pcNode->mChildren[i]);
+	}
+	return;
+}
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void PretransformVertices::Execute( aiScene* pScene)
+{
+	DefaultLogger::get()->debug("PretransformVerticesProcess begin");
+
+	// first compute absolute transformation matrices for all nodes
+	ComputeAbsoluteTransform(pScene->mRootNode);
+
+	// now build a list of output meshes
+	std::vector<aiMesh*> apcOutMeshes;
+	apcOutMeshes.reserve(pScene->mNumMaterials*2);
+	std::list<unsigned int> aiVFormats;
+	for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+	{
+		// get the list of all vertex formats for this material
+		aiVFormats.clear();
+		GetVFormatList(pScene,pScene->mRootNode,i,aiVFormats);
+		aiVFormats.sort(std::less<unsigned int>());
+		aiVFormats.unique();
+		for (std::list<unsigned int>::const_iterator
+			j =  aiVFormats.begin();
+			j != aiVFormats.end();++j)
+		{
+			unsigned int iVertices = 0;
+			unsigned int iFaces = 0; 
+			CountVerticesAndFaces(pScene,pScene->mRootNode,i,*j,&iFaces,&iVertices);
+			if (iFaces && iVertices)
+			{
+				apcOutMeshes.push_back(new aiMesh());
+				aiMesh* pcMesh = apcOutMeshes.back();
+				pcMesh->mNumFaces = iFaces;
+				pcMesh->mNumVertices = iVertices;
+				pcMesh->mFaces = new aiFace[iFaces];
+				pcMesh->mVertices = new aiVector3D[iVertices];
+				pcMesh->mMaterialIndex = i;
+				if ((*j) & 0x1)pcMesh->mNormals = new aiVector3D[iVertices];
+				if ((*j) & 0x2)
+				{
+					pcMesh->mTangents = new aiVector3D[iVertices];
+					pcMesh->mBitangents = new aiVector3D[iVertices];
+				}
+				iFaces = 0;
+				while ((*j) & (0x100 << iFaces))
+				{
+					pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices];
+					if ((*j) & (0x1000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3;
+					else pcMesh->mNumUVComponents[iFaces] = 2;
+					iFaces++;
+				}
+				iFaces = 0;
+				while ((*j) & (0x10000 << iFaces))
+					pcMesh->mColors[iFaces] = new aiColor4D[iVertices];
+
+				// fill the mesh ...
+				unsigned int aiTemp[2] = {0,0};
+				CollectData(pScene,pScene->mRootNode,i,*j,pcMesh,aiTemp);
+			}
+		}
+	}
+
+	// remove all animations from the scene
+	for (unsigned int i = 0; i < pScene->mNumAnimations;++i)
+		delete pScene->mAnimations[i];
+	pScene->mAnimations = NULL;
+	pScene->mNumAnimations = 0;
+
+	// now delete all meshes in the scene and build a new mesh list
+	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+		delete pScene->mMeshes[i];
+	if (apcOutMeshes.size() != pScene->mNumMeshes)
+	{
+		delete[] pScene->mMeshes;
+		pScene->mNumMeshes = apcOutMeshes.size();
+		pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+	}
+	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+		pScene->mMeshes[i] = apcOutMeshes[i];
+
+	// now delete all nodes in the scene and build a new
+	// flat node graph with a root node and some level 1 children
+	delete pScene->mRootNode;
+	pScene->mRootNode = new aiNode();
+	pScene->mRootNode->mName.Set("<dummy_root>");
+
+	if (1 == pScene->mNumMeshes)
+	{
+		pScene->mRootNode->mNumMeshes = 1;
+		pScene->mRootNode->mMeshes = new unsigned int[1];
+		pScene->mRootNode->mMeshes[0] = 0;
+	}
+	else
+	{
+		pScene->mRootNode->mNumChildren = pScene->mNumMeshes;
+		pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes];
+		for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+		{
+			aiNode* pcNode = pScene->mRootNode->mChildren[i] = new aiNode();
+			pcNode->mName.length = sprintf(pcNode->mName.data,"dummy_%i",i);
+
+			pcNode->mNumMeshes = 1;
+			pcNode->mMeshes = new unsigned int[1];
+			pcNode->mMeshes[0] = i;
+			pcNode->mParent = pScene->mRootNode;
+		}
+	}
+
+	DefaultLogger::get()->debug("PretransformVerticesProcess finished. All "
+		"vertices are in worldspace now");
+	return;
+}
+

+ 88 - 0
code/PretransformVertices.h

@@ -0,0 +1,88 @@
+/*
+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 Defines a post processing step to pretransform all 
+ vertices in the scenegraph */
+#ifndef AI_PRETRANSFORMVERTICES_H_INC
+#define AI_PRETRANSFORMVERTICES_H_INC
+
+#include "BaseProcess.h"
+#include "../include/aiMesh.h"
+
+namespace Assimp
+{
+
+// ---------------------------------------------------------------------------
+/** The PretransformVertices pretransforms all vertices in the nodegraph
+ *  and removes the whole graph. The output is a list of meshes, one for
+ *  each material.
+*/
+class PretransformVertices : public BaseProcess
+{
+	friend class Importer;
+
+protected:
+	/** Constructor to be privately used by Importer */
+	PretransformVertices ();
+
+	/** Destructor, private as well */
+	~PretransformVertices ();
+
+public:
+	// -------------------------------------------------------------------
+	/** Returns whether the processing step is present in the given flag field.
+	* @param pFlags The processing flags the importer was called with. A bitwise
+	*   combination of #aiPostProcessSteps.
+	* @return true if the process is present in this flag fields, false if not.
+	*/
+	bool IsActive( unsigned int pFlags) const;
+
+	// -------------------------------------------------------------------
+	/** Executes the post processing step on the given imported data.
+	* At the moment a process is not supposed to fail.
+	* @param pScene The imported data to work at.
+	*/
+	void Execute( aiScene* pScene);
+
+};
+
+} // end of namespace Assimp
+
+#endif // !!AI_GENFACENORMALPROCESS_H_INC

+ 0 - 0
code/unused/MakeVerboseFormat.cpp → code/extra/MakeVerboseFormat.cpp


+ 0 - 0
code/unused/MakeVerboseFormat.h → code/extra/MakeVerboseFormat.h


+ 44 - 2
doc/dox.h

@@ -565,8 +565,8 @@ Textures are generally defined by a set of parameters, including
 <b>1. The path to the texture.</b>  This property is always set. If it is not set, a texture 
 is not existing. This can either be a valid path (beware, sometimes
 it could be a 8.3 file name!) or an asterisk (*) suceeded by a zero-based index, the latter being
-a reference to an embedded texture (@link textures more details @endlink). I suggest using code
-like this to find out whether a texture is embedded:
+a reference to an embedded texture (see the "Textures" section for more details). I suggest using code
+like this to find out whether a texture is embedded or not:
 @code
 aiString path; // contains the path obtained via aiGetMaterialString()
 const aiScene* scene; // valid aiScene instance
@@ -606,6 +606,26 @@ the first texture in a texture slot (e.g. diffuse 0) specifies how the diffuse b
 vertex color have to be combined with the texture color value.
 <br>
 
+You can use the aiGetMaterialTexture() function to read all texture parameters at once (maybe
+if you're too lazy to read 4 or 5 values manually if there's a smart helper function 
+doing all the work for you ...).
+
+@code
+if (AI_SUCCESS != aiGetMaterialTexture(
+   pcMat,               // Material object
+   0,                   // first texture in the diffuse slot
+   AI_TEXTYPE_DIFFUSE,  // purpose of texture is diffuse
+   &path,               // receives the path of the texture
+   &uv,                 // receives the UV index of the texture
+   &blend,              // receives the blend factor of the texture
+   &op,                 // receives the blend operation of the texture
+   // (you may also specify 0 for a parameter if you don't need it)
+   )) 
+{
+   // cry, jump out of the window, but don't take drugs if this occurs!
+}
+@endcode
+
 @section bones Bones
 
 A mesh may have a set of bones in the form of aiBone structures.. Bones are a means to deform a mesh 
@@ -672,6 +692,28 @@ need them at all.
 
 @section textures Textures
 
+Normally textures used by assets are stored in separate files, however,
+there are file formats embedding their textures directly into the model file.
+Such textures are loaded into an aiTexture structure. 
+<br>
+There are two cases:
+<br>
+<b>1)</b> The texture is NOT compressed. Its color data is directly stored
+in the aiTexture structure as an array of aiTexture::mWidth * aiTexture::mHeight aiTexel structures. Each aiTexel represents a pixel (or "texel") of the texture
+image. The color data is stored in an unsigned RGBA8888 format, which can be easily used for
+both Direct3D and OpenGL (swizzling the order of the color components might be necessary).
+RGBA8888 has been chosen because it is well-known, easy to use and natively
+supported by nearly all graphics APIs.
+<br>
+<b>2)</b> This is the case for aiTexture::mHeight == 0. The texture is stored in a
+"compressed" format such as DDS or PNG. The term "compressed" does not mean that the
+texture data must actually be compressed, however the texture was stored in the
+model file as if it was stored in a separate file on the harddisk. Appropriate
+decoders (such as libjpeg, libpng, D3DX, DevIL) are required to load theses textures.
+aiTexture::mWidth specifies the size of the texture data in bytes, aiTexture::pcData is
+a pointer to the raw image data and aiTexture::achFormatHint is either zeroed or
+containing the file extension of the format of the embedded texture. This is only
+set if ASSIMP is able to determine the file format.
 */
 
 /** 

+ 17 - 1
include/aiPostProcess.h

@@ -108,7 +108,23 @@ enum aiPostProcessSteps
 	* in the internal SplitLargeMeshes.h header as AI_SLM_DEFAULT_MAX_VERTICES
 	* and AI_SLM_DEFAULT_MAX_TRIANGLES. 
 	*/
-	aiProcess_SplitLargeMeshes = 0x80
+	aiProcess_SplitLargeMeshes = 0x80,
+
+	/** Removes the node graph and pretransforms all vertices with
+	* the local transformation matrices of their nodes. The output
+	* scene does still contain nodes, however, there is only a
+	* root node with childs, each one referencing only one mesh,
+	* each mesh referencing one material. For rendering, you can
+	* simply render all meshes in order, you don't need to pay
+	* attention to local transformations and the node hierarchy.
+	* Animations are removed during this step. 
+	* This step is intended for applications that have no scenegraph.
+	* The step CAN cause some problems: if e.g. a mesh of the asset
+	* contains normals and another, using the same material index, does not, 
+	* they will be brought together, but the first meshes's part of
+	* the normal list will be zeroed.
+	*/
+	aiProcess_PreTransformVertices = 0x100,
 };
 
 // ---------------------------------------------------------------------------

+ 1 - 1
include/aiTexture.h

@@ -87,7 +87,7 @@ struct aiTexture
 {
 	/** Width of the texture, in pixels
 	 *
-	 * If mHeight is zero the texture is compressedin a format
+	 * If mHeight is zero the texture is compressed in a format
 	 * like JPEG. In this case mWidth specifies the size of the
 	 * memory area pcData is pointing to, in bytes.
 	 */

+ 1 - 1
port/jAssimp/src/assimp/Animation.java

@@ -62,6 +62,6 @@ public class Animation extends Mappable {
     }
 
     protected void onMap() throws NativeError {
-        
+
     }
 }

+ 22 - 15
port/jAssimp/src/assimp/CompressedTexture.java

@@ -70,8 +70,8 @@ public class CompressedTexture extends Texture {
         super(parent, index);
 
         // need to get the format of the texture via the JNI
-         if ((m_format = this._NativeGetCTextureFormat(((Scene) this.getParent()).
-                 getImporter().getContext(), this.getArrayIndex())).equals("")) {
+        if ((m_format = this._NativeGetCTextureFormat(((Scene) this.getParent()).
+                getImporter().getContext(), this.getArrayIndex())).equals("")) {
             throw new NativeError("Unable to get the format of the compressed texture");
         }
     }
@@ -80,8 +80,9 @@ public class CompressedTexture extends Texture {
      * Retrieves the format of the texture data. This is
      * the most common file extension of the format (without a
      * dot at the beginning). Examples include dds, png, jpg ...
+     *
      * @return Extension string or null if the format of the texture
-     * data is not known to ASSIMP.
+     *         data is not known to ASSIMP.
      */
     public String getFormat() {
         return m_format;
@@ -89,6 +90,7 @@ public class CompressedTexture extends Texture {
 
     /**
      * Get a pointer to the data of the compressed texture
+     *
      * @return Data poiner
      */
     public byte[] getData() {
@@ -100,11 +102,12 @@ public class CompressedTexture extends Texture {
                 return null;
             }
         }
-        return (byte[])data;
+        return (byte[]) data;
     }
 
     /**
      * Get the length of the data of the compressed texture
+     *
      * @return Data poiner
      */
     public int getLength() {
@@ -113,39 +116,43 @@ public class CompressedTexture extends Texture {
 
     /**
      * Returns 0 for compressed textures
+     *
      * @return n/a
      */
-     @Override
+    @Override
     public int getHeight() {
         return 0;
     }
 
     /**
      * Returns 0 for compressed textures
+     *
      * @return n/a
      */
-     @Override
+    @Override
     public int getWidth() {
         return 0;
     }
 
     /**
      * Returns null for compressed textures
+     *
      * @return n/a
      */
-     @Override
-     public Color getPixel(int x, int y) {
+    @Override
+    public Color getPixel(int x, int y) {
         return null;
-     }
+    }
 
     /**
      * Returns null for compressed textures
+     *
      * @return n/a
      */
     @Override
     public Color[] getColorArray() {
-         return null;
-     }
+        return null;
+    }
 
     /**
      * Internal helper function to map the native texture data into
@@ -162,14 +169,14 @@ public class CompressedTexture extends Texture {
 
         // and copy the native color data to it
         if (0xffffffff == this._NativeMapColorData(
-                ((Scene)this.getParent()).getImporter().getContext(),
-                this.getArrayIndex(),temp)) {
-           throw new NativeError("Unable to map compressed aiTexture into the Java-VM");
+                ((Scene) this.getParent()).getImporter().getContext(),
+                this.getArrayIndex(), temp)) {
+            throw new NativeError("Unable to map compressed aiTexture into the Java-VM");
         }
         DefaultLogger.get().debug("CompressedTexture.onMap successful");
 
         return;
     }
 
-     private native String _NativeGetCTextureFormat(long context, int arrayIndex);
+    private native String _NativeGetCTextureFormat(long context, int arrayIndex);
 }

+ 3 - 0
port/jAssimp/src/assimp/DefaultLogger.java

@@ -390,12 +390,15 @@ public class DefaultLogger implements Logger {
     public static void _NativeCallWriteError(String message) {
         DefaultLogger.get().error(message);
     }
+
     public static void _NativeCallWriteWarn(String message) {
         DefaultLogger.get().warn(message);
     }
+
     public static void _NativeCallWriteInfo(String message) {
         DefaultLogger.get().info(message);
     }
+
     public static void _NativeCallWriteDebug(String message) {
         DefaultLogger.get().debug(message);
     }

+ 4 - 2
port/jAssimp/src/assimp/Importer.java

@@ -188,7 +188,7 @@ public class Importer {
      * @param path Path to the file to be read
      * @return null if the import failed, otherwise a valid Scene instance
      * @throws NativeError This exception is thrown when an unknown error
-     * occurs in the JNI bridge module.
+     *                     occurs in the JNI bridge module.
      */
     public Scene readFile(String path) throws NativeError {
         this.scene = new Scene(this);
@@ -212,6 +212,7 @@ public class Importer {
             else if (step.equals(PostProcessStep.GenFaceNormals)) flags |= 0x20;
             else if (step.equals(PostProcessStep.GenSmoothNormals)) flags |= 0x40;
             else if (step.equals(PostProcessStep.SplitLargeMeshes)) flags |= 0x80;
+            else if (step.equals(PostProcessStep.PreTransformVertices)) flags |= 0x100;
         }
 
         // now load the mesh
@@ -222,7 +223,7 @@ public class Importer {
         }
         // and setup our Scene object
         try {
-          this.scene.construct();
+            this.scene.construct();
         }
         catch (NativeError exc) {
 
@@ -288,6 +289,7 @@ public class Importer {
     /**
      * Retrieves the native context of the class. This is normally the
      * address of the native Importer object.
+     *
      * @return Native context
      */
     public long getContext() {

+ 1 - 0
port/jAssimp/src/assimp/LogStream.java

@@ -56,6 +56,7 @@ public interface LogStream {
 
     /**
      * Override this for your own output implementations
+     *
      * @param message Message to be written to the log stream
      */
     public void write(String message);

+ 19 - 13
port/jAssimp/src/assimp/Logger.java

@@ -54,63 +54,69 @@ public interface Logger {
     /**
      * Debug log message
      */
-    public static final int ERRORSEVERITY_DEBUGGING	= 0x1;
+    public static final int ERRORSEVERITY_DEBUGGING = 0x1;
 
-     /**
+    /**
      * Information log message
      */
-    public static final int ERRORSEVERITY_INFO		= 0x2;
+    public static final int ERRORSEVERITY_INFO = 0x2;
 
-     /**
+    /**
      * Warn log message
      */
-    public static final int ERRORSEVERITY_WARN		= 0x4;
+    public static final int ERRORSEVERITY_WARN = 0x4;
 
-     /**
+    /**
      * Error log message
      */
-    public static final int ERRORSEVERITY_ERR		= 0x8;
+    public static final int ERRORSEVERITY_ERR = 0x8;
 
 
     /**
      * Write a debug message to the log
+     *
      * @param message Message to be logged
      */
     public void debug(String message);
 
     /**
      * Write an error message to the log
+     *
      * @param message Message to be logged
      */
     public void error(String message);
 
     /**
      * Write a warn message to the log
+     *
      * @param message Message to be logged
      */
     public void warn(String message);
 
     /**
      * Write an info message to the log
+     *
      * @param message Message to be logged
      */
     public void info(String message);
 
     /**
      * Attach a logstream to the logger
-     * @param stream Log stream instance
+     *
+     * @param stream   Log stream instance
      * @param severity Error severity. Bitwise combination of the
-     * ERRORSEVERITY_XXX constants. Specify 0 to attach the
-     * stream to all types of log messages.
+     *                 ERRORSEVERITY_XXX constants. Specify 0 to attach the
+     *                 stream to all types of log messages.
      */
     public void attachStream(LogStream stream, int severity);
 
     /**
      * Detach a logstream from the logger
-     * @param stream Log stream instance
+     *
+     * @param stream   Log stream instance
      * @param severity Error severities to detach the stream from.
-     * Bitwise combination of the ERRORSEVERITY_XXX constants.
-     * Specify 0 to detach the stream from all types of log messages.
+     *                 Bitwise combination of the ERRORSEVERITY_XXX constants.
+     *                 Specify 0 to detach the stream from all types of log messages.
      */
     public void detachStream(LogStream stream, int severity);
 }

+ 5 - 1
port/jAssimp/src/assimp/Mappable.java

@@ -64,8 +64,9 @@ public abstract class Mappable {
 
     /**
      * Construction from a given parent object and array index
+     *
      * @param parent Must be valid, null is not allowed
-     * @param index Valied index in the parent's list
+     * @param index  Valied index in the parent's list
      */
     public Mappable(Object parent, int index) {
         m_parent = parent;
@@ -77,6 +78,7 @@ public abstract class Mappable {
      * data into the address space of the Java virtual machine.
      * After this method has been called the class instance must
      * be ready to be used without an underyling native aiScene
+     *
      * @throws NativeError
      */
     protected abstract void onMap() throws NativeError;
@@ -84,6 +86,7 @@ public abstract class Mappable {
 
     /**
      * Retrieve the index ofthe mappable object in the parent mesh
+     *
      * @return Value between 0 and n-1
      */
     public int getArrayIndex() {
@@ -92,6 +95,7 @@ public abstract class Mappable {
 
     /**
      * Provide access to the parent
+     *
      * @return Never null ...
      */
     public Object getParent() {

+ 3 - 3
port/jAssimp/src/assimp/Mesh.java

@@ -782,7 +782,7 @@ public class Mesh extends Mappable {
                 this.m_vFaces)) {
             // this should occur rarely. No need to throw an exception,
             // simply write to log and let the array at 0
-             DefaultLogger.get().error("Unable to map faces into JVM memory");
+            DefaultLogger.get().error("Unable to map faces into JVM memory");
         }
     }
 
@@ -793,7 +793,7 @@ public class Mesh extends Mappable {
                 channel, this.m_avUVs[channel])) {
             // this should occur rarely. No need to throw an exception,
             // simply write to log and let the array at 0.0f
-             DefaultLogger.get().error("Unable to map UV coordinate set " + channel + " into JVM memory");
+            DefaultLogger.get().error("Unable to map UV coordinate set " + channel + " into JVM memory");
         }
     }
 
@@ -804,7 +804,7 @@ public class Mesh extends Mappable {
                 channel, this.m_avColors[channel])) {
             // this should occur rarely. No need to throw an exception,
             // simply write to log and let the array at 0.0f
-             DefaultLogger.get().error("Unable to map vertex color channel " + channel + " into JVM memory");
+            DefaultLogger.get().error("Unable to map vertex color channel " + channel + " into JVM memory");
         }
     }
 

+ 2 - 2
port/jAssimp/src/assimp/NativeError.java

@@ -48,10 +48,10 @@ package assimp;
 public class NativeError extends Exception {
 
     public NativeError() {
-      super("Unknown error");
+        super("Unknown error");
     }
 
     public NativeError(String sz) {
-       super(sz);
+        super(sz);
     }
 }

+ 21 - 6
port/jAssimp/src/assimp/PostProcessStep.java

@@ -52,11 +52,13 @@ package assimp;
  */
 public class PostProcessStep {
 
-    /** Default vertex split limit for the SplitLargeMeshes process
+    /**
+     * Default vertex split limit for the SplitLargeMeshes process
      */
     public static final int DEFAULT_VERTEX_SPLIT_LIMIT = 1000000;
 
-    /** Default triangle split limit for the SplitLargeMeshes process
+    /**
+     * Default triangle split limit for the SplitLargeMeshes process
      */
     public static final int DEFAULT_TRIANGLE_SPLIT_LIMIT = 1000000;
 
@@ -140,13 +142,26 @@ public class PostProcessStep {
             new PostProcessStep("ConvertToLeftHanded ");
 
 
+    /**
+     * Removes the node graph and pretransforms all vertices with the local
+     * transformation matrices of their nodes. The output scene does still
+     * contain nodes, however, there is only a root node with childs, each
+     * one referencing only one mesh, each mesh referencing one material.
+     * For rendering, you can simply render all meshes in order, you don't
+     * need to pay attention to local transformations and the node hierarchy.
+     * Animations are removed during this step.
+     */
+    public static final PostProcessStep PreTransformVertices =
+            new PostProcessStep("PreTransformVertices");
+
+
     /**
      * Set the vertex split limit for the "SplitLargeMeshes" process
      * If a mesh exceeds this limit it will be splitted
      *
      * @param limit New vertex split limit. Pass 0xffffffff to disable
-     * a vertex split limit. However, splitting by triangles is still active
-     * then.
+     *              a vertex split limit. However, splitting by triangles is still active
+     *              then.
      * @return Old vertex split limit
      */
     public static synchronized int setVertexSplitLimit(int limit) {
@@ -163,8 +178,8 @@ public class PostProcessStep {
      * If a mesh exceeds this limit it will be splitted
      *
      * @param limit new triangle split limit. Pass 0xffffffff to disable
-     * a triangle split limit. However, splitting by vertices is still active
-     * then.
+     *              a triangle split limit. However, splitting by vertices is still active
+     *              then.
      * @return Old triangle split limit
      */
     public static synchronized int setTriangleSplitLimit(int limit) {

+ 16 - 16
port/jAssimp/src/assimp/Texture.java

@@ -73,12 +73,12 @@ public class Texture extends Mappable {
         super(parent, index);
 
         long lTemp;
-        if (0x0 == (lTemp = this._NativeGetTextureInfo(((Scene)this.getParent()).
-                getImporter().getContext(),this.getArrayIndex()))) {
+        if (0x0 == (lTemp = this._NativeGetTextureInfo(((Scene) this.getParent()).
+                getImporter().getContext(), this.getArrayIndex()))) {
             throw new NativeError("Unable to get the width and height of the texture");
         }
-        this.width = (int)(lTemp);
-        this.height = (int)(lTemp >> 32);
+        this.width = (int) (lTemp);
+        this.height = (int) (lTemp >> 32);
     }
 
 
@@ -119,16 +119,17 @@ public class Texture extends Mappable {
                 return Color.black;
             }
         }
-        return ((Color[])data)[y * width + x];
+        return ((Color[]) data)[y * width + x];
     }
 
     /**
      * Get a pointer to the color buffer of the texture
+     *
      * @return Array of <code>java.awt.Color</code>, size: width * height
      */
     public Color[] getColorArray() {
 
-         // map the color data in memory if required ...
+        // map the color data in memory if required ...
         if (null == data) {
             try {
                 this.onMap();
@@ -136,7 +137,7 @@ public class Texture extends Mappable {
                 return null;
             }
         }
-        return (Color[])data;
+        return (Color[]) data;
     }
 
     /**
@@ -154,9 +155,9 @@ public class Texture extends Mappable {
         byte[] temp = new byte[(iNumPixels) << 2];
 
         // and copy the native color data to it
-        if (0xffffffff == this._NativeMapColorData(((Scene)this.getParent()).getImporter().getContext(),
-                this.getArrayIndex(),temp)) {
-           throw new NativeError("Unable to map aiTexture into the Java-VM");
+        if (0xffffffff == this._NativeMapColorData(((Scene) this.getParent()).getImporter().getContext(),
+                this.getArrayIndex(), temp)) {
+            throw new NativeError("Unable to map aiTexture into the Java-VM");
         }
 
         DefaultLogger.get().debug("Texture.onMap successful");
@@ -164,7 +165,7 @@ public class Texture extends Mappable {
         // now convert the temporary representation to a Color array
         // (data is given in BGRA order, we need RGBA)
         for (int i = 0, iBase = 0; i < iNumPixels; ++i, iBase += 4) {
-            ((Color[])data)[i] = new Color(temp[iBase + 2], temp[iBase + 1], temp[iBase], temp[iBase + 3]);
+            ((Color[]) data)[i] = new Color(temp[iBase + 2], temp[iBase + 1], temp[iBase], temp[iBase + 3]);
         }
         return;
     }
@@ -175,8 +176,8 @@ public class Texture extends Mappable {
      * the native memory area will be deleted afterwards.
      *
      * @param context Current importer context (imp.hashCode)
-     * @param index Index of the texture in the scene
-     * @param temp Output array. Assumed to be width * height * 4 in size
+     * @param index   Index of the texture in the scene
+     * @param temp    Output array. Assumed to be width * height * 4 in size
      * @return 0xffffffff if an error occured
      */
     protected native int _NativeMapColorData(long context, long index, byte[] temp);
@@ -186,10 +187,9 @@ public class Texture extends Mappable {
      * The method retrieves information on the underlying texture
      *
      * @param context Current importer context (imp.hashCode)
-     * @param index Index of the texture in the scene
+     * @param index   Index of the texture in the scene
      * @return 0x0 if an error occured, otherwise the width in the lower 32 bits
-     * and the height in the higher 32 bits
-     *
+     *         and the height in the higher 32 bits
      */
     private native long _NativeGetTextureInfo(long context, long index);
 }

+ 4 - 5
port/jAssimp/src/assimp/test/DumpToFile.java

@@ -67,8 +67,7 @@ public class DumpToFile {
             arguments = new String[2];
             arguments[0] = s;
             arguments[1] = "output.txt";
-        }
-        else if (2 != arguments.length)return;
+        } else if (2 != arguments.length) return;
 
         FileWriter stream;
         try {
@@ -136,10 +135,10 @@ public class DumpToFile {
              * at the moment!
              */
             float[] positions = mesh.getPositionArray();
-            float[] normals =  mesh.getNormalArray();
+            float[] normals = mesh.getNormalArray();
             float[] tangents = mesh.getTangentArray();
             float[] bitangents = mesh.getBitangentArray();
-            for (int i = 0;i < mesh.getNumVertices();++i) {
+            for (int i = 0; i < mesh.getNumVertices(); ++i) {
 
                 // format: "Vertex pos(x|y|z) nor(x|y|z) tan(x|y|) bit(x|y|z)"
                 // great that this IDE is automatically able to replace + with append ... ;-)
@@ -167,7 +166,7 @@ public class DumpToFile {
             /* Now write a list of all faces in this model
              */
             int[] faces = mesh.getFaceArray();
-            for (int i = 0; i < mesh.getNumFaces();++i) {
+            for (int i = 0; i < mesh.getNumFaces(); ++i) {
                 stream.write(new StringBuilder().append("\tFace (").
                         append(faces[i * 3]).append("|").
                         append(faces[i * 3 + 1]).append("|").

+ 84 - 8
tools/assimp_view/Display.cpp

@@ -139,6 +139,7 @@ int CDisplay::ClearDisplayList(void)
 {
 	// clear the combo box
 	TreeView_DeleteAllItems(GetDlgItem(g_hDlg,IDC_TREE1));
+	this->Reset();
 	return 1;
 }
 //-------------------------------------------------------------------------------
@@ -756,8 +757,31 @@ int CDisplay::OnRender()
 	return 1;
 }	
 //-------------------------------------------------------------------------------
+void UpdateColorFieldsInUI()
+{
+	InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE);
+	InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),NULL,TRUE);
+	InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),NULL,TRUE);
+
+	UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1));
+	UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2));
+	UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3));
+}
+//-------------------------------------------------------------------------------
 int CDisplay::FillDefaultStatistics(void)
 {
+	if (!g_pcAsset)
+	{
+		// clear all stats edit controls
+		SetDlgItemText(g_hDlg,IDC_EVERT,"0");
+		SetDlgItemText(g_hDlg,IDC_EFACE,"0");
+		SetDlgItemText(g_hDlg,IDC_EMAT,"0");
+		SetDlgItemText(g_hDlg,IDC_ENODE,"0");
+		SetDlgItemText(g_hDlg,IDC_ESHADER,"0");
+		SetDlgItemText(g_hDlg,IDC_ETEX,"0");
+		return 1;
+	}
+
 	// get the number of vertices/faces in the model
 	unsigned int iNumVert = 0;
 	unsigned int iNumFaces = 0;
@@ -791,6 +815,7 @@ int CDisplay::FillDefaultStatistics(void)
 	sprintf(szOut,"%.5f",(float)g_fLoadTime);
 	SetDlgItemText(g_hDlg,IDC_ELOAD,szOut);
 
+	UpdateColorFieldsInUI();
 	UpdateWindow(g_hDlg);
 	return 1;
 }
@@ -807,19 +832,24 @@ int CDisplay::Reset(void)
 	return this->OnSetupNormalView();
 }
 //-------------------------------------------------------------------------------
-void UpdateColorFieldsInUI()
+void ShowNormalUIComponents()
 {
-	InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE);
-	InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),NULL,TRUE);
-	InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),NULL,TRUE);
-
-	UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1));
-	UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2));
-	UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3));
+	ShowWindow(GetDlgItem(g_hDlg,IDC_NUMNODES),SW_SHOW);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_ENODEWND),SW_SHOW);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_NUMSHADERS),SW_SHOW);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_LOADTIME),SW_SHOW);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_ESHADER),SW_SHOW);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_ELOAD),SW_SHOW);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),SW_HIDE);
 }
 //-------------------------------------------------------------------------------
 int CDisplay::OnSetupNormalView()
 {
+	if (VIEWMODE_NODE == this->m_iViewMode)
+	{
+		ShowNormalUIComponents();
+	}
+
 	// now ... change the meaning of the statistics fields back
 	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Verts:");
 	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMNODES),"Nodes:");
@@ -848,6 +878,41 @@ int CDisplay::OnSetupNodeView(NodeInfo* pcNew)
 	ai_assert(NULL != pcNew);
 
 	if (this->m_pcCurrentNode == pcNew)return 2;
+	
+	// now ... change the meaning of the statistics fields back
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Verts:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Faces:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"Mats:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Mesh:");
+
+	ShowWindow(GetDlgItem(g_hDlg,IDC_NUMNODES),SW_HIDE);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_ENODEWND),SW_HIDE);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_NUMSHADERS),SW_HIDE);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_LOADTIME),SW_HIDE);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_ESHADER),SW_HIDE);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_ELOAD),SW_HIDE);
+	ShowWindow(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),SW_SHOW);
+
+	char szTemp[1024];
+	sprintf(szTemp,
+		"%.2f %.2f %.2f\r\n"
+		"%.2f %.2f %.2f\r\n"
+		"%.2f %.2f %.2f\r\n"
+		"%.2f %.2f %.2f\r\n",
+		pcNew->psNode->mTransformation.a1,
+		pcNew->psNode->mTransformation.b1,
+		pcNew->psNode->mTransformation.c1,
+		pcNew->psNode->mTransformation.a2,
+		pcNew->psNode->mTransformation.b2,
+		pcNew->psNode->mTransformation.c2,
+		pcNew->psNode->mTransformation.a3,
+		pcNew->psNode->mTransformation.b3,
+		pcNew->psNode->mTransformation.c3,
+		pcNew->psNode->mTransformation.a4,
+		pcNew->psNode->mTransformation.b4,
+		pcNew->psNode->mTransformation.c4);
+	SetWindowText(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),szTemp);
+
 
 	this->m_pcCurrentNode = pcNew;
 	this->SetViewMode(VIEWMODE_NODE);
@@ -861,6 +926,11 @@ int CDisplay::OnSetupMaterialView(MaterialInfo* pcNew)
 
 	if (this->m_pcCurrentMaterial == pcNew)return 2;
 
+	if (VIEWMODE_NODE == this->m_iViewMode)
+	{
+		ShowNormalUIComponents();
+	}
+
 	this->m_pcCurrentMaterial = pcNew;
 	this->SetViewMode(VIEWMODE_MATERIAL);
 
@@ -876,6 +946,12 @@ int CDisplay::OnSetupTextureView(TextureInfo* pcNew)
 	ai_assert(NULL != pcNew);
 
 	if (this->m_pcCurrentTexture == pcNew)return 2;
+
+	if (VIEWMODE_NODE == this->m_iViewMode)
+	{
+		ShowNormalUIComponents();
+	}
+
 	if ((AI_TEXTYPE_OPACITY | 0x40000000) == pcNew->iType)
 	{
 		// for opacity textures display a warn message

+ 12 - 0
tools/assimp_view/MessageProc.cpp

@@ -1329,6 +1329,10 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
 						b = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->z * 255.0f);
 						szText = "B0";
 					}
+					else if (!g_pcAsset)
+					{
+						r = g = b = 150;szText = "-";
+					}
 					else
 					{
 						r = (unsigned char)((g_avLightColors[0] >> 16) & 0xFF);
@@ -1358,6 +1362,10 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
 						b = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->z * 255.0f);
 						szText = "B1";
 					}
+					else if (!g_pcAsset)
+					{
+						r = g = b = 150;szText = "-";
+					}
 					else
 					{
 						r = (unsigned char)((g_avLightColors[1] >> 16) & 0xFF);
@@ -1383,6 +1391,10 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
 						r = g = b = 0;
 						szText = "-";
 					}
+					else if (!g_pcAsset)
+					{
+						r = g = b = 150;szText = "-";
+					}
 					else
 					{
 						r = (unsigned char)((g_avLightColors[2] >> 16) & 0xFF);

+ 1 - 1
tools/assimp_view/Normals.cpp

@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "GenVertexNormalsProcess.h"
 #include "JoinVerticesProcess.h"
 #include "CalcTangentsProcess.h"
-#include "unused/MakeVerboseFormat.h"
+#include "extra/MakeVerboseFormat.h"
 
 namespace AssimpView {
 

BIN
tools/assimp_view/assimp_view.aps


+ 1 - 8
tools/assimp_view/assimp_view.cpp

@@ -268,14 +268,6 @@ int DeleteAsset(void)
 	delete g_pcAsset;
 	g_pcAsset = NULL;
 
-	// clear all stats edit controls
-	SetDlgItemText(g_hDlg,IDC_EVERT,"0");
-	SetDlgItemText(g_hDlg,IDC_EFACE,"0");
-	SetDlgItemText(g_hDlg,IDC_EMAT,"0");
-	SetDlgItemText(g_hDlg,IDC_ENODE,"0");
-	SetDlgItemText(g_hDlg,IDC_ESHADER,"0");
-	SetDlgItemText(g_hDlg,IDC_ETEX,"0");
-
 	// reset the caption of the viewer window
 	SetWindowText(g_hDlg,AI_VIEW_CAPTION_BASE);
 
@@ -284,6 +276,7 @@ int DeleteAsset(void)
 	CDisplay::Instance().ClearDisplayList();
 
 	CMaterialManager::Instance().Reset();
+	UpdateWindow(g_hDlg);
 	return 1;
 }
 

+ 8 - 7
tools/assimp_view/assimp_view.rc

@@ -67,16 +67,16 @@ BEGIN
     CONTROL         "Toggle Wireframe",IDC_TOGGLEWIRE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,183,73,10
     CONTROL         "Disable Materials",IDC_TOGGLEMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,193,69,10
     LTEXT           "Verts:",IDC_NUMVERTS,475,14,47,8
-    LTEXT           "Faces:\t",IDC_NUMFACES,475,26,45,8
+    LTEXT           "Faces:\t",IDC_NUMFACES,539,14,27,8
     LTEXT           "Mats:",IDC_NUMMATS,540,26,26,8
     LTEXT           "FPS:",IDC_FPS,540,51,21,8
     CONTROL         "Display Normals",IDC_TOGGLENORMALS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,203,66,10
     CONTROL         "Toggle AutoRotate",IDC_AUTOROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,257,74,10
     CONTROL         130,IDC_STATIC,"Static",SS_BITMAP,0,360,600,25
     EDITTEXT        IDC_EVERT,504,11,32,12,ES_AUTOHSCROLL | ES_READONLY
-    EDITTEXT        IDC_EFACE,504,24,32,12,ES_AUTOHSCROLL | ES_READONLY
-    EDITTEXT        IDC_EMAT,564,24,27,12,ES_AUTOHSCROLL | ES_READONLY
-    EDITTEXT        IDC_EFPS,564,50,27,12,ES_AUTOHSCROLL | ES_READONLY
+    EDITTEXT        IDC_EFACE,562,11,29,12,ES_AUTOHSCROLL | ES_READONLY
+    EDITTEXT        IDC_EMAT,562,24,29,12,ES_AUTOHSCROLL | ES_READONLY
+    EDITTEXT        IDC_EFPS,562,50,29,12,ES_AUTOHSCROLL | ES_READONLY
     CONTROL         "Rotate light sources",IDC_LIGHTROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,276,74,10
     CONTROL         "2 directional lights",IDC_3LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,213,73,10
     LTEXT           "Time:",IDC_LOADTIME,475,51,46,8
@@ -113,16 +113,17 @@ BEGIN
     CONTROL         149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,583,161,10,9
     CONTROL         149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,584,245,10,9
     CONTROL         149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,584,287,10,9
-    LTEXT           "Nodes:",IDC_NUMNODES,540,13,24,8
-    EDITTEXT        IDC_ENODEWND,564,11,27,12,ES_AUTOHSCROLL | ES_READONLY
+    LTEXT           "Nodes:",IDC_NUMNODES,476,26,24,8
+    EDITTEXT        IDC_ENODEWND,504,24,32,12,ES_AUTOHSCROLL | ES_READONLY
     CONTROL         "",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP,470,74,123,88
     LTEXT           "Mesh:",IDC_NUMMESHES,540,39,20,8
-    EDITTEXT        IDC_EMESH,564,37,27,12,ES_AUTOHSCROLL | ES_READONLY
+    EDITTEXT        IDC_EMESH,562,37,29,12,ES_AUTOHSCROLL | ES_READONLY
     CONTROL         "",IDC_STATIC,"Static",SS_ETCHEDVERT,567,170,1,75
     CONTROL         "Button1",IDC_LCOLOR1,"Button",BS_OWNERDRAW | WS_TABSTOP,570,174,21,17
     CONTROL         "Button1",IDC_LCOLOR2,"Button",BS_OWNERDRAW | WS_TABSTOP,570,194,21,17
     CONTROL         "Button1",IDC_LCOLOR3,"Button",BS_OWNERDRAW | WS_TABSTOP,570,214,21,17
     PUSHBUTTON      "R",IDC_LRESET,576,232,15,11,BS_BOTTOM
+    EDITTEXT        IDC_VIEWMATRIX,475,24,61,38,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | NOT WS_VISIBLE
 END
 
 IDD_LOADDIALOG DIALOGEX 0, 0, 278, 99

+ 3 - 1
tools/assimp_view/resource.h

@@ -97,6 +97,8 @@
 #define IDC_LCOLOR3                     1044
 #define IDC_LRESET                      1046
 #define IDC_NUMMESHES                   1047
+#define IDC_VIEWMAT                     1048
+#define IDC_VIEWMATRIX                  1048
 #define ID_VIEWER_OPEN                  32771
 #define ID_VIEWER_CLOSETHIS             32772
 #define ID_VIEWER_CLOSEASSET            32773
@@ -158,7 +160,7 @@
 #define _APS_NO_MFC                     1
 #define _APS_NEXT_RESOURCE_VALUE        158
 #define _APS_NEXT_COMMAND_VALUE         32823
-#define _APS_NEXT_CONTROL_VALUE         1048
+#define _APS_NEXT_CONTROL_VALUE         1049
 #define _APS_NEXT_SYMED_VALUE           110
 #endif
 #endif

+ 14 - 2
workspaces/vc8/assimp.vcproj

@@ -588,6 +588,10 @@
 				RelativePath="..\..\code\MaterialSystem.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\code\PretransformVertices.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\code\SpatialSort.h"
 				>
@@ -719,6 +723,10 @@
 			<Filter
 				Name="MDLLoader"
 				>
+				<File
+					RelativePath="..\..\code\HalfLifeFileData.h"
+					>
+				</File>
 				<File
 					RelativePath="..\..\code\MDLDefaultColorMap.h"
 					>
@@ -804,7 +812,7 @@
 				Name="extra"
 				>
 				<File
-					RelativePath="..\..\code\unused\MakeVerboseFormat.h"
+					RelativePath="..\..\code\extra\MakeVerboseFormat.h"
 					>
 				</File>
 			</Filter>
@@ -864,6 +872,10 @@
 				RelativePath="..\..\code\MaterialSystem.cpp"
 				>
 			</File>
+			<File
+				RelativePath="..\..\code\PretransformVertices.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\..\code\SpatialSort.cpp"
 				>
@@ -1008,7 +1020,7 @@
 				Name="extra"
 				>
 				<File
-					RelativePath="..\..\code\unused\MakeVerboseFormat.cpp"
+					RelativePath="..\..\code\extra\MakeVerboseFormat.cpp"
 					>
 				</File>
 			</Filter>