kaolin.ops.conversions

API

kaolin.ops.conversions.sdf_to_voxelgrids(sdf, bbox_center=0.0, bbox_dim=1.0, init_res=32, upsampling_steps=0)

Converts SDFs to voxelgrids.

For each SDF returns a voxel grid with resolution \(init\_res * 2 ^ {upsampling\_steps} + 1\) (so the underlying voxel resolution is \(init\_res * 2 ^ {upsampling\_steps}\)) where each grid point holds a binary value determined by the sign of the SDF at the location of the grid point after normalizing the voxel grid to the bounding box defined by bbox_center and bbox_dim.

This solution is largely borrowed from “Multiresolution IsoSurface Extraction (MISE)” proposed in the CVPR 2019 paper “Occupancy Networks: Learning 3D Reconstruction in Function Space”: https://arxiv.org/abs/1906.02739. Instead of evaluating SDF values of all grid points at high resolution, this function incrementally builds an octree and only evaluate dense grid points around the surface.

Parameters:
  • sdf (list[callable]) – a list of callable that takes in an Nx3 tensor of N 3D coordinates and outputs the N corresponding SDF values
  • bbox_center (float) – center of the surface’s bounding box.
  • bbox_dim (float) – largest dimension of the surface’s bounding box.
  • init_res (int) – the initial resolution of the voxel, should be large enough to properly define the surface.
  • upsampling_steps (int) – Number of times the initial resolution will be doubled.
Returns:

Binary voxelgrids of shape \((batch\_size, init\_res * 2 ^ {upsampling\_steps} + 1)\)

Return type:

(torch.Tensor)

Example

>>> def sphere(points):
...     return torch.sum(points ** 2, 1) ** 0.5 - 0.5
>>> sdf_to_voxelgrids([sphere], init_res=4)
tensor([[[[0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 1., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.]],
<BLANKLINE>
         [[0., 0., 0., 0., 0.],
          [0., 1., 1., 1., 0.],
          [0., 1., 1., 1., 0.],
          [0., 1., 1., 1., 0.],
          [0., 0., 0., 0., 0.]],
<BLANKLINE>
         [[0., 0., 1., 0., 0.],
          [0., 1., 1., 1., 0.],
          [1., 1., 1., 1., 1.],
          [0., 1., 1., 1., 0.],
          [0., 0., 1., 0., 0.]],
<BLANKLINE>
         [[0., 0., 0., 0., 0.],
          [0., 1., 1., 1., 0.],
          [0., 1., 1., 1., 0.],
          [0., 1., 1., 1., 0.],
          [0., 0., 0., 0., 0.]],
<BLANKLINE>
         [[0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 1., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.]]]])
kaolin.ops.conversions.trianglemeshes_to_voxelgrids(vertices, faces, resolution, origin=None, scale=None)

Converts meshes to surface voxelgrids of a given resolution. It first upsamples triangle mesh’s vertices to given resolution, then it performs a box test. If a voxel contains a triangle vertex, set that voxel to 1. Vertex will be offset and scaled as following: \(\text{normalized_vertices} = (\text{vertices} - \text{origin}) / \text{scale}\) the voxelgrids will only be generated in the range [0, 1] of normalized_vertices.

Parameters:
  • vertices (torch.tensor) – batched vertices of shape (B, V, 3) of mesh to convert.
  • faces (torch.tensor) – unbatched faces of shape (F, 3) of mesh to convert.
  • resolution (int) – desired resolution of generated voxelgrid.
  • origin (torch.tensor) – origin of the voxelgrid in the mesh coordinates. It has shape \((\text{batch_size}, 3)\). Default: origin = torch.min(vertices, dim=1)[0]
  • scale (torch.tensor) – the scale by which we divide the vertex position. It has shape \((\text{batch_size})\). Default: scale = torch.max(torch.max(vertices, dim=1)[0] - origin, dim=1)[0]
Returns:

Binary batched voxelgrids of shape (B, resolution, resolution, resolution).

Return type:

(torch.Tensor)

Example

>>> vertices = torch.tensor([[[0, 0, 0],
...                           [1, 0, 0],
...                           [0, 0, 1]]], dtype=torch.float)
>>> faces = torch.tensor([[0, 1, 2]], dtype=torch.long)
>>> origin = torch.zeros((1, 3))
>>> scale = torch.ones((1))
>>> trianglemeshes_to_voxelgrids(vertices, faces, 3, origin, scale)
tensor([[[[1., 1., 1.],
          [0., 0., 0.],
          [0., 0., 0.]],
<BLANKLINE>
         [[1., 1., 0.],
          [0., 0., 0.],
          [0., 0., 0.]],
<BLANKLINE>
         [[1., 0., 0.],
          [0., 0., 0.],
          [0., 0., 0.]]]])
kaolin.ops.conversions.voxelgrids_to_cubic_meshes(voxelgrids, is_trimesh=True)

Convert voxelgrids to meshes by replacing each occupied voxel with a cuboid mesh (unit cube).

Each cube has 8 vertices and 6 (for quadmesh) or 12 faces (for triangular mesh). Internal faces are ignored. If is_trimesh==True, this function performs the same operation as “Cubify” defined in the ICCV 2019 paper “Mesh R-CNN”: https://arxiv.org/abs/1906.02739.

Parameters:
  • voxelgrids (torch.Tensor) – binary voxel array with shape (B, X, Y, Z).
  • is_trimesh (bool) – the outputs are triangular meshes if True. Otherwise quadmeshes are returned.
Returns:

tuple containing the list of vertices and the list of faces for each mesh.

Return type:

(list[torch.Tensor], list[torch.LongTensor])

Example

>>> voxelgrids = torch.ones((1, 1, 1, 1))
>>> verts, faces = voxelgrids_to_cubic_meshes(voxelgrids)
>>> verts[0]
tensor([[0., 0., 0.],
        [0., 0., 1.],
        [0., 1., 0.],
        [0., 1., 1.],
        [1., 0., 0.],
        [1., 0., 1.],
        [1., 1., 0.],
        [1., 1., 1.]])
>>> faces[0]
tensor([[0, 1, 2],
        [5, 4, 7],
        [0, 4, 1],
        [6, 2, 7],
        [0, 2, 4],
        [3, 1, 7],
        [3, 2, 1],
        [6, 7, 4],
        [5, 1, 4],
        [3, 7, 2],
        [6, 4, 2],
        [5, 7, 1]])
kaolin.ops.conversions.voxelgrids_to_trianglemeshes(voxelgrids, iso_value=0.5)

Converts voxelgrids to triangle meshes using marching cube algorithm. Please refer to: Lorensen, William E.; Cline, Harvey E. in Marching cubes, A high resolution 3D surface construction algorithm

Parameters:
  • voxelgrids (torch.Tensor) – Exact batched voxel array with shape \((\text{batch_size}, \text{dim}, \text{dim}, \text{dim})\).
  • iso_value (float) – Value in the range [0, 1] used to determine whether a voxel is inside the surface or not. Isovalue is also used to interpolate newly created triangle vertices. Defaults to 0.5
Returns:

List of vertices and faces tensors of the converted triangle mesh, corresponds to each voxelgrid.

Return type:

(List of torch.FloatTensor, List of torch.LongTensor)

Example

>>> voxelgrid = torch.tensor([[[[1, 0],
...                             [0, 0]],
...                            [[0, 0],
...                             [0, 0]]]], device='cuda', dtype=torch.uint8)
>>> vertices, faces = voxelgrids_to_trianglemeshes(voxelgrid)
>>> vertices[0]
tensor([[0.5000, 1.0000, 1.0000],
        [1.0000, 0.5000, 1.0000],
        [1.0000, 1.0000, 0.5000],
        [1.5000, 1.0000, 1.0000],
        [1.0000, 1.5000, 1.0000],
        [1.0000, 1.0000, 1.5000]], device='cuda:0')
>>> faces[0]
tensor([[2, 1, 0],
        [1, 2, 3],
        [2, 0, 4],
        [3, 2, 4],
        [1, 5, 0],
        [1, 3, 5],
        [0, 5, 4],
        [3, 4, 5]], device='cuda:0')