Roundtrip Mesh2Voxel conversions #4584
-
|
Hi, I'm trying to perform a roundtrip conversion from an ios-mesh to voxels (via a Simple Volume) and back to a ios-mesh. I want to work with a Simple Volume, since this is the only format I can convert to a NumPy array using The issue is that when I:
Any idea what might cause the large surrounding box when using the simple volume in the conversion? Image of the problem: Code to ReproduceMesh: upper.zip import meshlib.mrmeshnumpy as mrn
import meshlib.mrmeshpy as mr
import trimesh
import trimesh.scene
def mr_mesh_to_trimesh(mr_mesh):
mesh = trimesh.Trimesh()
mesh.vertices = mrn.getNumpyVerts(mr_mesh)
mesh.faces = mrn.getNumpyFaces(mr_mesh.topology)
return mesh
voxel_size = (0.2,0.2,0.2)
signed = False
surface_offset = 2
mesh = mr.loadMesh("/app/lower.stl")
params = mr.MeshToVolumeParams()
params.voxelSize = mr.Vector3f(voxel_size[0],voxel_size[1],voxel_size[2])
params.type = mr.MeshToVolumeParams.Type.Signed if signed else mr.MeshToVolumeParams.Type.Unsigned
params.surfaceOffset = surface_offset
#convert to vdb volume and back to mesh
vdb_volume1 = mr.meshToVolume(mr.MeshPart(mesh),params)
settings1 = mr.GridToMeshSettings()
settings1.isoValue = 0.52
settings1.voxelSize = mr.Vector3f(voxel_size[0],voxel_size[1],voxel_size[2])
inferred_mesh = mr.gridToMesh(vdb_volume1.data,settings1)
#convert to vdb volume then to simple volume and back to vdb volume and back to mesh
volume = mr.vdbVolumeToSimpleVolume(vdb_volume1)
vdb_volume = mr.simpleVolumeToVdbVolume(volume)
inferred_mesh2 = mr.gridToMesh(vdb_volume.data,settings1)
#marching cubes on simple volume
marching_cubes_params = mr.MarchingCubesParams()
marching_cubes_params.iso = 0.52
inferred_mesh3 = mr.marchingCubes(volume,marching_cubes_params)
#obj voxels iso surface
mr_vox = mr.ObjectVoxels()
mr_vox.construct(volume)
infered_mesh4 = mr_vox.recalculateIsoSurface(0.52)
mr_vox.setIsoValue(0.52)
infered_mesh5 = mr_vox.surface()
scene = trimesh.Scene([mr_mesh_to_trimesh(mesh),mr_mesh_to_trimesh(inferred_mesh)])
scene.show()
scene = trimesh.Scene([mr_mesh_to_trimesh(mesh),mr_mesh_to_trimesh(inferred_mesh2)])
scene.show()
scene = trimesh.Scene([mr_mesh_to_trimesh(mesh),mr_mesh_to_trimesh(inferred_mesh3)])
scene.show() |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
|
Hello @emil-peters !
VdbVolume stores So you can change simple->vdb conversion like this: def simpleVolumeToVdbDistanceField( volume: mr.SimpleVolumeMinMax ):
vdbVolume = mr.VdbVolume()
vdbVolume.data = mr.simpleVolumeToDenseGrid(volume,volume.max)
vdbVolume.max = volume.max
vdbVolume.min = volume.min
vdbVolume.dims = volume.dims
vdbVolume.voxelSize = volume.voxelSize
return vdbVolume
It happens because Also you can create SimpleVolume directly from mesh using m2dvParams = mr.MeshToDistanceVolumeParams()
m2dvParams.dist.maxDistSq = (voxel_size[0] * 10)**2
m2dvParams.vol.voxelSize = mr.Vector3f(voxel_size[0],voxel_size[1],voxel_size[2])
orgDims = mr.calcOriginAndDimensions(
mesh.computeBoundingBox().expanded(mr.Vector3f.diagonal( voxel_size[0] * 10)),m2dvParams.vol.voxelSize.x)
m2dvParams.vol.origin = orgDims.origin
m2dvParams.vol.dimensions = orgDims.dimensions
m2dvParams.dist.signMode = mr.SignDetectionMode.OpenVDB if signed else mr.SignDetectionMode.Unsigned # you can try different sign detection mode if signed needed
volume = mr.meshToDistanceVolume(mesh,m2dvParams)Please note that in this case result will differ because of difference in calculation distance fields in openvdb and in meshlib ( |
Beta Was this translation helpful? Give feedback.

Hello @emil-peters !
VdbVolume stores
openvdb::FloatGridinside which has a lot of metadata, and also "background" which is used for non-voxelized space out of scope. Usually we usesimpleVolumeToVdbVolumethis function, to convert density volumes to openvdb, and we put simpleVolume.min as background toopenvdb. It is correct for density volume, but for distance fields it should be opposite.So you can change simple->vdb conversion like this: