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 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 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 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 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 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 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 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_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()
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
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)
# this gives us a 3D frame we can align an object to centroid = mm.get_face_selection_centroid(remote) 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),
# select imported part mm.select_objects(remote, new_objs) # 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") 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 ) # translate origin of part to frame origin translate = mm.subv3( selFrame.origin, cur_origin ) # uncomment this line to shift along frame Z, this will 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 mm.accept_tool(remote) # make a copy of the object, because boolean will delete it and it is useful to be able to see where the part was mm.begin_tool(remote, "duplicate") mm.accept_tool(remote) # select original object and cylinder we imported
# short script examples. # Note that most of these use the SWIG-generated interface directly, # instead of the mm package import os import mmapi from mmRemote import * import mm # initialize connection r = mmRemote() r.connect() mm.begin_tool(r, "makePattern") mm.set_toolparam(r, "pattern", 20) # set default pipe diameter *in world units* (eg millimeters) pipe_diam = 2.0 mm.set_toolparam(r, "dimension1", pipe_diam) # now we can create the pattern. However, the numbers we pass for the # start and end points are not new diameters, the are dimensionless # scaling factors applied to the default pipe_diam. So, 1.0=pipe_diam, # 2.0 = pipe_diam*2, etc. And if you want to specify a specific diameter, # you would send (target_diam/pipe_diam) # # create pattern in **Scene** coordinates #mm.append_pattern_segment(r, (0,0,0), (0,0.5,0), 1.0, 1.5 ) #mm.append_pattern_segment(r, (0,0,0), (0.5,0.0,0), 1.0, 2.0 ) #mm.append_pattern_segment(r, (0,0,0), (0.0,0.0,0.5), 1.0, 3.0 )
# [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 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