Using Xith3D in Swing (specifically NetBeans)

Hi there, I am trying to get Xith3d to work inside a NetBeans TopComponent.

I plan to get my hands dirty on Xith3d by developing a scenegraph-editor as netbeans-module. Nothing big, just a view of a scene with the ability to load models and to arrange them in 3d space as a visual playground.

I’ve had no luck so far, since I can not get the 3d canvas to behave “stable”. I can add the canvas as one of netbeans editor-tabs, but if I for example switch to another tab and then back, I see only a gray swing panel, but no xith graph anymore. The same happens, if I maximize the tab with a doubleclick on the titlebar.

I can reduce the problems somewhat by putting the canvas inside a JPanel and overriding the removeNotify()-method to not call the removeNotify()-method of the xith canvas.

So I assume, that the JOGL-renderer is somewhat “confused” by the way the add- and removeNotify()-Methods are called when it is used inside a TabbedPane or a JScollpane, etc.

Could someone with knowledge of the JOGL renderer give me advise, how to solve this problem? So far I am walking in the dark :frowning:

JOGL provides two classes for hosting an openGL canvas ; GLCanvas and GLJPanel.

The first one is intended at AWT application, the second one is designed for Swing.

Most of the time, the first one works in all situations even with Swing but in some cases you will encounter the problem you have described. This is caused by the new layout management / z ordering system used by Swing.

In your case, the solution should be to use a GLJPanel instead of a GLCanvas.

The only problem is that, this will make you modify the core Xith3D (class RenderPeerImpl of JOGL renderer) which allways use GLCanvas when creating the rendering canvas.

The other drawback is that GLJPanel performs badly compared to GLCanvas.

       Vincent

Thanks for the reply!

I was considering using the GLJPanel myself, but I want to get the fastest possible performance. Maybe the hardware accelerated PBuffer-sollution of the newer JOGL builds are the way to go, but I don’t know if xith works with the latest JOGL releases. Also I am unsure if the JOGL single (AWT)-Thread hack plays nice with a xith3d rendering loop inside a swing application.

I Also have some experience in forcing AWT widgets to behave correctly in a swing context. I made an prototype of a JREX (Mozilla for Java) integration in netbeans some time ago. Most effects can be worked around by specifying heavyweight popup menues and take some actions if certain window-events are fired.

I am willing to take some effort to force the AWT canvas to behave somewhat swing conform but I am stuck at this problem and need someone to discuss possible solutions to get me out of my desultoriness :wink:

GLJPanel has a performance counterpart. Even with the PBuffer optimization (which is not always available), you still have the burden of rendering to offscreen then copying the bitmap to display.

The best thing would be to be able to have a Swing component with a direct openGL rendering context like with GLCanvas. If you know how to do this, I think that the JOGL folks will be happy with your commit !

Something you can try is to use LWJGL. Latest releases (0.96 and 0.97) provide AWTGLCanvas which gives you the possibility to render in an AWT canvas. I don’t know how well it performs with Swing. The code in Xith3D does not support it but it’s really easy to modify (class RenderPeerImpl of LWJGL renderer).

The easiest way to get a single thread system would be to avoid AWT / Swing. I think the perfect solution would be SWT but it is not supported by Xith3D and the openGL plugin for it is quite feature less (I have made a few test with this, it works but it has poor performances. I think a cross solution SWT for the widget toolkit and event model / SWT openGL plugin for the openGL creation and management / LWJGL for the openGL calls wrapping would be the way to get a good solution).

          Vincent

Since I want to create a NetBeans module, the SWT path is a no go for me (I am a die hard eclipse hater, too ;))

I don’t think, it is possible to create a swing implementation of a direct OpenGL canvas. I only wrap AWT components in JPanels, override some methods and tweak some properties on various events. This way I can create a pretty good illusion of a swing component, but nothing more :-/

Do you have added a rendering loop in your display? This could be the cause for it only rendering at the beginning and not updating later e.g. when resizing or switching.

Another problem would be the heavyweight/leightweight one. Swing is light wight, but AWT is heavylight. The Xith3d Canvas is also heavyweight, so it will always draw above swing components unless they are embedded in a awt.Panel.

Arne

Yes I have added a rendering loop. The lightweight/heavyweight problems are not relevant, since I can take care of them if the rest works :wink:

Since I can influence the effect by changing the removeNotify()-behaviour, I assume that the gl context can not be made current after some component hierarchy events.

I have made some progress. I can now switch tabs and maximize them without loosin the view, but I am still unable to get the view back if the component was closed and reopened.

In this case I get following error:


net.java.games.jogl.GLException: Attempt to call setRenderingThread on more than one drawable in this thread
      at net.java.games.jogl.impl.GLContext.setRenderingThread(GLContext.java:323)
      at net.java.games.jogl.GLCanvas.setRenderingThread(GLCanvas.java:140)
      at com.xith3d.render.jogl.CanvasPeerImpl.render(CanvasPeerImpl.java:1148)
      at com.xith3d.scenegraph.View.renderOnce(View.java:591)
      at com.xith3d.scenegraph.View.renderOnce(View.java:524)

Is there a way to cleanly shutdown a xith3d-canvas?

This is because you try to render on the “not anymore existing” canvas. You have to stop the rendering loop, too.

Hmm… thanks for the hint… I will take a closer look.

The exception occurs the first time I try to call renderOnce() on the new view. As far as I can tell, there are no more references to the old view inside my code that could accidently being used in my rendering loop. So I assumed I have to do some additional cleanup to be able to create a new RenderingPeer, etc.

Any ideas?

I should add, that I am using a global rendering loop, that is calling renderOnce() on any canvas, that is activated inside netbeans. So it seems, that I have to use one Thread per canvas since JOGL needs a dedicated Thread for each OGL context, right?

The Xith3D code should probably be changed to no longer call GLDrawable.setRenderingThread(). That was an optimization added early in JOGL development which is no longer enabled (or, apparently, necessary) by default. In the forthcoming JSR-231 implementation that API will be removed.

Thanks Ken, I have commented out the calls to these methods from Xith3D.

Changes are in CVS and the new build. I have also updated Xith3D with the new version of Jogl.

Will.

Since the use of a dedicated renderingThread per new created canvas had no effect, I will try the new build as soon as possible.

Thanks for your work!

The new release resolved most of my issues. I am now able to open/close multiple components containing a Canvas3D and switch between them.

Thanks again!

However, I have a new problem resulting in deadlock if I click too much :wink: For now every Xith-component uses it’s own rendering thread. Since JOGL is changed to the single threading solution (in the AWT-Thread I think), I suspect that I have to use a different technique to play save with JOGL for that matter. Could someone advice me how to handle the threading with the new build?

Do you pause the rendering thread, if you show a different xith-component?
I suggest for you also to add a fps display, so you can see how the fps is affected, when more than one xith-component is open.
I don’t know if this could help, but you could try.

Arne

Can you post the output from Ctrl-Break (Windows) or Ctrl-Backslash / SIGQUIT (on Unix) when your application deadlocks?

In a nutshell, JOGL executes its GLEventListener’s callbacks on the AWT event queue thread for better stability with many graphics cards. Unless you are using thread-local storage, this detail should not matter to your application. You should be careful when adding or removing widgets from the component hierarchy that you do that work on the AWT event queue thread via EventQueue.invokeLater() or EventQueue.invokeAndWait(), but this is either recommended or required practice already depending on how you look at it.

I use an own thread (not AWT) that calls renderOnce() on the Xith3D view. All scenegraph modification is made in that thread. Do I have to call renderOnce() and do the scenegraph modification from the AWT thread or is this JOGL requirement already met by xith?

Regarding the addition and removal of widgets: In fact I am not sure if all calls that modify the component hierarchy are made in the AWT thread, since I hacked some of this functionality and trigger add- and removeNotify methods from NetBeans component callbacks. I will investigate this and do some cleanup.

I will post feedback after that in the next few days.

[quote]I use an own thread (not AWT) that calls renderOnce() on the Xith3D view. All scenegraph modification is made in that thread. Do I have to call renderOnce() and do the scenegraph modification from the AWT thread or is this JOGL requirement already met by xith?
[/quote]
I don’t know Xith3D’s thread safety model so hopefully one of the Xith3D developers can chime in here. The modification of the Xith3D scenegraph and your AWT/Swing widgets are unrelated.

[quote]Regarding the addition and removal of widgets: In fact I am not sure if all calls that modify the component hierarchy are made in the AWT thread, since I hacked some of this functionality and trigger add- and removeNotify methods from NetBeans component callbacks. I will investigate this and do some cleanup.
[/quote]
Making widget hierarchy modifications from your component’s mouse and keyboard event handlers should be fine, since they are already executed on the AWT event queue thread.

After reactivating the normal add/removeNotify behaviour and synchronizing the renderOnce() calls using invokeLater, everything seems to work so far :slight_smile:

To any Xith3D-developer: is it really necessary to call the renderOnce()-method from the AWT event thread ? I would like to avoid this, if there is already a synchronization with JOLG from inside Xith3D.

iI don’t worry about the AWT thread, I just make sure scene graph updates can’t occur during rendering