Tutorial 03 :
Fullscreen loader v2.0 - BaseCode

Tutorial BaseCode Download Section

Thanks to Pepijn Van Eeckhoudt, I've learn how to render a frame in full screen mode and to choose the screen resolution.
I found it in the port of GLExcess written originally by Paolo Martella.
You can found GLExcess at:
    http://www.glexcess.com/

GLExcess is a beautifull OpenGl demo that show many effects through differents environments.
When I've see this demo, I'm impressed by the work of Paolo Martella. It is very incredible !
 

The goal of this tutorial is to load the OpenGl frame container created previously in fullscreen mode.
It will also allow the use to select, in a dialog, the screen resolution, scene dimension (if he don't want to load it in fullscreen mode).


To load an OpenGL scene in the default container, the code will look like :

Loading an OpenGl scene in the default GUI

public static void main(String[] args)
{
    Load.load("Title of the frame",            //Title of the frame
              Tutorial3.class,                 //Class that contain the scene
              Settings.Renderer.JOGL_JSR231)   //indicate if we use JGL4JAVA, JOGL or JOGL_JSR231
    //To use a specified container

//    Load.load(OpenglGui.class,                 //Use a specified GUI (extends SceneContainer)
//              "Title of the frame",            //Title of the frame
//              Tutorial3.class,                 //Class that contain the scene
//              Settings.Renderer.JOGL_JSR231)   //indicate if we use JGL4JAVA, JOGL or JOGL_JSR231
}

 

This Tutorial contains many files, here is all packages/classes used :


Class hierarchy

How to use all of this ?

The main class is org.jouvieje.opengl.load.Load. It is the entry point for :

 

GlLoader put the second parameter (the class that contain the scene) in the container constructor.
With this class, we can instanced a new object to creates the scene and add it into the frame.

The container must implements GlContainer that is to say defines this two classes of the interface.
We will see afterwards that you can use you own containers and passed it as a Class like the scene on a method of GlLoader.

org.jouvieje.opengl.scene.SceneContainer

package org.jouvieje.opengl.scene;

/*
 * T can be :
 *  gl4java.awt.GLAnimCanvas
 *  net.java.games.jogl.GLCanvas
 *  javax.media.opengl.GLCanvas
 * ...
 */

public abstract interface SceneContainer<T>
{
    public void start();
    public void setVisible(boolean visible);
    public T getGlScene();
}

  Using other container

Not only default container can be passed to Load class. Any container that implements SceneContainer can also be used.

The container must have a constructor with these parameters :
    String title, Class<?> scene, Settings<?> settings
 

The class that contains the scene must implements GLEventListener like we have seen in Tutorial 2.

The settings choosen by the user and the opengl scene to add in the container are passed to the constructor.
To instanciate the class, we will use ClassIntance which use internally Constructor.newInstance.

Settings store these 4 properties :

Here is the full code of the new container, with highlight of important code :

opengl.jsr231.Container.FrameContainer

package org.jouvieje.jsr231.container;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import net.java.games.jogl.*;

import opengl.common.Container.*;
import opengl.common.Loader.*;

public class FrameContainer extends JFrame implements SceneContainer<javax.media.opengl.GLCanvas>
{
    /*
     * OpenGl scene class that contains the OpenGl scene
     * This class must implements GLEventListener
     */

    protected final Class<?> glSceneClass;
    /*
     * Settings of the frame (from the dialog setting)
     */

    protected final Settings settings;
   
    //Graphical components
    private javax.swing.JPanel jContentPane = null;
    private net.java.games.jogl.GLCanvas glScene = null;
    private GLEventListener glEvents = null;

    /**
     * Constructor
     *
     * @param title title of the frame
     * @param scene class that implements GLEventListener
     * @param settings settings of the frame
     */

    public FrameContainer(String title, Class<?> scene, Settings<?> settings)
    {
        super(title);

        //the OpenGl animation class
        this.glSceneClass = scene;
        this.settings = settings;

        initialize();
    }

    /**
     * Start the OpenGl scene and request focus
     */

    public void start()
    {
        getJContentPane().add(getGlScene(), java.awt.BorderLayout.CENTER);
        this.pack();
        this.setLocationRelativeTo(null);

        //attempt to get the focus of the canvas
        getGlScene().requestFocus();
    }

    ...


    private void initialize()
    {
        this.setUndecorated(settings.isFullscreen());
        this.setContentPane(getJContentPane());
        ...
    }
    public void destroy()
    {
        /*
         * Destroy the fullscreen mode before closing
         */

        try
        {
            if(settings.isFullscreen())
            {
                GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
                graphicsDevice.setFullScreenWindow(null);
                graphicsDevice = null;
            }
        }
        catch(Exception ee)
        {
            System.err.println("[FrameContainer.destroy] PROBLEM WHEN EXITING FULLSCREEN MODE !");
        }
    }
    private javax.swing.JPanel getJContentPane()
    {
        if(jContentPane == null)
        {
            jContentPane = new javax.swing.JPanel();
            jContentPane.setLayout(new java.awt.BorderLayout());
            jContentPane.setBackground(java.awt.Color.black);
        }
        return jContentPane;
    }
    public javax.media.opengl.GLCanvas getGlScene()
    {
        if(glScene == null)
        {
            /**
             * Creates a Jogl scene
             *
             * First, we creates a GLCanvas with the first line (we can't use new GLCanvas())
             * After, we set his size with the settings
             */

            GLCapabilities glCapabilities = settings.glCapabilities instanceof GLCapabilities ?
                    (GLCapabilities)settings.glCapabilities : new GLCapabilities();
            glScene = new GLCanvas(glCapabilities);
            if(settings.isFullscreen())
                glScene.setSize(settings.getScreenResolution());
            else
                glScene.setSize(settings.getSceneDimension());

            /**
             * Here we add ou GLEvents
             * for this we creates a new instance of the Class
             */

            try
            {
                //Creates a new instances of our GLEvents
                glEvents = (GLEventListener)ClassInstance.sceneInstance(this, glSceneClass);
                //add the events in the component
                glScene.addGLEventListener(glEvents);
            }
            catch(Exception e)
            {
                System.out.println(e.getClass()+" : "+e.getMessage());
                e.printStackTrace();
                System.err.println("[FrameContainer.getGlScene] FAILED TO INITIALIZE THE OPENGL SCENE !");
                this.dispose();
            }
        }
        return glScene;
    }

     ...

}

 

The code is similar to JOGL-JSR231, here are major changes :

org.jouvieje.gl4java.container.FrameContainer

    public gl4java.awt.GLAnimCanvas getGlScene()
    {
        if(glScene == null)
        {
            try
            {
                /**
                 * Creates our OpenGL scene with the class loader
                 * glSceneClass must extends GLAnimCanvas
                 */

                glScene = (gl4java.awt.GLAnimCanvas)ClassInstance.sceneInstance(this, glSceneClass,
                    settings.isFullscreen() ? settings.getScreenResolution() : settings.getSceneDimension());


                glScene.addFocusListener(new java.awt.event.FocusListener() {
                    public void focusGained(java.awt.event.FocusEvent e) {
                        FrameContainer.this.focusGained(e);
                    }
                    public void focusLost(java.awt.event.FocusEvent e) {
                        FrameContainer.this.focusLost(e);
                    }
                });
                glScene.addMouseListener(new java.awt.event.MouseAdapter() {
                    public void mouseEntered(MouseEvent me) {
                        FrameContainer.this.mouseEntered(me);
                    }
                    public void mouseClicked(MouseEvent me) {
                        FrameContainer.this.mouseClicked(me);
                    }
                });
            }
            catch(Exception e)
            {
                System.out.println(e.getClass()+" : "+e.getMessage());
                e.printStackTrace();
                System.err.println("[FrameContainer.getGlScene] FAILED TO INITIALIZE THE OPENGL SCENE !");
                this.dispose();
            }
        }
        return glScene;
    }

 

For this, we use the class java.awt.GraphicsDevice. First, we gets the default GraphicsDevice with :
    GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
Afterwards, we put our frame in fullscreen mode with :
    graphicsDevice.setFullScreenWindow(glContainer)
Finaly, we change resolution, bit depth, refresh rate ... with :
    graphicsDevice.setDisplayMode(displayMode)

The displayMode is choosen between all display modes available. Display modes available can be acess via :
    graphicsDevice.getDisplayModes()

 

org.jouvieje.opengl.load.Load

package org.jouvieje.opengl.load;

import java.awt.*;
import javax.swing.JDialog;

import org.jouvieje.opengl.scene.SceneContainer;

public class Load
{
    ...

    /**
     * Load the OpenGl scene.
     * @param container the container that implements GlContainer
     * @param title title of the OpenGl scene
     * @param scene class that contains the OpenGl scene
     * @param settings your preferred settings
     */

    public static SceneContainer<?> loadScene(Class<? extends SceneContainer<?>> container, String title, Class<?> scene, Settings<?> settings)
    {
        SceneContainer<?> glContainer = null;
        try
        {
            glContainer = ClassInstance.containerInstance(container, title, scene, settings);
        }
        catch(Exception e)
        {
            e.printStackTrace();
            System.err.println("[Loader] : "+e.getMessage());
            System.exit(1);
        }

        try
        {
            /**
             * Here we change to fullscreen mode (only possible if the container
             * extends of Window)
             * The class we use for this is the java.awt.GraphicsDevice
             */

            if(settings.isFullscreen() && glContainer instanceof Window)
            {
                switchToFullscreenMode((Window)glContainer, settings);
            }
        }
        catch(Exception e)
        {
            System.err.println("[Loader] PROBLEM WITH FULLSCREEN MODE !");
        }

        glContainer.start();
        glContainer.setVisible(true);
        return glContainer;
    }

    private static void switchToFullscreenMode(Window glContainer, Settings<?> settings)
    {
        /*
         * Get the default GraphicsDevice
         */

        GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();

        /*
         * Set fullscreen to the container
         */

        graphicsDevice.setFullScreenWindow(glContainer);

        /*
         * Search the display mode with the user settings
         */

        DisplayMode displayMode = catchDisplayMode(
            graphicsDevice.getDisplayModes(),                   //all display mode available
            settings.getScreenResolution().width,               //screen resolution
            settings.getScreenResolution().height,
            graphicsDevice.getDisplayMode().getBitDepth(),      //keep the current bit depth
            graphicsDevice.getDisplayMode().getRefreshRate());  //keep the current refresh rate

        /*
         * Set the Display Mode found
         */

        graphicsDevice.setDisplayMode(displayMode);
    }

    /**
     * Catch the display mode in the displayModes array corresponding to the parameter of the method
     *
     * If zero displayMode match with the parameter, we take the first display mode in the array
     *
     * @author Pepijn Van Eeckhoudt
     */

    private static DisplayMode catchDisplayMode(DisplayMode[] displayModes, int requestedWidth, int requestedHeight,
            int requestedDepth, int requestedRefreshRate)
    {
        //Try to find the exact match
        DisplayMode displayMode = searchDisplayMode(displayModes, requestedWidth, requestedHeight,
                                                    requestedDepth, requestedRefreshRate);
       
        //If the previous trial has failled, try again ignoring the requested bit depth and refresh rate
        if(displayMode == null)
        {
            displayMode = searchDisplayMode(displayModes, requestedWidth, requestedHeight,
                                            -1, -1);
           
            //Try again, and again ignoring the requested bit depth and height
            if(displayMode == null)
            {
                displayMode = searchDisplayMode(displayModes, requestedWidth,
                                                -1, -1, -1);
               
                //If all else fails try to get any display mode
                if(displayMode == null)
                    displayMode = searchDisplayMode(displayModes, -1,
                                                    -1, -1, -1);
            }
        }
        else
        {
            System.out.println("Perfect DisplayMode Found !!!");
        }
       
        return displayMode;
    }
   
    /**
     * Search the DisplayMode in the displayModes array corresponding to the parameter of the method
     *
     * @author Pepijn Van Eeckhoudt
     */

    private static DisplayMode searchDisplayMode(DisplayMode[] displayModes, int requestedWidth, int requestedHeight,
            int requestedDepth, int requestedRefreshRate)
    {
        //the display mode to use
        DisplayMode displayModeToUse = null;
       
        /*
         * Search the display mode to use in the displayMode array
         *
         * If this methods is called with -1 for all parameters, we take the first displayMode
         */

        for(int i = 0; i < displayModes.length; i++)
        {
            DisplayMode displayMode = displayModes[i];
           
            if((requestedWidth == -1 || displayMode.getWidth() == requestedWidth) &&
                (requestedHeight == -1 || displayMode.getHeight() == requestedHeight) &&
                (requestedHeight == -1 || displayMode.getRefreshRate() == requestedRefreshRate) &&
                (requestedDepth == -1 || displayMode.getBitDepth() == requestedDepth))
                    displayModeToUse = displayMode;
        }
       
        return displayModeToUse;
    }
}

 

Display setting gui and loads the scene
    Load.load("Tutorial 3", Tutorial3.class, Settings.Renderer.RENDERER_JOGL)

Display setting gui with preferred settings (fullscreen in 800x600) :
    Settings settings = new Setting(Settings.Renderer.RENDERER_JOGL, true, new Dimension(800, 600))
    Load.load("Tutorial 3", Tutorial3.class, settings)

Loads directly the scene in the default container without displaying the settings gui :
    Settings settings = new Settings(Setting.Renderer.RENDERER_JOGL, true, new Dimension(800, 600))
    Load.loadScene("Tutorial 3", Tutorial3.class, settings)

Loads the scene in a specific container (detailed here) :
    Load.load(YourOwnContainer.class, "Tutorial 3", Tutorial3.class, Setting.Renderer.RENDERER_JOGL)
 

Until now, I didn't told you about how to creates the html code and to add an applet. Here is a short explanation to do this.

The structure of an html page is :

HTML structure

<HTML>
    <HEAD>
   
    </HEAD>
    <BODY>
   
    </BODY>
</HTML>

To put an applet in that page, we use the APLLET tag into the BODY block.
    code : indicates the class to load
    archive : indicates a jar file to put in the classpath
    glScene : a specific parameter readed by AppletContainer to know which scene must be shown.

I also added text to show you how to use the tag <P> (paragraph).

HTML structure + Text + Applet

<HTML>
    <HEAD>
   
    </HEAD>
    <BODY>
        <P>Jouvieje's Tutorials 03 - Fullscreen Loader v2.0 - Thanks to Pepijn Van Eeckhoudt</P>
       
        <APPLET CODE=org.jouvieje.gl4java.container.AppletContainer.class HEIGHT=480 WIDTH=640>
            <PARAM NAME=archive VALUE="Tutorial03.jar, BaseCode.jar">
            <PARAM NAME=glScene VALUE="org.jouvieje.gl4java.tutorials.Tutorial3">
        </APPLET>
    </BODY>
</HTML>

The APPLET tag is the most used to loads an applet in an html page.
But, here is an alternative (prefered) way to do this :

File Name

<HTML>
    <HEAD>
   
    </HEAD>
    <BODY>
        <OBJECT CODETYPE="application/java"
         CLASSID="java:org.jouvieje.gl4java.container.AppletContainer.class"
         HEIGHT=480 WIDTH=640>
            <PARAM NAME=archive VALUE="Tutorial03.jar, BaseCode.jar">
            <PARAM NAME=glScene VALUE="org.jouvieje.gl4java.tutorials.Tutorial3">
        </OBJECT>
    </BODY>
</HTML>

 

Remember to download the GraphicEngine-1.1.2 to run this tutorial !


If you've got any remarks on this tutorial, please let me know to improve it.
Thanks in advance for your feedback.
 

Previous Tutorial

Back

Next turorial

Copyright © 2004-2012 Jérôme Jouvie - All rights reserved. http://jerome.jouvie.free.fr/