diff options
Diffstat (limited to 'src/3rdparty/assimp/code/ObjFileParser.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/ObjFileParser.cpp | 454 |
1 files changed, 230 insertions, 224 deletions
diff --git a/src/3rdparty/assimp/code/ObjFileParser.cpp b/src/3rdparty/assimp/code/ObjFileParser.cpp index 79bc299bc..d89d52977 100644 --- a/src/3rdparty/assimp/code/ObjFileParser.cpp +++ b/src/3rdparty/assimp/code/ObjFileParser.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -38,8 +39,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ - - #ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER #include "ObjFileParser.h" @@ -47,23 +46,33 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ObjTools.h" #include "ObjFileData.h" #include "ParsingUtils.h" -#include "DefaultIOSystem.h" #include "BaseImporter.h" +#include <assimp/DefaultIOSystem.h> #include <assimp/DefaultLogger.hpp> #include <assimp/material.h> #include <assimp/Importer.hpp> #include <cstdlib> - namespace Assimp { const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME; -// ------------------------------------------------------------------- -// Constructor with loaded data and directories. -ObjFileParser::ObjFileParser(std::vector<char> &data, const std::string &modelName, IOSystem *io, ProgressHandler* progress, const std::string &originalObjFileName) : - m_DataIt(data.begin()), - m_DataItEnd(data.end()), +ObjFileParser::ObjFileParser() +: m_DataIt() +, m_DataItEnd() +, m_pModel( NULL ) +, m_uiLine( 0 ) +, m_pIO( nullptr ) +, m_progress( nullptr ) +, m_originalObjFileName() { + // empty +} + +ObjFileParser::ObjFileParser( IOStreamBuffer<char> &streamBuffer, const std::string &modelName, + IOSystem *io, ProgressHandler* progress, + const std::string &originalObjFileName) : + m_DataIt(), + m_DataItEnd(), m_pModel(NULL), m_uiLine(0), m_pIO( io ), @@ -83,71 +92,68 @@ ObjFileParser::ObjFileParser(std::vector<char> &data, const std::string &modelNa m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial; // Start parsing the file - parseFile(); + parseFile( streamBuffer ); } -// ------------------------------------------------------------------- -// Destructor -ObjFileParser::~ObjFileParser() -{ +ObjFileParser::~ObjFileParser() { delete m_pModel; m_pModel = NULL; } -// ------------------------------------------------------------------- -// Returns a pointer to the model instance. -ObjFile::Model *ObjFileParser::GetModel() const -{ - return m_pModel; +void ObjFileParser::setBuffer( std::vector<char> &buffer ) { + m_DataIt = buffer.begin(); + m_DataItEnd = buffer.end(); } -// ------------------------------------------------------------------- -// File parsing method. -void ObjFileParser::parseFile() -{ - if (m_DataIt == m_DataItEnd) - return; +ObjFile::Model *ObjFileParser::GetModel() const { + return m_pModel; +} +void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) { // only update every 100KB or it'll be too slow - const unsigned int updateProgressEveryBytes = 100 * 1024; + //const unsigned int updateProgressEveryBytes = 100 * 1024; unsigned int progressCounter = 0; - const unsigned int bytesToProcess = std::distance(m_DataIt, m_DataItEnd); + const unsigned int bytesToProcess = static_cast<unsigned int>(streamBuffer.size()); const unsigned int progressTotal = 3 * bytesToProcess; const unsigned int progressOffset = bytesToProcess; unsigned int processed = 0; + size_t lastFilePos( 0 ); - DataArrayIt lastDataIt = m_DataIt; + std::vector<char> buffer; + while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) { + m_DataIt = buffer.begin(); + m_DataItEnd = buffer.end(); - while (m_DataIt != m_DataItEnd) - { // Handle progress reporting - processed += std::distance(lastDataIt, m_DataIt); - lastDataIt = m_DataIt; - if (processed > (progressCounter * updateProgressEveryBytes)) - { + const size_t filePos( streamBuffer.getFilePos() ); + if ( lastFilePos < filePos ) { + processed += static_cast<unsigned int>(filePos); + lastFilePos = filePos; progressCounter++; - m_progress->UpdateFileRead(progressOffset + processed*2, progressTotal); + m_progress->UpdateFileRead( progressOffset + processed * 2, progressTotal ); } // parse line - switch (*m_DataIt) - { + switch (*m_DataIt) { case 'v': // Parse a vertex texture coordinate { ++m_DataIt; if (*m_DataIt == ' ' || *m_DataIt == '\t') { - size_t numComponents = getNumComponentsInLine(); + size_t numComponents = getNumComponentsInDataDefinition(); if (numComponents == 3) { // read in vertex definition getVector3(m_pModel->m_Vertices); + } else if (numComponents == 4) { + // read in vertex definition (homogeneous coords) + getHomogeneousVector3(m_pModel->m_Vertices); } else if (numComponents == 6) { // read vertex and vertex-color getTwoVectors3(m_pModel->m_Vertices, m_pModel->m_VertexColors); } } else if (*m_DataIt == 't') { // read in texture coordinate ( 2D or 3D ) - ++m_DataIt; - getVector( m_pModel->m_TextureCoord ); + ++m_DataIt; + getVector( m_pModel->m_TextureCoord ); } else if (*m_DataIt == 'n') { // Read in normal vector definition ++m_DataIt; @@ -173,16 +179,37 @@ void ObjFileParser::parseFile() case 'u': // Parse a material desc. setter { - getMaterialDesc(); + std::string name; + + getNameNoSpace(m_DataIt, m_DataItEnd, name); + + size_t nextSpace = name.find(" "); + if (nextSpace != std::string::npos) + name = name.substr(0, nextSpace); + + if(name == "usemtl") + { + getMaterialDesc(); + } } break; case 'm': // Parse a material library or merging group ('mg') { - if (*(m_DataIt + 1) == 'g') + std::string name; + + getNameNoSpace(m_DataIt, m_DataItEnd, name); + + size_t nextSpace = name.find(" "); + if (nextSpace != std::string::npos) + name = name.substr(0, nextSpace); + + if (name == "mg") getGroupNumberAndResolution(); - else + else if(name == "mtllib") getMaterialLib(); + else + goto pf_skip_line; } break; @@ -206,6 +233,7 @@ void ObjFileParser::parseFile() default: { +pf_skip_line: m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); } break; @@ -213,12 +241,14 @@ void ObjFileParser::parseFile() } } -// ------------------------------------------------------------------- -// Copy the next word in a temporary buffer -void ObjFileParser::copyNextWord(char *pBuffer, size_t length) -{ +void ObjFileParser::copyNextWord(char *pBuffer, size_t length) { size_t index = 0; m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd); + if ( *m_DataIt == '\\' ) { + m_DataIt++; + m_DataIt++; + m_DataIt = getNextWord<DataArrayIt>( m_DataIt, m_DataItEnd ); + } while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) { pBuffer[index] = *m_DataIt; index++; @@ -232,70 +262,61 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length) pBuffer[index] = '\0'; } -// ------------------------------------------------------------------- -// Copy the next line into a temporary buffer -void ObjFileParser::copyNextLine(char *pBuffer, size_t length) -{ - size_t index = 0u; - - // some OBJ files have line continuations using \ (such as in C++ et al) - bool continuation = false; - for (;m_DataIt != m_DataItEnd && index < length-1; ++m_DataIt) - { - const char c = *m_DataIt; - if (c == '\\') { - continuation = true; - continue; +static bool isDataDefinitionEnd( const char *tmp ) { + if ( *tmp == '\\' ) { + tmp++; + if ( IsLineEnd( *tmp ) ) { + tmp++; + return true; } - - if (c == '\n' || c == '\r') { - if(continuation) { - pBuffer[ index++ ] = ' '; - continue; - } - break; - } - - continuation = false; - pBuffer[ index++ ] = c; } - ai_assert(index < length); - pBuffer[ index ] = '\0'; + return false; } -size_t ObjFileParser::getNumComponentsInLine() { +size_t ObjFileParser::getNumComponentsInDataDefinition() { size_t numComponents( 0 ); const char* tmp( &m_DataIt[0] ); - while( !IsLineEnd( *tmp ) ) { + bool end_of_definition = false; + while ( !end_of_definition ) { + if ( isDataDefinitionEnd( tmp ) ) { + tmp += 2; + } else if ( IsLineEnd( *tmp ) ) { + end_of_definition = true; + } if ( !SkipSpaces( &tmp ) ) { break; } + const bool isNum( IsNumeric( *tmp ) ); SkipToken( tmp ); - ++numComponents; + if ( isNum ) { + ++numComponents; + } + if ( !SkipSpaces( &tmp ) ) { + break; + } } return numComponents; } -// ------------------------------------------------------------------- void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) { - size_t numComponents = getNumComponentsInLine(); - float x, y, z; + size_t numComponents = getNumComponentsInDataDefinition(); + ai_real x, y, z; if( 2 == numComponents ) { copyNextWord( m_buffer, Buffersize ); - x = ( float ) fast_atof( m_buffer ); + x = ( ai_real ) fast_atof( m_buffer ); copyNextWord( m_buffer, Buffersize ); - y = ( float ) fast_atof( m_buffer ); + y = ( ai_real ) fast_atof( m_buffer ); z = 0.0; } else if( 3 == numComponents ) { copyNextWord( m_buffer, Buffersize ); - x = ( float ) fast_atof( m_buffer ); + x = ( ai_real ) fast_atof( m_buffer ); copyNextWord( m_buffer, Buffersize ); - y = ( float ) fast_atof( m_buffer ); + y = ( ai_real ) fast_atof( m_buffer ); copyNextWord( m_buffer, Buffersize ); - z = ( float ) fast_atof( m_buffer ); + z = ( ai_real ) fast_atof( m_buffer ); } else { throw DeadlyImportError( "OBJ: Invalid number of components" ); } @@ -303,61 +324,75 @@ void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) { m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); } -// ------------------------------------------------------------------- -// Get values for a new 3D vector instance void ObjFileParser::getVector3( std::vector<aiVector3D> &point3d_array ) { - float x, y, z; + ai_real x, y, z; copyNextWord(m_buffer, Buffersize); - x = (float) fast_atof(m_buffer); + x = (ai_real) fast_atof(m_buffer); copyNextWord(m_buffer, Buffersize); - y = (float) fast_atof(m_buffer); + y = (ai_real) fast_atof(m_buffer); copyNextWord( m_buffer, Buffersize ); - z = ( float ) fast_atof( m_buffer ); + z = ( ai_real ) fast_atof( m_buffer ); point3d_array.push_back( aiVector3D( x, y, z ) ); m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); } -// ------------------------------------------------------------------- -// Get values for two 3D vectors on the same line +void ObjFileParser::getHomogeneousVector3( std::vector<aiVector3D> &point3d_array ) { + ai_real x, y, z, w; + copyNextWord(m_buffer, Buffersize); + x = (ai_real) fast_atof(m_buffer); + + copyNextWord(m_buffer, Buffersize); + y = (ai_real) fast_atof(m_buffer); + + copyNextWord( m_buffer, Buffersize ); + z = ( ai_real ) fast_atof( m_buffer ); + + copyNextWord( m_buffer, Buffersize ); + w = ( ai_real ) fast_atof( m_buffer ); + + ai_assert( w != 0 ); + + point3d_array.push_back( aiVector3D( x/w, y/w, z/w ) ); + m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); +} + void ObjFileParser::getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, std::vector<aiVector3D> &point3d_array_b ) { - float x, y, z; + ai_real x, y, z; copyNextWord(m_buffer, Buffersize); - x = (float) fast_atof(m_buffer); + x = (ai_real) fast_atof(m_buffer); copyNextWord(m_buffer, Buffersize); - y = (float) fast_atof(m_buffer); + y = (ai_real) fast_atof(m_buffer); copyNextWord( m_buffer, Buffersize ); - z = ( float ) fast_atof( m_buffer ); + z = ( ai_real ) fast_atof( m_buffer ); point3d_array_a.push_back( aiVector3D( x, y, z ) ); copyNextWord(m_buffer, Buffersize); - x = (float) fast_atof(m_buffer); + x = (ai_real) fast_atof(m_buffer); copyNextWord(m_buffer, Buffersize); - y = (float) fast_atof(m_buffer); + y = (ai_real) fast_atof(m_buffer); copyNextWord( m_buffer, Buffersize ); - z = ( float ) fast_atof( m_buffer ); + z = ( ai_real ) fast_atof( m_buffer ); point3d_array_b.push_back( aiVector3D( x, y, z ) ); m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); } -// ------------------------------------------------------------------- -// Get values for a new 2D vector instance void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) { - float x, y; + ai_real x, y; copyNextWord(m_buffer, Buffersize); - x = (float) fast_atof(m_buffer); + x = (ai_real) fast_atof(m_buffer); copyNextWord(m_buffer, Buffersize); - y = (float) fast_atof(m_buffer); + y = (ai_real) fast_atof(m_buffer); point2d_array.push_back(aiVector2D(x, y)); @@ -366,37 +401,30 @@ void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) { static const std::string DefaultObjName = "defaultobject"; -// ------------------------------------------------------------------- -// Get values for a new face instance -void ObjFileParser::getFace(aiPrimitiveType type) { - copyNextLine(m_buffer, Buffersize); - char *pPtr = m_buffer; - char *pEnd = &pPtr[Buffersize]; - pPtr = getNextToken<char*>(pPtr, pEnd); - if ( pPtr == pEnd || *pPtr == '\0' ) { +void ObjFileParser::getFace( aiPrimitiveType type ) { + m_DataIt = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd ); + if ( m_DataIt == m_DataItEnd || *m_DataIt == '\0' ) { return; } - std::vector<unsigned int> *pIndices = new std::vector<unsigned int>; - std::vector<unsigned int> *pTexID = new std::vector<unsigned int>; - std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>; + ObjFile::Face *face = new ObjFile::Face( type ); bool hasNormal = false; - const int vSize = m_pModel->m_Vertices.size(); - const int vtSize = m_pModel->m_TextureCoord.size(); - const int vnSize = m_pModel->m_Normals.size(); + const int vSize = static_cast<unsigned int>(m_pModel->m_Vertices.size()); + const int vtSize = static_cast<unsigned int>(m_pModel->m_TextureCoord.size()); + const int vnSize = static_cast<unsigned int>(m_pModel->m_Normals.size()); const bool vt = (!m_pModel->m_TextureCoord.empty()); const bool vn = (!m_pModel->m_Normals.empty()); int iStep = 0, iPos = 0; - while (pPtr != pEnd) { + while ( m_DataIt != m_DataItEnd ) { iStep = 1; - if ( IsLineEnd( *pPtr ) ) { + if ( IsLineEnd( *m_DataIt ) ) { break; } - if (*pPtr=='/' ) { + if ( *m_DataIt =='/' ) { if (type == aiPrimitiveType_POINT) { DefaultLogger::get()->error("Obj: Separator unexpected in point statement"); } @@ -408,11 +436,11 @@ void ObjFileParser::getFace(aiPrimitiveType type) { } } iPos++; - } else if( IsSpaceOrNewLine( *pPtr ) ) { + } else if( IsSpaceOrNewLine( *m_DataIt ) ) { iPos = 0; } else { //OBJ USES 1 Base ARRAYS!!!! - const int iVal( ::atoi( pPtr ) ); + const int iVal( ::atoi( & ( *m_DataIt ) ) ); // increment iStep position based off of the sign and # of digits int tmp = iVal; @@ -423,65 +451,50 @@ void ObjFileParser::getFace(aiPrimitiveType type) { ++iStep; } - if ( iVal > 0 ) - { + if ( iVal > 0 ) { // Store parsed index - if ( 0 == iPos ) - { - pIndices->push_back( iVal-1 ); - } - else if ( 1 == iPos ) - { - pTexID->push_back( iVal-1 ); - } - else if ( 2 == iPos ) - { - pNormalID->push_back( iVal-1 ); + if ( 0 == iPos ) { + face->m_vertices.push_back( iVal - 1 ); + } else if ( 1 == iPos ) { + face->m_texturCoords.push_back( iVal - 1 ); + } else if ( 2 == iPos ) { + face->m_normals.push_back( iVal - 1 ); hasNormal = true; - } - else - { + } else { reportErrorTokenInFace(); } - } - else if ( iVal < 0 ) - { + } else if ( iVal < 0 ) { // Store relatively index - if ( 0 == iPos ) - { - pIndices->push_back( vSize + iVal ); - } - else if ( 1 == iPos ) - { - pTexID->push_back( vtSize + iVal ); - } - else if ( 2 == iPos ) - { - pNormalID->push_back( vnSize + iVal ); + if ( 0 == iPos ) { + face->m_vertices.push_back( vSize + iVal ); + } else if ( 1 == iPos ) { + face->m_texturCoords.push_back( vtSize + iVal ); + } else if ( 2 == iPos ) { + face->m_normals.push_back( vnSize + iVal ); hasNormal = true; - } - else - { + } else { reportErrorTokenInFace(); } + } else { + //On error, std::atoi will return 0 which is not a valid value + delete face; + delete m_pModel; + m_pModel = nullptr; + throw DeadlyImportError("OBJ: Invalid face indice"); } + } - pPtr += iStep; + m_DataIt += iStep; } - if ( pIndices->empty() ) { + if ( face->m_vertices.empty() ) { DefaultLogger::get()->error("Obj: Ignoring empty face"); // skip line and clean up m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); - delete pNormalID; - delete pTexID; - delete pIndices; - + delete face; return; } - ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type ); - // Set active material, if one set if( NULL != m_pModel->m_pCurrentMaterial ) { face->m_pMaterial = m_pModel->m_pCurrentMaterial; @@ -501,8 +514,8 @@ void ObjFileParser::getFace(aiPrimitiveType type) { // Store the face m_pModel->m_pCurrentMesh->m_Faces.push_back( face ); - m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size(); - m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size(); + m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int) face->m_vertices.size(); + m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int) face->m_texturCoords.size(); if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) { m_pModel->m_pCurrentMesh->m_hasNormals = true; } @@ -510,10 +523,7 @@ void ObjFileParser::getFace(aiPrimitiveType type) { m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); } -// ------------------------------------------------------------------- -// Get values for a new material description -void ObjFileParser::getMaterialDesc() -{ +void ObjFileParser::getMaterialDesc() { // Get next data for material data m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); if (m_DataIt == m_DataItEnd) { @@ -536,28 +546,31 @@ void ObjFileParser::getMaterialDesc() // 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)) + if ( m_pModel->m_pCurrentMaterial && m_pModel->m_pCurrentMaterial->MaterialName == aiString( strName ) ) { skip = true; + } - if (!skip) - { + 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()) - { - // 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(); - } - else - { + if (it == m_pModel->m_MaterialMap.end()) { + // Not found, so we don't know anything about the material except for its name. + // This may be the case if the material library is missing. We don't want to lose all + // materials if that happens, so create a new named material instead of discarding it + // completely. + DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", creating new material"); + m_pModel->m_pCurrentMaterial = new ObjFile::Material(); + m_pModel->m_pCurrentMaterial->MaterialName.Set(strName); + m_pModel->m_MaterialLib.push_back(strName); + m_pModel->m_MaterialMap[strName] = m_pModel->m_pCurrentMaterial; + } else { // Found, using detected material m_pModel->m_pCurrentMaterial = (*it).second; } - if (needsNewMesh(strName)) - createMesh(strName); + if ( needsNewMesh( strName ) ) { + createMesh( strName ); + } m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strName); } @@ -568,26 +581,13 @@ void ObjFileParser::getMaterialDesc() // ------------------------------------------------------------------- // Get a comment, values will be skipped -void ObjFileParser::getComment() -{ - while (m_DataIt != m_DataItEnd) - { - if ( '\n' == (*m_DataIt)) - { - ++m_DataIt; - break; - } - else - { - ++m_DataIt; - } - } +void ObjFileParser::getComment() { + m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); } // ------------------------------------------------------------------- // Get material library from file. -void ObjFileParser::getMaterialLib() -{ +void ObjFileParser::getMaterialLib() { // Translate tuple m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); if( m_DataIt == m_DataItEnd ) { @@ -602,6 +602,13 @@ void ObjFileParser::getMaterialLib() // Check for existence const std::string strMatName(pStart, &(*m_DataIt)); std::string absName; + + // Check if directive is valid. + if ( 0 == strMatName.length() ) { + DefaultLogger::get()->warn( "OBJ: no name for material library specified." ); + return; + } + if ( m_pIO->StackSize() > 0 ) { std::string path = m_pIO->CurrentDirectory(); if ( '/' != *path.rbegin() ) { @@ -619,7 +626,7 @@ void ObjFileParser::getMaterialLib() DefaultLogger::get()->info("OBJ: Opening fallback material file " + strMatFallbackName); pFile = m_pIO->Open(strMatFallbackName); if (!pFile) { - DefaultLogger::get()->error("OBJ: Unable to locate fallback material file " + strMatName); + DefaultLogger::get()->error("OBJ: Unable to locate fallback material file " + strMatFallbackName); m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); return; } @@ -639,8 +646,7 @@ void ObjFileParser::getMaterialLib() // ------------------------------------------------------------------- // Set a new material definition as the current material. -void ObjFileParser::getNewMaterial() -{ +void ObjFileParser::getNewMaterial() { m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd); if( m_DataIt == m_DataItEnd ) { @@ -653,17 +659,13 @@ void ObjFileParser::getNewMaterial() ++m_DataIt; } std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat ); - if ( it == m_pModel->m_MaterialMap.end() ) - { + if ( it == m_pModel->m_MaterialMap.end() ) { // Show a warning, if material was not found DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat); m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial; - } - else - { + } else { // Set new material - if ( needsNewMesh( strMat ) ) - { + if ( needsNewMesh( strMat ) ) { createMesh( strMat ); } m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat ); @@ -692,36 +694,36 @@ int ObjFileParser::getMaterialIndex( const std::string &strMaterialName ) // ------------------------------------------------------------------- // Getter for a group name. -void ObjFileParser::getGroupName() -{ - std::string strGroupName; +void ObjFileParser::getGroupName() { + std::string groupName; - m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName); + // here we skip 'g ' from line + m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); + m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, groupName); if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) { return; } // Change active group, if necessary - if ( m_pModel->m_strActiveGroup != strGroupName ) - { + if ( m_pModel->m_strActiveGroup != groupName ) { // Search for already existing entry - ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(strGroupName); + ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(groupName); // We are mapping groups into the object structure - createObject( strGroupName ); + createObject( groupName ); // New group name, creating a new entry if (it == m_pModel->m_Groups.end()) { std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>; - m_pModel->m_Groups[ strGroupName ] = pFaceIDArray; + m_pModel->m_Groups[ groupName ] = pFaceIDArray; m_pModel->m_pGroupFaceIDs = (pFaceIDArray); } else { m_pModel->m_pGroupFaceIDs = (*it).second; } - m_pModel->m_strActiveGroup = strGroupName; + m_pModel->m_strActiveGroup = groupName; } m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); } @@ -809,7 +811,7 @@ void ObjFileParser::createMesh( const std::string &meshName ) ai_assert( NULL != m_pModel ); m_pModel->m_pCurrentMesh = new ObjFile::Mesh( meshName ); m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh ); - unsigned int meshId = m_pModel->m_Meshes.size()-1; + unsigned int meshId = static_cast<unsigned int>(m_pModel->m_Meshes.size()-1); if ( NULL != m_pModel->m_pCurrent ) { m_pModel->m_pCurrent->m_Meshes.push_back( meshId ); @@ -832,7 +834,11 @@ bool ObjFileParser::needsNewMesh( const std::string &materialName ) bool newMat = false; int matIdx = getMaterialIndex( materialName ); int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex; - if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) && curMatIdx != matIdx ) + if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) + && curMatIdx != matIdx + // no need create a new mesh if no faces in current + // lets say 'usemtl' goes straight after 'g' + && m_pModel->m_pCurrentMesh->m_Faces.size() > 0 ) { // New material -> only one material per mesh, so we need to create a new // material |