Fix T90808: wrong BoundBox after undo curve selection

There are two functions that recalculate the boundbox of an object:
- One that considers the evaluated geometry
- Another that only considers the object's `data`.

Most of the time, the bound box is calculated on the final object
(with modifiers), so it doesn't seem right to just rely on `ob->data`
to recalculate the `ob->runtime.bb`.

Be sure to calculate the BoundBox based on the final geometry and
only use `ob->data` as a fallback

Differential Revision: https://developer.blender.org/D12282
This commit is contained in:
Germano Cavalcante 2021-11-24 14:32:19 -03:00
parent 7a7ae4df43
commit 752c6d668b
Notes: blender-bot 2023-02-14 07:08:26 +01:00
Referenced by commit dae9917915, Fix T93384: Objects with Constraints to curves have wrong locations on file load
Referenced by issue #94282, Geometry Nodes causes insane dimension property
Referenced by issue #94113, Local view + Geometry Nodes is broken for instances
Referenced by issue #93384, Regression: objects with Constraints to curves have wrong locations on file load (curve boundingbox problem)
Referenced by issue #90808, BoundBox/Dimensions of curve not showing correct values
4 changed files with 41 additions and 31 deletions

View File

@ -240,6 +240,7 @@ void BKE_object_dimensions_set(struct Object *ob, const float value[3], int axis
void BKE_object_empty_draw_type_set(struct Object *ob, const int value);
void BKE_object_boundbox_flag(struct Object *ob, int flag, const bool set);
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);
void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden);
bool BKE_object_minmax_dupli(struct Depsgraph *depsgraph,
struct Scene *scene,

View File

@ -66,8 +66,6 @@
using blender::IndexRange;
static void boundbox_displist_object(Object *ob);
static void displist_elem_free(DispList *dl)
{
if (dl) {
@ -1528,7 +1526,9 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
ob->runtime.geometry_set_eval = new GeometrySet(std::move(geometry));
}
boundbox_displist_object(ob);
if (ob->runtime.bb) {
ob->runtime.bb->flag |= BOUNDBOX_DIRTY;
}
}
void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3])
@ -1551,30 +1551,3 @@ void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3])
zero_v3(max);
}
}
/* this is confusing, there's also min_max_object, applying the obmat... */
static void boundbox_displist_object(Object *ob)
{
BLI_assert(ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT));
/* Curve's BB is already calculated as a part of modifier stack,
* here we only calculate object BB based on final display list. */
/* object's BB is calculated from final displist */
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), __func__);
}
const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
if (mesh_eval) {
BKE_object_boundbox_calc_from_mesh(ob, mesh_eval);
}
else {
float min[3], max[3];
INIT_MINMAX(min, max);
BKE_displist_minmax(&ob->runtime.curve_cache->disp, min, max);
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
}
}

View File

@ -3965,6 +3965,37 @@ void BKE_object_boundbox_calc_from_mesh(Object *ob, const Mesh *me_eval)
ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
}
bool BKE_object_boundbox_calc_from_evaluated_geometry(Object *ob)
{
blender::float3 min, max;
INIT_MINMAX(min, max);
if (ob->runtime.geometry_set_eval) {
ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max);
}
else if (const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob)) {
if (!BKE_mesh_wrapper_minmax(mesh_eval, min, max)) {
return false;
}
}
else if (ob->runtime.curve_cache) {
BKE_displist_minmax(&ob->runtime.curve_cache->disp, min, max);
}
else {
return false;
}
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), __func__);
}
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
return true;
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -282,7 +282,12 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
/** Bounding box from evaluated geometry. */
static void object_sync_boundbox_to_original(Object *object_orig, Object *object_eval)
{
BoundBox *bb = BKE_object_boundbox_get(object_eval);
BoundBox *bb = object_eval->runtime.bb;
if (!bb || (bb->flag & BOUNDBOX_DIRTY)) {
BKE_object_boundbox_calc_from_evaluated_geometry(object_eval);
}
bb = BKE_object_boundbox_get(object_eval);
if (bb != NULL) {
if (object_orig->runtime.bb == NULL) {
object_orig->runtime.bb = MEM_mallocN(sizeof(*object_orig->runtime.bb), __func__);