From ab3e470b352269901973be81422cb4e8fbcf260f Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 1 Oct 2024 14:26:41 -0300 Subject: [PATCH] Fix: Occlusion of Curves failing during snapping The geometry of objects behind Curves was being considered for snapping even when occluded. The occlusion test logic has been reworked and simplified when the snap target is a Curve. As a result, Snap to Face now works correctly for the active Curve. --- .../transform/transform_snap_object.cc | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index 380201087fb..228f5afbeda 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -577,7 +577,7 @@ static eSnapMode raycast_obj_fn(SnapObjectContext *sctx, const Object *ob_eval, const ID *ob_data, const float4x4 &obmat, - bool is_object_active, + bool /*is_object_active*/, bool use_hide) { bool retval = false; @@ -603,7 +603,13 @@ static eSnapMode raycast_obj_fn(SnapObjectContext *sctx, else if (GS(ob_data->name) != ID_ME) { return SCE_SNAP_TO_NONE; } - else if (is_object_active && ELEM(ob_eval->type, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) { + else if (ELEM(ob_eval->type, OB_CURVES_LEGACY, OB_SURF) && + (sctx->runtime.params.edit_mode_type != SNAP_GEOM_FINAL) && + BKE_object_is_in_editmode(ob_eval)) + { + /* The final Curves geometry is generated as a Mesh. Skip this Mesh if the target is not + * #SNAP_GEOM_FINAL. This also avoids creating and destroying BVH Trees too frequently while + * editing. */ return SCE_SNAP_TO_NONE; } else { @@ -715,7 +721,7 @@ static eSnapMode nearest_world_object_fn(SnapObjectContext *sctx, const Object *ob_eval, const ID *ob_data, const float4x4 &obmat, - bool is_object_active, + bool /*is_object_active*/, bool use_hide) { eSnapMode retval = SCE_SNAP_TO_NONE; @@ -732,7 +738,13 @@ static eSnapMode nearest_world_object_fn(SnapObjectContext *sctx, else if (GS(ob_data->name) != ID_ME) { return SCE_SNAP_TO_NONE; } - else if (is_object_active && ELEM(ob_eval->type, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) { + else if (ELEM(ob_eval->type, OB_CURVES_LEGACY, OB_SURF) && + (sctx->runtime.params.edit_mode_type != SNAP_GEOM_FINAL) && + BKE_object_is_in_editmode(ob_eval)) + { + /* The final Curves geometry is generated as a Mesh. Skip this Mesh if the target is not + * #SNAP_GEOM_FINAL. This also avoids creating and destroying BVH Trees too frequently while + * editing. */ return SCE_SNAP_TO_NONE; } else { @@ -885,10 +897,11 @@ static eSnapMode snap_obj_fn(SnapObjectContext *sctx, } if (GS(ob_data->name) == ID_ME) { - if (ob_eval->type == OB_CURVES_LEGACY && BKE_object_is_in_editmode(ob_eval)) { - /* Sometimes, such as when Mesh is generated by Geometry Nodes, a Curve object may have Mesh - * instances. - * In these cases, skip the snap to Mesh if the Curve is in edit mode. */ + if (ELEM(ob_eval->type, OB_CURVES_LEGACY, OB_SURF) && + (sctx->runtime.params.edit_mode_type != SNAP_GEOM_FINAL)) + { + /* The final Curves geometry is generated as a Mesh. Skip this Mesh if the target is not + * #SNAP_GEOM_FINAL. */ return SCE_SNAP_TO_NONE; } return snap_object_mesh(sctx, ob_eval, ob_data, obmat, sctx->runtime.snap_to_flag, use_hide); @@ -906,19 +919,9 @@ static eSnapMode snap_obj_fn(SnapObjectContext *sctx, case OB_SURF: if (ob_eval->type == OB_CURVES_LEGACY || BKE_object_is_in_editmode(ob_eval)) { retval = snapCurve(sctx, ob_eval, obmat); - if (sctx->runtime.params.edit_mode_type != SNAP_GEOM_FINAL) { - break; - } - } - ATTR_FALLTHROUGH; - case OB_FONT: { - const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval); - if (mesh_eval) { - retval |= snap_object_mesh( - sctx, ob_eval, (ID *)mesh_eval, obmat, sctx->runtime.snap_to_flag, use_hide); } break; - } + case OB_FONT: case OB_EMPTY: case OB_GPENCIL_LEGACY: case OB_LAMP: @@ -1402,10 +1405,7 @@ eSnapMode ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, /* Remove what has already been computed. */ sctx->runtime.snap_to_flag &= ~(SCE_SNAP_TO_FACE | SCE_SNAP_INDIVIDUAL_NEAREST); - if (use_occlusion_plane && has_hit && - /* By convention we only snap to the original elements of a curve. */ - sctx->ret.ob->type != OB_CURVES_LEGACY) - { + if (use_occlusion_plane && has_hit) { /* Compute the new clip_pane but do not add it yet. */ BLI_ASSERT_UNIT_V3(sctx->ret.no); sctx->runtime.occlusion_plane = occlusion_plane_create(