Getting Started | C++

Introduction

Welcome to trueform — real-time geometric processing for C++.

trueform is a C++ library for real-time geometric processing. Spatial queries, mesh booleans, isocontours, topology — at interactive speed on million-polygon meshes. Robust on real-world inputs: non-manifold flaps, inconsistent geometry, the artifacts that pipelines accumulate. Algorithms with formal guarantees. Header-only; works directly on your data with zero-copy views.

Installation

Requirements and installation via CMake FetchContent.

Tutorial

Primitives, trees, topology, booleans — step by step.

Benchmarks

Benchmarked against VTK, CGAL, libigl, FCL, and nanoflann.

Live Examples

Booleans, collision, isobands, and more — in your browser.

VTK Integration

Bring trueform performance to VTK applications.

Publications

Research papers behind trueform's algorithms.

Research Foundation

Geometry pipelines accumulate defects. Sculpting, remeshing, format conversion—each step can introduce non-manifold flaps, inconsistencies, and surface artifacts. By the time geometry reaches your algorithm, it is rarely the ideal manifold most methods assume.

trueform is built around a simple idea: a mesh should be understood as an intended surface, observed through the noise of floating-point arithmetic and prior processing.

These defects are additive—they attach to the surface without redefining it. The underlying structure remains recoverable.

This perspective shapes the algorithms:

  • Topological consistency. The intersection graph is reduced to its unique canonical form. The reduction diagram maps each intersection to its simplest representative in the ε-topology, ensuring consistency under floating-point uncertainty.
  • Artifacts are modeled as independent noise. Geometric inconsistencies decompose locally across polygon regions; topological artifacts decompose globally across manifold edge-connected components—enabling robust classification of the intended structure.

The result is commutative correctness: operations on non-ideal meshes behave as if applied to the intended geometry. Chain operations freely and defer cleanup to the end.

Read the papers

Quick Tour

Here's how trueform enables complex geometric workflows with minimal code—wrapping your existing data, performing queries, and computing results in real time:

#include <trueform/trueform.hpp>

// Start with your raw data—no copies, no conversions
std::vector<float> raw_points = {0, 0, 0, 1, 0, 0, 0, 1, 0};
std::vector<int> indices = {0, 1, 2};

auto points = tf::make_points<3>(raw_points);
auto triangles = tf::make_polygons(tf::make_blocked_range<3>(indices), points);

Primitive queries work directly on geometry:

auto triangle = triangles.front();
auto segment = tf::make_segment_between_points(points[0], points[1]);
auto ray = tf::make_ray_between_points(
    tf::point<float, 3>{0.2f, 0.2f, -1.0f},
    tf::point<float, 3>{0.2f, 0.2f, 1.0f});

auto [dist2, pt_on_tri, pt_on_seg] = tf::closest_metric_point_pair(triangle, segment);
bool contains = tf::contains_point(triangle, points[0]);
if (auto hit = tf::ray_hit(ray, triangle)) {
    auto [status, t, hit_point] = hit;
}

Build topology for mesh-level operations:

tf::face_membership<int> face_membership;
face_membership.build(triangles);

tf::manifold_edge_link<int, 3> manifold_edge_link;
manifold_edge_link.build(triangles.faces(), face_membership);

// Label connected components
tf::buffer<int> component_labels;
component_labels.allocate(triangles.size());
auto component_count = tf::label_connected_components<int>(
    component_labels, tf::make_applier(manifold_edge_link));

Spatial acceleration enables real-time queries on transformed geometry:

tf::aabb_tree<int, float, 3> tree(triangles, tf::config_tree(4, 4));

auto transform = tf::random_transformation<float, 3>();
auto dynamic_form = tf::make_form(tf::make_frame(transform), tree,
                                triangles);
auto static_form = tf::make_form(tree,
                                triangles);

// Collision detection
bool does_intersect = tf::intersects(static_form, dynamic_form);
float distance2 = tf::distance2(static_form, dynamic_form);

// Collect all intersecting triangle pairs
std::vector<std::pair<int, int>> collisions;
tf::gather_ids(static_form, dynamic_form, tf::intersects_f,
               std::back_inserter(collisions));
// Compute intersection curves
auto curves = tf::make_intersection_curves(static_form, dynamic_form);

Boolean operations in real-time:

auto dynamic_form = tf::make_form(tf::make_frame(transform), tree,
    triangles | tf::tag(face_membership) | tf::tag(manifold_edge_link));
auto static_form = tf::make_form(tree,
    triangles | tf::tag(face_membership) | tf::tag(manifold_edge_link));

auto [result_mesh, labels, intersection_curves] = tf::make_boolean(
    static_form, dynamic_form, tf::boolean_op::merge, tf::return_curves);

Parallel algorithms create scalar fields efficiently:

auto some_plane = tf::make_plane(triangles.front());
tf::buffer<float> scalars;
scalars.allocate(points.size());
tf::parallel_transform(points, scalars, tf::distance_f(some_plane));

Curve embedding extracts isocontours directly into the mesh:

std::vector<float> cut_values = {0.1f, 0.5f, 1.0f};
auto [contour_mesh, contour_labels, isocontours] = tf::embedded_isocurves<int>(
    triangles, scalars, tf::make_range(cut_values), tf::return_curves);

This is trueform from a bird's eye view. For comprehensive coverage of all features, patterns, and advanced usage, explore the module documentation starting with Core.