"Debugging" a corrupted scene file (j3o)

Hi all,



My scene file (Terrain_1.j30) got corrupted in the Scene Composer. It was just a test, so it's not a big problem.



I still want to know what went wrong. When I load the scene file in my application, I've got the following error:

1-sep-2010 22:07:07 com.jme3.app.Application handleError

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.lang.NullPointerException

       at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:265)

       at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:477)

       at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:465)

       at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:581)

       at com.jme3.scene.Node.read(Node.java:534)

       at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:288)

       at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:196)

       at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:118)

       at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:108)

       at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:175)

       at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:297)

       at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:307)

       at PlatformGame.Terrain.<init>(Terrain.java:29)

       at PlatformGame.GameState.initialize(GameState.java:105)

       at com.jme3.app.state.AppStateManager.update(AppStateManager.java:98)

       at PlatformGame.PlatformGame.update(PlatformGame.java:149)

       at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:112)

       at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:101)

       at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:162)

       at java.lang.Thread.run(Thread.java:619)



I think the scene goes corrupted when the scene is opened and then you click on "load in scene composer" again.



Thanks in advance.



Edit:

I have reproduced the crash:

  • Open a correct scene file in the scene composer with physics
  • Open a crashed scene file in the scene composer
  • Open the correct scene file in the scene composer again and the correct scene file is also corrupted

Maybe its because the same BinaryExporter object is used from two threads?

I've tried it again and I know how I can exactly recreate the situation. There goes something wrong with the physics loading/saving.



You should do it exactly this way in the Scene Composer:

  • Create "Scene 1"
  • Create a linked mesh
  • Generate physics for the linked mesh
  • Save the scene
  • Create "Scene 2"
  • Create a linked mesh
  • Generate physics for the linked mesh
  • Save the scene
  • Open "Scene 1"  again in the Scene Composer
  • You should get a "java.lang.NullPointerException"
  • This is the stack trace:



    java.lang.NullPointerException

    at com.jme3.bullet.collision.PhysicsCollisionObject.read(PhysicsCollisionObject.java:264)

    at com.jme3.bullet.nodes.PhysicsNode.read(PhysicsNode.java:744)

    at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:288)

    at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:477)

    at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:465)

    at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:581)

    at com.jme3.scene.Node.read(Node.java:534)

    at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:288)

    at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:196)

    at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:118)

    at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:108)

    at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:175)

    at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:297)

    at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:307)

    at com.jme3.gde.scenecomposer.OpenSceneComposer$1.run(OpenSceneComposer.java:48)

    [catch] at java.lang.Thread.run(Thread.java:619)


Yeah, somethings wrong with loading the CompoundCollisionShape for physics objects, sorry. Its about loading a nested Savable class. I dont know if its generally not possible to have nested classes implement Savable or if its a special situation in the platform. Kirill, you know this? I will check it out… Sorry again and thanks for the good bug report :slight_smile:



Cheers,

Normen

It's ok.



Thanks for the quick reply.  :slight_smile:

Maybe is has to do with circular references (?) I am not sure, but its definitely worth testing.

Loading a Savable that is stored in another Savable is possible though.

Problem has been fixed in latest svn. Apparently Savables should not be nested classes like this:



public class MyClass implements Savable{
    //this class will not load properly:
    public class MyNestedClass implements Savable{
    }
}



And btw, reading through your post again, dont create a physics shape for a linked node.. That doesnt make much sense, the collision shape would be stored in the scene and the model in the other file. Modify the other file instead or add the model to the scene.

Cheers,
Normen

Thanks for fixing and thanks for the tip.



I still got one question. How can I see if the physics of the original model are created ?



I think I have found another bug:

  • Open the original model in the SceneComposer
  • Click on the "terrain_1-geom-1" (geometry)
  • Click on "create/update mesh shape"
  • (Bug) The geometry is removed from the mesh
Vortex said:

I still got one question. How can I see if the physics of the original model are created ?

I think I have found another bug:
- Open the original model in the SceneComposer
- Click on the "terrain_1-geom-1" (geometry)
- Click on "create/update mesh shape"
- (Bug) The geometry is removed from the mesh

If you click the "show selection" button and select a physicsNode, you should see its collisionshape. About the removing.. Maybe something else goes wrong here? It removes the geometry to create a physics collision shape and then attaches a physics node instead and the geometry as a child. Any warning signs in the bottom right that could give a clue?

This is the exception that I get:

java.lang.IllegalStateException: updateGeometricState() must be called on the root node to retrieve updated world transforms.

at com.jme3.scene.Spatial.checkUpdatedTransform(Spatial.java:250)

at com.jme3.scene.Spatial.getWorldScale(Spatial.java:284)

at com.jme3.bullet.util.CollisionShapeFactory.createSingleMeshShape(CollisionShapeFactory.java:175)

at com.jme3.bullet.util.CollisionShapeFactory.createMeshShape(CollisionShapeFactory.java:127)

at com.jme3.gde.scenecomposer.SceneEditorController.doCreatePhysicsMesh(SceneEditorController.java:327)

at com.jme3.gde.scenecomposer.SceneEditorController$4.call(SceneEditorController.java:301)

at com.jme3.app.AppTask.invoke(AppTask.java:141)

Caused: java.util.concurrent.ExecutionException

at com.jme3.app.AppTask.invoke(AppTask.java:157)

at com.jme3.app.Application.update(Application.java:384)

at com.jme3.gde.core.scene.SceneApplication.update(SceneApplication.java:204)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:112)

at com.jme3.system.lwjgl.LwjglCanvas.runLoop(LwjglCanvas.java:192)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:166)

[catch] at java.lang.Thread.run(Thread.java:619)

Ah ok… Very insightful report, thank you. I commited a fix for jme3 that I think should fix this problem. Should be in the jMP update tomorrow. Might be there are more of these popping up now that the world info checks are forcibly put into the jme3 system.

Cheers,

Normen

It works now. Thanks for the quick fix.



How should I now load the model ? I currently have this code:

Spatial terrain = (Spatial) assetManager.loadModel(“Scenes/Terrain_1.j3o”);

terrain.updateGeometricState();

terrain.updateModelBound();



CompoundCollisionShape terrainShape = CollisionShapeFactory.createMeshCompoundShape((Node) terrain);

PhysicsNode physicsMesh=new PhysicsNode(terrain,terrainShape,0);



physicsMesh.setFriction(0.1f);

physicsMesh.setLocalTranslation(new Vector3f(0,-1,10));

physicsMesh.updateGeometricState();

physicsMesh.updateModelBound();



getParent().attachChild(physicsMesh);

getPhysicsSpace().add(physicsMesh);

}

Looks good. You dont need all those updateXXX(), only the updateGeometricState for physicsMesh (because you changed its location). You can also create the collisionShape in jMP already and save it in the scene. Then you just have to do a getPhysicsSpace().addAll(loadedNode) to add it to the physics space.



Cheers,

Normen

I have saved the physics in the model and I have changed the code to this:

Node terrain = (Node) assetManager.loadModel(“Scenes/Terrain_1.j3o”);



terrain.setLocalTranslation(new Vector3f(0,-1,10));

terrain.updateGeometricState();



getParent().attachChild(terrain);

getPhysicsSpace().addAll(terrain);



The addAll method has solved the problem. All works well now.



Thanks for the help.

I was a little bit too early with my answer.



I have added some linked models to my scene. Now I get this error:

java.lang.ClassCastException: com.jme3.bounding.BoundingBox cannot be cast to com.jme3.scene.Spatial

at com.jme3.scene.Node.read(Node.java:539)

at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:288)

at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:196)

at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:118)

at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:108)

at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:175)

at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:297)

at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:307)

at com.jme3.gde.core.assets.BinaryModelDataObject.loadAsset(BinaryModelDataObject.java:58)

at com.jme3.gde.scenecomposer.OpenSceneComposer$1.run(OpenSceneComposer.java:43)

[catch] at java.lang.Thread.run(Thread.java:619)



Do you have a clue what went wrong ?

Hm, thats an odd error… It seems theres still some problems with linked nodes in general… Does this only happen when the physics collision shape is part of the scene?

It looks like it has nothing to do with the physics this time.



Just create 2 or more link nodes in the scene and you get the BoundingVolume exception.



Just a side question. How many people do you think are already using this functionality ?

Ok thanks, I will check this. I dont know how many people are using what functions in jMP and how they do it, wish more people gave such constructive feedback :wink: … I guess it depends on your workflow if you need linked Nodes at all.

Cheers,

Normen

I now have added the following in a scene and I get a crash too:

  • 1 linked node with physics
  • 2 normal nodes with physics



    This is the exception I get:

    java.lang.NullPointerException

    at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:265)

    at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:477)

    at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:465)

    at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:581)

    at com.jme3.scene.Node.read(Node.java:534)

    at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:288)

    at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:196)

    at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:118)

    at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:108)

    at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:175)

    at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:297)

    at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:307)

    at com.jme3.gde.core.assets.BinaryModelDataObject.loadAsset(BinaryModelDataObject.java:58)

    at com.jme3.gde.scenecomposer.OpenSceneComposer$1.run(OpenSceneComposer.java:43)

    [catch] at java.lang.Thread.run(Thread.java:619)



    When I open my scene for a second time it opens ok. When I open it in my application it gives the exception the first time.



    I think you should really play around a bit with the scene composer. It’s still buggy.

As said, the LinkedNode is buggy still. w/o LinkedNodes it should be fine.