diff options
Diffstat (limited to 'src/mesh/assimp-master/code/AssetLib/Obj/ObjFileParser.cpp')
-rw-r--r-- | src/mesh/assimp-master/code/AssetLib/Obj/ObjFileParser.cpp | 838 |
1 files changed, 0 insertions, 838 deletions
diff --git a/src/mesh/assimp-master/code/AssetLib/Obj/ObjFileParser.cpp b/src/mesh/assimp-master/code/AssetLib/Obj/ObjFileParser.cpp deleted file mode 100644 index 2e998a8..0000000 --- a/src/mesh/assimp-master/code/AssetLib/Obj/ObjFileParser.cpp +++ /dev/null @@ -1,838 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2020, assimp team - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the 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. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -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 -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ -#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER - -#include "ObjFileParser.h" -#include "ObjFileData.h" -#include "ObjFileMtlImporter.h" -#include "ObjTools.h" -#include <assimp/BaseImporter.h> -#include <assimp/DefaultIOSystem.h> -#include <assimp/ParsingUtils.h> -#include <assimp/DefaultLogger.hpp> -#include <assimp/Importer.hpp> -#include <cstdlib> -#include <memory> -#include <utility> - -namespace Assimp { - -constexpr char ObjFileParser::DEFAULT_MATERIAL[]; - -ObjFileParser::ObjFileParser() : - m_DataIt(), - m_DataItEnd(), - m_pModel(nullptr), - m_uiLine(0), - m_buffer(), - m_pIO(nullptr), - m_progress(nullptr), - m_originalObjFileName() { - std::fill_n(m_buffer, Buffersize, '\0'); -} - -ObjFileParser::ObjFileParser(IOStreamBuffer<char> &streamBuffer, const std::string &modelName, - IOSystem *io, ProgressHandler *progress, - const std::string &originalObjFileName) : - m_DataIt(), - m_DataItEnd(), - m_pModel(nullptr), - m_uiLine(0), - m_buffer(), - m_pIO(io), - m_progress(progress), - m_originalObjFileName(originalObjFileName) { - std::fill_n(m_buffer, Buffersize, '\0'); - - // Create the model instance to store all the data - m_pModel.reset(new ObjFile::Model()); - m_pModel->m_ModelName = modelName; - - // create default material and store it - m_pModel->m_pDefaultMaterial = new ObjFile::Material; - m_pModel->m_pDefaultMaterial->MaterialName.Set(DEFAULT_MATERIAL); - m_pModel->m_MaterialLib.push_back(DEFAULT_MATERIAL); - m_pModel->m_MaterialMap[DEFAULT_MATERIAL] = m_pModel->m_pDefaultMaterial; - - // Start parsing the file - parseFile(streamBuffer); -} - -ObjFileParser::~ObjFileParser() { -} - -void ObjFileParser::setBuffer(std::vector<char> &buffer) { - m_DataIt = buffer.begin(); - m_DataItEnd = buffer.end(); -} - -ObjFile::Model *ObjFileParser::GetModel() const { - return m_pModel.get(); -} - -void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) { - // only update every 100KB or it'll be too slow - //const unsigned int updateProgressEveryBytes = 100 * 1024; - unsigned int progressCounter = 0; - const unsigned int bytesToProcess = static_cast<unsigned int>(streamBuffer.size()); - const unsigned int progressTotal = bytesToProcess; - unsigned int processed = 0; - size_t lastFilePos(0); - - std::vector<char> buffer; - while (streamBuffer.getNextDataLine(buffer, '\\')) { - m_DataIt = buffer.begin(); - m_DataItEnd = buffer.end(); - - // Handle progress reporting - const size_t filePos(streamBuffer.getFilePos()); - if (lastFilePos < filePos) { - processed = static_cast<unsigned int>(filePos); - lastFilePos = filePos; - progressCounter++; - m_progress->UpdateFileRead(processed, progressTotal); - } - - // parse line - switch (*m_DataIt) { - case 'v': // Parse a vertex texture coordinate - { - ++m_DataIt; - if (*m_DataIt == ' ' || *m_DataIt == '\t') { - 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; - size_t dim = getTexCoordVector(m_pModel->m_TextureCoord); - m_pModel->m_TextureCoordDim = std::max(m_pModel->m_TextureCoordDim, (unsigned int)dim); - } else if (*m_DataIt == 'n') { - // Read in normal vector definition - ++m_DataIt; - getVector3(m_pModel->m_Normals); - } - } break; - - case 'p': // Parse a face, line or point statement - case 'l': - case 'f': { - getFace(*m_DataIt == 'f' ? aiPrimitiveType_POLYGON : (*m_DataIt == 'l' ? aiPrimitiveType_LINE : aiPrimitiveType_POINT)); - } break; - - case '#': // Parse a comment - { - getComment(); - } break; - - case 'u': // Parse a material desc. setter - { - 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') - { - 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 if (name == "mtllib") - getMaterialLib(); - else - goto pf_skip_line; - } break; - - case 'g': // Parse group name - { - getGroupName(); - } break; - - case 's': // Parse group number - { - getGroupNumber(); - } break; - - case 'o': // Parse object name - { - getObjectName(); - } break; - - default: { - pf_skip_line: - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); - } break; - } - } -} - -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++; - if (index == length - 1) { - break; - } - ++m_DataIt; - } - - ai_assert(index < length); - pBuffer[index] = '\0'; -} - -static bool isDataDefinitionEnd(const char *tmp) { - if (*tmp == '\\') { - tmp++; - if (IsLineEnd(*tmp)) { - return true; - } - } - return false; -} - -static bool isNanOrInf(const char *in) { - // Look for "nan" or "inf", case insensitive - return ((in[0] == 'N' || in[0] == 'n') && ASSIMP_strincmp(in, "nan", 3) == 0) || - ((in[0] == 'I' || in[0] == 'i') && ASSIMP_strincmp(in, "inf", 3) == 0); -} - -size_t ObjFileParser::getNumComponentsInDataDefinition() { - size_t numComponents(0); - const char *tmp(&m_DataIt[0]); - 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) || isNanOrInf(tmp)); - SkipToken(tmp); - if (isNum) { - ++numComponents; - } - if (!SkipSpaces(&tmp)) { - break; - } - } - return numComponents; -} - -size_t ObjFileParser::getTexCoordVector(std::vector<aiVector3D> &point3d_array) { - size_t numComponents = getNumComponentsInDataDefinition(); - ai_real x, y, z; - if (2 == numComponents) { - copyNextWord(m_buffer, Buffersize); - x = (ai_real)fast_atof(m_buffer); - - copyNextWord(m_buffer, Buffersize); - y = (ai_real)fast_atof(m_buffer); - z = 0.0; - } else if (3 == numComponents) { - 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); - } else { - throw DeadlyImportError("OBJ: Invalid number of components"); - } - - // Coerce nan and inf to 0 as is the OBJ default value - if (!std::isfinite(x)) - x = 0; - - if (!std::isfinite(y)) - y = 0; - - if (!std::isfinite(z)) - z = 0; - - point3d_array.emplace_back(x, y, z); - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); - return numComponents; -} - -void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) { - ai_real x, y, z; - 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); - - point3d_array.emplace_back(x, y, z); - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); -} - -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); - - if (w == 0) - throw DeadlyImportError("OBJ: Invalid component in homogeneous vector (Division by zero)"); - - point3d_array.emplace_back(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) { - ai_real x, y, z; - 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); - - point3d_array_a.emplace_back(x, y, z); - - 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); - - point3d_array_b.emplace_back(x, y, z); - - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); -} - -void ObjFileParser::getVector2(std::vector<aiVector2D> &point2d_array) { - ai_real x, y; - copyNextWord(m_buffer, Buffersize); - x = (ai_real)fast_atof(m_buffer); - - copyNextWord(m_buffer, Buffersize); - y = (ai_real)fast_atof(m_buffer); - - point2d_array.emplace_back(x, y); - - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); -} - -static const std::string DefaultObjName = "defaultobject"; - -void ObjFileParser::getFace(aiPrimitiveType type) { - m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); - if (m_DataIt == m_DataItEnd || *m_DataIt == '\0') { - return; - } - - ObjFile::Face *face = new ObjFile::Face(type); - bool hasNormal = false; - - 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 iPos = 0; - while (m_DataIt != m_DataItEnd) { - int iStep = 1; - - if (IsLineEnd(*m_DataIt)) { - break; - } - - if (*m_DataIt == '/') { - if (type == aiPrimitiveType_POINT) { - ASSIMP_LOG_ERROR("Obj: Separator unexpected in point statement"); - } - iPos++; - } else if (IsSpaceOrNewLine(*m_DataIt)) { - iPos = 0; - } else { - //OBJ USES 1 Base ARRAYS!!!! - const int iVal(::atoi(&(*m_DataIt))); - - // increment iStep position based off of the sign and # of digits - int tmp = iVal; - if (iVal < 0) { - ++iStep; - } - while ((tmp = tmp / 10) != 0) { - ++iStep; - } - - if (iPos == 1 && !vt && vn) - iPos = 2; // skip texture coords for normals if there are no tex coords - - if (iVal > 0) { - // Store parsed index - 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 { - reportErrorTokenInFace(); - } - } else if (iVal < 0) { - // Store relatively index - 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 { - reportErrorTokenInFace(); - } - } else { - //On error, std::atoi will return 0 which is not a valid value - delete face; - throw DeadlyImportError("OBJ: Invalid face indice"); - } - } - m_DataIt += iStep; - } - - if (face->m_vertices.empty()) { - ASSIMP_LOG_ERROR("Obj: Ignoring empty face"); - // skip line and clean up - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); - delete face; - return; - } - - // Set active material, if one set - if (nullptr != m_pModel->m_pCurrentMaterial) { - face->m_pMaterial = m_pModel->m_pCurrentMaterial; - } else { - face->m_pMaterial = m_pModel->m_pDefaultMaterial; - } - - // Create a default object, if nothing is there - if (nullptr == m_pModel->m_pCurrent) { - createObject(DefaultObjName); - } - - // Assign face to mesh - if (nullptr == m_pModel->m_pCurrentMesh) { - createMesh(DefaultObjName); - } - - // Store the face - m_pModel->m_pCurrentMesh->m_Faces.push_back(face); - 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; - } - // Skip the rest of the line - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); -} - -void ObjFileParser::getMaterialDesc() { - // Get next data for material data - m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); - if (m_DataIt == m_DataItEnd) { - return; - } - - char *pStart = &(*m_DataIt); - while (m_DataIt != m_DataItEnd && !IsLineEnd(*m_DataIt)) { - ++m_DataIt; - } - - // In some cases we should ignore this 'usemtl' command, this variable helps us to do so - bool skip = false; - - // Get name - std::string strName(pStart, &(*m_DataIt)); - strName = trim_whitespaces(strName); - if (strName.empty()) - skip = true; - - // 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)) { - skip = true; - } - - 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, 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. - ASSIMP_LOG_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); - } - - m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strName); - } - - // Skip rest of line - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); -} - -// ------------------------------------------------------------------- -// Get a comment, values will be skipped -void ObjFileParser::getComment() { - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); -} - -// ------------------------------------------------------------------- -// Get material library from file. -void ObjFileParser::getMaterialLib() { - // Translate tuple - m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); - if (m_DataIt == m_DataItEnd) { - return; - } - - char *pStart = &(*m_DataIt); - while (m_DataIt != m_DataItEnd && !IsLineEnd(*m_DataIt)) { - ++m_DataIt; - } - - // Check for existence - const std::string strMatName(pStart, &(*m_DataIt)); - std::string absName; - - // Check if directive is valid. - if (0 == strMatName.length()) { - ASSIMP_LOG_WARN("OBJ: no name for material library specified."); - return; - } - - if (m_pIO->StackSize() > 0) { - std::string path = m_pIO->CurrentDirectory(); - if ('/' != *path.rbegin()) { - path += '/'; - } - absName += path; - absName += strMatName; - } else { - absName = strMatName; - } - - IOStream *pFile = m_pIO->Open(absName); - if (nullptr == pFile) { - ASSIMP_LOG_ERROR("OBJ: Unable to locate material file ", strMatName); - std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl"; - ASSIMP_LOG_INFO("OBJ: Opening fallback material file ", strMatFallbackName); - pFile = m_pIO->Open(strMatFallbackName); - if (!pFile) { - ASSIMP_LOG_ERROR("OBJ: Unable to locate fallback material file ", strMatFallbackName); - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); - return; - } - } - - // Import material library data from file. - // Some exporters (e.g. Silo) will happily write out empty - // material files if the model doesn't use any materials, so we - // allow that. - std::vector<char> buffer; - BaseImporter::TextFileToBuffer(pFile, buffer, BaseImporter::ALLOW_EMPTY); - m_pIO->Close(pFile); - - // Importing the material library - ObjFileMtlImporter mtlImporter(buffer, strMatName, m_pModel.get()); -} - -// ------------------------------------------------------------------- -// Set a new material definition as the current material. -void ObjFileParser::getNewMaterial() { - m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); - m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd); - if (m_DataIt == m_DataItEnd) { - return; - } - - char *pStart = &(*m_DataIt); - std::string strMat(pStart, *m_DataIt); - while (m_DataIt != m_DataItEnd && IsSpaceOrNewLine(*m_DataIt)) { - ++m_DataIt; - } - std::map<std::string, ObjFile::Material *>::iterator it = m_pModel->m_MaterialMap.find(strMat); - if (it == m_pModel->m_MaterialMap.end()) { - // Show a warning, if material was not found - ASSIMP_LOG_WARN("OBJ: Unsupported material requested: ", strMat); - m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial; - } else { - // Set new material - if (needsNewMesh(strMat)) { - createMesh(strMat); - } - m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strMat); - } - - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); -} - -// ------------------------------------------------------------------- -int ObjFileParser::getMaterialIndex(const std::string &strMaterialName) { - int mat_index = -1; - if (strMaterialName.empty()) { - return mat_index; - } - for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index) { - if (strMaterialName == m_pModel->m_MaterialLib[index]) { - mat_index = (int)index; - break; - } - } - return mat_index; -} - -// ------------------------------------------------------------------- -// Getter for a group name. -void ObjFileParser::getGroupName() { - std::string groupName; - - // 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 != groupName) { - // Search for already existing entry - ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(groupName); - - // We are mapping groups into the object structure - 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[groupName] = pFaceIDArray; - m_pModel->m_pGroupFaceIDs = (pFaceIDArray); - } else { - m_pModel->m_pGroupFaceIDs = (*it).second; - } - m_pModel->m_strActiveGroup = groupName; - } - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); -} - -// ------------------------------------------------------------------- -// Not supported -void ObjFileParser::getGroupNumber() { - // Not used - - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); -} - -// ------------------------------------------------------------------- -// Not supported -void ObjFileParser::getGroupNumberAndResolution() { - // Not used - - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); -} - -// ------------------------------------------------------------------- -// Stores values for a new object instance, name will be used to -// identify it. -void ObjFileParser::getObjectName() { - m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); - if (m_DataIt == m_DataItEnd) { - return; - } - char *pStart = &(*m_DataIt); - while (m_DataIt != m_DataItEnd && !IsSpaceOrNewLine(*m_DataIt)) { - ++m_DataIt; - } - - std::string strObjectName(pStart, &(*m_DataIt)); - if (!strObjectName.empty()) { - // Reset current object - m_pModel->m_pCurrent = nullptr; - - // Search for actual object - for (std::vector<ObjFile::Object *>::const_iterator it = m_pModel->m_Objects.begin(); - it != m_pModel->m_Objects.end(); - ++it) { - if ((*it)->m_strObjName == strObjectName) { - m_pModel->m_pCurrent = *it; - break; - } - } - - // Allocate a new object, if current one was not found before - if (nullptr == m_pModel->m_pCurrent) { - createObject(strObjectName); - } - } - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); -} -// ------------------------------------------------------------------- -// Creates a new object instance -void ObjFileParser::createObject(const std::string &objName) { - ai_assert(nullptr != m_pModel); - - m_pModel->m_pCurrent = new ObjFile::Object; - m_pModel->m_pCurrent->m_strObjName = objName; - m_pModel->m_Objects.push_back(m_pModel->m_pCurrent); - - createMesh(objName); - - if (m_pModel->m_pCurrentMaterial) { - m_pModel->m_pCurrentMesh->m_uiMaterialIndex = - getMaterialIndex(m_pModel->m_pCurrentMaterial->MaterialName.data); - m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial; - } -} -// ------------------------------------------------------------------- -// Creates a new mesh -void ObjFileParser::createMesh(const std::string &meshName) { - ai_assert(nullptr != m_pModel); - - m_pModel->m_pCurrentMesh = new ObjFile::Mesh(meshName); - m_pModel->m_Meshes.push_back(m_pModel->m_pCurrentMesh); - unsigned int meshId = static_cast<unsigned int>(m_pModel->m_Meshes.size() - 1); - if (nullptr != m_pModel->m_pCurrent) { - m_pModel->m_pCurrent->m_Meshes.push_back(meshId); - } else { - ASSIMP_LOG_ERROR("OBJ: No object detected to attach a new mesh instance."); - } -} - -// ------------------------------------------------------------------- -// Returns true, if a new mesh must be created. -bool ObjFileParser::needsNewMesh(const std::string &materialName) { - // If no mesh data yet - if (m_pModel->m_pCurrentMesh == nullptr) { - return true; - } - bool newMat = false; - int matIdx = getMaterialIndex(materialName); - int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex; - 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.empty()) { - // New material -> only one material per mesh, so we need to create a new - // material - newMat = true; - } - return newMat; -} - -// ------------------------------------------------------------------- -// Shows an error in parsing process. -void ObjFileParser::reportErrorTokenInFace() { - m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); - ASSIMP_LOG_ERROR("OBJ: Not supported token in face description detected"); -} - -// ------------------------------------------------------------------- - -} // Namespace Assimp - -#endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER |