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

      GL4Java Implementation for the Microsoft Java VM under Windows
                   And some Other Interesting Topics
                          Ronald B. Cemer
                          August 10, 1999

{ This part is updated by Sven Goethel for GL4Java 2.1.0.0, 30th August 1999 }
------------------------------------------------------------------------------


Implementation


I began with GL4Java version 2.0.1.2, as maintained and distributed by Sven
Goethel.

Microsoft's VM comes in several versions.  While the latest versions support
JNI (Java Native Interface, an API which allows Java to call native code in
DLLs), many releases only support J/Direct, which is Microsoft's simplified
(and quite handy, but highly non-standard) interface to native code in DLLs.
I opted to use J/Direct for all native calls under the Microsoft VM.

If you have an early VM, it won't support J/Direct either, so you have to
download the latest VM in this case (or at least a newer one).  See the
"Installing" section.

Microsoft's VM uses what they call "lightweight" components.  They went to
great pains to re-use all of the ActiveX controls (whatever!) that they had
invested so much time and effort to develop.  These controls are at the heart
of the VM.  By "lightweight" they mean that each control (button, canvass,
etc.) does not have its own window handle, but are actually drawn onto the
frame, which has a window handle.  Therefore, within a frame (a top-level
window), all components share that frame's window handle.  As a result,
there's really no window to render to with OpenGL.  So I create one in the
DLL, and maintain it there.  The GLContext and GLCanvas classes cooperate to
keep the size and position of this window synchronized with the size and
position of the underlying canvas.  It all happens fairly transparently.

Beware, though, that you shouldn't try to draw on the canvas with normal Java
drawing commands, because you'll be drawing on a canvas that is obscured by
an OpenGL window and the results will never be seen.  In fact, the Win32
documentation states that PFD_DOUBLEBUFFER and PFD_SUPPORT_GDI are mutually
exclusive (see ChoosePixelFormat), so you shouldn't be trying this anyway.
Basically, the rule is this: Use OpenGL to draw everything in the GLCanvas or
GLAnimCanvas space.

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


Changes to existing applets/applications


To prevent security violations and to allow the applet to shutdown gracefully,
I added doCleanup() function to the GLCanvas class.  Since GLAnimCanvas is a
subclass of GLCanvas, doCleanup() is effectively added to both classes.

The doCleanup() function gets called by cvsDispose().  You should override
doCleanup() in your applet and put all OpenGL cleanup code there.  This is
where you delete display lists and textures, etc.

The following methods can be overridden in the GLCanvas or GLAnimCanvas object
you create, but you must call the super.*() version of the same method in your
overridden method in order for the applet to operate correctly.  Here are
sample implementations of these functions, with places for you to insert your
code:

    public void reshape(int width, int height)
    {
        super.reshape(width,height);
        /* Put your code here. */
    }

    public void componentResized(ComponentEvent e)
    {
        super.componentResized(e);
        /* Put your code here. */
    }

    public void componentMoved(ComponentEvent e)
    {
        super.componentMoved(e);
        /* Put your code here. */
    }

    public void componentShown(ComponentEvent e)
    {
        super.componentShown(e);
        /* Put your code here. */
    }

    public void componentHidden(ComponentEvent e)
    {
        super.componentHidden(e);
        /* Put your code here. */
    }

	public void windowOpened(WindowEvent e)
    {
        super.windowOpened(e);
        /* Put your code here. */
    }

    public void windowClosing(WindowEvent e)
    {
        super.windowClosing(e);
        /* Put your code here. */
    }

    public void windowClosed(WindowEvent e)
    {
        super.windowClosed(e);
        /* Put your code here. */
    }

    public void windowIconified(WindowEvent e)
    {
        super.windowIconified(e);
        /* Put your code here. */
    }

    public void windowDeiconified(WindowEvent e)
    {
        super.windowDeiconified(e);
        /* Put your code here. */
    }

    public void windowActivated(WindowEvent e)
    {
        super.windowActivated(e);
        /* Put your code here. */
    }

    public void windowDeactivated(WindowEvent e)
    {
        super.windowDeactivated(e);
        /* Put your code here. */
    }


The ideal structure for an applet is as follows.  We will use DemoApplet as
the applet class and DemoCanvas as the canvas class.  Use your own names.

The DemoApplet class looks like this:

    public class DemoApplet extends Applet 
    {
        DemoCanvas canvas = null;
    
        public void init()
        {
            Dimension d = getSize();
    
            setLayout(new BorderLayout());
            canvas = new DemoCanvas(d.width, d.height, null, null);
            add("Center", canvas);
        }
    
        public void start()
        {
    /* This only applies if you're using GLAnimCanvas: */
            canvas.start();
        }
    
        public void stop()
        {
    /* This only applies if you're using GLAnimCanvas: */
            canvas.stop();
        }
    
        public void destroy()
        {
            canvas.destroy();
        }
    }

The DemoCanvas class looks like this:

    class DemoCanvas extends GLAnimCanvas
    {
        public DemoCanvas(int w, int h, String glClass, String gluClass)
        {
            super(w, h, glClass, gluClass);
    /* These only apply if you're using GLAnimCanvas: */
            setUseRepaint(true);    /* Only for GLAnimCanvas */
            setUseFpsSleep(true);   /* Run it wide open */
        }
    
        public void init() 
        {
            gl.glEnable(GL_DEPTH_TEST);
            gl.glEnable(GL_CULL_FACE);
            gl.glShadeModel(GL_SMOOTH);
            gl.glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
            gl.glEnable(GL_LIGHTING);
            gl.glEnable(GL_LIGHT0);
    
    /* Do any OpenGL - related initialization here. */
    
            glj.gljCheckGL();
    
    /* This only applies if you're using GLAnimCanvas: */
            setSuspended(false);
        }
    
        public void ReInit()
        {
    /* This only applies if you're using GLAnimCanvas: */
            setSuspended(false);
        }
    
        public void destroy()
        {
            if (glj != null)
            {
    /* Call cvsDispose().  It will shutdown the GL context and call doCleanup()
       at the right time. */
                cvsDispose();
            }
        }
    
        public void doCleanup()
        {
            if (glj != null)
            {
                glj.gljMakeCurrent(true);
    /* Do any OpenGL - related cleanup here. */
                glj.gljFree();
            }
        }
    
        public void display()
        {
            if (glj == null) return;
            if (!glj.gljIsInit()) return;
            if (glj.gljMakeCurrent(true) == false) return;
    
    /* Put OpenGL commands here to render the scene. */
    
            glj.gljSwap();
            glj.gljCheckGL();
            glj.gljFree();
        }
    }
    
------------------------------------------------------------------------------


Building the jar files


First of all, edit symbols.mak.win32 to reflect your system's configuration.
Then copy symbols.mak.win32 to symbols.mak.  Note that you should use a UNIX
editor (vim works nicely) to edit symbols.mak and any makefile(s), because
the make that comes with Cygnus chokes on carriage-returns.  Carriage-returns
almost never appear in UNIX text files, because a newline (ASCII linefeed) is
treated the same way a CR-LF pair is treated in DOS/Windows.

To rebuild the Java classes which comprise the Java side of GL4Java, you will
need the Microsoft SDK for Java, Sun JDK (1.2.1 or later is preferred), and
Cygnus Win32 tools (UNIX commands for Win32).  You can get each of these
things at the following web sites:

    Microsoft SDK for Java: http://www.microsoft.com/downloads/
    Sun JDK 1.2.1         : http://www.java.sun.com/products/
    Cygnus Win32 tools    : http://sourceware.cygnus.com/cygwin/

To build the gl4java.jar, execute the
following commands:

    make w32
    cd ..

Everything will get built except the DLLs.

{ This part is updated by Sven Goethel for GL4Java 2.1.0.0 }
------------------------------------------------------------------------------


Building the dll files


Support for building the MS-specific version of the DLL has not been added
for DJGPP or Borland BC5, since I don't have either set up on my system.
Sven Goethel or others may wish to add this for the next release.

First make sure the jar files have been built and are up to date.

To rebuild the DLLS, you need Microsoft Visual C++ 6.0.  Open the workspace:

    Win32VC6\Win32VC6.dsw

Then select each project and select "Build -> Rebuild all".

The create the archive with the makefile:

    make win2binpkg

... be sure to have zip !

{ This part is updated by Sven Goethel for GL4Java 2.1.0.0 }
------------------------------------------------------------------------------


Installing


Please read the MS-JVM.txt file !!

{ This part is updated by Sven Goethel for GL4Java 2.1.0.0 }
------------------------------------------------------------------------------


Running


To run a Java application, simply type jview followed by the class name.

To run a Java applet, type jview /a followed by the html filename.

To run a Java applet in Internet Explorer, just install the 
GL4Java classes and dll (see MS-JVM.txt) !
Then you can run all applets :-) ! 
No more security overload ...

{ This part is updated by Sven Goethel for GL4Java 2.1.0.0 }
------------------------------------------------------------------------------


Deploying an applet


You do not need to create a signed cab-file for your applet.
Please read above - and MS-JVM.txt !!

Original Text (Kept here for informational purpose):
====================================================
Sun and Netscape like signed jar files; IE likes signed cab files.  What's
more, they all use different signing techniques, so it's a bit of a mess to
get past your browser's security measures, but it can be done.

First of all, you're best off to forget about the Sun Java2 plug-in unless
your users are willing to go through a huge download (about 10 MB).  If you
want to use the Java2 plug-in in spite of the download size, go to
java.sun.com and read about their HTML converter.  It's a free download that
will fix up your HTML for both IE and Netscape to automatically download and
install the Sun VM if it's not already on their system, the first time they
try to run your applet.  It works great, but the download time is too long
for most users.  The benefit is that you only have to maintain one set of
HTML pages and one deployed copy of the applet.

If you decide to go the route which minimizes the hassle for the end users,
then you must deploy duplicate web pages (one set for Netscape and one for
IE), and deploy both a signed jar file and a signed cab file.  You need
Netscape's signtool utility to sign jar files for Netscape's VM.  You can
get it at www.netscape.com.  Build and sign a jar file with all of the
classes which comprise your applet.  Then build and sign a cab file with the
same classes.  Remember to use the correct signing tool for each.  Then, in
the page which is to start the applet, insert a little JavaScript code to
sniff the browser (microsoft.com has app notes on how to do this), and
redirect to either a Netscape-specific page which starts the applet from the
jar file, or a Microsoft-specific page which starts the applet from the cab
file.

One final caveat.  Some versions of IE 5 seem to be shipping without a Java
VM of any kind.  When you try to run a Java applet, it starts downloading the
Microsoft Java VM (about 6.5 MB or so), which takes quite awhile.  Even worse,
in some early releases of IE 5, the hard-coded URL where the browser is
supposed to go to get the VM is incorrect, so it can't find it, and so it
basically tells you to go find it yourself.  It's best to have a link on
your page to http://www.microsoft.com/java/download/32updates.htm so they can
at least get at the VM download if this happens to them.

{ This part is updated by Sven Goethel for GL4Java 2.1.0.0 }
------------------------------------------------------------------------------
