object list not being consistent during rendering

Started by AugTech, December 11, 2011, 01:01:44 PM

Previous topic - Next topic

AugTech

Hi,
I wanted to check if there is a specific order to adding and building objects within the world(!) on an ongoing basis.

My application is dynamically creating and building objects based on a download, and then adding them into the world, but very quickly this results in the message
QuoteThere's a problem with the object list not being consistent during rendering. This is often caused by concurrent modification of jPCT objects on a thread different from the rendering thread!

I am trying to store the un-built objects built within an arraylist as they are downloaded and created, and then based on a timer within the onDrawFrame() method rattle through the list adding them into the world to try and ensure that the render thread is in control, but this doesn't help.

What seems to happen is that (for example) 1300 objects are created, then the addObject timer kicks in and adds them to the world - this is fine. The next time the addObject timer kicks in, it adds another 20 objects to the world, at which point the above error happens and kills the application. (Previously the objects were added as they were downloaded)

I have tried calling theWorld.buildAllObjects(); and theWorld.compileAllObjects(frameBuffer); after the objects are added, which helps stability for the first set of objects, but the error still happens the second time around.


public void onDrawFrame(GL10 arg0) {
long thisFrameTime = System.currentTimeMillis();

// Render the scene
theWorld.renderScene(frameBuffer);
theWorld.draw(frameBuffer);
frameBuffer.display();

if (thisFrameTime - addTime >= 5000) addObjectsToWorld();
}

private void addObjectsToWorld() {
//if (runed) return;
int i=0;
for (Dataset ds : theApp.getTheRegistry().getDataContainer()) {
for (Feature f : ds.getFeatureCollection()) {
if (f.isBuilt() && f.isVisible() && !f.isInWorld()) {
for (A_Object3D o : f.get3DObjects()) {
f.setInWorld(true);
theWorld.addObject(o);
}
i++;
}
}
}

if (i>0) {
theWorld.buildAllObjects();
try {
theWorld.compileAllObjects(frameBuffer);
} catch (Exception e) {
e.printStackTrace();
}
}
Log.i("Render","Added "+i+" objects to world");
addTime = System.currentTimeMillis();
}


Any help would be much appreciated

EgonOlsen

The message might not be correct in all cases. It just catches a null pointer exception which most common cause is what the message says but it doesn't has to be that. Actually, there should be an exception printed to the log too. I would like to have a look at this...

AugTech

Egon,
The additional log entry up to and including is;
Quote

12-11 12:17:47.200: INFO/jPCT-AE(14229): VBO created for object 'object525'
12-11 12:17:47.200: INFO/jPCT-AE(14229): VBO created for object 'object525'
12-11 12:17:47.240: INFO/jPCT-AE(14229): VBO created for object 'object30'
12-11 12:17:48.280: INFO/jPCT-AE(14229): [ 1323605868284 ] - WARNING: There's a problem with the object list not being consistent during rendering. This is often caused by concurrent modification of jPCT objects on a thread different from the rendering thread!
12-11 12:17:48.285: INFO/jPCT-AE(14229): [ 1323605868285 ] - ERROR: java.lang.NullPointerException
12-11 12:17:48.285: INFO/jPCT-AE(14229):     at com.threed.jpct.CompiledInstance.fill(CompiledInstance.java:1020)
12-11 12:17:48.285: INFO/jPCT-AE(14229):     at com.threed.jpct.Object3DCompiler.compile(Object3DCompiler.java:151)
12-11 12:17:48.285: INFO/jPCT-AE(14229):     at com.threed.jpct.World.compile(World.java:2055)
12-11 12:17:48.285: INFO/jPCT-AE(14229):     at com.threed.jpct.World.renderScene(World.java:1093)
12-11 12:17:48.285: INFO/jPCT-AE(14229):     at com.awila.app.graphics.JpctRenderer.onDrawFrame(JpctRenderer.java:110)
12-11 12:17:48.285: INFO/jPCT-AE(14229):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1388)
12-11 12:17:48.285: INFO/jPCT-AE(14229):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1138)



EgonOlsen

Well...looks like you are trying to compile an object that uses a mesh that has already been stripped. I'm not handling this case correctly and i've no idea how i should, because i can't possibly know which object's mesh will be reused in the future. I'm add better error checking to a new version so that this situation will be handled more gracefully. For now, you have basically three options:


  • Don't use strip() on these objects.
  • Add all objects to the world before rendering even if they are invisible (this might not be an option, but at least the engine can handle that case)
  • If the objects already share meshes, you can do this on the gpu level too by using Object3D.shareCompiledData(...); This should avoid the problem.

neo187

#4
Hi Egon

I am having the same issue when I try to use Loader.loadSerializedObject to load serialized objects.

So I have the Activity class with the GLSurfaceView.Renderer class inside as per Hello World example. I have this class initialize a different class called GameWorld where I want to have the World and all the Object3Ds. I have a loadLevel method that I call on initialization to load all the objects (and they are loaded fine) and when they are loaded I call a GameWorld.draw() method that calls in turn the world.renderScene and the world.draw methods.

I get the "object list not being consistent" error as soon as the drawing begins:

01-01 23:40:29.134: INFO/jPCT-AE(687): [ 1325461229141 ] - WARNING: There's a problem with the object list not being consistent during rendering. This is often caused by concurrent modification of jPCT objects on a thread different from the rendering thread!
01-01 23:40:29.164: INFO/jPCT-AE(687): [ 1325461229171 ] - ERROR: java.lang.NullPointerException
01-01 23:40:29.164: INFO/jPCT-AE(687):     at com.threed.jpct.Object3D.transformVertices(Object3D.java:6316)
01-01 23:40:29.164: INFO/jPCT-AE(687):     at com.threed.jpct.World.renderScene(World.java:1105)
01-01 23:40:29.164: INFO/jPCT-AE(687):     at com.voicegame.GameWorld.drawWorld(GameWorld.java:169)
01-01 23:40:29.164: INFO/jPCT-AE(687):     at com.voicegame.GameController$MyRenderer.onDrawFrame(GameController.java:348)
01-01 23:40:29.164: INFO/jPCT-AE(687):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1127)
01-01 23:40:29.164: INFO/jPCT-AE(687):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:975)
01-01 23:40:29.184: WARN/dalvikvm(687): threadid=15: thread exiting with uncaught exception (group=0x4001b188)
01-01 23:40:29.214: ERROR/AndroidRuntime(687): Uncaught handler: thread GLThread 8 exiting due to uncaught exception
01-01 23:40:29.224: ERROR/AndroidRuntime(687): java.lang.RuntimeException: [ 1325461229171 ] - ERROR: java.lang.NullPointerException
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at com.threed.jpct.Object3D.transformVertices(Object3D.java:6316)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at com.threed.jpct.World.renderScene(World.java:1105)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at com.voicegame.GameWorld.drawWorld(GameWorld.java:169)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at com.voicegame.GameController$MyRenderer.onDrawFrame(GameController.java:348)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1127)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:975)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at com.threed.jpct.Logger.log(Logger.java:189)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at com.threed.jpct.Logger.log(Logger.java:148)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at com.threed.jpct.World.renderScene(World.java:1121)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at com.voicegame.GameWorld.drawWorld(GameWorld.java:169)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at com.voicegame.GameController$MyRenderer.onDrawFrame(GameController.java:348)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1127)
01-01 23:40:29.224: ERROR/AndroidRuntime(687):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:975)


I'm not stripping any meshes and the error doesn't happen is I use the 3DS loader instead of the Ser one. In another thread a user mentions to have resolved this by separating threads... If that's the solution, how would I go about this?

Thanks for your help!

EgonOlsen

If it doesn't happen with 3ds but only with the .ser format, it seems to be a some problem with the deserialized objects or the way you are serializing/using them. Can you provide a test case with one of these objects so that i can see for myself?

neo187

Ok so it turns out that that's an error that you also get when you forget to .build() your deserialized objects...

I can't remember why I was doing this with my library, I think I read somewhere that building the objects in AE would impede some other process, maybe it was the animations.... so I was only calling .calcBoundingBox() and .calcNormals()...and this was working fine in another AE project..... but yeah, seems like I need to remember to always build all objects!...

Thanks for your prompt reply!

EgonOlsen

But that shouldn't happen. Best practice is to call build() on the objects before serializing them, because that removes some burden from the build() on Android, but if you don't do this, it shouldn't crash but build() should be called automatically...i'll look into this...

neo187

Yes I remembered that AE built objects automatically if they hadn't been already...could it have to do with the fact that I am doing the deserializing and adding to the world through a jar library and not inside the project itself? That's the only difference I can think of with the other AE project where the same function was working without calling .build()... and yes, the objects are all built in my editor before they are serialized....

EgonOlsen

I've no idea why this should happen...are you 100% sure that are NOT adding these objects at runtime, i.e. in a way that they interfere with the rendering thread?