FlexiCubes allows for gradient-based mesh optimization by representing a surface as the isosurface of a scalar field (SDF). This enables direct evaluation of objectives on the extracted surface while allowing for topological flexibility.
To optimize a mesh, you typically parameterize and optimize the following components:
- SDF (
sdf): The scalar field defining the surface. - Weights (
weight): Per-cube learnable weights (e.g., $\beta$, $\alpha$, $\gamma$) that control the local geometry. - Deformations (
deform): A displacement field applied to the voxel grid vertices.
In a typical optimization loop, you sample camera poses, render the current FlexiCubes mesh, compute reconstruction losses (like mask and depth loss) and regularization losses, and then backpropagate the total loss to update the parameters.
# Typical optimization loop structure
for it in tqdm.tqdm(range(iter)):
optimizer.zero_grad()
# 1. Sample cameras
cameras = render.get_random_camera_batch(batch, iter_res=train_res, device=device)
# 2. Extract mesh (use training=True during optimization)
grid_verts = x_nx3 + (2-1e-8) / (voxel_grid_res * 2) * torch.tanh(deform)
vertices, faces, L_dev = fc(
grid_verts, sdf, cube_fx8, voxel_grid_res,
beta=weight[:,:12], alpha=weight[:,12:20], gamma_f=weight[:,20],
training=True
)
flexicubes_mesh = kal.rep.SurfaceMesh(vertices=vertices, faces=faces)
# 3. Render and compute losses
buffers = render.render_mesh(flexicubes_mesh, cameras, train_res)
mask_loss = (buffers['mask'] - target['mask']).abs().mean()
# ... compute other losses ...
total_loss.backward()
optimizer.step()