Showing posts with label Java3D. Show all posts
Showing posts with label Java3D. Show all posts

Sunday, October 19, 2014

Access restriction: The constructor GraphicsConfigTemplate3D() is not accessible due to restriction on required library /System/Library/Java/Extensions/j3dcore.jar

This problem is reported by Eclipse. It's reason why project can't by compiled.

Problem is that default JRE include older 1.5 Java3D implementation which doesn't expose used GraphicsConfigTemplate3D() constructor. Solution is remove from eclipse build old 1.5 Java3D libraries and and new 1.6 to class paths.

How to configure it in eclipse is described it post Mac OS X 10.9 Mavericks how to install Java 3d.

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.

Thursday, March 13, 2014

Java3D and headless mode

Java3D headless mode is a way how to tell Java that there is not physical screen device and that there is no graphics acceleration. Headless model could be set in this way:

java -Djava.awt.headless=true 

In headless mode some object can't be instantiated, especially UI related objects from java.awt package like Button. More about headless could be found at http://www.oracle.com/technetwork/articles/javase/headless-136834.html.

Java3D application usually build 3D model and that draw it to Canvas3D. Sometimes server need to generate some images which are using Canvas3D. Sadly in headless mode it's not possible. Because it's not possible to instantiate Canvas3D. Lets look at following code:

public void testSimple() throws Exception {
 System.setProperty("java.awt.headless", "true");
 GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D();
 GraphicsConfiguration config = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getBestConfiguration(template);
 Canvas3D canvas3d = new Canvas3D(config, true);
}

In headless mode GraphicsEnvironment.getLocalGraphicsEnvironment() return instance of HeadlessGraphicsEnvironment. Method HeadlessGraphicsEnvironment is implemented in following way:

   public GraphicsDevice getDefaultScreenDevice()
         throws HeadlessException {
         throw new HeadlessException();
    }

So it always throw HeadlessException. Because of that it seems that Java3D can't be used with enabled headless mode.