diff --git a/.gitignore b/.gitignore index 53a2a9a..ead02e0 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,4 @@ CMakeList.txt.user* /bin /bii .vscode -build +build* diff --git a/cmake-lib/CMakeLists.txt b/cmake-lib/CMakeLists.txt new file mode 100644 index 0000000..030763c --- /dev/null +++ b/cmake-lib/CMakeLists.txt @@ -0,0 +1,77 @@ +project(PMUC) +cmake_minimum_required(VERSION 2.8) + +# Set C++11 flags to makesome function work +if(UNIX) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=gnu++0x") +endif() + +set (SRC_LIST + ../src/api/rvmcolorhelper.cpp + ../src/api/rvmparser.cpp + ../src/api/rvmreader.cpp + ../src/api/vector3f.cpp +) + +set (HEADER_LIST + ../src/api/lib_export.h + ../src/api/rvmcolorhelper.h + ../src/api/rvmparser.h + ../src/api/rvmprimitive.h + ../src/api/rvmreader.h + ../src/api/vector3f.h +) + +set (USE_MESH_HELPER TRUE CACHE BOOL + "Indicates whether it is needed to include rvmmeshhelper class in the library") + +if (USE_MESH_HELPER) + # Add OpenGL dependencies + set (OpenGL_GL_PREFERENCE LEGACY) + find_package (OpenGL REQUIRED) + + list (APPEND SRC_LIST ../src/api/rvmmeshhelper.cpp) + list (APPEND HEADER_LIST ../src/api/rvmmeshhelper.h) + +endif() + +add_library (${PROJECT_NAME} SHARED "${SRC_LIST}") + +set_target_properties (${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "${HEADER_LIST}") + + +install(TARGETS ${PROJECT_NAME} + CONFIGURATIONS Release + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + PUBLIC_HEADER DESTINATION include/pmuc) + +install(TARGETS ${PROJECT_NAME} + CONFIGURATIONS Debug + RUNTIME DESTINATION bind + ARCHIVE DESTINATION libd + LIBRARY DESTINATION libd + PUBLIC_HEADER DESTINATION include/pmuc) + +install(TARGETS ${PROJECT_NAME} + CONFIGURATIONS RelWithDebInfo + RUNTIME DESTINATION bini + ARCHIVE DESTINATION libi + LIBRARY DESTINATION libi + PUBLIC_HEADER DESTINATION include/pmuc) + +if (WIN32) + install(FILES $ CONFIGURATIONS Debug + DESTINATION bind OPTIONAL) + install(FILES $ CONFIGURATIONS RelWithDebInfo + DESTINATION bini OPTIONAL) +endif() + +if (USE_MESH_HELPER) + # Include OpenGL lib + target_link_libraries(${PROJECT_NAME} ${OPENGL_LIBRARIES}) +endif() + +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11) +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) diff --git a/src/api/lib_export.h b/src/api/lib_export.h new file mode 100644 index 0000000..9b2f94d --- /dev/null +++ b/src/api/lib_export.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(_WIN32) + #if defined(PMUC_EXPORTS) + #define DLL_PMUC_EXPORT __declspec(dllexport) + #else // !BUILDING_DLL + #define DLL_PMUC_EXPORT __declspec(dllimport) + #endif // BUILDING_DLL +#else // / UNIX / + #define DLL_PMUC_EXPORT +#endif // diff --git a/src/api/rvmcolorhelper.h b/src/api/rvmcolorhelper.h index 00937be..49f5b93 100644 --- a/src/api/rvmcolorhelper.h +++ b/src/api/rvmcolorhelper.h @@ -22,19 +22,21 @@ #ifndef RVMCOLORHELPER_H #define RVMCOLORHELPER_H +#include "lib_export.h" + #include class RVMColorHelper { public: - RVMColorHelper(); + DLL_PMUC_EXPORT RVMColorHelper(); /** * @brief Simple static method to return rgb floats from a PDMS color index. Use the conversion values from Navisworks * @param index the PDMS material index * @return RGB floats between 0. and 1. */ - static const std::vector color(unsigned char index); + DLL_PMUC_EXPORT static const std::vector color(unsigned char index); }; #endif // RVMCOLORHELPER_H diff --git a/src/api/rvmmeshhelper.cpp b/src/api/rvmmeshhelper.cpp index a476a43..3bb8822 100644 --- a/src/api/rvmmeshhelper.cpp +++ b/src/api/rvmmeshhelper.cpp @@ -65,7 +65,7 @@ static const unsigned long cube_index[] = {0, 1, 2, 2, 3, 0, 4, 7, 5, 5 void CALLBACK tessVertexData(void* vertex_data, void* polygon_data) { Mesh* userData = (Mesh*)polygon_data; - userData->positionIndex.push_back((unsigned long)vertex_data); + userData->positionIndex.push_back(static_cast(reinterpret_cast(vertex_data))); } void CALLBACK tessEdgeFlag(GLboolean flag, void* polygon_data) {} @@ -79,10 +79,10 @@ void CALLBACK tessCombineData(GLdouble newVert[3], void** outData, void* polygon_data) { Mesh* userData = (Mesh*)polygon_data; - unsigned long index = static_cast(userData->positions.size()); + size_t index = userData->positions.size(); userData->positions.push_back(Vector3F(float(newVert[0]), float(newVert[1]), float(newVert[2]))); userData->normals.push_back(Vector3F(0.0f, 1.0f, 0.0f)); - *outData = (void*)index; + *outData = reinterpret_cast(index); }; const Mesh RVMMeshHelper2::makeBox(const Primitives::Box& inBox, const float& maxSideSize, const int& minSides) { @@ -875,8 +875,8 @@ const Mesh RVMMeshHelper2::makeSphericalDish(const Primitives::SphericalDish& sD return result; } -pair createIndex(std::vector& references, const Vertex& newValue) { - unsigned int results = std::find(references.begin(), references.end(), newValue) - references.begin(); +pair createIndex(std::vector& references, const Vertex& newValue) { + size_t results = std::find(references.begin(), references.end(), newValue) - references.begin(); if (results == references.size()) { references.push_back(newValue); return make_pair(results, true); @@ -888,7 +888,7 @@ void RVMMeshHelper2::tesselateFacetGroup(const std::vector indexedVertices; - vector indexArray; + vector indexArray; gluTessCallback(tobj, GLU_TESS_EDGE_FLAG_DATA, (void(CALLBACK*)())tessEdgeFlag); gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (void(CALLBACK*)())tessVertexData); @@ -900,7 +900,7 @@ void RVMMeshHelper2::tesselateFacetGroup(const std::vector res = createIndex(indexedVertices, vertices[i][j][k]); + pair res = createIndex(indexedVertices, vertices[i][j][k]); indexArray.push_back(res.first); if (res.second) { userData->positions.push_back(vertices[i][j][k].first); @@ -923,7 +923,7 @@ void RVMMeshHelper2::tesselateFacetGroup(const std::vector(indexArray[tessIndex])); tessIndex++; } gluTessEndContour(tobj); diff --git a/src/api/rvmmeshhelper.h b/src/api/rvmmeshhelper.h index 5b485f7..6d4d413 100644 --- a/src/api/rvmmeshhelper.h +++ b/src/api/rvmmeshhelper.h @@ -29,6 +29,8 @@ #include "vector3f.h" #include "rvmprimitive.h" +#include "lib_export.h" + struct Mesh { std::vector positionIndex; std::vector normalIndex; @@ -54,10 +56,11 @@ enum PrimitiveTypes { typedef std::pair Vertex; + class RVMMeshHelper2 { public: - RVMMeshHelper2(); + DLL_PMUC_EXPORT RVMMeshHelper2(); public: /** @@ -67,7 +70,7 @@ class RVMMeshHelper2 * @param minSides not used here. For consistency with the other methods. * @return vertexes coordinates and their index. */ - static const Mesh makePyramid(const Primitives::Pyramid& inP, const float& maxSideSize, const int& minSides); + DLL_PMUC_EXPORT static const Mesh makePyramid(const Primitives::Pyramid& inP, const float& maxSideSize, const int& minSides); /** * @brief Builds up indexed coordinates for the described box @@ -78,7 +81,7 @@ class RVMMeshHelper2 * @param minSides not used here. For consistency with the other methods. * @return vertexes coordinates and their index. */ - static const Mesh makeBox(const Primitives::Box& box, const float& maxSideSize, const int& minSides); + DLL_PMUC_EXPORT static const Mesh makeBox(const Primitives::Box& box, const float& maxSideSize, const int& minSides); /** * @brief Builds up a sphere with the given radius @@ -87,7 +90,7 @@ class RVMMeshHelper2 * @param minSides * @return coordinates and normals with their indexes. */ - static const Mesh makeSphere(const Primitives::Sphere &sphere, const float& maxSideSize, const int& minSides); + DLL_PMUC_EXPORT static const Mesh makeSphere(const Primitives::Sphere& sphere, const float& maxSideSize, const int& minSides); /** * @brief makeCylinder @@ -97,7 +100,7 @@ class RVMMeshHelper2 * * @return Returns a mesh object. */ - static const Mesh makeCylinder(const Primitives::Cylinder &cylinder, unsigned long sides); + DLL_PMUC_EXPORT static const Mesh makeCylinder(const Primitives::Cylinder& cylinder, unsigned long sides); /** * @brief makeRectangularTorus @@ -106,7 +109,7 @@ class RVMMeshHelper2 * @param minSides * @return */ - static const Mesh makeRectangularTorus(const Primitives::RectangularTorus& rt, const float& maxSideSize, const int& minSides); + DLL_PMUC_EXPORT static const Mesh makeRectangularTorus(const Primitives::RectangularTorus& rt, const float& maxSideSize, const int& minSides); /** * @brief makeCircularTorus @@ -117,7 +120,7 @@ class RVMMeshHelper2 * @param minSides * @return */ - static const Mesh makeCircularTorus(const Primitives::CircularTorus& cTorus, unsigned long tsides, unsigned long csides); + DLL_PMUC_EXPORT static const Mesh makeCircularTorus(const Primitives::CircularTorus& cTorus, unsigned long tsides, unsigned long csides); /** * @brief makeSnout @@ -130,7 +133,7 @@ class RVMMeshHelper2 * @param minSides * @return */ - static const Mesh makeSnout(const Primitives::Snout& snout, unsigned long sides); + DLL_PMUC_EXPORT static const Mesh makeSnout(const Primitives::Snout& snout, unsigned long sides); /** * @brief makeEllipticalDish @@ -140,7 +143,7 @@ class RVMMeshHelper2 * @param csides * @return */ - static const Mesh makeEllipticalDish(const Primitives::EllipticalDish& eDish, unsigned long sides, unsigned long csides); + DLL_PMUC_EXPORT static const Mesh makeEllipticalDish(const Primitives::EllipticalDish& eDish, unsigned long sides, unsigned long csides); /** * @brief makeSphericalDish @@ -150,10 +153,10 @@ class RVMMeshHelper2 * @param minSides * @return */ - static const Mesh makeSphericalDish(const Primitives::SphericalDish& sDish , const float& maxSideSize, const int& minSides); + DLL_PMUC_EXPORT static const Mesh makeSphericalDish(const Primitives::SphericalDish& sDish, const float& maxSideSize, const int& minSides); - static void tesselateFacetGroup(const std::vector > >& vertices, Mesh* meshData); + DLL_PMUC_EXPORT static void tesselateFacetGroup(const std::vector > >& vertices, Mesh* meshData); /** * @param cylinder The cylinder primitive data. @@ -163,11 +166,11 @@ class RVMMeshHelper2 * @return Returns the number of sides of the cylinder. */ - static unsigned long infoCylinderNumSides(const Primitives::Cylinder &cylinder, float maxSideSize, unsigned long minSides); - static unsigned long infoSnoutNumSides(const Primitives::Snout &snout, float maxSideSize, unsigned long minSides); + DLL_PMUC_EXPORT static unsigned long infoCylinderNumSides(const Primitives::Cylinder& cylinder, float maxSideSize, unsigned long minSides); + DLL_PMUC_EXPORT static unsigned long infoSnoutNumSides(const Primitives::Snout& snout, float maxSideSize, unsigned long minSides); - static std::pair infoCircularTorusNumSides(const Primitives::CircularTorus& cTorus, float maxSideSize, unsigned long minSides); - static std::pair infoEllipticalDishNumSides(const Primitives::EllipticalDish& eDish, float maxSideSize, unsigned long minSides); + DLL_PMUC_EXPORT static std::pair infoCircularTorusNumSides(const Primitives::CircularTorus& cTorus, float maxSideSize, unsigned long minSides); + DLL_PMUC_EXPORT static std::pair infoEllipticalDishNumSides(const Primitives::EllipticalDish& eDish, float maxSideSize, unsigned long minSides); }; #endif // RVMMESHHELPER_H diff --git a/src/api/rvmparser.cpp b/src/api/rvmparser.cpp index 9eb9648..3d92d3c 100644 --- a/src/api/rvmparser.cpp +++ b/src/api/rvmparser.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "rvmreader.h" @@ -106,6 +107,16 @@ struct Identifier return std::string(chrs, chrs + 4); } + inline Identifier(const char source[5]) + : chrs { source[0], source[1], source[2], source[3] } + { + } + + inline Identifier() + : chrs { '0', '0', '0', '0' } + { + } + char chrs[4]; }; @@ -175,6 +186,24 @@ inline Identifier& read_(std::istream& in, Identifier& res) return res; } +size_t readUntil(std::istream& in, const Identifier& identifier) +{ + size_t counter = 0; + char charPtr[16]{}; + + do + { + ++counter; + memcpy(charPtr + 0, charPtr + 1, 15); + charPtr[15] = in.get(); + } while (charPtr[3] != identifier.chrs[0] || + charPtr[7] != identifier.chrs[1] || + charPtr[11] != identifier.chrs[2] || + charPtr[15] != identifier.chrs[3]); + + return counter; +} + template<> string& read_(istream& is, string& str) { @@ -374,12 +403,16 @@ void readArray_(std::istream &in, T(&a)[size]) ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// Implementation of a skip function /// Surprisingly, multiple calling get() multiple times seems to be faster than seekg. +/// We do not use seekg for the sake of supporting non-seekable streams. ///////////////////////////////////////////////////////////////////////////////////////////////////////// template inline void skip_(std::istream& in) { - in.seekg(sizeof(int) * numInts, in.cur); + for (size_t _ = 0; _ < numInts; ++_) + { + skip_<1>(in); + } } template<> @@ -433,8 +466,8 @@ namespace { } static void scaleMatrix(std::array& matrix, float factor) { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 3; j++) { + for (size_t i = 0; i < 4; i++) { + for (size_t j = 0; j < 3; j++) { matrix[i*3+j] *= factor; } } @@ -447,6 +480,7 @@ RVMParser::RVMParser(RVMReader& reader) : m_objectName(""), m_objectFound(0), m_forcedColor(-1), + m_aggregation(false), m_scale(1.), m_nbGroups(0), m_nbPyramids(0), @@ -460,9 +494,8 @@ RVMParser::RVMParser(RVMReader& reader) : m_nbSpheres(0), m_nbLines(0), m_nbFacetGroups(0), - m_attributeStream(0), m_attributes(0), - m_aggregation(false) { + m_brokenByUser(false) { } bool RVMParser::readFile(const string& filename, bool ignoreAttributes) @@ -477,27 +510,28 @@ bool RVMParser::readFile(const string& filename, bool ignoreAttributes) } // Try to find ATT companion file - m_attributeStream = 0; + std::istream* pAttributeStream = NULL; + std::istream attributeStream (NULL); filebuf afb; if (!ignoreAttributes) { string attfilename = filename.substr(0, filename.find_last_of(".")) + ".att"; if (afb.open(attfilename.data(), ios::in)) { cout << "Found attribute companion file: " << attfilename << endl; - m_attributeStream = new istream(&afb); + attributeStream.rdbuf (&afb); + pAttributeStream = &attributeStream; } else { attfilename = filename.substr(0, filename.find_last_of(".")) + ".ATT"; if (afb.open(attfilename.data(), ios::in)) { cout << "Found attribute companion file: " << attfilename << endl; - m_attributeStream = new istream(&afb); + attributeStream.rdbuf (&afb); + pAttributeStream = &attributeStream; } } - if (m_attributeStream && !m_attributeStream->eof()) { - std::getline(*m_attributeStream, m_currentAttributeLine, '\n'); - } + } - bool success = readStream(is); + bool success = readStream(is, pAttributeStream); is.close(); @@ -543,8 +577,77 @@ bool RVMParser::readBuffer(const char* buffer) { return success; } -bool RVMParser::readStream(istream& is) -{ +void RVMParser::readArttributes(std::istream& stream) { + size_t position{}; + std::string separator{":="}; + + TAttributeContainer temporaryContainer; + std::string temporaryName; + + m_groupAttributes.clear(); + + while (!stream.eof()) { + std::string line; + std::getline(stream, line); + + line = trim(latin_to_utf8(line)); + + if (line == "END") { + // Warning after std::move(temporaryContainer) this container will be an empty, also as a group + m_groupAttributes.emplace(std::make_pair(std::move(temporaryName), std::move(temporaryContainer))); + } else if (isFound(line, "NEW", position)) { + // + 3 - it is skip strlen ("NEW") + temporaryName = trim(line.substr(position + 3, string::npos)); + } else if (isFound(line, separator, position)) { + string name = line.substr(0, position); + string value = trim(line.substr(position + separator.size(), string::npos)); + + temporaryContainer.emplace_back(name, value); + } else { + // Skip other lines + } + } +} + +void RVMParser::insertAttributes(const std::string& name, bool ignoreAttributes) { + if (ignoreAttributes) { + return; + } + + auto it = m_groupAttributes.find(name); + + if (it != m_groupAttributes.end()) { + const TAttributeContainer& attributes = it->second; + + m_reader.startMetaData(); + + for (const TAttributePair& attribute : attributes) { + m_reader.startMetaDataPair(attribute.first, attribute.second); + m_reader.endMetaDataPair(); + m_attributes++; + } + m_reader.endMetaData(); + } +} + +bool RVMParser::isFound(const std::string& line, const std::string& substring, size_t& position) { + bool found = false; + + position = line.find(substring); + + if (position != std::string::npos) { + found = true; + } + + return found; +} + +bool RVMParser::readStream(istream& is, std::istream* attributeStream) { + // Read first line from file with attributes + if (attributeStream && (*attributeStream) && !attributeStream->eof()) { + readArttributes(*attributeStream); + } + Identifier id; if(!readUntilValidIdentifier(is, id)) { @@ -607,7 +710,9 @@ bool RVMParser::readStream(istream& is) return false; } - skip_<2>(is); // Garbage ? + m_reader.updateProgress(read_(is)); + + skip_<1>(is); // Garbage ? version = read_(is); string projectName, name; @@ -617,10 +722,10 @@ bool RVMParser::readStream(istream& is) if (!m_aggregation) m_reader.startModel(projectName, name); - while ((read_(is, id)) != "END") + while ((read_(is, id)) != "END" && m_brokenByUser == false) { if (id == "CNTB") { - if (!readGroup(is)) { + if (!readGroup(is, attributeStream)) { return false; } } else if (id == "PRIM") { @@ -637,12 +742,18 @@ bool RVMParser::readStream(istream& is) } } + if (m_brokenByUser) { + return false; + } + if (!m_aggregation) { m_reader.endModel(); // Garbage data ?? m_reader.endDocument(); } + m_groupAttributes.clear(); + return true; } @@ -651,20 +762,30 @@ const string RVMParser::lastError() return m_lastError; } -bool RVMParser::readGroup(std::istream& is) +bool RVMParser::readGroup(std::istream& is, std::istream* attributeStream) { - skip_<2>(is); // Garbage ? - const unsigned int version = read_(is); + m_reader.updateProgress(read_(is)); + + skip_<1>(is); // Garbage ? + const unsigned int version = + read_(is); string name; read_(is, name); Vector3F translation; readArray_(is, translation.m_values); - translation *= 0.001f; + translation *= 0.001f * m_scale; const unsigned int materialId = read_(is); + + if (version == 3) + { + //const unsigned int last = + read_(is); + } + if (m_objectName.empty() || m_objectFound || name == m_objectName) { m_objectFound++; } @@ -673,45 +794,63 @@ bool RVMParser::readGroup(std::istream& is) m_nbGroups++; m_reader.startGroup(name, translation, m_forcedColor != -1 ? m_forcedColor : materialId); // Attributes - if (m_attributeStream && !m_attributeStream->eof()) { - string p; - while (((p = trim(m_currentAttributeLine)) != "NEW " + name) && (!m_attributeStream->eof())) { - std::getline(*m_attributeStream, m_currentAttributeLine, '\n'); - } - if (p == "NEW " + name ) { - m_reader.startMetaData(); - size_t i; - std::getline(*m_attributeStream, m_currentAttributeLine, '\n'); - p = trim(latin_to_utf8(m_currentAttributeLine)); - while ((!m_attributeStream->eof()) && ((i = p.find(":=")) != string::npos)) { - string an = p.substr(0, i); - string av = p.substr(i+4, string::npos); - - m_reader.startMetaDataPair(an, av); - m_reader.endMetaDataPair(); - m_attributes++; - - std::getline(*m_attributeStream, m_currentAttributeLine, '\n'); - p = trim(latin_to_utf8(m_currentAttributeLine)); - } - m_reader.endMetaData(); - } - } + insertAttributes(name, attributeStream == nullptr); } // Children Identifier id; - while ((read_(is, id)) != "CNTE") { + while ((read_(is, id)) != "CNTE" && m_brokenByUser == false) { if (id == "CNTB") { - if (!readGroup(is)) { + if (!readGroup(is, attributeStream)) { return false; } } else if (id == "PRIM") { if (!readPrimitive(is)) { return false; } + } else if (id == "OBST") { + //unsigned int offset = + read_(is); + //unsigned int skiped = + read_(is); // Garbage ? + //unsigned int version = + read_(is); + + readUntil(is, "CNTE"); + break; } else { - m_lastError = "Unknown or invalid identifier found."; + std::stringstream stream; + + stream << "Unknown or invalid identifier {"; + stream << " 1: " << ((unsigned int)((unsigned char)id.chrs[0])); + if (id.chrs[0] != 0) + { + stream << " / '" << id.chrs[0] << "'"; + } + stream << ", "; + stream << " 2: " << ((unsigned int)((unsigned char)id.chrs[1])); + if (id.chrs[1] != 0) + { + stream << " / '" << id.chrs[1] << "'"; + } + stream << ", "; + stream << " 3: " << ((unsigned int)((unsigned char)id.chrs[2])); + if (id.chrs[2] != 0) + { + stream << " / '" << id.chrs[2] << "'"; + } + stream << ", "; + stream << " 4: " << ((unsigned int)((unsigned char)id.chrs[3])); + if (id.chrs[3] != 0) + { + stream << " / '" << id.chrs[3] << "'"; + } + stream << " } found. { 1 }, position of stream is { "; + stream << "10: " << is.tellg() << ", "; + stream << "16 (Hex): " << std::hex << is.tellg(); + stream << " }"; + + m_lastError = stream.str(); return false; } } @@ -723,13 +862,18 @@ bool RVMParser::readGroup(std::istream& is) m_objectFound--; } + if (m_brokenByUser) { + return false; + } + return true; } bool RVMParser::readPrimitive(std::istream& is) { skip_<2>(is); // Garbage ? - const unsigned int version = read_(is); + //const unsigned int version = + read_(is); const unsigned int primitiveKind = read_(is); std::array matrix; @@ -875,10 +1019,11 @@ bool RVMParser::readPrimitive(std::istream& is) bool RVMParser::readColor(std::istream& is) { - const auto pos = int(is.tellg()); + //const auto pos = int(is.tellg()); skip_<2>(is); // Garbage ? - const unsigned int version = read_(is); + //const unsigned int version = + read_(is); const unsigned int index = read_(is); std::array color; diff --git a/src/api/rvmparser.h b/src/api/rvmparser.h index e0c2c6c..794ed11 100644 --- a/src/api/rvmparser.h +++ b/src/api/rvmparser.h @@ -26,8 +26,11 @@ #include #include #include +#include +#include #include "vector3f.h" +#include "lib_export.h" class RVMReader; @@ -50,7 +53,7 @@ class RVMParser * @brief Constructs a parser ready to send data to the provided RVMReader * @param reader The reader object that will receive the data. */ - RVMParser(RVMReader& reader); + DLL_PMUC_EXPORT RVMParser(RVMReader& reader); /** * @brief Reads from a file a parse its content. @@ -58,26 +61,26 @@ class RVMParser * * @return true if the parsing was a success. */ - bool readFile(const std::string& filename, bool ignoreAttributes); + DLL_PMUC_EXPORT bool readFile(const std::string& filename, bool ignoreAttributes); /** * @brief Reads from a series of files. * @param filenames a vector of filenames * * @return true if the parsing was a success. */ - bool readFiles(const std::vector& filenames, const std::string& name, bool ignoreAttributes); + DLL_PMUC_EXPORT bool readFiles(const std::vector& filenames, const std::string& name, bool ignoreAttributes); /** * @brief Reads from a character buffer. * @param buffer the character buffer containing RVM data. * @return true if the parsing was a success. */ - bool readBuffer(const char* buffer); + DLL_PMUC_EXPORT bool readBuffer(const char* buffer); /** * @brief Reads RVM data from an input stream * @param is the input stream of RVM data. * @return true if the parsing was a success. */ - bool readStream(std::istream& is); + DLL_PMUC_EXPORT bool readStream(std::istream& is, std::istream* attributeStream = NULL); /** * @brief Allow to filter the RVM data to one named object @@ -95,7 +98,7 @@ class RVMParser * @brief In case of error, returns the last error that occured. * @return a string describing the error. */ - const std::string lastError(); + DLL_PMUC_EXPORT const std::string lastError(); /** * @brief Statistics of the parsing: number of groups @@ -162,11 +165,20 @@ class RVMParser * @return the number of attributes found in the source. */ const long& nbAttributes() { return m_attributes; } + + /** + * @brief Stop reading file/stream by user + */ + DLL_PMUC_EXPORT void Break() { m_brokenByUser = true; } private: - bool readGroup(std::istream& is); + bool readGroup(std::istream& is, std::istream* attributeStream); bool readPrimitive(std::istream& is); bool readColor(std::istream& is); + void readArttributes(std::istream& stream); + void insertAttributes(const std::string& name, bool ignoreAttributes); + bool isFound(const std::string& line, const std::string& substring, size_t& after); + void readMatrix(std::istream& is, std::array& matrix); @@ -174,13 +186,11 @@ class RVMParser std::string m_encoding; std::string m_lastError; - std::string m_currentAttributeLine; std::string m_objectName; int m_objectFound; int m_forcedColor; bool m_aggregation; float m_scale; - std::istream* m_attributeStream; int m_nbGroups; int m_nbPyramids; @@ -195,6 +205,13 @@ class RVMParser int m_nbLines; int m_nbFacetGroups; long m_attributes; + + bool m_brokenByUser; + + using TAttributePair = std::pair; + using TAttributeContainer = std::list; + + std::map m_groupAttributes; }; #endif // RVMPARSER_H diff --git a/src/api/rvmreader.cpp b/src/api/rvmreader.cpp index 559b3f9..06a3216 100644 --- a/src/api/rvmreader.cpp +++ b/src/api/rvmreader.cpp @@ -22,10 +22,10 @@ #include "rvmreader.h" RVMReader::RVMReader() : - m_primitives(false), - m_split(false), m_minSides(16), - m_maxSideSize(10) { + m_maxSideSize(10), + m_split(false), + m_primitives(false) { } RVMReader::~RVMReader() { diff --git a/src/api/rvmreader.h b/src/api/rvmreader.h index d2bd00d..173d038 100644 --- a/src/api/rvmreader.h +++ b/src/api/rvmreader.h @@ -26,6 +26,8 @@ #include #include +#include "lib_export.h" + #include "vector3f.h" #include "rvmprimitive.h" @@ -46,11 +48,12 @@ class RVMReader /** * @brief Default constructor. Initializes variables. */ - RVMReader(); + DLL_PMUC_EXPORT RVMReader(); + /** * @brief Pure virtual destructor */ - virtual ~RVMReader() = 0; + DLL_PMUC_EXPORT virtual ~RVMReader(); /** * @brief Signals the start of the document. @@ -217,7 +220,19 @@ class RVMReader * @param index - The index of the entry in the color map. * @param color - The new color values to be set. */ - virtual void updateColorPalette(std::uint32_t index, const std::array &color) {} + virtual void updateColorPalette(std::uint32_t index, const std::array& color) { + (void)index; + (void)color; + } + + /** + * Set progress of reading rvm file/stream. + * + * @param progress - The number of read bytes. + */ + DLL_PMUC_EXPORT virtual void updateProgress(std::size_t progress) { + (void)progress; + } /** * @brief Sets the maximum size for a side of a primitive when tesselating. diff --git a/src/api/vector3f.h b/src/api/vector3f.h index 03a9f82..913b41e 100644 --- a/src/api/vector3f.h +++ b/src/api/vector3f.h @@ -22,6 +22,8 @@ #ifndef Vector3F_H #define Vector3F_H +#include "lib_export.h" + #include #include #include @@ -33,11 +35,11 @@ */ class Vector3F { - public: - Vector3F(); - Vector3F(const float& x, const float& y, const float& z); - Vector3F(const Vector3F& v); - Vector3F(const std::vector& v); +public: + DLL_PMUC_EXPORT Vector3F(); + DLL_PMUC_EXPORT Vector3F(const float& x, const float& y, const float& z); + DLL_PMUC_EXPORT Vector3F(const Vector3F& v); + DLL_PMUC_EXPORT Vector3F(const std::vector& v); inline float& operator[](int i) { return m_values[i]; @@ -78,7 +80,7 @@ class Vector3F return 0.f; } - Vector3F cross(const Vector3F& y ); + DLL_PMUC_EXPORT Vector3F cross(const Vector3F& y); inline bool equals(const Vector3F& v) const { return (m_values[0] == v[0]) && (m_values[1] == v[1]) && (m_values[2] == v[2]); @@ -89,12 +91,12 @@ class Vector3F return *this; } - friend Vector3F operator-(const std::vector& p1, const std::vector& p2); - friend Vector3F operator-(const Vector3F& p1, const Vector3F& p2); - friend Vector3F operator+(const Vector3F& p1, const Vector3F& p2); - friend float operator*(const Vector3F& p1, const Vector3F& p2); - friend Vector3F operator*(const Vector3F& v, float f); - friend std::ostream& operator<<(std::ostream& out, const Vector3F& vec); + DLL_PMUC_EXPORT friend Vector3F operator-(const std::vector& p1, const std::vector& p2); + DLL_PMUC_EXPORT friend Vector3F operator-(const Vector3F& p1, const Vector3F& p2); + DLL_PMUC_EXPORT friend Vector3F operator+(const Vector3F& p1, const Vector3F& p2); + DLL_PMUC_EXPORT friend float operator*(const Vector3F& p1, const Vector3F& p2); + DLL_PMUC_EXPORT friend Vector3F operator*(const Vector3F& v, float f); + DLL_PMUC_EXPORT friend std::ostream& operator<<(std::ostream& out, const Vector3F& vec); friend bool operator!=(const Vector3F &a, const Vector3F &b) { return !(a==b);