From 752c6d668bcb9a6b357734f7e124a6b605ac9d9b Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Wed, 24 Nov 2021 14:32:19 -0300 Subject: 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 --- source/blender/blenkernel/BKE_object.h | 1 + source/blender/blenkernel/intern/displist.cc | 33 +++--------------------- source/blender/blenkernel/intern/object.cc | 31 ++++++++++++++++++++++ source/blender/blenkernel/intern/object_update.c | 7 ++++- 4 files changed, 41 insertions(+), 31 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 4e53af5562f..6e1486be0be 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -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, diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc index 0bf436aa8b2..f511bb2b65e 100644 --- a/source/blender/blenkernel/intern/displist.cc +++ b/source/blender/blenkernel/intern/displist.cc @@ -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; - } -} diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index 4b01ee29828..45e14675107 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -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; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 7e15ac5de5d..34a899b2e91 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -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__); -- cgit v1.2.3