2015-05-19 03:48:29 +00:00
|
|
|
/*
|
|
|
|
Open Asset Import Library (assimp)
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
|
2020-01-20 13:53:12 +00:00
|
|
|
Copyright (c) 2006-2020, assimp team
|
2018-01-28 18:42:05 +00:00
|
|
|
|
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/ParsingUtils.h>
|
2020-03-15 09:21:08 +00:00
|
|
|
#include <assimp/fast_atof.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
|
|
|
*/
|
2020-03-15 09:21:08 +00:00
|
|
|
template <class char_t>
|
|
|
|
inline bool isEndOfBuffer(char_t it, char_t end) {
|
|
|
|
if (it == end) {
|
2015-05-19 03:57:13 +00:00
|
|
|
return true;
|
2020-03-15 09:21:08 +00:00
|
|
|
} else {
|
2016-11-27 15:43:25 +00:00
|
|
|
--end;
|
2015-05-19 03:57:13 +00:00
|
|
|
}
|
2020-03-15 09:21:08 +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
|
|
|
*/
|
2020-03-15 09:21:08 +00:00
|
|
|
template <class Char_T>
|
|
|
|
inline Char_T getNextWord(Char_T pBuffer, Char_T pEnd) {
|
|
|
|
while (!isEndOfBuffer(pBuffer, pEnd)) {
|
|
|
|
if (!IsSpaceOrNewLine(*pBuffer) || IsLineEnd(*pBuffer)) {
|
2017-05-25 20:40:36 +00:00
|
|
|
//if ( *pBuffer != '\\' )
|
2020-03-15 09:21:08 +00:00
|
|
|
break;
|
2017-05-25 20:40:36 +00:00
|
|
|
}
|
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
|
|
|
*/
|
2020-03-15 09:21:08 +00:00
|
|
|
template <class Char_T>
|
|
|
|
inline Char_T getNextToken(Char_T pBuffer, Char_T pEnd) {
|
|
|
|
while (!isEndOfBuffer(pBuffer, pEnd)) {
|
|
|
|
if (IsSpaceOrNewLine(*pBuffer))
|
2015-05-19 03:57:13 +00:00
|
|
|
break;
|
|
|
|
pBuffer++;
|
|
|
|
}
|
2020-03-15 09:21:08 +00:00
|
|
|
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
|
|
|
*/
|
2020-03-15 09:21:08 +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)) {
|
2015-05-19 03:48:29 +00:00
|
|
|
++it;
|
|
|
|
}
|
2020-03-15 09:21:08 +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
|
2020-03-15 09:21:08 +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
|
|
|
*/
|
2020-03-15 09:21:08 +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 = "";
|
2020-03-15 09:21:08 +00:00
|
|
|
if (isEndOfBuffer(it, end)) {
|
2015-05-19 03:48:29 +00:00
|
|
|
return end;
|
|
|
|
}
|
2015-05-19 03:52:10 +00:00
|
|
|
|
2020-03-15 09:21:08 +00:00
|
|
|
char *pStart = &(*it);
|
|
|
|
while (!isEndOfBuffer(it, end) && !IsLineEnd(*it)) {
|
2015-05-19 03:57:13 +00:00
|
|
|
++it;
|
|
|
|
}
|
2015-05-19 03:48:29 +00:00
|
|
|
|
2020-03-15 09:21:08 +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;
|
|
|
|
}
|
2020-03-15 09:21:08 +00:00
|
|
|
std::string strName(pStart, &(*it));
|
|
|
|
if (strName.empty())
|
2016-11-10 23:12:36 +00:00
|
|
|
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
|
|
|
|
*/
|
2020-03-15 09:21:08 +00:00
|
|
|
template <class char_t>
|
|
|
|
inline char_t getNameNoSpace(char_t it, char_t end, std::string &name) {
|
2016-11-10 23:12:36 +00:00
|
|
|
name = "";
|
2020-03-15 09:21:08 +00:00
|
|
|
if (isEndOfBuffer(it, end)) {
|
2016-11-10 23:12:36 +00:00
|
|
|
return end;
|
|
|
|
}
|
|
|
|
|
2020-03-15 09:21:08 +00:00
|
|
|
char *pStart = &(*it);
|
|
|
|
while (!isEndOfBuffer(it, end) && !IsLineEnd(*it) && !IsSpaceOrNewLine(*it)) {
|
2016-11-10 23:12:36 +00:00
|
|
|
++it;
|
|
|
|
}
|
|
|
|
|
2020-03-15 09:21:08 +00:00
|
|
|
while (isEndOfBuffer(it, end) || IsLineEnd(*it) || IsSpaceOrNewLine(*it)) {
|
2016-11-10 23:12:36 +00:00
|
|
|
--it;
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
|
|
|
|
// Get name
|
|
|
|
// if there is no name, and the previous char is a separator, come back to start
|
|
|
|
while (&(*it) < pStart) {
|
|
|
|
++it;
|
|
|
|
}
|
2020-03-15 09:21:08 +00:00
|
|
|
std::string strName(pStart, &(*it));
|
|
|
|
if (strName.empty())
|
2015-05-19 03:57:13 +00:00
|
|
|
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
|
|
|
*/
|
2020-03-15 09:21:08 +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;
|
2020-03-15 09:21:08 +00:00
|
|
|
it = getNextWord<char_t>(it, end);
|
|
|
|
while (!IsSpaceOrNewLine(*it) && !isEndOfBuffer(it, end)) {
|
|
|
|
pBuffer[index] = *it;
|
2015-05-19 03:57:13 +00:00
|
|
|
index++;
|
2020-03-15 09:21:08 +00:00
|
|
|
if (index == length - 1)
|
2015-05-19 03:57:13 +00:00
|
|
|
break;
|
|
|
|
++it;
|
|
|
|
}
|
2020-03-15 09:21:08 +00:00
|
|
|
pBuffer[index] = '\0';
|
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 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
|
|
|
*/
|
2020-03-15 09:21:08 +00:00
|
|
|
template <class char_t>
|
|
|
|
inline char_t getFloat(char_t it, char_t end, ai_real &value) {
|
2015-05-19 03:57:13 +00:00
|
|
|
static const size_t BUFFERSIZE = 1024;
|
2020-03-15 09:21:08 +00:00
|
|
|
char buffer[BUFFERSIZE];
|
|
|
|
it = CopyNextWord<char_t>(it, end, buffer, BUFFERSIZE);
|
|
|
|
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
|
|
|
*/
|
2020-03-15 09:21:08 +00:00
|
|
|
template <class string_type>
|
|
|
|
unsigned int tokenize(const string_type &str, std::vector<string_type> &tokens,
|
|
|
|
const string_type &delimiters) {
|
2015-05-19 03:57:13 +00:00
|
|
|
// Skip delimiters at beginning.
|
2020-03-15 09:21:08 +00:00
|
|
|
typename string_type::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
2015-05-19 03:57:13 +00:00
|
|
|
|
|
|
|
// Find first "non-delimiter".
|
2020-03-15 09:21:08 +00:00
|
|
|
typename string_type::size_type pos = str.find_first_of(delimiters, lastPos);
|
|
|
|
while (string_type::npos != pos || string_type::npos != lastPos) {
|
2015-05-19 03:57:13 +00:00
|
|
|
// Found a token, add it to the vector.
|
|
|
|
string_type tmp = str.substr(lastPos, pos - lastPos);
|
2020-03-15 09:21:08 +00:00
|
|
|
if (!tmp.empty() && ' ' != tmp[0])
|
|
|
|
tokens.push_back(tmp);
|
2015-05-19 03:57:13 +00:00
|
|
|
|
|
|
|
// Skip delimiters. Note the "not_of"
|
2020-03-15 09:21:08 +00:00
|
|
|
lastPos = str.find_first_not_of(delimiters, pos);
|
2015-05-19 03:57:13 +00:00
|
|
|
|
|
|
|
// Find next "non-delimiter"
|
2020-03-15 09:21:08 +00:00
|
|
|
pos = str.find_first_of(delimiters, lastPos);
|
2015-05-19 03:57:13 +00:00
|
|
|
}
|
|
|
|
|
2020-03-15 09:21:08 +00:00
|
|
|
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>
|
2020-03-15 09:21:08 +00:00
|
|
|
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);
|
2015-12-13 19:32:09 +00:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2020-03-15 09:21:08 +00:00
|
|
|
template <class T>
|
|
|
|
bool hasLineEnd(T it, T end) {
|
|
|
|
bool hasLineEnd(false);
|
|
|
|
while (!isEndOfBuffer(it, end)) {
|
2016-10-11 10:29:40 +00:00
|
|
|
it++;
|
2020-03-15 09:21:08 +00:00
|
|
|
if (IsLineEnd(it)) {
|
2016-10-11 10:29:40 +00:00
|
|
|
hasLineEnd = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hasLineEnd;
|
|
|
|
}
|
|
|
|
|
2015-05-19 03:48:29 +00:00
|
|
|
} // Namespace Assimp
|
|
|
|
|
|
|
|
#endif // OBJ_TOOLS_H_INC
|