Remesh
The Remesh module provides tools for modifying triangle mesh resolution: reducing face count through decimation and edge collapse, or redistributing vertices through isotropic remeshing. All functions operate on triangle meshes and return a new mesh along with the resulting half-edge structure.
Include the module with:
#include <trueform/remesh.hpp>
tf::triangulated from the Geometry module.config.parallel = false for sequential execution (e.g. when processing many meshes in parallel externally).Decimation
Reduce face count using quadric error metrics. The algorithm collapses edges in priority order, placing the new vertex at the position that minimizes geometric error.
Basic Usage
auto mesh = tf::read_stl("model.stl");
auto polys = mesh.polygons();
// Decimate to 10% of original faces
auto [result, he] = tf::decimated(polys, 0.1f);
// result is a tf::polygons_buffer, he is a tf::half_edges
for (auto tri : result.polygons()) {
auto [pt0, pt1, pt2] = tri;
}
With Configuration
tf::decimate_config<float> config;
config.preserve_boundary = true;
config.max_aspect_ratio = 20;
config.parallel = false; // sequential execution
auto [result, he] = tf::decimated(polys, 0.1f, config);
decimate_config parameters:
| Parameter | Default | Description |
|---|---|---|
max_aspect_ratio | 40 | Maximum triangle aspect ratio after collapse. Set negative to disable |
preserve_boundary | false | If true, boundary edges are never collapsed |
stabilizer | 1e-3 | Tikhonov stabilizer for quadric solve |
parallel | true | If true, use parallel partitioned collapse |
With Index Maps
Pass tf::return_index_map to also receive face and vertex index maps that track which elements survived the decimation:
auto [result, he, face_map, vertex_map] =
tf::decimated(polys, 0.1f, tf::return_index_map);
// Or with config:
auto [result, he, face_map, vertex_map] =
tf::decimated(polys, 0.1f, config, tf::return_index_map);
With Pre-Computed Half-Edges
When half-edges are already available (e.g. from a previous operation), tag them onto the polygons to skip rebuilding:
tf::half_edges<int> he(polys);
// Tag half-edges onto polygons - decimated reuses them
auto [result, he_out] = tf::decimated(polys | tf::tag(he), 0.1f);
Isotropic Remeshing
Redistribute vertices to achieve uniform edge lengths. Each iteration splits long edges, collapses short edges, flips edges to improve valence, and relaxes vertex positions tangentially.
Basic Usage
auto mesh = tf::read_stl("model.stl");
auto polys = mesh.polygons();
// Remesh to target edge length
float mel = tf::mean_edge_length(polys);
auto [result, he] = tf::isotropic_remeshed(polys, 2.0f * mel);
With Configuration
tf::remesh_config<float> config;
config.target_length = 2.0f * mel;
config.iterations = 5;
config.relaxation_iters = 5;
config.preserve_boundary = true;
auto [result, he] = tf::isotropic_remeshed(polys, config);
remesh_config parameters:
| Parameter | Default | Description |
|---|---|---|
target_length | — | Target edge length. Edges longer are split, shorter are collapsed |
iterations | 3 | Number of outer iterations (split + collapse + flip + relax) |
relaxation_iters | 3 | Number of tangential relaxation iterations per outer iteration |
max_aspect_ratio | -1 | Maximum triangle aspect ratio after collapse. Set negative to disable |
lambda | 0.5 | Damping factor for tangential relaxation in (0, 1] |
preserve_boundary | false | If true, boundary edges are never split or collapsed |
use_quadric | false | If true, use quadric error metric for collapse vertex placement |
parallel | true | If true, use parallel collapse during the collapse step |
With Pre-Computed Half-Edges
tf::half_edges<int> he(polys);
auto [result, he_out] = tf::isotropic_remeshed(polys | tf::tag(he), 2.0f * mel);
Edge Collapse
Collapse edges shorter than a threshold. Unlike decimation which uses quadric error ordering, this collapses by edge length — shortest first.
Basic Usage
auto mesh = tf::read_stl("model.stl");
auto polys = mesh.polygons();
float mel = tf::mean_edge_length(polys);
// Collapse edges shorter than 3/4 mel
auto [result, he] = tf::collapsed_short_edges(polys, 0.75f * mel);
With Configuration
tf::length_collapse_config<float> config;
config.max_length = 1.25f * mel;
config.preserve_boundary = true;
config.use_quadric = true;
auto [result, he] = tf::collapsed_short_edges(polys, 0.75f * mel, config);
length_collapse_config parameters:
| Parameter | Default | Description |
|---|---|---|
max_length | max | Maximum edge length allowed after a collapse |
preserve_boundary | false | If true, boundary edges are never collapsed |
use_quadric | true | If true, use quadric error metric for vertex placement |
max_aspect_ratio | 40 | Maximum triangle aspect ratio after collapse. Set negative to disable |
stabilizer | 1e-6 | Tikhonov stabilizer for quadric solve |
parallel | true | If true, use parallel partitioned collapse |
With Index Maps
Pass tf::return_index_map to also receive face and vertex index maps:
auto [result, he, face_map, vertex_map] =
tf::collapsed_short_edges(polys, 0.75f * mel, tf::return_index_map);
// Or with config:
auto [result, he, face_map, vertex_map] =
tf::collapsed_short_edges(polys, 0.75f * mel, config, tf::return_index_map);
With Pre-Computed Half-Edges
tf::half_edges<int> he(polys);
auto [result, he_out] = tf::collapsed_short_edges(polys | tf::tag(he), 0.75f * mel);
