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.
No comments:
Post a Comment