Java3D stereo

classic Classic list List threaded Threaded
22 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Java3D stereo

jodyv
From : jdverret@tx.rr.com

Hello everyone.

First, congratulations to the team on your very fast port for Java3D to use
jogl!  I'm very impressed with the much improved performance over Java3d 1.5.1

However, I cannot seem to get true stereo working with Java3D
(see example code StereoTestJava3D.java)

However, it works just fine using the jogl.
(see example code StereoTestJogl.java)

The symptom when I try StereoTestJava3D is that I get this message when trying

 "Stereo is not support, you should only see the left red cone."

(and BTW, I don't see the red nor the green cone)

I'm running Linux Fedora 15 and have the latest nvidia drivers.

Thanks in advance.
-------------------------------------------------
//StereoTestJava3D
import java.util.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;

/**
 * Pure immediate mode stereo example program for stereo. In pure
 * immediate mode, the renderer must be stopped on the Canvas being
 * rendered into. In our example, this is done immediately after the
 * canvas is created. A separate thread is started up to do the
 * immediate mode rendering.
 */

public class StereoTestJava3D extends javax.swing.JFrame implements Runnable {

    private SimpleUniverse univ = null;
    private BranchGroup scene = null;

    // Set this to true when the graphics card use shared z buffer
    // in stereo mode.
    public static String defaultSharedStereoZbuffer = Boolean.TRUE.toString();

    private boolean sharedStereoZbuffer;
    private boolean stereoSupport;
    private Canvas3D canvas;
    private GraphicsContext3D gc;
    private Shape3D leftConeBody, rightConeBody;
    private Shape3D leftConeCap, rightConeCap;
    private Transform3D cmt = new Transform3D();
    private Vector3f leftTrans, rightTrans;

    // One rotation (2*PI radians) every 6 seconds
    private Alpha rotAlpha = new Alpha(-1, 6000);
    private double angle;

    // Compute data which is common for both
    // left and right eye
    void computeSharedData() {
        // Compute angle of rotation based on alpha value
        angle = rotAlpha.value() * 2.0*Math.PI;
        cmt.rotY(angle);
    }

    // Render the geometry in right eye
    void renderLeft() {
        cmt.setTranslation(leftTrans);
        gc.setModelTransform(cmt);

        if (sharedStereoZbuffer) {
            // Graphics card shared same z buffer in stereo mode,
            // in this case we have to explicitly clearing both
            // frame buffers.
            gc.clear();
        }
        gc.draw(leftConeBody);
        gc.draw(leftConeCap);
    }

    // Render the geometry for right eye
     void renderRight() {
        cmt.setTranslation(rightTrans);
        gc.setModelTransform(cmt);

        if (sharedStereoZbuffer) {
            // Graphics card shared same z buffer in stereo mode,
            // in this case we have to explicitly clearing both
            // frame buffers.
            gc.clear();
        }
        gc.draw(rightConeBody);
        gc.draw(rightConeCap);
    }

    //
    // Run method for our immediate mode rendering thread.
    //
    public void run() {
        // Set up Graphics context
        gc = canvas.getGraphicsContext3D();

        // We always need to set this for PureImmediate
        // stereo mode
        gc.setBufferOverride(true);

        Color3f lightColor = new Color3f(1, 1, 1);
        Vector3f lightDir = new Vector3f(0, 0, -1);
        DirectionalLight light = new DirectionalLight(lightColor,
                                                      lightDir);

        gc.addLight(light);

        Appearance redApp = new Appearance();
        Appearance greenApp = new Appearance();
        Color3f ambientColor = new Color3f(0, 0, 0);
        Color3f emissiveColor = new Color3f(0, 0, 0);
        Color3f diffuseColor =  new Color3f(1, 0, 0);
        Color3f specularColor =  new Color3f(1, 1, 1);
        redApp.setMaterial(new Material(ambientColor, emissiveColor,
                                        diffuseColor, specularColor, 5));
        diffuseColor =  new Color3f(0, 1, 0);

        greenApp.setMaterial(new Material(ambientColor, emissiveColor,
                                          diffuseColor, specularColor, 5));

        // Set up geometry
        Cone leftCone = new Cone(0.4f, 0.6f,
                                 Primitive.GENERATE_NORMALS, redApp);
        Cone rightCone = new Cone(0.4f, 0.6f,
                                  Primitive.GENERATE_NORMALS, greenApp);
        leftConeBody  = leftCone.getShape(Cone.BODY);
        leftConeCap   = leftCone.getShape(Cone.CAP);

        rightConeBody = rightCone.getShape(Cone.BODY);
        rightConeCap  = rightCone.getShape(Cone.CAP);
        leftTrans = new Vector3f(-0.6f, 0, 0);
        rightTrans = new Vector3f(0.6f, 0, 0);


        while (true) {
            // compute data which is can be used
            // for both left and right eye
            computeSharedData();

            if (stereoSupport) {
                if (!sharedStereoZbuffer) {
                    gc.setStereoMode(GraphicsContext3D.STEREO_BOTH);
                    // This clear both left and right buffers, we
                    // must set STEREO_BOTH before it. Otherwise
                    // it only clear LEFT or RIGHT buffer unless
                    // this is invoke twice for each buffer.
                    gc.clear();
                }

                gc.setStereoMode(GraphicsContext3D.STEREO_LEFT);
                renderLeft();

                gc.setStereoMode(GraphicsContext3D.STEREO_RIGHT);
                renderRight();
            } else {
                gc.clear();
                renderLeft();
            }
            // This swap both left and right buffers so
            // there is no need to set STEREO_BOTH before it
            canvas.swap();

            // Be polite to other threads !
            Thread.yield();
        }
    }


    private void createUniverse() {
        // Preferred to use Stereo
        GraphicsConfigTemplate3D gct = new GraphicsConfigTemplate3D();
        gct.setStereo(GraphicsConfigTemplate3D.PREFERRED);

        GraphicsConfiguration config =
            GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getBestConfiguration(gct);

        canvas = new Canvas3D(config);
        Map map = canvas.queryProperties();

        stereoSupport = canvas.getStereoAvailable();

        if (stereoSupport) {
            System.out.println("This machine support stereo, you should see a red cone on the left and green cone on the right.");
            // User can overide the above default behavior using
            // java3d property.
            String str = System.getProperty("j3d.sharedstereozbuffer",
                                            defaultSharedStereoZbuffer);
            sharedStereoZbuffer = (new Boolean(str)).booleanValue();

System.out.println("**********   Enabling stereo");

       canvas.setStereoEnable( true );

        } else {
            System.out.println("Stereo is not support, you should only see the left red cone.");
        }

        if (!canvas.getDoubleBufferAvailable()) {
            System.out.println("Double buffer is not support !");
        }

        // we must stop the Renderer in PureImmediate mode

        canvas.stopRenderer();

        // Create simple universe with view branch
        univ = new SimpleUniverse(canvas);

        // This will move the ViewPlatform back a bit so the
        // objects in the scene can be viewed.
        univ.getViewingPlatform().setNominalViewingTransform();

        // Ensure at least 5 msec per frame (i.e., < 200Hz)
        univ.getViewer().getView().setMinimumFrameCycleTime(5);

        // Start a new thread that will continuously render
        (new Thread(this)).start();
    }

    /**
     * Creates new form StereoTestJava3D
     */
    public StereoTestJava3D() {
        // Initialize the GUI components
        initComponents();

        // Create Canvas3D and SimpleUniverse; add canvas to drawing panel
        createUniverse();
        drawingPanel.add(canvas, java.awt.BorderLayout.CENTER);
    }
    // ----------------------------------------------------------------

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        drawingPanel = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("StereoTestJava3D");
        drawingPanel.setLayout(new java.awt.BorderLayout());

        drawingPanel.setPreferredSize(new java.awt.Dimension(512, 256));
        getContentPane().add(drawingPanel, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new StereoTestJava3D().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel drawingPanel;
    // End of variables declaration//GEN-END:variables

}
===========================================
===========================================
// StereoTestJogl
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.*;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.util.gl2.GLUT;

public class StereoTestJogl implements GLEventListener {

   private GLU glu = new GLU();
   private GLUT glut = new GLUT();

   public static void main(String[] args) {
     StereoTestJogl StereoTestJogl = new StereoTestJogl();

     GLCapabilities glCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2));
     glCaps.setStereo(true);
     GLCanvas canvas = new GLCanvas(glCaps);
     canvas.addGLEventListener(StereoTestJogl);

     final Frame frame = new Frame("Stereo Test");
     frame.add(canvas);
     frame.setSize(800, 600);
     frame.setLocationRelativeTo(null);
     final FPSAnimator animator = new FPSAnimator(canvas, 60);
     frame.addWindowListener(new WindowAdapter() {
             public void windowClosing(WindowEvent e) {
                     animator.stop();
                     frame.dispose();
                     System.exit(0);
             }
     });
     frame.setVisible(true);

     animator.start();
     canvas.requestFocusInWindow();
   }

   public void init(GLAutoDrawable drawable) {
     GL2 gl = drawable.getGL().getGL2();

     gl.glMatrixMode(GL2.GL_PROJECTION);
     gl.glLoadIdentity();
     glu.gluPerspective(45.0f, 800/600.0f, 1, 100);

     gl.glMatrixMode(GL2.GL_MODELVIEW);
     gl.glLoadIdentity();
     glu.gluLookAt(0, 0, 4, 0, 0, 0, 0, 1, 0);

     gl.glEnable(GL.GL_DEPTH_TEST);
     gl.glEnable(GL2.GL_LIGHTING);
     gl.glEnable(GL2.GL_LIGHT0);
   }

   public void display(GLAutoDrawable drawable) {
     GL2 gl = drawable.getGL().getGL2();

     gl.glDrawBuffer(GL2GL3.GL_BACK_LEFT);
     gl.glClear(GL.GL_COLOR_BUFFER_BIT |GL.GL_DEPTH_BUFFER_BIT);
     gl.glPushMatrix();
     gl.glTranslated(-0.2, 0, 0);
     drawScene(gl);
     gl.glPopMatrix();

     gl.glDrawBuffer(GL2GL3.GL_BACK_RIGHT);
     gl.glClear(GL.GL_COLOR_BUFFER_BIT |GL.GL_DEPTH_BUFFER_BIT);
     gl.glPushMatrix();
     gl.glTranslated(0.2, 0, 0);
     drawScene(gl);
     gl.glPopMatrix();
   }

   private void drawScene(GL2 gl) {
      glut.glutSolidTeapot(1);
//     glut.glutSolidTorus( 0.5,1,50,50);
//    glut.glutSolidDodecahedron();
//    glut.glutSolidTetrahedron();
   }

   public void dispose(GLAutoDrawable drawable) {}

   public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {}
}



jdverret@tx.rr.com
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

bjoern
This post was updated on .
Hi Harvey, Hi Julien, and Hi Jody,

first of all, thanks a lot to you - Julien and Harvey - for starting saving Java 3D! We are also using Java 3D for our CELLmicrocosmos project, and as these are quite large software projects running since several years (area: Bioinformatics & Visualization), we were quite unhappy about the situation of J3D. Still, it runs on many machines, but as you said, on Mac OS X it is already a huge problem.

So we are happy that you started porting J3D to JOGL. I made a few tests with our major projects MembraneEditor and CellExplorer, and both work very fine with your j3d-1.6.0-pre8. I did it by using Eclipse, importing Jogamp as a separate project, binding it e.g. to the CellExplorer project via the Build Path and then I just substituted the standard J3D jars (j3dcore/j3dutil/vecmath). Moreover, I use the ancient j3d-org-geom-core.jar. I just left it in the Build Path, and still it seems to work.

However, I did only some first tests, to I may add small bugs later.

But, here the topic of jodyv is Stereo, and this is also a major topic of our projects. And yes, we have the same problem as Jody, stereo does not work.

To help you to evaluate this problem, I just coded some small example how the standard stereo method of Java3D works (I stole Jody's cone ;-) . It is even more easy than the one of Jody, as it does not use immediate mode and this means, the this Jody's example is closer to OpenGL. I use only Java 3D coding now.

Here is the source code:

----------------------------------------------------------------------------------------------------------------

import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;

import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.GraphicsConfigTemplate3D;
import javax.media.j3d.Material;
import javax.media.j3d.PointLight;
import javax.swing.JFrame;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
import com.sun.j3d.utils.geometry.Cone;
import com.sun.j3d.utils.geometry.Primitive;
import com.sun.j3d.utils.universe.SimpleUniverse;

/**
 * Simple Java 3D Stereoscopy test example.
 *
 * There are two ways to activate stereoscopy here:
 * 1. Use the code block _STEREO_CANVAS_ and the last code block in
 *    StereoTestJava3DStandard()
 * 2. Deactivate the code blocks mentioned in 1. and activate the line
 *    SimpleUniverse universe = new SimpleUniverse(); and start the
 *    program with the VM argument -Dj3d.stereo=PREFERRED
 *
 * You need some professional 3D equipment such as NVIDIA Quadro (FX) or
 * ATI/ASUS FireGL, compatible monitors and to activate the stereoscopic
 * capabilities in the graphics driver preferences.
 *
 * @author bjoern
 */
public class StereoTestJava3DStandard {

        public StereoTestJava3DStandard() {

                BranchGroup rootBG = new BranchGroup();

                BoundingSphere universeBounds = new BoundingSphere(new Point3d(0.0,
                                0.0, 0.0), 100000.0);

                // add directional light (for front of object)
                Color3f lightColor = new Color3f(1, 1, 1);
                Vector3f lightDir = new Vector3f(0, 0, -1);
                DirectionalLight dirLight = new DirectionalLight(true, lightColor,
                                lightDir);
                rootBG.addChild(dirLight);
                dirLight.setInfluencingBounds(universeBounds);

                // add point light (for bottom of object)
                PointLight pointLight = new PointLight(true, new Color3f(1, 1, 1),
                                new Point3f(0, -1, 0), new Point3f(1, 1, 1));
                pointLight.setInfluencingBounds(universeBounds);
                rootBG.addChild(pointLight);

                // add colored cone
                Appearance redApp = new Appearance();
                Color3f ambientColor = new Color3f(0, 0, 0);
                Color3f emissiveColor = new Color3f(0, 0, 0);
                Color3f diffuseColor = new Color3f(1, 0, 0);
                Color3f specularColor = new Color3f(1, 1, 1);
                redApp.setMaterial(new Material(ambientColor, emissiveColor,
                                diffuseColor, specularColor, 5));
                Cone cone = new Cone(0.4f, 0.6f, Primitive.GENERATE_NORMALS, 64, 64,
                                redApp);
                rootBG.addChild(cone);

                // create stereo canvas and universe (-> _STEREO_CANVAS_)
                GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D();
                template.setStereo(GraphicsConfigTemplate3D.PREFERRED);
                template.setSceneAntialiasing(GraphicsConfigTemplate3D.PREFERRED);
                GraphicsConfiguration config = GraphicsEnvironment
                                .getLocalGraphicsEnvironment().getDefaultScreenDevice()
                                .getBestConfiguration(template);
                Canvas3D stereoCanvas = new Canvas3D(config);
                SimpleUniverse universe = new SimpleUniverse(stereoCanvas);

                // create standard canvas and universe (used only without
                // _STEREO_CANVAS_)
                // activate 3D stereoscopy with VM argument:
                // -Dj3d.stereo=PREFERRED
                // SimpleUniverse universe = new SimpleUniverse();

                universe.getViewingPlatform().setNominalViewingTransform();
                universe.addBranchGraph(rootBG);

                // attach orbit behavior for mouse navigation
                OrbitBehavior orbit = new OrbitBehavior(universe.getCanvas(),
                                OrbitBehavior.REVERSE_ALL);
                orbit.setSchedulingBounds(universeBounds);
                universe.getViewingPlatform().setViewPlatformBehavior(orbit);

                // create the window and add the 3D canvas (used only with
                // _STEREO_CANVAS_)
                JFrame frame = new JFrame();
                frame.setSize(new Dimension(200, 200));
                frame.setMinimumSize(new Dimension(200, 200));
                frame.add(stereoCanvas);
                frame.setVisible(true);

        }

        public static void main(String[] args) {

                // start the program
                new StereoTestJava3DStandard();

        }

}


----------------------------------------------------------------------------------------------------------------

So, if I use this example with standard Java 3D libraries on my computer (incl. PNY/NVIDIA Quadro 4000 + Planar StereoMirror Monitor), the cone is rendered for the left and the right eye. And now - this should be interesting also for Jody - if I use your libraries, then neither the left nor the right perspective is rendered. Exceptionally the centered perspective is rendered (cyclopean perspective). In other words, stereo is completely ignored.

By the way, these are the files found in my build path:

gluegen-rt-natives-windows-i586.jar
j3dcore.jar
j3dutils.jar
joal-natives-windows-i586.jar
jocl-natives-windows-i586.jar
jogl-all-natives-windows-amd64.jar
jogl-all-noawt.jar
jogl-awt.jar
vecmath.jar

You can run the example above in two ways. If you just copy it this way, then it will try to start stereoscopy mode, if it is available by the hardware. The other way is, to use just a completely regular canvas (see the comment in the source code) and use then the VM argument :
-Dj3d.stereo=PREFERRED
This was the standard way how I used all these years the stereo method.

I just tested it now on Windows 7 (64 bit). Of course, I also tested Jody's example. With the old libraries, I see one cone for each eye. With the JOGL J3D libraries, I see only - oh - a black background. I think, this is the case, because Jody's pipeline addresses explicitely the left and right eye.

So, maybe it is really easy for Harvey to fix this problem by just adding some swith, but it might also be a little bit complicated. For example, in J3D you can easily manipulate the eye distance in a stereo environment with this method:

----------------------------------------------------------------------------------------------------------------

        public void setEyeDistance(double d) {

                        Canvas3D canvas = universe.getCanvas();
                        if (canvas == null)
                                return;
                       
                        double lx = -d/2;
                        Point3d left = new Point3d();
                        canvas.getView().getPhysicalBody().getLeftEyePosition(left);
                        left.setX(lx);
                       
                        double rx = d/2;
                        Point3d right= new Point3d();
                        canvas.getView().getPhysicalBody().getRightEyePosition(right);
                        right.setX(rx);
                       
                        canvas.setLeftManualEyeInImagePlate(left);
                        canvas.setRightManualEyeInImagePlate(right);
                       
                        canvas.getView().getPhysicalBody().setLeftEyePosition(left);
                        canvas.getView().getPhysicalBody().setRightEyePosition(right);
                       
        }

----------------------------------------------------------------------------------------------------------------

So if you - Harvey - already were coding in this area, maybe it runs already, if you attach a small swith. But if you did not work with this PhysicalBody methods, it might be even more work.

So if there are more questions and I can help in this issue, please let me know.

However, thanks a lot for your great work!!!
Björn
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

babor
Hi everyone,

We are using Java3D as a rendering engine in our open source scientific visualization software VisNow (http://visnow.icm.edu.pl).
So far we were forced to stick to v1.5.2 as it was no longer developed, but it was some problem recently especially on MacOS X.
So I will add another compliments to Harvey and other - great work porting Java3D to JOGL!!! We'll switch to it in our software soon - right after we confirm all tests are working properly.

As far as stereo rendering - we are using stereo under Linux (Linux 64-bit + Nvidia Quadro 6000 + 331.38 driver) and have quite similar problems as in your posts, but with some exceptions. I'll summarize them in points for our setup:
- we observed that stereo is working properly on JRE 1.6 and it does not work on JRE 1.7
- it applies to both old Java3D 1.5.2 and new 1.6.0-pre9
- the result on JRE 1.7 is that only one image eye is visible
- pure JOGL stereo works fine on both platforms 1.6 and 1.7
- the code above works properly (1.6) only with changes:
    template.setStereo(GraphicsConfigTemplate3D.REQUIRED);
    stereoCanvas.setStereoEnable(true);

It seems that something has changed in Java 7 that is causing Canvas3D to improperly interpret stereo rendering.
I've only found one such report similar to our problems and related to Java 7:
http://stackoverflow.com/questions/21239229/stereo-problems-on-linux-using-java-7-how-to-change-the-gc-of-a-component-afte?rq=1

Unfortunately Harvey told me that he's short on time now to take a deeper look into the problem.

Anyone have any ideas?


Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

gouessej
Administrator
Hi

Please can you indicate exactly which version of Java you use under GNU Linux? Please test at least once with OpenJDK. If there is a regression in Java itself, this bug should be reproducible without Java3D and reported against Java.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

babor
This post was updated on .
Hi,

I've tested this issue under Oracle JDK 1.7.0_51, OpenJDK 1.7.0_51, IBM
JDK 1.7, Oracle JDK 1.6.0_43 and IBM JDK 1.6. See below for details. On
all platforms it works fine on Java 6 and does not work with Java 7.
See also this post for reference:
http://stackoverflow.com/questions/21239229/stereo-problems-on-linux-using-java-7-how-to-change-the-gc-of-a-component-afte?rq=1


1) Oracle JDK 1.7.0_51 - stereo rendering does not work with Java3D
Canvas3D, works fine with JOGL GLCanvas

java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 24.51-b03
java.vm.vendor = Oracle Corporation
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
java.specification.version = 1.7
java.runtime.version = 1.7.0_51-b13
os.arch = amd64
os.name = Linux
os.version = 3.11.10-7-desktop


2) OpenJDK 1.7.0_51 - stereo rendering does not work with Java3D
Canvas3D, works fine with JOGL GLCanvas

java version "1.7.0_51"
OpenJDK Runtime Environment (IcedTea 2.4.4) (suse-24.13.5-x86_64)
OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)

java.runtime.name = OpenJDK Runtime Environment
java.vm.version = 24.45-b08
java.vm.vendor = Oracle Corporation
java.vm.name = OpenJDK 64-Bit Server VM
java.specification.version = 1.7
java.runtime.version = 1.7.0_51-b00
os.arch = amd64
os.name = Linux
os.version = 3.11.10-7-desktop

3) IBM JDK 1.7.0 - stereo rendering does not work with Java3D Canvas3D,
works fine with JOGL GLCanvas

java version "1.7.0"
Java(TM) SE Runtime Environment (build pxa6470_27-20131115_04)
IBM J9 VM (build 2.7, JRE 1.7.0 Linux amd64-64 Compressed References
20131114_175264 (JIT enabled, AOT enabled)
J9VM - R27_Java727_GA_20131114_0833_B175264
JIT  - tr.r13.java_20131113_50523
GC   - R27_Java727_GA_20131114_0833_B175264_CMPRSS
J9CL - 20131114_175264)
JCL - 20131113_01 based on Oracle 7u45-b18

java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 2.7
java.vm.vendor = IBM Corporation
java.vm.name = IBM J9 VM
java.specification.version = 1.7
java.runtime.version = pxa6470_27-20131115_04
os.arch = amd64
os.name = Linux
os.version = 3.11.10-7-desktop


4) Oracle JDK 1.6.0_43 - stereo rendering works properly with both
Java3D Canvas3Dand JOGL GLCanvas

java version "1.6.0_43"
Java(TM) SE Runtime Environment (build 1.6.0_43-b01)
Java HotSpot(TM) 64-Bit Server VM (build 20.14-b01, mixed mode)

java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 20.14-b01
java.vm.vendor = Sun Microsystems Inc.
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
java.specification.version = 1.6
java.runtime.version = 1.6.0_43-b01
os.arch = amd64
os.name = Linux
os.version = 3.11.10-7-desktop


5) IBM JDK 1.6.0 - stereo rendering works properly with both Java3D
Canvas3Dand JOGL GLCanvas

java version "1.6.0"
Java(TM) SE Runtime Environment (build pxa6460sr15fp1-20140110_01(SR15 FP1))
IBM J9 VM (build 2.4, JRE 1.6.0 IBM J9 2.4 Linux amd64-64
jvmxa6460sr15-20131231_180656 (JIT enabled, AOT enabled)
J9VM - 20131231_180656
JIT  - r9_20130920_46510ifx3
GC   - GA24_Java6_SR15_20131231_1152_B180656)
JCL  - 20140107_01

java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 2.4
java.vm.vendor = IBM Corporation
java.vm.name = IBM J9 VM
java.specification.version = 1.6
java.runtime.version = pxa6460sr15fp1-20140110_01 (SR15 FP1)
os.arch = amd64
os.name = Linux
os.version = 3.11.10-7-desktop
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

Xerxes RÃ¥nby
In reply to this post by babor
The changes seen in the Java 7 update are caused by the following bug-fix 5 years ago:
http://bugs.java.com/view_bug.do?bug_id=6804747
http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/rev/66d6db0a1de6


Is it possibly for you to set the stereo GC on the parent component before you add the Canvas3D to it?


2014-03-06 10:57 GMT+01:00 babor [via jogamp] <[hidden email]>:
Hi everyone,

We are using Java3D as a rendering engine in our open source scientific visualization software VisNow (http://visnow.icm.edu.pl).
So far we were forced to stick to v1.5.2 as it was no longer developed, but it was some problem recently especially on MacOS X.
So I will add another compliments to Harvey and other - great work porting Java3D to JOGL!!! We'll switch to it in our software soon - right after we confirm all tests are working properly.

As far as stereo rendering - we are using stereo under Linux (Linux 64-bit + Nvidia Quadro 6000 + 331.38 driver) and have quite similar problems as in your posts, but with some exceptions. I'll summarize them in points for our setup:
- we observed that stereo is working properly on JRE 1.6 and it does not work on JRE 1.7
- it applies to both old Java3D 1.5.2 and new 1.6.0-pre9
- the result on JRE 1.7 is that only one image eye is visible
- pure JOGL stereo works fine on both platforms 1.6 and 1.7
- the code above works properly (1.6) only with changes:
    template.setStereo(GraphicsConfigTemplate3D.REQUIRED);
    stereoCanvas.setStereoEnable(true);

It seems that something has changed in Java 7 that is causing Canvas3D to improperly interpret stereo rendering.
I've only found one such report similar to our problems and related to Java 7:
http://stackoverflow.com/questions/21239229/stereo-problems-on-linux-using-java-7-how-to-change-the-gc-of-a-component-afte?rq=1

Unfortunately Harvey told me that he's short on time now to take a deeper look into the problem.

Anyone have any ideas?





If you reply to this email, your message will be added to the discussion below:
http://forum.jogamp.org/Java3D-stereo-tp4029914p4031784.html
To start a new topic under java3d, email [hidden email]
To unsubscribe from jogamp, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

babor
Xerxes RÃ¥nby wrote
Is it possibly for you to set the stereo GC on the parent component before
you add the Canvas3D to it?
First of all, even if you could do that it seems highly impractical - every time you wish to add Canvas3D to any container you'd have to set GC to the whole hierarchy up to the JFrame or Window.

Secondly, the GC you have with stereo enabled is javax.media.j3d.JoglGraphicsConfiguration and as it cannot be cast to sun.awt.X11GraphicsConfig you can't use it in JFrame constructor (as setGraphicsConfiguration is private in Component).

Finally, I am aware of this change in setGraphicsConfiguration in Java 7, but it should not influence stereo on Canvas3D as it does not influence stereo on GLCanvas in JOGL (and they both extend java.awt.Canvas).

Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

Xerxes RÃ¥nby
I have posted the issue to OpenJDK awt-dev:
http://mail.openjdk.java.net/pipermail/awt-dev/2014-March/007173.html
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

gouessej
Administrator
In reply to this post by babor
babor wrote
Finally, I am aware of this change in setGraphicsConfiguration in Java 7, but it should not influence stereo on Canvas3D as it does not influence stereo on GLCanvas in JOGL (and they both extend java.awt.Canvas).
Maybe it would be possible to write a dirty kludge to work around this known regression in AWT but I'm against this option because it isn't suitable on the long term, it would probably be difficult to maintain on all supported platforms (especially under Mac) and this bug should be fixed in AWT itself. Moreover, the fact that GLCanvas and Canvas3D both extend java.awt.Canvas doesn't mean that they don't work differently. Canvas3D was initially written not with JOGL in mind as Java3D had to stay compatible with several renderers. If you really want to avoid this kind of trouble in the future, rather use another scenegraph whose canvases and windows directly extend JOGL canvases. The poorly implemented Java3D canvases won't be rewritten and we won't provide some NEWT compatible Java3D canvases which means that you'll be concerned by all regressions in AWT affecting its canvases based on it or on Swing. Xerxes just did the right thing.

I imagine that this is typically not the kind of answer you would like to get but I still plan to write detailed migration guides to help developers to switch to more viable scenegraphs on the long term and I can help you. Some of us try to keep Java3D alive as is, without changing its public API but some of its design flaws prevent us from making it evolve without risking to break it. You might have to live with Java3D and undergo some remaining AWT bugs or to switch to another scenegraph (which is doable but not without any risk).
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

babor
Thanks for your comments. Surely the idea of different scenegraph is acceptable, but at the moment we'd like to keep Java3D API within our application. Changing the scenegraph will be quite a challenge for us.

In the meantime I have a kind of the solution - it works fine but is not very "graceful" :)
Following the path that AWT Component overrides GC of Canvas3D when it is added to a parent, it is possible to react on such event, find the topmost Component and reset the original Canvas3D GC to the whole hierarchy using reflection on setGraphicsConfiguration  (quite as Xerxes suggested).

A wrapped Canvas3D can look like this:
import java.awt.Component;
import java.awt.Container;
import java.awt.GraphicsConfiguration;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.lang.reflect.Method;
import javax.media.j3d.Canvas3D;

public class WrappedCanvas3D extends Canvas3D {
    
    private GraphicsConfiguration initialGC;
    
    public WrappedCanvas3D(GraphicsConfiguration graphicsConfiguration) {
        super(graphicsConfiguration);
        initialGC = this.getGraphicsConfiguration();        
        this.addHierarchyListener(new HierarchyListener() {
            @Override
            public void hierarchyChanged(HierarchyEvent e) {
                if(e.getChangeFlags() == HierarchyEvent.PARENT_CHANGED) {
                    try {
                        Class c = java.awt.Component.class;
                        Method method = c.getDeclaredMethod("setGraphicsConfiguration", GraphicsConfiguration.class);
                        method.setAccessible(true);
                        Component topmostComponent = getTopmostComponent(e.getChangedParent());
                        if(topmostComponent != null && initialGC != null)
                             method.invoke(topmostComponent, initialGC);
                    } catch (Exception ex) {
                        throw new RuntimeException(ex.getMessage());
                    }                    
                }                
            }
        });
    }
    
    private Component getTopmostComponent(Component component) {
        if(component == null)
            return null;        
        Container parent = component.getParent();
        if(parent == null || !(parent instanceof Component))
            return component;
        return getTopmostComponent((Component)parent);
    }
}


Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

Xerxes RÃ¥nby
Anthony have created a new OpenJDK bugreport to track the AWT regression that broke Java3D stereo.
http://mail.openjdk.java.net/pipermail/awt-dev/2014-March/007175.html
https://bugs.openjdk.java.net/browse/JDK-8036875 - Component.setGraphicsConfiguration() breaks some 3D applications

Cheers
Xerxes
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

gouessej
Administrator
In reply to this post by babor
babor wrote
Thanks for your comments. Surely the idea of different scenegraph is acceptable, but at the moment we'd like to keep Java3D API within our application. Changing the scenegraph will be quite a challenge for us.
Your source code is available on Github but I haven't found yet the classes that rely on Java3D. Several JOGL users have already switched from Java3D to Ardor3D or use them both, this is still a challenge but it's worth the change.

Can't you use an existing method of SwingUtilities instead of getTopmostComponent?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

babor
gouessej wrote
Your source code is available on Github but I haven't found yet the classes that rely on Java3D. Several JOGL users have already switched from Java3D to Ardor3D or use them both, this is still a challenge but it's worth the change.
The most important class that uses Canvas3D is pl.edu.icm.visnow.geometries.viewer3d.Display3DPanel

gouessej wrote
Can't you use an existing method of SwingUtilities instead of getTopmostComponent?
I assume you mean SwingUtilities.getWindowAncestor? Sure I can :)
I'd also add some security for backward compatibility on Java 6.

As a result we have:

import java.awt.Container;
import java.awt.GraphicsConfiguration;
import java.awt.Window;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.lang.reflect.Method;
import javax.media.j3d.Canvas3D;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;

/**
 * @author  Bartosz Borucki (babor@icm.edu.pl)
 * University of Warsaw, Interdisciplinary Centre
 * for Mathematical and Computational Modelling
 */
public class WrappedCanvas3D extends Canvas3D {
    
    private GraphicsConfiguration initialGC;
    
    public WrappedCanvas3D(GraphicsConfiguration graphicsConfiguration) {
        super(graphicsConfiguration);
        initialGC = this.getGraphicsConfiguration();        
        this.addHierarchyListener(new HierarchyListener() {
            @Override
            public void hierarchyChanged(HierarchyEvent e) {
                if(e.getChangeFlags() == HierarchyEvent.PARENT_CHANGED) {
                    Container parent = e.getChangedParent();                    
                    try {                        
                        Class<?> c = java.awt.Component.class;
                        Method method = c.getDeclaredMethod("setGraphicsConfiguration", GraphicsConfiguration.class);
                        if(method == null)
                            return;
                        method.setAccessible(true);
                        if(parent == null)
                            return;
                        Window parentWindow = SwingUtilities.getWindowAncestor(parent);
                        if(parentWindow != null && initialGC != null)
                            method.invoke(parentWindow, initialGC);                                                
                    } catch (NoSuchMethodException ex) {
                        //in case of Java 6 ignore this exception
                    } catch (Exception ex) {
                        throw new RuntimeException(ex.getMessage());
                    }                    
                    if(parent instanceof JComponent)
                        ((JComponent)parent).revalidate();
                }                
            }
        });
    }
    
}
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

Julien
Hello All,

In an effort to try to restart this discussion, and make some progress on this issue, I have posted this message:

http://mail.openjdk.java.net/pipermail/awt-dev/2014-December/008787.html

Hoping we can revive the Java 3D stereo capability.

Many Thanks,

-Julien C
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

bjoern
Hi all,

I do not really understand why you are making these efforts to enable stereo with Java3D. I coded now a little example based on our CELLmicrocosmos projects, and it works fine with Java 8 u60 and Java 7 u80-b15.

So please check it and let me know if it solves your problems (or not at all ;- )

JogampJ3DStereoSample.java



import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;

import javax.media.j3d.AmbientLight;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.GraphicsConfigTemplate3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.vecmath.Color3f;
import javax.vecmath.Matrix4d;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
import com.sun.j3d.utils.behaviors.vp.ViewPlatformAWTBehavior;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.ConfiguredUniverse;

public class JogampJ3DStereoSample {
       
        private static boolean CHECK_SCREEN_UPDATES = false;
       
        /**
         * This is a simple example showing how to use a 3D-stereoscopic canvas with Java3D.
         * This works also very nice with Jogamp's Java3D implementation.
         * Tested with J3D Version 1.6_pre11 and Java 8 u60 and Java 7 u80-b15.
         * Thanks go to Julien Gousse, Harvey Harrison and all other contributors for their great work!!!
         *
         * @author Bjorn Sommer for CELLmicrocosmos.org
         */
        public static void main(String[] args) {
               
                // create universe and Canvas3D with stereo support
                GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D();
    template.setStereo(GraphicsConfigTemplate3D.PREFERRED);
            GraphicsConfiguration config = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getBestConfiguration(template);
            Canvas3D canvas3D = !CHECK_SCREEN_UPDATES?
            new Canvas3D(config):
                                                                new Canvas3D(config) {
                                                                        private static final long serialVersionUID = 500419811339553034L;
                                                                        // this is a nice place to force e.g. an offscreen canvas or 2D labels on the 3D screen to be updated
                                                                        // - and yes, this also works perfect with Jogamp's J3D!
                                                                        public void postRender() {
                                                                                super.postRender();
                                                                                System.out.print("update...");
                                                                        }
                                                                };
 
            if (canvas3D.getStereoAvailable()) {
            System.out.println("Stereo available");
            } else {
            System.out.println("Okay, Stereo is not working. \n"
            + "If you have an NVIDIA Quadro graphics or similar professional graphics, check out that stereo is activated in the driver.\n"
            + "Example: 1. NVIDIA Control Panel -> 3D Settings -> Manage 3D Settings -> Global Settings -> Stereo: Enable -> On \n"
            + "            Note: You might have to swap the eyes here in the settings - depends on the configuration."
            + "         2. NVIDIA Control Panel -> Stereoscopic 3D -> Set up stereoscopic 3D -> Enable Stereo 3D\n"
            + "            Note: This setting is optional and depends on your configuration/driver. \n"
            + "                  It might be also that this checkbox has to be deactivated - although this\n"
            + "                  theoretically does not make any sense. But it debends on the hardware configuration.\n\n"
            + "If you do not have a (semi-)professional graphics card, this will usually not work at all. \n"
            + "Then, you need e.g. a 3D TV and do the side-by-side rendering with Java3D on your own - \n"
            + "but this makes only sense in full screen mode.");
            }
           
                // create an object
                BranchGroup bg1 = new BranchGroup();
                TransformGroup tg1 = new TransformGroup();
                Transform3D t3d1 = new Transform3D();
                t3d1.set(new Vector3d(0,0,0));
                t3d1.rotX(Math.toRadians(45));
                tg1.setTransform(t3d1);
                ColorCube colorCube = new ColorCube(0.3);
               
                // create a light
                BranchGroup bg2 = new BranchGroup();
                TransformGroup tg2 = new TransformGroup();
                Transform3D t3d2 = new Transform3D();
                t3d2.set(new Vector3d(0,0,0));
                tg2.setTransform(t3d2);
                AmbientLight aLight = new AmbientLight();
                aLight.setEnable(true);
                aLight.setColor(new Color3f(1,1,1));
               
                Dimension dimension = new Dimension(400,400);
               
                // create the panel and add the Canvas3D
                JPanel panel = new JPanel();
                panel.setLayout(new BorderLayout());
                panel.add("Center", canvas3D);
                canvas3D.setVisible(true);
                canvas3D.setSize(dimension);
               
                // create the universe
                ConfiguredUniverse universe = new ConfiguredUniverse(canvas3D);
               
                // add object to scene
                tg1.addChild(colorCube);
                bg1.addChild(tg1);
                universe.addBranchGraph(bg1);
               
                // add light to scene
                tg2.addChild(aLight);
                bg2.addChild(tg2);
                universe.addBranchGraph(bg2);
               
                // set the position of the view
                Transform3D t3dVP = new Transform3D(new Matrix4d( 1,0,0,0,
                                                                                                                        0,1,0,0,
                                                                                                                        0,0,1,3,
                                                                                                                        0,0,0,1));
                universe.getViewingPlatform().getViewPlatformTransform().setTransform(t3dVP);;
               
                // create the panel and frame
                panel.setSize(dimension);
                panel.setVisible(true);
                JFrame frame = new JFrame();
                frame.setSize(dimension);
                frame.add(panel);
                frame.setVisible(true);
               
                // set the eye positions
                Point3d eyePosRight= new Point3d(-0.01,0,0);
                Point3d eyePosLeft= new Point3d(0.01,0,0);
                canvas3D.setLeftManualEyeInImagePlate(eyePosLeft);
                canvas3D.setRightManualEyeInImagePlate(eyePosRight);
                canvas3D.getView().getPhysicalBody().setLeftEyePosition(eyePosLeft);
                canvas3D.getView().getPhysicalBody().setRightEyePosition(eyePosRight);
               
                // add a behavior
                //  note: I experienced here, without the behavior, that Java likes to show a white screen instead of the image
                OrbitBehavior orbitBehavior = new OrbitBehavior(canvas3D,
                                                                                                                ViewPlatformAWTBehavior.KEY_LISTENER |
                                                                                                                OrbitBehavior.REVERSE_ROTATE |
                                                                                                                OrbitBehavior.REVERSE_TRANSLATE |
                                                                                                                OrbitBehavior.PROPORTIONAL_ZOOM);
                orbitBehavior.setSchedulingBounds(new BoundingSphere(new Point3d(0, 0, 0), 100));
                universe.getViewingPlatform().setViewPlatformBehavior(orbitBehavior);
        }
       
}
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

bjoern
Looking for something completely different, I just came across this info from Andrew Davison:

Starting with Java 7, you have a redraw problem caused by the heavyweight/lightweight conflict. Sometime, you see only the background - this is very annoying and my example above had the same problem in case the OrbitBehavior was not added. Just add this line to the code:

System.setProperty("sun.awt.noerasebackground", "true");

Thanks, Andrew!

His book Killer Game Programming you certainly all know, at this website I found also this valuable info (look for the Java 3D section):

http://fivedots.coe.psu.ac.th/~ad/jg/

This hint might also solve problems with Mac OS X. I experienced that sometime popup elements are not shown on the Canvas3D. Okay, but I did not test it by now, maybe not ...
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

gouessej
Administrator
Actually, this property works less and less as time goes by:
https://jogamp.org/bugzilla/show_bug.cgi?id=1182
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

bjoern
Yes, Julien, might be in the future. But did somebody of you test my code above, which should solve your stereo issues with J3D?

see JogampJ3DStereoSample.java
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

Jody Verret
In reply to this post by jodyv
After much procrastination, I finally decided to test getting Java3D stereo
via JOGL working under linux.  (See my original post on Aug 30, 2013)

My solution was basically this:

o Get JOGL jars for java3d from here:

  http://forum.jogamp.org/Java3D-1-6-0-pre8-released-and-future-plans-tt4029680.html

o Get Java 1.6 from here:

  http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase6-419409.html

  In this case, I downloaded jdk1.6.0_45

o Complie using 1.6 javac and classpath set to JOGL and the above java3d jars.

My StereoTestJava3D post on Aug 30, 2013 works.

The basic trick as Mr. Babor alluded in Mar 06, 2014 post was to use JRE 1.6
(vice JRE 1.7)

I might also add that I perceive that the JOGL implementation of Java3D is
much faster than the prior 1.5 (non-JOGL) baseline.

Thank you very much for investigating my problem.

Also, many thanks to you for continuing the J3D development.
Reply | Threaded
Open this post in threaded view
|

Re: Java3D stereo

gouessej
Administrator
Hi

Does your trick work with a more recent build of Java3D?
Julien Gouesse | Personal blog | Website
12