ad simple visualization
This commit is contained in:
@@ -38,8 +38,9 @@ add_subdirectory(deps/glfw-3.4)
|
|||||||
# --------- Executable ---------
|
# --------- Executable ---------
|
||||||
add_executable(${PROJECT_NAME} src/apps/v0/conformallab_cli.cpp )
|
add_executable(${PROJECT_NAME} src/apps/v0/conformallab_cli.cpp )
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
|
||||||
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/deps/single_includes
|
${CMAKE_CURRENT_SOURCE_DIR}/deps/single_includes
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/deps/eigen-3.4.0/
|
${CMAKE_CURRENT_SOURCE_DIR}/deps/eigen-3.4.0/
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/deps/CGAL-6.1.1/include
|
${CMAKE_CURRENT_SOURCE_DIR}/deps/CGAL-6.1.1/include
|
||||||
@@ -47,8 +48,9 @@ target_include_directories(${PROJECT_NAME} PRIVATE
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-2.6.0/include
|
${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-2.6.0/include
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-glad/include
|
${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-glad/include
|
||||||
)
|
)
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
)
|
||||||
add_library(glad STATIC
|
add_library(glad STATIC
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-glad/src/glad.c
|
${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-glad/src/glad.c
|
||||||
)
|
)
|
||||||
|
|||||||
64
code/include/simple_visualize.h
Normal file
64
code/include/simple_visualize.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <CGAL/Surface_mesh.h>
|
||||||
|
#include <Eigen/Dense>
|
||||||
|
#include <igl/opengl/glfw/Viewer.h>
|
||||||
|
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace mesh_utils {
|
||||||
|
|
||||||
|
template <typename Kernel>
|
||||||
|
void cgal_to_eigen(CGAL::Surface_mesh<typename Kernel::Point_3>& mesh,
|
||||||
|
Eigen::MatrixXd& V, Eigen::MatrixXi& F) {
|
||||||
|
V.resize(mesh.num_vertices(), 3);
|
||||||
|
F.resize(mesh.num_faces(), 3);
|
||||||
|
|
||||||
|
for (auto v : mesh.vertices()) {
|
||||||
|
auto p = mesh.point(v);
|
||||||
|
V.row(v.idx()) << p.x(), p.y(), p.z();
|
||||||
|
}
|
||||||
|
|
||||||
|
Eigen::Index face_idx = 0;
|
||||||
|
for (auto f : mesh.faces()) {
|
||||||
|
int vertex_count = 0;
|
||||||
|
for (auto h : CGAL::halfedges_around_face(mesh.halfedge(f), mesh)) {
|
||||||
|
auto v = mesh.target(h);
|
||||||
|
F(face_idx, vertex_count) = v.idx();
|
||||||
|
++vertex_count;
|
||||||
|
}
|
||||||
|
face_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Kernel>
|
||||||
|
void simple_visualize_mesh( CGAL::Surface_mesh<typename Kernel::Point_3>& mesh, bool triangulate = true) {
|
||||||
|
if(CGAL::is_triangle_mesh(mesh)) {
|
||||||
|
std::cerr << "Warning: Mesh is not triangulated. Visualizer expects triangles.\n";
|
||||||
|
|
||||||
|
|
||||||
|
if(triangulate){
|
||||||
|
std::cerr << "Triangulating mesh for visualization...\n";
|
||||||
|
CGAL::Polygon_mesh_processing::triangulate_faces(mesh);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
std::cerr << " exit without visualizetion.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Eigen::MatrixXd V; Eigen::MatrixXi F;
|
||||||
|
cgal_to_eigen<Kernel>(mesh, V, F);
|
||||||
|
igl::opengl::glfw::Viewer viewer;
|
||||||
|
viewer.data().set_mesh(V, F);
|
||||||
|
viewer.launch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zero-Copy Map für V (optional)
|
||||||
|
template <typename Kernel>
|
||||||
|
Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, 3, Eigen::RowMajor>>
|
||||||
|
get_vertex_map(CGAL::Surface_mesh<typename Kernel::Point_3>& mesh) {
|
||||||
|
auto& points = mesh.points();
|
||||||
|
double* data = reinterpret_cast<double*>(&points[0][0]);
|
||||||
|
return {data, static_cast<Eigen::Index>(points.size()), 3};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
@@ -1,31 +1,38 @@
|
|||||||
#include <CGAL/Simple_cartesian.h>
|
#include <CGAL/Simple_cartesian.h>
|
||||||
#include <CGAL/Surface_mesh.h>
|
#include <CGAL/Surface_mesh.h>
|
||||||
#include <CGAL/IO/polygon_mesh_io.h>
|
#include <CGAL/IO/polygon_mesh_io.h>
|
||||||
|
#include "simple_visualize.h"
|
||||||
|
|
||||||
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
|
|
||||||
|
|
||||||
#include <CLI11.hpp>
|
#include <CLI11.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <igl/opengl/glfw/Viewer.h>
|
|
||||||
#include <Eigen/Core>
|
#include <Eigen/Core>
|
||||||
|
|
||||||
|
|
||||||
using Kernel = CGAL::Simple_cartesian<double>;
|
using Kernel = CGAL::Simple_cartesian<double>;
|
||||||
using Point = Kernel::Point_3;
|
using Point = Kernel::Point_3;
|
||||||
using Mesh = CGAL::Surface_mesh<Point>;
|
using Mesh = CGAL::Surface_mesh<Point>;
|
||||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
|
|
||||||
|
bool parse_arguments(int argc, char* argv[], std::string& input_file, std::string& output_file, bool& show, bool& verbose) {
|
||||||
CLI::App app{"demo of conformallab"};
|
CLI::App app{"demo of conformallab"};
|
||||||
std::string input_file;
|
|
||||||
std::string output_file; // default output file name
|
|
||||||
|
|
||||||
app.add_option("-i,--input", input_file, "Input OFF file")->required();
|
app.add_option("-i,--input", input_file, "Input OFF file")->required();
|
||||||
app.add_option("-o,--output", output_file, "Output OFF file (optional)");
|
app.add_option("-o,--output", output_file, "Output OFF file (optional)");
|
||||||
CLI11_PARSE(app, argc, argv);
|
app.add_flag("-s,--show", show, "Show the input mesh in a viewer");
|
||||||
|
app.add_flag("-v,--verbose",verbose, "Enable verbose output");
|
||||||
|
app.set_help_flag("-h,--help", "Show this help message and exit");
|
||||||
|
|
||||||
|
try {
|
||||||
|
CLI11_PARSE(app, argc, argv);
|
||||||
|
} catch (const CLI::ParseError &e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
if (input_file.empty()) {
|
if (input_file.empty()) {
|
||||||
std::cerr << "Input file is required.\n";
|
std::cerr << "Input file is required.\n";
|
||||||
@@ -36,6 +43,28 @@ int main(int argc, char* argv[])
|
|||||||
std::cerr << "Unsupported file format. Please provide an OFF file.\n";
|
std::cerr << "Unsupported file format. Please provide an OFF file.\n";
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
std::string input_file;
|
||||||
|
std::string output_file;
|
||||||
|
bool show = false;
|
||||||
|
bool verbose = false;
|
||||||
|
|
||||||
|
if(!parse_arguments(argc, argv, input_file, output_file, show, verbose)) {
|
||||||
|
std::cerr << "Failed to parse arguments.\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Input file: " << input_file << "\n";
|
||||||
|
std::cout << "Output file: " << output_file << "\n";
|
||||||
|
std::cout << "Show mesh: " << (show ? "Yes" : "No") << "\n";
|
||||||
|
std::cout << "Verbose: " << (verbose ? "Yes" : "No") << "\n";
|
||||||
|
|
||||||
Mesh surface_mesh;
|
Mesh surface_mesh;
|
||||||
if (!CGAL::IO::read_polygon_mesh(input_file, surface_mesh) || surface_mesh.is_empty()) {
|
if (!CGAL::IO::read_polygon_mesh(input_file, surface_mesh) || surface_mesh.is_empty()) {
|
||||||
@@ -52,36 +81,9 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
|
|
||||||
// CGAL -> libigl
|
// CGAL -> libigl
|
||||||
PMP::triangulate_faces(surface_mesh);
|
if(show){
|
||||||
//todo : we should check if the mesh is already triangulated, and only call this if it isn't, to avoid unnecessary processing. CGAL::Polygon_mesh_processing::is_triangulated() can be used for this check.
|
mesh_utils::simple_visualize_mesh<Kernel>(surface_mesh,true);
|
||||||
Eigen::MatrixXd Vertices;
|
}
|
||||||
Eigen::MatrixXi Faces;
|
|
||||||
Vertices.resize(surface_mesh.number_of_vertices(), 3);
|
|
||||||
Faces.resize(surface_mesh.number_of_faces(), 3);
|
|
||||||
|
|
||||||
for (auto v : surface_mesh.vertices()) {
|
|
||||||
const auto& p = surface_mesh.point(v);
|
|
||||||
Vertices(v.idx(), 0) = p.x();
|
|
||||||
Vertices(v.idx(), 1) = p.y();
|
|
||||||
Vertices(v.idx(), 2) = p.z();
|
|
||||||
}
|
|
||||||
|
|
||||||
int f_i = 0;
|
|
||||||
for (auto f : surface_mesh.faces()) {
|
|
||||||
int k = 0;
|
|
||||||
for (auto hv : CGAL::halfedges_around_face(surface_mesh.halfedge(f), surface_mesh)) {
|
|
||||||
auto v = surface_mesh.target(hv);
|
|
||||||
Faces(f_i, k) = v.idx();
|
|
||||||
++k;
|
|
||||||
}
|
|
||||||
++f_i;
|
|
||||||
}
|
|
||||||
|
|
||||||
igl::opengl::glfw::Viewer viewer;
|
|
||||||
viewer.data().set_mesh(Vertices, Faces);
|
|
||||||
viewer.launch();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// for now, we just write the input mesh to the output file as a placeholder
|
// for now, we just write the input mesh to the output file as a placeholder
|
||||||
if (!output_file.empty() && !CGAL::IO::write_polygon_mesh(output_file, surface_mesh)) {
|
if (!output_file.empty() && !CGAL::IO::write_polygon_mesh(output_file, surface_mesh)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user