warp.geometry.sparse_marching_cubes_from_cells#
- warp.geometry.sparse_marching_cubes_from_cells(
- cells,
- corner_values,
- origin=(0.0, 0.0, 0.0),
- cell_width=1.0,
- threshold=0.0,
- device=None,
Extract an isosurface from an explicit set of occupied cells and corner values.
This is the sparse marching cubes core: it runs marching cubes on a caller-provided list of voxels (rather than cells discovered by a Lipschitz octree), sharing vertices between adjacent cells so the output is watertight. It is useful when the occupied cells are already known, such as a marked band of voxels around an object from a vision or generative model, and the implicit field has already been sampled at their corners.
cellsare expected to be unique (duplicate cells may result in duplicate/intersecting output mesh faces).lipschitz_octree()returns cell subscripts in this function’s convention, but not sampled corner values, which the caller must supply.This function supports backward-mode automatic differentiation: if
corner_valueshasrequires_grad=Trueand the call is wrapped in awarp.Tape(), gradient flows from the outputvertsback tocorner_valuesthrough the marching-cubes vertex interpolation. When a corner is shared by several cells,corner_valuesis expected to agree at that corner (see above); gradient flows back through exactly one of the agreeing entries (a fixed, deterministic choice, not an arbitrary one), which is the correct behavior when the redundant entries are independent evaluations of the same underlying point function.cells(and any cell-selection step that produced them, such aslipschitz_octree()) is not differentiated – it is integer subscript data with no gradient to carry.Note
The subscript convention here differs from the VDB-style one used by
warp.Volume, so subscripts are not interchangeable between the two. Inwarp.Volume, a subscript names a voxel and the sample lives at that voxel’s center, so voxel(i, j, k)covers[ijk - 1/2, ijk + 1/2]in index space. Here a subscript names a cell by its minimum corner, so cell(i, j, k)covers[ijk, ijk + 1]and the samples live at its 8 corners.Both place samples on the integer lattice, so what shifts by half a cell is the region a subscript refers to, not the data. Concretely, a
warp.Volumevoxel subscript corresponds to a corner subscript here rather than a cell subscript: the corners of cell(i, j, k)are the volume voxels(i, j, k)through(i + 1, j + 1, k + 1).originmatchesmin_worldinwarp.Volume.load_from_numpy()andcell_widthmatchesvoxel_size, since both give the world position of subscript(0, 0, 0)and the lattice spacing.- Parameters:
cells (array | ArrayLike) – An
(N, 3)array of integer cell minimum-corner subscripts, as awarp.array[warp.vec3i], awarp.array[warp.int32]of shape(N, 3), or any array-like convertible to one. A cell at subscript(i, j, k)occupies the box with minimum cornerorigin + cell_width * (i, j, k). Subscripts may be negative and need not be contiguous. Awarp.arrayalready ondeviceis consumed in place, without a host round trip.corner_values (array | ArrayLike) – An
(N, 8)array of the field value at each cell’s 8 corners, ordered bywarp.geometry.IsoSurfaceMarchingCubes.CUBE_CORNER_OFFSETS(cornercis at subscript(i, j, k) + CUBE_CORNER_OFFSETS[c]). Values at corners shared between cells are expected to agree.origin (vec3f | tuple[float, float, float]) – The world-space position of cell subscript
(0, 0, 0).cell_width (float) – The side length of a cell.
threshold (float) – The isovalue defining the surface.
device (Device | str | None) – The Warp device to run on. Defaults to the current device.
- Returns:
A tuple
(vertices, indices)as insparse_marching_cubes().- Raises:
ValueError – If
cell_widthis not positive, the shapes ofcellsandcorner_valuesare inconsistent, or the subscript range is too large to pack into 64-bit corner codes.- Return type: