ordito puts mesh processing on the GPU. Geometry, topology, repair, remeshing, spatial queries, discrete differential operators, geodesics, point-cloud reconstruction, and registration — as plain array-in / array-out functions backed by NVIDIA Warp kernels, with a trimesh-inspired API. Every function runs on CUDA when a GPU is available and falls back to CPU otherwise, with the same code.
Ordito (or-DEE-toh) is Italian for the warp of a fabric, and an anagram of toroid: a fitting name for a mesh library built on Warp.
Highlights
- One dependency. The runtime depends on
warp-langalone; NumPy comes with Warp; nothing else (no SciPy, PyTorch or trimesh) is needed at runtime. - Broad coverage. Hundreds of functions across dozens of public modules, spanning primitives, topology, repair, remeshing, spatial queries, discrete differential operators, geodesics, sampling, surface reconstruction, and registration.
- Stays on the device. Functions take Warp arrays and return Warp arrays, so pipelines compose without host round-trips; device placement follows the inputs.
- Optional
Trimeshobject. A frozen mesh class with lazily cached derived quantities (normals, adjacency, boundary loops, manifoldness and watertightness predicates, BVH) for when an object API is more convenient than free functions. - Fully typed (
py.typed), documented per module at https://lucagrementieri.github.io/ordito/, and validated function-by-function against eleven reference implementations — nine established geometry-processing libraries plus SciPy and NumPy (see below).
Learn more
- Getting started — install, the mental model, and a first repair-then-remesh pipeline.
- Examples — a gallery of runnable examples with the images they produce: cleaning a scan, point clouds to watertight surfaces, geodesic distance fields, aligning two scans, and many more.
- Migrating from another library — already know trimesh, libigl, Open3D, MeshLab, potpourri3d, or PyTorch3D? Start here for a function-by-function map.
- Performance — why the GPU path is fast, and how to check any speed claim yourself.
One GPU library instead of nine
Mesh processing in Python has long meant stitching together several excellent — but mostly CPU-bound and stylistically different — libraries. ordito consolidates the functionality it needs from each of them behind a single GPU-accelerated API:
| Replaces | For | In ordito |
|---|---|---|
| trimesh | Mesh bookkeeping: edges, adjacency, boundary, validation, primitives, sampling, proximity | edges, adjacency, boundary, validation, creation, sample, proximity, the Trimesh class |
| libigl (Python bindings) | Discrete differential geometry: cotangent Laplacians, mass matrices, curvature, parametrization, heat-method geodesics | laplacian, energies, curvature, parametrization, heat |
| Open3D | Point clouds, registration, and surface reconstruction: ICP, screened Poisson, ball pivoting | points, registration, reconstruction |
| MeshLab (PyMeshLab) | Mesh editing filters: isotropic remeshing, decimation, smoothing, hole filling, uniform resampling | remesh, smoothing, holes, repair |
| PyVista (VTK) | The VTK toolkit: feature edges, cell-quality metrics, contouring and clipping, point location, arc-length and polyline measures, voxelization | edges, triangles, intersection, levelset, proximity, polyline, voxels |
| MeshLib | Minimum-weight hole filling and stitching, self-intersection repair, voxel offsets and booleans, projection queries, spike and outlier detection | holes, repair, levelset, voxels, proximity, points |
| PyMeshFix (MeshFix / TMesh) | The repair pipeline end to end: a broken digitised surface in, one watertight solid out | repair, holes, validation |
| potpourri3d (geometry-central) | The heat-method family: vector heat, parallel transport, log maps, signed distance, tangent frames | heat, tangent_space |
| PyTorch3D | Batched neighbour and Chamfer primitives, the mesh regularization losses, cubify and marching cubes | metrics, neighbors, energies, registration, levelset, voxels |
SciPy's spatial.KDTree and sparse.csgraph (covered by neighbors,
graph and proximity) and NumPy's array primitives (array, reduce, grouping, linalg)
round the set out to the eleven reference implementations the suite measures against.
These libraries are not runtime dependencies; they are test oracles. Wherever one of them
computes the same quantity as an ordito function, a regression test compares the two outputs
value by value. A parity gate in the test suite fails the build if any library the benchmarks
time against ordito is neither compared in a test nor exempted with a written reason. Every
(group, library) pair in the benchmark suite is either covered by a value test or carries a
written exemption (typically a different algorithm answering a related question); none are
uncovered, and python -m tests.parity prints the current matrix. Where ordito and a reference disagree by definition rather than by rounding
(a sign convention, a squared distance), the docstring says so and the test pins the difference.
Install
uv add ordito
or with pip:
pip install ordito
Requires Python ≥ 3.11 and warp-lang ≥ 1.18. A CUDA-capable GPU is recommended but not
required — every function also runs on Warp's CPU backend. Mesh file I/O via
meshio is an optional extra: pip install "ordito[io]".
Tested on Linux, with and without CUDA, and on macOS (Apple Silicon, CPU backend). The
wheel is pure Python and warp-lang supports Windows, so ordito is expected to work there, but it
is not verified — see
Platform support.
Quickstart
import ordito as od
# Parametric primitives allocate directly on the default device (CUDA if available).
vertices, faces = od.creation.icosphere(subdivisions=4)
# Optional object API: derived quantities are computed on first access and cached.
mesh = od.Trimesh(vertices, faces)
print(f"{mesh.area:.4f}") # 12.5514
print(mesh.is_watertight) # True
print(mesh.euler_characteristic) # 2
Everything the Trimesh class offers is also available as free functions over raw Warp
arrays, so pipelines stay on the device end to end:
import numpy as np
import warp as wp
import ordito as od
vertices, faces = od.creation.icosphere(subdivisions=4)
# Geodesic distance from vertex 0 via the heat method (two sparse solves, on the device).
sources = wp.array([0], dtype=wp.int32, device=vertices.device)
distance = od.heat.heat_geodesic(vertices, faces, sources)
# Uniform, area-weighted surface sampling.
points, face_ids = od.sample.sample_surface(vertices, faces, 10_000, seed=0)
# Feature-preserving isotropic remeshing (split / collapse / flip / smooth / reproject).
remeshed_vertices, remeshed_faces = od.remesh.isotropic_remesh(vertices, faces, target_length=0.05)
Interop with NumPy is a wp.array(...) / .numpy() pair away, and
od.mesh.Trimesh.from_warp_mesh / mesh.warp_mesh bridge to Warp's own wp.Mesh BVH for ray
and proximity queries. For a pipeline that starts from a realistically messy input — a hole to
close, stray debris to drop — see the
one-call watertight solid example.
What's inside
| Area | Modules | Highlights |
|---|---|---|
| Primitives | creation |
Boxes, spheres, platonic solids, capsules, tori; extrusion, revolution, sweeps, 2D polygon triangulation |
| Structure & topology | mesh, vertices, edges, triangles, halfedge, adjacency, boundary, selection, validation, homology, tangent_space |
Edge/face adjacency, half-edge structure, boundary loops, manifold/watertight/orientability predicates, submesh selection, homology generators, tangent frames |
| Measures & shape descriptors | measures, curvature, bounds, visibility |
Volume, centroid, and inertia integrals; discrete mean/Gaussian curvature and principal directions; axis-aligned and oriented bounding boxes; ambient occlusion, shape diameter, thickness |
| Editing & repair | transform, repair, holes, combine, remesh, smoothing, seams, levelset |
Rigid transforms, hole filling, winding repair, isotropic remeshing, quadric and clustering decimation, Loop and midpoint subdivision, Laplacian/Taubin smoothing, seam cutting, level-set offsets and marching cubes |
| Spatial queries | proximity, ray, neighbors, intersection, metrics |
Closest point, signed distance, winding number, ray casting, BVH and hash-grid neighbor queries, triangle-triangle intersection, chamfer and Hausdorff distance (differentiable via wp.Tape) |
| Point clouds, voxels & reconstruction | points, sample, voxels, reconstruction, registration |
Poisson-disk and blue-noise sampling, farthest-point and voxel down-sampling, screened Poisson reconstruction, ball pivoting, marching cubes, Delaunay triangulation, Procrustes and ICP (point-to-point, point-to-plane) |
| Operators & solvers | laplacian, energies, linalg, interpolation, parametrization |
Cotangent Laplacian, mass matrices, discrete energies, sparse conjugate-gradient solvers (Jacobi and multigrid-preconditioned), harmonic, LSCM, and ARAP parametrization |
| Geodesics & heat methods | geodesic_walk, heat |
Straightest-geodesic walks (exponential map), heat-method geodesic distance, vector heat / parallel transport / log maps, signed heat method |
| Curves | polyline |
Polyline resampling, simplification, and measures |
| Attributes & I/O | texture, io |
Per-vertex/face attribute handling, meshio-backed mesh loading |
| Arrays & infrastructure | array, reduce, grouping, graph, typing, constants |
GPU sort/scan/unique/group primitives, reductions, graph algorithms (connected components, shortest paths, cycles), typed array aliases |
50 public modules in total — the full API reference, generated per module, lives at https://lucagrementieri.github.io/ordito/.
Design
- Arrays in, arrays out. The core API is free functions over
wp.arraybuffers — no mandatory mesh object, no hidden state. Faces are a flatint32index buffer, vertices awp.vec3array, the same convention everywhere. - The device follows the data. Every kernel launch and allocation inherits the device of its inputs; there are no global device switches.
- Host syncs are budgeted. Wrappers avoid device-to-host readbacks, and where one is unavoidable the reason is documented; bounds a caller already knows can be passed in to skip the inference.
- Measured, not assumed. Every public module has both a test file and a benchmark file; performance work lands only with a before/after measurement, and correctness is asserted on values, never just shapes.
Status
ordito is pre-1.0 (0.x): the test suite is extensive (thousands of tests per device, an
eleven-library parity gate with no uncovered pair) and the library is safe to build on, but a
public signature may still shift a positional argument to a keyword or gain a required parameter
between minor versions until 1.0. Released versions are recorded in
CHANGELOG.md.
Development
git clone https://github.com/lucagrementieri/ordito
cd ordito
uv sync --all-groups # runtime + dev + test + docs + bench dependencies
uv run pytest # regression tests against the reference libraries
uv run ruff format ordito tests && uv run ruff check ordito tests
uv run basedpyright # type checking (0 errors expected)
uv run zensical serve # preview the docs locally
uv run pytest --device=cpu -n 4 --cov=ordito # coverage, the way CI measures it
The coverage badge measures the Python wrapper layer on the CPU backend, which is what CI can
run, and is refreshed by the main build. It deliberately excludes ordito/kernels/: a
@wp.kernel body is compiled from its AST and executed on the device, never called as Python, so
coverage.py reports every line of a constantly-running kernel as unexecuted. Device-side behaviour
is covered instead by running the suite on both backends (uv run python -m tests.devices), which
is a two-process job and needs a GPU.
The test environment installs the reference stack (trimesh, libigl, Open3D, potpourri3d,
PyMeshLab, PyVista, MeshLib, PyMeshFix, PyTorch3D, SciPy, and more) so the comparison suite runs
in full.
Benchmarks live in benchmarks/ and use pytest-benchmark; PyTorch3D is the one reference with
CUDA kernels of its own, so it is also the suite's only GPU-against-GPU comparison. To reproduce
them, follow benchmarks/README.md § Reproduce: a two-step install,
then uv run pytest benchmarks/. The scan meshes are downloaded on first use from the
meshes-v1 release and checked
against pinned SHA-256 hashes.
Bug reports, reproductions and pull requests are welcome — see CONTRIBUTING.md for the development loop, the bar a pull request has to clear, and where the internal engineering reference lives.
Links
- Documentation: https://lucagrementieri.github.io/ordito/
- Source: https://github.com/lucagrementieri/ordito
- Issues: https://github.com/lucagrementieri/ordito/issues
- NVIDIA Warp: https://nvidia.github.io/warp/
Citation
If ordito is useful in your research, please cite it:
@software{grementieri_ordito,
author = {Grementieri, Luca},
title = {{ordito}: GPU-accelerated triangular mesh processing on NVIDIA Warp},
year = {2026},
url = {https://github.com/lucagrementieri/ordito},
version = {0.1.0}
}
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in ordito by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Metadata
Release files for ordito 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ordito-0.1.0.tar.gz | 2.8 MB | With provenance | Details for ordito-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ordito-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for ordito-0.1.0-py3-none-any.whl |
Total release size: 4.7 MB
Release files / ordito-0.1.0.tar.gz
| Download URL | ordito-0.1.0.tar.gz |
|---|---|
| Size | 2.8 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1b2a7bc5688d260042c3339993d826d71b6a5412d00ff9b9e27204a22b27f464
|
|
BLAKE2b-256 checksum How to use checksums |
3201c5b685076d165ad73d7b4b0fbb8e2b09dd0e925fe5777c01c242c7a129be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / ordito-0.1.0-py3-none-any.whl
| Download URL | ordito-0.1.0-py3-none-any.whl |
|---|---|
| Size | 1.9 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7a2aee63da46f6509b9f0187a50e682530766004262a67634c294379f544a11a
|
|
BLAKE2b-256 checksum How to use checksums |
9945131d9ae440e2b4a7517238ce603083e76b372547f9313a7fd6428a05fc54
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logSecurity for ordito 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ordito-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.