Filter Mesh Using Quadric Decimation
SUMMARY
Filter Mesh Using Quadric Decimation simplifies a datatypes.Mesh3D to at most a target number of triangles.
It repeatedly collapses the edge whose removal least changes the surface (quadric error metric decimation), then removes degenerate and duplicated triangles and unused vertices. The overall shape and bounds are preserved closely, so the result is a lighter stand-in for the original mesh. This Skill operates on a datatypes.Mesh3D, not a datatypes.PointCloud.
Use this Skill when a dense CAD or scanned mesh is too heavy for pose estimation, collision checking, or visualization and you need the same shape with far fewer triangles.
The Skill
from telekinesis import vitreous
simplified_mesh = vitreous.filter_mesh_using_quadric_decimation(
mesh=mesh,
target_number_of_triangles=5000,
)Data Transfer Notice
There is no longer a fixed limit of 1 million points per request. However, very large datasets may result in slower data transfer and processing times. We are continuously optimizing performance as part of our beta program, with ongoing improvements to enhance speed and reliability.
The Code
"""
Demonstrates simplifying a dense mesh to a target triangle count while preserving its shape.
"""
from loguru import logger
import rerun as rr
from telekinesis import vitreous, datatypes
def filter_mesh_using_quadric_decimation_example():
"""
Simplifies a mesh using quadric error metric decimation.
Collapses the edges whose removal least changes the surface until the mesh
has at most the target number of triangles, producing a lighter mesh with
the same overall shape.
"""
# ===================== Load Data ==========================================
mesh_url = "https://assets.telekinesis.ai/examples/v1/meshes/beer_can.glb"
mesh = datatypes.Mesh3D.from_url(url=mesh_url, use_cache=True)
# ===================== Run Skill ==========================================
simplified_mesh = vitreous.filter_mesh_using_quadric_decimation(
mesh=mesh,
target_number_of_triangles=5000,
)
# ===================== Log ================================================
logger.success(f"Simplified {mesh} using quadric decimation")
logger.success(f"Results: {simplified_mesh}")
logger.info(
f"Triangles: {len(mesh.triangle_indices)} -> "
f"{len(simplified_mesh.triangle_indices)}, vertices: "
f"{len(mesh.vertex_positions)} -> {len(simplified_mesh.vertex_positions)}"
)
# ===================== Visualization (Optional) ===========================
rr.init("filter_mesh_using_quadric_decimation_example", spawn=True)
datatypes.visualize(mesh, entity_path="/1-original_mesh")
datatypes.visualize(simplified_mesh, entity_path="/2-simplified_mesh")
if __name__ == "__main__":
filter_mesh_using_quadric_decimation_example()Runnable examples are available in the Telekinesis examples repository.
Follow the README in that repository to set up the environment, run this specific example with:
cd telekinesis-examples
python examples/point_cloud/filter_mesh_using_quadric_decimation.pyParameter Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
mesh | datatypes.Mesh3D | required | The mesh to simplify. Must contain triangles. Not a datatypes.PointCloud |
target_number_of_triangles | datatypes.Int | int | required | The maximum number of triangles in the simplified mesh. Must be > 0. A mesh that already has this many triangles or fewer is returned unchanged |
Returns
| Type | Description |
|---|---|
datatypes.Mesh3D | The simplified mesh, with at most target_number_of_triangles triangles. Use len(mesh.triangle_indices) for the triangle count and len(mesh.vertex_positions) for the vertex count. Vertex normals present on the input are recomputed for the simplified surface. |
Raises
| Exception | Condition |
|---|---|
TypeError | A parameter's value does not match its expected type (see the Parameter Configuration table above) |
ValueError | target_number_of_triangles is not positive (must be > 0) |
ConfigurationError | The TELEKINESIS_API_KEY environment variable is not set |
SerializationError | The request input failed to serialize, the response was not returned as an Arrow stream, or the response failed to deserialize |
RequestTimeoutError | The request to the Vitreous service timed out |
TransportError | A network failure occurred before a response was received |
ClientError | The Vitreous service rejected the request due to invalid or malformed input, such as a mesh without triangles (HTTP 400/422), an unrecognized endpoint (HTTP 404), or another unexpected 4xx response |
AuthenticationError | The API key was rejected as invalid or expired (HTTP 401) |
AuthenticationServiceError | The authentication service returned an invalid response, was temporarily unavailable, or timed out (HTTP 502/503/504) |
ServerError | The Vitreous service returned a 5xx or otherwise unexpected error response |
How to Tune the Parameters
filter_mesh_using_quadric_decimation exposes one parameter.
target_number_of_triangles
- Controls: The size of the simplified mesh — the result has at most this many triangles.
- Must be
> 0— zero or a negative value raises aValueError - Increase → keeps more detail, at the cost of a heavier mesh
- Decrease → a lighter, faster mesh; very low targets round off small features such as edges, threads, and holes
- Typical range: 5,000–50,000 for pose estimation and collision checking of a single part; 1,000–5,000 for coarse visualization or proxies
TIP
Best practice: Pick the lowest target at which the features your downstream Skill relies on (edges for pose estimation, contact surfaces for grasping) are still visible. Compare the original and simplified meshes in Rerun before fixing the value.
Where to Use the Skill
Common pipelines include:
- Pose estimation preprocessing – Simplifying a dense CAD model before
estimate_pose_using_foundation_poseto reduce rendering cost per hypothesis - Collision geometry – Producing a lighter mesh for planning-scene collision checks
- Visualization – Keeping large scanned or CAD meshes responsive in viewers
- Data transfer – Reducing payload size before sending a mesh to other Skills
Alternative Skills
| Skill | Comparison with Filter Mesh Using Quadric Decimation |
|---|---|
| reconstruct_mesh_using_convex_hull | Produces a much coarser convex envelope and loses all concave features. Use it only when a convex bound is enough. |
| convert_mesh_to_point_cloud | Use it when the downstream Skill needs points rather than a lighter mesh. |
When Not to Use the Skill
Do not use Filter Mesh Using Quadric Decimation when:
- The input is a point cloud – this Skill requires a
datatypes.Mesh3D; reconstruct a mesh first, or use a point-cloud downsampling Skill such asfilter_point_cloud_using_voxel_downsampling - Exact geometry is required – decimation approximates the surface; keep the original mesh for metrology or tight-tolerance inspection
- Fine features matter at a low target – thin walls, small holes, and sharp edges are the first details to be lost