Fix T46099: snapping failed on objects with some NULL-dimension in their bbox.

Added a helper that ensures a bbox has some non-NULL dimension along all its axes.

Also, fixed some (rather unlikely) NULL dereference cases (though it should not in this context,
`BKE_object_boundbox_get()` can return NULL).
This commit is contained in:
Bastien Montagne 2015-09-14 12:51:04 +02:00
parent 2db71782e7
commit 34843a855e
Notes: blender-bot 2023-02-14 08:40:27 +01:00
Referenced by issue #46099, blender 2.76 testbuild2 problem with snapping
3 changed files with 84 additions and 4 deletions

View File

@ -143,6 +143,8 @@ bool BKE_boundbox_ray_hit_check(
void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]);
void BKE_boundbox_calc_size_aabb(const struct BoundBox *bb, float r_size[3]);
void BKE_boundbox_minmax(const struct BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3]);
struct BoundBox *BKE_boundbox_ensure_minimum_dimensions(
struct BoundBox *bb, struct BoundBox *bb_temp, const float epsilon);
struct BoundBox *BKE_object_boundbox_get(struct Object *ob);
void BKE_object_dimensions_get(struct Object *ob, float vec[3]);

View File

@ -2665,6 +2665,66 @@ void BKE_boundbox_minmax(const BoundBox *bb, float obmat[4][4], float r_min[3],
}
}
/**
* Returns a BBox which each dimensions are at least epsilon.
* \note In case a given dimension needs to be enlarged, its final value will be in [epsilon, 3 * epsilon] range.
*
* \param bb the input bbox to check.
* \param bb_temp the temp bbox to modify (\a bb content is never changed).
* \param epsilon the minimum dimension to ensure.
* \return either bb (if nothing needed to be changed) or bb_temp.
*/
BoundBox *BKE_boundbox_ensure_minimum_dimensions(BoundBox *bb, BoundBox *bb_temp, const float epsilon)
{
if (fabsf(bb->vec[0][0] - bb->vec[4][0]) < epsilon) {
/* Flat along X axis... */
*bb_temp = *bb;
bb = bb_temp;
bb->vec[0][0] -= epsilon;
bb->vec[1][0] -= epsilon;
bb->vec[2][0] -= epsilon;
bb->vec[3][0] -= epsilon;
bb->vec[4][0] += epsilon;
bb->vec[5][0] += epsilon;
bb->vec[6][0] += epsilon;
bb->vec[7][0] += epsilon;
}
if (fabsf(bb->vec[0][1] - bb->vec[3][1]) < epsilon) {
/* Flat along Y axis... */
if (bb != bb_temp) {
*bb_temp = *bb;
bb = bb_temp;
}
bb->vec[0][1] -= epsilon;
bb->vec[1][1] -= epsilon;
bb->vec[4][1] -= epsilon;
bb->vec[5][1] -= epsilon;
bb->vec[2][1] += epsilon;
bb->vec[3][1] += epsilon;
bb->vec[6][1] += epsilon;
bb->vec[7][1] += epsilon;
}
if (fabsf(bb->vec[0][2] - bb->vec[1][2]) < epsilon) {
/* Flat along Z axis... */
if (bb != bb_temp) {
*bb_temp = *bb;
bb = bb_temp;
}
bb->vec[0][2] -= epsilon;
bb->vec[3][2] -= epsilon;
bb->vec[4][2] -= epsilon;
bb->vec[7][2] -= epsilon;
bb->vec[1][2] += epsilon;
bb->vec[2][2] += epsilon;
bb->vec[5][2] += epsilon;
bb->vec[6][2] += epsilon;
}
return bb;
}
BoundBox *BKE_object_boundbox_get(Object *ob)
{
BoundBox *bb = NULL;

View File

@ -1527,8 +1527,17 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
if (do_bb) {
BoundBox *bb = BKE_object_boundbox_get(ob);
if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) {
return retval;
if (bb) {
BoundBox bb_temp;
/* We cannot aford a bbox with some null dimension, which may happen in some cases...
* Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) {
return retval;
}
}
}
else if (do_ray_start_correction) {
@ -2151,8 +2160,17 @@ static bool peelDerivedMesh(
* test against boundbox first
* */
if (looptri_num > 16) {
struct BoundBox *bb = BKE_object_boundbox_get(ob);
test = BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, NULL);
BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
BoundBox bb_temp;
/* We cannot aford a bbox with some null dimension, which may happen in some cases...
* Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
test = BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, NULL);
}
}
if (test == true) {