[SOLVED] BulletAppState, physics tick and update methods exclude each other

Dear experts,
I have a class with following parameters:
extends BulletAppState implements PhysicsTickListener

in this class method prePhysicsTick I read input keys and apply player movement/rotation.
So far that works.

Now I work on showing to user selected object on mouse over.
This is done by adding/removing ambient light for selected object.

If I add this code inside of method prePhysicsTick or PhysicsTick, I get error:

Uncaught exception thrown in Thread[jME3 Main,5,main]
IllegalStateException: Scene graph is not properly updated for rendering.
State was changed after rootNode.updateGeometricState() call.
Make sure you do not modify the scene from another thread!
Problem spatial name: Root Node

If I implement code in public void update(float tpf),
then Physics tick is not executed anymore.

What could you advise, what am I doing wrong?

1 Like

You are not allowed modifying the scene graph from another thread.

Use app.enqueue() instead.

Regards
Domenic

2 Likes

Thanks a lot Domenic!
This was the solution in case someone else has same situation as me:

@Override
public void prePhysicsTick(PhysicsSpace space,
        float tpf) {
    //apply user input
    app.enqueue(new Runnable() {
        @Override
        public void run() {
        //apply scene graph changes
        }
    });
}
1 Like

This is really bad practice. You shouldnt be monitoring input events from another thread. Using enqueue to get back to the main thread stinks of both bad design and not fully understanding threading. Its the equivalent of making everything static for convenience. Yes it works, but it should definitely be used with caution and very specific circumstances - not as a work-around for bad design. A regular input listener registered to the inputManager is perfectly sufficient.

If anything, enqueue should only really be used to run something in the next frame. Not for thread-jumping. Unless you have a very specific circumstance.

/rant

1 Like

Right, gather your input, do your highlighting, etc. in the regular update of an app state.

Apply the current state of whatever the input says in your prePhysicsTick… with proper thread safety.

1 Like

Hi Pspeed,

that was my idea as well to use update method of the app state to handle user input.
However, if you do implement such method in the BulletAppState class,
then prePhysicsTick is never called. Is it a bug?

Best regards,
Denis

1 Like

Hi Jayfella,

thanks for your input. I am new into java development, and I also have no much understanding of threading.
However, I would not really use current solution, if app state would allow me to do input management there…
It works for standard AbstractAppState, but not for BulletAppState

1 Like

No. You changed something else or your detection that it’s not called is incorrect.

The two things are completely unrelated and there is no “magic code” that would make one stop working just because you use the other one. So it must be something else you’ve done.

Edit: unless the app state you are extending did something in its own update() call and you are not calling super.update(). In which case, you need to call super.update(). I didn’t think of it at first because that’s just a general rule when you override a standard class’s methods like that.

2 Likes

Well, I decided to comment and find what in my own code could cause it.
In the end I commented everything, so there is no code at all, and tick is never called.
This is quite a simple example:

> public class LevelOnePhysics extends BulletAppState implements PhysicsTickListener {
>     @Override
>     public void initialize(AppStateManager stateManager, Application app) {
>     }
>     @Override
>     public void prePhysicsTick(PhysicsSpace space,
>             float tpf) {
>         System.out.println("Called new tick");
>     }
>     @Override
>     public void physicsTick(PhysicsSpace space, float f) {
>     }   
>     @Override
>     public void update(float tpf)  {
>  
>     }
> }

But, if I comment the void update, the tick is called
:astonished:

1 Like

Have you tried invoking super.update() in your update method, as Paul suggested?

2 Likes

Sorry,very dumb from me, I somehow oversaw this part. It is working perfectly, thank you a lot!

1 Like

Hi Pspeed, I somehow oversaw you last edit:

Stupid from me, I did not call super.update, now it works, thank you a lot! :))

1 Like