def TestFit(tar_object, selFrame, scale_size, move_dy): new_objs = mm.append_objects_from_file(remote, hole_filename) mm.select_objects(remote, new_objs) mm.begin_tool(remote, "transform") mm.set_toolparam(remote, "scale", scale_size) #mm.set_toolparam(remote, "translation", [0,0,0]) mm.accept_tool(remote) (min, max) = mm.get_selected_bounding_box(remote) mm.begin_tool(remote, "transform") cur_origin = mm.get_toolparam(remote, "origin") dy = -((cur_origin[1] - min[1]) + move_dy * 2 / size_x) rotation = mm.make_matrix_from_axes(selFrame.x, mm.negv3(selFrame.z), selFrame.y) mm.set_toolparam(remote, "rotation", rotation) translate = mm.subv3(selFrame.origin, cur_origin) translate = mm.addv3(translate, mm.mulv3s(selFrame.z, dy)) mm.set_toolparam(remote, "translation", translate) mm.accept_tool(remote) mm.select_objects(remote, [tar_object, new_objs[0]]) result = TestIntersection(tar_object, new_objs[0]) mm.select_objects(remote, [new_objs[0]]) delete_select_objects() mm.select_objects(remote, [tar_object]) return not result
def hollow(remote, mesh_object, offset=2, solid_resolution=128, mesh_resolution=128): """ Hollow mesh offsetDistance float offsetDistanceWorld float GUI default: 2 holeRadiusWorld float holeTaperWorld float hollowType integer solidResolution integer GUI default: this depends on the mesh size. Try using 256 as default meshResolution integer GUI default: 128 holesPerComponent integer """ mm.scene.select_objects(remote, mesh_object) mm.begin_tool(remote, 'hollow') mm.set_toolparam(remote, 'offsetDistanceWorld', offset) mm.set_toolparam(remote, 'solidResolution', solid_resolution) # Solid Accuracy mm.set_toolparam(remote, 'meshResolution', mesh_resolution) # Mesh Density mm.tool_utility_command(remote, 'update') mm.accept_tool(remote) return None
def hollow(remote, mesh_object, offset=2, solid_resolution=128, mesh_resolution=128): """ Hollow mesh offsetDistance float offsetDistanceWorld float GUI default: 2 holeRadiusWorld float holeTaperWorld float hollowType integer solidResolution integer GUI default: this depends on the mesh size. Try using 256 as default meshResolution integer GUI default: 128 holesPerComponent integer """ mm.scene.select_objects(remote, mesh_object) mm.begin_tool(remote, 'hollow') mm.set_toolparam(remote, 'offsetDistanceWorld', offset) mm.set_toolparam( remote, 'solidResolution', solid_resolution) # Solid Accuracy mm.set_toolparam(remote, 'meshResolution', mesh_resolution) # Mesh Density mm.tool_utility_command(remote, 'update') mm.accept_tool(remote) return None
def TestFit(selFrame, scale_size, move_dy): new_objs = mm.append_objects_from_file(remote, hole_filename) mm.select_objects(remote, new_objs) mm.begin_tool(remote, "transform") mm.set_toolparam(remote, "scale", scale_size) mm.accept_tool(remote) (min, max) = mm.get_selected_bounding_box(remote) mm.begin_tool(remote, "transform") cur_origin = mm.get_toolparam(remote, "origin") dy = -((cur_origin[1] - min[1]) + move_dy * 2 / size_x) rotation = mm.make_matrix_from_axes(selFrame.x, mm.negv3(selFrame.z), selFrame.y) mm.set_toolparam(remote, "rotation", rotation) translate = mm.subv3(selFrame.origin, cur_origin) translate = mm.addv3(translate, mm.mulv3s(selFrame.z, dy)) mm.set_toolparam(remote, "translation", translate) mm.accept_tool(remote) mm.select_objects(remote, [obj_list[0], new_objs[0]]) result = TestIntersection(obj_list[0], new_objs[0]) mm.select_objects(remote, [new_objs[0]]) cmd_D = mmapi.StoredCommands() cmd_D.AppendSceneCommand_DeleteSelectedObjects() remote.runCommand(cmd_D) mm.select_objects(remote, [obj_list[0]]) return not result
def make_solid(remote, mesh_object, offset=None, min_thickness=None, edge_collapse_thresh=None, solid_type=None, solid_resolution=None, mesh_resolution=None, close_holes=True, transfer_face_groups=False): """ Make Solid tool offsetDistance : float ; default 0 offsetDistanceWorld : float minThickness : float ; default 0 minThicknessWorld : float edgeCollapseThresh : float ; default 100 solidType : integer ; default 1 (Fast) 0 = Blocky 1 = Fast 2 = Accurate (Required for offset & minThickness) 3 = Sharp Edge Preserve solidResolution : integer ; default 128 meshResolution : integer ; default 128 closeHoles : boolean ; default True transferFaceGroups : boolean ; default False http://www.mmmanual.com/make-solid/ Make Solid approximates your object with small cubes (voxels). This approximation actually happens twice. First we voxelize the shape using solid_resolution as the sampling rate. Then we use a second set of voxels to create a mesh of the first voxel approximation; mesh_resolution is the sampling rate of this second voxelization. These sampling rates can be the same, but they do not have to be. """ mm.scene.select_objects(remote, mesh_object) mm.begin_tool(remote, 'makeSolid') if offset is not None: mm.set_toolparam(remote, 'offsetDistanceWorld', offset) if min_thickness is not None: mm.set_toolparam(remote, 'minThicknessWorld', min_thickness) if edge_collapse_thresh is not None: mm.set_toolparam(remote, 'edgeCollapseThresh', edge_collapse_thresh) if solid_type is not None: mm.set_toolparam(remote, 'solidType', solid_type) if solid_resolution is not None: mm.set_toolparam( remote, 'solidResolution', solid_resolution) # Solid Accuracy if mesh_resolution is not None: mm.set_toolparam( remote, 'meshResolution', mesh_resolution) # Mesh Density mm.set_toolparam(remote, 'closeHoles', close_holes) mm.set_toolparam(remote, 'transferFaceGroups', transfer_face_groups) mm.tool_utility_command(remote, 'update') mm.accept_tool(remote) new_mesh_object = mm.scene.list_selected_objects(remote) print('new_mesh_object = %s' % new_mesh_object) return new_mesh_object
def DFS_Compute_Model(root_id): root=State(root_id) #copy model mm.select_objects(remote, obj_list[0]) mm.begin_tool(remote, "duplicate") mm.accept_tool(remote)
def connector_join(): remote = mmRemote(); remote.connect(); # accept outstanding tools, if there are any mm.accept_tool(remote) [found,id1] = mm.find_object_by_name(remote,'socket') [found,id2] = mm.find_object_by_name(remote,"connector") mm.select_objects(remote,[id1,id2]) # combine part with socket mm.begin_tool(remote, "combine") # select-all and do join # [TODO] support select-boundary-loops in API mm.select_all(remote) mm.begin_tool(remote, "join") mm.accept_tool(remote) [foundconnector,id1] = mm.find_object_by_name(remote,'connector') ## we need to rename the connector back to socket if foundconnector: cmd = mmapi.StoredCommands() cmd.AppendSceneCommand_SetObjectName(id1,'socket') remote.runCommand(cmd) ## [RMS] this block will clean up holes, but requires ability to save & restore selection! ## [TODO] we can do this now, because we can read back facegroup after createFaceGroup... #if False: # # save selection # mm.begin_tool(remote, "createFaceGroup") # mm.clear_face_selection(remote) # # do repair pass, in case join created holes (happens!) # mm.begin_tool(remote, "inspector") # mm.tool_utility_command(remote, "repairAll") # # [TODO] restore selection ## expand selection a few times, then remesh #if True: # for x in range(0,8): # mm.selection_utility_command(remote, "expandByOneRing") # mm.begin_tool(remote, "remesh") # mm.accept_tool(remote) # mm.begin_tool(remote, "smooth") # mm.set_toolparam(remote, "scale", 500.0) # mm.accept_tool(remote) #mm.clear_face_selection(remote) remote.shutdown()
def import_connector(do_accept): # initialize connection remote = mmRemote(); remote.connect(); # find center of current selection, and then shoot ray from below this point, straight upwards, and # hope that it hits outer shell centroid = mm.get_face_selection_centroid(remote) sel_ctr = centroid (bFound, selFrame) = mm.find_ray_hit(remote, mm.addv3(sel_ctr, (0,-10,0)), (0,1,0) ) # exit out of selection tool mm.clear_face_selection(remote) # import part we want to position at selection cwd = os.getcwd() socketPath = os.path.join(cwd,'socket','socket.obj') new_objs = mm.append_objects_from_file(remote, socketPath); # rename part mm.set_object_name(remote, new_objs[0], ConnectorName() ) # select new part mm.select_objects(remote, new_objs) # get bbox of part, so that we can put origin at bottom of cylinder if desired (assume file authored that way) (min,max) = mm.get_selected_bounding_box(remote) partTop = ( (min[0]+max[0])/2, max[1], (min[2]+max[2])/2 ) partCenter = ( (min[0]+max[0])/2, (min[1]+max[1])/2, (min[2]+max[2])/2 ) partH = max[1]-min[1] # RMS HACK BECAUSE OF UNITS STUPID plane_cut_setback = partH * 0.5 # start transform tool mm.begin_tool(remote, "transform") cur_origin = mm.get_toolparam(remote, "origin") dy = 0.5*partH # [RMS] currently assuming that leg is oriented wrt axis, so we keep connector vertical # compute and apply rotation #rotation = mm.make_matrix_from_axes(selFrame.x, mm.negv3(selFrame.z), selFrame.y ) #mm.set_toolparam(remote, "rotation", rotation ) # translate origin of part to frame origin translate = mm.subv3( selFrame.origin, cur_origin ) # shift along frame Z to place bottom of part on surface (ie at frame origin) translate = mm.addv3( translate, mm.mulv3s( selFrame.z, dy ) ) mm.set_toolparam(remote, "translation", translate ) # accept xform if do_accept: mm.accept_tool(remote) remote.shutdown()
def import_connector(do_accept,connectorName): # initialize connection remote = mmRemote(); remote.connect(); setConnectorPath(connectorName) # find center of current selection, and then shoot ray from below this point, straight upwards, and # hope that it hits outer shell centroid = mm.get_face_selection_centroid(remote) sel_ctr = centroid (bFound, selFrame) = mm.find_ray_hit(remote, mm.addv3(sel_ctr, (0,-10,0)), (0,1,0) ) # exit out of selection tool mm.clear_face_selection(remote) # import part we want to position at selection cwd = os.getcwd() socketPath = os.path.join(cwd,'socket',connectorName) new_objs = mm.append_objects_from_file(remote, socketPath); # rename part mm.set_object_name(remote, new_objs[0], ConnectorName() ) # select new part mm.select_objects(remote, new_objs) # get bbox of part, so that we can put origin at bottom of cylinder if desired (assume file authored that way) (min,max) = mm.get_selected_bounding_box(remote) partTop = ( (min[0]+max[0])/2, max[1], (min[2]+max[2])/2 ) partCenter = ( (min[0]+max[0])/2, (min[1]+max[1])/2, (min[2]+max[2])/2 ) partH = max[1]-min[1] # RMS HACK BECAUSE OF UNITS STUPID plane_cut_setback = partH * 0.5 # start transform tool mm.begin_tool(remote, "transform") cur_origin = mm.get_toolparam(remote, "origin") dy = 0.5*partH # [RMS] currently assuming that leg is oriented wrt axis, so we keep connector vertical # compute and apply rotation #rotation = mm.make_matrix_from_axes(selFrame.x, mm.negv3(selFrame.z), selFrame.y ) #mm.set_toolparam(remote, "rotation", rotation ) # translate origin of part to frame origin translate = mm.subv3( selFrame.origin, cur_origin ) # shift along frame Z to place bottom of part on surface (ie at frame origin) translate = mm.addv3( translate, mm.mulv3s( selFrame.z, dy ) ) mm.set_toolparam(remote, "translation", translate ) # accept xform if do_accept: mm.accept_tool(remote) remote.shutdown()
def backtracking(node): global final_result global used_sizes global selected_area global action_dict global frame_dict print("start: " + str(node.object)) if selected_area == []: final_result = node.object print(str(node.object) + " return 1") return 1 cur_frame = selected_area.pop() while len(node.possible_size): if final_result: print("result found") print(str(node.object) + " break") break print(str(node.object) + " possible: " + str(node.possible_size)) size = node.possible_size[0] for move_dy in tube_length: if not TestFit(node.object, cur_frame, [size, size, size], move_dy): print(str(node.object) + " removed " + str(size)) node.possible_size.remove(size) else: print(str(node.object) + " picked " + str(size)) node.possible_size.remove(size) action_dict[size] = frame_dict[cur_frame] mm.select_objects(remote, [node.object]) mm.begin_tool(remote, "duplicate") mm.accept_tool(remote) copy_object = mm.list_selected_objects(remote)[0] drill_holes(copy_object, cur_frame, pipe_filename, [1, 0.1 * move_dy + 0.1, 1], 0, 0) drill_holes(copy_object, cur_frame, hole_filename, [size, size, size], move_dy, 1) child = State(copy_object) child.used_size = size used_sizes.append(size) child.frame = cur_frame print("used size: " + str(used_sizes)) child.possible_size = list(set(hole_sizes) - set(used_sizes)) print( str(child.object) + " possible: " + str(child.possible_size)) backtracking(child) break print(str(node.object) + " return -2") if node.used_size != None: used_sizes.remove(node.used_size) if node.frame != None: selected_area.append(cur_frame) return -2
def create_ring(tar_object, selFrame, scale_size): new_objs = mm.append_objects_from_file(remote, ring_name) mm.select_objects(remote, new_objs) mm.begin_tool(remote, "transform") mm.set_toolparam(remote, "scale", scale_size) mm.accept_tool(remote) (min, max) = mm.get_selected_bounding_box(remote) mm.begin_tool(remote, "transform") cur_origin = mm.get_toolparam(remote, "origin") rotation = mm.make_matrix_from_axes(selFrame.x, mm.negv3(selFrame.z), selFrame.y) mm.set_toolparam(remote, "rotation", rotation) translate = mm.subv3(selFrame.origin, cur_origin) mm.set_toolparam(remote, "translation", translate) mm.accept_tool(remote) mm.select_objects(remote, [tar_object, new_objs[0]]) mm.begin_tool(remote, "combine") mm.accept_tool(remote) return
def drill_holes(tar_object, selFrame, filenames, scale_size, move_dy, flag_set_dy): new_objs = mm.append_objects_from_file(remote, filenames) mm.select_objects(remote, new_objs) mm.begin_tool(remote, "transform") mm.set_toolparam(remote, "scale", scale_size) #mm.set_toolparam(remote, "translation", [0,0,0]) mm.accept_tool(remote) (min, max) = mm.get_selected_bounding_box(remote) mm.begin_tool(remote, "transform") cur_origin = mm.get_toolparam(remote, "origin") dy = flag_set_dy * (-((cur_origin[1] - min[1]) + move_dy * 2 / size_x)) rotation = mm.make_matrix_from_axes(selFrame.x, mm.negv3(selFrame.z), selFrame.y) mm.set_toolparam(remote, "rotation", rotation) translate = mm.subv3(selFrame.origin, cur_origin) translate = mm.addv3(translate, mm.mulv3s(selFrame.z, dy)) mm.set_toolparam(remote, "translation", translate) mm.accept_tool(remote) #mm.begin_tool(remote, "duplicate") #mm.accept_tool(remote) mm.select_objects(remote, [tar_object, new_objs[0]]) mm.begin_tool(remote, "difference") mm.accept_tool(remote) return
def create_ring(selFrame, scale_size): new_objs = mm.append_objects_from_file(remote, ring_name) mm.select_objects(remote, new_objs) mm.begin_tool(remote, "transform") mm.set_toolparam(remote, "scale", scale_size) mm.accept_tool(remote) (min, max) = mm.get_selected_bounding_box(remote) mm.begin_tool(remote, "transform") cur_origin = mm.get_toolparam(remote, "origin") #dy = flag_set_dy*(-((cur_origin[1] - min[1])+move_dy*2/size_x)) rotation = mm.make_matrix_from_axes(selFrame.x, mm.negv3(selFrame.z), selFrame.y) mm.set_toolparam(remote, "rotation", rotation) translate = mm.subv3(selFrame.origin, cur_origin) #translate = mm.addv3( translate, mm.mulv3s( selFrame.z, dy ) ) mm.set_toolparam(remote, "translation", translate) mm.accept_tool(remote) #mm.begin_tool(remote, "duplicate") #mm.accept_tool(remote) mm.select_objects(remote, [obj_list[0], new_objs[0]]) mm.begin_tool(remote, "combine") mm.accept_tool(remote) return
def connector_join(): remote = mmRemote(); remote.connect(); # accept outstanding tools, if there are any mm.accept_tool(remote) [found,id1] = mm.find_object_by_name(remote,SocketName()) [found,id2] = mm.find_object_by_name(remote,ConnectorName()) mm.select_objects(remote,[id1,id2]) # combine part with socket mm.begin_tool(remote, "combine") # select-all and do join # [TODO] support select-boundary-loops in API mm.select_all(remote) mm.begin_tool(remote, "join") mm.accept_tool(remote) # [RMS] this block will clean up holes, but requires ability to save & restore selection! # [TODO] we can do this now, because we can read back facegroup after createFaceGroup... if False: # save selection mm.begin_tool(remote, "createFaceGroup") mm.clear_face_selection(remote) # do repair pass, in case join created holes (happens!) mm.begin_tool(remote, "inspector") mm.tool_utility_command(remote, "repairAll") # [TODO] restore selection # expand selection a few times, then remesh if True: for x in range(0,8): mm.selection_utility_command(remote, "expandByOneRing") mm.begin_tool(remote, "remesh") mm.accept_tool(remote) mm.begin_tool(remote, "smooth") mm.set_toolparam(remote, "scale", 500.0) mm.accept_tool(remote) mm.clear_face_selection(remote) remote.shutdown()
def connector_plane_cut(do_accept): remote = mmRemote(); remote.connect(); # accept outstanding tools, if there are any mm.accept_tool(remote) # get bbox of connector mm.select_object_by_name(remote, ConnectorName() ) (min,max) = mm.get_selected_bounding_box(remote) partCenter = ( (min[0]+max[0])/2, (min[1]+max[1])/2, (min[2]+max[2])/2 ) partH = max[1]-min[1] mm.select_object_by_name(remote, SocketName() ) # shoot ray upwards to hit exterior of socket, and then get facegroup of outer shell (bounds_min, bounds_max) = mm.get_selected_bounding_box(remote) bounds_ctr = mm.mulvs(mm.addv3(bounds_min, bounds_max), 0.5) mm.begin_tool(remote, "select") mm.select_hit_triangle(remote, mm.addv3(bounds_ctr, (0,-10,0)), (0,1,0) ) groups = mm.list_selected_groups(remote) # select outer shell facegroup and start plane cut mm.select_facegroups(remote, groups) mm.begin_tool(remote, "planeCut") # position cutting plane at offset from part mm.set_toolparam(remote, "fillType", 0) #planeNormal = (0,1,0) #mm.set_toolparam(remote, "normal", planeNormal ) planeOrigin = max planeOrigin = mm.addv3( planeOrigin, mm.mulv3s(planeNormal, 0.5*partH) ) mm.set_toolparam(remote, "origin", planeOrigin) if do_accept: mm.accept_tool(remote) remote.shutdown()
def connector_plane_cut(do_accept): remote = mmRemote(); remote.connect(); # accept outstanding tools, if there are any mm.accept_tool(remote) # get bbox of connector mm.select_object_by_name(remote, ConnectorName() ) (min,max) = mm.get_selected_bounding_box(remote) partCenter = ( (min[0]+max[0])/2, (min[1]+max[1])/2, (min[2]+max[2])/2 ) partH = max[1]-min[1] mm.select_object_by_name(remote, SocketName() ) # shoot ray upwards to hit exterior of socket, and then get facegroup of outer shell (bounds_min, bounds_max) = mm.get_selected_bounding_box(remote) bounds_ctr = mm.mulvs(mm.addv3(bounds_min, bounds_max), 0.5) mm.begin_tool(remote, "select") mm.select_hit_triangle(remote, mm.addv3(bounds_ctr, (0,-10,0)), (0,1,0) ) groups = mm.list_selected_groups(remote) # select outer shell facegroup and start plane cut mm.select_facegroups(remote, groups) mm.begin_tool(remote, "planeCut") # position cutting plane at offset from part mm.set_toolparam(remote, "fillType", 0) planeNormal = (0,1,0) #mm.set_toolparam(remote, "normal", planeNormal ) planeOrigin = max planeOrigin = mm.addv3( planeOrigin, mm.mulv3s(planeNormal, 0.5*partH) ) mm.set_toolparam(remote, "origin", planeOrigin) if do_accept: mm.accept_tool(remote) remote.shutdown()
# [RMS] this is a simple demo that just runs the plane cut command # and accepts the result. This cuts the current object in half. import mmapi from mmRemote import * import mm # initialize connection remote = mmRemote() remote.connect() # run planeCut command mm.begin_tool(remote, "planeCut") # rotate cutting plane 90 degrees rotation = mm.make_rotZ_matrix(3.14159*0.5) mm.set_toolparam(remote, "rotation", rotation ) # accept result mm.accept_tool(remote) #done! remote.shutdown()
def scriptButton(theEvent): print("!!!!!!!!!function blow hole!!!!!!!!!!!!") flag_done = 0 root = State(mm.list_selected_objects(remote)[0]) cur_state = root possible_size = root.possible_size remain_area = list(selected_area) used_sizes = list() print("area:" + str(len(remain_area)) + "," + str(remain_area)) while (len(possible_size) and len(remain_area)): print("###in while loop###") print("1: cur " + str(cur_state.object)) mm.select_objects(remote, [cur_state.object]) mm.begin_tool(remote, "duplicate") mm.accept_tool(remote) copy_object = mm.list_selected_objects(remote)[0] print("2:" + str(copy_object)) cur_frame = remain_area.pop() cur_state.frame = cur_frame print(["3:", cur_frame]) flag_done = 0 print("4: used " + str(used_sizes)) print("4: possi " + str(possible_size)) print("4: cur_possi " + str(cur_state.possible_size)) for size in possible_size: if not TestFit(copy_object, cur_frame, [size, size, size], 5): cur_state.possible_size.remove(size) else: print("5 select:" + str(size)) print("5: " + str( TestFit(copy_object, cur_frame, [size, size, size], 5))) print("6:" + str(cur_state.possible_size)) flag_done = 1 cur_state.possible_size.remove(size) print("6:" + str(cur_state.possible_size)) cur_state.used_size = size used_sizes.append(size) print("7:" + str(used_sizes)) create_ring(copy_object, cur_frame, [8, 2, 8]) drill_holes(copy_object, cur_frame, pipe_filename, [1, 0.5, 1], 0, 0) drill_holes(copy_object, cur_frame, hole_filename, [size, size, size], 5, 1) new_state = State(copy_object) print("9: new " + str(new_state.object)) new_state.parent = cur_state new_state.possible_size = list( set(hole_sizes) - set(used_sizes)) print("10:" + str(new_state.possible_size)) cur_state = new_state possible_size = cur_state.possible_size print("11:" + str(possible_size)) break if not cur_state.parent: possible_size = list() break if flag_done == 0: print("12: failed") new_state = cur_state.parent print("13: " + str(cur_state.frame)) remain_area.append(cur_state.frame) used_sizes.append(new_state.used_size) print("15: " + str(possible_size)) possible_size = cur_state.possible_size if not len(remain_area): print("done area:" + str(len(remain_area))) setStatusText("Success!") #selected_area=[] else: setStatusText("Unable to assign the holes")
sel_ctr = centroid (bFound, selFrame) = mm.find_nearest(remote, sel_ctr) # exit out of selection tool mm.clear_face_selection(remote) for size in [0.5]: # import part we want to position at selection new_objs = mm.append_objects_from_file(remote, pipe_filename) # select imported part mm.select_objects(remote, new_objs) mm.begin_tool(remote, "transform") mm.set_toolparam(remote, "scale", [1, size, 1]) #mm.set_toolparam(remote, "translation", [0,0,0]) mm.accept_tool(remote) # get bbox of part, so that we can put origin at bottom of object if desired # (we are assuming that in its file, the part is positioned at the origin, on the ground plane) (min, max) = mm.get_selected_bounding_box(remote) # start transform tool mm.begin_tool(remote, "transform") cur_origin = mm.get_toolparam(remote, "origin") print(cur_origin) print(min) dy = -(cur_origin[1] - min[1]) # compute and apply rotation rotation = mm.make_matrix_from_axes(selFrame.x, mm.negv3(selFrame.z), selFrame.y) mm.set_toolparam(remote, "rotation", rotation)
import mmapi from mmRemote import * import mm # initialize connection r = mmRemote() r.connect() # save initial selection list initial_selection = mm.list_selected_objects(r) # generate shell using Offset tool mm.select_all(r) mm.begin_tool(r, "offset") mm.set_toolparam(r, "offsetWorld", 1.25) mm.accept_tool(r) # now Offset is done, and shell is selected. Next we Separate it mm.begin_tool(r, "separate") mm.accept_tool(r) # read back current selection (will be shell) shell_objects = mm.list_selected_objects(r) mm.set_object_name(r, shell_objects[0], "shell") # set current as target (will be offset shell) mm.set_as_target(r) # restore original selection mm.select_objects(r, initial_selection)
def make_solid(remote, mesh_object, offset=None, min_thickness=None, edge_collapse_thresh=None, solid_type=None, solid_resolution=None, mesh_resolution=None, close_holes=True, transfer_face_groups=False): """ Make Solid tool offsetDistance : float ; default 0 offsetDistanceWorld : float minThickness : float ; default 0 minThicknessWorld : float edgeCollapseThresh : float ; default 100 solidType : integer ; default 1 (Fast) 0 = Blocky 1 = Fast 2 = Accurate (Required for offset & minThickness) 3 = Sharp Edge Preserve solidResolution : integer ; default 128 meshResolution : integer ; default 128 closeHoles : boolean ; default True transferFaceGroups : boolean ; default False http://www.mmmanual.com/make-solid/ Make Solid approximates your object with small cubes (voxels). This approximation actually happens twice. First we voxelize the shape using solid_resolution as the sampling rate. Then we use a second set of voxels to create a mesh of the first voxel approximation; mesh_resolution is the sampling rate of this second voxelization. These sampling rates can be the same, but they do not have to be. """ mm.scene.select_objects(remote, mesh_object) mm.begin_tool(remote, 'makeSolid') if offset is not None: mm.set_toolparam(remote, 'offsetDistanceWorld', offset) if min_thickness is not None: mm.set_toolparam(remote, 'minThicknessWorld', min_thickness) if edge_collapse_thresh is not None: mm.set_toolparam(remote, 'edgeCollapseThresh', edge_collapse_thresh) if solid_type is not None: mm.set_toolparam(remote, 'solidType', solid_type) if solid_resolution is not None: mm.set_toolparam(remote, 'solidResolution', solid_resolution) # Solid Accuracy if mesh_resolution is not None: mm.set_toolparam(remote, 'meshResolution', mesh_resolution) # Mesh Density mm.set_toolparam(remote, 'closeHoles', close_holes) mm.set_toolparam(remote, 'transferFaceGroups', transfer_face_groups) mm.tool_utility_command(remote, 'update') mm.accept_tool(remote) new_mesh_object = mm.scene.list_selected_objects(remote) print('new_mesh_object = %s' % new_mesh_object) return new_mesh_object