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 pyopenvdb as vdb
offset = self.offset
resolution = self.resolution
join = self.join
mode_orig = context.mode
if not self.offset:
return {'FINISHED'}
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
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
nverts = len(m.vertices)
ntris = len(m.loop_triangles)
verts = np.zeros(3*nverts, dtype=np.float32)
tris = np.zeros(3*ntris, dtype=np.int32)
m.vertices.foreach_get('co', verts)
nverts = len(mesh_target.vertices)
ntris = len(mesh_target.loop_triangles)
verts = np.zeros(3 * nverts, dtype=np.float32)
tris = np.zeros(3 * ntris, dtype=np.int32)
mesh_target.vertices.foreach_get('co', verts)
verts.shape = (-1, 3)
m.loop_triangles.foreach_get('vertices', tris)
mesh_target.loop_triangles.foreach_get('vertices', tris)
tris.shape = (-1, 3)
# 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.scale(resolution)
levelset = vdb.FloatGrid.createLevelSetFromPolygons(verts, triangles=tris,
transform=trans, halfWidth=half_width)
trans.scale(self.resolution)
levelset = vdb.FloatGrid.createLevelSetFromPolygons(verts, triangles=tris, transform=trans, halfWidth=half_width)
# Generate offset surface
newverts, newquads = levelset.convertToQuads(offset)
polys = [x for x in newquads]
newverts, newquads = levelset.convertToQuads(self.offset)
polys = list(newquads)
# Instantiate new object in Blender
mesh = bpy.data.meshes.new(m.name + ' offset')
mesh.from_pydata(newverts, [], polys)
newobj = bpy.data.objects.new(obj.name + ' offset', mesh)
newobj.matrix_world = obj.matrix_world.copy()
bpy.context.collection.objects.link(newobj)
mesh_offset = bpy.data.meshes.new(mesh_target.name + ' offset')
mesh_offset.from_pydata(newverts, [], polys)
obj_offset = bpy.data.objects.new(obj.name + ' offset', mesh_offset)
bpy.context.collection.objects.link(obj_offset)
if not join:
if not self.join:
# 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:
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
pass
else:
# Offset surface is outside, correct normals, see above
mesh.flip_normals()
mesh_offset.flip_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.select_all(action='DESELECT')
newobj.select_set(True)
obj.select_set(True)
context.view_layer.objects.active = obj
obj_offset.select_set(True)
obj_hollow.select_set(True)
context.view_layer.objects.active = obj_hollow
bpy.ops.object.join()
if mode_orig == 'EDIT_MESH':
bpy.ops.object.mode_set(mode='EDIT')
return {'FINISHED'}
@ -921,6 +921,8 @@ class MESH_OT_print3d_hollow(Operator):
self.offset = print_3d.hollow_offset
self.resolution = print_3d.hollow_resolution
self.join = print_3d.hollow_join
if context.mode == 'EDIT_MESH':
bpy.ops.object.mode_set(mode='OBJECT')
return self.execute(context)