[Bf-blender-cvs] [7fb8e475d9e] blender-v3.2-release: Fix T99270: bones using empties as custom shapes can't be selected

Campbell Barton noreply at git.blender.org
Fri Jul 15 15:04:20 CEST 2022


Commit: 7fb8e475d9eca93bff87f011b29ac8aa7bc0ebca
Author: Campbell Barton
Date:   Thu Jul 7 14:57:43 2022 +1000
Branches: blender-v3.2-release
https://developer.blender.org/rB7fb8e475d9eca93bff87f011b29ac8aa7bc0ebca

Fix T99270: bones using empties as custom shapes can't be selected

Regression in [0] which didn't account for the bounds of empty objects.
Add support support calculating bounds from empty draw-type to use in
pose-bone culling.

[0]: 3267c91b4d5caab7da8aef071a446dd2e86f86a9

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

M	source/blender/blenkernel/BKE_armature.h
M	source/blender/blenkernel/BKE_object.h
M	source/blender/blenkernel/intern/armature.c
M	source/blender/blenkernel/intern/object.cc
M	source/blender/draw/engines/overlay/overlay_armature.c

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

diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 888de38dcc7..98f9f8e3588 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -158,9 +158,13 @@ struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
  * or the custom object's bounds (if the bone uses a custom object).
  * Visual elements such as the envelopes radius & bendy-bone spline segments are *not* included,
  * making this not so useful for viewport culling.
+ *
+ * \param use_empty_drawtype: When enabled, the draw type of empty custom-objects is tagen into
+ * account when calculating the bounds.
  */
 void BKE_pchan_minmax(const struct Object *ob,
                       const struct bPoseChannel *pchan,
+                      const bool use_empty_drawtype,
                       float r_min[3],
                       float r_max[3]);
 /**
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index faf878dfc2a..6ed05bc267a 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -369,6 +369,9 @@ void BKE_object_empty_draw_type_set(struct Object *ob, int value);
 
 void BKE_object_boundbox_calc_from_mesh(struct Object *ob, const struct Mesh *me_eval);
 bool BKE_object_boundbox_calc_from_evaluated_geometry(struct Object *ob);
+/**
+ * Calculate visual bounds from an empty objects draw-type.
+ */
 void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], bool use_hidden);
 bool BKE_object_minmax_dupli(struct Depsgraph *depsgraph,
                              struct Scene *scene,
@@ -376,6 +379,7 @@ bool BKE_object_minmax_dupli(struct Depsgraph *depsgraph,
                              float r_min[3],
                              float r_max[3],
                              bool use_hidden);
+bool BKE_object_minmax_empty_drawtype(const struct Object *ob, float r_min[3], float r_max[3]);
 
 /**
  * Sometimes min-max isn't enough, we need to loop over each point.
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index dfe3d9cc310..622ecde6a91 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -2661,13 +2661,30 @@ BoundBox *BKE_armature_boundbox_get(Object *ob)
   return ob->runtime.bb;
 }
 
-void BKE_pchan_minmax(const Object *ob, const bPoseChannel *pchan, float r_min[3], float r_max[3])
+void BKE_pchan_minmax(const Object *ob,
+                      const bPoseChannel *pchan,
+                      const bool use_empty_drawtype,
+                      float r_min[3],
+                      float r_max[3])
 {
   const bArmature *arm = ob->data;
   const bPoseChannel *pchan_tx = (pchan->custom && pchan->custom_tx) ? pchan->custom_tx : pchan;
-  const BoundBox *bb_custom = ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) ?
-                                  BKE_object_boundbox_get(pchan->custom) :
-                                  NULL;
+  const BoundBox *bb_custom = NULL;
+  BoundBox bb_custom_buf;
+
+  if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) {
+    float min[3], max[3];
+    if (use_empty_drawtype && (pchan->custom->type == OB_EMPTY) &&
+        BKE_object_minmax_empty_drawtype(pchan->custom, min, max)) {
+      memset(&bb_custom_buf, 0x0, sizeof(bb_custom_buf));
+      BKE_boundbox_init_from_minmax(&bb_custom_buf, min, max);
+      bb_custom = &bb_custom_buf;
+    }
+    else {
+      bb_custom = BKE_object_boundbox_get(pchan->custom);
+    }
+  }
+
   if (bb_custom) {
     float mat[4][4], smat[4][4], rmat[4][4], tmp[4][4];
     scale_m4_fl(smat, PCHAN_CUSTOM_BONE_LENGTH(pchan));
@@ -2704,7 +2721,7 @@ bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden
       if (pchan->bone && (!((use_hidden == false) && (PBONE_VISIBLE(arm, pchan->bone) == false)) &&
                           !((use_select == true) && ((pchan->bone->flag & BONE_SELECTED) == 0)))) {
 
-        BKE_pchan_minmax(ob, pchan, r_min, r_max);
+        BKE_pchan_minmax(ob, pchan, false, r_min, r_max);
         changed = true;
       }
     }
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index 0bc092bec4f..d3301f46559 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -3990,6 +3990,70 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re
   return true;
 }
 
+bool BKE_object_minmax_empty_drawtype(const struct Object *ob, float r_min[3], float r_max[3])
+{
+  BLI_assert(ob->type == OB_EMPTY);
+  float3 min(0), max(0);
+
+  bool ok = false;
+  const float radius = ob->empty_drawsize;
+
+  switch (ob->empty_drawtype) {
+    case OB_ARROWS: {
+      max = float3(radius);
+      ok = true;
+      break;
+    }
+    case OB_PLAINAXES:
+    case OB_CUBE:
+    case OB_EMPTY_SPHERE: {
+      min = float3(-radius);
+      max = float3(radius);
+      ok = true;
+      break;
+    }
+    case OB_CIRCLE: {
+      max[0] = max[2] = radius;
+      min[0] = min[2] = -radius;
+      ok = true;
+      break;
+    }
+    case OB_SINGLE_ARROW: {
+      max[2] = radius;
+      ok = true;
+      break;
+    }
+    case OB_EMPTY_CONE: {
+      min = float3(-radius, 0.0f, -radius);
+      max = float3(radius, radius * 2.0f, radius);
+      ok = true;
+      break;
+    }
+    case OB_EMPTY_IMAGE: {
+      const float *ofs = ob->ima_ofs;
+      /* NOTE: this is the best approximation that can be calculated without loading the image. */
+      min[0] = ofs[0] * radius;
+      min[1] = ofs[1] * radius;
+      max[0] = radius + (ofs[0] * radius);
+      max[1] = radius + (ofs[1] * radius);
+      /* Since the image aspect can shrink the bounds towards the object origin,
+       * adjust the min/max to account for that.  */
+      for (int i = 0; i < 2; i++) {
+        CLAMP_MAX(min[i], 0.0f);
+        CLAMP_MIN(max[i], 0.0f);
+      }
+      ok = true;
+      break;
+    }
+  }
+
+  if (ok) {
+    copy_v3_v3(r_min, min);
+    copy_v3_v3(r_max, max);
+  }
+  return ok;
+}
+
 bool BKE_object_minmax_dupli(Depsgraph *depsgraph,
                              Scene *scene,
                              Object *ob,
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index ea0c2f287a6..e38695c76ab 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -2102,7 +2102,7 @@ static void pchan_culling_calc_bsphere(const Object *ob,
 {
   float min[3], max[3];
   INIT_MINMAX(min, max);
-  BKE_pchan_minmax(ob, pchan, min, max);
+  BKE_pchan_minmax(ob, pchan, true, min, max);
   mid_v3_v3v3(r_bsphere->center, min, max);
   r_bsphere->radius = len_v3v3(min, r_bsphere->center);
 }



More information about the Bf-blender-cvs mailing list