Destroying an Object3D

Started by paulscode, December 29, 2008, 02:14:50 AM

Previous topic - Next topic

paulscode

In an applet I am working on, I got the following messages, which I haven't seen before:
Additional visibility list (2) created with size: 10000
Exception in thread "AWT-EventQueue-2" java.lang.NullPointerException
at com.threed.jpct.World.renderScene(Unknown Source)
at C3.JupiterDefense.paint(JupiterDefense.java:166)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)


The applet is a target shooter which generates a lot of bullets, each having two Object3Ds (a box and a billboarded quad), so I am thinking that perhaps the problem is that I am not disposing of all these Object3Ds properly.  When I am finished with each bullet, I am running the following method:
    public void remove()
    {
        world.removeObject( object3D );
        if( childrenObjects != null )
        {
            for( int i = 0; i < childrenObjects.length; i++ )
            {
                world.removeObject( childrenObjects[i] );
            }
        }
    }


Is there something else I need to be doing in addition to calling removeObject()?

At this point, I don't really know if it is related to too many Object3Ds or what.  I will try and replicate a simple test case if possible - the project is quite large atm.  I thought in the mean time, someone might recognize that message (or why might the message "Additional visibility list (2) created with size: 10000" be generated?)

--EDIT--
Oh, I forgot to mention, I have the following line in the applet's init() method, which is where the number "10000" is coming from:
Config.maxPolysVisible = 10000;
I suppose a posibility is that the applet is running out of memory, but in that case I would expect to receive some kind of "out of memory" message instead.  I'll try and run this program as an application and see if the problem still exists.

EgonOlsen

Looks more to me as if you are creating and/or removing bullets in another thread than the rendering thread (which seems to be the awt event thread, i.e. in paint). jPCT isn't thread safe, i.e. it's not allowed to create/remove/manipulate objects from outside the rendering thread with proper synchronization.

paulscode

I see, so all calls to world.addObject (or new Object3D(...)?) and world.removeObject must be done from the paint() method, correct?  I am really surprised that I haven't run into this problem before.  Well actually, come to think of it most of my applets up to now do not create Object3Ds on-the-fly (other than the ShipRotationProblem and BulletTargetCollision demos).

I suppose the solution is a command queue for all Object3D adding and removing, which is processed and executed from the paint() method (or is there a better way to do this)?  What other things need to be done from the paint() method besides adding and removing Object3Ds (I assume things like light source creation and  removal, Light.enable(), Light.disable(), and Object3D.setVisibility() for example)?

EgonOlsen

Quote from: paulscode on December 29, 2008, 01:41:05 PM
What other things need to be done from the paint() method besides adding and removing Object3Ds (I assume things like light source creation and  removal, Light.enable(), Light.disable(), and Object3D.setVisibility() for example)?
That's a little hard to tell, so i keep it like swing does: Everything! That's not really true but like in swing, it's impossible to find and list all exceptions, so "everything" is on the safe side.
You basically have four options to deal with this:


  • Do active rendering in your own thread, i.e. no paint/paintComponent is used at all.
  • Synchronize your paint-block with the other questionable parts. You may use your own sync-object or the world itself or whatever fits.
  • Create the command-queue thing you've mentioned and enqueue all calls.
  • Use the normal SwingUtilities-stuff like invokeLater.

I think i would go with option 2...

paulscode

Yes, actually that seems like it would be the easiest option (only require adding a few lines of code).

Just to clarify on the Object3D destroy question, is world.removeObject() sufficient for letting the Java garbage collector remove an Object3D from memory (assuming I remove all handles to the object in my code), or are there other references internal to jPCT that point to the Object3D or its components, which must be removed with a call to some other method?

EgonOlsen

Quote from: paulscode on December 29, 2008, 09:11:18 PM
Just to clarify on the Object3D destroy question, is world.removeObject() sufficient for letting the Java garbage collector remove an Object3D from memory (assuming I remove all handles to the object in my code), or are there other references internal to jPCT that point to the Object3D or its components, which must be removed with a call to some other method?
No, that's fine. Some internal lists, especially when using the AWTGLRenderer, may keep a reference to that object for some time but those will be cleaned up from time to time (Config.glAWTCommandQueueCleanup, default is 10000).