diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-12-15 01:41:22 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-12-15 01:41:22 +0400 |
commit | 071a43f7540cbb263d3b974203c4c2cb0757464c (patch) | |
tree | 5fd85a95f2ac039fd20442dafefdec5d6b41eb44 /source/blender/blenlib/intern/math_matrix.c | |
parent | f1d487d1c452559afe395f578c84ff29121b24d0 (diff) |
Fix #33497: seting object scale to 0 on one axis made moving verts in edit mode
impossible. In this case matrix inversion failed and didn't give a useful result.
Now it falls back to a pseudoinverse in that case, so that moving along the
other axes still works.
There may be other places that can benefit from this, but this is a place where
it has no significant performance impact, doing this in general for e.g. bone
matrices could be quite slow.
Diffstat (limited to 'source/blender/blenlib/intern/math_matrix.c')
-rw-r--r-- | source/blender/blenlib/intern/math_matrix.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 70eb5c1bb60..a0c372c13dc 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -504,8 +504,7 @@ void sub_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4]) m1[i][j] = m2[i][j] - m3[i][j]; } -/* why not make this a standard part of the API? */ -static float determinant_m3_local(float m[3][3]) +float determinant_m3_array(float m[3][3]) { return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) - m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) + @@ -534,7 +533,7 @@ int invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon) adjoint_m3_m3(m1, m2); /* then determinant old matrix! */ - det = determinant_m3_local(m2); + det = determinant_m3_array(m2); success = (fabsf(det) > epsilon); @@ -569,7 +568,7 @@ int invert_m3_m3(float m1[3][3], float m2[3][3]) adjoint_m3_m3(m1, m2); /* then determinant old matrix! */ - det = determinant_m3_local(m2); + det = determinant_m3_array(m2); success = (det != 0.0f); @@ -1903,3 +1902,16 @@ void pseudoinverse_m4_m4(float Ainv[4][4], float A[4][4], float epsilon) mul_serie_m4(Ainv, U, Wm, V, NULL, NULL, NULL, NULL, NULL); } + +void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon) +{ + /* try regular inverse when possible, otherwise fall back to slow svd */ + if(!invert_m3_m3(Ainv, A)) { + float tmp[4][4], tmpinv[4][4]; + + copy_m4_m3(tmp, A); + pseudoinverse_m4_m4(tmpinv, tmp, epsilon); + copy_m3_m4(Ainv, tmpinv); + } +} + |