this patch fixes multiple objects generation in OBJ reader if faces are prepended with 'usemtl' line

This commit is contained in:
Vitaly Ovchinnikov
2015-12-13 22:54:50 +13:00
parent 078dd0c08b
commit 6214fbfbbe
3 changed files with 85 additions and 24 deletions

View File

@@ -457,15 +457,6 @@ void ObjFileParser::getFace(aiPrimitiveType type)
// Get values for a new material description
void ObjFileParser::getMaterialDesc()
{
// Each material request a new object.
// Sometimes the object is already created (see 'o' tag by example), but it is not initialized !
// So, we create a new object only if the current on is already initialized !
if (m_pModel->m_pCurrent != NULL &&
( m_pModel->m_pCurrent->m_Meshes.size() > 1 ||
(m_pModel->m_pCurrent->m_Meshes.size() == 1 && m_pModel->m_Meshes[m_pModel->m_pCurrent->m_Meshes[0]]->m_Faces.size() != 0) )
)
m_pModel->m_pCurrent = NULL;
// Get next data for material data
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
if (m_DataIt == m_DataItEnd) {
@@ -477,25 +468,40 @@ void ObjFileParser::getMaterialDesc()
++m_DataIt;
}
// In some cases we should ignore this 'usemtl' command, this variable helps us to do so
bool skip = false;
// Get name
std::string strName(pStart, &(*m_DataIt));
if ( strName.empty())
return;
if (strName.empty())
skip = true;
// Search for material
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
if ( it == m_pModel->m_MaterialMap.end() ) {
// Not found, use default material
m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
} else {
// Found, using detected material
m_pModel->m_pCurrentMaterial = (*it).second;
if ( needsNewMesh( strName ))
// If the current mesh has the same material, we simply ignore that 'usemtl' command
// There is no need to create another object or even mesh here
if (m_pModel->m_pCurrentMaterial && m_pModel->m_pCurrentMaterial->MaterialName == aiString(strName))
skip = true;
if (!skip)
{
// Search for material
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find(strName);
if (it == m_pModel->m_MaterialMap.end())
{
createMesh( strName );
// Not found, use default material
m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
strName = m_pModel->m_pDefaultMaterial->MaterialName.C_Str();
}
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName );
else
{
// Found, using detected material
m_pModel->m_pCurrentMaterial = (*it).second;
}
if (needsNewMesh(strName))
createMesh();
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strName);
}
// Skip rest of line
@@ -759,7 +765,7 @@ bool ObjFileParser::needsNewMesh( const std::string &rMaterialName )
bool newMat = false;
int matIdx = getMaterialIndex( rMaterialName );
int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) || curMatIdx != matIdx )
if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) && curMatIdx != matIdx )
{
// New material -> only one material per mesh, so we need to create a new
// material