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

pull/19/head
ulf 2013-02-12 13:13:12 +01:00
parent 0f781516bf
commit 18f01268e6
4 changed files with 48 additions and 39 deletions

View File

@ -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 */

View File

@ -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]; XFile::Mesh* sourceMesh = pMeshes[a];
// first convert its materials so that we can find them when searching by name afterwards // 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 // find the material in the scene's material list. Either own material
// or referenced material, it should already be found there // 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); mesh->mMaterialIndex = sourceMesh->mMaterials[b].sceneIndex;
if( matIt == mImportedMats.end())
mesh->mMaterialIndex = 0;
else
mesh->mMaterialIndex = matIt->second;
} 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++; numNewMaterials++;
if( numMaterials == 0)
return;
// 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
if( numNewMaterials > 0 )
{
aiMaterial** prevMats = pScene->mMaterials; aiMaterial** prevMats = pScene->mMaterials;
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numMaterials]; pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numNewMaterials];
if( prevMats) if( prevMats)
{ {
memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*)); memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*));
delete [] prevMats; 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)
{
// 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; 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++;
} }
} }

View File

@ -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, void CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData);
const 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, void ConvertMaterials( aiScene* pScene, std::vector<XFile::Material>& pMaterials);
const 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

View File

@ -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();