Fix #121161: Regression: Frame Selected Includes Hidden Bones

Refactor `BKE_armature_min_max()` so that it calls `BKE_pose_minmax(ob,
use_hidden=false)`. The former took neither bone visibility nor custom
bone shapes into account when computing the bounding box. Now these two
are unified, fixing the regression.

`BKE_armature_min_max()` is now basically a thin wrapper that uses more
modern C++ types in its signature. This will be cleaned up in a
follow-up refactor commit.

Another difference is that these functions return the AABB in different
coordinate spaces (object vs. world). This isn't done entirely correctly
(just transforming the two extreme points), but in a way that is
symmetrical with `BKE_object_minmax()`.

Pull Request: https://projects.blender.org/blender/blender/pulls/121739
This commit is contained in:
Sybren A. Stüvel
2024-05-13 12:41:14 +02:00
parent 547067f599
commit 6212c3c374
4 changed files with 19 additions and 14 deletions

View File

@@ -155,7 +155,10 @@ void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature
void BKE_armature_transform(bArmature *arm, const float mat[4][4], bool do_props);
std::optional<blender::Bounds<blender::float3>> BKE_armature_min_max(const bPose *pose);
/**
* Return the posed Armature bounding box in object-local coordinate space.
*/
std::optional<blender::Bounds<blender::float3>> BKE_armature_min_max(const Object *ob);
/**
* Calculate the axis-aligned bounds of `pchan` in world-space,

View File

@@ -22,6 +22,7 @@
#include "BLI_listbase.h"
#include "BLI_math_geom.h"
#include "BLI_math_matrix.h"
#include "BLI_math_matrix.hh"
#include "BLI_math_rotation.h"
#include "BLI_math_vector.h"
#include "BLI_span.hh"
@@ -3020,21 +3021,23 @@ void BKE_pose_where_is(Depsgraph *depsgraph, Scene *scene, Object *ob)
/** \name Calculate Bounding Box (Armature & Pose)
* \{ */
std::optional<blender::Bounds<blender::float3>> BKE_armature_min_max(const bPose *pose)
std::optional<blender::Bounds<blender::float3>> BKE_armature_min_max(const Object *ob)
{
if (BLI_listbase_is_empty(&pose->chanbase)) {
return std::nullopt;
}
BLI_assert(ob->data);
BLI_assert(ob->type == OB_ARMATURE);
BLI_assert(GS(static_cast<ID *>(ob->data)->name) == ID_AR);
blender::float3 min(std::numeric_limits<float>::max());
blender::float3 max(std::numeric_limits<float>::lowest());
/* For now, we assume BKE_pose_where_is has already been called
* (hence we have valid data in pachan). */
LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
minmax_v3v3_v3(min, max, pchan->pose_head);
minmax_v3v3_v3(min, max, pchan->pose_tail);
const bool has_minmax = BKE_pose_minmax(ob, &min[0], &max[0], false, false);
if (!has_minmax) {
return std::nullopt;
}
return blender::Bounds<blender::float3>{min, max};
return blender::Bounds<blender::float3>{math::transform_point(ob->world_to_object(), min),
math::transform_point(ob->world_to_object(), max)};
}
void BKE_pchan_minmax(const Object *ob,

View File

@@ -3569,7 +3569,7 @@ std::optional<blender::Bounds<blender::float3>> BKE_object_boundbox_get(const Ob
case OB_LATTICE:
return BKE_lattice_minmax(static_cast<const Lattice *>(ob->data));
case OB_ARMATURE:
return BKE_armature_min_max(ob->pose);
return BKE_armature_min_max(ob);
case OB_GPENCIL_LEGACY:
return BKE_gpencil_data_minmax(static_cast<const bGPdata *>(ob->data));
case OB_CURVES:

View File

@@ -39,8 +39,7 @@ eSnapMode snapArmature(SnapObjectContext *sctx,
const bool is_editmode = arm->edbo != nullptr;
if (is_editmode == false) {
const std::optional<blender::Bounds<blender::float3>> bounds = BKE_armature_min_max(
ob_eval->pose);
const std::optional<blender::Bounds<blender::float3>> bounds = BKE_armature_min_max(ob_eval);
if (bounds && !nearest2d.snap_boundbox(bounds->min, bounds->max)) {
return retval;
}