#include "vcgtrimesh.hpp" #include "utilities.hpp" #include "wrap/io_trimesh/import_obj.h" #include "wrap/io_trimesh/import_off.h" #include #include #include //#include #ifdef POLYSCOPE_DEFINED #include #endif bool VCGTriMesh::load(const std::filesystem::__cxx11::path &meshFilePath) { assert(std::filesystem::exists(meshFilePath)); unsigned int mask = 0; mask |= vcg::tri::io::Mask::IOM_VERTCOORD; mask |= vcg::tri::io::Mask::IOM_VERTNORMAL; mask |= vcg::tri::io::Mask::IOM_VERTCOLOR; mask |= vcg::tri::io::Mask::IOM_EDGEINDEX; mask |= vcg::tri::io::Mask::IOM_FACEINDEX; // if (nanoply::NanoPlyWrapper::LoadModel( // std::filesystem::absolute(filename).string().c_str(), *this, mask) // != 0) { if (vcg::tri::io::Importer::Open(*this, std::filesystem::absolute(meshFilePath).string().c_str()) != 0) { std::cout << "Could not load tri mesh" << std::endl; return false; } vcg::tri::UpdateTopology::AllocateEdge(*this); vcg::tri::UpdateTopology::FaceFace(*this); vcg::tri::UpdateTopology::VertexFace(*this); vcg::tri::UpdateTopology::VertexEdge(*this); vcg::tri::UpdateNormal::PerVertexNormalized(*this); label = std::filesystem::path(meshFilePath).stem().string(); return true; } bool VCGTriMesh::load(std::istringstream &offInputStream) { Clear(); // assert(plyFileHasAllRequiredFields(plyFilename)); // Load the ply file int mask = 0; mask |= vcg::tri::io::Mask::IOM_VERTCOORD; mask |= vcg::tri::io::Mask::IOM_VERTNORMAL; mask |= vcg::tri::io::Mask::IOM_VERTCOLOR; mask |= vcg::tri::io::Mask::IOM_EDGEINDEX; const bool openingFromStreamErrorCode = vcg::tri::io::ImporterOFF::OpenStream(*this, offInputStream, mask); if (openingFromStreamErrorCode != 0) { std::cerr << "Error reading from stream:" << vcg::tri::io::ImporterOFF::ErrorMsg(openingFromStreamErrorCode) << std::endl; return false; } vcg::tri::UpdateTopology::AllocateEdge(*this); vcg::tri::UpdateTopology::FaceFace(*this); vcg::tri::UpdateTopology::VertexFace(*this); vcg::tri::UpdateTopology::VertexEdge(*this); vcg::tri::UpdateNormal::PerVertexNormalized(*this); return true; } Eigen::MatrixX3d VCGTriMesh::getVertices() const { // vcg::tri::Allocator::CompactVertexVector(m); Eigen::MatrixX3d vertices(VN(), 3); for (size_t vi = 0; vi < VN(); vi++) { VCGTriMesh::CoordType vertexCoordinates = vert[vi].cP(); vertices.row(vi) = vertexCoordinates.ToEigenVector(); } return vertices; } Eigen::MatrixX3i VCGTriMesh::getFaces() const { // vcg::tri::Allocator::CompactFaceVector(m); Eigen::MatrixX3i faces(FN(), 3); for (int fi = 0; fi < FN(); fi++) { const VCGTriMesh::FaceType &face = this->face[fi]; const size_t v0 = vcg::tri::Index(*this, face.cV(0)); const size_t v1 = vcg::tri::Index(*this, face.cV(1)); const size_t v2 = vcg::tri::Index(*this, face.cV(2)); faces.row(fi) = Eigen::Vector3i(v0, v1, v2); } return faces; } Eigen::MatrixX2i VCGTriMesh::getEdges() const { // vcg::tri::Allocator::CompactFaceVector(m); Eigen::MatrixX2i edges(EN(), 2); for (int ei = 0; ei < EN(); ei++) { const VCGTriMesh::EdgeType &edge = this->edge[ei]; const size_t v0 = vcg::tri::Index(*this, edge.cV(0)); const size_t v1 = vcg::tri::Index(*this, edge.cV(1)); edges.row(ei) = Eigen::Vector2i(v0, v1); } return edges; } bool VCGTriMesh::save(const std::string plyFilename) { // vcg::tri::Allocator::CompactEveryVector(*this); assert(std::filesystem::path(plyFilename).extension() == ".ply"); // Load the ply file unsigned int mask = 0; mask |= vcg::tri::io::Mask::IOM_VERTCOORD; mask |= vcg::tri::io::Mask::IOM_VERTCOLOR; mask |= vcg::tri::io::Mask::IOM_FACEINDEX; mask |= vcg::tri::io::Mask::IOM_FACENORMAL; if (vcg::tri::io::Exporter::Save(*this, plyFilename.c_str(), mask) != 0) { return false; } return true; } #ifdef POLYSCOPE_DEFINED polyscope::SurfaceMesh *VCGTriMesh::registerForDrawing( const std::optional> &desiredColor, const bool &shouldEnable) const { auto vertices = getVertices(); auto faces = getFaces(); PolyscopeInterface::init(); if (faces.rows() == 0) { auto edges = getEdges(); polyscope::CurveNetwork *polyscopeHandle_mesh( polyscope::registerCurveNetwork(label, vertices, edges)); return nullptr; } polyscope::SurfaceMesh *polyscopeHandle_mesh( polyscope::registerSurfaceMesh(label, vertices, faces)); polyscopeHandle_mesh->setEnabled(shouldEnable); const double drawingRadius = 0.002; polyscopeHandle_mesh->setEdgeWidth(drawingRadius); if (desiredColor.has_value()) { const glm::vec3 desiredColor_glm(desiredColor.value()[0], desiredColor.value()[1], desiredColor.value()[2]); polyscopeHandle_mesh->setSurfaceColor(desiredColor_glm); } return polyscopeHandle_mesh; } #endif VCGTriMesh::VCGTriMesh() {} VCGTriMesh::VCGTriMesh(const std::string &filename) { const std::string extension = std::filesystem::path(filename).extension().string(); if (extension == ".ply") { load(filename); } else if (extension == ".obj") { vcg::tri::io::ImporterOBJ::Info info; vcg::tri::io::ImporterOBJ::Open(*this, filename.c_str(), info); } else if (extension == ".off") { vcg::tri::io::ImporterOFF::Open(*this, filename.c_str()); } else { std::cerr << "Uknown file extension " << extension << ". Could not open " << filename << std::endl; assert(false); } vcg::tri::UpdateTopology::AllocateEdge(*this); vcg::tri::UpdateTopology::FaceFace(*this); vcg::tri::UpdateTopology::VertexFace(*this); vcg::tri::UpdateNormal::PerVertexNormalized(*this); } void VCGTriMesh::moveToCenter() { CoordType centerOfMass(0, 0, 0); for (int vi = 0; vi < VN(); vi++) { centerOfMass += vert[vi].cP(); } centerOfMass /= VN(); vcg::tri::UpdatePosition::Translate(*this, -centerOfMass); }