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

pull/709/head
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

View File

@ -0,0 +1,11 @@
newmtl mtl
Ka 1.000 1.000 1.000
Kd 1.000 1.000 1.000
Ns 200.000
Ks 0.050 0.050 0.050
newmtl mtl2
Ka 1.000 1.000 1.000
Kd 1.000 1.000 1.000
Ns 16.000
Ks 0.375 0.375 0.375

View File

@ -0,0 +1,44 @@
mtllib cube_usemtl.mtl
g cube
v 0.0 0.0 0.0
v 0.0 0.0 1.0
v 0.0 1.0 0.0
v 0.0 1.0 1.0
v 1.0 0.0 0.0
v 1.0 0.0 1.0
v 1.0 1.0 0.0
v 1.0 1.0 1.0
vn 0.0 0.0 1.0
vn 0.0 0.0 -1.0
vn 0.0 1.0 0.0
vn 0.0 -1.0 0.0
vn 1.0 0.0 0.0
vn -1.0 0.0 0.0
usemtl mtl3
f 1//2 7//2 5//2
usemtl mtl3
f 1//2 3//2 7//2
usemtl mtl
f 1//6 4//6 3//6
usemtl mtl
f 1//6 2//6 4//6
usemtl mtl
f 3//3 8//3 7//3
usemtl mtl2
f 3//3 4//3 8//3
usemtl mtl2
f 5//5 7//5 8//5
usemtl mtl2
f 5//5 8//5 6//5
usemtl mtl2
f 1//4 5//4 6//4
usemtl mtl
f 1//4 6//4 2//4
usemtl mtl
f 2//1 6//1 8//1
usemtl mtl
f 2//1 8//1 4//1