diff options
-rw-r--r-- | source/blender/blenkernel/intern/constraint.c | 4 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_math_matrix.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_matrix.c | 20 |
3 files changed, 24 insertions, 2 deletions
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 415c84a776d..580a8a7a505 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -312,7 +312,7 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[ if (ob->parent) { /* 'subtract' parent's effects from owner */ mul_m4_m4m4(diff_mat, ob->parent->obmat, ob->parentinv); - invert_m4_m4(imat, diff_mat); + invert_m4_m4_safe(imat, diff_mat); mul_m4_m4m4(mat, imat, mat); } else { @@ -323,7 +323,7 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[ normalize_m4(diff_mat); zero_v3(diff_mat[3]); - invert_m4_m4(imat, diff_mat); + invert_m4_m4_safe(imat, diff_mat); mul_m4_m4m4(mat, imat, mat); } } diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index af251480ece..e59c557b327 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -166,6 +166,8 @@ void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon); bool has_zero_axis_m4(float matrix[4][4]); +void invert_m4_m4_safe(float Ainv[4][4], float A[4][4]); + /****************************** Transformations ******************************/ void scale_m3_fl(float R[3][3], float scale); diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index eb5c5f4aab4..3dd6c667494 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -2110,3 +2110,23 @@ bool has_zero_axis_m4(float matrix[4][4]) len_squared_v3(matrix[1]) < FLT_EPSILON || len_squared_v3(matrix[2]) < FLT_EPSILON; } + +void invert_m4_m4_safe(float Ainv[4][4], float A[4][4]) +{ + if (!invert_m4_m4(Ainv, A)) { + float Atemp[4][4]; + + copy_m4_m4(Atemp, A); + + /* Matrix is degenerate (e.g. 0 scale on some axis), ideally we should + * never be in this situation, but try to invert it anyway with tweak. + */ + Atemp[0][0] += 1e-8f; + Atemp[1][1] += 1e-8f; + Atemp[2][2] += 1e-8f; + + if (!invert_m4_m4(Ainv, Atemp)) { + return unit_m4(Ainv); + } + } +} |