Render problems for custom context menu in OpenGL / SWT

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Render problems for custom context menu in OpenGL / SWT

alexsb
Hi.

I'm trying to open a context menu on a right mouse click, when picking an item in opengl. I use the swt/awt bridge for jogl.

Opening the menu out of opengl works fine as long as I don't open it using a click - i.e. opening the menu on a mouse-over event works as expected, but not when I click the item. I suspect that the click triggers the menu to be closed immediately.  Does anyone know how I could avoid that?

Thanks & cheers,

Alex
Reply | Threaded
Open this post in threaded view
|

Re: Render problems for custom context menu in OpenGL / SWT

alexsb
I should add that the context menu is in SWT
Reply | Threaded
Open this post in threaded view
|

Re: Render problems for custom context menu in OpenGL / SWT

Wade Walker
Administrator
Could you post the code you're using to create and set the menu? I'll also need to know what platform you're running on and what JOGL version you're using.

Reply | Threaded
Open this post in threaded view
|

Re: Render problems for custom context menu in OpenGL / SWT

gouessej
Administrator
In reply to this post by alexsb
Hi!

Is the use of SWT really mandatory for your popup menu? You could use AWT for the popup menu and execute any SWT operations on the SWT rendering thread by using Display.asyncExec.

Do you use the GLCanvas of JOGL 2 (as I do) or do you use the GLCanvas of SWT (as Wade does)?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Render problems for custom context menu in OpenGL / SWT

alexsb
Hi,

thanks guys for trying to help!

Here's the code I use to create the menu:

                                PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
                                        @Override
                                        public void run() {
                                                manager.getParentGLCanvas().getParentComposite()
                                                                .notifyListeners(SWT.MouseDown, new Event());

                                                Menu menu = new Menu(manager.getParentGLCanvas()
                                                                .getParentComposite().getShell(), SWT.POP_UP);
                                                Point point = manager.getParentGLCanvas().getParentComposite()
                                                                .toDisplay(0, 0);
                                                System.out.println(point);
                                                menu.setLocation(point.x + pick.getPickedPoint().x, point.y
                                                                + pick.getPickedPoint().y);
                                                MenuItem item = new MenuItem(menu, SWT.PUSH);
                                                item.setText("Popup");
                                                item = new MenuItem(menu, SWT.PUSH);
                                                item.setText("Popup1");
                                                item = new MenuItem(menu, SWT.PUSH);
                                                item.setText("Popup2");
                                                item = new MenuItem(menu, SWT.PUSH);
                                                item.setText("Popup3");
                                                item = new MenuItem(menu, SWT.PUSH);
                                                item.setText("Popup4");
                                                item = new MenuItem(menu, SWT.PUSH);
                                                item.setText("Popup5");
                                                // manager.getParentGLCanvas().getParentComposite().setMenu(menu);
                                                menu.setVisible(true);

                                        }
                                });
                       
SWT is not really mandatory, however, we are using Eclipse RCP - so it would be natural to do so. In the long run (as soon as the GLCanvas of SWT ever becomes reliable for all Platforms) we want to get completely rid of AWT.

We're using the latest jogl2 beta with GL2.
Reply | Threaded
Open this post in threaded view
|

Re: Render problems for custom context menu in OpenGL / SWT

gouessej
Administrator
No there is no "natural" way of mixing SWT and OpenGL as the GLCanvas of SWT is broken and mixing AWT, SWT and JOGL is not trivial.

The GLCanvas of SWT is no more maintained since 2006 so using it is not a really good idea on my view. I use Eclipse RCP too. You should use AWT until we get a nice SWT implementation of NEWT. Make an AWT PopupMenu and add it to the parent of the JOGL GLCanvas. Use SWT_AWT to create an AWT Frame and put it into your EditorPart or ViewPart. If you need an example, I wrote something simple in a bug report.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Render problems for custom context menu in OpenGL / SWT

Wade Walker
Administrator
In reply to this post by alexsb
Hi Alex,

Here's a complete program that opens a context menu in SWT with the SWT GLCanvas when the user right-clicks. I tested it on Linux 64-bit with GTK just now, but it should work on Windows too. It looks like your problem was you were trying to set the menu on the composite instead of the GLCanvas.

package name.wadewalker.onetriangle;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.opengl.GLCanvas;
import org.eclipse.swt.opengl.GLData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;

import javax.media.opengl.GL;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GL2;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.glu.GLU;

public class OneTriangle {

    public static void main(String [] args) {
        GLProfile.initSingleton( true );
        Display display = new Display();
                final Shell shell = new Shell( display );
                shell.setLayout( new FillLayout() );
                final Composite composite = new Composite( shell, SWT.NONE );
        composite.setLayout( new FillLayout() );

        GLData gldata = new GLData();
        gldata.doubleBuffer = true;
        // need SWT.NO_BACKGROUND to prevent SWT from clearing the window
        // at the wrong times (we use glClear for this instead)
        final GLCanvas glcanvas = new GLCanvas( composite, SWT.NO_BACKGROUND, gldata );
        glcanvas.setCurrent();
        GLProfile glprofile = GLProfile.get( GLProfile.GL2 );
        final GLContext glcontext = GLDrawableFactory.getFactory( glprofile ).createExternalGLContext();

        // fix the viewport when the user resizes the window
        glcanvas.addListener( SWT.Resize, new Listener() {
            public void handleEvent(Event event) {
            setup( glcanvas, glcontext );
            }
        });

        // draw the triangle when the OS tells us that any part of the window needs drawing
        glcanvas.addPaintListener( new PaintListener() {
            public void paintControl( PaintEvent paintevent ) {
                render( glcanvas, glcontext );
            }
        });

        final Menu menu = new Menu( shell, SWT.POP_UP );
        MenuItem item = new MenuItem( menu, SWT.PUSH );
        item.setText( "Popup" );
        glcanvas.setMenu( menu );

        glcanvas.addListener( SWT.MenuDetect, new Listener () {
            public void handleEvent( Event event ) {
                // this gets called when the user right-clicks
            }
        });

                shell.setText( "OneTriangle" );
                shell.setSize( 640, 480 );
                shell.open();

                while( !shell.isDisposed() ) {
                        if( !display.readAndDispatch() )
                                display.sleep();
                }

        glcanvas.dispose();
                display.dispose();
    }

    private static void setup( GLCanvas glcanvas, GLContext glcontext ) {
        Rectangle rectangle = glcanvas.getClientArea();

        glcanvas.setCurrent();
        glcontext.makeCurrent();

        GL2 gl = glcontext.getGL().getGL2();
        gl.glMatrixMode( GL2.GL_PROJECTION );
        gl.glLoadIdentity();

        // coordinate system origin at lower left with width and height same as the window
        GLU glu = new GLU();
        glu.gluOrtho2D( 0.0f, rectangle.width, 0.0f, rectangle.height );

        gl.glMatrixMode( GL2.GL_MODELVIEW );
        gl.glLoadIdentity();

        gl.glViewport( 0, 0, rectangle.width, rectangle.height );
        glcontext.release();    
    }

    private static void render( GLCanvas glcanvas, GLContext glcontext ) {
        Rectangle rectangle = glcanvas.getClientArea();

        glcanvas.setCurrent();
        glcontext.makeCurrent();

        GL2 gl = glcontext.getGL().getGL2();
        gl.glClear( GL.GL_COLOR_BUFFER_BIT );

        // draw a triangle filling the window
        gl.glLoadIdentity();
        gl.glBegin( GL.GL_TRIANGLES );
        gl.glColor3f( 1, 0, 0 );
        gl.glVertex2f( 0, 0 );
        gl.glColor3f( 0, 1, 0 );
        gl.glVertex2f( rectangle.width, 0 );
        gl.glColor3f( 0, 0, 1 );
        gl.glVertex2f( rectangle.width / 2, rectangle.height );
        gl.glEnd();

        glcanvas.swapBuffers();
        glcontext.release();    
    }
}

Note that if you're doing the context menu in an Eclipse RCP app, you may want something more like this (this is clipped from a program that opens a context menu in an IEditorPart):

        createMenuActions();
        MenuManager menumanagerPopup = new MenuManager( "#PopupMenu" );
        menumanagerPopup.setRemoveAllWhenShown( false );
        final Menu menu = menumanagerPopup.createContextMenu( glcanvas );
        glcanvas.setMenu( menu );
        placementeditor.getEditorSite().registerContextMenu( menumanagerPopup, this );
        menumanagerPopup.add( createrowaction );
Reply | Threaded
Open this post in threaded view
|

Re: Render problems for custom context menu in OpenGL / SWT

Wade Walker
Administrator
In reply to this post by gouessej
I have to respectfully differ with Julien's viewpoint  He is a strong advocate for JOGL 2, and a great coder, but I think he may be using more advanced OpenGL features than business and scientific users do.

We've used "pure" SWT in Eclipse RCP applications at work for many years, and never had a problem we couldn't overcome (in JOGL 1.1.1a). The SWT GLCanvas may have bugs with JOGL 2 features like shaders, but I haven't seen an example of that yet.

If we want to entice people to switch from JOGL 1.1.1a to JOGL 2, I think the best way is for JOGL 2 to work perfectly in SWT and AWT with the existing canvases. That way existing JOGL users can make the minimum possible modifications to their programs to take advantage of the new OpenGL 2.0 & 3.0 features.
Reply | Threaded
Open this post in threaded view
|

Re: Render problems for custom context menu in OpenGL / SWT

Matt
In reply to this post by gouessej
Sorry for a bit of OT:

gouessej, you said that GLCanvas from SWT lib is not a good idea, and well, I see its drawbacks especially in multisampling being broken.
However... I might had done something wrong, but some simple tests I did quite some time ago have proven the SWT's GLCanvas to be noticably faster from the AWT bridge... so what would you suggest to use for the main OpenGL container if I wanted to stay with SWT, because the GLCanvas is just a small portion of the whole GUI application, so the standalone NEWT is rather not an option... ?
Reply | Threaded
Open this post in threaded view
|

Re: Render problems for custom context menu in OpenGL / SWT

gouessej
Administrator
Personally I have quite good performances with the SWT_AWT bridge used on very big meshes but with JOGL 1.1.1a. When I switched to JOGL 2.0, I found a bug that affects one of my optimizations that allowed me to swap the buffer by myself. The best solution would be a NEWT implementation for SWT so that we could use a NEWT canvas inside an SWT application and do the rendering on the SWT dispatching thread.

I think that a "naive" use of the SWT_AWT bridge can cause some tiny problems of synchronization and then you can noticeably (70%?) decrease the performance.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Render problems for custom context menu in OpenGL / SWT

alexsb
Just a quick note: Thanks guys for your suggestions. I got sidetracked to more pressing issues, however, I hope to give your suggestions a try in a week or two!

Alex