- rewrote the XFileLoader material management to handle meshes with dummy material names correctly.
parent
0f781516bf
commit
18f01268e6
|
@ -85,7 +85,9 @@ struct Material
|
|||
aiColor3D mEmissive;
|
||||
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 */
|
||||
|
|
|
@ -110,10 +110,6 @@ void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
|||
if( fileSize < 16)
|
||||
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 ...
|
||||
mBuffer.resize( fileSize + 1);
|
||||
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.
|
||||
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
|
||||
ConvertMaterials( pScene, pData->mGlobalMaterials);
|
||||
|
@ -233,8 +229,8 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
|
|||
std::vector<aiMesh*> meshes;
|
||||
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);
|
||||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
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.
|
||||
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
|
||||
unsigned int numMaterials = 0;
|
||||
unsigned int numNewMaterials = 0;
|
||||
for( unsigned int a = 0; a < pMaterials.size(); a++)
|
||||
if( !pMaterials[a].mIsReference)
|
||||
numMaterials++;
|
||||
|
||||
if( numMaterials == 0)
|
||||
return;
|
||||
numNewMaterials++;
|
||||
|
||||
// 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
|
||||
for( unsigned int a = 0; a < pMaterials.size(); a++)
|
||||
{
|
||||
const XFile::Material& oldMat = pMaterials[a];
|
||||
XFile::Material& oldMat = pMaterials[a];
|
||||
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;
|
||||
aiString name;
|
||||
|
@ -678,7 +690,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
|
|||
}
|
||||
|
||||
pScene->mMaterials[pScene->mNumMaterials] = mat;
|
||||
mImportedMats[oldMat.mName] = pScene->mNumMaterials;
|
||||
oldMat.sceneIndex = pScene->mNumMaterials;
|
||||
pScene->mNumMaterials++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,8 +99,7 @@ protected:
|
|||
* @param pData The imported data in the internal temporary
|
||||
* representation.
|
||||
*/
|
||||
void CreateDataRepresentationFromImport( aiScene* pScene,
|
||||
const XFile::Scene* pData);
|
||||
void CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Recursively creates scene nodes from the imported hierarchy.
|
||||
|
@ -139,15 +138,11 @@ protected:
|
|||
* @param pScene The scene to hold the converted materials.
|
||||
* @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:
|
||||
/** Buffer to hold the loaded file */
|
||||
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
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
~XFileParser();
|
||||
|
||||
/** Returns the temporary representation of the imported data */
|
||||
const XFile::Scene* GetImportedData() const { return mScene; }
|
||||
XFile::Scene* GetImportedData() const { return mScene; }
|
||||
|
||||
protected:
|
||||
void ParseFile();
|
||||
|
|
Loading…
Reference in New Issue