Skip to content

Convert Mesh to Point Cloud

SUMMARY

Convert Mesh to Point Cloud samples a triangle mesh's surface into a point cloud.

It converts a datatypes.Mesh3D (vertices + triangles) into a datatypes.PointCloud by sampling points across the mesh's surface — the reverse of reconstruct_mesh_using_convex_hull/reconstruct_mesh_using_poisson. This is useful for turning a CAD or parametric model (e.g. from create_cylinder_mesh, create_sphere_mesh, create_torus_mesh, create_plane_mesh) into a synthetic point cloud for testing point-cloud Skills, or for resampling a scanned mesh at a controlled point density.

Use this Skill when you want to turn a mesh model into a point cloud at a controlled density, for example to prepare a CAD model for 6D pose estimation or registration against real sensor data.

The Skill

python
from telekinesis import vitreous

point_cloud = vitreous.convert_mesh_to_point_cloud(
    mesh=mesh,
    num_points=10000,
    sampling_method="poisson_disk",
    initial_sampling_factor=5,
    initial_point_cloud=None,
    use_triangle_normal=False,
)
API Reference
Full parameter and return type documentation for convert_mesh_to_point_cloud.
View Reference →

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.

Example

Input Mesh

Output Point Cloud

Parameters: num_points=10000, sampling_method="poisson_disk", initial_sampling_factor=5, initial_point_cloud=None, use_triangle_normal=False.

The Code

python
"""
Demonstrates sampling a mesh's surface into a 3D point cloud.
"""

import numpy as np
from loguru import logger
import rerun as rr

from telekinesis import vitreous, datatypes


def convert_mesh_to_point_cloud_example():
    """
    Samples a mesh's surface into a point cloud.

    Converts a mesh into a point cloud by sampling points across its surface,
    using Poisson-disk sampling for even ("blue noise") coverage.
    """
    # ===================== Load Data ==========================================
    cylinder_mesh = vitreous.create_cylinder_mesh(
        radius=0.01,
        height=0.02,
        radial_resolution=20,
        height_resolution=4,
        retain_base=False,
        vertex_tolerance=1e-6,
        transformation_matrix=np.eye(4, dtype=np.float32),
        compute_vertex_normals=True,
    )

    # ===================== Run Skill ==========================================
    point_cloud = vitreous.convert_mesh_to_point_cloud(
        mesh=cylinder_mesh,
        num_points=10000,
        sampling_method="poisson_disk",
        initial_sampling_factor=5,
        initial_point_cloud=None,
        use_triangle_normal=False,
    )

    # ===================== Log ================================================
    logger.success(f"Converted {cylinder_mesh} to a point cloud")
    logger.success(f"Results: {point_cloud}")
    logger.info(f"Point cloud has {len(point_cloud.positions)} points")

    # ===================== Visualization  (Optional) ===========================
    rr.init("convert_mesh_to_point_cloud_example", spawn=True)
    datatypes.visualize(cylinder_mesh, entity_path="/1-cylinder_mesh")
    datatypes.visualize(point_cloud, entity_path="/2-sampled_point_cloud")


if __name__ == "__main__":
    convert_mesh_to_point_cloud_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:

bash
cd telekinesis-examples
python examples/point_cloud/convert_mesh_to_point_cloud.py

Parameter Configuration

ParameterTypeDefaultDescription
meshdatatypes.Mesh3DrequiredThe mesh to sample points from. Must not be empty
num_pointsdatatypes.Int | int1000The number of points to sample from the surface. Must be > 0
sampling_methoddatatypes.String | str"uniform"The sampling algorithm: "uniform" or "poisson_disk"
initial_sampling_factordatatypes.Int | int1Only used when sampling_method="poisson_disk": the initial uniform oversample has initial_sampling_factor * num_points points before thinning down to num_points. Must be > 0; the server additionally requires >= 2 when sampling_method="poisson_disk" (the SDK does not enforce this locally, so the default of 1 will be rejected by the server in that mode)
initial_point_clouddatatypes.PointCloud | NoneNoneAn optional existing point cloud to seed "poisson_disk" sampling with, instead of starting from scratch. Not used in "uniform" mode
use_triangle_normaldatatypes.Bool | boolFalseWhether each sampled point's normal is taken from its parent triangle's flat face normal instead of interpolated per-vertex normals

Returns

TypeDescription
datatypes.PointCloudA point cloud with num_points sampled positions (and normals, derived per use_triangle_normal). Use .positions for the (num_points, 3) array, len(...) for the point count, and .has_normals/.normals to check/access the sampled normals. No particular ordering of the sampled points is guaranteed.

Raises

ExceptionCondition
TypeErrorA parameter's value does not match its expected type (see the Parameter Configuration table above)
ValueErrornum_points or initial_sampling_factor is not > 0, or sampling_method is not one of "uniform"/"poisson_disk"
ConfigurationErrorThe TELEKINESIS_API_KEY environment variable is not set
SerializationErrorThe request input failed to serialize, the response was not returned as an Arrow stream, or the response failed to deserialize
RequestTimeoutErrorThe request to the Vitreous service timed out
TransportErrorA network failure occurred before a response was received
ClientErrorThe Vitreous service rejected the request due to invalid or malformed input (HTTP 400/422), an unrecognized endpoint (HTTP 404), or another unexpected 4xx response
AuthenticationErrorThe API key was rejected as invalid or expired (HTTP 401)
AuthenticationServiceErrorThe authentication service returned an invalid response, was temporarily unavailable, or timed out (HTTP 502/503/504)
ServerErrorThe Vitreous service returned a 5xx or otherwise unexpected error response

How to Tune the Parameters

num_points

  • Controls: The number of sampled surface points.
  • Units: Points (count)
  • Default: 1000
  • Increase → denser, more detailed coverage, at the cost of a larger point cloud
  • Decrease → sparser sample, smaller point cloud
  • Typical range: 1,000–20,000+, depending on how much detail downstream Skills need

sampling_method

  • Controls: How points are distributed across the mesh surface.
  • Units: N/A (categorical)
  • Default: "uniform"
    • Options:
      • "uniform" — samples points uniformly at random, weighted by triangle area. Fast, but points can clump or leave small gaps since there's no minimum spacing between them.
      • "poisson_disk" — produces a more evenly-spaced ("blue noise") sample with a minimum distance between points, by drawing an initial uniform oversample (see initial_sampling_factor) and thinning it down to num_points. Slower than "uniform" but gives more visually/statistically even coverage.

initial_sampling_factor

  • Controls: Only used when sampling_method="poisson_disk" — how large the initial uniform oversample is, as a multiple of num_points, before thinning.
  • Units: Dimensionless multiplier
  • Default: 1
  • Increase → gives the Poisson-disk thinning step more candidates to pick from (better final spacing), at the cost of more up-front sampling work
  • Typical range: 2–10 — start at 5

WARNING

The server requires initial_sampling_factor >= 2 when sampling_method="poisson_disk", but this parameter's default is 1. The SDK does not check this locally, so calling with sampling_method="poisson_disk" and the default initial_sampling_factor will fail server-side — always pass initial_sampling_factor=2 or higher when using "poisson_disk".

initial_point_cloud

  • Controls: An optional existing point cloud to seed "poisson_disk" sampling with, e.g. to extend a previous sample with more, evenly-spaced points, instead of starting from scratch.
  • Units: N/A
  • Default: None
  • Use None for a standard, from-scratch mesh-to-point-cloud conversion; provide a seed cloud for incremental refinement or consistency across runs

use_triangle_normal

  • Controls: Whether a sampled point's normal comes from its parent triangle's flat face normal (True) or is interpolated from the mesh's per-vertex normals (False).
  • Units: Boolean flag
  • Default: False
  • Keep False for smoother normals on curved surfaces; set True when you specifically need per-triangle flat-face normals (or the mesh has no per-vertex normals to interpolate)

TIP

Start with sampling_method="uniform" for quick iteration; switch to "poisson_disk" (with initial_sampling_factor around 5) once you need an evenly-spaced sample for registration or pose estimation.

Where to Use the Skill

Common pipelines include:

  • 6D pose estimation and registration – converting a CAD or mesh model into a point cloud so it can be aligned with real sensor data via correspondence-based registration
  • Synthetic test data generation – sampling a parametric mesh from create_cylinder_mesh, create_sphere_mesh, create_torus_mesh, or create_plane_mesh to get a synthetic point cloud for testing other point-cloud Skills
  • Controlled resampling – resampling a scanned or reconstructed mesh at a chosen point density instead of using its raw vertex count

Alternative Skills

Skillvs. Convert Mesh to Point Cloud
reconstruct_mesh_using_poissonGoes the opposite direction: builds a mesh surface from a point cloud instead of sampling a point cloud from a mesh.
reconstruct_mesh_using_convex_hullAlso builds a mesh from a point cloud, using its convex hull, rather than sampling points from an existing mesh.
create_cylinder_meshGenerates a parametric mesh you can feed into this Skill as synthetic test geometry.
convert_depth_image_to_point_cloudAlso produces a datatypes.PointCloud, but back-projects it from a datatypes.DepthImage instead of sampling a mesh's surface.

When Not to Use the Skill

Do not use Convert Mesh to Point Cloud when:

  • You already have a real point cloud - this Skill produces a synthetic sample from a mesh's surface, not a sensor capture
  • You need a mesh from a point cloud - use reconstruct_mesh_using_poisson or reconstruct_mesh_using_convex_hull instead, which go the opposite direction
  • You need the mesh's exact original vertices rather than a resampled surface - sampled points are new positions on the surface, not the mesh's own vertex positions

TIP

If you're building synthetic test data, pair this Skill with a generator like create_cylinder_mesh, create_sphere_mesh, create_torus_mesh, or create_plane_mesh — they produce meshes purpose-built to be sampled into point clouds.