Hi!
After hours and hours of trying to wrap my head around JOGL, NEWT, etc I have finally managed to implement a simple JOGL application that: -displays something using OpenGL -has common GUI support (AWT) -and can toggle fullscreen mode (without bugging out!) Considering that I have rewritten the same app three times before, never fully utilizing all of the above, I just wanted to get some confirmation that the basic model I have now is feasible at all before I spent any more time on it. Please leave suggestions on how to avoid problems down the road. If there is a better solution, please let me know. CODE: import java.awt.*; import java.awt.Frame; import java.awt.Button; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.glu.GLU; import com.jogamp.opengl.util.FPSAnimator; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.event.KeyEvent; public class NewtSuite implements GLEventListener, KeyListener, ActionListener { private long fps_time_start, fps_time_current, fps_time_passed; private int fps_frames, fps_frames_com; private FPSAnimator gl_FPSAnimator; private GL2 gGL; private GLU gGLU; private GLWindow gl_GLWindow; NewtCanvasAWT gl_canvas; private boolean isFullscreen; private Frame frame_normal, frame_full; public NewtSuite() { init_GLWindow(); reparent_normal(); gl_FPSAnimator = new FPSAnimator(gl_GLWindow, 120); gl_FPSAnimator.start(); } private void init_GLWindow() { gl_GLWindow = GLWindow.create(getGLCapabilities()); gl_GLWindow.setSize(800, 600); gl_GLWindow.addGLEventListener(this); gl_GLWindow.addKeyListener(this); gl_GLWindow.setVisible(true); gl_canvas = new NewtCanvasAWT(gl_GLWindow); isFullscreen = false; } private void reparent_normal() { frame_normal = new Frame("AWT Frame Normal"); frame_normal.addWindowListener (new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent e) { gl_FPSAnimator.stop(); System.exit(0); } } ); Button btn; frame_normal.setLayout(new BorderLayout()); btn = new Button("North"); btn.setActionCommand("North"); btn.addActionListener(this); frame_normal.add(btn, BorderLayout.NORTH); btn = new Button("South"); btn.setActionCommand("South"); btn.addActionListener(this); frame_normal.add(btn, BorderLayout.SOUTH); btn = new Button("East"); btn.setActionCommand("East"); btn.addActionListener(this); frame_normal.add(btn, BorderLayout.EAST); btn = new Button("West"); btn.setActionCommand("West"); btn.addActionListener(this); frame_normal.add(btn, BorderLayout.WEST); frame_normal.setSize(500, 500); frame_normal.setLocation(0, 0); frame_normal.setUndecorated(false); frame_normal.setExtendedState(Frame.NORMAL); frame_normal.setVisible(true); frame_normal.add(gl_canvas); } private void reparent_full() { frame_full = new Frame("AWT Frame Normal"); frame_full.addWindowListener (new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent e) { gl_FPSAnimator.stop(); System.exit(0); } } ); Button btn; frame_full.setLayout(new BorderLayout()); btn = new Button("North"); btn.setActionCommand("North"); btn.addActionListener(this); frame_full.add(btn, BorderLayout.NORTH); btn = new Button("South"); btn.setActionCommand("South"); btn.addActionListener(this); frame_full.add(btn, BorderLayout.SOUTH); btn = new Button("East"); btn.setActionCommand("East"); btn.addActionListener(this); frame_full.add(btn, BorderLayout.EAST); btn = new Button("West"); btn.setActionCommand("West"); btn.addActionListener(this); frame_full.add(btn, BorderLayout.WEST); frame_full.setSize(500, 500); frame_full.setLocation(0, 0); frame_full.setUndecorated(true); frame_full.setExtendedState(Frame.MAXIMIZED_BOTH); frame_full.setVisible(true); frame_full.add(gl_canvas); } private void toggle_fullscreen() { if (frame_full != null && frame_full.isVisible()){ reparent_normal(); isFullscreen = false; frame_full.setVisible(false); }else{ reparent_full(); isFullscreen = true; frame_normal.setVisible(false); } gl_GLWindow.requestFocus(); } @Override public void keyPressed(KeyEvent e) { System.out.println("pressed"); toggle_fullscreen(); } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { } public void actionPerformed(ActionEvent e) { System.out.println(e.getActionCommand()+""); } @Override public void init(GLAutoDrawable arg0) { this.gGL = arg0.getGL().getGL2(); this.gGLU = new GLU(); this.gGL.glEnable(GL2.GL_DEPTH_TEST); this.gGL.glEnable(GL2.GL_TEXTURE_2D); this.gGL.glEnableClientState(GL2.GL_VERTEX_ARRAY); this.gGL.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY); fps_time_start = System.currentTimeMillis(); fps_frames = 0; } @Override public void display(GLAutoDrawable arg0) { this.gGL.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); this.gGL.glMatrixMode(GL2.GL_PROJECTION); this.gGL.glLoadIdentity(); this.gGL.glOrtho(0,500,0,500,-1,1); this.gGL.glBegin(GL2.GL_QUADS); this.gGL.glTexCoord2d (0.0,1.0); this.gGL.glVertex2d (100, 100); // Bottom Left this.gGL.glTexCoord2d (1.0,1.0); this.gGL.glVertex2d (200, 100); // Bottom Right this.gGL.glTexCoord2d (1.0,0.0); this.gGL.glVertex2d (200, 200); // Top Right this.gGL.glTexCoord2d (0.0,0.0); this.gGL.glVertex2d (100, 200+ fps_frames); // Top Left this.gGL.glEnd(); fps_frames++; fps_time_current = System.currentTimeMillis(); fps_time_passed = fps_time_current - fps_time_start; if (fps_time_passed > 1000) { System.out.println(""+fps_frames); fps_frames_com = fps_frames; fps_frames = 0; fps_time_start = fps_time_current; } } @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, int height) { } public GLCapabilities getGLCapabilities() { GLProfile glp = GLProfile.getDefault(); return new GLCapabilities(glp); } @Override public void dispose(GLAutoDrawable arg0) { } public static void main(String[] args) { new NewtSuite(); } } |
Administrator
|
Hi
AWT full screen mode is broken on some platforms including GNU Linux. You can fix solve this problem by using GLWindow. Sorry to disappoint you.
Julien Gouesse | Personal blog | Website
|
That is kind of my question. I am using a GLWindow that gets re-parented into different AWT-Frames when switching modes.
Alternatively, is there any way to have standard UI components in a GLWindow? |
Administrator
|
I have forgotten another problem. If you don't use NEWT, the OpenGL context will be destroyed when switching from full screen to windowed mode and vice versa except if you tinker... a lot.
Perhaps you can use a GLWindow whose child component is a NEWTCanvasAWT. Then, you don't need to use an instance of java.awt.Frame. When you want to switch from full screen mode, just call setUndecorated(boolean) and setFullscreen(boolean) on your main GLWindow. If it doesn't work, I will try to provide you a better solution. There are GUI libraries directly based on JOGL but they have all some drawbacks: - some widgets are directly in JOGL but they require shader support - FengGui is somehow unusable, a contributor started a big code redesign on the SVN repository and left it unfinished - Nifty Gui is very good but its memory footprint is prohibitive - PureSwing could be ported to JOGL but its main contributor plans to stop its development soon - TWL could be ported to JOGL but I don't know whether it would be a trivial task @Sven, do you have a better solution to suggest?
Julien Gouesse | Personal blog | Website
|
I don't think it's possible to add Components to a GLWindow.
Using GLWindow's addChild method only works with NativeWindow objects. NewtCanvasAWT is of the Component class and can't be added to GLWindow. Or I don't know how, anyway. From what I can tell, my GLContext doesn't get destroyed. I haven't been getting any exceptions so far. Are you saying it might be possible to add AWT components to the NewtCanvasAWT directly? I haven't actually tried that yet. I don't think I have the skill or patience to port any of those GUIs. I wouldn't even know where to begin. |
Hmm, I can only add a PopupMenu to the NewtCanvasAwt and even that causes an exception because the canvas is not actually a visible component. Bummer.
I still hope there's a solution with no awt frame. Thank you for the help so far. |
Administrator
|
In reply to this post by gouessej
On Tuesday, January 17, 2012 12:11:26 AM gouessej [via jogamp] wrote:
> > I have forgotten another problem. If you don't use NEWT, the OpenGL context > will be destroyed when switching from full screen to windowed mode and vice > versa except if you tinker... a lot. > > Perhaps you can use a GLWindow whose child component is a NEWTCanvasAWT. > Then, you don't need to use an instance of java.awt.Frame. When you want to > switch from full screen mode, just call setUndecorated(boolean) and > setFullscreen(boolean) on your main GLWindow. > > If it doesn't work, I will try to provide you a better solution. There are > GUI libraries directly based on JOGL but they have all some drawbacks: > - some widgets are directly in JOGL but they require shader support > - FengGui is somehow unusable, a contributor started a big code redesign on > the SVN repository and left it unfinished > - Nifty Gui is very good but its memory footprint is prohibitive > - PureSwing could be ported to JOGL but its main contributor plans to stop > its development soon > - TWL could be ported to JOGL but I don't know whether it would be a trivial > task > > @Sven, do you have a better solution to suggest? It would be great if an active maintainer of the above mentioned OpenGL GUI's would port or accept our patches, yes. AFAIK there were some approaches to render AWT/Swing to an offscreen image, but I don't know whats the status of it. Nevertheless this would require a solution for input events as well. I guess Julien is more up to date with all the packages floating around. +++ At least Rami and I will enhance Graph UI this year to become more usable. GLWindow is a pure NEWT component not designed to hold AWT or SWT, it supports proper fullscreen mode w/ screen mode change. NewtCanvasAWT is an adapter to plug-in NEWT to AWT, not the other way around. ~Sven |
Administrator
|
In reply to this post by klatu
I wrote a bug report, I tried to port Sven's fix in AWT but I failed. I think it would be the best solution because it would allow you to use AWT and Swing inside a full screen frame without any other third party library except JOGL, the only remaining problem would be the handling of the OpenGL context.
As far as I know, you can create a NewtCanvasAWT with a GLWindow as a parent: http://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/newt/awt/NewtCanvasAWT.html#NewtCanvasAWT(com.jogamp.newt.Window) Give it a try and if it works for you, I will check if it works fine on GNU Linux too.
Julien Gouesse | Personal blog | Website
|
Administrator
|
On Tuesday, January 17, 2012 10:36:01 AM gouessej [via jogamp] wrote:
> > As far as I know, you can create a NewtCanvasAWT with a GLWindow as a > parent: *as a child. GLWindow is a native _child_ of NewtCanvasAWT. NewtCanvasAWT is a native _parent_ of GLWindow. *native*, because it utilizes the native windowing toolkit's parenting not AWT's, which is the solution to make it work. > http://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/newt/awt/NewtCanvasAWT.html#NewtCanvasAWT(com.jogamp.newt.Window) > http://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/newt/awt/NewtCanvasAWT.html#NewtCanvasAWT(com.jogamp.newt.Window) > Give it a try and if it works for you, I will check if it works fine on GNU > Linux too. |
Thank you both for the effort!
It's not the answer I was hoping for, but at least I know how it works now. @gouessej I may be wrong, but I remember reading on this board somewhere that you have made a port for Nifty GUI. If so, where could I find it? @Sven Graph UI looks like it has potential. Sadly it's not really what I'm looking for right now. Luckily I don't need my app to be platform independent, so I will stick to my current model for the time being. Thank you. |
Administrator
|
The source code is here but my renderer has probably not been maintained:
http://nifty-gui.git.sourceforge.net/git/gitweb-index.cgi
Julien Gouesse | Personal blog | Website
|
Free forum by Nabble | Edit this page |