From 3120660a965440de84dfacdf24c361574151b3bf Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 6 Jul 2021 19:32:10 +0200 Subject: [PATCH] create polymesh from eigen matrix --- .../utilities/eigen_mesh_conversions.cpp | 137 ++++++++++++++++++ src/common/utilities/eigen_mesh_conversions.h | 10 ++ 2 files changed, 147 insertions(+) diff --git a/src/common/utilities/eigen_mesh_conversions.cpp b/src/common/utilities/eigen_mesh_conversions.cpp index 78f8e5530..9d2e044b8 100644 --- a/src/common/utilities/eigen_mesh_conversions.cpp +++ b/src/common/utilities/eigen_mesh_conversions.cpp @@ -23,6 +23,43 @@ #include "eigen_mesh_conversions.h" #include "../mlexception.h" +#include + +namespace vcg { +class PEdge; +class PFace; +class PVertex; +struct PUsedTypes : public UsedTypes< + Use ::AsVertexType, + Use ::AsEdgeType, + Use ::AsFaceType> {}; + +class PVertex : public Vertex< + PUsedTypes, + vertex::Coord3f, + vertex::Normal3f, + vertex::Qualityf, + vertex::Color4b, + vertex::BitFlags +> {}; +class PEdge : public Edge< + PUsedTypes, + edge::VertexRef, + edge::BitFlags +> {}; +class PFace :public vcg::Face< + PUsedTypes, + face::PolyInfo, // this is necessary if you use component in vcg/simplex/face/component_polygon.h + face::PFVAdj, // Pointer to the vertices (just like FVAdj ) + face::Qualityf, + face::Color4b, + face::BitFlags, // bit flags + face::Normal3f, // normal + face::WedgeTexCoord2f +> {}; + +} //namespace vcg +class PolyMesh : public vcg::tri::TriMesh< std::vector, std::vector, std::vector > {}; /** * @brief Creates a CMeshO mesh from the data contained in the given matrices. @@ -138,6 +175,106 @@ CMeshO meshlab::meshFromMatrices( return m; } +CMeshO meshlab::polyMeshFromMatrices( + const EigenMatrixX3m& vertices, + const std::list& faces, + const EigenMatrixX3m& vertexNormals, + const EigenMatrixX3m& faceNormals, + const EigenVectorXm& vertexQuality, + const EigenVectorXm& faceQuality) +{ + PolyMesh pm; + CMeshO m; + if (vertices.rows() > 0) { + //add vertices and their associated normals and quality if any + std::vector ivp(vertices.rows()); + + bool hasVNormals = vertexNormals.rows() > 0; + bool hasVQuality = vertexQuality.rows() > 0; + if (hasVNormals && (vertices.rows() != vertexNormals.rows())) { + throw MLException( + "Error while creating mesh: the number of vertex normals " + "is different from the number of vertices."); + } + if (hasVQuality && (vertices.rows() != vertexQuality.size())) { + throw MLException( + "Error while creating mesh: the number of vertex quality " + "values is different from the number of vertices."); + } + PolyMesh::VertexIterator vi = + vcg::tri::Allocator::AddVertices(pm, vertices.rows()); + for (unsigned int i = 0; i < vertices.rows(); ++i, ++vi) { + ivp[i] = &*vi; + vi->P() = PolyMesh::CoordType(vertices(i,0), vertices(i,1), vertices(i,2)); + if (hasVNormals) { + vi->N() = PolyMesh::CoordType( + vertexNormals(i,0), + vertexNormals(i,1), + vertexNormals(i,2)); + } + if (hasVQuality) { + vi->Q() = vertexQuality(i); + } + } + + //add faces and their associated normals and quality if any + + bool hasFNormals = faceNormals.rows() > 0; + bool hasFQuality = faceQuality.rows() > 0; + if (hasFNormals && (faces.size() != (size_t)faceNormals.rows())) { + throw MLException( + "Error while creating mesh: the number of face normals " + "is different from the number of faces."); + } + if (hasFQuality) { + if (faces.size() != (size_t)faceQuality.size()) { + throw MLException( + "Error while creating mesh: the number of face quality " + "values is different from the number of faces."); + } + } + PolyMesh::FaceIterator fi = + vcg::tri::Allocator::AddFaces(pm, faces.size()); + auto it = faces.begin(); + for (unsigned int i = 0; i < faces.size(); ++i, ++fi, ++it) { + fi->Alloc(it->size()); + const EigenVectorXui& iface = *it; + for (unsigned int j = 0; j < iface.size(); ++j){ + if ((unsigned int)iface(j) >= ivp.size()) { + throw MLException( + "Error while creating mesh: bad vertex index " + + QString::number(iface(j)) + " in face " + + QString::number(i) + "; vertex " + QString::number(j) + "."); + } + fi->V(j) = ivp[iface(j)]; + } + if (hasFNormals){ + fi->N() = PolyMesh::CoordType( + faceNormals(i,0), + faceNormals(i,1), + faceNormals(i,2)); + } + if (hasFQuality) { + fi->Q() = faceQuality(i); + } + } + + vcg::tri::PolygonSupport::ImportFromPolyMesh(m, pm); + + if (!hasFNormals){ + vcg::tri::UpdateNormal::PerFace(m); + } + if (!hasVNormals){ + vcg::tri::UpdateNormal::PerVertex(m); + } + } + else { + throw MLException("Error while creating mesh: Vertex matrix is empty."); + } + + return m; +} + /** * @brief Adds a new custom vertex attribute of scalars to the given mesh. * diff --git a/src/common/utilities/eigen_mesh_conversions.h b/src/common/utilities/eigen_mesh_conversions.h index ea4ed7a88..e25771a29 100644 --- a/src/common/utilities/eigen_mesh_conversions.h +++ b/src/common/utilities/eigen_mesh_conversions.h @@ -25,6 +25,7 @@ #define MESHLAB_EIGEN_MESH_CONVERSIONS_H #include +#include #include "../ml_document/cmesh.h" typedef Eigen::Matrix EigenVectorXm; @@ -44,6 +45,15 @@ CMeshO meshFromMatrices( const EigenVectorXm& vertexQuality = EigenVectorXm(), const EigenVectorXm& faceQuality = EigenVectorXm()); +// From eigen to polygonal CMeshO +CMeshO polyMeshFromMatrices( + const EigenMatrixX3m& vertices, + const std::list& faces, + const EigenMatrixX3m& vertexNormals = EigenMatrixX3m(), + const EigenMatrixX3m& faceNormals = EigenMatrixX3m(), + const EigenVectorXm& vertexQuality = EigenVectorXm(), + const EigenVectorXm& faceQuality = EigenVectorXm()); + void addVertexScalarAttribute( CMeshO& mesh, const EigenVectorXm& attributeValues,