summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/assimp/code/ObjFileParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/assimp/code/ObjFileParser.cpp')
-rw-r--r--src/3rdparty/assimp/code/ObjFileParser.cpp454
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