#ifndef CONVEXHULL_HPP_ #define CONVEXHULL_HPP_ #include "Structs/Vector3.hpp" #include "Structs/Mesh.hpp" #include "Structs/VertexDataSource.hpp" #include #include #include #include namespace quickhull { template class ConvexHull { std::unique_ptr>> m_optimizedVertexBuffer; VertexDataSource m_vertices; std::vector m_indices; public: ConvexHull() {} // Copy constructor ConvexHull(const ConvexHull& o) { m_indices = o.m_indices; if (o.m_optimizedVertexBuffer) { m_optimizedVertexBuffer.reset(new std::vector>(*o.m_optimizedVertexBuffer)); m_vertices = VertexDataSource(*m_optimizedVertexBuffer); } else { m_vertices = o.m_vertices; } } ConvexHull& operator=(const ConvexHull& o) { if (&o == this) { return *this; } m_indices = o.m_indices; if (o.m_optimizedVertexBuffer) { m_optimizedVertexBuffer.reset(new std::vector>(*o.m_optimizedVertexBuffer)); m_vertices = VertexDataSource(*m_optimizedVertexBuffer); } else { m_vertices = o.m_vertices; } return *this; } ConvexHull(ConvexHull&& o) { m_indices = std::move(o.m_indices); if (o.m_optimizedVertexBuffer) { m_optimizedVertexBuffer = std::move(o.m_optimizedVertexBuffer); o.m_vertices = VertexDataSource(); m_vertices = VertexDataSource(*m_optimizedVertexBuffer); } else { m_vertices = o.m_vertices; } } ConvexHull& operator=(ConvexHull&& o) { if (&o == this) { return *this; } m_indices = std::move(o.m_indices); if (o.m_optimizedVertexBuffer) { m_optimizedVertexBuffer = std::move(o.m_optimizedVertexBuffer); o.m_vertices = VertexDataSource(); m_vertices = VertexDataSource(*m_optimizedVertexBuffer); } else { m_vertices = o.m_vertices; } return *this; } // Construct vertex and index buffers from half edge mesh and pointcloud ConvexHull(const MeshBuilder& mesh, const VertexDataSource& pointCloud, bool CCW, bool useOriginalIndices) { if (!useOriginalIndices) { m_optimizedVertexBuffer.reset(new std::vector>()); } std::vector faceProcessed(mesh.m_faces.size(),false); std::vector faceStack; std::unordered_map vertexIndexMapping; // Map vertex indices from original point cloud to the new mesh vertex indices for (size_t i = 0;ipush_back(pointCloud[v]); vertexIndexMapping[v] = m_optimizedVertexBuffer->size()-1; v = m_optimizedVertexBuffer->size()-1; } else { v = itV->second; } } } m_indices.push_back(vertices[0]); m_indices.push_back(vertices[1 + iCCW]); m_indices.push_back(vertices[2 - iCCW]); } } if (!useOriginalIndices) { m_vertices = VertexDataSource(*m_optimizedVertexBuffer); } else { m_vertices = pointCloud; } } std::vector& getIndexBuffer() { return m_indices; } const std::vector& getIndexBuffer() const { return m_indices; } VertexDataSource& getVertexBuffer() { return m_vertices; } const VertexDataSource& getVertexBuffer() const { return m_vertices; } // Export the mesh to a Waveform OBJ file void writeWaveformOBJ(const std::string& filename, const std::string& objectName = "quickhull") const { std::ofstream objFile; objFile.open (filename); objFile << "o " << objectName << "\n"; for (const auto& v : getVertexBuffer()) { objFile << "v " << v.x << " " << v.y << " " << v.z << "\n"; } const auto& indBuf = getIndexBuffer(); size_t triangleCount = indBuf.size()/3; for (size_t i=0;i