I have following problem in my Java3D application:
javax.vecmath.SingularMatrixException: cannot invert matrix at javax.media.j3d.Transform3D.invertGeneral(Transform3D.java:3099) at javax.media.j3d.Transform3D.invert(Transform3D.java:2864)
Occurring of this problem is deterministic and it happen always in same scene processing. Source code of java class Transform3D.java is here. Piece of code where is problem rooted is:
final void invertGeneral(Transform3D t1) { double tmp[] = new double[16]; int row_perm[] = new int[4]; int i, r, c; // Use LU decomposition and backsubstitution code specifically // for floating-point 4x4 matrices. // Copy source matrix to tmp System.arraycopy(t1.mat, 0, tmp, 0, tmp.length); // Calculate LU decomposition: Is the matrix singular? if (!luDecomposition(tmp, row_perm)) { // Matrix has no inverse throw new SingularMatrixException(J3dI18N.getString("Transform3D1")); } // Perform back substitution on the identity matrix // luDecomposition will set rot[] & scales[] for use // in luBacksubstituation mat[0] = 1.0; mat[1] = 0.0; mat[2] = 0.0; mat[3] = 0.0; mat[4] = 0.0; mat[5] = 1.0; mat[6] = 0.0; mat[7] = 0.0; mat[8] = 0.0; mat[9] = 0.0; mat[10] = 1.0; mat[11] = 0.0; mat[12] = 0.0; mat[13] = 0.0; mat[14] = 0.0; mat[15] = 1.0; luBacksubstitution(tmp, row_perm, this.mat); type = 0; dirtyBits = ALL_DIRTY; }
Obviously piece of resource bundle defining error messages looks like:
Transform3D1=cannot invert matrix
The root of the problem is using of class Transform3D. In my code is this class used like this:
Point3d center = new Point3d(); boundingSphere.getCenter(center); Transform3D lookAt = new Transform3D(); lookAt.lookAt(new Point3d(0.0, 0.0, -40.0), center, new Vector3d(0.0, 1.0, 0.0)); lookAt.invert();
Than it's easy. Method lookAt have following parameters:
- eye - the location of the eye (Point3d)
- center - a point in the virtual world where the eye is looking (Point3d)
- up - an up vector specifying the frustum's up direction (Vector3d)
In my case is solution pretty simple. When center and eye are same points slightly adjust one of them like this:
Point3d center = new Point3d(0.0, 0.0, -40.0); Point3d eye = new Point3d(0.0, 0.0, -40.0); Vector3d up = new Vector3d(0.0, 1.0, 0.0); Transform3D lookAt = new Transform3D(); lookAt.lookAt(eye, center, up); if (Double.compare(Double.NaN, lookAt.determinant()) == 0) { eye = new Point3d(eye.x + 0.001F, eye.y + 0.001F, eye.z + 0.001F); lookAt.lookAt(eye, center, up); } lookAt.invert();
And than it works fine. One think is strange. Determinant of singular matrix should be zero not specific value "Not a Number". Probably it's because of determinant computing implementation.