2020-11-27 11:47:21 +01:00
|
|
|
#include "vcgtrimesh.hpp"
|
2021-04-08 20:03:23 +02:00
|
|
|
#include "utilities.hpp"
|
2020-11-27 11:47:21 +01:00
|
|
|
#include "wrap/io_trimesh/import_obj.h"
|
|
|
|
#include "wrap/io_trimesh/import_off.h"
|
|
|
|
#include <filesystem>
|
2021-11-15 10:08:39 +01:00
|
|
|
#include <wrap/io_trimesh/export.h>
|
2021-04-08 20:03:23 +02:00
|
|
|
#include <wrap/io_trimesh/import.h>
|
2021-11-15 10:08:39 +01:00
|
|
|
//#include <wrap/nanoply/include/nanoplyWrapper.hpp>
|
2022-05-06 15:28:28 +02:00
|
|
|
#ifdef POLYSCOPE_DEFINED
|
|
|
|
#include <polyscope/curve_network.h>
|
|
|
|
#endif
|
2021-04-08 20:03:23 +02:00
|
|
|
|
2022-01-14 14:02:27 +01:00
|
|
|
bool VCGTriMesh::load(const std::filesystem::__cxx11::path &meshFilePath) {
|
|
|
|
assert(std::filesystem::exists(meshFilePath));
|
2021-06-24 09:02:20 +02:00
|
|
|
unsigned int mask = 0;
|
2021-11-15 10:08:39 +01:00
|
|
|
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;
|
2020-11-27 11:47:21 +01:00
|
|
|
|
2021-06-30 09:28:13 +02:00
|
|
|
// if (nanoply::NanoPlyWrapper<VCGTriMesh>::LoadModel(
|
|
|
|
// std::filesystem::absolute(filename).string().c_str(), *this, mask)
|
|
|
|
// != 0) {
|
|
|
|
if (vcg::tri::io::Importer<VCGTriMesh>::Open(*this,
|
2022-01-14 14:02:27 +01:00
|
|
|
std::filesystem::absolute(meshFilePath).string().c_str())
|
2021-04-08 20:03:23 +02:00
|
|
|
!= 0) {
|
|
|
|
std::cout << "Could not load tri mesh" << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-06-24 09:02:20 +02:00
|
|
|
vcg::tri::UpdateTopology<VCGTriMesh>::AllocateEdge(*this);
|
|
|
|
vcg::tri::UpdateTopology<VCGTriMesh>::FaceFace(*this);
|
|
|
|
vcg::tri::UpdateTopology<VCGTriMesh>::VertexFace(*this);
|
|
|
|
vcg::tri::UpdateTopology<VCGTriMesh>::VertexEdge(*this);
|
|
|
|
vcg::tri::UpdateNormal<VCGTriMesh>::PerVertexNormalized(*this);
|
|
|
|
|
2022-01-14 14:02:27 +01:00
|
|
|
label = std::filesystem::path(meshFilePath).stem().string();
|
2021-06-24 09:02:20 +02:00
|
|
|
return true;
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
|
|
|
|
2022-05-06 15:28:28 +02:00
|
|
|
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<VCGTriMesh>::OpenStream(*this, offInputStream, mask);
|
|
|
|
if (openingFromStreamErrorCode != 0) {
|
|
|
|
std::cerr << "Error reading from stream:"
|
|
|
|
<< vcg::tri::io::ImporterOFF<VCGTriMesh>::ErrorMsg(openingFromStreamErrorCode)
|
|
|
|
<< std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
vcg::tri::UpdateTopology<VCGTriMesh>::AllocateEdge(*this);
|
|
|
|
vcg::tri::UpdateTopology<VCGTriMesh>::FaceFace(*this);
|
|
|
|
vcg::tri::UpdateTopology<VCGTriMesh>::VertexFace(*this);
|
|
|
|
vcg::tri::UpdateTopology<VCGTriMesh>::VertexEdge(*this);
|
|
|
|
vcg::tri::UpdateNormal<VCGTriMesh>::PerVertexNormalized(*this);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-04-08 20:03:23 +02:00
|
|
|
Eigen::MatrixX3d VCGTriMesh::getVertices() const
|
|
|
|
{
|
|
|
|
// vcg::tri::Allocator<VCGTriMesh>::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<Eigen::Vector3d>();
|
|
|
|
}
|
|
|
|
return vertices;
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
|
|
|
|
2021-04-08 20:03:23 +02:00
|
|
|
Eigen::MatrixX3i VCGTriMesh::getFaces() const
|
|
|
|
{
|
|
|
|
// vcg::tri::Allocator<VCGTriMesh>::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<VCGTriMesh>(*this, face.cV(0));
|
|
|
|
const size_t v1 = vcg::tri::Index<VCGTriMesh>(*this, face.cV(1));
|
|
|
|
const size_t v2 = vcg::tri::Index<VCGTriMesh>(*this, face.cV(2));
|
|
|
|
faces.row(fi) = Eigen::Vector3i(v0, v1, v2);
|
|
|
|
}
|
|
|
|
return faces;
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
|
|
|
|
2021-04-08 20:03:23 +02:00
|
|
|
Eigen::MatrixX2i VCGTriMesh::getEdges() const
|
|
|
|
{
|
|
|
|
// vcg::tri::Allocator<VCGTriMesh>::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<VCGTriMesh>(*this, edge.cV(0));
|
|
|
|
const size_t v1 = vcg::tri::Index<VCGTriMesh>(*this, edge.cV(1));
|
|
|
|
edges.row(ei) = Eigen::Vector2i(v0, v1);
|
|
|
|
}
|
|
|
|
return edges;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VCGTriMesh::save(const std::string plyFilename)
|
|
|
|
{
|
|
|
|
// vcg::tri::Allocator<VCGTriMesh>::CompactEveryVector(*this);
|
|
|
|
assert(std::filesystem::path(plyFilename).extension() == ".ply");
|
|
|
|
// Load the ply file
|
|
|
|
unsigned int mask = 0;
|
2021-11-15 10:08:39 +01:00
|
|
|
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<VCGTriMesh>::Save(*this, plyFilename.c_str(), mask) != 0) {
|
2021-04-08 20:03:23 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-04-30 12:13:58 +02:00
|
|
|
#ifdef POLYSCOPE_DEFINED
|
2021-06-24 09:02:20 +02:00
|
|
|
|
2022-09-14 13:04:05 +02:00
|
|
|
polyscope::SurfaceMesh *VCGTriMesh::registerForDrawing(const std::optional<std::array<float, 3> > &desiredColor, const bool &shouldEnable) const
|
2021-04-08 20:03:23 +02:00
|
|
|
{
|
|
|
|
auto vertices = getVertices();
|
|
|
|
auto faces = getFaces();
|
2021-04-30 12:13:58 +02:00
|
|
|
PolyscopeInterface::init();
|
2021-04-08 20:03:23 +02:00
|
|
|
|
|
|
|
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]);
|
2022-07-12 12:13:01 +02:00
|
|
|
polyscopeHandle_mesh->setSurfaceColor(desiredColor_glm);
|
2021-04-08 20:03:23 +02:00
|
|
|
}
|
|
|
|
return polyscopeHandle_mesh;
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
2021-04-30 12:13:58 +02:00
|
|
|
#endif
|
2020-11-27 11:47:21 +01:00
|
|
|
|
|
|
|
VCGTriMesh::VCGTriMesh() {}
|
|
|
|
|
2021-04-08 20:03:23 +02:00
|
|
|
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<VCGTriMesh>::Info info;
|
|
|
|
vcg::tri::io::ImporterOBJ<VCGTriMesh>::Open(*this, filename.c_str(), info);
|
|
|
|
} else if (extension == ".off") {
|
|
|
|
vcg::tri::io::ImporterOFF<VCGTriMesh>::Open(*this, filename.c_str());
|
2020-11-27 11:47:21 +01:00
|
|
|
|
2021-04-08 20:03:23 +02:00
|
|
|
} else {
|
|
|
|
std::cerr << "Uknown file extension " << extension << ". Could not open " << filename
|
|
|
|
<< std::endl;
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
vcg::tri::UpdateTopology<VCGTriMesh>::AllocateEdge(*this);
|
|
|
|
vcg::tri::UpdateTopology<VCGTriMesh>::FaceFace(*this);
|
|
|
|
vcg::tri::UpdateTopology<VCGTriMesh>::VertexFace(*this);
|
|
|
|
vcg::tri::UpdateNormal<VCGTriMesh>::PerVertexNormalized(*this);
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
2021-11-15 10:08:39 +01:00
|
|
|
|
|
|
|
void VCGTriMesh::moveToCenter()
|
|
|
|
{
|
|
|
|
CoordType centerOfMass(0, 0, 0);
|
|
|
|
|
|
|
|
for (int vi = 0; vi < VN(); vi++) {
|
|
|
|
centerOfMass += vert[vi].cP();
|
|
|
|
}
|
|
|
|
centerOfMass /= VN();
|
|
|
|
vcg::tri::UpdatePosition<VCGTriMesh>::Translate(*this, -centerOfMass);
|
|
|
|
}
|