Bug in World.renderScene()?

Started by AGP, December 19, 2010, 04:41:05 AM

Previous topic - Next topic

AGP

Is this a bug? It has to be, right? It's on the renderScene() call, after all, and nothing's null.

Is World null? false Is buffer? false Number of objects: 3

[ Sun Dec 19 01:34:56 BRST 2010 ] - ERROR: Can't remove object #7!
Exception in thread "Thread-4" java.lang.NullPointerException
        at com.threed.jpct.World.renderScene(Unknown Source)
        at MyQuestForGlory.draw(MyQuestForGlory.java:1161) //World.renderScene() call!
        at MyQuestForGlory.run(MyQuestForGlory.java:743)
        at java.lang.Thread.run(Unknown Source)

EgonOlsen


AGP


EgonOlsen

But maybe a scaled blit in software mode?

AGP

I'm doing nothing complex at all. I have characters, they're being animated, there are a few 2D layers (renderScene() and draw() get called a few times in my draw method, but it's crashing on the first call anyway), that's it.

EgonOlsen

#5
Well, that doesn't really answer my question. Judging from the log you've posted, somebody removes objects from the world. Why this fails in that case is another question, but the basic question is: Who? In jPCT itself, there's one line of code that does this and that inside the dispose() method of an Overlay. If you are using scaled blitting in the software renderer, an Overlay is internally used, which might be another source.
If you are not using any of these, i assume that your own code does this, which looks like a threading issue to me. The "normal" way to create a null pointer in renderScene() is to mess around with a world's set of objects while the world is being rendered.
If you are unsure about the removal, set the Logger to throw an Exception in case of an error. We should get the stack trace of that call then. Maybe that helps to find the source.

AGP

I do World.removeObject (when the screens change), but it's the same code that's been there for years and never crashed. I don't do it from inside draw() or anything. Hey, lightbulb: has the multi-thread settings in jpct change recently? The only new factor I can think of is that I replaced the laptop on which I'm working from a single-core to a multi-core one.

EgonOlsen

No, it hasn't changed...but replacing a single core cpu with a dual core can have exactly this effect, because it now happens in parallel and not just "faked" parallel. If your removeObject() has any chance to interfere with the rendering, try to synchronize it and see if that helps.

AGP

I tried setting a boolean to prevent draw from being called while inside changeRoom(Room) but that did not prevent the crash. But the remove thing's out of the console:

Is World null? false Is buffer? false Number of objects: 4

Exception in thread "Thread-4" java.lang.NullPointerException
        at com.threed.jpct.Object3D.transformVertices(Unknown Source)
        at com.threed.jpct.World.renderScene(Unknown Source)
        at MyQuestForGlory.draw(MyQuestForGlory.java:1162)
        at MyQuestForGlory.run(MyQuestForGlory.java:744)
        at java.lang.Thread.run(Unknown Source)

EgonOlsen

World can't be null as you wouldn't get that far in that case anyway. Looks like the same issue just at a different stage. boolean flags don't cut it for synchronization, they aren't save. You have to synchronize against some common object for example (can be anything) using synchronize(<obj>){...} for both blocks.

AGP

I declared both draw() and changeRoom(Room) synchronized (private synchronized void changeRoom(...)). Is that supposed to have done it? It didn't.

EgonOlsen

No idea if that's all that's needed because i don't know the code. Everything that manipulates the world or its objects (that includes translations and rotations) from outside the drawing thread (may that be your own thread or the awt event dispatch thread) has to be synchronized to the drawing thread or otherwise, all kinds of funny things might happen. This is why i always recommend to do everything in the drawing thread. Just like Swing, where you are supposed to do your Swing related stuff in the awt event dispatch thread.
Is it possible to replace all calls to remove...() by setVisible(false) to see if that helps? Just for testing...

paulscode

It generally works to simply wrap the following around everything jPCT-related:
synchronized( frameBuffer.getLock() )
{
    // stuff here
}


I don't think simply declaring the individual methods as synchronized will work.  I may I misunderstand how Java works, but I believe doing it that way will synchronized calls to those methods individually, while calls between those methods are not synchronized (in other words two threads could not call changeRoom() at the same time, but one thread could call changeRoom() while another is calling draw()).  It is best to synchronize everything to a single Object, and the getLock() method works well for providing one.

EgonOlsen

synchronizing a method means that no other thread can access ANY other synchronized method of the same instance. It's virtually the same as doing a synchronized(this) {....} in each method.

VT900

I've had this problem before. this occurs when you are removing an object that has been added to the world twice. Go through your code and look for where this has happened.

Quote from: AGP on December 19, 2010, 10:01:26 PM
I tried setting a boolean to prevent draw from being called while inside changeRoom(Room) but that did not prevent the crash. But the remove thing's out of the console:

Is World null? false Is buffer? false Number of objects: 4

Exception in thread "Thread-4" java.lang.NullPointerException
        at com.threed.jpct.Object3D.transformVertices(Unknown Source)
        at com.threed.jpct.World.renderScene(Unknown Source)
        at MyQuestForGlory.draw(MyQuestForGlory.java:1162)
        at MyQuestForGlory.run(MyQuestForGlory.java:744)
        at java.lang.Thread.run(Unknown Source)