Thursday, July 24, 2014

SingularMatrixException: cannot invert matrix - solved

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)
When one of eye, scene and center vectors is linear combination of others than matrix is singular.Detect that transformation is singular matrix could be done for example by determinant. So code could be easily fixed. Nice think is that it works fine in Java3D 1.5 release by Sun. This doesn't work in Java3D 1.6 which could be found at github.com/hharrison/java3d-core/.

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.

Java 3D - differences in rendering on different platform

I have tool for generating images of LEGO models. I works easy user upload LEGO model source file and tool generate with JAVA 3d model and store image or images.

After some time of using this tool I met strange problem when it's deployed on my Mac and on productions system - Debian generated images looks slightly different. When I put these images in one window I was surprised how much images are different. Look at the following picture.

I'll investigate this problem more closely and I'll update this article.

Monday, June 16, 2014

Java 3D problem - No X11 DISPLAY variable was set

I have following exception during Java3D application startup:

No X11 DISPLAY variable was set, but this program performed an operation which requires it.
java.awt.HeadlessException:
No X11 DISPLAY variable was set, but this program performed an operation which requires it.
       at sun.java2d.HeadlessGraphicsEnvironment.getDefaultScreenDevice(HeadlessGraphicsEnvironment.java:77)

Problem is quite easy understand and resolve. Java 3D drive don't know address of X11 windows server. X11 server address should be stored in environment variable "DISPLAY". Environment could be set up like this:

export DISPLAY=:0.0

This will work just in case that your X11 server is at localhost. How to find X11 server address is nicely described at http://stackoverflow.com/questions/784404/how-can-i-specify-a-display

Monday, June 9, 2014

Java 3D exception: TransformGroupRetained : Can't find hashKey

Following exception appears in my Java 3D application:

TransformGroupRetained : Can't find hashKey
Exception in thread "J3D-TransformStructureUpdateThread-1" java.lang.ArrayIndexOutOfBoundsException: -1
 at javax.media.j3d.TransformGroupRetained.updateChildLocalToVworld(TransformGroupRetained.java:979)
 at javax.media.j3d.TransformGroupRetained.updateChildLocalToVworld(TransformGroupRetained.java:961)
 at javax.media.j3d.TransformGroupRetained.processChildLocalToVworld(TransformGroupRetained.java:825)
 at javax.media.j3d.TransformStructure.processCurrentLocalToVworld(TransformStructure.java:306)
 at javax.media.j3d.TransformStructure.processMessages(TransformStructure.java:186)
 at javax.media.j3d.StructureUpdateThread.doWork(StructureUpdateThread.java:83)
 at javax.media.j3d.J3dThread.run(J3dThread.java:250)

In my case I incorrectly used one of available ways to hide and show part of 3D objects graph. I use javax.media.j3d.Link and when I wand to show specific subgraph I call:

link.setSharedGroup(mySharedGroup);

and similary I called when I want to hide some object I called:

link.setSharedGroup(null);

I works fine up to the moment when setSharedGroup was called with same object parameter more than once. It leads to "TransformGroupRetained : Can't find hashKey" Exception. Fix is quite simple:

if(link.getSharedGroup() == null){
    link.setSharedGroup(mySharedGroup);
}

and

if(link.getSharedGroup() != null){
    link.setSharedGroup(null);
}

This should help. Hopefully it will save you some time.

regards

Monday, June 2, 2014

Java 3D problem - java.lang.UnsatisfiedLinkError: Can't load library: /System/Library/Frameworks/gluegen-rt.Framework/gluegen-rt

Correctly set Java 3D in eclipse project could be tricky. I'll try to write down problems that I have met.

Compilation problem

Double check that there are latest (1.6.*) version of Java 3D at class path.

Caused by: java.lang.UnsatisfiedLinkError: Can't load library:

Following exception:
Caused by: java.lang.UnsatisfiedLinkError: Can't load library: /System/Library/Frameworks/gluegen-rt.Framework/gluegen-rt
Means that is class path is not 'gluegen-rt'. Check it in eclipse project setting.

Wednesday, May 28, 2014

Mac OS X 10.9 Mavericks how to install Java 3d

At the beginning I would like to point out that it's tricky. This guide helps you to run Java 3D from Eclipse environment.

Remove old Java 3D

At Maverick you can have ORACLE java 1.7 or Apple Java or both. Both of them comes with previous version of Java 3D, but this version is old not not so much useful. First of all this Java 3D versions should be removed from eclipse JRE. It could be done from following dialog "Eclipse" > "Preferences" > "Java" > "Installed JREs".

Find there JRE that will be used click on "Edit" and remove:
  • j3dutils.jar
  • j3dcore.jar
  • vecmath.jar

Get new Java 3D

From http://jogamp.org/deployment/java3d/1.6.0-pre10/ Download new versions of j3dutils.jar, j3dcore.jar and vecmath.jar and store them on disk. Old Java 3D version up 1.5.* which could be get from ORACLE is not compatible with 1.6.*. There is no backward compatibility in Java 1.6.*. Also ORACLE doesn't support Java 3D development.

Install new Java 3D

So open "Project" > "Properties" > "Java build path" and there select "Libraries" tab. Select "Add external jars" and add downloaded Java 3D libraries.

When you are done with it project should compile but not run.

Get latest JOGL

Java 3d is just API. Now you'll need layer between Java 3D API and mac OpenGL libraries. This layer is JOGL. From http://jogamp.org/deployment/jogamp-current/archive/ download file "jogamp-all-platforms.7z". And expand this package somewhere at your disk. For example muCommander could do it for you (for free).

Install latest JOGL

Now go again to project "Java build path" and in "Libraries" tab add external libraries from expanded JOGL package. Namely add:

  • gluegen-rt.jar
  • jogl-all.jar
Native libraries are not necessary until you are not making final distribution package.

Now your Java 3D project should compile and even run. So good luck.

Sunday, April 6, 2014

TOP explained

Very often when I look at linux command top I found difficult to fully understand the result. So following should remind me whats going on there.

top - 20:04:34 up 157 days, 17:22,  1 user,  load average: 2.52, 2.11, 1.23
Tasks: 102 total,   1 running, 101 sleeping,   0 stopped,   0 zombie
Cpu(s): 71.4%us,  0.2%sy,  0.0%ni, 28.3%id,  0.2%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   1018236k total,  1002152k used,    16084k free,    13600k buffers
Swap:  2064344k total,  1022604k used,  1041740k free,   183736k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                           
11025 honza     18   0  908m 596m 7292 S 285.9 60.0   2129:53 java                                                                                                                              
    1 root      15   0  2160  228  204 S  0.0  0.0   0:22.88 init                                                                                                                               
    2 root      RT  -5     0    0    0 S  0.0  0.0   0:03.42 migration/0                                                                                                                        
    3 root      34  19     0    0    0 S  0.0  0.0   0:00.03 ksoftirqd/0                                                                                                                        
    4 root      RT  -5     0    0    0 S  0.0  0.0   0:00.00 watchdog/0         

I'll describe just part that made me a problem.

Cpu(s) abbreviations

  • us: user cpu time (or) % CPU time spent in user space
  • sy: system cpu time (or) % CPU time spent in kernel space
  • ni: user nice cpu time (or) % CPU time spent on low priority processes
  • id: idle cpu time (or) % CPU time spent idle
  • wa: io wait cpu time (or) % CPU time spent in wait (on disk)
  • hi: hardware irq (or) % CPU time spent servicing/handling hardware interrupts
  • si: software irq (or) % CPU time spent servicing/handling software interrupts
  • st: steal time - - % CPU time in involuntary wait by virtual cpu while hypervisor

Column names

Column names abbreviations:
  • PID -- Process Id The task's unique process ID, which periodically wraps, though never restarting at zero.
  • PR -- Priority The priority of the task.
  • NI -- Nice value The nice value of the task. A negative nice value means higher priority, whereas a positive nice value means lower priority. Zero in this field simply means priority will not be adjusted in determining a task's dispatchability.
  • P -- Last used CPU (SMP) A number representing the last used processor. In a true SMP environment this will likely change frequently since the kernel intentionally uses weak affinity. Also, the very act of running top may break this weak affinity and cause more processes to change CPUs more often (because of the extra demand for cpu time).
  • %CPU -- CPU usage The task's share of the elapsed CPU time since the last screen update, expressed as a percentage of total CPU time. In a true SMP environment, if 'Irix mode' is Off, top will operate in 'Solaris mode' where a task's cpu usage will be divided by the total number of CPUs. You toggle 'Irix/Solaris' modes with the 'I' inter- active command.
  • TIME -- CPU Time Total CPU time the task has used since it started. When 'Cumulative mode' is On, each process is listed with the cpu time that it and its dead children has used. You toggle 'Cumulative mode' with 'S', which is a command-line option and an interactive command. See the 'S' interactive command for additional information regarding this mode.
  • TIME+ -- CPU Time, hundredths The same as 'TIME', but reflecting more granularity through hundredths of a second.
  • %MEM -- Memory usage (RES) A task's currently used share of available physical memory.
  • VIRT -- Virtual Image (kb) The total amount of virtual memory used by the task. It includes all code, data and shared libraries plus pages that have been swapped out. (Note: you can define the STATSIZE=1 environment variable and the VIRT will be calculated from the /proc/#/state VmSize field.) VIRT = SWAP + RES.
  • SWAP -- Swapped size (kb) The swapped out portion of a task's total virtual memory image.
  • RES -- Resident size (kb) The non-swapped physical memory a task has used. RES = CODE + DATA.
  • CODE -- Code size (kb) The amount of physical memory devoted to executable code, also known as the 'text resident set' size or TRS.
  • DATA -- Data+Stack size (kb) The amount of physical memory devoted to other than executable code, also known as the 'data resident set' size or DRS.
  • SHR -- Shared Mem size (kb) The amount of shared memory used by a task. It simply reflects memory that could be potentially shared with other processes.
  • nFLT -- Page Fault count The number of major page faults that have occurred for a task. A page fault occurs when a process attempts to read from or write to a virtual page that is not currently present in its address space. A major page fault is when disk access is involved in making that page available.
  • nDRT -- Dirty Pages count The number of pages that have been modified since they were last written to disk. Dirty pages must be written to disk before the corresponding physical memory location can be used for some other virtual page.
  • S -- Process Status The status of the task which can be one of:
    • 'D' = uninterruptible sleep
    • 'R' = running
    • 'S' = sleeping
    • 'T' = traced or stopped
    • 'Z' = zombie