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::FloatGrid
inside which has a lot of metadata, and also "background" which is used for non-voxelized space out of scope. Usually we usesimpleVolumeToVdbVolume
this 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: