LWJGL JPanel

Started by Rainer, February 29, 2008, 12:30:16

Previous topic - Next topic

Rainer

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

Schnitter

I remember there is somewhere in this forum a reply of evil-devil. So you can look for the author.

Rainer


Rainer

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?

bobjob

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);
}



Rainer

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();
        }
    }
}

bobjob

its set to 1 fps, maybe change the FRAMERATE to 60

Rainer

it was set to more than 1, that was just a test ;)

Rainer

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?

Evil-Devil

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 :)

Rainer

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?

Rainer

So nobody knows how to create an intelligent renderloop with AWTGLCanvas?
Also, is it possible, to use the Keyboard. methods, without a created Display?

Evil-Devil

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.

Rainer

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.