Spaces:
Running on Zero
Running on Zero
| import torch | |
| import o_voxel | |
| import utils | |
| RES = 512 | |
| asset = utils.get_helmet() | |
| # 0. Normalize asset to unit cube | |
| aabb = asset.bounding_box.bounds | |
| center = (aabb[0] + aabb[1]) / 2 | |
| scale = 0.99999 / (aabb[1] - aabb[0]).max() # To avoid numerical issues | |
| asset.apply_translation(-center) | |
| asset.apply_scale(scale) | |
| # 1. Geometry Voxelization (Flexible Dual Grid) | |
| # Returns: occupied indices, dual vertices (QEF solution), and edge intersected | |
| mesh = asset.to_mesh() | |
| vertices = torch.from_numpy(mesh.vertices).float() | |
| faces = torch.from_numpy(mesh.faces).long() | |
| voxel_indices, dual_vertices, intersected = o_voxel.convert.mesh_to_flexible_dual_grid( | |
| vertices, faces, | |
| grid_size=RES, # Resolution | |
| aabb=[[-0.5,-0.5,-0.5],[0.5,0.5,0.5]], # Axis-aligned bounding box | |
| face_weight=1.0, # Face term weight in QEF | |
| boundary_weight=0.2, # Boundary term weight in QEF | |
| regularization_weight=1e-2, # Regularization term weight in QEF | |
| timing=True | |
| ) | |
| ## sort to ensure align between geometry and material voxelization | |
| vid = o_voxel.serialize.encode_seq(voxel_indices) | |
| mapping = torch.argsort(vid) | |
| voxel_indices = voxel_indices[mapping] | |
| dual_vertices = dual_vertices[mapping] | |
| intersected = intersected[mapping] | |
| # 2. Material Voxelization (Volumetric Attributes) | |
| # Returns: dict containing 'base_color', 'metallic', 'roughness', etc. | |
| voxel_indices_mat, attributes = o_voxel.convert.textured_mesh_to_volumetric_attr( | |
| asset, | |
| grid_size=RES, | |
| aabb=[[-0.5,-0.5,-0.5],[0.5,0.5,0.5]], | |
| timing=True | |
| ) | |
| ## sort to ensure align between geometry and material voxelization | |
| vid_mat = o_voxel.serialize.encode_seq(voxel_indices_mat) | |
| mapping_mat = torch.argsort(vid_mat) | |
| attributes = {k: v[mapping_mat] for k, v in attributes.items()} | |
| # Save to compressed .vxz format | |
| ## packing | |
| dual_vertices = dual_vertices * RES - voxel_indices | |
| dual_vertices = (torch.clamp(dual_vertices, 0, 1) * 255).type(torch.uint8) | |
| intersected = (intersected[:, 0:1] + 2 * intersected[:, 1:2] + 4 * intersected[:, 2:3]).type(torch.uint8) | |
| attributes['dual_vertices'] = dual_vertices | |
| attributes['intersected'] = intersected | |
| o_voxel.io.write("ovoxel_helmet.vxz", voxel_indices, attributes) |