diff options
-rw-r--r-- | source/blender/editors/armature/armature_relations.c | 5 | ||||
-rw-r--r-- | source/blender/editors/curve/editcurve.c | 5 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_data.c | 7 | ||||
-rw-r--r-- | source/blender/editors/mesh/meshtools.c | 5 | ||||
-rw-r--r-- | source/blender/editors/object/object_add.c | 51 |
5 files changed, 53 insertions, 20 deletions
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) |