From 6214fbfbbe6b421088860a6a503fb5dbed6fbe17 Mon Sep 17 00:00:00 2001 From: Vitaly Ovchinnikov Date: Sun, 13 Dec 2015 22:54:50 +1300 Subject: [PATCH] this patch fixes multiple objects generation in OBJ reader if faces are prepended with 'usemtl' line --- code/ObjFileParser.cpp | 54 ++++++++++++++++++--------------- test/models/OBJ/cube_usemtl.mtl | 11 +++++++ test/models/OBJ/cube_usemtl.obj | 44 +++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 24 deletions(-) create mode 100644 test/models/OBJ/cube_usemtl.mtl create mode 100644 test/models/OBJ/cube_usemtl.obj diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index 83262b5d4..4d8b20c46 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -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(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::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::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 diff --git a/test/models/OBJ/cube_usemtl.mtl b/test/models/OBJ/cube_usemtl.mtl new file mode 100644 index 000000000..040e0adad --- /dev/null +++ b/test/models/OBJ/cube_usemtl.mtl @@ -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 diff --git a/test/models/OBJ/cube_usemtl.obj b/test/models/OBJ/cube_usemtl.obj new file mode 100644 index 000000000..d840a28fc --- /dev/null +++ b/test/models/OBJ/cube_usemtl.obj @@ -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