LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: Rainer on February 29, 2008, 12:30:16

Title: LWJGL JPanel
Post by: Rainer on February 29, 2008, 12:30:16
Is there somewhere an example how i can add OpenGL content to a JPanel/JFrame?
I tried this: http://lwjgl.org/forum/index.php/topic,1474.0.html
but failed on: org.lwjgl.LWJGLException: No Pbuffer support
Title: Re: LWJGL JPanel
Post by: Schnitter on February 29, 2008, 13:06:06
I remember there is somewhere in this forum a reply of evil-devil. So you can look for the author.
Title: Re: LWJGL JPanel
Post by: Rainer on February 29, 2008, 14:59:46
I think you mean this one:
http://lwjgl.org/forum/index.php/topic,1451.0.html

I'll try :)
Title: Re: LWJGL JPanel
Post by: Rainer on March 01, 2008, 15:22:02
I now got a solution with AWTGLCanvas working.
Since there is no call of Display.create(); i can't use all of the Display... functions.
Until now, i did the rendering in a while(true) loop with Display.sync(FRAMERATE).
How can i do someting similar with the canvas?
Title: Re: LWJGL JPanel
Post by: bobjob on March 01, 2008, 19:31:34
If you want to use the sync method outside of Display try this:

import org.lwjgl.Sys;


long tm; //last time holder

//add your own sync method
public static long sync(int fps, long timeThen) {
long gapTo = Sys.getTimerResolution() / fps + timeThen;
long timeNow = Sys.getTime();

while (gapTo > timeNow) {
try { Thread.sleep(1);
} catch (InterruptedException e) {}
timeNow = Sys.getTime();
}
return timeNow;
}

//PLACE IN YOUR INIT CODE
public void init() {
             Sys.initialize();
             tm = Sys.getTime(); //init time
}

//PLACE OVER YOU OLD SYNC CALL
public void render() {
            tm = sync(FRAMEFRATE, tm);
}


Title: Re: LWJGL JPanel
Post by: Rainer on March 02, 2008, 12:54:43
Thanks, that works, now the problem is that rendering blocks every other things, e.g. menus arn't working anymore.
I guess i need to do the rendering in a second thrad?
Don't know how this is done the proper way :(
I attach my testprogram so you might be able to help :)

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.AWTGLCanvas;
import org.lwjgl.opengl.PixelFormat;
import java.awt.*;
import javax.swing.*;
import org.lwjgl.opengl.glu.GLU;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.Sys;

public class GLPanel extends JPanel {

    private int width;
    private int height;
    private int FRAMERATE = 1;
    private long tm;
    private MyCanvas canvas;

    public GLPanel(int width, int height) {
        this.width = width;
        this.height = height;
        setSize(width, height);
        setLayout(new BorderLayout());

        Sys.initialize();
        tm = Sys.getTime();

        try {
            canvas = new MyCanvas();
            add(canvas, BorderLayout.CENTER);
        } catch (LWJGLException e) {
            e.printStackTrace();
        }
    }

    /**
     * The canvas that will show the GL scene
     */
    private class MyCanvas extends AWTGLCanvas {

        /**
         * Creates a new Canvas
         * @throws  LWJGLException If we can't make a view
         */
        public MyCanvas() throws LWJGLException {
            super(new PixelFormat());
        }

        public void initGL() {
            glEnable(GL_TEXTURE_2D);
            glShadeModel(GL_SMOOTH);
            glClearColor(0, 0, 0, 1.0f);
            glClearDepth(1.0f);
            glEnable(GL_DEPTH_TEST);
            glDepthFunc(GL_LEQUAL);
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();

            GLU.gluPerspective(45.0f, ((float) width) / (float) height, 0.1f, 150.0f);
            glMatrixMode(GL_MODELVIEW);

            glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
        }

        private long sync(int fps, long timeThen) {
            long gapTo = Sys.getTimerResolution() / fps + timeThen;
            long timeNow = Sys.getTime();

            while (gapTo > timeNow) {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                }
                timeNow = Sys.getTime();
            }
            return timeThen = timeNow;
        }

        public void paintGL() {
            while (true) {
                render();

                if (glGetError() != GL_NO_ERROR) {
                    System.out.println("error occured");
                }
                try {
                    swapBuffers();
                } catch (LWJGLException e) {
                    e.printStackTrace();
                }
                tm = sync(FRAMERATE, tm);
            }
        }
       
        private void render() {
            glClearColor((float) Math.random(), (float) Math.random(), (float) Math.random(), 1.0f);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            glLoadIdentity();
            glTranslatef(0.0f, 0.0f, -6.0f);
            glColor3f(1.0f, 0.0f, 0.0f);
            glBegin(GL_QUADS);
            glVertex3f(-1.0f, 1.0f, 0.0f);
            glVertex3f(1.0f, 1.0f, 0.0f);
            glVertex3f(1.0f, -1.0f, 0.0f);
            glVertex3f(-1.0f, -1.0f, 0.0f);
            glEnd();
        }
    }
}

Title: Re: LWJGL JPanel
Post by: bobjob on March 03, 2008, 00:41:58
its set to 1 fps, maybe change the FRAMERATE to 60
Title: Re: LWJGL JPanel
Post by: Rainer on March 03, 2008, 06:34:07
it was set to more than 1, that was just a test ;)
Title: Re: LWJGL JPanel
Post by: Rainer on March 03, 2008, 07:19:58
Ok, new Idea:

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.AWTGLCanvas;
import org.lwjgl.opengl.PixelFormat;
import java.awt.*;
import javax.swing.*;
import org.lwjgl.opengl.glu.GLU;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.Sys;

/**
* Panel which contains the OpenGL scene
* @author  swift
*/
public class GLPanel extends JPanel{

    private int width;
    private int height;
    private int FRAMERATE = 60;
    private long tm;
    private MyCanvas canvas;

    public GLPanel(int width, int height) {
        this.width = width;
        this.height = height;
        setSize(width, height);
        setLayout(new BorderLayout());

        Sys.initialize();
        tm = Sys.getTime();

        try {
            canvas = new MyCanvas();
            add(canvas, BorderLayout.CENTER);
        } catch (LWJGLException e) {
            e.printStackTrace();
        }
    }

    /**
     * The canvas that will show the GL scene
     */
    private class MyCanvas extends AWTGLCanvas implements Runnable{

        /**
         * Creates a new Canvas
         * @throws  LWJGLException If we can't make a view
         */
        public MyCanvas() throws LWJGLException {
            super(new PixelFormat());
            new Thread(this, "RenderThread").start();
        }

        public void initGL() {
            glEnable(GL_TEXTURE_2D);
            glShadeModel(GL_SMOOTH);
            glClearColor(0, 0, 0, 1.0f);
            glClearDepth(1.0f);
            glEnable(GL_DEPTH_TEST);
            glDepthFunc(GL_LEQUAL);
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();

            GLU.gluPerspective(45.0f, ((float) width) / (float) height, 0.1f, 150.0f);
            glMatrixMode(GL_MODELVIEW);

            glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
        }

        private long sync(int fps, long timeThen) {
            long gapTo = Sys.getTimerResolution() / fps + timeThen;
            long timeNow = Sys.getTime();

            while (gapTo > timeNow) {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                }
                timeNow = Sys.getTime();
            }
            return timeThen = timeNow;
        }

        public void paintGL() {
                render();

                if (glGetError() != GL_NO_ERROR) {
                    System.out.println("gl_error");
                }
                try {
                    swapBuffers();
                } catch (LWJGLException e) {
                    e.printStackTrace();
                }
        }
       
        private void render() {
            glClearColor((float) Math.random(), (float) Math.random(), (float) Math.random(), 1.0f);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            glLoadIdentity();
            glTranslatef(0.0f, 0.0f, -6.0f);
            glColor3f(1.0f, 0.0f, 0.0f);
            glBegin(GL_QUADS);
            glVertex3f(-1.0f, 1.0f, 0.0f);
            glVertex3f(1.0f, 1.0f, 0.0f);
            glVertex3f(1.0f, -1.0f, 0.0f);
            glVertex3f(-1.0f, -1.0f, 0.0f);
            glEnd();
        }

        public void run() {
            while(true){
            repaint();
            tm = sync(FRAMERATE, tm);
            }
        }
    }
}


Do you think, this solution is ok?
Title: Re: LWJGL JPanel
Post by: Evil-Devil on March 03, 2008, 14:16:25
Its been a while since I used the AWT GLCanvas back at version 0.99 ^^".

Thought you should subclass the AWTGlCanvas directly and use it instead of a JPanel. I added the subclassed Canvas to the panel and of course the Canvas have to run in its own thread. Anyway, to make menus to appear and work properly you have to set them HeavyWeight.

Hope that helps :)
Title: Re: LWJGL JPanel
Post by: Rainer on March 03, 2008, 18:25:31
Problem from the version i posted is now that the thread just has some timer function, rendering itself is still done by the AWT-EventQueue.
So if i begin to load e.g. some big textures, the application is not responding until loading finished, it would need to be done in the new thread.
How can i start the canvas in it's own thread?
Title: Re: LWJGL JPanel
Post by: Rainer on March 06, 2008, 10:18:45
So nobody knows how to create an intelligent renderloop with AWTGLCanvas?
Also, is it possible, to use the Keyboard. methods, without a created Display?
Title: Re: LWJGL JPanel
Post by: Evil-Devil on March 13, 2008, 08:36:38
AFAIK you will allways have a short or long wait when loading textures. Therefor I suggest to preload all needed textures.

Another possible way might be to create a shared context. The AWT GLCanvas displays the scene and in the background a pbuffer loads the needed data within its own thread.

last and ultimate way is to recreate the awt glcanvas with your own version. As i haven't used it since 0.99 and my example application does not run with the current version there have been changed a lot of stuff.

Just my thoughts.
Title: Re: LWJGL JPanel
Post by: Rainer on March 14, 2008, 13:11:58
Quote from: Evil-Devil on March 13, 2008, 08:36:38
Another possible way might be to create a shared context. The AWT GLCanvas displays the scene and in the background a pbuffer loads the needed data within its own thread.
I tryed the pbuffer, but it wasn't supported on my notebook (if i remember correctly).
Since i'll not be able to recreate awtglcanvas i'll go with the first solution, even if the app hangs a little time.