Getting Started | C++

Introduction

Real-time geometric processing. Easy to use, robust on real-world data.

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

Try it in your browser

Interactive mesh booleans, collisions, isobands and more. No install needed.

You control the complexity. Simple code just works. Algorithms compute what they need internally. In performance-critical paths, precompute structures and tag them. The compiler detects and reuses them.

Your Datastd::vector<int>Your Datastd::vector<float>Faces Rangetf::make_faces<3>(ids)auto [a,b,c] = faces[i];for (auto f : faces) { }Points Rangetf::make_points<3>(coords)auto v = pt + vec;auto d = tf::dot(a, b);Composed Rangepolygons = tf::make_polygons(faces, points)auto poly = polygons.front();auto [p0, p1, p2] = poly;auto [id0, id1, id2] = poly.indices();Optional StructuresPrecomputetf::aabb_tree<int, float, 3> tree{polygons};auto fm = tf::make_face_membership(polygons);...auto mel = tf::make_manifold_edge_link(polygons);Attach Policiestagged = polygons | tf::tag(tree) | ... | tf::tag(mel)+ Transformform0 = tagged | tf::tag(tr0)+ Transformform1 = tagged | tf::tag(tr1)Algorithmstf::make_boolean(form0, form1, op);tf::intersects(form0, form1);...tf::distance2(form0, form1);

You choose the complexity; trueform adapts.

Installation

Install via pip, system-wide, or FetchContent.

Modules

Learn how trueform works — primitives, ranges, policies, and the algorithms that connect them.

Benchmarks

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

Examples

Complete workflows — geometry, alignment, and library comparisons.

VTK Integration

Bring trueform performance to VTK applications.

Research

Theory, publications, and citation.

Quick Tour

Here's how trueform enables complex geometric workflows with minimal code:

#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 faces = tf::make_faces<3>(indices);
auto triangles = tf::make_polygons(faces, points);
// or maybe faces are variable
std::vector<int> offsets = {0, 3};
auto d_faces = tf::make_faces(offsets, indices);
auto d_polygons = tf::make_polygons(d_faces, points);

auto polygons_buffer = tf::read_stl("file.stl");
auto polygons = polygons_buffer.polygons();

Primitive queries work directly on geometry:

auto polygon = polygons.front();
auto segment = tf::make_segment_between_points(points[0], points[1]);
auto ray = tf::make_ray_between_points(
    tf::make_point(0.2f, 0.2f, -1.0f),
    tf::make_point(0.2f, 0.2f, 1.0f));

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

Mesh analysis reveals structure and defects:

// Connected components
auto [n_components, labels] = tf::make_manifold_edge_connected_component_labels(polygons);
auto [components, component_ids] = tf::split_into_components(polygons, labels);

// Vertex neighborhoods
auto v_link = tf::make_vertex_link(polygons);
auto k2_ring = tf::make_k_rings(v_link, 2);
auto neighs = tf::make_neighborhoods(polygons.points() | tf::tag(v_link), 0.5f);

// Principal curvatures and directions
auto [k0, k1, d0, d1] = tf::make_principal_directions(polygons);

// Boundary curves (open edges)
auto boundary_paths = tf::make_boundary_paths(polygons);
auto boundary_curves = tf::make_curves(boundary_paths, polygons.points());

// Non-manifold edges (shared by >2 faces)
auto bad_edges = tf::make_non_manifold_edges(polygons);
auto bad_segments = tf::make_segments(bad_edges, polygons.points());

// Fix inconsistent face winding
tf::orient_faces_consistently(polygons);

Spatial acceleration enables queries on transformed geometry:

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

auto dynamic_form = polygons | tf::tag(tree)
    | tf::tag(tf::make_frame(tf::random_transformation<float, 3>()));
auto static_form = polygons | tf::tag(tree);

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

// Collect all intersecting primitive 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 combine meshes:

auto [result_mesh, labels] = tf::make_boolean(
    polygons0,
    polygons1 | tf::tag(tf::make_rotation(tf::deg(45.f), tf::axis<2>)),
    tf::boolean_op::merge);

// With intersection curves
auto [result, labels, curves] = tf::make_boolean(
    polygons0, polygons1, tf::boolean_op::intersection, tf::return_curves);

Scalar fields and isocontours:

// Compute distance field from a plane
auto plane = tf::make_plane(polygons.front());
tf::buffer<float> scalars;
scalars.allocate(polygons.points().size());
tf::parallel_transform(polygons.points(), scalars, tf::distance_f(plane));

// Extract isocontours embedded into the mesh
std::vector<float> cut_values = {-0.5f, 0.0f, 0.5f};
auto [contour_mesh, contour_labels, isocontours] = tf::embedded_isocurves(
    polygons, scalars, tf::make_range(cut_values), tf::return_curves);

Mesh cleanup prepares geometry for processing:

// Merge coincident vertices, remove degenerates and duplicates
auto clean_mesh = tf::cleaned(polygons, tf::epsilon<float>);

// Triangulate n-gons
auto tri_mesh = tf::triangulated(polygons);

// Ensure outward-facing normals on closed meshes
tf::ensure_positive_orientation(polygons);

Continue Learning

The Quick Tour above shows trueform's syntax. To build intuition for real workflows, start with the Geometry Walkthrough — a complete example from raw data to final output. Then explore the Modules to understand the underlying patterns.

Geometry Walkthrough

A hands-on tour from raw geometry through booleans and connected components. See the library in action.

Modules

Learn how trueform works — primitives, ranges, policies, and the algorithms that connect them.