jME-Physics: Why that dependency on the input handling module?

Hi developers,



Why the dependency of jME-Physics on jME input system, via SyntheticButton:s?



I find it this dependency adds to the complexity of the physics engine, since one needs to study also the input handling module to fully understand how the physics engine abstraction layer works.



I modified my version of jME-Physics to drop this dependency, and could remove around 30 + 50 lines of code from OdePhysicsSpace and PhysicsSpace. I added 15 lines of code: an ArrayList<ReusableContactInfo>, which remembers which collisions occurred so they can be invoked at the end of OdePhysicsSpace.update().



This of course entails that physics callbacks are invoked at the end of PhysicsSpace.update(), not when the input system is updated — which I think is more intuitively understandable.



Also, of course, the dependency on the input module is gone; one no longer needs to study any parts of the input handling module in order to understand how the physics module functions. In my opinion, this is more user friendly (of course, if you already know how the input module functions this is not an issue, but I believe new users that step through the physics module source code get confused when collision events are enqueued on the input module in PhysicsSpace.collisionEvent( ContactInfo info ). At least I was.



Lastly, the physics module was somewhat simplified: the functions OdePhysicsSpace.reuseContactInfos(), swapContactInfos() and reusableContactInfo() no longer needed. I consider those functions relatively complex functions, and I believe OdePhysicsSpace is easier to read with those gone.



The per-geometry / per-node callbacks were dropped (only the global one kept), but I don't think that's an issue (except for backwards compatibility), since the global callback provides all info anyway. (Of course, if people uses those callbacks, they could be rewritten in the same manner.)



Best regards,

Magnus



(Edit note: removed strange formulation about obfuscation.)

It's important to apply reactions to the collision events at particular times. Plus you are not allowed to access gl stuff in other threads than the game loop thread. Thus one needs decoupling of physics update and application specific reactions in many cases. imo it's more user friendly to provide this already instead of implementing it for each application.

As well, I don't understand why it's a drawback to have a dependency to the input handlers.

irrisor said:

It's important to apply reactions to the collision events at particular times.


Both the SyntheticButton approach and the code I wrote are safe in this regard, I believe, since in both cases collision callbacks are invoked after the actual physics calculations.

It's just that in the SynteticButton case they're invoked a bit later, in my case directly *after* the physics update. (With my approach, one could invoke the physics update just before the input update, and results should in essence be the same as in the SynteticButton case.)

irrisor said:

Plus you are not allowed to access gl stuff in other threads than the game loop thread.


In this regard, the SyntheticButton approach and the code I wrote are equally safe.

irrisor said:

Thus one needs decoupling of physics update and application specific reactions in many cases. imo it's more user friendly to provide this already instead of implementing it for each application.


In both the SyntheticButton approach and the other approach you have to register a callback object, which is application specific. The difference lies in whether the callback object extends from InputAction and handles the event in a void performAction(InputActionEvent evt) function, and is invoked when input is updated,
  or if it implements an interface named e.g. CollisionEventCallback and handles the event in a function onCollision(ContactInfo contactInfo), and is updated after the physics update step.

In my case, delaying the callback so it's invoked from the input handling routines is trivial (a one-line-function for me). I'd say it better to give people freedom to choose more precisely when the physics callbacks are to be invoked (when physics is updated, or e.g. when the input system is updated), than to assume they want physics callbacks to be invoked from the input handling module.

irrisor said:

As well, I don't understand why it's a drawback to have a dependency to the input handlers.


I generally try to avoid dependencies between modules. I think it would be reasonable to be able to rewrite/exchange the input handling module, without breaking jME-Phyics.

( Well, I suppose we need not talk more about this; it's of no interest unless you find a dependency on the input handling module less appropriate. I believe I did not appropriately describe the changes I made, given your reply, but doesn't matter. )


Thanks for your answer,
and best wishes with future development,

Magnus

( I'm using jME-Physics/ODEJava to control ragdolls, which fight each other with swords; it works fine :)  )

You approach is similar regarding timing etc. when compared to SimplePhysicsGames, that's true. But physics update might happen in another thread or at another time in the game loop in other applications. So it's not always the same.


LeoMaheo said:

I generally try to avoid dependencies between modules. I think it would be reasonable to be able to rewrite/exchange the input handling module, without breaking jME-Phyics.

Well, the InputHandler is exactly for the purpose it is used for in jME Physics - decoupling input events from input handling efficiently. That's why I think your argument does not apply in this case.

LeoMaheo said:

( I'm using jME-Physics/ODEJava to control ragdolls, which fight each other with swords; it works fine :)  )

cool :)
irrisor said:

You approach is similar regarding timing etc. when compared to SimplePhysicsGames, that's true. But physics update might happen in another thread or at another time in the game loop in other applications. So it's not always the same.


Okay, now I realize (I didn't, before) what you meant with that earlier thread statement, "Plus you are not allowed to access gl stuff in other threads than the game loop thread".

irrisor said:

LeoMaheo said:

I generally try to avoid dependencies between modules. I think it would be reasonable to be able to rewrite/exchange the input handling module, without breaking jME-Phyics.

Well, the InputHandler is exactly for the purpose it is used for in jME Physics - decoupling input events from input handling efficiently. That's why I think your argument does not apply in this case.


Okay. (You are confusing me a bit when you refer to physics engine collisions as "input events". I think of input events as keyboard and mouse clicks, although I understand why you also consider collisions as input events.)

I no longer think it matters that much, but there's still another approach that decouples the occurrence of physics engine collision input events (unambigious :)) from the application handling those events, and does not depend on the input handling module:
  The collision input events could be stored by the PhysicsSpace in a publicly read-only list until the next time update() is invoked. Inbetween, the application could fetch the events with any thread it saw fit,  loop through them, handle them directly (that's what I'd prefer) or [ wrap them in a SyntheticButton and delay them until the input handling module is updated, as is in effect done now ]. This should be as thread safe as the current approach, you would save those lines of code I mentioned above, and the programmer would have freedom to handle physics engine events at any time he/she saw fit, and... the dependency would be gone :) But for people that prefer that physics input events be invoked via a SyntheticButton, this would require, I think, an additional two lines for loop somewhere.

( However, the issue that you refer to here (in OdePhysicsSpace):
    public void update( float tpf ) {
        reuseContactInfos(); //FIX ME: deactivate triggers using this infos? keep infos for active triggers?
is obviously of relevance also to the approach I described, not only to the pure SyntheticButton approach, I believe. )

Regards,
Magnus