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]: 3267c91b4d
This commit is contained in:
parent
cc58682344
commit
7fb8e475d9
Notes:
blender-bot
2023-02-13 22:39:58 +01:00
Referenced by issue #99270, Regression: Bones using Empties as Custom Shapes cannot be selected properly Referenced by issue #98661, 3.2: Potential candidates for corrective releases
|
@ -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]);
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue