[Bf-blender-cvs] [ff4f14b21a4] master: Fix T102053: snap fails with instances of geometry nodes

Germano Cavalcante noreply at git.blender.org
Mon Nov 7 12:27:42 CET 2022


Commit: ff4f14b21a42e65de49f073bba2e6de81569d07a
Author: Germano Cavalcante
Date:   Sun Nov 6 12:24:20 2022 -0300
Branches: master
https://developer.blender.org/rBff4f14b21a42e65de49f073bba2e6de81569d07a

Fix T102053: snap fails with instances of geometry nodes

As instances are often generated geometries, we cannot rely on the data
provided by `DupliObject::ob`.

Use `DupliObject::ob_data` when possible.

This required a major refactor in the code as the output variables are
now gathered in context and easier to access.

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

M	source/blender/editors/transform/transform_snap_object.cc

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

diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc
index 2fab789afca..54085295e9e 100644
--- a/source/blender/editors/transform/transform_snap_object.cc
+++ b/source/blender/editors/transform/transform_snap_object.cc
@@ -35,6 +35,7 @@
 #include "BKE_layer.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_runtime.h"
+#include "BKE_mesh_wrapper.h"
 #include "BKE_object.h"
 #include "BKE_tracking.h"
 
@@ -125,6 +126,28 @@ struct SnapObjectContext {
     eSnapMode snap_to_flag;
     bool has_occlusion_plane; /* Ignore plane of occlusion in curves. */
   } runtime;
+
+  /* Output. */
+  struct {
+    /* Location of snapped point on target surface. */
+    float loc[3];
+    /* Normal of snapped point on target surface. */
+    float no[3];
+    /* Index of snapped element on target object (-1 when no valid index is found). */
+    int index;
+    /* Matrix of target object (may not be #Object.object_to_world with dupli-instances). */
+    float obmat[4][4];
+    /* List of #SnapObjectHitDepth (caller must free). */
+    ListBase *hit_list;
+    /* Snapped object. */
+    Object *ob;
+    /* Snapped data. */
+    ID *data;
+
+    float dist_sq;
+
+    bool is_edit;
+  } ret;
 };
 
 /** \} */
@@ -140,20 +163,20 @@ struct SnapObjectContext {
  * - In rare cases there is no evaluated mesh available and a null result doesn't imply an
  *   edit-mesh, so callers need to account for a null edit-mesh too, see: T96536.
  */
-static const Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide)
+static ID *data_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide)
 {
-  const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
   bool use_hide = false;
 
   switch (ob_eval->type) {
     case OB_MESH: {
+      Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
       if (BKE_object_is_in_editmode(ob_eval)) {
         if (edit_mode_type == SNAP_GEOM_EDIT) {
           return nullptr;
         }
 
-        const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval);
-        const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval);
+        Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval);
+        Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval);
 
         if ((edit_mode_type == SNAP_GEOM_FINAL) && editmesh_eval_final) {
           if (editmesh_eval_final->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
@@ -170,7 +193,10 @@ static const Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type,
           use_hide = true;
         }
       }
-      break;
+      if (r_use_hide) {
+        *r_use_hide = use_hide;
+      }
+      return (ID *)me_eval;
     }
     default:
       break;
@@ -178,7 +204,7 @@ static const Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type,
   if (r_use_hide) {
     *r_use_hide = use_hide;
   }
-  return me_eval;
+  return (ID *)ob_eval->data;
 }
 
 /** \} */
@@ -368,12 +394,14 @@ static BVHTreeFromEditMesh *snap_object_data_editmesh_treedata_get(SnapObjectCon
 /** \name Iterator
  * \{ */
 
-using IterSnapObjsCallback = void (*)(SnapObjectContext *sctx,
-                                      const SnapObjectParams *params,
-                                      Object *ob_eval,
-                                      const float obmat[4][4],
-                                      bool is_object_active,
-                                      void *data);
+using IterSnapObjsCallback = eSnapMode (*)(SnapObjectContext *sctx,
+                                           const SnapObjectParams *params,
+                                           Object *ob_eval,
+                                           ID *ob_data,
+                                           const float obmat[4][4],
+                                           bool is_object_active,
+                                           bool use_hide,
+                                           void *data);
 
 static bool snap_object_is_snappable(const SnapObjectContext *sctx,
                                      const eSnapTargetSelect snap_target_select,
@@ -433,11 +461,14 @@ static bool snap_object_is_snappable(const SnapObjectContext *sctx,
 /**
  * Walks through all objects in the scene to create the list of objects to snap.
  */
-static void iter_snap_objects(SnapObjectContext *sctx,
-                              const SnapObjectParams *params,
-                              IterSnapObjsCallback sob_callback,
-                              void *data)
+static eSnapMode iter_snap_objects(SnapObjectContext *sctx,
+                                   const SnapObjectParams *params,
+                                   IterSnapObjsCallback sob_callback,
+                                   void *data)
 {
+  eSnapMode ret = SCE_SNAP_MODE_NONE;
+  eSnapMode tmp;
+
   Scene *scene = DEG_get_input_scene(sctx->runtime.depsgraph);
   ViewLayer *view_layer = DEG_get_input_view_layer(sctx->runtime.depsgraph);
   const eSnapTargetSelect snap_target_select = params->snap_target_select;
@@ -455,13 +486,34 @@ static void iter_snap_objects(SnapObjectContext *sctx,
       ListBase *lb = object_duplilist(sctx->runtime.depsgraph, sctx->scene, obj_eval);
       LISTBASE_FOREACH (DupliObject *, dupli_ob, lb) {
         BLI_assert(DEG_is_evaluated_object(dupli_ob->ob));
-        sob_callback(sctx, params, dupli_ob->ob, dupli_ob->mat, is_object_active, data);
+        if ((tmp = sob_callback(sctx,
+                                params,
+                                dupli_ob->ob,
+                                dupli_ob->ob_data,
+                                dupli_ob->mat,
+                                is_object_active,
+                                false,
+                                data)) != SCE_SNAP_MODE_NONE) {
+          ret = tmp;
+        }
       }
       free_object_duplilist(lb);
     }
 
-    sob_callback(sctx, params, obj_eval, obj_eval->object_to_world, is_object_active, data);
+    bool use_hide = false;
+    ID *ob_data = data_for_snap(obj_eval, params->edit_mode_type, &use_hide);
+    if ((tmp = sob_callback(sctx,
+                            params,
+                            obj_eval,
+                            ob_data,
+                            obj_eval->object_to_world,
+                            is_object_active,
+                            use_hide,
+                            data)) != SCE_SNAP_MODE_NONE) {
+      ret = tmp;
+    }
   }
+  return ret;
 }
 
 /** \} */
@@ -662,14 +714,17 @@ static bool raycastMesh(SnapObjectContext *sctx,
   }
 
   /* Test BoundBox */
-  const BoundBox *bb = BKE_object_boundbox_get(ob_eval);
-  if (bb) {
-    /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
-    if (!isect_ray_aabb_v3_simple(
-            ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, nullptr)) {
-      return retval;
+  if (ob_eval->data == me_eval) {
+    const BoundBox *bb = BKE_object_boundbox_get(ob_eval);
+    if (bb) {
+      /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+      if (!isect_ray_aabb_v3_simple(
+              ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, nullptr)) {
+        return retval;
+      }
     }
   }
+
   /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
    * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
    */
@@ -896,26 +951,21 @@ struct RaycastObjUserData {
   uint ob_index;
   /* read/write args */
   float *ray_depth;
-  /* return args */
-  float *r_loc;
-  float *r_no;
-  int *r_index;
-  Object **r_ob;
-  float (*r_obmat)[4];
-  ListBase *r_hit_list;
+
   bool use_occlusion_test;
-  bool ret;
 };
 
 /**
  * \note Duplicate args here are documented at #snapObjectsRay
  */
-static void raycast_obj_fn(SnapObjectContext *sctx,
-                           const SnapObjectParams *params,
-                           Object *ob_eval,
-                           const float obmat[4][4],
-                           bool is_object_active,
-                           void *data)
+static eSnapMode raycast_obj_fn(SnapObjectContext *sctx,
+                                const SnapObjectParams *params,
+                                Object *ob_eval,
+                                ID *ob_data,
+                                const float obmat[4][4],
+                                bool is_object_active,
+                                bool use_hide,
+                                void *data)
 {
   RaycastObjUserData *dt = static_cast<RaycastObjUserData *>(data);
   const uint ob_index = dt->ob_index++;
@@ -924,92 +974,74 @@ static void raycast_obj_fn(SnapObjectContext *sctx,
   float *ray_depth = dt->ray_depth;
 
   bool retval = false;
+  bool is_edit = false;
   if (use_occlusion_test) {
     if (ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE)) {
       /* Do not hit objects that are in wire or bounding box
        * display mode. */
-      return;
+      return SCE_SNAP_MODE_NONE;
     }
   }
 
-  switch (ob_eval->type) {
-    case OB_MESH: {
-      const eSnapEditType edit_mode_type = params->edit_mode_type;
-      bool use_hide = false;
-      const Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide);
-      if (me_eval == nullptr) {
-        BMEditMesh *em = BKE_editmesh_from_object(ob_eval);
-        if (UNLIKELY(!em)) { /* See #mesh_for_snap doc-string. */
-          return;
-        }
-        BLI_assert_msg(em == BKE_editmesh_from_object(DEG_get_original_object(ob_eval)),
-                       "Make sure there is only one pointer for looptris");
-        retval = raycastEditMesh(sctx,
-                                 params,
-                                 dt->ray_start,
-                                 dt->ray_dir,
-                                 ob_eval,
-                                 em,
-                                 obmat,
-                                 ob_index,
-                                 ray_depth,
-                                 dt->r_loc,
-                                 dt->r_no,
-       

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list