def execute(self, context): sce=bpy.context.scene ob = context.object layers_copy = [layer for layer in context.scene.layers] context.scene.layers[0] = True if ob: L = odcutils.get_bbox_center(ob, world=True) elif sce.odc_props.master: ob = bpy.data.objects[sce.odc_props.master] L = odcutils.get_bbox_center(ob, world=True) else: L = bpy.context.scene.cursor_location bpy.ops.view3d.viewnumpad(type='TOP') bpy.ops.object.select_all(action='DESELECT') if context.mode != 'OBJECT': bpy.ops.object.mode_set(mode='OBJECT') #bpy.context.scene.cursor_location = L bpy.ops.curve.primitive_bezier_curve_add(view_align=True, enter_editmode=True, location=L) PlanCurve = context.object PlanCurve.layers[4] = True PlanCurve.layers[0] = True PlanCurve.layers[1] = True PlanCurve.layers[3] = True context.tool_settings.use_snap = True context.tool_settings.snap_target= 'ACTIVE' context.tool_settings.snap_element = 'FACE' context.tool_settings.proportional_edit = 'DISABLED' context.tool_settings.use_snap_project = False bpy.ops.object.mode_set(mode='EDIT') bpy.ops.curve.handle_type_set(type='AUTOMATIC') bpy.ops.curve.select_all(action='DESELECT') context.object.data.splines[0].bezier_points[1].select_control_point=True bpy.ops.curve.delete() bpy.ops.curve.select_all(action='SELECT') odcutils.layer_management(sce.odc_splints) for i, layer in enumerate(layers_copy): context.scene.layers[i] = layer context.scene.layers[3] = True return {'FINISHED'}
def execute(self, context): sce=bpy.context.scene n = sce.odc_splint_index splint = sce.odc_splints[n] layers_copy = [layer for layer in context.scene.layers] context.scene.layers[0] = True model = splint.model Model = bpy.data.objects[model] L = odcutils.get_bbox_center(Model, world=True) #L = bpy.context.scene.cursor_location #bpy.ops.view3d.viewnumpad(type='TOP') bpy.ops.object.select_all(action='DESELECT') if context.mode != 'OBJECT': bpy.ops.object.mode_set(mode='OBJECT') #bpy.context.scene.cursor_location = L bpy.ops.curve.primitive_bezier_curve_add(view_align=True, enter_editmode=True, location=L) context.tool_settings.use_snap = True context.tool_settings.snap_target= 'ACTIVE' context.tool_settings.snap_element = 'FACE' context.tool_settings.proportional_edit = 'DISABLED' Margin =context.object Margin.name=splint.name + "_margin" Margin.parent = Model bpy.ops.object.mode_set(mode='EDIT') bpy.ops.curve.handle_type_set(type='AUTOMATIC') bpy.ops.curve.select_all(action='DESELECT') context.object.data.splines[0].bezier_points[1].select_control_point=True bpy.ops.curve.delete() bpy.ops.curve.select_all(action='SELECT') mod = Margin.modifiers.new('Wrap','SHRINKWRAP') mod.target = Model mod.offset = .75 mod.use_keep_above_surface = True mod = Margin.modifiers.new('Smooth','SMOOTH') mod.iterations = 10 splint.margin = Margin.name odcutils.layer_management(sce.odc_splints) for i, layer in enumerate(layers_copy): context.scene.layers[i] = layer context.scene.layers[4] = True return {'FINISHED'}
def invoke(self,context, event): if context.object: ob = context.object L = odcutils.get_bbox_center(ob, world=True) context.scene.cursor_location = L self.crv = CurveDataManager(context,snap_type ='SCENE', snap_object = None, shrink_mod = False, name = 'Plan Curve') #TODO, tweak the modifier as needed help_txt = "DRAW ARCH OUTLINE\n\nLeft Click in scene to draw a curve \nPoints will snap to objects under mouse \nNot clicking on object will make points at same depth as 3D cursor \n Right click to delete a point n\ G to grab \n ENTER to confirm \n ESC to cancel" self.help_box = TextBox(context,500,500,300,200,10,20,help_txt) self.help_box.snap_to_corner(context, corner = [1,1]) self.mode = 'main' self._handle = bpy.types.SpaceView3D.draw_handler_add(arch_crv_draw_callback, (self, context), 'WINDOW', 'POST_PIXEL') context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'}
def finish(self, context): loc = odcutils.get_bbox_center(self.model, world=True) ins_ob = bpy.data.objects.get('Insertion Axis') view = ins_ob.matrix_world.to_quaternion() * Vector((0, 0, 1)) #view = context.space_data.region_3d.view_rotation * Vector((0,0,1)) odcutils.silouette_brute_force(context, self.model, view, True) #mxT = Matrix.Translation(loc) #mxR = context.space_data.region_3d.view_rotation.to_matrix().to_4x4() #if "Insertion Axis" in bpy.data.objects: # ob = bpy.data.objects.get('Insertion Axis') # ob.hide = False #else: # ob = bpy.data.objects.new('Insertion Axis', None) # ob.empty_draw_type = 'SINGLE_ARROW' # ob.empty_draw_size = 20 # context.scene.objects.link(ob) bpy.ops.object.select_all(action='DESELECT') #ob.parent = self.model #ob.matrix_world = mxT * mxR context.scene.objects.active = self.model self.model.select = True #context.scene.cursor_location = loc #bpy.ops.view3d.view_center_cursor() #bpy.ops.view3d.viewnumpad(type = 'FRONT') #bpy.ops.view3d.view_selected() #context.space_data.transform_manipulators = {'ROTATE'} for i, mat in enumerate(self.model.data.materials): if mat.name == 'Undercut': break self.model.data.materials.pop(i, update_data=True) context.space_data.show_textured_solid = False self.splint.insertion_path = True self.model.lock_location[0], self.model.lock_location[ 1], self.model.lock_location[2] = True, True, True
def preview_direction(self, context): start = time.time() view = context.space_data.region_3d.view_rotation * Vector((0, 0, 1)) mx = self.model.matrix_world i_mx = mx.inverted() view_local = i_mx.to_quaternion() * view fs_undercut = bme_undercut_faces(self.bme, view_local) print('there are %i undercts' % len(fs_undercut)) vcolor_data = self.bme.loops.layers.color['Undercut'] bmesh_color_bmfaces(self.bme.faces[:], vcolor_data, Color((1, 1, 1))) bmesh_color_bmfaces(fs_undercut, vcolor_data, Color((.8, .2, .5))) self.bme.to_mesh(self.model.data) finish = time.time() print('took %s to detect undercuts' % str(finish - start)[0:4]) loc = odcutils.get_bbox_center(self.model, world=True) mxT = Matrix.Translation(loc) mxR = context.space_data.region_3d.view_rotation.to_matrix().to_4x4() self.ins_ob.matrix_world = mxT * mxR self.previewed = True return
def break_contact_deform(context, ob1,ob2, debug = False): ''' separate two objects by deforming a lattice with a plane. Results in a smooth separation. args: ret: ''' if debug: print('ob1 name: %s' % ob1.name) print('ob2 name: %s' % ob2.name) quat_1 = ob1.matrix_world.to_quaternion() quat_2 = ob2.matrix_world.to_quaternion() lat1 = odcutils.bbox_to_lattice(context.scene, ob1) lat2 = odcutils.bbox_to_lattice(context.scene, ob2) print('we made lattices?') loc_1 = odcutils.get_bbox_center(ob1, world = True) loc_2 = odcutils.get_bbox_center(ob2, world = True) diff = loc_2 - loc_1 #the directions to keep things simple. x = Vector((1,0,0)) y = Vector((0,1,0)) z = Vector((0,0,1)) vecs = [x,y,z] #dot each of the x,y,z coords (transformed to workd dir) with the vector between #the two bounding box centers. dirs1 = [(quat_1 * x).dot(diff)**2, (quat_1 * y).dot(diff)**2, (quat_1 * z).dot(diff)**2] dirs2 = [(quat_2 * x).dot(diff)**2, (quat_2 * y).dot(diff)**2, (quat_2 * z).dot(diff)**2] #find the maximium dot product #this is the dirction which is most parallel dir1 = dirs1.index(max(dirs1)) dir2 = dirs2.index(max(dirs2)) #check i we need to negate eithe directions #don't get confused because we will negate again #when we put the shrinwrap mod on. This is determinging #whether +x or -x points at the othe robject neg1 = 1 + -2 * ((quat_1 * vecs[dir1]).dot(diff) < 0) neg2 = 1 + -2 * ((quat_2 * vecs[dir2]).dot(diff) > 0) vec1 = neg1 * vecs[dir1] vec2 = neg2 * vecs[dir2] if debug: print(ob1.name + ' is pointed toward ' + ob2.name + ' in the direction:') print(vec1) print(ob2.name + ' is pointed toward ' + ob1.name + ' in the direction:') print(vec2) pt1 = odcutils.box_feature_locations(ob1, vec1) pt2 = odcutils.box_feature_locations(ob2, vec2) if debug: print(pt1) print(pt2) midpoint = .5 * (pt1 + pt2) pln_verts = [Vector((1,1,0)),Vector((-1,1,0)),Vector((-1,-1,0)),Vector((1,-1,0))] pln_faces = [(0,1,2,3)] pln_mesh = bpy.data.meshes.new('separator') pln_mesh.from_pydata(pln_verts,[],pln_faces) new_plane_ob = bpy.data.objects.new('Separator', pln_mesh) new_plane_ob.rotation_mode = 'QUATERNION' new_plane_ob.rotation_quaternion = odcutils.rot_between_vecs(Vector((0,0,1)), diff) new_plane_ob.location = midpoint new_plane_ob.scale = .5 * (ob1.dimensions + ob2.dimensions) context.scene.objects.link(new_plane_ob) mod1 = lat1.modifiers.new('Contact', 'SHRINKWRAP') mod2 = lat2.modifiers.new('Contact', 'SHRINKWRAP') mod1.wrap_method = 'PROJECT' mod2.wrap_method = 'PROJECT' if neg1 < 0: mod1.use_negative_direction = False mod1.use_positive_direction = True else: mod1.use_negative_direction = True mod1.use_positive_direction = False if neg2 < 0: mod2.use_negative_direction = False mod2.use_positive_direction = True else: mod2.use_negative_direction = True mod2.use_positive_direction = False if dir1 == 0: mod1.use_project_x = True elif dir1 == 1: mod1.use_project_y = True else: mod1.use_project_z = True if dir2 == 0: mod2.use_project_x = True elif dir2 == 1: mod2.use_project_y = True else: mod2.use_project_z = True mod1.target = new_plane_ob mod2.target = new_plane_ob print('broken!')
def invoke(self, context, event): if len(context.scene.odc_splints) == 0: self.report({'ERROR'}, "Need to mark splint and opposing models first") return {'CANCELLED'} n = context.scene.odc_splint_index self.splint = context.scene.odc_splints[n] self.previewed = False max_model = self.splint.get_maxilla() mand_model = self.splint.get_mandible() if self.splint.jaw_type == 'MANDIBLE': Model = bpy.data.objects.get(mand_model) else: Model = bpy.data.objects.get(max_model) for ob in bpy.data.objects: ob.select = False ob.hide = True Model.select = True Model.hide = False context.scene.objects.active = Model add_volcolor_material_to_obj(Model, 'Undercut') #view a presumptive occlusal axis if self.splint.jaw_type == 'MAXILLA': bpy.ops.view3d.viewnumpad(type='BOTTOM') else: bpy.ops.view3d.viewnumpad(type='TOP') #add in a insertin axis direction loc = odcutils.get_bbox_center(Model, world=True) view = context.space_data.region_3d.view_rotation * Vector((0, 0, 1)) mxT = Matrix.Translation(loc) mxR = context.space_data.region_3d.view_rotation.to_matrix().to_4x4() if "Insertion Axis" in bpy.data.objects: ins_ob = bpy.data.objects.get('Insertion Axis') else: ins_ob = bpy.data.objects.new('Insertion Axis', None) ins_ob.empty_draw_type = 'SINGLE_ARROW' ins_ob.empty_draw_size = 20 context.scene.objects.link(ins_ob) ins_ob.hide = False ins_ob.parent = Model ins_ob.matrix_world = mxT * mxR self.ins_ob = ins_ob #get bmesh data to process self.bme = bmesh.new() self.bme.from_mesh(Model.data) self.bme.verts.ensure_lookup_table() self.bme.edges.ensure_lookup_table() self.bme.faces.ensure_lookup_table() self.model = Model bpy.ops.view3d.view_selected() context.space_data.viewport_shade = 'SOLID' context.space_data.show_textured_solid = True #TODO, tweak the modifier as needed help_txt = "Pick Insertion Axis\n\n- Position your viewing direction looking onto the model\n- LEFT CLICK on the model\n- You can then rotate and pan your view to assess the undercuts. This process can be repeated until the desired insertion axis is chosen.\n\nADVANCED USE\n\n- Use LEFT_ARROW, RIGHT_ARROW, UP_ARROW and DOWN_ARROW to accurately alter the axis. Holding SHIFT while pressing the ARROW keys will alter the axis by 0.5 degrees.\nPress ENTER when finished" self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt) self.help_box.snap_to_corner(context, corner=[1, 1]) self.mode = 'main' self._handle = bpy.types.SpaceView3D.draw_handler_add( pick_axis_draw_callback, (self, context), 'WINDOW', 'POST_PIXEL') context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'}