From 813f3b8248d8b3f7ef8f641b1ef004c99c8bc9fe Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 30 May 2017 21:10:33 +0200 Subject: [PATCH] ObjLoader: improve performance of obj-import. --- code/IOStreamBuffer.h | 32 +++++++++++++++++++++++--------- code/ObjFileParser.cpp | 17 +++++++---------- code/ObjTools.h | 7 ++++++- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/code/IOStreamBuffer.h b/code/IOStreamBuffer.h index d8c7d00ab..d8728aee3 100644 --- a/code/IOStreamBuffer.h +++ b/code/IOStreamBuffer.h @@ -45,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "ParsingUtils.h" +#include + namespace Assimp { // --------------------------------------------------------------------------- @@ -54,6 +56,8 @@ namespace Assimp { template class IOStreamBuffer { public: + typedef typename std::vector::iterator CacheIter; + /// @brief The class constructor. IOStreamBuffer( size_t cache = 4096 * 4096 ); @@ -69,8 +73,8 @@ public: /// @return true if successful. bool close(); - /// @brief Returns the filesize. - /// @return The filesize. + /// @brief Returns the file-size. + /// @return The file-size. size_t size() const; /// @brief Returns the cache size. @@ -96,7 +100,7 @@ public: /// @brief Will read the next line. /// @param buffer The buffer for the next line. /// @return true if successful. - bool getNextLine( std::vector &buffer ); + bool getNextLine( CacheIter &begin, CacheIter &end ); private: IOStream *m_stream; @@ -106,6 +110,7 @@ private: size_t m_blockIdx; std::vector m_cache; size_t m_cachePos; + CacheIter m_it; size_t m_filePos; }; @@ -118,6 +123,7 @@ IOStreamBuffer::IOStreamBuffer( size_t cache ) , m_numBlocks( 0 ) , m_blockIdx( 0 ) , m_cachePos( 0 ) +, m_it() , m_filePos( 0 ) { m_cache.resize( cache ); std::fill( m_cache.begin(), m_cache.end(), '\n' ); @@ -203,6 +209,7 @@ bool IOStreamBuffer::readNextBlock() { m_filePos += m_cacheSize; m_cachePos = 0; m_blockIdx++; + m_it = m_cache.begin(); return true; } @@ -227,25 +234,32 @@ size_t IOStreamBuffer::getFilePos() const { template inline -bool IOStreamBuffer::getNextLine( std::vector &buffer ) { - buffer.resize( m_cacheSize ); +bool IOStreamBuffer::getNextLine( CacheIter &begin, CacheIter &end ) { if ( m_cachePos == m_cacheSize || 0 == m_filePos ) { if ( !readNextBlock() ) { + begin = m_it; + end = m_it; return false; } + m_it = m_cache.begin(); } - size_t i = 0; + + //size_t i = 0; + begin = m_it; while ( !IsLineEnd( m_cache[ m_cachePos ] ) ) { - buffer[ i ] = m_cache[ m_cachePos ]; m_cachePos++; - i++; + ++m_it; + //i++; if ( m_cachePos >= m_cacheSize ) { if ( !readNextBlock() ) { + begin = m_it; + end = m_it; return false; } } } - buffer[ i ] = '\n'; + ++m_it; + end = m_it; m_cachePos++; return true; diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index decfacbf5..44d171dcc 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -109,7 +109,7 @@ ObjFile::Model *ObjFileParser::GetModel() const { return m_pModel; } -void ignoreNewLines(IOStreamBuffer &streamBuffer, std::vector &buffer) +/*void ignoreNewLines(IOStreamBuffer &streamBuffer, std::vector &buffer) { auto curPosition = buffer.begin(); do @@ -129,7 +129,7 @@ void ignoreNewLines(IOStreamBuffer &streamBuffer, std::vector &buffe std::copy(tempBuf.cbegin(), tempBuf.cend(), ++curPosition); } } while (*curPosition!='\n'); -} +}*/ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { // only update every 100KB or it'll be too slow @@ -141,11 +141,7 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { unsigned int processed = 0; size_t lastFilePos( 0 ); - std::vector buffer; - while ( streamBuffer.getNextLine( buffer ) ) { - m_DataIt = buffer.begin(); - m_DataItEnd = buffer.end(); - + while ( streamBuffer.getNextLine( m_DataIt, m_DataItEnd ) ) { // Handle progress reporting const size_t filePos( streamBuffer.getFilePos() ); if ( lastFilePos < filePos ) { @@ -245,7 +241,6 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { default: { pf_skip_line: - m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } break; @@ -595,14 +590,16 @@ void ObjFileParser::getMaterialDesc() { // ------------------------------------------------------------------- // Get a comment, values will be skipped void ObjFileParser::getComment() { - while (m_DataIt != m_DataItEnd) { + m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); + +/* while (m_DataIt != m_DataItEnd) { if ( '\n' == (*m_DataIt)) { ++m_DataIt; break; } else { ++m_DataIt; } - } + }*/ } // ------------------------------------------------------------------- diff --git a/code/ObjTools.h b/code/ObjTools.h index 7b0bdcedf..1be518700 100644 --- a/code/ObjTools.h +++ b/code/ObjTools.h @@ -115,6 +115,9 @@ template inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) { while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) { ++it; + if ( *it == '\n' ) { + ++it; + } } if ( it != end ) { @@ -122,8 +125,10 @@ inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) { ++uiLine; } // fix .. from time to time there are spaces at the beginning of a material line - while ( it != end && (*it == '\t' || *it == ' ') ) + while ( it != end && ( *it == '\t' || *it == ' ' ) ) { ++it; + } + return it; }