Commit: 34843a855e6b45cffbc0cd0ffae2d688e6ee1168
Author: Bastien Montagne
Date:   Mon Sep 14 12:51:04 2015 +0200
Branches: master
https://developer.blender.org/rB34843a855e6b45cffbc0cd0ffae2d688e6ee1168

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).

===================================================================

M       source/blender/blenkernel/BKE_object.h
M       source/blender/blenkernel/intern/object.c
M       source/blender/editors/transform/transform_snap.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_object.h 
b/source/blender/blenkernel/BKE_object.h
index 15ebfb5..6c5081d 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -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]);
diff --git a/source/blender/blenkernel/intern/object.c 
b/source/blender/blenkernel/intern/object.c
index fa20607..526a71b 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -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;
diff --git a/source/blender/editors/transform/transform_snap.c 
b/source/blender/editors/transform/transform_snap.c
index 867e862..f604073 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -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) {

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to