From c351de8b2ab0d1ef6c1a2a12befb5e3d03a87553 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 10 Oct 2023 10:52:30 -0300 Subject: [PATCH 1/2] Fix #113486: Crash snapping with clipping borders Caused by 2cead79747 The clip_plane count in BLI_kdopbvh.c was incorrectly reduced. To solve, make the size of the clip_plane array variable. This eliminates the need to keep values in sync. --- source/blender/blenlib/intern/BLI_kdopbvh.c | 46 +++++++++++---------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index abcd5b51546..f531ee05662 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -142,15 +142,14 @@ typedef struct BVHRayCastData { } BVHRayCastData; typedef struct BVHNearestProjectedData { - const BVHTree *tree; struct DistProjectedAABBPrecalc precalc; bool closest_axis[3]; - float clip_plane[6][4]; - int clip_plane_len; BVHTree_NearestProjectedCallback callback; void *userdata; BVHTreeNearest nearest; + int clip_plane_len; + float clip_plane[0][4]; } BVHNearestProjectedData; typedef struct BVHIntersectPlaneData { @@ -2340,54 +2339,57 @@ int BLI_bvhtree_find_nearest_projected(const BVHTree *tree, { BVHNode *root = tree->nodes[tree->leaf_num]; if (root != NULL) { - BVHNearestProjectedData data; - dist_squared_to_projected_aabb_precalc(&data.precalc, projmat, winsize, mval); + BVHNearestProjectedData *data = (BVHNearestProjectedData *)alloca( + sizeof(*data) + (sizeof(*clip_plane) * max_ii(1, clip_plane_len))); - data.callback = callback; - data.userdata = userdata; + dist_squared_to_projected_aabb_precalc(&data->precalc, projmat, winsize, mval); + + data->callback = callback; + data->userdata = userdata; if (clip_plane) { - data.clip_plane_len = clip_plane_len; - for (int i = 0; i < data.clip_plane_len; i++) { - copy_v4_v4(data.clip_plane[i], clip_plane[i]); + data->clip_plane_len = clip_plane_len; + for (int i = 0; i < clip_plane_len; i++) { + copy_v4_v4(data->clip_plane[i], clip_plane[i]); } } else { - data.clip_plane_len = 1; - planes_from_projmat(projmat, NULL, NULL, NULL, NULL, data.clip_plane[0], NULL); + data->clip_plane_len = 1; + planes_from_projmat(projmat, NULL, NULL, NULL, NULL, data->clip_plane[0], NULL); } if (nearest) { - memcpy(&data.nearest, nearest, sizeof(*nearest)); + memcpy(&data->nearest, nearest, sizeof(*nearest)); } else { - data.nearest.index = -1; - data.nearest.dist_sq = FLT_MAX; + data->nearest.index = -1; + data->nearest.dist_sq = FLT_MAX; } { const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]}; const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]}; - int isect_type = isect_aabb_planes_v3(data.clip_plane, data.clip_plane_len, bb_min, bb_max); + int isect_type = isect_aabb_planes_v3( + data->clip_plane, data->clip_plane_len, bb_min, bb_max); if (isect_type != 0 && - dist_squared_to_projected_aabb(&data.precalc, bb_min, bb_max, data.closest_axis) <= - data.nearest.dist_sq) + dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <= + data->nearest.dist_sq) { if (isect_type == 1) { - bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(&data, root); + bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(data, root); } else { - bvhtree_nearest_projected_dfs_recursive(&data, root); + bvhtree_nearest_projected_dfs_recursive(data, root); } } } if (nearest) { - memcpy(nearest, &data.nearest, sizeof(*nearest)); + memcpy(nearest, &data->nearest, sizeof(*nearest)); } - return data.nearest.index; + return data->nearest.index; } return -1; } From 02ee5a76936617c51b70c8369d3b5213782f0247 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 10 Oct 2023 11:30:15 -0300 Subject: [PATCH 2/2] Fix Snap to Face ignoring back Clip Planes Snap to Face ignoring some clip planes is an old behavior, but it is not desirable as the snap is made to non-visible geometry. --- source/blender/editors/include/ED_view3d.hh | 6 ++- .../editors/space_view3d/view3d_project.cc | 11 +++--- .../transform/transform_snap_object.cc | 38 ++++++++++++------- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/source/blender/editors/include/ED_view3d.hh b/source/blender/editors/include/ED_view3d.hh index c87c4bee636..e7ad7761388 100644 --- a/source/blender/editors/include/ED_view3d.hh +++ b/source/blender/editors/include/ED_view3d.hh @@ -561,20 +561,22 @@ bool ED_view3d_win_to_ray_clipped(Depsgraph *depsgraph, * \param region: The region (used for the window width and height). * \param v3d: The 3d viewport (used for near clipping value). * \param mval: The area relative 2d location (such as `event->mval`, converted into float[2]). + * \param do_clip_planes: Optionally clip the start of the ray by the view clipping planes. * \param r_ray_co: The world-space point where the ray intersects the window plane. * \param r_ray_normal: The normalized world-space direction of towards mval. * \param r_ray_start: The world-space starting point of the ray. - * \param do_clip_planes: Optionally clip the start of the ray by the view clipping planes. + * \param r_ray_end: The world-space end point of the segment. * \return success, false if the ray is totally clipped. */ bool ED_view3d_win_to_ray_clipped_ex(Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const float mval[2], + const bool do_clip_planes, float r_ray_co[3], float r_ray_normal[3], float r_ray_start[3], - bool do_clip_planes); + float r_ray_end[3]); /** * Calculate a 3d viewpoint and direction vector from 2d window coordinates. * This ray_start is located at the viewpoint, ray_normal is the direction towards `mval`. diff --git a/source/blender/editors/space_view3d/view3d_project.cc b/source/blender/editors/space_view3d/view3d_project.cc index 6635d2b7212..20168a57dc5 100644 --- a/source/blender/editors/space_view3d/view3d_project.cc +++ b/source/blender/editors/space_view3d/view3d_project.cc @@ -372,20 +372,19 @@ bool ED_view3d_win_to_ray_clipped_ex(Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const float mval[2], + const bool do_clip_planes, float r_ray_co[3], float r_ray_normal[3], float r_ray_start[3], - bool do_clip_planes) + float r_ray_end[3]) { - float ray_end[3]; - view3d_win_to_ray_segment( - depsgraph, region, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, ray_end); + depsgraph, region, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, r_ray_end); /* bounds clipping */ if (do_clip_planes) { return ED_view3d_clip_segment( - static_cast(region->regiondata), r_ray_start, ray_end); + static_cast(region->regiondata), r_ray_start, r_ray_end); } return true; @@ -400,7 +399,7 @@ bool ED_view3d_win_to_ray_clipped(Depsgraph *depsgraph, const bool do_clip_planes) { return ED_view3d_win_to_ray_clipped_ex( - depsgraph, region, v3d, mval, nullptr, r_ray_normal, r_ray_start, do_clip_planes); + depsgraph, region, v3d, mval, do_clip_planes, nullptr, r_ray_normal, r_ray_start, nullptr); } void ED_view3d_win_to_ray(const ARegion *region, diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index 6212da72780..054fc683d4a 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -1257,21 +1257,33 @@ eSnapMode ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, float r_face_nor[3]) { eSnapMode retval = SCE_SNAP_TO_NONE; + float ray_depth_max = BVH_RAYCAST_DIST_MAX; bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(v3d); if (use_occlusion_test || (snap_to_flag & SCE_SNAP_TO_FACE)) { - if (!ED_view3d_win_to_ray_clipped_ex(depsgraph, - region, - v3d, - mval, - nullptr, - sctx->runtime.ray_dir, - sctx->runtime.ray_start, - true)) - { - snap_to_flag &= ~SCE_SNAP_TO_FACE; - use_occlusion_test = false; + const RegionView3D *rv3d = static_cast(region->regiondata); + float3 ray_end; + ED_view3d_win_to_ray_clipped_ex(depsgraph, + region, + v3d, + mval, + false, + nullptr, + sctx->runtime.ray_dir, + sctx->runtime.ray_start, + ray_end); + + if (rv3d->rflag & RV3D_CLIPPING) { + if (clip_segment_v3_plane_n( + sctx->runtime.ray_start, ray_end, rv3d->clip, 6, sctx->runtime.ray_start, ray_end)) + { + ray_depth_max = math::dot(ray_end - sctx->runtime.ray_start, sctx->runtime.ray_dir); + } + else { + snap_to_flag &= ~SCE_SNAP_TO_FACE; + use_occlusion_test = false; + } } } @@ -1283,7 +1295,7 @@ eSnapMode ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, params, sctx->runtime.ray_start, sctx->runtime.ray_dir, - BVH_RAYCAST_DIST_MAX, + ray_depth_max, mval, init_co, prev_co, @@ -1465,7 +1477,7 @@ bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx, float ray_start[3], ray_normal[3]; if (!ED_view3d_win_to_ray_clipped_ex( - depsgraph, region, v3d, mval, nullptr, ray_normal, ray_start, true)) + depsgraph, region, v3d, mval, true, nullptr, ray_normal, ray_start, nullptr)) { return false; }