def pick_voxel(self, context, event, voxelarray): """Run this function on left mouse, execute the ray cast TODO: report/go through some problems with selecting in the operator_modal_view3d_raycast.py. Most of the problem is when trying to click close to the edge of the object. The distance values are often mucked up""" # get the context arguments ray_max=10000.0 region = context.region rv3d = context.region_data coord = event.mouse_region_x, event.mouse_region_y # get the ray from the viewport and mouse view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * ray_max) #TODO: raise some kind of error, or do a check/poll on this operator #to ensure that there has been a voxel array created and selected isects = voxelarray.intersect_ray(ray_origin, ray_target) best_dist_squared = ray_max * ray_max best_isect = None if isects is None: return None for isect in isects: dist_squared = isect.dist_squared if(dist_squared < best_dist_squared): best_dist_squared = dist_squared best_isect = isect return best_isect
def click_add_seed(self,context,x,y): ''' x,y = event.mouse_region_x, event.mouse_region_y this will add a point into the bezier curve or close the curve into a cyclic curve ''' region = context.region rv3d = context.region_data coord = x, y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) mx = self.cut_ob.matrix_world imx = mx.inverted() if bversion() < '002.077.000': loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target) else: res, loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target - imx * ray_origin) if face_ind == -1: self.selected = -1 return self.seed = self.bme.faces[face_ind] self.seed_loc = loc self.geo_data = [dict(), set(), set(), set()]
def click_add_target(self, context, x, y): region = context.region rv3d = context.region_data coord = x, y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) mx = self.cut_ob.matrix_world imx = mx.inverted() loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target) if face_ind == -1: return self.target = self.bme.faces[face_ind] self.target_loc = loc geos, fixed, close, far = geodesic_walk(self.bme, self.seed, self.seed_loc, targets = [self.target], subset = None, max_iters = 100000, min_dist = None) path_elements, self.path = gradient_descent(self.bme, geos, self.target, self.target_loc, epsilon = .0000001) self.geo_data = [geos, fixed, close, far] return
def set_ray_from_region(self, x, y): context = bpy.context mesh_object = self.mesh_object region = context.region region_co = Vector((x, y)) rv3d = context.region_data sv3d = context.space_data # Determine the view's clipping distances. if rv3d.view_perspective == 'CAMERA': camera_data = sv3d.camera.data clip_start = camera_data.clip_start clip_end = camera_data.clip_end else: clip_start = sv3d.clip_start clip_end = sv3d.clip_end # Determine the ray's direction in world space. ray_direction = view3d_utils.region_2d_to_vector_3d( region, rv3d, region_co ) # For orthographic projections in Blender versions prior to 2.72, the # ray's direction needs to be inverted to point into the scene. if bpy.app.version < (2, 72, 0): if rv3d.view_perspective == 'ORTHO' or ( rv3d.view_perspective == 'CAMERA' and sv3d.camera.data.type == 'ORTHO' ): ray_direction *= -1 # Determine the ray's origin in world space. ray_origin =\ view3d_utils.region_2d_to_origin_3d(region, rv3d, region_co) # Determine the ray's target in world space. ray_target = ray_origin + clip_end * ray_direction # If the view is an orthographic projection, the ray's origin may exist # behind the mesh object. Therefore, it is necessary to move the ray's # origin a sufficient distance antiparallel to the ray's direction to # ensure that the ray's origin is in front of the mesh object. if rv3d.view_perspective == 'ORTHO': ray_origin -= 10000 * ray_direction # Otherwise, if the view is a perspective projection or projected from # a camera then advance the ray's origin to the near clipping plane. else: ray_origin += clip_start * ray_direction # Convert the ray's origin and target from world space to object space, # if necessary. if self.coordinate_system == 'OBJECT': inverse_model_matrix = mesh_object.matrix_world.inverted() for co in ray_origin, ray_target: co.xyz = inverse_model_matrix * co # Set the ray caster object's ray attributes. self.ray_origin = ray_origin self.ray_target = ray_target
def pick_object(region, rv3d, x, y, near, far, objects): ''' Selects an object underneath given screen coordinates Parameters: region (bpy.types.Region): Section of the UI in which to do picking rv3d (bpy.types.RegionView3D): 3D view region data near (float): Near clipping plane far (float): Far clipping plane objects (seq<bpy.types.Object>): Sequence of pickable objects Returns: (obj, location, normal, index): Reference to picked object and raycast hit information; otherwise None obj (bpy.types.Object): Nearest object in path of the ray location (Vector): Object space location of ray-face intersection normal (Vector): Normal vector of intersected face index (int): Index of intersected face ''' blender_version = bpy.app.version # Determine ray extents. coord = Vector((x, y)) ray_dir = region_2d_to_vector_3d(region, rv3d, coord) ray_start = region_2d_to_origin_3d(region, rv3d, coord) + ray_dir * near ray_end = ray_start + ray_dir * (far - near) # Pick a mesh object underneath given screen coordinates. result = None min_dist_squared = sys.float_info.max for obj in objects: # Skip objects that cannot participate in ray casting. if (not obj.type == 'MESH' or obj.mode == 'EDIT' or not obj.data.polygons ): continue # Cast ray in object space. inverse_model_matrix = obj.matrix_world.inverted() hit = obj.ray_cast( inverse_model_matrix * ray_start, inverse_model_matrix * ray_end ) if blender_version < (2, 76, 9): location, normal, index = hit else: location, normal, index = hit[1:] # Compare intersection distances. if index != -1: dist_squared = (obj.matrix_world * location - ray_start).length_squared # Record closer of the two hits. if dist_squared < min_dist_squared: min_dist_squared = dist_squared result = (obj, location, normal, index) return result
def click_add_target(self, context, x, y): region = context.region rv3d = context.region_data coord = x, y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) mx = self.cut_ob.matrix_world imx = mx.inverted() if bversion() < '002.077.000': loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target) else: res, loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target - imx * ray_origin) if face_ind == -1: return self.target = self.bme.faces[face_ind] self.target_loc = loc vrts, eds, ed_cross, f_cross, error = path_between_2_points(self.bme, self.bvh, mx,mx* self.seed_loc,mx*self.target_loc, max_tests = 10000, debug = True, prev_face = None, use_limit = True) if not error: self.path = vrts else: self.path = [] return
def raycast_screen(self, loc2d, rgn, r3d): o,d = region_2d_to_origin_3d(rgn, r3d, loc2d),region_2d_to_vector_3d(rgn, r3d, loc2d) back = 0 if r3d.is_perspective else 100 p3d,n3d,idx,dist = self.bvh_raycast(self.imx * (o-d*back), self.imx3x3 * d) p3d = self.mx * p3d if p3d else None n3d = self.nmx * n3d if n3d else None return (p3d, n3d)
def modal(self, context, event): region = context.region rv3d = context.region_data co2d = ((event.mouse_region_x, event.mouse_region_y)) view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, co2d) enterloc = view3d_utils.region_2d_to_origin_3d(region, rv3d, co2d) + view_vector*100 NP020PL.enterloc = copy.deepcopy(enterloc) print('02_GetMouseloc_FINISHED', ';', 'NP020PL.flag = ', NP020PL.flag) return{'FINISHED'}
def cast_obj_ray_from_mouse(mousepos, candidates=None, exclude_decals=True, debug=False): region = bpy.context.region region_data = bpy.context.region_data origin_3d = region_2d_to_origin_3d(region, region_data, mousepos) vector_3d = region_2d_to_vector_3d(region, region_data, mousepos) # get candidate objects, that could be hit if not candidates: candidates = bpy.context.visible_objects if exclude_decals: objects = [(obj, None) for obj in candidates if obj.type == "MESH" and not obj.DM.isdecal] else: objects = [(obj, None) for obj in candidates if obj.type == "MESH"] hitobj = None hitlocation = None hitnormal = None hitindex = None hitdistance = sys.maxsize for obj, src in objects: mx = obj.matrix_world mxi = mx.inverted() ray_origin = mxi @ origin_3d ray_direction = mxi.to_3x3() @ vector_3d # success, location, normal, index = obj.ray_cast(origin=ray_origin, direction=ray_direction, depsgraph=depsgraph) success, location, normal, index = obj.ray_cast( origin=ray_origin, direction=ray_direction) distance = (mx @ location - origin_3d).length if debug: print("candidate:", success, obj.name, location, normal, index, distance) if success and distance < hitdistance: hitobj, hitlocation, hitnormal, hitindex, hitdistance = obj, mx @ location, mx.to_3x3( ) @ normal, index, distance if debug: print("best hit:", hitobj.name if hitobj else None, hitlocation, hitnormal, hitindex, hitdistance if hitobj else None) print() if hitobj: return hitobj, hitlocation, hitnormal, hitindex, hitdistance return None, None, None, None, None
def modal(self,context,event): print('05_BglPlane_START',';','NP020RM.flag = ', NP020RM.flag) context.area.tag_redraw() flag = NP020RM.flag mode = NP020RM.mode plane = NP020RM.plane helper = NP020RM.helper centerloc = NP020RM.centerloc if event.type == 'MOUSEMOVE': self.co2d = ((event.mouse_region_x, event.mouse_region_y)) print('05_BglPlane_mousemove',';','NP020RM.flag = ', NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode, 'NP020RM.plane = ', NP020RM.plane) elif event.type in ('LEFTMOUSE', 'RIGHTMOUSE', 'RET', 'NUMPAD_ENTER'): bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') region = context.region rv3d = context.region_data co2d = self.co2d view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, co2d) viewloc = view3d_utils.region_2d_to_origin_3d(region, rv3d, co2d) away = (centerloc - viewloc).length pointloc = viewloc + view_vector * away # to place the helper on centerloc to be in the vicinity of projection plane helper.location = pointloc helper.hide = False NP020RM.qdef = copy.deepcopy(NP020RM.q) NP020RM.ndef = copy.deepcopy(NP020RM.n) NP020RM.plane = 'SET' NP020RM.flag = 'RUNTRANSSTART' print('05_BglPlane_lmb_FINISHED',';','NP020RM.flag = ', NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode, 'NP020RM.plane = ', NP020RM.plane) return{'FINISHED'} elif event.ctrl and event.value == 'PRESS': bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') if mode == 'FREE': NP020RM.mode = 'X' elif mode == 'X': NP020RM.mode = 'Y' elif mode == 'Y': NP020RM.mode = 'Z' else: NP020RM.mode = 'FREE' print('05_BglPlane_rmb_FINISHED',';','NP020RM.flag = ', NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode, 'NP020RM.plane = ', NP020RM.plane) elif event.type == 'ESC': bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') NP020RM.flag = 'EXIT' print('05_BglPlane_esc_FINISHED',';','NP020RM.flag = ', NP020RM.flag) return{'FINISHED'} elif event.type in {'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}: print('05_BglPlane_middle_wheel_any_PASS_THROUGH') return {'PASS_THROUGH'} print('05_BglPlane_standard_RUNNING_MODAL',';','NP020RM.flag = ', NP020RM.flag) return {'RUNNING_MODAL'}
def modal(self,context,event): np_print('05_BglPlane_START',';','NP020RM.flag = ', NP020RM.flag) context.area.tag_redraw() flag = NP020RM.flag mode = NP020RM.mode plane = NP020RM.plane helper = NP020RM.helper centerloc = NP020RM.centerloc if event.type == 'MOUSEMOVE': self.co2d = ((event.mouse_region_x, event.mouse_region_y)) np_print('05_BglPlane_mousemove',';','NP020RM.flag = ', NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode, 'NP020RM.plane = ', NP020RM.plane) elif event.type in ('LEFTMOUSE', 'RIGHTMOUSE', 'RET', 'NUMPAD_ENTER'): bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') region = context.region rv3d = context.region_data co2d = self.co2d view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, co2d) viewloc = view3d_utils.region_2d_to_origin_3d(region, rv3d, co2d) away = (centerloc - viewloc).length pointloc = viewloc + view_vector * away # to place the helper on centerloc to be in the vicinity of projection plane helper.location = pointloc helper.hide = False NP020RM.qdef = copy.deepcopy(NP020RM.q) NP020RM.ndef = copy.deepcopy(NP020RM.n) NP020RM.plane = 'SET' NP020RM.flag = 'RUNTRANSSTART' np_print('05_BglPlane_lmb_FINISHED',';','NP020RM.flag = ', NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode, 'NP020RM.plane = ', NP020RM.plane) return{'FINISHED'} elif event.ctrl and event.value == 'PRESS': bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') if mode == 'FREE': NP020RM.mode = 'X' elif mode == 'X': NP020RM.mode = 'Y' elif mode == 'Y': NP020RM.mode = 'Z' else: NP020RM.mode = 'FREE' np_print('05_BglPlane_rmb_FINISHED',';','NP020RM.flag = ', NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode, 'NP020RM.plane = ', NP020RM.plane) elif event.type == 'ESC': bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') NP020RM.flag = 'EXIT' np_print('05_BglPlane_esc_FINISHED',';','NP020RM.flag = ', NP020RM.flag) return{'FINISHED'} elif event.type in {'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}: np_print('05_BglPlane_middle_wheel_any_PASS_THROUGH') return {'PASS_THROUGH'} np_print('05_BglPlane_standard_RUNNING_MODAL',';','NP020RM.flag = ', NP020RM.flag) return {'RUNNING_MODAL'}
def pick_object(region, rv3d, x, y, near, far, objects): ''' Selects an object underneath given screen coordinates Parameters: region (bpy.types.Region): Section of the UI in which to do picking rv3d (bpy.types.RegionView3D): 3D view region data near (float): Near clipping plane far (float): Far clipping plane objects (seq<bpy.types.Object>): Sequence of pickable objects Returns: (obj, location, normal, index): Reference to picked object and raycast hit information; otherwise None obj (bpy.types.Object): Nearest object in path of the ray location (Vector): Object space location of ray-face intersection normal (Vector): Normal vector of intersected face index (int): Index of intersected face ''' # Determine ray extents. coord = Vector((x, y)) ray_dir = region_2d_to_vector_3d(region, rv3d, coord) ray_start = region_2d_to_origin_3d(region, rv3d, coord) + ray_dir * near ray_end = ray_start + ray_dir * (far - near) # Pick a mesh object underneath given screen coordinates. result = None min_dist_squared = sys.float_info.max for obj in objects: # Skip objects that cannot participate in ray casting. if (not obj.type == 'MESH' or obj.mode == 'EDIT' or not obj.data.polygons ): continue # Cast ray in object space. inverse_model_matrix = obj.matrix_world.inverted() location, normal, index = obj.ray_cast( inverse_model_matrix * ray_start, inverse_model_matrix * ray_end )[0:3] # Compare intersection distances. if index != -1: dist_squared = (obj.matrix_world * location - ray_start).length_squared # Record closer of the two hits. if dist_squared < min_dist_squared: min_dist_squared = dist_squared result = (obj, location, normal, index) return result
def get_slide_vector_intersection(self, context): view_origin = region_2d_to_origin_3d(context.region, context.region_data, self.mousepos) view_dir = region_2d_to_vector_3d(context.region, context.region_data, self.mousepos) i = intersect_line_line(view_origin, view_origin + view_dir, self.origin, self.target_avg) return i[1]
def modal(self, context, event): region = context.region rv3d = context.region_data co2d = ((event.mouse_region_x, event.mouse_region_y)) view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, co2d) enterloc = view3d_utils.region_2d_to_origin_3d( region, rv3d, co2d) + view_vector * 100 NP020RM.enterloc = copy.deepcopy(enterloc) np_print('02_GetMouseloc_FINISHED', ';', 'NP020RM.flag = ', NP020RM.flag) return {'FINISHED'}
def modal(self,context, event): region = context.region rv3d = context.region_data co2d = ((event.mouse_region_x, event.mouse_region_y)) view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, co2d) pointloc = view3d_utils.region_2d_to_origin_3d(region, rv3d, co2d) + view_vector/5 print(pointloc) Storage.pointloc=pointloc #print('020') return{'FINISHED'}
def get_target(region: bpy.types.Region, region_3d: bpy.types.RegionView3D, pixel_coords: Tuple[float, float]): from bpy_extras import view3d_utils view_vector = view3d_utils.region_2d_to_vector_3d(region, region_3d, pixel_coords) ray_origin = view3d_utils.region_2d_to_origin_3d(region, region_3d, pixel_coords) target = ray_origin + view_vector return [target.x, target.y, target.z]
def grab_mouse_move(self, context, x, y): region = context.region rv3d = context.region_data coord = x, y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) hit = False if self.snap_type == 'SCENE': mx = Matrix.Identity(4) #scene ray cast returns world coords imx = Matrix.Identity(4) no_mx = imx.to_3x3().transposed() if bversion() < '002.077.000': res, obj, omx, loc, no = context.scene.ray_cast( ray_origin, ray_target) else: res, loc, no, ind, obj, omx = context.scene.ray_cast( ray_origin, view_vector) if res: hit = True else: #cast the ray into a plane a #perpendicular to the view dir, at the last bez point of the curve hit = True view_direction = rv3d.view_rotation * Vector((0, 0, -1)) plane_pt = self.grab_undo_loc loc = intersect_line_plane(ray_origin, ray_target, plane_pt, view_direction) no = view_direction elif self.snap_type == 'OBJECT': mx = self.snap_ob.matrix_world imx = mx.inverted() no_mx = imx.to_3x3().transposed() if bversion() < '002.077.000': loc, no, face_ind = self.snap_ob.ray_cast( imx * ray_origin, imx * ray_target) if face_ind != -1: hit = True else: ok, loc, no, face_ind = self.snap_ob.ray_cast( imx * ray_origin, imx * ray_target - imx * ray_origin) if ok: hit = True if not hit: self.grab_cancel() else: self.b_pts[self.selected].location = mx * loc self.b_pts[self.selected].surface_normal = no_mx * no
def GetMouseLocation(self, event, context): region = bpy.context.region rv3d = bpy.context.region_data coord = event.mouse_region_x, event.mouse_region_y view_vector_mouse = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin_mouse = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) V_a = ray_origin_mouse + view_vector_mouse V_b = rv3d.view_rotation @ Vector((0.0, 0.0, -1.0)) pointLoc = intersect_line_plane(ray_origin_mouse, V_a, context.object.location, V_b) loc = (self.GeneralNormal @ pointLoc) * -1 return loc
def get_ray_target(x, y, ray_max=1e4): region = bpy.context.region rv3d = bpy.context.region_data cam = bpy.context.camera coord = x, y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) if rv3d.view_perspective == "ORTHO" or (rv3d.view_perspective == "CAMERA" and cam and cam.type == "ORTHO"): # move ortho origin back ray_origin = ray_origin - (view_vector * (ray_max / 2.0)) ray_target = ray_origin + (view_vector * 1e4)
def modal(self, context, event): context.area.tag_redraw() context.window.cursor_modal_set("EYEDROPPER") scene = context.scene region = context.region rv3d = context.region_data if event.type == 'LEFTMOUSE' and event.value == 'RELEASE': self.mouse = event.mouse_region_x, event.mouse_region_y view_vector = view3d_utils.region_2d_to_vector_3d( region, rv3d, self.mouse) ray_origin = view3d_utils.region_2d_to_origin_3d( region, rv3d, self.mouse) raycast = scene.ray_cast(ray_origin, view_vector) if raycast[0] == True: ob = raycast[4] if ob.data.materials: mat = ob.data.materials[0] for shape in [ o for o in context.selected_objects if o.type in ('MESH', 'CURVE', 'FONT') ]: if not shape.data.materials: shape.data.materials.append(mat) else: shape.material_slots[0].material = mat #context.space_data.draw_handler_remove(self._handle, 'WINDOW') context.window.cursor_modal_restore() for ob in self.temp_ob: bpy.data.objects.remove(ob, True) return {'FINISHED'} #return {'FINISHED'} elif event.type in {'RIGHTMOUSE', 'ESC'}: #context.object.location.x = self.first_value context.window.cursor_modal_restore() for ob in self.temp_ob: bpy.data.objects.remove(ob, True) return {'CANCELLED'} return {'RUNNING_MODAL'}
def hover_non_man(self,context,x,y): region = context.region rv3d = context.region_data coord = x, y self.mouse = Vector((x, y)) loc3d_reg2D = view3d_utils.location_3d_to_region_2d view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) mx = self.cut_ob.matrix_world imx = mx.inverted() loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target) if len(self.non_man_points): co3d, index, dist = self.kd.find(mx * loc) #get the actual non man vert from original list close_bmvert = self.bme.verts[self.non_man_bmverts[index]] #stupid mapping, unreadable, terrible, fix this, because can't keep a list of actual bmverts close_eds = [ed for ed in close_bmvert.link_edges if not ed.is_manifold] if len(close_eds) == 2: bm0 = close_eds[0].other_vert(close_bmvert) bm1 = close_eds[1].other_vert(close_bmvert) a0 = bm0.co b = close_bmvert.co a1 = bm1.co inter_0, d0 = intersect_point_line(loc, a0, b) inter_1, d1 = intersect_point_line(loc, a1, b) screen_0 = loc3d_reg2D(region, rv3d, mx * inter_0) screen_1 = loc3d_reg2D(region, rv3d, mx * inter_1) screen_v = loc3d_reg2D(region, rv3d, mx * b) screen_d0 = (self.mouse - screen_0).length screen_d1 = (self.mouse - screen_1).length screen_dv = (self.mouse - screen_v).length if 0 < d0 <= 1 and screen_d0 < 30: self.hovered = ['NON_MAN_ED', (close_eds[0], mx*inter_0)] return elif 0 < d1 <= 1 and screen_d1 < 30: self.hovered = ['NON_MAN_ED', (close_eds[1], mx*inter_1)] return elif screen_dv < 30: if abs(d0) < abs(d1): self.hovered = ['NON_MAN_VERT', (close_eds[0], mx*b)] return else: self.hovered = ['NON_MAN_VERT', (close_eds[1], mx*b)] return
def mouse_to_scene_raycast(self, context, event): """ convert mouse pos to 3d point over plane defined by origin and normal """ region = context.region rv3d = context.region_data co2d = (event.mouse_region_x, event.mouse_region_y) view_vector_mouse = region_2d_to_vector_3d(region, rv3d, co2d) ray_origin_mouse = region_2d_to_origin_3d(region, rv3d, co2d) res, pos, normal, face_index, object, matrix_world = context.scene.ray_cast( ray_origin_mouse, view_vector_mouse) return res, pos, normal, face_index, object, matrix_world
def screen_space_to_3d(location, distance, context): region = context.region data = context.space_data.region_3d if data.is_perspective: vec = region_2d_to_vector_3d(region, data, location) origin = region_2d_to_origin_3d(region, data, location, distance) else: vec = data.view_rotation @ Vector((0, 0, -1)) origin = region_2d_to_location_3d(region, data, location, -vec * data.view_distance) location = vec * distance + origin return location
def unProject(region, rv3d, mcursor): view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, mcursor) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, mcursor) ray_target = ray_origin + (view_vector * 1000) scene = bpy.context.scene # cast the ray result, object, matrix, location, normal = scene.ray_cast(ray_origin, ray_target) if location == None: location = Vector((0,0,0)) return result, object, matrix, location, normal
def modal(self, context, event): region = context.region rv3d = context.region_data co2d = ((event.mouse_region_x, event.mouse_region_y)) view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, co2d) pointloc = view3d_utils.region_2d_to_origin_3d(region, rv3d, co2d) + view_vector / 5 print(pointloc) Storage.pointloc = pointloc #print('020') return {'FINISHED'}
def grab_mouse_move(self,context,x,y): region = context.region rv3d = context.region_data coord = x, y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) crv_mx = self.crv_obj.matrix_world i_crv_mx = crv_mx.inverted() hit = False if self.snap_type == 'SCENE': mx = Matrix.Identity(4) #scene ray cast returns world coords if bversion() < '002.077.000': res, obj, omx, loc, no = context.scene.ray_cast(ray_origin, ray_target) else: res, loc, no, ind, obj, omx = context.scene.ray_cast(ray_origin, view_vector) if res: hit = True else: #cast the ray into a plane a #perpendicular to the view dir, at the last bez point of the curve hit = True view_direction = rv3d.view_rotation * Vector((0,0,-1)) plane_pt = self.grab_undo_loc loc = intersect_line_plane(ray_origin, ray_target,plane_pt, view_direction) elif self.snap_type == 'OBJECT': mx = self.snap_ob.matrix_world imx = mx.inverted() if bversion() < '002.077.000': loc, no, face_ind = self.snap_ob.ray_cast(imx * ray_origin, imx * ray_target) if face_ind != -1: hit = True else: ok, loc, no, face_ind = self.snap_ob.ray_cast(imx * ray_origin, imx * ray_target - imx*ray_origin) if ok: hit = True if not hit: self.grab_cancel() else: local_loc = i_crv_mx * mx * loc self.crv_data.splines[0].bezier_points[self.selected].co = local_loc self.b_pts[self.selected] = mx * loc
def modal(self, context, event): props = context.scene.son_props if context.mode == 'OBJECT': # マウスカーソルのリージョン座標を取得 mv = Vector((event.mouse_region_x, event.mouse_region_y)) # 3Dビューエリアのウィンドウリージョンと、スペースを取得する region, space = ShowObjectName.__get_region_space( context, 'VIEW_3D', 'WINDOW', 'VIEW_3D' ) # マウスカーソルの位置に向けて発したレイの方向を求める ray_dir = view3d_utils.region_2d_to_vector_3d( region, space.region_3d, mv ) # マウスカーソルの位置に向けて発したレイの発生源を求める ray_orig = view3d_utils.region_2d_to_origin_3d( region, space.region_3d, mv ) # レイの始点 start = ray_orig # レイの終点(線分の長さは2000とした) end = ray_orig + ray_dir * 2000 # カメラやライトなど、メッシュ型ではないオブジェクトは除く objs = [o for o in bpy.data.objects if o.type == 'MESH'] self.__intersected_objs = [] for o in objs: try: # レイとオブジェクトの交差判定 mwi = o.matrix_world.inverted() result = o.ray_cast(mwi * start, mwi * end) # オブジェクトとレイが交差した場合は交差した面のインデックス、交差しない場合は-1が返ってくる if result[2] != -1: self.__intersected_objs.append(o) # メッシュタイプのオブジェクトが作られているが、ray_cast対象の面が存在しない場合 except RuntimeError: print("""サンプル5-4: オブジェクト生成タイミングの問題により、 例外エラー「レイキャスト可能なデータなし」が発生""") # 3Dビューの画面を更新 if context.area: context.area.tag_redraw() # 作業時間計測を停止 if props.running is False: self.__handle_remove(context) return {'FINISHED'} return {'PASS_THROUGH'}
def mouse_raycast(context: bpy.types.Context, mx: float, my: float) -> tuple: """Perform a raycast from the mouse. Parameters: context: Blender context mx: mouse x-coordinate my: mouse y-coordinate Returns: tuple: Tuple containing: if a object was hit; location; normal; rotation; face index; object; matrix; """ region = context.region rv3d = context.region_data coord = mx, my # get the ray from the viewport and mouse target_distance = 1e9 view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * target_distance) vec = ray_target - ray_origin ( has_hit, snapped_location, snapped_normal, face_index, obj_hit, matrix, ) = bpy.context.scene.ray_cast(bpy.context.view_layer.depsgraph, ray_origin, vec) randoffset = math.pi if has_hit: snapped_rotation = snapped_normal.to_track_quat('Z', 'Y').to_euler() up = Vector((0, 0, 1)) props = getattr(bpy.context.window_manager, HANA3D_MODELS) angle_threshold = 10.0 if snapped_normal.angle(up) < math.radians(angle_threshold): randoffset = props.offset_rotation_amount + math.pi else: # we don't rotate this way on walls and ceilings. randoffset = props.offset_rotation_amount else: snapped_rotation = mathutils.Quaternion((0, 0, 0, 0)).to_euler() snapped_rotation.rotate_axis('Z', randoffset) return has_hit, snapped_location, snapped_normal, snapped_rotation, face_index, obj_hit, matrix
def ray_cast_to_mouse(self): # get the ray from the viewport and mouse view_vector = view3d_utils.region_2d_to_vector_3d( self.act_reg, self.act_rv3d, self._mouse_reg_loc) ray_origin = view3d_utils.region_2d_to_origin_3d( self.act_reg, self.act_rv3d, self._mouse_reg_loc) hit, norm, ind, dist = self._object_bvh.ray_cast( ray_origin, view_vector, 10000) if hit != None and ind != None: return hit, ind return None
def unProject(region, rv3d, mcursor): view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, mcursor) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, mcursor) ray_target = ray_origin + (view_vector * 1000) scene = bpy.context.scene # cast the ray result, object, matrix, location, normal = scene.ray_cast( ray_origin, ray_target) if location == None: location = Vector((0, 0, 0)) return result, object, matrix, location, normal
def ray_cast_view_occlude_test(co, mouse_co, bvh, region, rv3d): orig_co = view3d_utils.region_2d_to_origin_3d( region, rv3d, mouse_co) direction_to = (orig_co - co).normalized() occluded = False hit_to_view, norm_to_view, ind_to_view, dist_to_view = bvh.ray_cast( co+direction_to*.001, direction_to, 1000000) if hit_to_view != None: occluded = True return occluded
def to3d(coords, distance=1.0): """ Args: coords: distance: (Default value = 1.0) Returns: """ # bgl.glUnProject() return view3d_utils.region_2d_to_origin_3d(*getRegionData(), (coords), distance)
def get_mouse_on_plane(context, plane_pos, mouse_coords): region = context.region rv3d = context.region_data cam_dir = rv3d.view_rotation * Vector((0.0, 0.0, -1.0)) #cam_pos = view3d_utils.region_2d_to_origin_3d(region, rv3d, (region.width/2.0, region.height/2.0)) mouse_pos = view3d_utils.region_2d_to_origin_3d(region, rv3d, mouse_coords) mouse_dir = view3d_utils.region_2d_to_vector_3d(region, rv3d, mouse_coords) new_pos = mathu.geometry.intersect_line_plane(mouse_pos, mouse_pos+(mouse_dir*10000.0), plane_pos, cam_dir, False) if new_pos: return new_pos return None
def modal(self, context, event): if event.type == 'MOUSEMOVE': mouse = (event.mouse_region_x, event.mouse_region_y) input_value = internal.nearestPointOfLines( bpy.context.scene.cursor.location, bpy.context.scene.cursor.matrix.col[2].xyz, view3d_utils.region_2d_to_origin_3d(context.region, context.region_data, mouse), view3d_utils.region_2d_to_vector_3d(context.region, context.region_data, mouse))[1] if self.mode == 'PITCH': self.pitch = input_value / ( self.slice_count - 1) if self.slice_count > 2 else input_value elif self.mode == 'OFFSET': self.offset = input_value - self.pitch * 0.5 * ( (self.slice_count - 1) if self.slice_count > 2 else 1.0) elif event.type == 'WHEELUPMOUSE': if self.slice_count > 2: self.pitch *= (self.slice_count - 1) self.slice_count += 1 if self.slice_count > 2: self.pitch /= (self.slice_count - 1) elif event.type == 'WHEELDOWNMOUSE': if self.slice_count > 2: self.pitch *= (self.slice_count - 1) if self.slice_count > 1: self.slice_count -= 1 if self.slice_count > 2: self.pitch /= (self.slice_count - 1) elif event.type == 'LEFTMOUSE' and event.value == 'RELEASE': if self.mode == 'PITCH': self.mode = 'OFFSET' return {'RUNNING_MODAL'} elif self.mode == 'OFFSET': self.mesh.free() return {'FINISHED'} elif event.type in {'RIGHTMOUSE', 'ESC'}: self.mesh.free() if self.dst_obj.type == 'MESH': bpy.data.meshes.remove(self.dst_obj.data) else: bpy.data.curves.remove(self.dst_obj.data) bpy.context.view_layer.objects.active = self.src_obj return {'CANCELLED'} else: return {'PASS_THROUGH'} self.perform() return {'RUNNING_MODAL'}
def floor_raycast(context: bpy.types.Context, mx: float, my: float) -> tuple: """Perform a raycast from the floor. Parameters: context: Blender context mx: mouse x-coordinate my: mouse y-coordinate Returns: tuple: Tuple containing: if a object was hit; location; normal; rotation; face index; object; matrix; """ region = context.region rv3d = context.region_data coord = mx, my # get the ray from the viewport and mouse view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) # various intersection plane normals are needed for corner cases # that might actually happen quite often - in front and side view. # default plane normal is scene floor. tolerance = 1e-4 plane_normal = (0, 0, 1) if math.isclose(view_vector.z, 0, abs_tol=tolerance): if math.isclose(view_vector.x, 0, abs_tol=tolerance): plane_normal = (0, 1, 0) else: plane_normal = (1, 0, 0) origin = (0, 0, 0) snapped_location = mathutils.geometry.intersect_line_plane( ray_origin, ray_target, origin, plane_normal, ) if snapped_location is not None: has_hit = True snapped_normal = Vector((0, 0, 1)) face_index = None obj_hit = None matrix = None snapped_rotation = snapped_normal.to_track_quat('Z', 'Y').to_euler() props = getattr(bpy.context.window_manager, HANA3D_MODELS) randoffset = props.offset_rotation_amount + math.pi snapped_rotation.rotate_axis('Z', randoffset) return has_hit, snapped_location, snapped_normal, snapped_rotation, face_index, obj_hit, matrix
def grab_mouse_move(self, context, x, y): region = context.region rv3d = context.region_data coord = x, y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) mx = self.cut_ob.matrix_world imx = mx.inverted() loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target) if face_ind == -1: self.grab_cancel() return #check if first or end point and it's a non man edge! geos, fixed, close, far = self.geo_data self.target = self.bme.faces[face_ind] self.target_loc = loc if all([v in fixed for v in self.target.verts]): path_elements, self.path = gradient_descent(self.bme, geos, self.target, self.target_loc, epsilon=.0000001) print('great we have already waked the geodesic this far') else: print('continue geo walk until we find it, then get it') continue_geodesic_walk(self.bme, self.seed, self.seed_loc, geos, fixed, close, far, targets=[self.bme.faces[face_ind]], subset=None, max_iters=100000, min_dist=None) path_elements, self.path = gradient_descent(self.bme, geos, self.target, self.target_loc, epsilon=.0000001)
def hover(self, context, x, y): ''' hovering happens in mixed 3d and screen space. It's a mess! ''' if len(self.b_pts) == 0: return region = context.region rv3d = context.region_data self.mouse = Vector((x, y)) coord = x, y loc3d_reg2D = view3d_utils.location_3d_to_region_2d view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) if self.snap_type == 'OBJECT': mx = self.snap_ob.matrix_world imx = mx.inverted() res, loc, no, face_ind = self.snap_ob.ray_cast(imx @ ray_origin, imx @ ray_target - imx @ ray_origin) if not res: #do some shit pass elif self.snap_type == 'SCENE': mx = Matrix.Identity(4) #scene ray cast returns world coords res, loc, no, ind, obj, omx = context.scene.ray_cast(context.view_layer, ray_origin, view_vector) print(obj) def dist(v): diff = v - Vector((x,y)) return diff.length def dist3d(pt): if pt.location is None: return 100000000 delt = pt.location - mx @ loc return delt.length closest_3d_point = min(self.b_pts, key=dist3d) screen_dist = dist(loc3d_reg2D(context.region, context.space_data.region_3d, closest_3d_point.location)) self.hovered = ['POINT', self.b_pts.index(closest_3d_point)] if screen_dist < 20 else [None, -1] print(self.hovered)
def GetValue(self, MousePosition, normal, clip_normal): region = bpy.context.region rv3d = bpy.context.region_data view_vector_mouse = view3d_utils.region_2d_to_vector_3d(region, rv3d, MousePosition) ray_origin_mouse = view3d_utils.region_2d_to_origin_3d(region, rv3d, MousePosition) MouseVector = view_vector_mouse + ray_origin_mouse pointLoc = intersect_line_plane(ray_origin_mouse, MouseVector, self.Center, clip_normal) # dvec = self.Center-pointLoc # dnormal = dvec.dot(normal) # val = self.Center + Vector(dnormal*normal) return ((((pointLoc - self.Center)) @ normal) * -1)
def mouse_sc_raycast(context, co2d): '''Raycast that works in edit mode - caution: returns evaluated face idx does not match''' view_vector = region_2d_to_vector_3d(context.region, context.region_data, co2d) ray_origin = region_2d_to_origin_3d(context.region, context.region_data, co2d) viewlayer = context.view_layer hidden = [] hit_index = None hit_obj = None hit_loc = None hit_normal = None hit_mtx = None hit = False is_visible = False # scene invisible is dfferent from view invisible, so we must do this dance while not is_visible: result, location, normal, index, obj, matrix = context.scene.ray_cast( context.evaluated_depsgraph_get(), ray_origin, view_vector, distance=9001) if obj is not None: is_visible = obj.visible_get(view_layer=viewlayer) if not is_visible: obj.hide_viewport = True hidden.append(obj) if is_visible: if obj.type == 'MESH': hit_index = index hit_obj = obj hit_normal = normal # hit_normal = correct_normal(matrix, normal) hit_loc = location hit_mtx = matrix hit = result else: hit_obj = None hit_index = None is_visible = True if hidden: for o in hidden: o.hide_viewport = False return hit, hit_loc, hit_normal, hit_index, hit_obj, hit_mtx
def getOrigin(self, context, event, mode=False): scene = context.scene region = context.region rv3d = context.region_data coord = event.mouse_region_x, event.mouse_region_y # get the ray from the viewport and mouse view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) origin_ = intersect_point_line(self.actPos, ray_origin, ray_origin + view_vector) origin = origin_[0] return origin
def modal(self, context, event): # get the ray from the viewport and mouse if bpy.context.mode == 'OBJECT': MousePosition = Vector( ((event.mouse_x) - context.area.regions.data.x, event.mouse_y - context.area.regions.data.y)) region = bpy.context.region rv3d = bpy.context.region_data view_vector_mouse = view3d_utils.region_2d_to_vector_3d( region, rv3d, MousePosition) ray_origin_mouse = view3d_utils.region_2d_to_origin_3d( region, rv3d, MousePosition) direction = ray_origin_mouse + (view_vector_mouse * 1000) direction = direction - ray_origin_mouse result, location, normal, index, obj, matrix = bpy.context.scene.ray_cast( bpy.context.view_layer.depsgraph, ray_origin_mouse, direction) if result: if self.Extend and not obj.select_get(): bpy.ops.view3d.select('INVOKE_DEFAULT', extend=True, deselect=False) elif self.Deselect and obj.select_get(): obj.select_set(False) elif not self.Extend and not self.Deselect and not obj.select_get( ): bpy.ops.view3d.select('INVOKE_DEFAULT', extend=True, deselect=False) else: # context.mode in ['EDIT_CURVE','EDIT_MESH']: if self.Extend: bpy.ops.view3d.select('INVOKE_DEFAULT', extend=True, deselect=False) elif self.Deselect: bpy.ops.view3d.select('INVOKE_DEFAULT', extend=False, deselect=True) elif not self.Extend and not self.Deselect: bpy.ops.view3d.select('INVOKE_DEFAULT', extend=True, deselect=False) # elif context.mode == 'EDIT_ARMATURE': # self.obj = if event.value == 'RELEASE': return {'CANCELLED'} return {'RUNNING_MODAL'}
def raycast_2d_3d(_ctx, _2dPos): region, regionData = get_regiondata_view3d(_ctx) # get region data # normalized 3d vector from 2d region coords to 3d space # length of 1 vNormalized = view3d_utils.region_2d_to_vector_3d( region, regionData, _2dPos) # this returns a 3d vector (mathutils.Vector) # Get view origin from relative 2d coords of the region to the 3d spcace origin = view3d_utils.region_2d_to_origin_3d(region, regionData, _2dPos) # hit, pos, normal, index, obj, matrix return _ctx.scene.ray_cast(_ctx.view_layer if blender_version()[1] < 91 else _ctx.view_layer.depsgraph, origin, vNormalized, distance=1e+10) # distance can be higher
def __StarPosMouse(self, context, event): region = bpy.context.region rv3d = bpy.context.region_data coord = event.mouse_region_x, event.mouse_region_y view_vector_mouse = view3d_utils.region_2d_to_vector_3d( region, rv3d, coord) ray_origin_mouse = view3d_utils.region_2d_to_origin_3d( region, rv3d, coord) pointLoc = intersect_line_plane( ray_origin_mouse, ray_origin_mouse + view_vector_mouse, self.center, rv3d.view_rotation * Vector((0.0, 0.0, -1.0)), False) return pointLoc, (self.direction * pointLoc) * -1
def out_Location(rv3d, region, mcursor): view_matrix = rv3d.view_matrix.transposed() orig = view3d_utils.region_2d_to_origin_3d(region, rv3d, mcursor) vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, mcursor) v1 = Vector((int(view_matrix[0][0]*1.5),int(view_matrix[1][0]*1.5),int(view_matrix[2][0]*1.5))) v2 = Vector((int(view_matrix[0][1]*1.5),int(view_matrix[1][1]*1.5),int(view_matrix[2][1]*1.5))) hit = mathutils.geometry.intersect_ray_tri(Vector((1,0,0)), Vector((0,1,0)), Vector((0,0,0)), (vector), (orig), False) if hit == None: hit = mathutils.geometry.intersect_ray_tri(v1, v2, Vector((0,0,0)), (vector), (orig), False) if hit == None: hit = mathutils.geometry.intersect_ray_tri(v1, v2, Vector((0,0,0)), (-vector), (orig), False) if hit == None: hit = Vector((0,0,0)) return hit
def click_model(self, context, x, y): region = context.region rv3d = context.region_data coord = x, y ray_max = 10000 view_vector = region_2d_to_vector_3d(region, rv3d, coord) ray_origin = region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * ray_max) imx = self.model.matrix_world.inverted() result, loc, normal, idx = self.model.ray_cast( imx * ray_origin, imx * ray_target - imx * ray_origin) return result
def get_view_origin_position(): #method 1 from bpy_extras import view3d_utils region = bpy.context.region rv3d = bpy.context.region_data view_loc = view3d_utils.region_2d_to_origin_3d(region, rv3d, (region.width/2.0, region.height/2.0)) print("view_loc1", view_loc)#Dbg #method 2 r3d = bpy.context.space_data.region_3d view_loc2 = r3d.view_matrix.inverted().translation print("view_loc2", view_loc2)#Dbg if view_loc != view_loc2: print('there might be an errror when finding view coordinate') return view_loc
def mousemove_drawing(self, context, event): screen_v = Vector((event.mouse_region_x, event.mouse_region_y)) self.mouse_path.append((event.mouse_region_x, event.mouse_region_y)) #this will just add in apoint every 10 recorded mouse positions #later you will want to do something smarter :-) if len(self.mouse_path) > self.draw_points_max or (screen_v - Vector(self.mouse_path[0])).length >= self.extrusion_radius: region = context.region rv3d = context.region_data #this is the view_vector @ the mous coord #which is not the same as the view_direction!!! view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, self.mouse_path[-1]) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, self.mouse_path[-1]) ray_target = ray_origin + (view_vector * 10000) #cast the ray into a plane a #perpendicular to the view dir, at the last bez point of the curve view_direction = rv3d.view_rotation * Vector((0,0,-1)) if self.active_spline.type == 'BEZIER': plane_pt = self.curve_object.matrix_world * self.active_spline.bezier_points[-1].co elif self.active_spline.type == 'NURBS': plane_pt = self.curve_object.matrix_world * self.active_spline.points[-1].co new_coord = intersect_line_plane(ray_origin, ray_target,plane_pt, view_direction) if new_coord: if self.active_spline.type == 'BEZIER': self.active_spline.bezier_points.add(1) self.active_spline.bezier_points[-1].co = self.curve_object.matrix_world.inverted() * new_coord self.active_spline.bezier_points[-1].handle_right.xyz = self.active_spline.bezier_points[-1].co self.active_spline.bezier_points[-1].handle_left.xyz = self.active_spline.bezier_points[-1].co self.active_spline.bezier_points[-1].handle_left_type = 'AUTO' self.active_spline.bezier_points[-1].handle_right_type = 'AUTO' elif self.active_spline.type == 'NURBS': self.active_spline.points.add(1) loc = self.curve_object.matrix_world.inverted() * new_coord #NURBS pahts have 4 dim points self.active_spline.points[-1].co = Vector((loc[0], loc[1], loc[2], 1)) #udpate everything #udpate modifiers and objects etc. self.curve_object.update_tag() context.scene.update() self.mouse_path = []
def mouse_to_plane(self, context, event, origin=Vector((0, 0, 0)), normal=Vector((0, 0, 1))): """ convert mouse pos to 3d point over plane defined by origin and normal """ region = context.region rv3d = context.region_data co2d = (event.mouse_region_x, event.mouse_region_y) view_vector_mouse = region_2d_to_vector_3d(region, rv3d, co2d) ray_origin_mouse = region_2d_to_origin_3d(region, rv3d, co2d) pt = intersect_line_plane(ray_origin_mouse, ray_origin_mouse + view_vector_mouse, origin, normal, False) # fix issue with parallel plane if pt is None: pt = intersect_line_plane(ray_origin_mouse, ray_origin_mouse + view_vector_mouse, origin, view_vector_mouse, False) return pt
def get_mouse_on_plane(context, plane_pos, plane_dir, mouse_coords): region = context.region rv3d = context.region_data final_dir = plane_dir if plane_dir is None: final_dir = rv3d.view_rotation * Vector((0.0, 0.0, -1.0)) mouse_pos = view3d_utils.region_2d_to_origin_3d(region, rv3d, mouse_coords) mouse_dir = view3d_utils.region_2d_to_vector_3d(region, rv3d, mouse_coords) new_pos = mathu.geometry.intersect_line_plane( mouse_pos, mouse_pos + (mouse_dir * 10000.0), plane_pos, final_dir, False) if new_pos: return new_pos return None
def click_add_point(self,context,x,y): ''' x,y = event.mouse_region_x, event.mouse_region_y this will add a point into the bezier curve or close the curve into a cyclic curve ''' region = context.region rv3d = context.region_data coord = x, y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) mx = self.cut_ob.matrix_world imx = mx.inverted() if bversion() < '002.077.000': loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target) else: ok, loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target - imx*ray_origin) if face_ind == -1: self.selected = -1 return if self.hovered[0] == None: #adding in a new point self.pts += [mx * loc] self.cut_pts += [loc] self.normals += [no] self.face_map += [face_ind] self.selected = len(self.pts) -1 if self.hovered[0] == 'POINT': self.selected = self.hovered[1] if self.hovered[1] == 0: #clicked on first bpt, close loop self.cyclic = self.cyclic == False return elif self.hovered[0] == 'EDGE': #cut in a new point self.pts.insert(self.hovered[1]+1, mx * loc) self.cut_pts.insert(self.hovered[1]+1, loc) self.normals.insert(self.hovered[1]+1, no) self.face_map.insert(self.hovered[1]+1, face_ind) self.selected = self.hovered[1] + 1 return
def ray_cast_region2d(region, rv3d, screen_coord, ob, settings): ''' performs ray casting on object given region, rv3d, and coords wrt region. returns tuple of ray vector (from coords of region) and hit info ''' mx = ob.matrix_world imx = mx.inverted() ray_vector = region_2d_to_vector_3d(region, rv3d, screen_coord).normalized() ray_origin = region_2d_to_origin_3d(region, rv3d, screen_coord) if rv3d.is_perspective: #ray_target = ray_origin + ray_vector * 100 r1 = get_ray_origin(ray_origin, -ray_vector, ob) ray_target = r1 else: # need to back up the ray's origin, because ortho projection has front and back # projection planes at inf r0 = get_ray_origin(ray_origin, ray_vector, ob) r1 = get_ray_origin(ray_origin, -ray_vector, ob) dprint(str(r0) + '->' + str(r1), l=4) ray_origin = r0 ray_target = r1 #TODO: make a max ray depth or pull this depth from clip depth ray_start_local = imx * ray_origin ray_target_local = imx * ray_target if settings.debug > 3: print('ray_persp = ' + str(rv3d.is_perspective)) print('ray_origin = ' + str(ray_origin)) print('ray_target = ' + str(ray_target)) print('ray_vector = ' + str(ray_vector)) print('ray_diff = ' + str((ray_target - ray_origin).normalized())) print('start: ' + str(ray_start_local)) print('target: ' + str(ray_target_local)) if bversion() >= '002.077.000': hit = ob.ray_cast(ray_start_local, (ray_target_local - ray_start_local)) else: hit = ob.ray_cast(ray_start_local, ray_target_local) return (ray_vector, hit)
def hover_scene(self,context,x, y): scene = context.scene region = context.region rv3d = context.region_data coord = x, y ray_max = 10000 view_vector = region_2d_to_vector_3d(region, rv3d, coord) ray_origin = region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * ray_max) result, ob, mx, loc, normal = scene.ray_cast(ray_origin, ray_target) if result: self.ob = ob self.ob_preview = ob.name context.area.header_text_set(ob.name) else: self.ob = None self.ob_preview = 'None' context.area.header_text_set('None')
def get_mouse_raycast(context, objects_list, coords_2d, ray_max=10000.0): region = context.region rv3d = context.region_data best_obj, hit_normal, hit_position = None, None, None best_length_squared = 20000.0 * 20000.0 # get the ray from the viewport and mouse view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coords_2d) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coords_2d) for obj, matrix in objects_list: # Do RayCast! t1,t2,t3,t4 - temp values t1, t2, t3 = obj_raycast(obj, matrix, view_vector, ray_origin, ray_max) if t1 is not None and t3 < best_length_squared: best_obj, hit_normal, hit_position = obj, t1, t2 best_length_squared = t3 return best_obj, hit_normal, hit_position
def grab_mouse_move(self,context,x,y): region = context.region rv3d = context.region_data coord = x, y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) mx = self.cut_ob.matrix_world imx = mx.inverted() if bversion() < '002.077.000': loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target) if face_ind == -1: self.grab_cancel() return else: res, loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target - imx * ray_origin) if not res: self.grab_cancel() return #check if first or end point and it's a non man edge! geos, fixed, close, far = self.geo_data self.target = self.bme.faces[face_ind] self.target_loc = loc if all([v in fixed for v in self.target.verts]): path_elements, self.path = gradient_descent(self.bme, geos, self.target, self.target_loc, epsilon = .0000001) print('great we have already waked the geodesic this far') else: print('continue geo walk until we find it, then get it') continue_geodesic_walk(self.bme, self.seed, self.seed_loc, geos, fixed, close, far, targets =[self.bme.faces[face_ind]], subset = None, max_iters = 100000, min_dist = None) path_elements, self.path = gradient_descent(self.bme, geos, self.target, self.target_loc, epsilon = .0000001)
def mousePlaneIntersection(self, context, event, o, N): scene = context.scene region = context.region rv3d = context.region_data coord = event.mouse_region_x, event.mouse_region_y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) if rv3d.view_perspective != 'ORTHO': return rayPlaneIntersection(ray_origin, view_vector, o, N), view_vector if abs(view_vector.y) == 1: ray_origin.y = 0 elif abs(view_vector.x) == 1: ray_origin.x = 0 elif abs(view_vector.z) == 1: ray_origin.z = 0 return ray_origin, view_vector
def get_ray_origin_target(region, rv3d, screen_coord, ob): ray_vector = region_2d_to_vector_3d(region, rv3d, screen_coord).normalized() ray_origin = region_2d_to_origin_3d(region, rv3d, screen_coord) if not rv3d.is_perspective: # need to back up the ray's origin, because ortho projection has front and back # projection planes at inf bver = '%03d.%03d.%03d' % (bpy.app.version[0],bpy.app.version[1],bpy.app.version[2]) # why does this need to be negated? # but not when ortho front/back view?? if bver < '002.073.000' and abs(ray_vector.y)<1: ray_vector = -ray_vector r0 = get_ray_origin(ray_origin, ray_vector, ob) r1 = get_ray_origin(ray_origin, -ray_vector, ob) ray_origin = r0 ray_target = r1 else: ray_target = get_ray_origin(ray_origin, -ray_vector, ob) return (ray_origin, ray_target)
def click_seed_select(self, context, x, y): region = context.region rv3d = context.region_data coord = x, y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) mx = self.cut_ob.matrix_world imx = mx.inverted() loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target) if face_ind != -1: self.face_seed = face_ind print('face selected!!') return True else: self.face_seed = None print('face not selected') return False
def grab_mouse_move(self,context,x,y): region = context.region rv3d = context.region_data coord = x, y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * 1000) mx = self.cut_ob.matrix_world imx = mx.inverted() if bversion() < '002.077.000': loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target) else: ok, loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target - imx*ray_origin) if face_ind == -1: self.grab_cancel() else: self.pts[self.selected] = mx * loc self.cut_pts[self.selected] = loc self.normals[self.selected] = no self.face_map[self.selected] = face_ind
def Pick(context, event, self, ray_max=10000.0): scene = context.scene region = context.region rv3d = context.region_data coord = event.mouse_region_x, event.mouse_region_y view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) ray_target = ray_origin + (view_vector * ray_max) def obj_ray_cast(obj, matrix): matrix_inv = matrix.inverted() ray_origin_obj = matrix_inv * ray_origin ray_target_obj = matrix_inv * ray_target hit, normal, face_index = obj.ray_cast(ray_origin_obj, ray_target_obj) if face_index != -1: return hit, normal, face_index else: return None, None, None best_length_squared = ray_max * ray_max best_obj = None for obj in self.CList: matrix = obj.matrix_world hit, normal, face_index = obj_ray_cast(obj, matrix) if hit is not None: hit_world = matrix * hit length_squared = (hit_world - ray_origin).length_squared if length_squared < best_length_squared: best_length_squared = length_squared best_obj = obj hits = hit_world ns = normal fs = face_index if best_obj is not None: return hits, ns, fs else: return None, None, None