mlx3d.ops¶
mlx3d.ops
¶
decimate_mesh(meshes, voxel_size)
¶
Simplify a mesh by vertex clustering on a regular voxel grid.
Vertices in the same voxel_size cell collapse to their centroid; faces
are remapped and degenerate ones (with a repeated vertex) dropped. Fast and
robust — coarser than quadric-error decimation, but topology-agnostic.
Returns a new single-mesh :class:~mlx3d.structures.Meshes.
Source code in src/mlx3d/ops/geometry.py
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | |
estimate_point_normals(points, k=16, orient_towards=None)
¶
Estimate per-point normals by PCA over each point's k nearest neighbors.
The normal is the eigenvector of the local covariance with the smallest
eigenvalue. Normal orientation is inherently ambiguous; pass
orient_towards (e.g. the camera position) to flip normals consistently
toward that point.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
array
|
|
required |
k
|
int
|
neighborhood size. |
16
|
orient_towards
|
tuple[float, float, float] | array | None
|
optional |
None
|
Returns:
| Type | Description |
|---|---|
array
|
|
Source code in src/mlx3d/ops/geometry.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | |
icp(source, target, iters=20, tol=1e-06)
¶
Rigidly align source to target with Iterative Closest Point.
Each iteration matches every source point to its nearest target point and
solves for the best rigid transform (Kabsch/SVD), accumulating the total
R/t such that aligned = source @ R.T + t.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
array
|
|
required |
target
|
array
|
|
required |
iters
|
int
|
maximum iterations. |
20
|
tol
|
float
|
stop when the mean matched-distance improves by less than this. |
1e-06
|
Returns:
| Type | Description |
|---|---|
dict[str, array]
|
dict with |
dict[str, array]
|
|
Source code in src/mlx3d/ops/geometry.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | |
poisson_reconstruction(points, normals, resolution=64, padding=0.1)
¶
Reconstruct a watertight surface mesh from oriented points (Poisson).
Solves the Poisson equation on a regular grid: the oriented points define a
vector field whose divergence drives an indicator function chi (via an
FFT Poisson solve), then the surface is extracted with marching cubes at the
iso-level passing through the input points. This is the regular-grid form of
Screened Poisson Surface Reconstruction (Kazhdan et al.) -- the same physics
without an octree.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
array
|
|
required |
normals
|
array
|
|
required |
resolution
|
int
|
grid cells per axis. |
64
|
padding
|
float
|
fractional padding added around the point bounding box. |
0.1
|
Returns:
| Type | Description |
|---|---|
Meshes
|
A single-mesh :class: |
Source code in src/mlx3d/ops/geometry.py
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | |
knn_gather(x, idx)
¶
Gather neighbor features: x (N, P2, C), idx (N, P1, K) -> (N, P1, K, C).
Source code in src/mlx3d/ops/knn.py
180 181 182 183 184 185 186 | |
knn_points(p1, p2, K=1, chunk_size=4096)
¶
For each point in p1 find its K nearest neighbors in p2.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p1
|
array
|
(N, P1, D) or (P1, D) query points. |
required |
p2
|
array
|
(N, P2, D) or (P2, D) reference points. |
required |
K
|
int
|
number of neighbors. |
1
|
chunk_size
|
int
|
queries processed per tile to bound the (P1, P2) distance matrix memory. |
4096
|
Returns:
| Type | Description |
|---|---|
array
|
|
array
|
into |
Source code in src/mlx3d/ops/knn.py
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
ray_mesh_intersect(meshes, origins, directions, face_chunk_size=4096, eps=1e-08, aabb_cull=True, spatial_sort=False, return_stats=False)
¶
Nearest ray-triangle hit per ray (Möller-Trumbore).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
meshes
|
Meshes
|
a single-mesh :class: |
required |
origins
|
array
|
|
required |
directions
|
array
|
|
required |
face_chunk_size
|
int
|
faces per chunk, bounding the |
4096
|
eps
|
float
|
parallel / degenerate-triangle tolerance. |
1e-08
|
aabb_cull
|
bool
|
if |
True
|
spatial_sort
|
bool
|
sort faces by Morton code before chunking. This one-time
CPU preprocessing step is useful for arbitrary face orderings and
maps returned |
False
|
return_stats
|
bool
|
include simple broad-phase counters useful for tests and profiling. |
False
|
Returns:
| Type | Description |
|---|---|
dict[str, object]
|
dict with |
dict[str, object]
|
miss), |
dict[str, object]
|
barycentric coords, and |
dict[str, object]
|
hit position is differentiable w.r.t. the mesh vertices. |
Source code in src/mlx3d/ops/ray_mesh.py
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | |
spatially_sort_faces(meshes)
¶
Return a copy with faces sorted by Morton code of their centroids.
Spatial ordering makes adjacent face chunks geometrically coherent, which
improves the effectiveness of chunk-level AABB culling in
:func:ray_mesh_intersect. The second return value maps sorted face rows
back to original packed face indices.
Source code in src/mlx3d/ops/ray_mesh.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | |
sample_points_from_meshes(meshes, num_samples=10000, return_normals=False)
¶
Uniformly sample points from mesh surfaces (area-weighted).
Sampling locations are differentiable with respect to vertex positions (the face choice and barycentric coordinates are treated as constants, as in PyTorch3D).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
meshes
|
Meshes
|
a :class: |
required |
num_samples
|
int
|
points per mesh. |
10000
|
return_normals
|
bool
|
also return the face normal at each sample. |
False
|
Returns:
| Type | Description |
|---|---|
array | tuple[array, array]
|
An (N, num_samples, 3) array of samples, plus an (N, num_samples, 3) |
array | tuple[array, array]
|
array of normals if |
Source code in src/mlx3d/ops/sample_points.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
sample_sdf_grid(sdf_fn, resolution=64, bounds=1.5)
¶
Evaluate an SDF on a regular grid, ready for :func:marching_cubes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sdf_fn
|
Callable[[array], array]
|
callable mapping |
required |
resolution
|
int
|
number of grid samples per axis. |
64
|
bounds
|
float | tuple[float, float] | tuple[tuple[float, float], ...]
|
sampling extent. A scalar |
1.5
|
Returns:
| Type | Description |
|---|---|
array
|
|
tuple[float, float, float]
|
of signed distances indexed |
tuple[float, float, float]
|
are the voxel size and grid origin to pass straight to |
tuple[array, tuple[float, float, float], tuple[float, float, float]]
|
func: |
Source code in src/mlx3d/ops/sdf.py
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | |
sdf_box(points, half_extents=(1.0, 1.0, 1.0), center=(0.0, 0.0, 0.0))
¶
Signed distance to an axis-aligned box.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
array
|
|
required |
half_extents
|
tuple[float, float, float] | array
|
|
(1.0, 1.0, 1.0)
|
center
|
tuple[float, float, float] | array
|
|
(0.0, 0.0, 0.0)
|
Returns:
| Type | Description |
|---|---|
array
|
|
Source code in src/mlx3d/ops/sdf.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | |
sdf_difference(distance_a, distance_b)
¶
Subtract shape b from shape a (a minus b).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
distance_a
|
array
|
distances of the shape to keep. |
required |
distance_b
|
array
|
distances of the shape to carve away. |
required |
Returns:
| Type | Description |
|---|---|
array
|
Combined signed distances. |
Source code in src/mlx3d/ops/sdf.py
172 173 174 175 176 177 178 179 180 181 182 | |
sdf_intersection(*distances)
¶
Boolean intersection of shapes: the pointwise maximum of their distances.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*distances
|
array
|
two or more broadcastable distance arrays. |
()
|
Returns:
| Type | Description |
|---|---|
array
|
Combined signed distances. |
Source code in src/mlx3d/ops/sdf.py
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
sdf_plane(points, normal=(0.0, 1.0, 0.0), offset=0.0)
¶
Signed distance to a plane dot(p, n) = offset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
array
|
|
required |
normal
|
tuple[float, float, float] | array
|
plane normal (need not be unit length). |
(0.0, 1.0, 0.0)
|
offset
|
float
|
signed distance of the plane from the origin along |
0.0
|
Returns:
| Type | Description |
|---|---|
array
|
|
Source code in src/mlx3d/ops/sdf.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | |
sdf_smooth_difference(distance_a, distance_b, k=0.1)
¶
Smooth (blended) subtraction of shape b from shape a.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
distance_a
|
array
|
distances of the shape to keep. |
required |
distance_b
|
array
|
distances of the shape to carve away. |
required |
k
|
float
|
blend radius; larger values round the join more. |
0.1
|
Returns:
| Type | Description |
|---|---|
array
|
Combined signed distances. |
Source code in src/mlx3d/ops/sdf.py
215 216 217 218 219 220 221 222 223 224 225 226 | |
sdf_smooth_intersection(distance_a, distance_b, k=0.1)
¶
Smooth (blended) intersection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
distance_a
|
array
|
first shape's distances. |
required |
distance_b
|
array
|
second shape's distances. |
required |
k
|
float
|
blend radius; larger values round the join more. |
0.1
|
Returns:
| Type | Description |
|---|---|
array
|
Combined signed distances. |
Source code in src/mlx3d/ops/sdf.py
201 202 203 204 205 206 207 208 209 210 211 212 | |
sdf_smooth_union(distance_a, distance_b, k=0.1)
¶
Smooth (blended) union, after Inigo Quilez's polynomial smin.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
distance_a
|
array
|
first shape's distances. |
required |
distance_b
|
array
|
second shape's distances. |
required |
k
|
float
|
blend radius; larger values round the join more. As |
0.1
|
Returns:
| Type | Description |
|---|---|
array
|
Combined signed distances. |
Source code in src/mlx3d/ops/sdf.py
185 186 187 188 189 190 191 192 193 194 195 196 197 198 | |
sdf_sphere(points, radius=1.0, center=(0.0, 0.0, 0.0))
¶
Signed distance to a sphere.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
array
|
|
required |
radius
|
float
|
sphere radius. |
1.0
|
center
|
tuple[float, float, float] | array
|
|
(0.0, 0.0, 0.0)
|
Returns:
| Type | Description |
|---|---|
array
|
|
Source code in src/mlx3d/ops/sdf.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
sdf_to_mesh(sdf_fn, resolution=64, bounds=1.5, level=0.0)
¶
Extract a triangle mesh from an SDF callable.
Convenience wrapper that samples sdf_fn on a grid with
:func:sample_sdf_grid and runs :func:marching_cubes at level.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sdf_fn
|
Callable[[array], array]
|
callable mapping |
required |
resolution
|
int
|
grid samples per axis. |
64
|
bounds
|
float | tuple[float, float] | tuple[tuple[float, float], ...]
|
sampling extent (see :func: |
1.5
|
level
|
float
|
isovalue to extract ( |
0.0
|
Returns:
| Type | Description |
|---|---|
Meshes
|
A single-mesh :class: |
Source code in src/mlx3d/ops/sdf.py
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | |
sdf_torus(points, major_radius=1.0, minor_radius=0.25, center=(0.0, 0.0, 0.0))
¶
Signed distance to a torus lying in the xz-plane (y is the axis).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
array
|
|
required |
major_radius
|
float
|
distance from the center to the tube center. |
1.0
|
minor_radius
|
float
|
tube radius. |
0.25
|
center
|
tuple[float, float, float] | array
|
|
(0.0, 0.0, 0.0)
|
Returns:
| Type | Description |
|---|---|
array
|
|
Source code in src/mlx3d/ops/sdf.py
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | |
sdf_union(*distances)
¶
Boolean union of shapes: the pointwise minimum of their distances.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*distances
|
array
|
two or more broadcastable distance arrays. |
()
|
Returns:
| Type | Description |
|---|---|
array
|
Combined signed distances. |
Source code in src/mlx3d/ops/sdf.py
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
subdivide_meshes(meshes)
¶
Subdivide each triangle into four by inserting edge midpoints.
Each face (v0, v1, v2) becomes four faces using the midpoints of its
three edges; midpoints are shared between adjacent faces (so the result is
watertight where the input was). New vertex positions are the differentiable
averages of their two endpoints, so gradients flow back to the originals.
Operates on a single mesh and returns a new :class:~mlx3d.structures.Meshes.
Source code in src/mlx3d/ops/subdivide.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |