Real-time, segment-driven surface mesh deformation with thin-plate smoothing and detail preservation. Built with C++20, libigl, Eigen, Polyscope, and ImGui.
Highlights
- Paint-based segment selection with a fast KD-tree brush.
- Save/load editable segments to a simple text format (
.seg). - Thin-plate bi-Laplacian smoothing (cotangent Laplacian, inverse-area weights).
- Pre-factorized deformation solver for interactive updates.
- Detail-preserving reconstruction via per-vertex local frames.
- Real-time visualization with Polyscope + ImGui.
Repo Structure
src/main.cpp– GUI, interaction modes, and overall app flow.src/kd_tree.*– KD-tree for brush-based vertex queries.src/mesh_smoothing.*– Thin-plate smoothing on the surface mesh.src/mesh_deformation.*– Pre-factorized deformation solver (bi-Laplacian).src/mesh_detail.*– Local-frame detail extraction and reconstruction.src/serialization.*– Human-readable segment I/O.data/– Sample.offmeshes and example.segsegment files.assets/– Screenshots used in this README.
Quick Start
- Prereqs: C++20 compiler and CMake 3.28+. Ninja is used by the presets.
- Recommended compilers:
gcc >= 12,clang >= 12,msvc >= 19.29.
- Recommended compilers:
- Clone with submodules:
git clone --recursive <this-repo>- or
git submodule update --init --recursiveif already cloned.
- Build (Release):
cmake --preset releasecmake --build build/release -j(add-j2on low-memory machines)
- Run:
build/release/main [optional_path/to/mesh.off]- Sample meshes live in
data/(e.g.,data/bunny.off).
Notes
- The Release preset enables
-march=native. If you hit CPU-specific issues, configure without presets and omit that flag (e.g.,cmake -S . -B build/release -DCMAKE_BUILD_TYPE=Release). - If Ninja is not installed, either install it or change the generator in
CMakePresets.json.
Using The App
- Load Mesh
- Click “Load .off Mesh” and choose a file (e.g., from
data/).
- Click “Load .off Mesh” and choose a file (e.g., from
- Vertex Selector (Paint Mode)
- Click “Start Painting”. Left-click to paint, right-click to erase.
- Adjust “Brush Radius”. Click “Create Segment from Selection”.
- Segments
- Switch between segments. Save to or load from
.segfiles.
- Switch between segments. Save to or load from
- Mesh Smoothing
- “Compute Smooth Mesh” to derive a low-frequency base. Toggle between smooth/detail views.
- Segment Transformation
- “Start Deformation” to enable interactive transforms. Adjust translation and Euler-angle rotations; “Reset” to clear transforms.
- FPS and render settings: Polyscope → Render.
Screenshots
Data & Segment Format
- Samples included in
data/:bunny.off,hand.off,woody-hi.off,luigi.off, etc.- Example segments:
bunny_segments.seg,hand_segments.seg,woody_hi_segments.seg,luigi_segments.seg.
.segfile format (one segment per line):name; tx,ty,tz; rx,ry,rz; v0,v1,v2,...- Translation
(t*)in units of the mesh; rotation(r*)in radians about X/Y/Z;v*are vertex indices in the loaded mesh.
How It Works
- Selection & Segments
- A custom KD-tree (
src/kd_tree.*) accelerates brush queries to add/remove vertices from the active selection. Selections become named segments.
- A custom KD-tree (
- Thin-Plate Smoothing
- Builds a bi-Laplacian system
L W Lcomputed from cotangent Laplacian and inverse Voronoi area mass matrix (libigl). Known vertices (near segments) are fixed; unknowns are solved via sparse LDLT.
- Builds a bi-Laplacian system
- Deformation Solver
- Segment transforms are applied to the smoothed mesh. The linear system is pre-factorized so updates are interactive when sliders change.
- Detail Preservation
- High-frequency detail is extracted on the original mesh into a local tangent frame per vertex, then reconstructed after deformation to preserve fine features.
Build Details
- Toolchain
- CMake 3.28+, C++20 compiler (GCC/Clang/MSVC as above).
- Third-party (via
extern/submodules)- libigl, Eigen (via libigl), Polyscope, ImGui (via Polyscope), spdlog, portable-file-dialogs.
- Presets
debug(warnings, debug logs),sanitize(ASan),release(optimized),profile(RelWithDebInfo +-pg).
- Logging
- Debug builds define
SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_DEBUG. Adjust inCMakeLists.txtif desired.
- Debug builds define
Troubleshooting
- Ninja not found
- Install Ninja or change
generatorinCMakePresets.jsonto e.g.Unix Makefilesor Visual Studio.
- Install Ninja or change
- OpenGL issues
- Ensure a working OpenGL 3.3+ context and drivers. On headless/remote setups, use a proper OpenGL-capable environment.
- Illegal instruction on older CPUs
- Reconfigure without
-march=native(avoid thereleasepreset or edit it).
- Reconfigure without
Roadmap Ideas
- Segment deletion and reordering.
- Additional constraint types and weighting schemes.
- Support for more mesh formats beyond OFF.
- Export deformed meshes to common formats.
Acknowledgments
- Built with libigl, Eigen, Polyscope, ImGui, spdlog, and portable-file-dialogs. See their licenses in
extern/.
License
- Project source currently has no explicit license. Third-party submodules are under their respective licenses in
extern/. Add a project license if you plan to share or distribute.



