From 78bf358bf0805f69bc7317c4c5d1e10c0ece4dca Mon Sep 17 00:00:00 2001 From: mano-wii Date: Tue, 2 Apr 2019 20:03:16 -0300 Subject: Remove support for blender2.79 The addon does not work on all OS. And now there is an improved version of it for blender2.8. --- mesh_snap_utilities_line.py | 1191 -------------------- modules/snap_context/__init__.py | 322 ------ modules/snap_context/mesh_drawing.py | 518 --------- modules/snap_context/resources/3D_vert.glsl | 26 - .../snap_context/resources/primitive_id_frag.glsl | 22 - modules/snap_context/utils_projection.py | 212 ---- modules/snap_context/utils_shader.py | 85 -- 7 files changed, 2376 deletions(-) delete mode 100644 mesh_snap_utilities_line.py delete mode 100644 modules/snap_context/__init__.py delete mode 100644 modules/snap_context/mesh_drawing.py delete mode 100644 modules/snap_context/resources/3D_vert.glsl delete mode 100644 modules/snap_context/resources/primitive_id_frag.glsl delete mode 100644 modules/snap_context/utils_projection.py delete mode 100644 modules/snap_context/utils_shader.py diff --git a/mesh_snap_utilities_line.py b/mesh_snap_utilities_line.py deleted file mode 100644 index 8f2f2a94..00000000 --- a/mesh_snap_utilities_line.py +++ /dev/null @@ -1,1191 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# ##### END GPL LICENSE BLOCK ##### - -# Contact for more information about the Addon: -# Email: germano.costa@ig.com.br -# Twitter: wii_mano @mano_wii - - -bl_info = { - "name": "Snap Utilities Line", - "author": "Germano Cavalcante", - "version": (5, 7, 6), - "blender": (2, 75, 0), - "location": "View3D > TOOLS > Snap Utilities > snap utilities", - "description": "Extends Blender Snap controls", - "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Modeling/Snap_Utils_Line", - "category": "Mesh"} - -import bpy -import bgl -import bmesh -from mathutils import Vector -from mathutils.geometry import ( - intersect_point_line, - intersect_line_line, - intersect_line_plane, - intersect_ray_tri - ) -from bpy.types import ( - Operator, - Panel, - AddonPreferences, - ) -from bpy.props import ( - BoolProperty, - FloatProperty, - FloatVectorProperty, - StringProperty, - ) - -##DEBUG = False -##if DEBUG: -## from .snap_framebuffer_debug import screenTexture -## from .snap_context import mesh_drawing - - -def get_units_info(scale, unit_system, separate_units): - if unit_system == 'METRIC': - scale_steps = ((1000, 'km'), (1, 'm'), (1 / 100, 'cm'), - (1 / 1000, 'mm'), (1 / 1000000, '\u00b5m')) - elif unit_system == 'IMPERIAL': - scale_steps = ((5280, 'mi'), (1, '\''), - (1 / 12, '"'), (1 / 12000, 'thou')) - scale /= 0.3048 # BU to feet - else: - scale_steps = ((1, ' BU'),) - separate_units = False - - return (scale, scale_steps, separate_units) - - -def convert_distance(val, units_info, precision=5): - scale, scale_steps, separate_units = units_info - sval = val * scale - idx = 0 - while idx < len(scale_steps) - 1: - if sval >= scale_steps[idx][0]: - break - idx += 1 - factor, suffix = scale_steps[idx] - sval /= factor - if not separate_units or idx == len(scale_steps) - 1: - dval = str(round(sval, precision)) + suffix - else: - ival = int(sval) - dval = str(round(ival, precision)) + suffix - fval = sval - ival - idx += 1 - while idx < len(scale_steps): - fval *= scale_steps[idx - 1][0] / scale_steps[idx][0] - if fval >= 1: - dval += ' ' \ - + ("%.1f" % fval) \ - + scale_steps[idx][1] - break - idx += 1 - - return dval - - -def location_3d_to_region_2d(region, rv3d, coord): - prj = rv3d.perspective_matrix * Vector((coord[0], coord[1], coord[2], 1.0)) - width_half = region.width / 2.0 - height_half = region.height / 2.0 - return Vector((width_half + width_half * (prj.x / prj.w), - height_half + height_half * (prj.y / prj.w), - prj.z / prj.w - )) - - -def out_Location(rv3d, region, orig, vector): - view_matrix = rv3d.view_matrix - v1 = Vector((int(view_matrix[0][0] * 1.5), int(view_matrix[0][1] * 1.5), int(view_matrix[0][2] * 1.5))) - v2 = Vector((int(view_matrix[1][0] * 1.5), int(view_matrix[1][1] * 1.5), int(view_matrix[1][2] * 1.5))) - - hit = intersect_ray_tri(Vector((1, 0, 0)), Vector((0, 1, 0)), Vector(), (vector), (orig), False) - if hit is None: - hit = intersect_ray_tri(v1, v2, Vector(), (vector), (orig), False) - if hit is None: - hit = intersect_ray_tri(v1, v2, Vector(), (-vector), (orig), False) - if hit is None: - hit = Vector() - return hit - - -def get_closest_edge(bm, point, dist): - r_edge = None - for edge in bm.edges: - v1 = edge.verts[0].co - v2 = edge.verts[1].co - # Test the BVH (AABB) first - for i in range(3): - if v1[i] <= v2[i]: - isect = v1[i] - dist <= point[i] <= v2[i] + dist - else: - isect = v2[i] - dist <= point[i] <= v1[i] + dist - - if not isect: - break - else: - ret = intersect_point_line(point, v1, v2) - - if ret[1] < 0.0: - tmp = v1 - elif ret[1] > 1.0: - tmp = v2 - else: - tmp = ret[0] - - new_dist = (point - tmp).length - if new_dist <= dist: - dist = new_dist - r_edge = edge - - return r_edge - - -class SnapCache(): - bvert = None - vco = None - - bedge = None - v0 = None - v1 = None - vmid = None - vperp = None - v2d0 = None - v2d1 = None - v2dmid = None - v2dperp = None - - bm_geom_selected = None - - -def snap_utilities( - sctx, obj, - cache, context, obj_matrix_world, - bm, mcursor, - constrain = None, - previous_vert = None, - increment = 0.0): - - rv3d = context.region_data - region = context.region - scene = context.scene - is_increment = False - r_loc = None - r_type = None - r_len = 0.0 - bm_geom = None - - if cache.bm_geom_selected: - try: - cache.bm_geom_selected.select = False - except ReferenceError as e: - print(e) - - snp_obj, loc, elem = sctx.snap_get(mcursor) - view_vector, orig = sctx.last_ray - - if not snp_obj: - is_increment = True - if constrain: - end = orig + view_vector - t_loc = intersect_line_line(constrain[0], constrain[1], orig, end) - if t_loc is None: - t_loc = constrain - r_loc = t_loc[0] - else: - r_type = 'OUT' - r_loc = out_Location(rv3d, region, orig, view_vector) - - elif snp_obj.data[0] != obj: #OUT - r_loc = loc - - if constrain: - is_increment = False - r_loc = intersect_point_line(r_loc, constrain[0], constrain[1])[0] - if not r_loc: - r_loc = out_Location(rv3d, region, orig, view_vector) - elif len(elem) == 1: - is_increment = False - r_type = 'VERT' - elif len(elem) == 2: - is_increment = True - r_type = 'EDGE' - else: - is_increment = True - r_type = 'FACE' - - elif len(elem) == 1: - r_type = 'VERT' - bm_geom = bm.verts[elem[0]] - - if cache.bvert != bm_geom: - cache.bvert = bm_geom - cache.vco = loc - #cache.v2d = location_3d_to_region_2d(region, rv3d, cache.vco) - - if constrain: - r_loc = intersect_point_line(cache.vco, constrain[0], constrain[1])[0] - else: - r_loc = cache.vco - - elif len(elem) == 2: - v1 = bm.verts[elem[0]] - v2 = bm.verts[elem[1]] - bm_geom = bm.edges.get([v1, v2]) - - if cache.bedge != bm_geom: - cache.bedge = bm_geom - cache.v0 = obj_matrix_world * v1.co - cache.v1 = obj_matrix_world * v2.co - cache.vmid = 0.5 * (cache.v0 + cache.v1) - cache.v2d0 = location_3d_to_region_2d(region, rv3d, cache.v0) - cache.v2d1 = location_3d_to_region_2d(region, rv3d, cache.v1) - cache.v2dmid = location_3d_to_region_2d(region, rv3d, cache.vmid) - - if previous_vert and previous_vert not in {v1, v2}: - pvert_co = obj_matrix_world * previous_vert.co - perp_point = intersect_point_line(pvert_co, cache.v0, cache.v1) - cache.vperp = perp_point[0] - #factor = point_perpendicular[1] - cache.v2dperp = location_3d_to_region_2d(region, rv3d, perp_point[0]) - - #else: cache.v2dperp = None - - if constrain: - t_loc = intersect_line_line(constrain[0], constrain[1], cache.v0, cache.v1) - if t_loc is None: - is_increment = True - end = orig + view_vector - t_loc = intersect_line_line(constrain[0], constrain[1], orig, end) - r_loc = t_loc[0] - - elif cache.v2dperp and\ - abs(cache.v2dperp[0] - mcursor[0]) < 10 and abs(cache.v2dperp[1] - mcursor[1]) < 10: - r_type = 'PERPENDICULAR' - r_loc = cache.vperp - - elif abs(cache.v2dmid[0] - mcursor[0]) < 10 and abs(cache.v2dmid[1] - mcursor[1]) < 10: - r_type = 'CENTER' - r_loc = cache.vmid - - else: - if increment and previous_vert in cache.bedge.verts: - is_increment = True - - r_type = 'EDGE' - r_loc = loc - - elif len(elem) == 3: - is_increment = True - r_type = 'FACE' - tri = [ - bm.verts[elem[0]], - bm.verts[elem[1]], - bm.verts[elem[2]], - ] - - faces = set(tri[0].link_faces).intersection(tri[1].link_faces, tri[2].link_faces) - if len(faces) == 1: - bm_geom = faces.pop() - else: - i = -2 - edge = None - while not edge and i != 1: - edge = bm.edges.get([tri[i], tri[i + 1]]) - i += 1 - if edge: - for l in edge.link_loops: - if l.link_loop_next.vert == tri[i] or l.link_loop_prev.vert == tri[i - 2]: - bm_geom = l.face - break - else: # This should never happen!!!! - raise - bm_geom = faces.pop() - - r_loc = loc - - if constrain: - is_increment = False - r_loc = intersect_point_line(r_loc, constrain[0], constrain[1])[0] - - if previous_vert: - pv_co = obj_matrix_world * previous_vert.co - vec = r_loc - pv_co - if is_increment and increment: - r_len = round((1 / increment) * vec.length) * increment - r_loc = r_len * vec.normalized() + pv_co - else: - r_len = vec.length - - if bm_geom: - bm_geom.select = True - - cache.bm_geom_selected = bm_geom - - return r_loc, r_type, bm_geom, r_len - - -def get_loose_linked_edges(bmvert): - linked = [e for e in bmvert.link_edges if not e.link_faces] - for e in linked: - linked += [le for v in e.verts if not v.link_faces for le in v.link_edges if le not in linked] - return linked - - -def draw_line(self, obj, bm, bm_geom, location): - split_faces = set() - - drawing_is_dirt = False - update_edit_mesh = False - tessface = False - - if bm_geom is None: - vert = bm.verts.new(location) - self.list_verts.append(vert) - - elif isinstance(bm_geom, bmesh.types.BMVert): - if (bm_geom.co - location).length_squared < .001: - if self.list_verts == [] or self.list_verts[-1] != bm_geom: - self.list_verts.append(bm_geom) - else: - vert = bm.verts.new(location) - self.list_verts.append(vert) - drawing_is_dirt = True - - elif isinstance(bm_geom, bmesh.types.BMEdge): - self.list_edges.append(bm_geom) - ret = intersect_point_line(location, bm_geom.verts[0].co, bm_geom.verts[1].co) - - if (ret[0] - location).length_squared < .001: - if ret[1] == 0.0: - vert = bm_geom.verts[0] - elif ret[1] == 1.0: - vert = bm_geom.verts[1] - else: - edge, vert = bmesh.utils.edge_split(bm_geom, bm_geom.verts[0], ret[1]) - drawing_is_dirt = True - self.list_verts.append(vert) - # self.list_edges.append(edge) - - else: # constrain point is near - vert = bm.verts.new(location) - self.list_verts.append(vert) - drawing_is_dirt = True - - elif isinstance(bm_geom, bmesh.types.BMFace): - split_faces.add(bm_geom) - vert = bm.verts.new(location) - self.list_verts.append(vert) - drawing_is_dirt = True - - # draw, split and create face - if len(self.list_verts) >= 2: - v1, v2 = self.list_verts[-2:] - # v2_link_verts = [x for y in [a.verts for a in v2.link_edges] for x in y if x != v2] - edge = bm.edges.get([v1, v2]) - if edge: - self.list_edges.append(edge) - - else: # if v1 not in v2_link_verts: - if not v2.link_edges: - edge = bm.edges.new([v1, v2]) - self.list_edges.append(edge) - drawing_is_dirt = True - else: # split face - v1_link_faces = v1.link_faces - v2_link_faces = v2.link_faces - if v1_link_faces and v2_link_faces: - split_faces.update(set(v1_link_faces).intersection(v2_link_faces)) - - else: - if v1_link_faces: - faces = v1_link_faces - co2 = v2.co.copy() - else: - faces = v2_link_faces - co2 = v1.co.copy() - - for face in faces: - if bmesh.geometry.intersect_face_point(face, co2): - co = co2 - face.calc_center_median() - if co.dot(face.normal) < 0.001: - split_faces.add(face) - - if split_faces: - edge = bm.edges.new([v1, v2]) - self.list_edges.append(edge) - ed_list = get_loose_linked_edges(v2) - for face in split_faces: - facesp = bmesh.utils.face_split_edgenet(face, ed_list) - del split_faces - update_edit_mesh = True - tessface = True - else: - if self.intersect: - facesp = bmesh.ops.connect_vert_pair(bm, verts=[v1, v2], verts_exclude=bm.verts) - # print(facesp) - if not self.intersect or not facesp['edges']: - edge = bm.edges.new([v1, v2]) - self.list_edges.append(edge) - drawing_is_dirt = True - else: - for edge in facesp['edges']: - self.list_edges.append(edge) - update_edit_mesh = True - tessface = True - - # create face - if self.create_face: - ed_list = set(self.list_edges) - for edge in v2.link_edges: - for vert in edge.verts: - if vert != v2 and vert in self.list_verts: - ed_list.add(edge) - break - else: - continue - # Inner loop had a break, break the outer - break - - ed_list.update(get_loose_linked_edges(v2)) - - bmesh.ops.edgenet_fill(bm, edges=list(ed_list)) - update_edit_mesh = True - tessface = True - # print('face created') - if update_edit_mesh: - bmesh.update_edit_mesh(obj.data, tessface = tessface) - self.sctx.update_drawn_snap_object(self.snap_obj) - #bm.verts.index_update() - elif drawing_is_dirt: - self.obj.update_from_editmode() - self.sctx.update_drawn_snap_object(self.snap_obj) - - return [obj.matrix_world * v.co for v in self.list_verts] - - -class NavigationKeys: - def __init__(self, context): - # TO DO: - # 'View Orbit', 'View Pan', 'NDOF Orbit View', 'NDOF Pan View' - self._rotate = set() - self._move = set() - self._zoom = set() - for key in context.window_manager.keyconfigs.user.keymaps['3D View'].keymap_items: - if key.idname == 'view3d.rotate': - #self.keys_rotate[key.id]={'Alt': key.alt, 'Ctrl': key.ctrl, 'Shift':key.shift, 'Type':key.type, 'Value':key.value} - self._rotate.add((key.alt, key.ctrl, key.shift, key.type, key.value)) - if key.idname == 'view3d.move': - self._move.add((key.alt, key.ctrl, key.shift, key.type, key.value)) - if key.idname == 'view3d.zoom': - if key.type == 'WHEELINMOUSE': - self._zoom.add((key.alt, key.ctrl, key.shift, 'WHEELUPMOUSE', key.value, key.properties.delta)) - elif key.type == 'WHEELOUTMOUSE': - self._zoom.add((key.alt, key.ctrl, key.shift, 'WHEELDOWNMOUSE', key.value, key.properties.delta)) - else: - self._zoom.add((key.alt, key.ctrl, key.shift, key.type, key.value, key.properties.delta)) - - -class CharMap: - ascii = { - ".", ",", "-", "+", "1", "2", "3", - "4", "5", "6", "7", "8", "9", "0", - "c", "m", "d", "k", "h", "a", - " ", "/", "*", "'", "\"" - # "=" - } - type = { - 'BACK_SPACE', 'DEL', - 'LEFT_ARROW', 'RIGHT_ARROW' - } - - @staticmethod - def modal(self, context, event): - c = event.ascii - if c: - if c == ",": - c = "." - self.length_entered = self.length_entered[:self.line_pos] + c + self.length_entered[self.line_pos:] - self.line_pos += 1 - if self.length_entered: - if event.type == 'BACK_SPACE': - self.length_entered = self.length_entered[:self.line_pos - 1] + self.length_entered[self.line_pos:] - self.line_pos -= 1 - - elif event.type == 'DEL': - self.length_entered = self.length_entered[:self.line_pos] + self.length_entered[self.line_pos + 1:] - - elif event.type == 'LEFT_ARROW': - self.line_pos = (self.line_pos - 1) % (len(self.length_entered) + 1) - - elif event.type == 'RIGHT_ARROW': - self.line_pos = (self.line_pos + 1) % (len(self.length_entered) + 1) - - -class SnapUtilitiesLine(Operator): - bl_idname = "mesh.snap_utilities_line" - bl_label = "Line Tool" - bl_description = "Draw edges. Connect them to split faces" - bl_options = {'REGISTER', 'UNDO'} - - constrain_keys = { - 'X': Vector((1, 0, 0)), - 'Y': Vector((0, 1, 0)), - 'Z': Vector((0, 0, 1)), - 'RIGHT_SHIFT': 'shift', - 'LEFT_SHIFT': 'shift', - } - - @classmethod - def poll(cls, context): - preferences = context.user_preferences.addons[__name__].preferences - return (context.mode in {'EDIT_MESH', 'OBJECT'} and - preferences.create_new_obj or - (context.object is not None and - context.object.type == 'MESH')) - - - def draw_callback_px(self, context): - # draw 3d point OpenGL in the 3D View - bgl.glEnable(bgl.GL_BLEND) - bgl.glDisable(bgl.GL_DEPTH_TEST) - # bgl.glPushMatrix() - # bgl.glMultMatrixf(self.obj_glmatrix) - -## if DEBUG: -## mesh_drawing._store_current_shader_state(mesh_drawing.PreviousGLState) -## self.screen.Draw(self.sctx._texture) -## mesh_drawing._restore_shader_state(mesh_drawing.PreviousGLState) - - if self.vector_constrain: - vc = self.vector_constrain - if hasattr(self, 'preloc') and self.type in {'VERT', 'FACE'}: - bgl.glColor4f(1.0, 1.0, 1.0, 0.5) - bgl.glPointSize(5) - bgl.glBegin(bgl.GL_POINTS) - bgl.glVertex3f(*self.preloc) - bgl.glEnd() - if vc[2] == 'X': - Color4f = (self.axis_x_color + (1.0,)) - elif vc[2] == 'Y': - Color4f = (self.axis_y_color + (1.0,)) - elif vc[2] == 'Z': - Color4f = (self.axis_z_color + (1.0,)) - else: - Color4f = self.constrain_shift_color - else: - if self.type == 'OUT': - Color4f = self.out_color - elif self.type == 'FACE': - Color4f = self.face_color - elif self.type == 'EDGE': - Color4f = self.edge_color - elif self.type == 'VERT': - Color4f = self.vert_color - elif self.type == 'CENTER': - Color4f = self.center_color - elif self.type == 'PERPENDICULAR': - Color4f = self.perpendicular_color - else: # self.type == None - Color4f = self.out_color - - bgl.glColor4f(*Color4f) - bgl.glPointSize(10) - bgl.glBegin(bgl.GL_POINTS) - bgl.glVertex3f(*self.location) - bgl.glEnd() - - # draw 3d line OpenGL in the 3D View - bgl.glEnable(bgl.GL_DEPTH_TEST) - bgl.glDepthRange(0, 0.9999) - bgl.glColor4f(1.0, 0.8, 0.0, 1.0) - bgl.glLineWidth(2) - bgl.glEnable(bgl.GL_LINE_STIPPLE) - bgl.glBegin(bgl.GL_LINE_STRIP) - for vert_co in self.list_verts_co: - bgl.glVertex3f(*vert_co) - bgl.glVertex3f(*self.location) - bgl.glEnd() - - # restore opengl defaults - # bgl.glPopMatrix() - bgl.glDepthRange(0, 1) - bgl.glPointSize(1) - bgl.glLineWidth(1) - bgl.glDisable(bgl.GL_BLEND) - bgl.glDisable(bgl.GL_LINE_STIPPLE) - bgl.glColor4f(0.0, 0.0, 0.0, 1.0) - - - def modal_navigation(self, context, event): - evkey = (event.alt, event.ctrl, event.shift, event.type, event.value) - if evkey in self.navigation_keys._rotate: - bpy.ops.view3d.rotate('INVOKE_DEFAULT') - return True - elif evkey in self.navigation_keys._move: - if event.shift and self.vector_constrain and \ - self.vector_constrain[2] in {'RIGHT_SHIFT', 'LEFT_SHIFT', 'shift'}: - self.vector_constrain = None - bpy.ops.view3d.move('INVOKE_DEFAULT') - return True - else: - for key in self.navigation_keys._zoom: - if evkey == key[0:5]: - if True: # TODO: Use Zoom to mouse position - v3d = context.space_data - dist_range = (v3d.clip_start, v3d.clip_end) - rv3d = context.region_data - if (key[5] < 0 and rv3d.view_distance < dist_range[1]) or\ - (key[5] > 0 and rv3d.view_distance > dist_range[0]): - rv3d.view_location += key[5] * (self.location - rv3d.view_location) / 6 - rv3d.view_distance -= key[5] * rv3d.view_distance / 6 - else: - bpy.ops.view3d.zoom('INVOKE_DEFAULT', delta = key[5]) - return True - #break - - return False - - - def modal(self, context, event): - if self.modal_navigation(context, event): - return {'RUNNING_MODAL'} - - context.area.tag_redraw() - - if event.ctrl and event.type == 'Z' and event.value == 'PRESS': - bpy.ops.ed.undo() - self.vector_constrain = None - self.list_verts_co = [] - self.list_verts = [] - self.list_edges = [] - self.obj = bpy.context.active_object - self.obj_matrix = self.obj.matrix_world.copy() - self.bm = bmesh.from_edit_mesh(self.obj.data) - self.sctx.update_drawn_snap_object(self.snap_obj) - return {'RUNNING_MODAL'} - - if event.type == 'MOUSEMOVE' or self.bool_update: - if self.rv3d.view_matrix != self.rotMat: - self.rotMat = self.rv3d.view_matrix.copy() - self.bool_update = True - self.cache.bedge = None - else: - self.bool_update = False - - mval = Vector((event.mouse_region_x, event.mouse_region_y)) - - self.location, self.type, self.geom, self.len = snap_utilities( - self.sctx, self.obj, self.cache, context, self.obj_matrix, - self.bm, mval, - constrain = self.vector_constrain, - previous_vert = (self.list_verts[-1] if self.list_verts else None), - increment = self.incremental - ) - if self.snap_to_grid and self.type == 'OUT': - loc = self.location / self.rd - self.location = Vector((round(loc.x), - round(loc.y), - round(loc.z))) * self.rd - - if self.keyf8 and self.list_verts_co: - lloc = self.list_verts_co[-1] - view_vec, orig = self.sctx.last_ray - location = intersect_point_line(lloc, orig, (orig + view_vec)) - vec = (location[0] - lloc) - ax, ay, az = abs(vec.x), abs(vec.y), abs(vec.z) - vec.x = ax > ay > az or ax > az > ay - vec.y = ay > ax > az or ay > az > ax - vec.z = az > ay > ax or az > ax > ay - if vec == Vector(): - self.vector_constrain = None - else: - vc = lloc + vec - try: - if vc != self.vector_constrain[1]: - type = 'X' if vec.x else 'Y' if vec.y else 'Z' if vec.z else 'shift' - self.vector_constrain = [lloc, vc, type] - except: - type = 'X' if vec.x else 'Y' if vec.y else 'Z' if vec.z else 'shift' - self.vector_constrain = [lloc, vc, type] - - if event.value == 'PRESS': - if self.list_verts_co and (event.ascii in CharMap.ascii or event.type in CharMap.type): - CharMap.modal(self, context, event) - - elif event.type in self.constrain_keys: - self.bool_update = True - if self.vector_constrain and self.vector_constrain[2] == event.type: - self.vector_constrain = () - - else: - if event.shift: - if isinstance(self.geom, bmesh.types.BMEdge): - if self.list_verts: - loc = self.list_verts_co[-1] - self.vector_constrain = (loc, loc + self.geom.verts[1].co - - self.geom.verts[0].co, event.type) - else: - self.vector_constrain = [self.obj_matrix * v.co for - v in self.geom.verts] + [event.type] - else: - if self.list_verts: - loc = self.list_verts_co[-1] - else: - loc = self.location - self.vector_constrain = [loc, loc + self.constrain_keys[event.type]] + [event.type] - - elif event.type == 'LEFTMOUSE': - point = self.obj_matinv * self.location - # with constraint the intersection can be in a different element of the selected one - if self.vector_constrain and self.geom: - geom2 = get_closest_edge(self.bm, point, 0.001) - else: - geom2 = self.geom - - self.vector_constrain = None - self.list_verts_co = draw_line(self, self.obj, self.bm, geom2, point) - bpy.ops.ed.undo_push(message="Undo draw line*") - - elif event.type == 'TAB': - self.keytab = self.keytab is False - if self.keytab: - self.sctx.set_snap_mode(False, False, True) - context.tool_settings.mesh_select_mode = (False, False, True) - else: - self.sctx.set_snap_mode(True, True, True) - context.tool_settings.mesh_select_mode = (True, True, True) - - elif event.type == 'F8': - self.vector_constrain = None - self.keyf8 = self.keyf8 is False - - elif event.value == 'RELEASE': - if event.type in {'RET', 'NUMPAD_ENTER'}: - if self.length_entered != "" and self.list_verts_co: - try: - text_value = bpy.utils.units.to_value(self.unit_system, 'LENGTH', self.length_entered) - vector = (self.location - self.list_verts_co[-1]).normalized() - location = (self.list_verts_co[-1] + (vector * text_value)) - G_location = self.obj_matinv * location - self.list_verts_co = draw_line(self, self.obj, self.bm, self.geom, G_location) - self.length_entered = "" - self.vector_constrain = None - - except: # ValueError: - self.report({'INFO'}, "Operation not supported yet") - - elif event.type in {'RIGHTMOUSE', 'ESC'}: - if self.list_verts_co == [] or event.type == 'ESC': - del self.bm - del self.list_edges - del self.list_verts - del self.list_verts_co - - bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') - context.area.header_text_set("") - self.sctx.free() - - #restore initial state - context.user_preferences.view.use_rotate_around_active = self.use_rotate_around_active - context.tool_settings.mesh_select_mode = self.select_mode - if not self.is_editmode: - bpy.ops.object.editmode_toggle() - - return {'FINISHED'} - else: - self.vector_constrain = None - self.list_edges = [] - self.list_verts = [] - self.list_verts_co = [] - - a = "" - if self.list_verts_co: - if self.length_entered: - pos = self.line_pos - a = 'length: ' + self.length_entered[:pos] + '|' + self.length_entered[pos:] - else: - length = self.len - length = convert_distance(length, self.uinfo) - a = 'length: ' + length - - context.area.header_text_set( - "hit: %.3f %.3f %.3f %s" % (self.location[0], - self.location[1], self.location[2], a) - ) - - return {'RUNNING_MODAL'} - - def invoke(self, context, event): - if context.space_data.type == 'VIEW_3D': - # print('name', __name__, __package__) - preferences = context.user_preferences.addons[__name__].preferences - - #Store the preferences that will be used in modal - self.intersect = preferences.intersect - self.create_face = preferences.create_face - self.outer_verts = preferences.outer_verts - self.snap_to_grid = preferences.increments_grid - - self.out_color = preferences.out_color - self.face_color = preferences.face_color - self.edge_color = preferences.edge_color - self.vert_color = preferences.vert_color - self.center_color = preferences.center_color - self.perpendicular_color = preferences.perpendicular_color - self.constrain_shift_color = preferences.constrain_shift_color - - self.axis_x_color = tuple(context.user_preferences.themes[0].user_interface.axis_x) - self.axis_y_color = tuple(context.user_preferences.themes[0].user_interface.axis_y) - self.axis_z_color = tuple(context.user_preferences.themes[0].user_interface.axis_z) - - if context.mode == 'OBJECT' and \ - (preferences.create_new_obj or context.object is None or context.object.type != 'MESH'): - - mesh = bpy.data.meshes.new("") - obj = bpy.data.objects.new("", mesh) - context.scene.objects.link(obj) - context.scene.objects.active = obj - - #Store current state - self.is_editmode = context.object.data.is_editmode - self.use_rotate_around_active = context.user_preferences.view.use_rotate_around_active - self.select_mode = context.tool_settings.mesh_select_mode[:] - - #Modify the current state - bpy.ops.object.mode_set(mode='EDIT') - bpy.ops.mesh.select_all(action='DESELECT') - context.user_preferences.view.use_rotate_around_active = True - context.tool_settings.mesh_select_mode = (True, True, True) - context.space_data.use_occlude_geometry = True - - #Configure the unit of measure - scale = context.scene.unit_settings.scale_length - self.unit_system = context.scene.unit_settings.system - separate_units = context.scene.unit_settings.use_separate - self.uinfo = get_units_info(scale, self.unit_system, separate_units) - - scale /= context.space_data.grid_scale * preferences.relative_scale - self.rd = bpy.utils.units.to_value(self.unit_system, 'LENGTH', str(1 / scale)) - - self.incremental = bpy.utils.units.to_value(self.unit_system, 'LENGTH', str(preferences.incremental)) - - #Store values from 3d view context - self.rv3d = context.region_data - self.rotMat = self.rv3d.view_matrix.copy() - self.obj = bpy.context.active_object - self.obj_matrix = self.obj.matrix_world.copy() - self.obj_matinv = self.obj_matrix.inverted() - # self.obj_glmatrix = bgl.Buffer(bgl.GL_FLOAT, [4, 4], self.obj_matrix.transposed()) - self.bm = bmesh.from_edit_mesh(self.obj.data) #remove at end - self.cache = SnapCache() - - #init these variables to avoid errors - self.prevloc = Vector() - self.location = Vector() - self.list_verts = [] - self.list_edges = [] - self.list_verts_co = [] - self.bool_update = False - self.vector_constrain = () - self.navigation_keys = NavigationKeys(context) - self.type = 'OUT' - self.len = 0 - self.length_entered = "" - self.line_pos = 0 - self.bm_geom_selected = None - - #Init event variables - self.keytab = False - self.keyf8 = False - - #Init Snap Context - from snap_context import SnapContext - - self.sctx = SnapContext(context.region, context.space_data) - self.sctx.set_pixel_dist(12) - self.sctx.use_clip_planes(True) - - act_base = context.active_base - - if self.outer_verts: - for base in context.visible_bases: - if base != act_base: - self.sctx.add_obj(base.object, base.object.matrix_world) - - self.snap_obj = self.sctx.add_obj(act_base.object, act_base.object.matrix_world) - - self.snap_face = context.space_data.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} - self.sctx.set_snap_mode(True, True, self.snap_face) - - #modals - self._handle = bpy.types.SpaceView3D.draw_handler_add(self.draw_callback_px, (context,), 'WINDOW', 'POST_VIEW') - context.window_manager.modal_handler_add(self) - - return {'RUNNING_MODAL'} - else: - self.report({'WARNING'}, "Active space must be a View3d") - return {'CANCELLED'} - - -class PanelSnapUtilities(Panel): - bl_space_type = "VIEW_3D" - bl_region_type = "TOOLS" - bl_category = "Snap Utilities" - bl_label = "Snap Utilities" - - @classmethod - def poll(cls, context): - preferences = context.user_preferences.addons[__name__].preferences - return (context.mode in {'EDIT_MESH', 'OBJECT'} and - preferences.create_new_obj or - (context.object is not None and - context.object.type == 'MESH')) - - def draw(self, context): - layout = self.layout - TheCol = layout.column(align=True) - TheCol.operator("mesh.snap_utilities_line", text="Line", icon="GREASEPENCIL") - - addon_prefs = context.user_preferences.addons[__name__].preferences - expand = addon_prefs.expand_snap_settings - icon = "TRIA_DOWN" if expand else "TRIA_RIGHT" - - box = layout.box() - box.prop(addon_prefs, "expand_snap_settings", icon=icon, - text="Settings:", emboss=False) - if expand: - box.prop(addon_prefs, "outer_verts") - box.prop(addon_prefs, "incremental") - box.prop(addon_prefs, "increments_grid") - if addon_prefs.increments_grid: - box.prop(addon_prefs, "relative_scale") - box.label(text="Line Tool:") - box.prop(addon_prefs, "intersect") - box.prop(addon_prefs, "create_face") - box.prop(addon_prefs, "create_new_obj") - - -# Add-ons Preferences Update Panel - -# Define Panel classes for updating -panels = ( - PanelSnapUtilities, - ) - - -def update_panel(self, context): - message = "Snap Utilities Line: Updating Panel locations has failed" - addon_prefs = context.user_preferences.addons[__name__].preferences - try: - for panel in panels: - if addon_prefs.category != panel.bl_category: - if "bl_rna" in panel.__dict__: - bpy.utils.unregister_class(panel) - - panel.bl_category = addon_prefs.category - bpy.utils.register_class(panel) - - except Exception as e: - print("\n[{}]\n{}\n\nError:\n{}".format(__name__, message, e)) - pass - - -class SnapAddonPreferences(AddonPreferences): - # this must match the addon name, use '__package__' - # when defining this in a submodule of a python package. - bl_idname = __name__ - - intersect = BoolProperty( - name="Intersect", - description="Intersects created line with the existing edges, " - "even if the lines do not intersect", - default=True - ) - create_new_obj = BoolProperty( - name="Create a new object", - description="If have not a active object, or the active object " - "is not in edit mode, it creates a new object", - default=False - ) - create_face = BoolProperty( - name="Create faces", - description="Create faces defined by enclosed edges", - default=False - ) - outer_verts = BoolProperty( - name="Snap to outer vertices", - description="The vertices of the objects are not activated also snapped", - default=True - ) - expand_snap_settings = BoolProperty( - name="Expand", - description="Expand, to display the settings", - default=False - ) - expand_color_settings = BoolProperty( - name="Color Settings", - description="Expand, to display the color settings", - default=False - ) - increments_grid = BoolProperty( - name="Increments of Grid", - description="Snap to increments of grid", - default=False - ) - category = StringProperty( - name="Category", - description="Choose a name for the category of the panel", - default="Snap Utilities", - update=update_panel - ) - incremental = FloatProperty( - name="Incremental", - description="Snap in defined increments", - default=0, - min=0, - step=1, - precision=3 - ) - relative_scale = FloatProperty( - name="Relative Scale", - description="Value that divides the global scale", - default=1, - min=0, - step=1, - precision=3 - ) - out_color = FloatVectorProperty( - name="OUT", - default=(0.0, 0.0, 0.0, 0.5), - size=4, - subtype="COLOR", - min=0, max=1 - ) - face_color = FloatVectorProperty( - name="FACE", - default=(1.0, 0.8, 0.0, 1.0), - size=4, - subtype="COLOR", - min=0, max=1 - ) - edge_color = FloatVectorProperty( - name="EDGE", - default=(0.0, 0.8, 1.0, 1.0), - size=4, - subtype="COLOR", - min=0, max=1 - ) - vert_color = FloatVectorProperty( - name="VERT", - default=(1.0, 0.5, 0.0, 1.0), - size=4, - subtype="COLOR", - min=0, max=1 - ) - center_color = FloatVectorProperty( - name="CENTER", - default=(1.0, 0.0, 1.0, 1.0), - size=4, - subtype="COLOR", - min=0, max=1 - ) - perpendicular_color = FloatVectorProperty( - name="PERPENDICULAR", - default=(0.1, 0.5, 0.5, 1.0), - size=4, - subtype="COLOR", - min=0, max=1 - ) - constrain_shift_color = FloatVectorProperty( - name="SHIFT CONSTRAIN", - default=(0.8, 0.5, 0.4, 1.0), - size=4, - subtype="COLOR", - min=0, max=1 - ) - - def draw(self, context): - layout = self.layout - icon = "TRIA_DOWN" if self.expand_color_settings else "TRIA_RIGHT" - - box = layout.box() - box.prop(self, "expand_color_settings", icon=icon, toggle=True, emboss=False) - if self.expand_color_settings: - split = box.split() - - col = split.column() - col.prop(self, "out_color") - col.prop(self, "constrain_shift_color") - col = split.column() - col.prop(self, "face_color") - col.prop(self, "center_color") - col = split.column() - col.prop(self, "edge_color") - col.prop(self, "perpendicular_color") - col = split.column() - col.prop(self, "vert_color") - - row = layout.row() - - col = row.column(align=True) - box = col.box() - box.label(text="Snap Items:") - box.prop(self, "incremental") - box.prop(self, "outer_verts") - box.prop(self, "increments_grid") - if self.increments_grid: - box.prop(self, "relative_scale") - else: - box.separator() - box.separator() - - col = row.column(align=True) - box = col.box() - box.label(text="Line Tool:") - box.prop(self, "intersect") - box.prop(self, "create_face") - box.prop(self, "create_new_obj") - box.separator() - box.separator() - - row = layout.row() - col = row.column() - col.label(text="Tab Category:") - col.prop(self, "category", text="") - - -def register(): - bpy.utils.register_class(SnapAddonPreferences) - bpy.utils.register_class(SnapUtilitiesLine) - bpy.utils.register_class(PanelSnapUtilities) - update_panel(None, bpy.context) - - -def unregister(): - bpy.utils.unregister_class(PanelSnapUtilities) - bpy.utils.unregister_class(SnapUtilitiesLine) - bpy.utils.unregister_class(SnapAddonPreferences) - - -if __name__ == "__main__": - __name__ = "mesh_snap_utilities_line" - register() diff --git a/modules/snap_context/__init__.py b/modules/snap_context/__init__.py deleted file mode 100644 index 77e84726..00000000 --- a/modules/snap_context/__init__.py +++ /dev/null @@ -1,322 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# ##### END GPL LICENSE BLOCK ##### - -__all__ = ( - "SnapContext", - ) - -import bgl -from mathutils import Vector - -VERT = 1 -EDGE = 2 -FACE = 4 - - -class _Internal: - from .mesh_drawing import ( - gpu_Indices_enable_state, - gpu_Indices_restore_state, - gpu_Indices_use_clip_planes, - gpu_Indices_set_ProjectionMatrix, - ) - - from .utils_projection import ( - region_2d_to_orig_and_view_vector, - intersect_boundbox_threshold, - intersect_ray_segment_fac, - project_co_v3, - ) - - from mathutils.geometry import intersect_line_plane - - -class _SnapObjectData(): - __slots__ = ('data', 'mat') - def __init__(self, data, omat): - self.data = data - self.mat = omat - - -class SnapContext(): - """ - Initializes the snap context with the region and space where the snap objects will be added. - - .. note:: - After the context has been created, add the objects with the `add_obj` method. - - :arg region: region of the 3D viewport, typically bpy.context.region. - :type region: :class:`bpy.types.Region` - :arg space: 3D region data, typically bpy.context.space_data. - :type space: :class:`bpy.types.SpaceView3D` - """ - - def __init__(self, region, space): - import gpu - import ctypes - - self.freed = False - self.snap_objects = [] - self.drawn_count = 0 - self._offset_cur = 1 # Starts with index 1 - self.region = region - self.rv3d = space.region_3d - - if self.rv3d.is_perspective: - self.depth_range = Vector((space.clip_start, space.clip_end)) - else: - self.depth_range = Vector((-space.clip_end, space.clip_end)) - - self.proj_mat = None - self.mval = Vector((0, 0)) - self._snap_mode = VERT | EDGE | FACE - - self.set_pixel_dist(12) - - self._offscreen = gpu.offscreen.new(self.region.width, self.region.height) - - self._texture = self._offscreen.color_texture - bgl.glBindTexture(bgl.GL_TEXTURE_2D, self._texture) - - NULL = bgl.Buffer(bgl.GL_INT, 1, (ctypes.c_int32 * 1).from_address(0)) - bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_R32UI, self.region.width, self.region.height, 0, bgl.GL_RED_INTEGER, bgl.GL_UNSIGNED_INT, NULL) - del NULL - - bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_NEAREST) - bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_NEAREST) - bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0) - - self.winsize = Vector((self._offscreen.width, self._offscreen.height)) - - ## PRIVATE ## - - def _get_snap_obj_by_index(self, index): - for snap_obj in self.snap_objects[:self.drawn_count]: - data = snap_obj.data[1] - if index < data.first_index + data.get_tot_elems(): - return snap_obj - return None - - def _get_nearest_index(self): - loc = [self._dist_px, self._dist_px] - d = 1 - m = self.threshold - max = 2 * m - 1 - offset = 1 - last_snap_obj = None - r_value = 0 - while m < max: - for i in range(2): - while 2 * loc[i] * d < m: - value = int(self._snap_buffer[loc[0]][loc[1]]) - loc[i] += d - if value >= offset: - r_value = value - snap_obj = self._get_snap_obj_by_index(r_value) - - if self._snap_mode & FACE and self._snap_mode & (VERT | EDGE) and last_snap_obj != snap_obj: - data = snap_obj.data[1] - offset = data.first_index + data.num_tris - last_snap_obj = snap_obj - continue - return snap_obj, r_value - d = -d - m += 4 * self._dist_px * d + 1 - - return last_snap_obj, r_value - - def _get_loc(self, snap_obj, index): - index -= snap_obj.data[1].first_index - gpu_data = snap_obj.data[1] - - if gpu_data.draw_tris: - if index < snap_obj.data[1].num_tris: - tri_verts = gpu_data.get_tri_verts(index) - tri_co = [snap_obj.mat * Vector(v) for v in gpu_data.get_tri_co(index)] - nor = (tri_co[1] - tri_co[0]).cross(tri_co[2] - tri_co[0]) - return _Internal.intersect_line_plane(self.last_ray[1], self.last_ray[1] + self.last_ray[0], tri_co[0], nor), tri_verts - - index -= gpu_data.num_tris - - if gpu_data.draw_edges: - if index < snap_obj.data[1].num_edges: - edge_verts = gpu_data.get_edge_verts(index) - edge_co = [snap_obj.mat * Vector(v) for v in gpu_data.get_edge_co(index)] - fac = _Internal.intersect_ray_segment_fac(*edge_co, *self.last_ray) - - if (self._snap_mode) & VERT and (fac < 0.25 or fac > 0.75): - co = edge_co[0] if fac < 0.5 else edge_co[1] - proj_co = _Internal.project_co_v3(self, co) - dist = self.mval - proj_co - if abs(dist.x) < self._dist_px and abs(dist.y) < self._dist_px: - return co, (edge_verts[0] if fac < 0.5 else edge_verts[1],) - - if fac <= 0.0: - co = edge_co[0] - elif fac >= 1.0: - co = edge_co[1] - else: - co = edge_co[0] + fac * (edge_co[1] - edge_co[0]) - - return co, edge_verts - - index -= gpu_data.num_edges - - if gpu_data.draw_verts: - if index < snap_obj.data[1].num_verts: - return snap_obj.mat * Vector(gpu_data.get_loosevert_co(index)), (gpu_data.get_loosevert_index(index),) - - return None, None - - - def _get_snap_obj_by_obj(self, obj): - for snap_obj in self.snap_objects: - if obj == snap_obj.data[0]: - return snap_obj - - def __del__(self): - if not self.freed: - self._offscreen.free() - # Some objects may still be being referenced - for snap_obj in self.snap_objects: - del snap_obj.data - del snap_obj.mat - del snap_obj - del self.snap_objects - - ## PUBLIC ## - - def update_all(self): - self.drawn_count = 0 - self._offset_cur = 1 - - bgl.glClearColor(0.0, 0.0, 0.0, 0.0) - bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT) - - def update_drawn_snap_object(self, snap_obj): - if len(snap_obj.data) > 1: - del snap_obj.data[1:] - #self.update_all() - # Update on next snap_get call # - self.proj_mat = None - - def use_clip_planes(self, value): - _Internal.gpu_Indices_use_clip_planes(self.rv3d, value) - - def set_pixel_dist(self, dist_px): - self._dist_px = int(dist_px) - self._dist_px_sq = self._dist_px ** 2 - self.threshold = 2 * self._dist_px + 1 - self._snap_buffer = bgl.Buffer(bgl.GL_FLOAT, (self.threshold, self.threshold)) - - def set_snap_mode(self, snap_to_vert, snap_to_edge, snap_to_face): - snap_mode = 0 - if snap_to_vert: - snap_mode |= VERT - if snap_to_edge: - snap_mode |= EDGE - if snap_to_face: - snap_mode |= FACE - - if snap_mode != self._snap_mode: - self._snap_mode = snap_mode - self.update_all() - - def add_obj(self, obj, matrix): - matrix = matrix.copy() - snap_obj = self._get_snap_obj_by_obj(obj) - if not snap_obj: - self.snap_objects.append(_SnapObjectData([obj], matrix)) - else: - self.snap_objects.append(_SnapObjectData(snap_obj.data, matrix)) - - return self.snap_objects[-1] - - def get_ray(self, mval): - self.last_ray = _Internal.region_2d_to_orig_and_view_vector(self.region, self.rv3d, mval) - return self.last_ray - - def snap_get(self, mval): - ret = None, None - self.mval[:] = mval - snap_vert = self._snap_mode & VERT != 0 - snap_edge = self._snap_mode & EDGE != 0 - snap_face = self._snap_mode & FACE != 0 - - _Internal.gpu_Indices_enable_state() - self._offscreen.bind() - - #bgl.glDisable(bgl.GL_DITHER) # dithering and AA break color coding, so disable # - #multisample_enabled = bgl.glIsEnabled(bgl.GL_MULTISAMPLE) - #bgl.glDisable(bgl.GL_MULTISAMPLE) - bgl.glEnable(bgl.GL_DEPTH_TEST) - - proj_mat = self.rv3d.perspective_matrix.copy() - if self.proj_mat != proj_mat: - self.proj_mat = proj_mat - _Internal.gpu_Indices_set_ProjectionMatrix(self.proj_mat) - self.update_all() - - ray_dir, ray_orig = self.get_ray(mval) - for i, snap_obj in enumerate(self.snap_objects[self.drawn_count:], self.drawn_count): - obj = snap_obj.data[0] - bbmin = Vector(obj.bound_box[0]) - bbmax = Vector(obj.bound_box[6]) - - if bbmin != bbmax: - MVP = proj_mat * snap_obj.mat - mat_inv = snap_obj.mat.inverted() - ray_orig_local = mat_inv * ray_orig - ray_dir_local = mat_inv.to_3x3() * ray_dir - in_threshold = _Internal.intersect_boundbox_threshold(self, MVP, ray_orig_local, ray_dir_local, bbmin, bbmax) - else: - proj_co = _Internal.project_co_v3(self, snap_obj.mat.translation) - dist = self.mval - proj_co - in_threshold = abs(dist.x) < self._dist_px and abs(dist.y) < self._dist_px - #snap_obj.data[1] = primitive_point - - if in_threshold: - if len(snap_obj.data) == 1: - from .mesh_drawing import GPU_Indices_Mesh - snap_obj.data.append(GPU_Indices_Mesh(obj, snap_face, snap_edge, snap_vert)) - snap_obj.data[1].set_draw_mode(snap_face, snap_edge, snap_vert) - snap_obj.data[1].set_ModelViewMatrix(snap_obj.mat) - snap_obj.data[1].Draw(self._offset_cur) - self._offset_cur += snap_obj.data[1].get_tot_elems() - - self.snap_objects[self.drawn_count], self.snap_objects[i] = self.snap_objects[i], self.snap_objects[self.drawn_count] - self.drawn_count += 1 - - bgl.glReadBuffer(bgl.GL_COLOR_ATTACHMENT0) - bgl.glReadPixels( - int(self.mval[0]) - self._dist_px, int(self.mval[1]) - self._dist_px, - self.threshold, self.threshold, bgl.GL_RED_INTEGER, bgl.GL_UNSIGNED_INT, self._snap_buffer) - bgl.glReadBuffer(bgl.GL_BACK) - - snap_obj, index = self._get_nearest_index() - #print(index) - if snap_obj: - ret = self._get_loc(snap_obj, index) - - self._offscreen.unbind() - _Internal.gpu_Indices_restore_state() - - return snap_obj, ret[0], ret[1] - - def free(self): - self.__del__() - self.freed = True diff --git a/modules/snap_context/mesh_drawing.py b/modules/snap_context/mesh_drawing.py deleted file mode 100644 index bdfca4d3..00000000 --- a/modules/snap_context/mesh_drawing.py +++ /dev/null @@ -1,518 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# ##### END GPL LICENSE BLOCK ##### - - -import bgl -import bmesh -import numpy as np -from mathutils import Matrix - -from .utils_shader import Shader - - -def load_shader(shadername): - from os import path - with open(path.join(path.dirname(__file__), 'resources', shadername), 'r') as f: - return f.read() - -def gl_buffer_void_as_long(value): - import ctypes - a = (ctypes.c_byte * 1).from_address(value) - return bgl.Buffer(bgl.GL_BYTE, 1, a) - -def get_mesh_vert_co_array(me): - tot_vco = len(me.vertices) - if tot_vco: - verts_co = np.empty(len(me.vertices) * 3, 'f4') - me.vertices.foreach_get("co", verts_co) - verts_co.shape = (-1, 3) - return verts_co - return None - - -def get_bmesh_vert_co_array(bm): - tot_vco = len(bm.verts) - if tot_vco: - return np.array([v.co for v in bm.verts], 'f4') - return None - - -def get_mesh_tri_verts_array(me): - me.calc_tessface() - len_tessfaces = len(me.tessfaces) - if len_tessfaces: - tessfaces = np.empty(len_tessfaces * 4, 'i4') - me.tessfaces.foreach_get("vertices_raw", tessfaces) - tessfaces.shape = (-1, 4) - - quad_indices = tessfaces[:, 3].nonzero()[0] - tris = np.empty(((len_tessfaces + len(quad_indices)), 3), 'i4') - - tris[:len_tessfaces] = tessfaces[:, :3] - tris[len_tessfaces:] = tessfaces[quad_indices][:, (0, 2, 3)] - - del tessfaces - return tris - return None - - -def get_bmesh_tri_verts_array(bm): - ltris = bm.calc_tessface() - tris = [[ltri[0].vert.index, ltri[1].vert.index, ltri[2].vert.index] for ltri in ltris if not ltri[0].face.hide] - if tris: - return np.array(tris, 'i4') - return None - - -def get_mesh_edge_verts_array(me): - tot_edges = len(me.edges) - if tot_edges: - edge_verts = np.empty(tot_edges * 2, 'i4') - me.edges.foreach_get("vertices", edge_verts) - edge_verts.shape = tot_edges, 2 - return edge_verts - return None - - -def get_bmesh_edge_verts_array(bm): - bm.edges.ensure_lookup_table() - edges = [[e.verts[0].index, e.verts[1].index] for e in bm.edges if not e.hide] - if edges: - return np.array(edges, 'i4') - return None - - -def get_mesh_loosevert_array(me, edges): - verts = np.arange(len(me.vertices)) - - mask = np.in1d(verts, edges, invert=True) - - verts = verts[mask] - if len(verts): - return verts - return None - - -def get_bmesh_loosevert_array(bm): - looseverts = [v.index for v in bm.verts if not (v.link_edges or v.hide)] - if looseverts: - return np.array(looseverts, 'i4') - return None - - -class _Mesh_Arrays(): - def __init__(self, obj, create_tris, create_edges, create_looseverts): - self.tri_verts = self.edge_verts = self.looseverts = None - self.tris_co = self.edges_co = self.looseverts_co = None - if obj.type == 'MESH': - me = obj.data - if me.is_editmode: - bm = bmesh.from_edit_mesh(me) - bm.verts.ensure_lookup_table() - - self.verts_co = get_bmesh_vert_co_array(bm) - - if create_tris: - self.tri_verts = get_bmesh_tri_verts_array(bm) - if create_edges: - self.edge_verts = get_bmesh_edge_verts_array(bm) - if create_looseverts: - self.looseverts = get_bmesh_loosevert_array(bm) - else: - self.verts_co = get_mesh_vert_co_array(me) - - if create_tris: - self.tri_verts = get_mesh_tri_verts_array(me) - if create_edges: - self.edge_verts = get_mesh_edge_verts_array(me) - if create_looseverts: - edge_verts = self.edge_verts - if edge_verts is None: - edge_verts = get_mesh_edge_verts_array(me) - self.looseverts = get_mesh_loosevert_array(me, edge_verts) - del edge_verts - - else: #TODO - self.verts_co = np.zeros((1,3), 'f4') - self.looseverts = np.zeros(1, 'i4') - - def __del__(self): - del self.tri_verts, self.edge_verts, self.looseverts - del self.verts_co - - -class GPU_Indices_Mesh(): - shader = None - - @classmethod - def end_opengl(cls): - del cls.shader - del cls._NULL - del cls.P - del cls.MV - del cls.MVP - del cls.vert_index - del cls.tri_co - del cls.edge_co - del cls.vert_co - - del cls - - @classmethod - def init_opengl(cls): - # OpenGL was already initialized, nothing to do here. - if cls.shader is not None: - return - - import atexit - - # Make sure we only registered the callback once. - atexit.unregister(cls.end_opengl) - atexit.register(cls.end_opengl) - - cls.shader = Shader( - load_shader('3D_vert.glsl'), - None, - load_shader('primitive_id_frag.glsl'), - ) - - cls.unif_use_clip_planes = bgl.glGetUniformLocation(cls.shader.program, 'use_clip_planes') - cls.unif_clip_plane = bgl.glGetUniformLocation(cls.shader.program, 'clip_plane') - - cls._NULL = gl_buffer_void_as_long(0) - - cls.unif_MVP = bgl.glGetUniformLocation(cls.shader.program, 'MVP') - cls.unif_MV = bgl.glGetUniformLocation(cls.shader.program, 'MV') - cls.unif_offset = bgl.glGetUniformLocation(cls.shader.program, 'offset') - - cls.attr_pos = bgl.glGetAttribLocation(cls.shader.program, 'pos') - cls.attr_primitive_id = bgl.glGetAttribLocation(cls.shader.program, 'primitive_id') - - cls.P = bgl.Buffer(bgl.GL_FLOAT, (4, 4)) - cls.MV = bgl.Buffer(bgl.GL_FLOAT, (4, 4)) - cls.MVP = bgl.Buffer(bgl.GL_FLOAT, (4, 4)) - - # returns of public API # - cls.vert_index = bgl.Buffer(bgl.GL_INT, 1) - - cls.tri_co = bgl.Buffer(bgl.GL_FLOAT, (3, 3)) - cls.edge_co = bgl.Buffer(bgl.GL_FLOAT, (2, 3)) - cls.vert_co = bgl.Buffer(bgl.GL_FLOAT, 3) - - def __init__(self, obj, draw_tris, draw_edges, draw_verts): - GPU_Indices_Mesh.init_opengl() - - self.obj = obj - self.draw_tris = draw_tris - self.draw_edges = draw_edges - self.draw_verts = draw_verts - - self.vbo = None - self.vbo_tris = None - self.vbo_edges = None - self.vbo_verts = None - - ## Create VAO ## - self.vao = bgl.Buffer(bgl.GL_INT, 1) - bgl.glGenVertexArrays(1, self.vao) - bgl.glBindVertexArray(self.vao[0]) - - ## Init Array ## - mesh_arrays = _Mesh_Arrays(obj, draw_tris, draw_edges, draw_verts) - - ## Create VBO for vertices ## - if mesh_arrays.verts_co is None: - self.draw_tris = False - self.draw_edges = False - self.draw_verts = False - return - - if False: # Blender 2.8 - self.vbo_len = len(mesh_arrays.verts_co) - - self.vbo = bgl.Buffer(bgl.GL_INT, 1) - bgl.glGenBuffers(1, self.vbo) - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo[0]) - verts_co = bgl.Buffer(bgl.GL_FLOAT, mesh_arrays.verts_co.shape, mesh_arrays.verts_co) - bgl.glBufferData(bgl.GL_ARRAY_BUFFER, self.vbo_len * 12, verts_co, bgl.GL_STATIC_DRAW) - - ## Create VBO for Tris ## - if mesh_arrays.tri_verts is not None: - self.tri_verts = mesh_arrays.tri_verts - self.num_tris = len(self.tri_verts) - - np_tris_co = mesh_arrays.verts_co[mesh_arrays.tri_verts] - np_tris_co = bgl.Buffer(bgl.GL_FLOAT, np_tris_co.shape, np_tris_co) - self.vbo_tris = bgl.Buffer(bgl.GL_INT, 1) - bgl.glGenBuffers(1, self.vbo_tris) - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_tris[0]) - bgl.glBufferData(bgl.GL_ARRAY_BUFFER, self.num_tris * 36, np_tris_co, bgl.GL_STATIC_DRAW) - del np_tris_co - - tri_indices = np.repeat(np.arange(self.num_tris, dtype = 'f4'), 3) - tri_indices = bgl.Buffer(bgl.GL_FLOAT, tri_indices.shape, tri_indices) - self.vbo_tri_indices = bgl.Buffer(bgl.GL_INT, 1) - bgl.glGenBuffers(1, self.vbo_tri_indices) - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_tri_indices[0]) - bgl.glBufferData(bgl.GL_ARRAY_BUFFER, self.num_tris * 12, tri_indices, bgl.GL_STATIC_DRAW) - del tri_indices - - else: - self.num_tris = 0 - self.draw_tris = False - - ## Create VBO for Edges ## - if mesh_arrays.edge_verts is not None: - self.edge_verts = mesh_arrays.edge_verts - self.num_edges = len(self.edge_verts) - - np_edges_co = mesh_arrays.verts_co[mesh_arrays.edge_verts] - np_edges_co = bgl.Buffer(bgl.GL_FLOAT, np_edges_co.shape, np_edges_co) - self.vbo_edges = bgl.Buffer(bgl.GL_INT, 1) - bgl.glGenBuffers(1, self.vbo_edges) - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_edges[0]) - bgl.glBufferData(bgl.GL_ARRAY_BUFFER, self.num_edges * 24, np_edges_co, bgl.GL_STATIC_DRAW) - del np_edges_co - - edge_indices = np.repeat(np.arange(self.num_edges, dtype = 'f4'), 2) - edge_indices = bgl.Buffer(bgl.GL_FLOAT, edge_indices.shape, edge_indices) - self.vbo_edge_indices = bgl.Buffer(bgl.GL_INT, 1) - bgl.glGenBuffers(1, self.vbo_edge_indices) - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_edge_indices[0]) - bgl.glBufferData(bgl.GL_ARRAY_BUFFER, self.num_edges * 8, edge_indices, bgl.GL_STATIC_DRAW) - del edge_indices - else: - self.num_edges = 0 - self.draw_edges = False - - ## Create EBO for Loose Verts ## - if mesh_arrays.looseverts is not None: - self.looseverts = mesh_arrays.looseverts - self.num_verts = len(mesh_arrays.looseverts) - - np_lverts_co = mesh_arrays.verts_co[mesh_arrays.looseverts] - np_lverts_co = bgl.Buffer(bgl.GL_FLOAT, np_lverts_co.shape, np_lverts_co) - self.vbo_verts = bgl.Buffer(bgl.GL_INT, 1) - bgl.glGenBuffers(1, self.vbo_verts) - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_verts[0]) - bgl.glBufferData(bgl.GL_ARRAY_BUFFER, self.num_verts * 12, np_lverts_co, bgl.GL_STATIC_DRAW) - del np_lverts_co - - looseverts_indices = np.arange(self.num_verts, dtype = 'f4') - looseverts_indices = bgl.Buffer(bgl.GL_FLOAT, looseverts_indices.shape, looseverts_indices) - self.vbo_looseverts_indices = bgl.Buffer(bgl.GL_INT, 1) - bgl.glGenBuffers(1, self.vbo_looseverts_indices) - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_looseverts_indices[0]) - bgl.glBufferData(bgl.GL_ARRAY_BUFFER, self.num_verts * 4, looseverts_indices, bgl.GL_STATIC_DRAW) - del looseverts_indices - else: - self.num_verts = 0 - self.draw_verts = False - - del mesh_arrays - - bgl.glBindVertexArray(0) - - - def get_tot_elems(self): - tot = 0 - - if self.draw_tris: - tot += self.num_tris - - if self.draw_edges: - tot += self.num_edges - - if self.draw_verts: - tot += self.num_verts - - return tot - - - def set_draw_mode(self, draw_tris, draw_edges, draw_verts): - self.draw_tris = draw_tris and self.vbo_tris - self.draw_edges = draw_edges and self.vbo_edges - self.draw_verts = draw_verts and self.vbo_verts - - - def set_ModelViewMatrix(self, MV): - self.MV[:] = MV[:] - self.MVP[:] = Matrix(self.P) * MV - - - def Draw(self, index_offset): - self.first_index = index_offset - bgl.glUseProgram(self.shader.program) - bgl.glBindVertexArray(self.vao[0]) - - bgl.glUniformMatrix4fv(self.unif_MV, 1, bgl.GL_TRUE, self.MV) - bgl.glUniformMatrix4fv(self.unif_MVP, 1, bgl.GL_TRUE, self.MVP) - - if self.draw_tris: - bgl.glUniform1f(self.unif_offset, float(index_offset)) # bgl has no glUniform1ui :\ - - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_tris[0]) - bgl.glEnableVertexAttribArray(self.attr_pos) - bgl.glVertexAttribPointer(self.attr_pos, 3, bgl.GL_FLOAT, bgl.GL_FALSE, 0, self._NULL) - - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_tri_indices[0]) - bgl.glEnableVertexAttribArray(self.attr_primitive_id) - bgl.glVertexAttribPointer(self.attr_primitive_id, 1, bgl.GL_FLOAT, bgl.GL_FALSE, 0, self._NULL) - - bgl.glDrawArrays(bgl.GL_TRIANGLES, 0, self.num_tris * 3) - - index_offset += self.num_tris - bgl.glDepthRange(-0.00005, 0.99995) - - if self.draw_edges: - bgl.glUniform1f(self.unif_offset, float(index_offset)) #TODO: use glUniform1ui - - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_edges[0]) - bgl.glVertexAttribPointer(self.attr_pos, 3, bgl.GL_FLOAT, bgl.GL_FALSE, 0, self._NULL) - bgl.glEnableVertexAttribArray(self.attr_pos) - - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_edge_indices[0]) - bgl.glVertexAttribPointer(self.attr_primitive_id, 1, bgl.GL_FLOAT, bgl.GL_FALSE, 0, self._NULL) - bgl.glEnableVertexAttribArray(self.attr_primitive_id) - - bgl.glDrawArrays(bgl.GL_LINES, 0, self.num_edges * 2) - - index_offset += self.num_edges - - if self.draw_verts: - bgl.glUniform1f(self.unif_offset, float(index_offset)) #TODO: use glUniform1ui - - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_verts[0]) - bgl.glVertexAttribPointer(self.attr_pos, 3, bgl.GL_FLOAT, bgl.GL_FALSE, 0, self._NULL) - bgl.glEnableVertexAttribArray(self.attr_pos) - - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_looseverts_indices[0]) - bgl.glVertexAttribPointer(self.attr_primitive_id, 1, bgl.GL_FLOAT, bgl.GL_FALSE, 0, self._NULL) - bgl.glEnableVertexAttribArray(self.attr_primitive_id) - - bgl.glDrawArrays(bgl.GL_POINTS, 0, self.num_verts) - - bgl.glDepthRange(0.0, 1.0) - - - def get_tri_co(self, index): - bgl.glBindVertexArray(self.vao[0]) - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_tris[0]) - bgl.glGetBufferSubData(bgl.GL_ARRAY_BUFFER, index * 36, 36, self.tri_co) - bgl.glBindVertexArray(0) - return self.tri_co - - - def get_edge_co(self, index): - bgl.glBindVertexArray(self.vao[0]) - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_edges[0]) - bgl.glGetBufferSubData(bgl.GL_ARRAY_BUFFER, index * 24, 24, self.edge_co) - bgl.glBindVertexArray(0) - return self.edge_co - - - def get_loosevert_co(self, index): - bgl.glBindVertexArray(self.vao[0]) - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vbo_verts[0]) - bgl.glGetBufferSubData(bgl.GL_ARRAY_BUFFER, index * 12, 12, self.vert_co) - bgl.glBindVertexArray(0) - return self.vert_co - - - def get_tri_verts(self, index): - return self.tri_verts[index] - - - def get_edge_verts(self, index): - return self.edge_verts[index] - - - def get_loosevert_index(self, index): - return self.looseverts[index] - - - def __del__(self): - if self.vbo_tris: - bgl.glDeleteBuffers(1, self.vbo_tris) - bgl.glDeleteBuffers(1, self.vbo_tri_indices) - del self.tri_verts - - if self.vbo_edges: - bgl.glDeleteBuffers(1, self.vbo_edges) - bgl.glDeleteBuffers(1, self.vbo_edge_indices) - del self.edge_verts - - if self.vbo_verts: - bgl.glDeleteBuffers(1, self.vbo_verts) - bgl.glDeleteBuffers(1, self.vbo_looseverts_indices) - del self.looseverts - - bgl.glDeleteVertexArrays(1, self.vao) - #print('mesh_del', self.obj.name) - - -class PreviousGLState: - buf = bgl.Buffer(bgl.GL_INT, (4, 1)) - cur_program = buf[0] - cur_vao = buf[1] - cur_vbo = buf[2] - cur_ebo = buf[3] - - -def _store_current_shader_state(cls): - bgl.glGetIntegerv(bgl.GL_CURRENT_PROGRAM, cls.cur_program) - bgl.glGetIntegerv(bgl.GL_VERTEX_ARRAY_BINDING, cls.cur_vao) - bgl.glGetIntegerv(bgl.GL_ARRAY_BUFFER_BINDING, cls.cur_vbo) - bgl.glGetIntegerv(bgl.GL_ELEMENT_ARRAY_BUFFER_BINDING, cls.cur_ebo) - - -def _restore_shader_state(cls): - bgl.glUseProgram(cls.cur_program[0]) - bgl.glBindVertexArray(cls.cur_vao[0]) - bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, cls.cur_vbo[0]) - bgl.glBindBuffer(bgl.GL_ELEMENT_ARRAY_BUFFER, cls.cur_ebo[0]) - - -def gpu_Indices_enable_state(): - _store_current_shader_state(PreviousGLState) - - GPU_Indices_Mesh.init_opengl() - bgl.glUseProgram(GPU_Indices_Mesh.shader.program) - #bgl.glBindVertexArray(GPU_Indices_Mesh.vao[0]) - - -def gpu_Indices_restore_state(): - bgl.glBindVertexArray(0) - _restore_shader_state(PreviousGLState) - - -def gpu_Indices_use_clip_planes(rv3d, value): - if rv3d.use_clip_planes: - planes = bgl.Buffer(bgl.GL_FLOAT, (6, 4), rv3d.clip_planes) - - _store_current_shader_state(PreviousGLState) - GPU_Indices_Mesh.init_opengl() - bgl.glUseProgram(GPU_Indices_Mesh.shader.program) - bgl.glUniform1i(GPU_Indices_Mesh.unif_use_clip_planes, value) - - bgl.glUniform4fv(GPU_Indices_Mesh.unif_clip_plane, 4, planes) - - _restore_shader_state(PreviousGLState) - - -def gpu_Indices_set_ProjectionMatrix(P): - GPU_Indices_Mesh.P[:] = P diff --git a/modules/snap_context/resources/3D_vert.glsl b/modules/snap_context/resources/3D_vert.glsl deleted file mode 100644 index c97df2bf..00000000 --- a/modules/snap_context/resources/3D_vert.glsl +++ /dev/null @@ -1,26 +0,0 @@ -#version 120 - -uniform bool use_clip_planes; -uniform vec4 clip_plane[4]; -varying vec4 clip_distance; - -uniform mat4 MV; -uniform mat4 MVP; - -attribute vec3 pos; -attribute float primitive_id; -varying float primitive_id_var; - -void main() -{ - if (use_clip_planes) { - vec4 g_pos = MV * vec4(pos, 1.0); - - for (int i = 0; i != 4; i++) { - clip_distance[i] = dot(clip_plane[i], g_pos); - } - } - - primitive_id_var = primitive_id; - gl_Position = MVP * vec4(pos, 1.0); -} diff --git a/modules/snap_context/resources/primitive_id_frag.glsl b/modules/snap_context/resources/primitive_id_frag.glsl deleted file mode 100644 index f3f7a124..00000000 --- a/modules/snap_context/resources/primitive_id_frag.glsl +++ /dev/null @@ -1,22 +0,0 @@ -#version 120 - -uniform bool use_clip_planes; -varying vec4 clip_distance; - -uniform float offset; - -varying float primitive_id_var; - -void main() -{ - if (use_clip_planes && - ((clip_distance[0] < 0) || - (clip_distance[1] < 0) || - (clip_distance[2] < 0) || - (clip_distance[3] < 0))) - { - discard; - } - - gl_FragColor = vec4(offset + primitive_id_var, 0, 0, 0); -} diff --git a/modules/snap_context/utils_projection.py b/modules/snap_context/utils_projection.py deleted file mode 100644 index d3970b46..00000000 --- a/modules/snap_context/utils_projection.py +++ /dev/null @@ -1,212 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# ##### END GPL LICENSE BLOCK ##### - - -from mathutils import Vector -from mathutils.geometry import intersect_point_line - - -def depth_get(co, ray_start, ray_dir): - dvec = co - ray_start - return dvec.dot(ray_dir) - - -def region_2d_to_orig_and_view_vector(region, rv3d, coord): - viewinv = rv3d.view_matrix.inverted() - persinv = rv3d.perspective_matrix.inverted() - - dx = (2.0 * coord[0] / region.width) - 1.0 - dy = (2.0 * coord[1] / region.height) - 1.0 - - if rv3d.is_perspective: - origin_start = viewinv.translation.copy() - - out = Vector((dx, dy, -0.5)) - - w = out.dot(persinv[3].xyz) + persinv[3][3] - - view_vector = ((persinv * out) / w) - origin_start - else: - view_vector = -viewinv.col[2].xyz - - origin_start = ((persinv.col[0].xyz * dx) + - (persinv.col[1].xyz * dy) + - viewinv.translation) - - view_vector.normalize() - return view_vector, origin_start - - -def project_co_v3(sctx, co): - proj_co = sctx.proj_mat * co.to_4d() - proj_co.xy /= proj_co.w - - win_half = sctx.winsize * 0.5 - proj_co[0] = (proj_co[0] + 1.0) * win_half[0] - proj_co[1] = (proj_co[1] + 1.0) * win_half[1] - - return proj_co.xy - - - -def intersect_boundbox_threshold(sctx, MVP, ray_origin_local, ray_direction_local, bbmin, bbmax): - local_bvmin = Vector() - local_bvmax = Vector() - tmin = Vector() - tmax = Vector() - - if (ray_direction_local[0] < 0.0): - local_bvmin[0] = bbmax[0] - local_bvmax[0] = bbmin[0] - else: - local_bvmin[0] = bbmin[0] - local_bvmax[0] = bbmax[0] - - if (ray_direction_local[1] < 0.0): - local_bvmin[1] = bbmax[1] - local_bvmax[1] = bbmin[1] - else: - local_bvmin[1] = bbmin[1] - local_bvmax[1] = bbmax[1] - - if (ray_direction_local[2] < 0.0): - local_bvmin[2] = bbmax[2] - local_bvmax[2] = bbmin[2] - else: - local_bvmin[2] = bbmin[2] - local_bvmax[2] = bbmax[2] - - if (ray_direction_local[0]): - tmin[0] = (local_bvmin[0] - ray_origin_local[0]) / ray_direction_local[0] - tmax[0] = (local_bvmax[0] - ray_origin_local[0]) / ray_direction_local[0] - else: - tmin[0] = tmax[0] = sctx.depth_range[1] - - if (ray_direction_local[1]): - tmin[1] = (local_bvmin[1] - ray_origin_local[1]) / ray_direction_local[1] - tmax[1] = (local_bvmax[1] - ray_origin_local[1]) / ray_direction_local[1] - else: - tmin[1] = tmax[1] = sctx.depth_range[1] - - if (ray_direction_local[2]): - tmin[2] = (local_bvmin[2] - ray_origin_local[2]) / ray_direction_local[2] - tmax[2] = (local_bvmax[2] - ray_origin_local[2]) / ray_direction_local[2] - else: - tmin[2] = tmax[2] = sctx.depth_range[1] - - # `va` and `vb` are the coordinates of the AABB edge closest to the ray # - va = Vector() - vb = Vector() - # `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB # - - if ((tmax[0] <= tmax[1]) and (tmax[0] <= tmax[2])): - rtmax = tmax[0] - va[0] = vb[0] = local_bvmax[0] - main_axis = 3 - elif ((tmax[1] <= tmax[0]) and (tmax[1] <= tmax[2])): - rtmax = tmax[1] - va[1] = vb[1] = local_bvmax[1] - main_axis = 2 - else: - rtmax = tmax[2] - va[2] = vb[2] = local_bvmax[2] - main_axis = 1 - - if ((tmin[0] >= tmin[1]) and (tmin[0] >= tmin[2])): - rtmin = tmin[0] - va[0] = vb[0] = local_bvmin[0] - main_axis -= 3 - - elif ((tmin[1] >= tmin[0]) and (tmin[1] >= tmin[2])): - rtmin = tmin[1] - va[1] = vb[1] = local_bvmin[1] - main_axis -= 1 - - else: - rtmin = tmin[2] - va[2] = vb[2] = local_bvmin[2] - main_axis -= 2 - - if (main_axis < 0): - main_axis += 3 - -#ifdef IGNORE_BEHIND_RAY - depth_max = depth_get(local_bvmax, ray_origin_local, ray_direction_local) - if (depth_max < sctx.depth_range[0]): - return False -#endif - - if (rtmin <= rtmax): - # if rtmin < rtmax, ray intersect `AABB` # - return True - - if (ray_direction_local[main_axis] < 0.0): - va[main_axis] = local_bvmax[main_axis] - vb[main_axis] = local_bvmin[main_axis] - - else: - va[main_axis] = local_bvmin[main_axis] - vb[main_axis] = local_bvmax[main_axis] - - win_half = sctx.winsize * 0.5 - - scale = abs(local_bvmax[main_axis] - local_bvmin[main_axis]) - - va2d = Vector(( - (MVP[0].xyz.dot(va) + MVP[0][3]), - (MVP[1].xyz.dot(va) + MVP[1][3]), - )) - - vb2d = Vector(( - (va2d[0] + MVP[0][main_axis] * scale), - (va2d[1] + MVP[1][main_axis] * scale), - )) - - depth_a = MVP[3].xyz.dot(va) + MVP[3][3] - depth_b = depth_a + MVP[3][main_axis] * scale - - va2d /= depth_a - vb2d /= depth_b - - va2d[0] = (va2d[0] + 1.0) * win_half[0] - va2d[1] = (va2d[1] + 1.0) * win_half[1] - vb2d[0] = (vb2d[0] + 1.0) * win_half[0] - vb2d[1] = (vb2d[1] + 1.0) * win_half[1] - - p, fac = intersect_point_line(sctx.mval, va2d, vb2d) - if fac < 0.0: - return (sctx.mval - va2d).length_squared < sctx._dist_px_sq - elif fac > 1.0: - return (sctx.mval - vb2d).length_squared < sctx._dist_px_sq - else: - return (sctx.mval - p).length_squared < sctx._dist_px_sq - - -def intersect_ray_segment_fac(v0, v1, ray_direction, ray_origin): - a = v1 - v0 - t = v0 - ray_origin - n = a.cross(ray_direction) - nlen = n.length_squared - - # if (nlen == 0.0f) the lines are parallel, has no nearest point, only distance squared.*/ - if nlen == 0.0: - # Calculate the distance to the nearest point to origin then # - return a.dot(ray_direction) < 0 - else: - c = n - t - cray = c.cross(ray_direction) - return cray.dot(n) / nlen diff --git a/modules/snap_context/utils_shader.py b/modules/snap_context/utils_shader.py deleted file mode 100644 index 1758585a..00000000 --- a/modules/snap_context/utils_shader.py +++ /dev/null @@ -1,85 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# ##### END GPL LICENSE BLOCK ##### - - -import bgl - -def check_shaderError(shader, flag, isProgram, errorMessage): - success = bgl.Buffer(bgl.GL_INT, 1) - - if isProgram: - bgl.glGetProgramiv(shader, flag, success) - else: - bgl.glGetShaderiv(shader, flag, success) - - if success[0] == bgl.GL_FALSE: - import numpy as np - import ctypes - - offset = bgl.Buffer(bgl.GL_INT, 1, (ctypes.c_int32 * 1).from_address(0)) - error = bgl.Buffer(bgl.GL_BYTE, 1024) - if isProgram: - bgl.glGetProgramInfoLog(shader, 1024, offset, error) - print(errorMessage, np.bytes_(error).decode("utf-8")) - else: - bgl.glGetShaderInfoLog(shader, 1024, offset, error) - print(errorMessage, np.bytes_(error).decode("utf-8")) - - del offset - raise #RuntimeError(errorMessage, bgl.glGetShaderInfoLog(shader)) - - -def create_shader(source, shaderType): - shader = bgl.glCreateShader(shaderType) - - if shader == 0: - raise RuntimeError("Error: Shader creation failed!") - - bgl.glShaderSource(shader, source) - bgl.glCompileShader(shader) - - check_shaderError(shader, bgl.GL_COMPILE_STATUS, False, "Error: Shader compilation failed:") - - return shader - - -class Shader(): - def __init__(self, vertexcode, geomcode, fragcode): - self.program = bgl.glCreateProgram() - self.shaders = [] - - if vertexcode: - self.shaders.append(create_shader(vertexcode, bgl.GL_VERTEX_SHADER)) - if geomcode: - self.shaders.append(create_shader(geomcode, bgl.GL_GEOMETRY_SHADER)) - if fragcode: - self.shaders.append(create_shader(fragcode, bgl.GL_FRAGMENT_SHADER)) - - for shad in self.shaders: - bgl.glAttachShader(self.program, shad) - - bgl.glLinkProgram(self.program) - check_shaderError(self.program, bgl.GL_LINK_STATUS, True, "Error: Program linking failed:") - bgl.glValidateProgram(self.program) - check_shaderError(self.program, bgl.GL_VALIDATE_STATUS, True, "Error: Program is invalid:") - - def __del__(self): - for shad in self.shaders: - bgl.glDetachShader(self.program, shad) - bgl.glDeleteShader(shad) - bgl.glDeleteProgram(self.program) - #print('shader_del') -- cgit v1.2.3