Kaynağa Gözat

- Bugfix: XFileParser handles vertex colors correctly now. Fixes exception in sheep.x import
- Added support for separate normal map filename tag in XFile material list
- shortened texture type determination in XFile loader while I was there
- Bugfix: ValidateDataStructure wrongly flagged animations with zero duration as error

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

ulfjorensen 17 yıl önce
ebeveyn
işleme
b17a5e3b69

+ 3 - 1
code/ValidateDataStructure.cpp

@@ -428,7 +428,9 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
 		}
 	}
 	else this->ReportError("aiAnimation::mNumBones is 0. At least one bone animation channel must be there.");
-	if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero");
+
+	// Animation duration is allowed to be zero in cases where the anim contains only a single key frame.
+	// if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero");
 }
 // ------------------------------------------------------------------------------------------------
 void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,

+ 13 - 1
code/XFileHelper.h

@@ -62,6 +62,18 @@ struct Face
 	std::vector<unsigned int> mIndices;
 };
 
+/** Helper structure representing a texture filename inside a material and its potential source */
+struct TexEntry
+{
+	std::string mName;
+	bool mIsNormalMap; // true if the texname was specified in a NormalmapFilename tag
+
+	TexEntry() { mIsNormalMap = false; }
+	TexEntry( const std::string& pName, bool pIsNormalMap = false) 
+		: mName( pName), mIsNormalMap( pIsNormalMap) 
+	{ /* done */ }
+};
+
 /** Helper structure representing a XFile material */
 struct Material
 {
@@ -71,7 +83,7 @@ struct Material
 	float mSpecularExponent;
 	aiColor3D mSpecular;
 	aiColor3D mEmissive;
-	std::vector<std::string> mTextures;
+	std::vector<TexEntry> mTextures;
 
 	Material() { mIsReference = false; }
 };

+ 42 - 122
code/XFileImporter.cpp

@@ -580,12 +580,15 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
 		// texture, if there is one
 		if (1 == oldMat.mTextures.size())
 		{
-			if (oldMat.mTextures[0].length())
+			const XFile::TexEntry& otex = oldMat.mTextures.back();
+			if (otex.mName.length())
 			{
 				// if there is only one texture assume it contains the diffuse color
-				aiString tex;
-				tex.Set( oldMat.mTextures[0]);
-				mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
+				aiString tex( otex.mName);
+				if( otex.mIsNormalMap)
+					mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(0));
+				else
+					mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
 			}
 		}
 		else
@@ -595,7 +598,8 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
 			unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0;
 			for( unsigned int b = 0; b < oldMat.mTextures.size(); b++)
 			{
-				std::string sz = oldMat.mTextures[b];
+				const XFile::TexEntry& otex = oldMat.mTextures[b];
+				std::string sz = otex.mName;
 				if (!sz.length())continue;
 
 				char key[256];
@@ -616,151 +620,67 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
 					sz[sExt] = '\0';
 				}
 
+				// convert to lower case for easier comparision
+				for( unsigned int c = 0; c < sz.length(); c++)
+					if( isalpha( sz[c]))
+						sz[c] = tolower( sz[c]);
+
 				// bump map
-				std::string::size_type s2 = sz.find("bump",s);
-				if (std::string::npos == s2)
-				{
-					if (std::string::npos == (s2 = sz.find("BUMP",s)))
-					{
-						if (std::string::npos == (s2 = sz.find("Bump",s)))
-						{
-							if (std::string::npos == (s2 = sz.find("height",s)))
-							{
-								if (std::string::npos == (s2 = sz.find("HEIGHT",s)))
-								{
-									s2 = sz.find("Height",s);
-								}
-							}
-						}
-					}
-				}
-				if (std::string::npos != s2)
+				if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s))
 				{
 #if _MSC_VER >= 1400
 					::sprintf_s(key,AI_MATKEY_TEXTURE_HEIGHT_ "[%i]",iHM++);
 #else
 					::sprintf(key,AI_MATKEY_TEXTURE_HEIGHT_ "[%i]",iHM++);
 #endif
-				}
-				else
+				} else
+				if (otex.mIsNormalMap || std::string::npos != sz.find( "normal", s) || std::string::npos != sz.find("nm", s))
 				{
-					// Normal map
-					std::string::size_type s2 = sz.find("normal",s);
-					if (std::string::npos == s2)
-					{
-						if (std::string::npos == (s2 = sz.find("NORMAL",s)))
-						{
-							if (std::string::npos == (s2 = sz.find("nm",s)))
-							{ 
-								if (std::string::npos == (s2 = sz.find("Normal",s)))
-								{
-									s2 = sz.find("NM",s); 
-								}
-							}
-						}
-					}
-					if (std::string::npos != s2)
-					{
 #if _MSC_VER >= 1400
-						::sprintf_s(key,AI_MATKEY_TEXTURE_NORMALS_ "[%i]",iNM++);
+					::sprintf_s(key,AI_MATKEY_TEXTURE_NORMALS_ "[%i]",iNM++);
 #else
-						::sprintf(key,AI_MATKEY_TEXTURE_NORMALS_ "[%i]",iNM++);
+					::sprintf(key,AI_MATKEY_TEXTURE_NORMALS_ "[%i]",iNM++);
 #endif
-					}
-					else
-					{
-
-						// specular color texture (not unique, too. Could
-						// also be the material's shininess)
-						std::string::size_type s2 = sz.find("spec",s);
-						if (std::string::npos == s2)
-						{
-							if (std::string::npos == (s2 = sz.find("Spec",s)))
-							{
-								if (std::string::npos == (sz.find("SPEC",s)))
-								{
-									if (std::string::npos == (s2 = sz.find("Glanz",s)))
-									{
-										s2 = sz.find("glanz",s);
-									}
-								}
-							}
-						}
-						if (std::string::npos != s2)
-						{
+				} else
+				if (std::string::npos != sz.find( "spec", s) || std::string::npos != sz.find( "glanz", s))
+				{
 #if _MSC_VER >= 1400
-							::sprintf_s(key,AI_MATKEY_TEXTURE_SPECULAR_ "[%i]",iSM++);
+					::sprintf_s(key,AI_MATKEY_TEXTURE_SPECULAR_ "[%i]",iSM++);
 #else
-							::sprintf(key,AI_MATKEY_TEXTURE_SPECULAR_ "[%i]",iSM++);
+					::sprintf(key,AI_MATKEY_TEXTURE_SPECULAR_ "[%i]",iSM++);
 #endif
-						}
-						else
-						{
-							// ambient color texture
-							std::string::size_type s2 = sz.find("ambi",s);
-							if (std::string::npos == s2)
-							{
-								if (std::string::npos == (s2 = sz.find("AMBI",s)))
-								{
-									if (std::string::npos == (s2 = sz.find("env",s)))
-									{
-										s2 = sz.find("Ambi",s);
-									}
-								}
-							}
-							if (std::string::npos != s2)
-							{
+				} else
+				if (std::string::npos != sz.find( "ambi", s) || std::string::npos != sz.find( "env", s))
+				{
 #if _MSC_VER >= 1400
-								::sprintf_s(key,AI_MATKEY_TEXTURE_AMBIENT_ "[%i]",iAM++);
+					::sprintf_s(key,AI_MATKEY_TEXTURE_AMBIENT_ "[%i]",iAM++);
 #else
-								::sprintf(key,AI_MATKEY_TEXTURE_AMBIENT_ "[%i]",iAM++);
+					::sprintf(key,AI_MATKEY_TEXTURE_AMBIENT_ "[%i]",iAM++);
 #endif
-							}
-							else
-							{
-								// emissive color texture
-								std::string::size_type s2 = sz.find("emissive",s);
-								if (std::string::npos == s2)
-								{
-									s2 = sz.find("EMISSIVE",s);
-									if (std::string::npos == s2)
-									{
-										// self illumination
-										if (std::string::npos == (s2 = sz.find("self",s)))
-										{
-											s2 = sz.find("Emissive",s);
-										}
-									}
-								}
-								if (std::string::npos != s2)
-								{
+				} else
+				if (std::string::npos != sz.find( "emissive", s) || std::string::npos != sz.find( "self", s))
+				{
 #if _MSC_VER >= 1400
-									::sprintf_s(key,AI_MATKEY_TEXTURE_EMISSIVE_ "[%i]",iEM++);
+					::sprintf_s(key,AI_MATKEY_TEXTURE_EMISSIVE_ "[%i]",iEM++);
 #else
-									::sprintf(key,AI_MATKEY_TEXTURE_EMISSIVE_ "[%i]",iEM++);
+					::sprintf(key,AI_MATKEY_TEXTURE_EMISSIVE_ "[%i]",iEM++);
 #endif
-								}
-								else
-								{
-									// assume it is a diffuse texture
+				} else
+				{
+				// assume it is a diffuse texture
 #if _MSC_VER >= 1400
-									::sprintf_s(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++);
+					::sprintf_s(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++);
 #else
-									::sprintf(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++);
+					::sprintf(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++);
 #endif
-								}
-							}
-						}
-					}
 				}
 
-				aiString tex;
-				tex.Set( oldMat.mTextures[b] );
-
+				// place texture filename property under the corresponding name
+				aiString tex( oldMat.mTextures[b].mName);
 				mat->AddProperty( &tex, key);
 			}
-
 		}
+
 		pScene->mMaterials[pScene->mNumMaterials] = mat;
 		mImportedMats[oldMat.mName] = pScene->mNumMaterials;
 		pScene->mNumMaterials++;

+ 13 - 2
code/XFileParser.cpp

@@ -466,9 +466,9 @@ void XFileParser::ParseDataObjectMeshVertexColors( Mesh* pMesh)
 			ThrowException( "Vertex color index out of bounds");
 
 		colors[index] = ReadRGBA();
+		CheckForSeparator();
 	}
 
-	CheckForSemicolon();
 	CheckForClosingBrace();
 }
 
@@ -569,7 +569,14 @@ void XFileParser::ParseDataObjectMaterial( Material* pMaterial)
 			// some exporters write "TextureFileName" instead.
 			std::string texname;
 			ParseDataObjectTextureFilename( texname);
-			pMaterial->mTextures.push_back( texname);
+			pMaterial->mTextures.push_back( TexEntry( texname));
+		} else
+		if( objectName == "NormalmapFilename" || objectName == "NormalmapFileName")
+		{
+			// one exporter writes out the normal map in a separate filename tag
+			std::string texname;
+			ParseDataObjectTextureFilename( texname);
+			pMaterial->mTextures.push_back( TexEntry( texname, true));
 		} else
 		{
 			DefaultLogger::get()->warn("Unknown data object in material in x file");
@@ -755,6 +762,10 @@ void XFileParser::ParseDataObjectTextureFilename( std::string& pName)
 	{
 		DefaultLogger::get()->warn("Length of texture file name is zero. Skipping this texture.");
 	}
+
+	// some exporters write double backslash paths out. We simply replace them if we find them
+	while( pName.find( "\\\\") != std::string::npos)
+		pName.replace( pName.find( "\\\\"), 2, "\\");
 }
 
 // ------------------------------------------------------------------------------------------------

+ 9 - 1
include/aiTypes.h

@@ -140,7 +140,7 @@ struct aiString
 		data[0] = '\0';
 	}
 
-	//! construction from a given std::string
+	//! Copy constructor
 	inline aiString(const aiString& rOther) : 
 		length(rOther.length) 
 	{
@@ -148,6 +148,14 @@ struct aiString
 		this->data[this->length] = '\0';
 	}
 
+	//! Constructor from std::string
+	inline aiString(const std::string& pString) : 
+		length(pString.length()) 
+	{
+		memcpy( data, pString.c_str(), length);
+		data[length] = '\0';
+	}
+
 	//! copy a std::string to the aiString
 	void Set( const std::string& pString)
 	{