فهرست منبع

- rewrote the XFileLoader material management to handle meshes with dummy material names correctly.

ulf 12 سال پیش
والد
کامیت
18f01268e6
4فایلهای تغییر یافته به همراه48 افزوده شده و 39 حذف شده
  1. 3 1
      code/XFileHelper.h
  2. 42 30
      code/XFileImporter.cpp
  3. 2 7
      code/XFileImporter.h
  4. 1 1
      code/XFileParser.h

+ 3 - 1
code/XFileHelper.h

@@ -85,7 +85,9 @@ struct Material
 	aiColor3D mEmissive;
 	aiColor3D mEmissive;
 	std::vector<TexEntry> mTextures;
 	std::vector<TexEntry> mTextures;
 
 
-	Material() { mIsReference = false; }
+  size_t sceneIndex; ///< the index under which it was stored in the scene's material list
+
+	Material() { mIsReference = false; sceneIndex = SIZE_MAX; }
 };
 };
 
 
 /** Helper structure to represent a bone weight */
 /** Helper structure to represent a bone weight */

+ 42 - 30
code/XFileImporter.cpp

@@ -110,10 +110,6 @@ void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, I
 	if( fileSize < 16)
 	if( fileSize < 16)
 		throw DeadlyImportError( "XFile is too small.");
 		throw DeadlyImportError( "XFile is too small.");
 
 
-	// need to clear members - this method might be called multiple
-	// times on a single XFileImporter instance.
-	mImportedMats.clear();
-
 	// in the hope that binary files will never start with a BOM ...
 	// in the hope that binary files will never start with a BOM ...
 	mBuffer.resize( fileSize + 1);
 	mBuffer.resize( fileSize + 1);
 	file->Read( &mBuffer.front(), 1, fileSize);
 	file->Read( &mBuffer.front(), 1, fileSize);
@@ -132,7 +128,7 @@ void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, I
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructs the return data structure out of the imported data.
 // Constructs the return data structure out of the imported data.
-void XFileImporter::CreateDataRepresentationFromImport( aiScene* pScene, const XFile::Scene* pData)
+void XFileImporter::CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData)
 {
 {
 	// Read the global materials first so that meshes referring to them can find them later
 	// Read the global materials first so that meshes referring to them can find them later
 	ConvertMaterials( pScene, pData->mGlobalMaterials);
 	ConvertMaterials( pScene, pData->mGlobalMaterials);
@@ -233,8 +229,8 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
 	std::vector<aiMesh*> meshes;
 	std::vector<aiMesh*> meshes;
 	for( unsigned int a = 0; a < pMeshes.size(); a++)
 	for( unsigned int a = 0; a < pMeshes.size(); a++)
 	{
 	{
-		const XFile::Mesh* sourceMesh = pMeshes[a];
-		// first convert its materials so that we can find them when searching by name afterwards
+		XFile::Mesh* sourceMesh = pMeshes[a];
+		// first convert its materials so that we can find them with their index afterwards
 		ConvertMaterials( pScene, sourceMesh->mMaterials);
 		ConvertMaterials( pScene, sourceMesh->mMaterials);
 
 
 		unsigned int numMaterials = std::max( (unsigned int)sourceMesh->mMaterials.size(), 1u);
 		unsigned int numMaterials = std::max( (unsigned int)sourceMesh->mMaterials.size(), 1u);
@@ -272,15 +268,11 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
 			aiMesh* mesh = new aiMesh;
 			aiMesh* mesh = new aiMesh;
 			meshes.push_back( mesh);
 			meshes.push_back( mesh);
 
 
-			// find the material by name in the scene's material list. Either own material
-			// or referenced material, it should already be found there
+			// find the material in the scene's material list. Either own material
+			// or referenced material, it should already have a valid index
 			if( sourceMesh->mFaceMaterials.size() > 0)
 			if( sourceMesh->mFaceMaterials.size() > 0)
 			{
 			{
-				std::map<std::string, unsigned int>::const_iterator matIt = mImportedMats.find( sourceMesh->mMaterials[b].mName);
-				if( matIt == mImportedMats.end())
-					mesh->mMaterialIndex = 0;
-				else
-					mesh->mMaterialIndex = matIt->second;
+        mesh->mMaterialIndex = sourceMesh->mMaterials[b].sceneIndex;
 			} else
 			} else
 			{
 			{
 				mesh->mMaterialIndex = 0;
 				mesh->mMaterialIndex = 0;
@@ -554,32 +546,52 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Converts all materials in the given array and stores them in the scene's material list.
 // Converts all materials in the given array and stores them in the scene's material list.
-void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::Material>& pMaterials)
+void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Material>& pMaterials)
 {
 {
 	// count the non-referrer materials in the array
 	// count the non-referrer materials in the array
-	unsigned int numMaterials = 0;
+	unsigned int numNewMaterials = 0;
 	for( unsigned int a = 0; a < pMaterials.size(); a++)
 	for( unsigned int a = 0; a < pMaterials.size(); a++)
 		if( !pMaterials[a].mIsReference)
 		if( !pMaterials[a].mIsReference)
-			numMaterials++;
-
-	if( numMaterials == 0)
-		return;
+			numNewMaterials++;
 
 
 	// resize the scene's material list to offer enough space for the new materials
 	// resize the scene's material list to offer enough space for the new materials
-	aiMaterial** prevMats = pScene->mMaterials;
-	pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numMaterials];
-	if( prevMats)
-	{
-		memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*));
-		delete [] prevMats;
-	}
+  if( numNewMaterials > 0 )
+  {
+	  aiMaterial** prevMats = pScene->mMaterials;
+	  pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numNewMaterials];
+	  if( prevMats)
+	  {
+		  memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*));
+		  delete [] prevMats;
+	  }
+  }
 
 
 	// convert all the materials given in the array
 	// convert all the materials given in the array
 	for( unsigned int a = 0; a < pMaterials.size(); a++)
 	for( unsigned int a = 0; a < pMaterials.size(); a++)
 	{
 	{
-		const XFile::Material& oldMat = pMaterials[a];
+		XFile::Material& oldMat = pMaterials[a];
 		if( oldMat.mIsReference)
 		if( oldMat.mIsReference)
-			continue;
+    {
+      // find the material it refers to by name, and store its index
+      for( size_t a = 0; a < pScene->mNumMaterials; ++a )
+      {
+        aiString name;
+        pScene->mMaterials[a]->Get( AI_MATKEY_NAME, name);
+        if( strcmp( name.C_Str(), oldMat.mName.data()) == 0 )
+        {
+          oldMat.sceneIndex = a;
+          break;
+        }
+      }
+
+      if( oldMat.sceneIndex == SIZE_MAX )
+      {
+        DefaultLogger::get()->warn( boost::str( boost::format( "Could not resolve global material reference \"%s\"") % oldMat.mName));
+        oldMat.sceneIndex = 0;
+      }
+
+      continue;
+    }
 
 
 		aiMaterial* mat = new aiMaterial;
 		aiMaterial* mat = new aiMaterial;
 		aiString name;
 		aiString name;
@@ -678,7 +690,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
 		}
 		}
 
 
 		pScene->mMaterials[pScene->mNumMaterials] = mat;
 		pScene->mMaterials[pScene->mNumMaterials] = mat;
-		mImportedMats[oldMat.mName] = pScene->mNumMaterials;
+		oldMat.sceneIndex = pScene->mNumMaterials;
 		pScene->mNumMaterials++;
 		pScene->mNumMaterials++;
 	}
 	}
 }
 }

+ 2 - 7
code/XFileImporter.h

@@ -99,8 +99,7 @@ protected:
 	 * @param pData The imported data in the internal temporary 
 	 * @param pData The imported data in the internal temporary 
 	 *   representation.
 	 *   representation.
 	 */
 	 */
-	void CreateDataRepresentationFromImport( aiScene* pScene, 
-		const XFile::Scene* pData);
+	void CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData);
 
 
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
 	/** Recursively creates scene nodes from the imported hierarchy.
 	/** Recursively creates scene nodes from the imported hierarchy.
@@ -139,15 +138,11 @@ protected:
 	 * @param pScene The scene to hold the converted materials.
 	 * @param pScene The scene to hold the converted materials.
 	 * @param pMaterials The material array to convert.
 	 * @param pMaterials The material array to convert.
 	 */
 	 */
-	void ConvertMaterials( aiScene* pScene, 
-		const std::vector<XFile::Material>& pMaterials);
+	void ConvertMaterials( aiScene* pScene, std::vector<XFile::Material>& pMaterials);
 
 
 protected:
 protected:
 	/** Buffer to hold the loaded file */
 	/** Buffer to hold the loaded file */
 	std::vector<char> mBuffer;
 	std::vector<char> mBuffer;
-
-	/** Imported materials: index in the scene's material list by name */
-	std::map<std::string, unsigned int> mImportedMats;
 };
 };
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp

+ 1 - 1
code/XFileParser.h

@@ -74,7 +74,7 @@ public:
 	~XFileParser();
 	~XFileParser();
 
 
 	/** Returns the temporary representation of the imported data */
 	/** Returns the temporary representation of the imported data */
-	const XFile::Scene* GetImportedData() const { return mScene; }
+	XFile::Scene* GetImportedData() const { return mScene; }
 
 
 protected:
 protected:
 	void ParseFile();
 	void ParseFile();