[Bf-blender-cvs] [5eb7aa5ebba] master: Fix T80077: Objects disappear when joining with a zero scaled axis

Campbell Barton noreply at git.blender.org
Tue Aug 25 06:42:09 CEST 2020


Commit: 5eb7aa5ebba9cf6a88e0433ac679ad8f810c5c47
Author: Campbell Barton
Date:   Tue Aug 25 14:32:10 2020 +1000
Branches: master
https://developer.blender.org/rB5eb7aa5ebba9cf6a88e0433ac679ad8f810c5c47

Fix T80077: Objects disappear when joining with a zero scaled axis

Use invert_m4_m4_safe_ortho when joining objects so zero scaled axis
doesn't cause all points to be scaled to zero.

Instead geometry is left un-scaled on degenerate axes.

Report a warning in this case since users may want to adjust the
active objects scale.

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

M	source/blender/editors/armature/armature_relations.c
M	source/blender/editors/curve/editcurve.c
M	source/blender/editors/gpencil/gpencil_data.c
M	source/blender/editors/mesh/meshtools.c
M	source/blender/editors/object/object_add.c

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

diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index caf9cc3b2a3..2efb7315b89 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -304,6 +304,10 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op)
     return OPERATOR_CANCELLED;
   }
 
+  /* Inverse transform for all selected armatures in this object,
+   * See #object_join_exec for detailed comment on why the safe version is used. */
+  invert_m4_m4_safe_ortho(oimat, ob_active->obmat);
+
   /* Get edit-bones of active armature to add edit-bones to */
   ED_armature_to_edit(arm);
 
@@ -334,7 +338,6 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op)
       // BASACT->flag &= ~OB_MODE_POSE;
 
       /* Find the difference matrix */
-      invert_m4_m4(oimat, ob_active->obmat);
       mul_m4_m4m4(mat, oimat, ob_iter->obmat);
 
       /* Copy bones and posechannels from the object to the edit armature */
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 075a1fcf832..4e12063544e 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -6923,8 +6923,9 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op)
 
   BLI_listbase_clear(&tempbase);
 
-  /* trasnform all selected curves inverse in obact */
-  invert_m4_m4(imat, ob_active->obmat);
+  /* Inverse transform for all selected curves in this object,
+   * See #object_join_exec for detailed comment on why the safe version is used. */
+  invert_m4_m4_safe_ortho(imat, ob_active->obmat);
 
   CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
     if (ob_iter->type == ob_active->type) {
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 6264cac0973..6c003b85edd 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -2819,7 +2819,10 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
 
         sub_v3_v3v3(offset_global, ob_active->loc, ob_iter->obmat[3]);
         copy_m3_m4(bmat, ob_active->obmat);
-        invert_m3_m3(imat, bmat);
+
+        /* Inverse transform for all selected curves in this object,
+         * See #object_join_exec for detailed comment on why the safe version is used. */
+        invert_m3_m3_safe_ortho(imat, bmat);
         mul_m3_v3(imat, offset_global);
         mul_v3_m3v3(offset_local, imat, offset_global);
 
@@ -2830,7 +2833,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
 
           /* recalculate all stroke points */
           BKE_gpencil_parent_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat);
-          invert_m4_m4(inverse_diff_mat, diff_mat);
+          invert_m4_m4_safe_ortho(inverse_diff_mat, diff_mat);
 
           Material *ma_src = NULL;
           LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_new->frames) {
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index e89d2726c06..bd14919d1d7 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -590,8 +590,9 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
   loopofs = 0;
   polyofs = 0;
 
-  /* inverse transform for all selected meshes in this object */
-  invert_m4_m4(imat, ob->obmat);
+  /* Inverse transform for all selected meshes in this object,
+   * See #object_join_exec for detailed comment on why the safe version is used. */
+  invert_m4_m4_safe_ortho(imat, ob->obmat);
 
   /* Add back active mesh first.
    * This allows to keep things similar as they were, as much as possible
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index a59d8136f47..72180d58ecb 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -3167,20 +3167,45 @@ static int object_join_exec(bContext *C, wmOperator *op)
     }
   }
 
+  int ret = OPERATOR_CANCELLED;
   if (ob->type == OB_MESH) {
-    return ED_mesh_join_objects_exec(C, op);
-  }
-  if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
-    return ED_curve_join_objects_exec(C, op);
-  }
-  if (ob->type == OB_ARMATURE) {
-    return ED_armature_join_objects_exec(C, op);
-  }
-  if (ob->type == OB_GPENCIL) {
-    return ED_gpencil_join_objects_exec(C, op);
-  }
-
-  return OPERATOR_CANCELLED;
+    ret = ED_mesh_join_objects_exec(C, op);
+  }
+  else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+    ret = ED_curve_join_objects_exec(C, op);
+  }
+  else if (ob->type == OB_ARMATURE) {
+    ret = ED_armature_join_objects_exec(C, op);
+  }
+  else if (ob->type == OB_GPENCIL) {
+    ret = ED_gpencil_join_objects_exec(C, op);
+  }
+
+  if (ret & OPERATOR_FINISHED) {
+    /* Even though internally failure to invert is accounted for with a fallback,
+     * show a warning since the result may not be what the user expects. See T80077.
+     *
+     * Failure to invert the matrix is typically caused by zero scaled axes
+     * (which can be caused by constraints, even if the input scale isn't zero).
+     *
+     * Internally the join functions use #invert_m4_m4_safe_ortho which creates
+     * an inevitable matrix from one that has one or more degenerate axes.
+     *
+     * In most cases we don't worry about special handling for non-inevitable matrices however for
+     * joining objects there may be flat 2D objects where it's not obvious the scale is zero.
+     * In this case, using #invert_m4_m4_safe_ortho works as well as we can expect,
+     * joining the contents, flattening on the axis that's zero scaled.
+     * If the zero scale is removed, the data on this axis remains un-scaled
+     * (something that wouldn't work for #invert_m4_m4_safe). */
+    float imat_test[4][4];
+    if (!invert_m4_m4(imat_test, ob->obmat)) {
+      BKE_report(op->reports,
+                 RPT_WARNING,
+                 "Active object final transform has one or more zero scaled axes");
+    }
+  }
+
+  return ret;
 }
 
 void OBJECT_OT_join(wmOperatorType *ot)



More information about the Bf-blender-cvs mailing list