PeelMesh is a C++ library with optional Python bindings for flexible and interactive 3D mesh segmentation. It supports manually specified landmarks, dynamic geodesic path embedding, and mesh topology editing. This repository accompanies the CGI 2025 paper: "PeelMesh: Efficient Interactive Segmentation via Geodesic-Driven Dynamic Topological Updates"
- Custom landmark-based segmentation
- Halfedge-based triangle mesh data structure with dynamic KD-tree integration
- Geometric attributes query (e.g. curvatures, surface area, geodesic distance)
- Optional Python bindings via pybind11
peelmesh
βββ include/peelmesh/ # Public C++ headers
βββ src/peelmesh/ # C++ source files
βββ src/bindings/ # pybind11 bindings
βββ tests/ # GoogleTest test suite
βββ examples/ # Example C++ demos and PSD experiment
βββ models/ # Some meshes
βββ cmake/ # CMake config & export files
βββ external/ # External dependencies via FetchContent
βββ CMakeLists.txt # CMake project- CMake
$\ge$ 3.21 - C++ compiler with C++20 support (e.g. MSVC 2022, Clang for MSVC 2022, GCC 11+)
- Python 3.x (optional, for bindings)
PeelMesh uses CMake FetchContent to automatically manage most dependencies. You don't need to install them manually.
| Library | Purpose | Managed By | Optional? |
|---|---|---|---|
| fmt | Safe & fast string formatting | FetchContent | No |
| geometry-central | Fast geodesic computation | FetchContent | No |
| pybind11 | C++ to Python bindings | FetchContent | Yes (if PEELMESH_BUILD_PYTHON_MOUDLE=ON) |
| googletest | Unit testing framework | FetchContent | Yes (if PEELMESH_BUILD_UNIT_TESTS=ON) |
| Open3D | 3D visualization and GUI demo | System/FetchContent | Yes (if PEELMESH_BUILD_EXAMPLES=ON) |
Note on Open3D: Due to its size, we recommend having Open3D pre-installed on your system if you wish to build the interactive demo.
# Clone repository
git clone https://github.com/Nightinghost/peelmesh
cd peelmesh
# Configure
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=<path-to-install>
# Build
cmake --build . --target installYou can install PeelMesh directly into your Python environment:
cd peelmesh
pip install .If you need to build the extension without installing:
conda activate myenv # activate your Python environment
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DPEELMESH_BUILD_PYTHON_BINDINGS=ON
cmake --build .The resulting Python module will be named peelmesh and located in the build/lib/Release (or build/lib/) folder, e.g. build/lib/Release/peelmesh.cp313-win_amd64.pyd on Windows.
To use the library in your project, you can add the following to your CMakeLists.txt file:
find_package(peelmesh REQUIRED)
message(STATUS "PeelMesh version: ${peelmesh_VERSION}")
if(MSVC)
add_compile_definitions(_USE_MATH_DEFINES)
endif()
target_link_libraries(your_target PRIVATE peelmesh::peelmesh)#include <peelmesh/pipeline.hpp>
int main()
{
// Mesh data
std::vector<Eigen::Vector3d> vertices = {{0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {1, 1, 0}};
std::vector<Eigen::Vector3i> triangles = {{0, 1, 2}, {1, 3, 2}};
auto mesh = std::make_shared<peelmesh::TriangleMesh>(vertices, triangles);
// Halfedge information of the mesh
mesh->PrintMesh();
// Create a pipeline object
peelmesh::PeelMeshPipeline pipe(mesh);
// Compute geodesic paths from vertices[start] to vertices[end]
pipe.AddGeodesicPath(0, 1);
pipe.AddGeodesicPath(1, 3);
pipe.AddGeodesicPath(3, 0);
// Extract the segment bounded by the geodesics based on the given vertices sequence
auto segment = pipe.PeelOffMesh({0, 1, 3, 0});
// Get the vertices and triangles of the segmented new mesh
const auto &[verts, tris] = segment->getMeshData();
return 0;
}To use the library in Python, you should copy the peelmesh.*.pyd file (e.g. peelmesh.cp310-win_amd64.pyd) to the Python project directory. Then, you can import the peelmesh module and use the TriangleMesh and PeelMeshPipeline classes as shown in the example below:
import numpy as np
import peelmesh as pm
# Mesh data
vertices = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]])
triangles = np.asarray([[0, 1, 2], [1, 3, 2]])
# Create a pipeline object
pipe = pm.PeelMeshPipeline(vertices, triangles)
# Compute geodesic paths from vertices[start] to vertices[end]
pipe.add_geodesic_path(0, 1)
pipe.add_geodesic_path(1, 3)
pipe.add_geodesic_path(3, 0)
# Extract the segment bounded by the geodesics based on the given vertices sequence
segment = pipe.peeloff_mesh([0, 1, 3, 0])
# Get the vertices and triangles of the segmented new mesh
verts, tris = segment.get_mesh_data()For other information, try:
import peelmesh as pm
help(pm)This project includes an interactive GUI demo for mesh segmentation. The tool allows you to manually define landmarks and extract a sub-mesh from a closed boundary on the surface.
β Demo binaries are available under the Releases page.
Please refer to the included README.md inside the zip file for usage instructions.
-
Load and visualize mesh models (File > Open)
-
Export all segmented sub-meshes (Export > Export Segments)
-
Interactive landmark selection
| Action | Shortcut |
|---|---|
| Select feature point | Ctrl + Left Click |
| Undo last feature point | Ctrl + Right Click |
| Close boundary | Right Click on canvas |
| Execute segmentation | Enter |
| Reset camera | R key |
After pressing Enter, the tool computes a segmentation based on the geodesic path between selected landmarks, and extracts the corresponding sub-meshes for further processing or export.
If you use this code in your research, please cite our paper:
@incollection{PeelMesh,
title = {{{PeelMesh}}: {{Efficient Interactive Segmentation}} via {{Geodesic-Driven Dynamic Topological Updates}}},
booktitle = {Advances in {{Computer Graphics}}},
author = {Yin, Junjie and Zhou, Hao and Huang, Zixi and Fang, Meie and Li, Ping and Ma, Weiyin},
year = 2026,
volume = {16507},
pages = {180--191},
publisher = {Springer Nature Switzerland},
doi = {10.1007/978-3-032-22261-9_15},
}