Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mesh_snap_utilities_line/snap_context_l/utils_projection.py')
-rw-r--r--mesh_snap_utilities_line/snap_context_l/utils_projection.py216
1 files changed, 216 insertions, 0 deletions
diff --git a/mesh_snap_utilities_line/snap_context_l/utils_projection.py b/mesh_snap_utilities_line/snap_context_l/utils_projection.py
new file mode 100644
index 00000000..cc17aa23
--- /dev/null
+++ b/mesh_snap_utilities_line/snap_context_l/utils_projection.py
@@ -0,0 +1,216 @@
+# ##### 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 #####
+
+
+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_safe()
+ persinv = rv3d.perspective_matrix.inverted_safe()
+
+ 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()
+ try:
+ proj_co.xy /= proj_co.w
+ except Exception as e:
+ print(e)
+
+ 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
+