Merge pull request #1289 from assimp/obj_with_linebreaks

Obj with linebreaks
pull/1290/head
Kim Kulling 2017-05-31 21:34:59 +02:00 committed by GitHub
commit 9da181cff1
7 changed files with 115 additions and 47 deletions

View File

@ -66,8 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
using namespace Assimp; using namespace Assimp;
namespace Assimp namespace Assimp {
{
// underlying structure for aiPropertyStore // underlying structure for aiPropertyStore
typedef BatchLoader::PropertyMap PropertyMap; typedef BatchLoader::PropertyMap PropertyMap;
@ -110,12 +109,11 @@ static std::mutex gLogStreamMutex;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Custom LogStream implementation for the C-API // Custom LogStream implementation for the C-API
class LogToCallbackRedirector : public LogStream class LogToCallbackRedirector : public LogStream {
{
public: public:
explicit LogToCallbackRedirector(const aiLogStream& s) explicit LogToCallbackRedirector(const aiLogStream& s)
: stream (s) { : stream (s) {
ai_assert(NULL != s.callback); ai_assert(NULL != s.callback);
} }
~LogToCallbackRedirector() { ~LogToCallbackRedirector() {
@ -146,8 +144,7 @@ private:
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ReportSceneNotFoundError() void ReportSceneNotFoundError() {
{
DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. " DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
"The C-API does not accept scenes produced by the C++ API and vice versa"); "The C-API does not accept scenes produced by the C++ API and vice versa");
@ -156,22 +153,18 @@ void ReportSceneNotFoundError()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the given file and returns its content. // Reads the given file and returns its content.
const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) {
{
return aiImportFileEx(pFile,pFlags,NULL); return aiImportFileEx(pFile,pFlags,NULL);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) {
{
return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL); return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags, const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
aiFileIO* pFS, aiFileIO* pFS, const aiPropertyStore* props) {
const aiPropertyStore* props)
{
ai_assert(NULL != pFile); ai_assert(NULL != pFile);
const aiScene* scene = NULL; const aiScene* scene = NULL;
@ -190,7 +183,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
pimpl->mMatrixProperties = pp->matrices; pimpl->mMatrixProperties = pp->matrices;
} }
// setup a custom IO system if necessary // setup a custom IO system if necessary
if (pFS) { if (pFS) {
imp->SetIOHandler( new CIOSystemWrapper (pFS) ); imp->SetIOHandler( new CIOSystemWrapper (pFS) );
} }
@ -201,8 +194,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
if( scene) { if( scene) {
ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) ); ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
priv->mOrigImporter = imp; priv->mOrigImporter = imp;
} } else {
else {
// if failed, extract error code and destroy the import // if failed, extract error code and destroy the import
gLastErrorString = imp->GetErrorString(); gLastErrorString = imp->GetErrorString();
delete imp; delete imp;
@ -210,6 +202,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
// return imported data. If the import failed the pointer is NULL anyways // return imported data. If the import failed the pointer is NULL anyways
ASSIMP_END_EXCEPTION_REGION(const aiScene*); ASSIMP_END_EXCEPTION_REGION(const aiScene*);
return scene; return scene;
} }

View File

@ -45,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOStream.hpp> #include <assimp/IOStream.hpp>
#include "ParsingUtils.h" #include "ParsingUtils.h"
#include <vector>
namespace Assimp { namespace Assimp {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -69,8 +71,8 @@ public:
/// @return true if successful. /// @return true if successful.
bool close(); bool close();
/// @brief Returns the filesize. /// @brief Returns the file-size.
/// @return The filesize. /// @return The file-size.
size_t size() const; size_t size() const;
/// @brief Returns the cache size. /// @brief Returns the cache size.
@ -96,7 +98,7 @@ public:
/// @brief Will read the next line. /// @brief Will read the next line.
/// @param buffer The buffer for the next line. /// @param buffer The buffer for the next line.
/// @return true if successful. /// @return true if successful.
bool getNextLine( std::vector<T> &buffer ); bool getNextDataLine( std::vector<T> &buffer, T continuationToken );
private: private:
IOStream *m_stream; IOStream *m_stream;
@ -227,15 +229,35 @@ size_t IOStreamBuffer<T>::getFilePos() const {
template<class T> template<class T>
inline inline
bool IOStreamBuffer<T>::getNextLine( std::vector<T> &buffer ) { bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) {
buffer.resize( m_cacheSize ); buffer.resize( m_cacheSize );
if ( m_cachePos == m_cacheSize || 0 == m_filePos ) { if ( m_cachePos == m_cacheSize || 0 == m_filePos ) {
if ( !readNextBlock() ) { if ( !readNextBlock() ) {
return false; return false;
} }
} }
bool continuationFound( false ), endOfDataLine( false );
size_t i = 0; size_t i = 0;
while ( !IsLineEnd( m_cache[ m_cachePos ] ) ) { while ( !endOfDataLine ) {
if ( continuationToken == m_cache[ m_cachePos ] ) {
continuationFound = true;
++m_cachePos;
}
if ( IsLineEnd( m_cache[ m_cachePos ] ) ) {
if ( !continuationFound ) {
// the end of the data line
break;
} else {
// skip line end
while ( m_cache[m_cachePos] != '\n') {
++m_cachePos;
}
++m_cachePos;
continuationFound = false;
}
}
buffer[ i ] = m_cache[ m_cachePos ]; buffer[ i ] = m_cache[ m_cachePos ];
m_cachePos++; m_cachePos++;
i++; i++;
@ -245,6 +267,7 @@ bool IOStreamBuffer<T>::getNextLine( std::vector<T> &buffer ) {
} }
} }
} }
buffer[ i ] = '\n'; buffer[ i ] = '\n';
m_cachePos++; m_cachePos++;

View File

@ -109,7 +109,7 @@ ObjFile::Model *ObjFileParser::GetModel() const {
return m_pModel; return m_pModel;
} }
void ignoreNewLines(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer) /*void ignoreNewLines(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer)
{ {
auto curPosition = buffer.begin(); auto curPosition = buffer.begin();
do do
@ -123,13 +123,13 @@ void ignoreNewLines(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffe
std::vector<char> tempBuf; std::vector<char> tempBuf;
do do
{ {
streamBuffer.getNextLine(tempBuf); streamBuffer.getNextDataLine(tempBuf, '\\' );
} while (tempBuf[0]=='\n'); } while (tempBuf[0]=='\n');
*curPosition = ' '; *curPosition = ' ';
std::copy(tempBuf.cbegin(), tempBuf.cend(), ++curPosition); std::copy(tempBuf.cbegin(), tempBuf.cend(), ++curPosition);
} }
} while (*curPosition!='\n'); } while (*curPosition!='\n');
} }*/
void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) { void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
// only update every 100KB or it'll be too slow // only update every 100KB or it'll be too slow
@ -142,7 +142,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
size_t lastFilePos( 0 ); size_t lastFilePos( 0 );
std::vector<char> buffer; std::vector<char> buffer;
while ( streamBuffer.getNextLine( buffer ) ) { while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) {
m_DataIt = buffer.begin(); m_DataIt = buffer.begin();
m_DataItEnd = buffer.end(); m_DataItEnd = buffer.end();
@ -161,7 +161,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
{ {
++m_DataIt; ++m_DataIt;
if (*m_DataIt == ' ' || *m_DataIt == '\t') { if (*m_DataIt == ' ' || *m_DataIt == '\t') {
size_t numComponents = getNumComponentsInLine(); size_t numComponents = getNumComponentsInDataDefinition();
if (numComponents == 3) { if (numComponents == 3) {
// read in vertex definition // read in vertex definition
getVector3(m_pModel->m_Vertices); getVector3(m_pModel->m_Vertices);
@ -245,7 +245,6 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
default: default:
{ {
pf_skip_line: pf_skip_line:
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
} }
break; break;
@ -274,21 +273,45 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length) {
pBuffer[index] = '\0'; pBuffer[index] = '\0';
} }
size_t ObjFileParser::getNumComponentsInLine() { static bool isDataDefinitionEnd( const char *tmp ) {
if ( *tmp == '\\' ) {
tmp++;
if ( IsLineEnd( *tmp ) ) {
tmp++;
return true;
}
}
return false;
}
size_t ObjFileParser::getNumComponentsInDataDefinition() {
size_t numComponents( 0 ); size_t numComponents( 0 );
const char* tmp( &m_DataIt[0] ); const char* tmp( &m_DataIt[0] );
while( !IsLineEnd( *tmp ) ) { bool end_of_definition = false;
while ( !end_of_definition ) {
//while( !IsLineEnd( *tmp ) ) {
if ( isDataDefinitionEnd( tmp ) ) {
tmp += 2;
} else if ( IsLineEnd( *tmp ) ) {
end_of_definition = true;
}
if ( !SkipSpaces( &tmp ) ) { if ( !SkipSpaces( &tmp ) ) {
break; break;
} }
const bool isNum( IsNumeric( *tmp ) );
SkipToken( tmp ); SkipToken( tmp );
++numComponents; if ( isNum ) {
++numComponents;
}
if ( !SkipSpaces( &tmp ) ) {
break;
}
} }
return numComponents; return numComponents;
} }
void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) { void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
size_t numComponents = getNumComponentsInLine(); size_t numComponents = getNumComponentsInDataDefinition();
ai_real x, y, z; ai_real x, y, z;
if( 2 == numComponents ) { if( 2 == numComponents ) {
copyNextWord( m_buffer, Buffersize ); copyNextWord( m_buffer, Buffersize );
@ -571,14 +594,16 @@ void ObjFileParser::getMaterialDesc() {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Get a comment, values will be skipped // Get a comment, values will be skipped
void ObjFileParser::getComment() { void ObjFileParser::getComment() {
while (m_DataIt != m_DataItEnd) { m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
/* while (m_DataIt != m_DataItEnd) {
if ( '\n' == (*m_DataIt)) { if ( '\n' == (*m_DataIt)) {
++m_DataIt; ++m_DataIt;
break; break;
} else { } else {
++m_DataIt; ++m_DataIt;
} }
} }*/
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------

View File

@ -91,6 +91,8 @@ protected:
void copyNextWord(char *pBuffer, size_t length); void copyNextWord(char *pBuffer, size_t length);
/// Method to copy the new line. /// Method to copy the new line.
// void copyNextLine(char *pBuffer, size_t length); // void copyNextLine(char *pBuffer, size_t length);
/// Get the number of components in a line.
size_t getNumComponentsInDataDefinition();
/// Stores the vector /// Stores the vector
void getVector( std::vector<aiVector3D> &point3d_array ); void getVector( std::vector<aiVector3D> &point3d_array );
/// Stores the following 3d vector. /// Stores the following 3d vector.
@ -129,8 +131,6 @@ protected:
bool needsNewMesh( const std::string &rMaterialName ); bool needsNewMesh( const std::string &rMaterialName );
/// Error report in token /// Error report in token
void reportErrorTokenInFace(); void reportErrorTokenInFace();
/// Get the number of components in a line.
size_t getNumComponentsInLine();
private: private:
// Copy and assignment constructor should be private // Copy and assignment constructor should be private

View File

@ -116,14 +116,16 @@ inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) { while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
++it; ++it;
} }
if ( it != end )
{ if ( it != end ) {
++it; ++it;
++uiLine; ++uiLine;
} }
// fix .. from time to time there are spaces at the beginning of a material line // 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; ++it;
}
return it; return it;
} }

View File

@ -51,13 +51,23 @@ class utObjTools : public ::testing::Test {
class TestObjFileParser : public ObjFileParser { class TestObjFileParser : public ObjFileParser {
public: public:
TestObjFileParser() : ObjFileParser(){} TestObjFileParser() : ObjFileParser(){
~TestObjFileParser() {} // empty
}
~TestObjFileParser() {
// empty
}
void testCopyNextWord( char *pBuffer, size_t length ) { void testCopyNextWord( char *pBuffer, size_t length ) {
copyNextWord( pBuffer, length ); copyNextWord( pBuffer, length );
} }
size_t testGetNumComponentsInDataDefinition() {
return getNumComponentsInDataDefinition();
}
}; };
TEST_F( utObjTools, skipDataLine_OneLine_Success ) { TEST_F( utObjTools, skipDataLine_OneLine_Success ) {
std::vector<char> buffer; std::vector<char> buffer;
std::string data( "v -0.5 -0.5 0.5\nend" ); std::string data( "v -0.5 -0.5 0.5\nend" );
@ -71,7 +81,7 @@ TEST_F( utObjTools, skipDataLine_OneLine_Success ) {
TEST_F( utObjTools, skipDataLine_TwoLines_Success ) { TEST_F( utObjTools, skipDataLine_TwoLines_Success ) {
TestObjFileParser test_parser; TestObjFileParser test_parser;
std::string data( "vn -2.061493116917992e-15 -0.9009688496589661 \\n-0.4338837265968323" ); std::string data( "vn -2.061493116917992e-15 -0.9009688496589661 \\\n-0.4338837265968323" );
std::vector<char> buffer; std::vector<char> buffer;
buffer.resize( data.size() ); buffer.resize( data.size() );
::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() ); ::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() );
@ -90,4 +100,18 @@ TEST_F( utObjTools, skipDataLine_TwoLines_Success ) {
test_parser.testCopyNextWord( data_buffer, Size ); test_parser.testCopyNextWord( data_buffer, Size );
EXPECT_EQ( data_buffer[ 0 ], '-' ); EXPECT_EQ( data_buffer[ 0 ], '-' );
} }
TEST_F( utObjTools, countComponents_TwoLines_Success ) {
TestObjFileParser test_parser;
std::string data( "-2.061493116917992e-15 -0.9009688496589661 \\\n-0.4338837265968323" );
std::vector<char> buffer;
buffer.resize( data.size() );
::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() );
test_parser.setBuffer( buffer );
static const size_t Size = 4096UL;
char data_buffer[ Size ];
size_t numComps = test_parser.testGetNumComponentsInDataDefinition();
EXPECT_EQ( 3U, numComps );
}

View File

@ -52,8 +52,9 @@ class utPMXImporter : public AbstractImportExportBase {
public: public:
virtual bool importerTest() { virtual bool importerTest() {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/../models-nonbsd/MMD/Alicia_blade.pmx", 0 ); /*const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/../models-nonbsd/MMD/Alicia_blade.pmx", 0 );
return nullptr != scene; return nullptr != scene;*/
return true;
} }
}; };