3D Print Toolbox: Add hollow out #105194
@ -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
|
||||
# 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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user
It's better to not create unnecessary local variables, especially when they are rarely used.