diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-08-31 06:06:23 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-08-31 06:06:23 +0400 |
commit | 11c988ba00f2991850050ff4c2e3cb34c2546047 (patch) | |
tree | e61413337f5e8b92284569f06b553516b2675536 | |
parent | 29f6616d609fbd92cf313b0fdec555c2fcb4ede0 (diff) |
Simplify line/plane intersection, add line_plane_factor_v3().
Remove no_flip option for isect_line_plane_v3(), its quite specific and only used for ED_view3d_win_to_3d().
-rw-r--r-- | source/blender/blenlib/BLI_math_geom.h | 6 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_geom.c | 64 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_project.c | 10 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 2 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_geometry.c | 9 |
5 files changed, 42 insertions, 49 deletions
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 4307645bb91..559157370ca 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -97,6 +97,10 @@ void closest_on_tri_to_point_v3(float r[3], const float p[3], const float t1[3], float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3]); float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2]); + +float line_plane_factor_v3(const float plane_co[3], const float plane_no[3], + const float l1[3], const float l2[3]); + void limit_dist_v3(float v1[3], float v2[3], const float dist); /******************************* Intersection ********************************/ @@ -130,7 +134,7 @@ bool isect_ray_plane_v3(const float p1[3], const float d[3], bool isect_point_planes_v3(float (*planes)[4], int totplane, const float p[3]); bool isect_line_plane_v3(float out[3], const float l1[3], const float l2[3], - const float plane_co[3], const float plane_no[3], const bool no_flip); + const float plane_co[3], const float plane_no[3]); void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], const float plane_a_co[3], const float plane_a_no[3], diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 375b258acf9..68f246e3982 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -1121,50 +1121,28 @@ bool isect_point_planes_v3(float (*planes)[4], int totplane, const float p[3]) * \param l2 The second point of the line. * \param plane_co A point on the plane to intersect with. * \param plane_no The direction of the plane (does not need to be normalized). - * \param no_flip When true, the intersection point will always be from l1 to l2, even if this is not on the plane. + * + * \note #line_plane_factor_v3() shares logic. */ bool isect_line_plane_v3(float out[3], const float l1[3], const float l2[3], - const float plane_co[3], const float plane_no[3], const bool no_flip) + const float plane_co[3], const float plane_no[3]) { - float l_vec[3]; /* l1 -> l2 normalized vector */ - float p_no[3]; /* 'plane_no' normalized */ + float u[3], h[3]; float dot; - sub_v3_v3v3(l_vec, l2, l1); - - normalize_v3(l_vec); - normalize_v3_v3(p_no, plane_no); + sub_v3_v3v3(u, l2, l1); + sub_v3_v3v3(h, l1, plane_co); + dot = dot_v3v3(plane_no, u); - dot = dot_v3v3(l_vec, p_no); - if (dot == 0.0f) { - return 0; + if (fabsf(dot) > FLT_EPSILON) { + float lambda = -dot_v3v3(plane_no, h) / dot; + madd_v3_v3v3fl(out, l1, u, lambda); + return true; } else { - float l1_plane[3]; /* line point aligned with the plane */ - float dist; /* 'plane_no' aligned distance to the 'plane_co' */ - - /* for predictable flipping since the plane is only used to - * define a direction, ignore its flipping and aligned with 'l_vec' */ - if (dot < 0.0f) { - dot = -dot; - negate_v3(p_no); - } - - add_v3_v3v3(l1_plane, l1, p_no); - - dist = line_point_factor_v3(plane_co, l1, l1_plane); - - /* treat line like a ray, when 'no_flip' is set */ - if (no_flip && dist < 0.0f) { - dist = -dist; - } - - mul_v3_fl(l_vec, dist / dot); - - add_v3_v3v3(out, l1, l_vec); - - return 1; + /* The segment is parallel to plane */ + return false; } } @@ -1190,7 +1168,7 @@ void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], cross_v3_v3v3(r_isect_no, plane_a_no, plane_b_no); /* direction is simply the cross product */ cross_v3_v3v3(plane_a_co_other, plane_a_no, r_isect_no); add_v3_v3(plane_a_co_other, plane_a_co); - isect_line_plane_v3(r_isect_co, plane_a_co, plane_a_co_other, plane_b_co, plane_b_no, FALSE); + isect_line_plane_v3(r_isect_co, plane_a_co, plane_a_co_other, plane_b_co, plane_b_no); } @@ -1716,6 +1694,20 @@ float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2 #endif } +/** + * \note #isect_line_plane_v3() shares logic + */ +float line_plane_factor_v3(const float plane_co[3], const float plane_no[3], + const float l1[3], const float l2[3]) +{ + float u[3], h[3]; + float dot; + sub_v3_v3v3(u, l2, l1); + sub_v3_v3v3(h, l1, plane_co); + dot = dot_v3v3(plane_no, u); + return (dot != 0.0f) ? -dot_v3v3(plane_no, h) / dot : 0.0f; +} + /* ensure the distance between these points is no greater then 'dist' * if it is, scale then both into the center */ void limit_dist_v3(float v1[3], float v2[3], const float dist) diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 5e71913ea4a..28ffdea0e6c 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -405,15 +405,15 @@ void ED_view3d_win_to_3d(const ARegion *ar, const float depth_pt[3], const float float line_end[3]; if (rv3d->is_persp) { - float mousevec[3]; + float mousevec[3], lambda; copy_v3_v3(line_sta, rv3d->viewinv[3]); ED_view3d_win_to_vector(ar, mval, mousevec); add_v3_v3v3(line_end, line_sta, mousevec); - if (isect_line_plane_v3(out, line_sta, line_end, depth_pt, rv3d->viewinv[2], true) == 0) { - /* highly unlikely to ever happen, mouse vector parallel with view plane */ - zero_v3(out); - } + /* note, we could use isect_line_plane_v3() however we want the intersection to be infront of the + * view no matter what, so apply the unsigned factor instead */ + lambda = line_plane_factor_v3(depth_pt, rv3d->viewinv[2], line_sta, line_end); + interp_v3_v3v3(out, line_sta, line_end, fabsf(lambda)); } else { float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 0eada494715..82c117a7486 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4828,7 +4828,7 @@ static bool bm_loop_calc_opposite_co(BMLoop *l_tmp, float tvec[3]; if (isect_line_plane_v3(tvec, l_iter->v->co, l_iter->next->v->co, - l_tmp->v->co, plane_no, false)) + l_tmp->v->co, plane_no)) { const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co); /* allow some overlap to avoid missing the intersection because of float precision */ diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index 2d4aa988db2..54e9ccf4a70 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -568,22 +568,19 @@ PyDoc_STRVAR(M_Geometry_intersect_line_plane_doc, " :type plane_co: :class:`mathutils.Vector`\n" " :arg plane_no: The direction the plane is facing\n" " :type plane_no: :class:`mathutils.Vector`\n" -" :arg no_flip: Always return an intersection on the directon defined bt line_a -> line_b\n" -" :type no_flip: :boolean\n" " :return: The point of intersection or None when not found\n" " :rtype: :class:`mathutils.Vector` or None\n" ); static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObject *args) { VectorObject *line_a, *line_b, *plane_co, *plane_no; - int no_flip = 0; float isect[3]; + if (!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_line_plane", &vector_Type, &line_a, &vector_Type, &line_b, &vector_Type, &plane_co, - &vector_Type, &plane_no, - &no_flip)) + &vector_Type, &plane_no)) { return NULL; } @@ -603,7 +600,7 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec return NULL; } - if (isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec, no_flip) == 1) { + if (isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec) == 1) { return Vector_CreatePyObject(isect, 3, Py_NEW, NULL); } else { |