3D Print Toolbox: Add hollow out #105194

Merged
Mikhail Rachinskiy merged 9 commits from usfreitas/blender-addons:hollow into main 2024-03-18 12:24:30 +01:00
Showing only changes of commit 8fcf96fa09 - Show all commits

View File

@ -853,66 +853,66 @@ class MESH_OT_print3d_hollow(Operator):
import numpy as np import numpy as np
import pyopenvdb as vdb import pyopenvdb as vdb
offset = self.offset if not self.offset:
resolution = self.resolution return {'FINISHED'}
join = self.join
mode_orig = context.mode
MikhailRachinskiy marked this conversation as resolved

It's better to not create unnecessary local variables, especially when they are rarely used.

It's better to not create unnecessary local variables, especially when they are rarely used.
# Target object # Target object
obj = context.active_object obj = context.active_object
m = obj.data # mesh depsgraph = context.evaluated_depsgraph_get()
mesh_target = bpy.data.meshes.new_from_object(obj.evaluated_get(depsgraph))
mesh_target.transform(obj.matrix_world)
# Read mesh to numpy arrays # Read mesh to numpy arrays
nverts = len(m.vertices) nverts = len(mesh_target.vertices)
ntris = len(m.loop_triangles) ntris = len(mesh_target.loop_triangles)
verts = np.zeros(3 * nverts, dtype=np.float32) verts = np.zeros(3 * nverts, dtype=np.float32)
tris = np.zeros(3 * ntris, dtype=np.int32) tris = np.zeros(3 * ntris, dtype=np.int32)
m.vertices.foreach_get('co', verts) mesh_target.vertices.foreach_get('co', verts)
verts.shape = (-1, 3) verts.shape = (-1, 3)
m.loop_triangles.foreach_get('vertices', tris) mesh_target.loop_triangles.foreach_get('vertices', tris)
tris.shape = (-1, 3) tris.shape = (-1, 3)
# Generate VDB levelset # Generate VDB levelset
half_width = max(3.0, math.ceil(abs(offset)/resolution) + 2.0) # half_width has to envelop offset half_width = max(3.0, math.ceil(abs(self.offset) / self.resolution) + 2.0) # half_width has to envelop offset
trans = vdb.Transform() trans = vdb.Transform()
trans.scale(resolution) trans.scale(self.resolution)
levelset = vdb.FloatGrid.createLevelSetFromPolygons(verts, triangles=tris, levelset = vdb.FloatGrid.createLevelSetFromPolygons(verts, triangles=tris, transform=trans, halfWidth=half_width)
transform=trans, halfWidth=half_width)
# Generate offset surface # Generate offset surface
newverts, newquads = levelset.convertToQuads(offset) newverts, newquads = levelset.convertToQuads(self.offset)
polys = [x for x in newquads] polys = list(newquads)
# Instantiate new object in Blender # Instantiate new object in Blender
mesh = bpy.data.meshes.new(m.name + ' offset') mesh_offset = bpy.data.meshes.new(mesh_target.name + ' offset')
mesh.from_pydata(newverts, [], polys) mesh_offset.from_pydata(newverts, [], polys)
newobj = bpy.data.objects.new(obj.name + ' offset', mesh) obj_offset = bpy.data.objects.new(obj.name + ' offset', mesh_offset)
newobj.matrix_world = obj.matrix_world.copy() bpy.context.collection.objects.link(obj_offset)
bpy.context.collection.objects.link(newobj)
if not join: if not self.join:
# For some reason OpenVDB has inverted normals # For some reason OpenVDB has inverted normals
mesh.flip_normals() mesh_offset.flip_normals()
# This mesh will not be used anymore
bpy.data.meshes.remove(mesh_target)
else: else:
if offset < 0.0: # Create a copy of the target object with applied modifiers, scale
obj_hollow = bpy.data.objects.new(obj.name + " hollow", mesh_target)
bpy.context.collection.objects.link(obj_hollow)
if self.offset < 0.0:
# Offset surface already has normals as they should, see above # Offset surface already has normals as they should, see above
pass pass
else: else:
# Offset surface is outside, correct normals, see above # Offset surface is outside, correct normals, see above
mesh.flip_normals() mesh_offset.flip_normals()
# Original surface is inside, flip its normals # Original surface is inside, flip its normals
m.flip_normals() mesh_target.flip_normals()
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_all(action='DESELECT')
newobj.select_set(True) obj_offset.select_set(True)
obj.select_set(True) obj_hollow.select_set(True)
context.view_layer.objects.active = obj context.view_layer.objects.active = obj_hollow
bpy.ops.object.join() bpy.ops.object.join()
if mode_orig == 'EDIT_MESH':
bpy.ops.object.mode_set(mode='EDIT')
return {'FINISHED'} return {'FINISHED'}
@ -921,6 +921,8 @@ class MESH_OT_print3d_hollow(Operator):
self.offset = print_3d.hollow_offset self.offset = print_3d.hollow_offset
self.resolution = print_3d.hollow_resolution self.resolution = print_3d.hollow_resolution
self.join = print_3d.hollow_join self.join = print_3d.hollow_join
if context.mode == 'EDIT_MESH':
bpy.ops.object.mode_set(mode='OBJECT')
return self.execute(context) return self.execute(context)