[Bf-extensions-cvs] [136a8f83] master: New `snap_context` module for `addons/module`

Germano noreply at git.blender.org
Sun Sep 10 01:12:16 CEST 2017


Commit: 136a8f839aab01c23a809eba13db014d654511c3
Author: Germano
Date:   Sat Sep 9 20:11:38 2017 -0300
Branches: master
https://developer.blender.org/rBA136a8f839aab01c23a809eba13db014d654511c3

New `snap_context` module for `addons/module`

This module basically uses OpenGL to draw, in an offscreen, the vertices, edges and tris of specific objects and use colors as information for snap

===================================================================

A	modules/snap_context/__init__.py
A	modules/snap_context/bgl_ext.py
A	modules/snap_context/mesh_drawing.py
A	modules/snap_context/resources/3D_vert.glsl
A	modules/snap_context/resources/primitive_id_frag.glsl
A	modules/snap_context/utils_projection.py
A	modules/snap_context/utils_shader.py

===================================================================

diff --git a/modules/snap_context/__init__.py b/modules/snap_context/__init__.py
new file mode 100644
index 00000000..4767862f
--- /dev/null
+++ b/modules/snap_context/__init__.py
@@ -0,0 +1,292 @@
+# ##### 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 <http://www.gnu.org/licenses/>.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+import bgl
+import gpu
+from mathutils import Vector, Matrix
+from mathutils.geometry import intersect_point_line, intersect_ray_tri
+
+from .bgl_ext import VoidBufValue, get_clip_planes
+from .mesh_drawing import GPU_Indices_Mesh, gpu_Indices_enable_state, gpu_Indices_restore_state
+from .utils_projection import (
+    region_2d_to_orig_and_view_vector as _get_ray,
+    intersect_boundbox_threshold,
+    intersect_ray_segment_fac,
+    project_co_v3,
+    )
+
+VERT = 1
+EDGE = 2
+FACE = 4
+
+class _SnapObjectData():
+    def __init__(self, data, omat):
+        self.data = data
+        self.mat = omat
+
+
+class SnapContext():
+    def __init__(self, region, space):
+        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
+        self.proj_mat = Matrix.Identity(4)
+        self.depth_range = Vector((space.clip_start, space.clip_end))
+        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 = VoidBufValue(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.buf)
+        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)]
+                return intersect_ray_tri(*tri_co, *self.last_ray, False), 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 = 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 = 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()
+            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 = Matrix.Identity(4)
+
+    def use_clip_planes(self, value):
+        planes = get_clip_planes(self.rv3d)
+        if planes:
+            self._store_current_shader_state()
+            GPU_Indices_Mesh.shader
+            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)
+
+            self._restore_shader_state()
+
+    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.freeze()
+        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 = _get_ray(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
+
+        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
+            GPU_Indices_Mesh.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 = ray_dir * snap_obj.mat
+                in_threshold = intersect_boundbox_threshold(self, MVP, ray_orig_local, ray_dir_local, bbmin, bbmax)
+            else:
+                proj_co = 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:
+                    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

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list