2015-05-19 03:48:29 +00:00
|
|
|
/*
|
|
|
|
Open Asset Import Library (assimp)
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
|
2017-05-09 17:57:36 +00:00
|
|
|
Copyright (c) 2006-2017, assimp team
|
|
|
|
|
2015-05-19 03:48:29 +00:00
|
|
|
All rights reserved.
|
|
|
|
|
2015-05-19 03:52:10 +00:00
|
|
|
Redistribution and use of this software in source and binary forms,
|
|
|
|
with or without modification, are permitted provided that the
|
2015-05-19 03:48:29 +00:00
|
|
|
following conditions are met:
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above
|
|
|
|
copyright notice, this list of conditions and the
|
|
|
|
following disclaimer.
|
|
|
|
|
|
|
|
* Redistributions in binary form must reproduce the above
|
|
|
|
copyright notice, this list of conditions and the
|
|
|
|
following disclaimer in the documentation and/or other
|
|
|
|
materials provided with the distribution.
|
|
|
|
|
|
|
|
* Neither the name of the assimp team, nor the names of its
|
|
|
|
contributors may be used to endorse or promote products
|
|
|
|
derived from this software without specific prior
|
|
|
|
written permission of the assimp team.
|
|
|
|
|
2015-05-19 03:52:10 +00:00
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
2015-05-19 03:48:29 +00:00
|
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
2015-05-19 03:52:10 +00:00
|
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
2015-05-19 03:48:29 +00:00
|
|
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
2015-05-19 03:52:10 +00:00
|
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
2015-05-19 03:48:29 +00:00
|
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
2015-05-19 03:52:10 +00:00
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
2015-05-19 03:48:29 +00:00
|
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
/** @file ObjTools.h
|
|
|
|
* @brief Some helpful templates for text parsing
|
2015-05-19 03:48:29 +00:00
|
|
|
*/
|
|
|
|
#ifndef OBJ_TOOLS_H_INC
|
|
|
|
#define OBJ_TOOLS_H_INC
|
|
|
|
|
2018-01-06 00:18:33 +00:00
|
|
|
#include <assimp/fast_atof.h>
|
|
|
|
#include <assimp/ParsingUtils.h>
|
2015-05-19 03:48:29 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2016-11-27 15:43:25 +00:00
|
|
|
namespace Assimp {
|
2015-05-19 03:48:29 +00:00
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
/** @brief Returns true, if the last entry of the buffer is reached.
|
|
|
|
* @param it Iterator of current position.
|
|
|
|
* @param end Iterator with end of buffer.
|
|
|
|
* @return true, if the end of the buffer is reached.
|
2015-05-19 03:48:29 +00:00
|
|
|
*/
|
|
|
|
template<class char_t>
|
2016-11-27 15:43:25 +00:00
|
|
|
inline bool isEndOfBuffer( char_t it, char_t end ) {
|
2015-05-19 03:57:13 +00:00
|
|
|
if ( it == end )
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-27 15:43:25 +00:00
|
|
|
--end;
|
2015-05-19 03:57:13 +00:00
|
|
|
}
|
|
|
|
return ( it == end );
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
/** @brief Returns next word separated by a space
|
|
|
|
* @param pBuffer Pointer to data buffer
|
|
|
|
* @param pEnd Pointer to end of buffer
|
|
|
|
* @return Pointer to next space
|
2015-05-19 03:48:29 +00:00
|
|
|
*/
|
|
|
|
template<class Char_T>
|
|
|
|
inline Char_T getNextWord( Char_T pBuffer, Char_T pEnd )
|
|
|
|
{
|
2015-05-19 03:57:13 +00:00
|
|
|
while ( !isEndOfBuffer( pBuffer, pEnd ) )
|
|
|
|
{
|
2017-05-25 20:40:36 +00:00
|
|
|
if ( !IsSpaceOrNewLine( *pBuffer ) || IsLineEnd( *pBuffer ) ) {
|
|
|
|
//if ( *pBuffer != '\\' )
|
|
|
|
break;
|
|
|
|
}
|
2015-05-19 03:57:13 +00:00
|
|
|
pBuffer++;
|
|
|
|
}
|
|
|
|
return pBuffer;
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
/** @brief Returns pointer a next token
|
|
|
|
* @param pBuffer Pointer to data buffer
|
|
|
|
* @param pEnd Pointer to end of buffer
|
|
|
|
* @return Pointer to next token
|
2015-05-19 03:48:29 +00:00
|
|
|
*/
|
|
|
|
template<class Char_T>
|
|
|
|
inline Char_T getNextToken( Char_T pBuffer, Char_T pEnd )
|
|
|
|
{
|
2015-05-19 03:57:13 +00:00
|
|
|
while ( !isEndOfBuffer( pBuffer, pEnd ) )
|
|
|
|
{
|
2015-05-19 03:48:29 +00:00
|
|
|
if( IsSpaceOrNewLine( *pBuffer ) )
|
2015-05-19 03:57:13 +00:00
|
|
|
break;
|
|
|
|
pBuffer++;
|
|
|
|
}
|
|
|
|
return getNextWord( pBuffer, pEnd );
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
/** @brief Skips a line
|
|
|
|
* @param it Iterator set to current position
|
|
|
|
* @param end Iterator set to end of scratch buffer for readout
|
|
|
|
* @param uiLine Current line number in format
|
|
|
|
* @return Current-iterator with new position
|
2015-05-19 03:48:29 +00:00
|
|
|
*/
|
|
|
|
template<class char_t>
|
|
|
|
inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
|
|
|
|
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
|
|
|
|
++it;
|
|
|
|
}
|
2017-05-31 18:18:39 +00:00
|
|
|
|
|
|
|
if ( it != end ) {
|
2015-05-19 03:57:13 +00:00
|
|
|
++it;
|
|
|
|
++uiLine;
|
|
|
|
}
|
|
|
|
// fix .. from time to time there are spaces at the beginning of a material line
|
2017-05-30 19:10:33 +00:00
|
|
|
while ( it != end && ( *it == '\t' || *it == ' ' ) ) {
|
2015-05-19 03:57:13 +00:00
|
|
|
++it;
|
2017-05-30 19:10:33 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
return it;
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
/** @brief Get a name from the current line. Preserve space in the middle,
|
2015-05-19 03:48:29 +00:00
|
|
|
* but trim it at the end.
|
2015-05-19 03:57:13 +00:00
|
|
|
* @param it set to current position
|
|
|
|
* @param end set to end of scratch buffer for readout
|
|
|
|
* @param name Separated name
|
|
|
|
* @return Current-iterator with new position
|
2015-05-19 03:48:29 +00:00
|
|
|
*/
|
|
|
|
template<class char_t>
|
|
|
|
inline char_t getName( char_t it, char_t end, std::string &name )
|
|
|
|
{
|
2015-05-19 03:57:13 +00:00
|
|
|
name = "";
|
2015-05-19 03:48:29 +00:00
|
|
|
if( isEndOfBuffer( it, end ) ) {
|
|
|
|
return end;
|
|
|
|
}
|
2015-05-19 03:52:10 +00:00
|
|
|
|
2016-02-07 19:03:24 +00:00
|
|
|
char *pStart = &( *it );
|
2017-01-31 04:27:35 +00:00
|
|
|
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it )) {
|
2015-05-19 03:57:13 +00:00
|
|
|
++it;
|
|
|
|
}
|
2015-05-19 03:48:29 +00:00
|
|
|
|
2017-01-31 04:27:35 +00:00
|
|
|
while(IsSpace( *it ) ) {
|
2015-05-19 03:57:13 +00:00
|
|
|
--it;
|
|
|
|
}
|
|
|
|
// Get name
|
|
|
|
// if there is no name, and the previous char is a separator, come back to start
|
2016-02-07 19:03:24 +00:00
|
|
|
while (&(*it) < pStart) {
|
2015-05-19 03:57:13 +00:00
|
|
|
++it;
|
|
|
|
}
|
2016-02-07 19:03:24 +00:00
|
|
|
std::string strName( pStart, &(*it) );
|
2016-11-10 23:12:36 +00:00
|
|
|
if ( strName.empty() )
|
|
|
|
return it;
|
|
|
|
else
|
|
|
|
name = strName;
|
|
|
|
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @brief Get a name from the current line. Do not preserve space
|
|
|
|
* in the middle, but trim it at the end.
|
|
|
|
* @param it set to current position
|
|
|
|
* @param end set to end of scratch buffer for readout
|
|
|
|
* @param name Separated name
|
|
|
|
* @return Current-iterator with new position
|
|
|
|
*/
|
|
|
|
template<class char_t>
|
|
|
|
inline char_t getNameNoSpace( char_t it, char_t end, std::string &name )
|
|
|
|
{
|
|
|
|
name = "";
|
|
|
|
if( isEndOfBuffer( it, end ) ) {
|
|
|
|
return end;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *pStart = &( *it );
|
|
|
|
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it )
|
|
|
|
&& !IsSpaceOrNewLine( *it ) ) {
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
|
|
|
|
while( isEndOfBuffer( it, end ) || IsLineEnd( *it )
|
|
|
|
|| IsSpaceOrNewLine( *it ) ) {
|
|
|
|
--it;
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
|
|
|
|
// Get name
|
|
|
|
// if there is no name, and the previous char is a separator, come back to start
|
|
|
|
while (&(*it) < pStart) {
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
std::string strName( pStart, &(*it) );
|
2015-05-19 03:57:13 +00:00
|
|
|
if ( strName.empty() )
|
|
|
|
return it;
|
|
|
|
else
|
|
|
|
name = strName;
|
|
|
|
|
|
|
|
return it;
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
/** @brief Get next word from given line
|
|
|
|
* @param it set to current position
|
|
|
|
* @param end set to end of scratch buffer for readout
|
|
|
|
* @param pBuffer Buffer for next word
|
|
|
|
* @param length Buffer length
|
|
|
|
* @return Current-iterator with new position
|
2015-05-19 03:48:29 +00:00
|
|
|
*/
|
|
|
|
template<class char_t>
|
|
|
|
inline char_t CopyNextWord( char_t it, char_t end, char *pBuffer, size_t length )
|
|
|
|
{
|
2015-05-19 03:57:13 +00:00
|
|
|
size_t index = 0;
|
|
|
|
it = getNextWord<char_t>( it, end );
|
2015-05-19 03:48:29 +00:00
|
|
|
while( !IsSpaceOrNewLine( *it ) && !isEndOfBuffer( it, end ) )
|
2015-05-19 03:57:13 +00:00
|
|
|
{
|
|
|
|
pBuffer[index] = *it ;
|
|
|
|
index++;
|
|
|
|
if (index == length-1)
|
|
|
|
break;
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
pBuffer[ index ] = '\0';
|
|
|
|
return it;
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
/** @brief Get next float from given line
|
|
|
|
* @param it set to current position
|
|
|
|
* @param end set to end of scratch buffer for readout
|
|
|
|
* @param value Separated float value.
|
|
|
|
* @return Current-iterator with new position
|
2015-05-19 03:48:29 +00:00
|
|
|
*/
|
|
|
|
template<class char_t>
|
2016-07-16 02:14:36 +00:00
|
|
|
inline char_t getFloat( char_t it, char_t end, ai_real &value )
|
2015-05-19 03:48:29 +00:00
|
|
|
{
|
2015-05-19 03:57:13 +00:00
|
|
|
static const size_t BUFFERSIZE = 1024;
|
|
|
|
char buffer[ BUFFERSIZE ];
|
|
|
|
it = CopyNextWord<char_t>( it, end, buffer, BUFFERSIZE );
|
2016-07-16 02:14:36 +00:00
|
|
|
value = (ai_real) fast_atof( buffer );
|
2015-05-19 03:48:29 +00:00
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
return it;
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 03:57:13 +00:00
|
|
|
/** @brief Will perform a simple tokenize.
|
|
|
|
* @param str String to tokenize.
|
|
|
|
* @param tokens Array with tokens, will be empty if no token was found.
|
|
|
|
* @param delimiters Delimiter for tokenize.
|
|
|
|
* @return Number of found token.
|
2015-05-19 03:48:29 +00:00
|
|
|
*/
|
|
|
|
template<class string_type>
|
2015-05-19 03:52:10 +00:00
|
|
|
unsigned int tokenize( const string_type& str, std::vector<string_type>& tokens,
|
2015-05-19 03:57:13 +00:00
|
|
|
const string_type& delimiters )
|
2015-05-19 03:48:29 +00:00
|
|
|
{
|
2015-05-19 03:57:13 +00:00
|
|
|
// Skip delimiters at beginning.
|
|
|
|
typename string_type::size_type lastPos = str.find_first_not_of( delimiters, 0 );
|
|
|
|
|
|
|
|
// Find first "non-delimiter".
|
|
|
|
typename string_type::size_type pos = str.find_first_of( delimiters, lastPos );
|
|
|
|
while ( string_type::npos != pos || string_type::npos != lastPos )
|
|
|
|
{
|
|
|
|
// Found a token, add it to the vector.
|
|
|
|
string_type tmp = str.substr(lastPos, pos - lastPos);
|
|
|
|
if ( !tmp.empty() && ' ' != tmp[ 0 ] )
|
|
|
|
tokens.push_back( tmp );
|
|
|
|
|
|
|
|
// Skip delimiters. Note the "not_of"
|
|
|
|
lastPos = str.find_first_not_of( delimiters, pos );
|
|
|
|
|
|
|
|
// Find next "non-delimiter"
|
|
|
|
pos = str.find_first_of( delimiters, lastPos );
|
|
|
|
}
|
|
|
|
|
|
|
|
return static_cast<unsigned int>( tokens.size() );
|
2015-05-19 03:48:29 +00:00
|
|
|
}
|
|
|
|
|
2015-12-13 19:32:09 +00:00
|
|
|
template <class string_type>
|
|
|
|
string_type trim_whitespaces(string_type str)
|
|
|
|
{
|
|
|
|
while (!str.empty() && IsSpace(str[0])) str.erase(0);
|
|
|
|
while (!str.empty() && IsSpace(str[str.length() - 1])) str.erase(str.length() - 1);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2016-10-11 10:29:40 +00:00
|
|
|
template<class T>
|
|
|
|
bool hasLineEnd( T it, T end ) {
|
|
|
|
bool hasLineEnd( false );
|
|
|
|
while ( !isEndOfBuffer( it, end ) ) {
|
|
|
|
it++;
|
|
|
|
if ( IsLineEnd( it ) ) {
|
|
|
|
hasLineEnd = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hasLineEnd;
|
|
|
|
}
|
|
|
|
|
2015-05-19 03:48:29 +00:00
|
|
|
} // Namespace Assimp
|
|
|
|
|
|
|
|
#endif // OBJ_TOOLS_H_INC
|