Java3d Nothing is Rendered

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

Java3d Nothing is Rendered

wenlinm
Hi everyone,

I currently received a job to fix a project that was developed 15 years ago and was still running 2 years ago. It was using an ancient version of Java3d 1.5.2 before and it is no longer work on the Mac OSX. So I ported this project to Java3d 1.6.0 from here and Java 1.8.

The problem is that everything works fine with no warning or errors but only a black background is rendered in the window.

I attached the code I used to test. It should render a color cube however nothing is actually rendered. Only a window with black background is shown.

I am new to Java3d so please correct me if I am wrong. I feel the problem happens with the GraphicsContext3D's draw method as I tried with several different test code snippet and only the code uses GraphicsContext3D failed to render. However, I have no idea how to fix this problem without changing the structure too much.

I tried this project on both Mac Mojave, High Sierra, and El Capitan but none of the operating system worked.

Any suggestion would be helpful. Thanks in advance.

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

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;

import javax.media.j3d.Alpha;
import javax.media.j3d.Appearance;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Geometry;
import javax.media.j3d.GraphicsContext3D;
import javax.media.j3d.Transform3D;

import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.SimpleUniverse;

/**
 * Pure immediate mode example program. 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 PureImmediate extends Applet implements Runnable {

    private Canvas3D canvas;

    private GraphicsContext3D gc = null;

    private Geometry cube = null;

    private Transform3D cmt = new Transform3D();

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

    private SimpleUniverse u = null;

    //
    // Renders a single frame by clearing the canvas, drawing the
    // geometry, and swapping the draw and display buffer.
    //
    public void render() {
        if (gc == null) {
            // Set up Graphics context
            gc = canvas.getGraphicsContext3D();
            gc.setAppearance(new Appearance());

            // Set up geometry
            cube = new ColorCube(0.4).getGeometry();
        }

        // Compute angle of rotation based on alpha value
        double angle = rotAlpha.value() * 2.0 * Math.PI;
        cmt.rotY(angle);

        // Render the geometry for this frame
        gc.clear();
        gc.setModelTransform(cmt);
        gc.draw(cube);
        canvas.swap();
    }

    //
    // Run method for our immediate mode rendering thread.
    //
    public void run() {
        System.out.println("PureImmediate.run: starting main loop");
        while (true) {
            render();
            Thread.yield();
        }
    }

    public PureImmediate() {
    }

    //
    // init: create the canvas, stop the renderer,
    // create the universe, and start the drawing thread.
    //
    public void init() {
        setLayout(new BorderLayout());
        GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();

        canvas = new Canvas3D(config);
        canvas.stopRenderer();
        add("Center", canvas);

        // Create the universe and viewing branch
        u = new SimpleUniverse(canvas);

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

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

    public void destroy() {
        u.cleanup();
    }

    //
    // The following allows PureImmediate to be run as an application
    // as well as an applet
    //
    public static void main(String[] args) {
        System.setProperty("sun.awt.noerasebackground", "true");
        new MainFrame(new PureImmediate(), 256, 256);

    }
}
Reply | Threaded
Open this post in threaded view
|

Re: Java3d Nothing is Rendered

philjord
Hi,
Thanks for this bug report.
I see that the example you've given is basically the pure immediate mode from the java3d-examples.

The good news is that this code also doesn't work for me, so I will start stepping through to see if I can find the problem.

I would note that I've never seen this example code working so it might take a little longer to track down the issue.

Thanks,
Phil.
Reply | Threaded
Open this post in threaded view
|

Re: Java3d Nothing is Rendered

wenlinm
Thanks for your quick reply.

I have found this post that is very similar to my problem.
http://forum.jogamp.org/Java3D-stereo-td4029914.html

In this post the StereoTestJava3D which used GraphicsContext3D didn't work. However, the code for StereoTestJogl actually worked after I made some minor changes in importing package's name. All code in other thread that didn't use GraphicsContext3D is working.

I tried to solve this problem by following the solution mentioned here but it didn't solve my problem.

Hope these information can bring more context to you and help you identify the problem easier.

Thanks,

Wenlin
Reply | Threaded
Open this post in threaded view
|

Re: Java3d Nothing is Rendered

philjord
Ok good news, I've discovered the source of the problem, but I may need GouesseJ's advice on how to fix it correctly.

Here is a listing of the verbose output from the JoglPipeline of a Retained mode  rendering cycle, that simply renders the same cube onto the same canvas.
Retained mode is the "normal" Java3D mode where the rendering thread simply loops and renders constantly (where needed).

Note I've trimmed away the setup calls as they are identical (because the code calling them is also identical - the createUniverse method)


JoglPipeline.validGraphicsMode()
  Returning true
JoglPipeline.createNewContext()
JoglPipeline.updateSeparateSpecularColorEnable()
JoglPipeline.setSceneAmbient()
JoglPipeline.disableFog()
JoglPipeline.resetRenderingAttributes()
JoglPipeline.resetTextureNative()
JoglPipeline.resetTexCoordGeneration()
JoglPipeline.resetTextureAttributes()
JoglPipeline.resetPolygonAttributes()
JoglPipeline.resetLineAttributes()
JoglPipeline.resetPointAttributes()
JoglPipeline.resetTransparency()
JoglPipeline.resetColoringAttributes()
JoglPipeline.updateMaterialColor()
JoglPipeline.useCtx()
JoglPipeline.setViewport()
JoglPipeline.setRenderMode()
JoglPipeline.clear()
JoglPipeline.setRenderMode()
JoglPipeline.setProjectionMatrix()
JoglPipeline.setVertexFormat()
JoglPipeline.setModelViewMatrix()
JoglPipeline.setLightEnables()
JoglPipeline.setSceneAmbient()
JoglPipeline.disableFog()
JoglPipeline.disableModelClip()
JoglPipeline.resetRenderingAttributes()
JoglPipeline.resetPolygonAttributes()
JoglPipeline.resetTransparency()
JoglPipeline.updateMaterialColor()
JoglPipeline.resetColoringAttributes()
JoglPipeline.setModelViewMatrix()
JoglPipeline.execute()
JoglPipeline.executeGeometryArray()
JoglPipeline.testForInterleavedArrays()
JoglPipeline.setRenderMode()
JoglPipeline.syncRender()
JoglPipeline.swapBuffers()
JoglPipeline.releaseCtx()



Compare with the same output for the immediate mode example
JoglPipeline.validGraphicsMode()
  Returning true
JoglPipeline.createNewContext()
JoglPipeline.updateSeparateSpecularColorEnable()
JoglPipeline.setSceneAmbient()
JoglPipeline.disableFog()
JoglPipeline.resetRenderingAttributes()
JoglPipeline.resetPolygonAttributes()
JoglPipeline.resetLineAttributes()
JoglPipeline.resetPointAttributes()
JoglPipeline.resetTransparency()
JoglPipeline.resetColoringAttributes()
JoglPipeline.updateMaterialColor()
JoglPipeline.activeTextureUnit()
JoglPipeline.resetTransparency()
JoglPipeline.getNumCtxLights()
JoglPipeline.clear()
JoglPipeline.setViewport()
JoglPipeline.setProjectionMatrix()
JoglPipeline.setModelViewMatrix()
JoglPipeline.activeTextureUnit()
JoglPipeline.resetTransparency()
JoglPipeline.setModelViewMatrix()
JoglPipeline.setSceneAmbient()
JoglPipeline.setLightEnables()
JoglPipeline.setModelViewMatrix()
JoglPipeline.setVertexFormat()
JoglPipeline.execute()
JoglPipeline.executeGeometryArray()
JoglPipeline.testForInterleavedArrays()
JoglPipeline.syncRender()
JoglPipeline.swapBuffers()


Apart from some texture calls that differ (we have no textures in the example) and a few order of operations the most significant difference is the lack of useCtx and releaseCtx calls.

So when I insert the function from useCtx  
context(ctx).makeCurrent();

into the first interesting render operation for immediate mode - updateSeparateSpecularColorEnable

I get



Woot!

so to get your code going, if you have the source for 1.6.0 and are willing to compile it, in the JoglPipeline class add this line

// Native method to update separate specular color control
    @Override
    void updateSeparateSpecularColorEnable(Context ctx, boolean enable) {
        if (VERBOSE) System.err.println("JoglPipeline.updateSeparateSpecularColorEnable()");

       
        context(ctx).makeCurrent();
       
        GL2 gl = context(ctx).getGL().getGL2();

        if (enable) {
            gl.glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL, GL2.GL_SEPARATE_SPECULAR_COLOR);
        } else {
            gl.glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL, GL2.GL_SINGLE_COLOR);
        }
    }


I will now put together a fix that involves the renderer always using and releasing the context on pure immediate calls, along with the first create of context in GraphicsContext3D.doClear using the context correctly as well.

Note the fix I'm proposing will require all pure immedate systems to call doClear on the GraphicContext3D immedately after creation like this

public void render() {
    System.out.println("render");
        if (gc == null) {
            // Set up Graphics context
            gc = canvas.getGraphicsContext3D();
            gc.clear();// clear must be the first call for pure immediate to set up the context and pipeline
            gc.setAppearance(new Appearance());// calls  GraphicsContext3D.doSetAppearance a sync

            // Set up geometry
            cube = new ColorCube(0.4).getGeometry();
        }
...

Julien, Harvey I'll put together a git pull request with the changes I think are required shortly, can you check it and see if it will cause trouble or be incomplete or there is a better way to solve the problem.

Thanks,
Phil.
Reply | Threaded
Open this post in threaded view
|

Re: Java3d Nothing is Rendered

gouessej
Administrator
I'll review your pull request with pleasure but I'd like to know Harvey's opinion.

It looks good to me. I'm a bit annoyed by the necessary call to clear().
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Java3d Nothing is Rendered

philjord
Yes, the doClear call seems needless, however in the entire code base there are only 3 calls to Canvas3d.createNewContext().
Two of them are in the Renderer class loop in the retained mode section (after the immediate mode if case) called whenever retained mode is doing anything and it checks for a context and lazily creates if needed. The other one is in the immediate mode doClear call. I would like to take the immediate mode create call out into the Renderer and have it run as a lazy init before any of the immediate mode calls, just like the retianed is doing now. But that's a fairly major code change that may have unknown impacts.

 
Reply | Threaded
Open this post in threaded view
|

Re: Java3d Nothing is Rendered

philjord
Ok I've done a pull request that should fix it and does not demand the doClear
Reply | Threaded
Open this post in threaded view
|

Re: Java3d Nothing is Rendered

gouessej
Administrator
Good job :)
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Java3d Nothing is Rendered

wenlinm
In reply to this post by philjord
Thanks for fixing this bug. Now everything works.
Reply | Threaded
Open this post in threaded view
|

Re: Java3d Nothing is Rendered

philjord
That's good news.

Please post any other questions/problems you come across in the future.

The link to the pull (in case anyone needs it):
https://github.com/hharrison/java3d-core/pull/27