Multiple physic controls on one object [SOLVED]

I am trying to add two controls which ‘extends RigidBodyControl implements PhysicsTickListener, PhysicsControl’ to one object. The result is that one of the controls is actually moving the object, while the other isn’t. When I check getPhysicsLocation() on the one which is not moving the object, I see the physics control is moving, but the object is not.

To be clear: I want to use one control for following the waves and another control to apply thrust and rudder forces to actually move the ship.

I have a class ShipTest (extending Node) in which I attach both controls to the object (just showing everything related to the controls here):
[java]shipTestControl = new ShipTestControl(this, hull, shipScale, shipsMass);
buoyancyControl = new BuoyancyControl(this, hull, shipScale, shipsMass, shipsDraft);
hull.addControl(shipTestControl);
hull.addControl(buoyancyControl);
buoyancyControl.setAngularDamping(0.9f);
buoyancyControl.setLinearDamping(0.8f);
shipTestControl.setAngularDamping(0.9f);
shipTestControl.setLinearDamping(0.8f);
myBulletAppState.getPhysicsSpace().add(shipTestControl);
myBulletAppState.getPhysicsSpace().add(buoyancyControl);
buoyancyControl.setPhysicsRotation(new Quaternion().fromAngleAxis(shipsCourse, new Vector3f(0,1,0)));
buoyancyControl.setPhysicsLocation(new Vector3f(shipPos.x, shipPos.y, shipPos.z));
shipTestControl.setPhysicsRotation(new Quaternion().fromAngleAxis(shipsCourse, new Vector3f(0,1,0)));
shipTestControl.setPhysicsLocation(new Vector3f(shipPos.x, shipPos.y, shipPos.z));
hull.getControl(RigidBodyControl.class).setCollisionGroup(PhysicsCollisionObject.COLLISION_GROUP_03);
hull.getControl(RigidBodyControl.class).setCollideWithGroups(PhysicsCollisionObject.COLLISION_GROUP_02 | PhysicsCollisionObject.COLLISION_GROUP_03);[/java]

Then the two contols:
[java]public final class ShipTestControl extends RigidBodyControl implements PhysicsTickListener, PhysicsControl
{

}[/java]
and
[java]public final class BuoyancyControl extends RigidBodyControl implements PhysicsTickListener, PhysicsControl
{

}[/java]

Am I missing something here? Or is it just not possible? Or should I somehow tie the two controls together, because now they do not move each other of course?

Hum… Why do you need extending RigidBodyControl ?

You have 3 controls :

  • standard RigidBody
  • waves -> apply forces to RigidBody
  • navigation -> rudder & thrust => forces to RigidBody

Maybe I’ve not thought well about it, but it seems the way to go…
Hope that helps!

2 Likes

Yeah its possible but you have to think about the fact that the default implementations of e.g. RigidBodyControls just apply their value to the spatial. So if you have two on one spatial and update is due, the second attached control will just overwrite the values set previously by the first. You can adapt the code for the controls ofc. to cater your situation. As a sidenote, the addAll and removeAll functions of the PhysicsSpace will only work with the first PhysicsControl of any Spatial (they do getControl(PhysicsControl.class) so can only grab the first of that kind).

1 Like

Okay, think I will revert back to one control again then! I was just trying to separate the buoyancy from the rest for better readability, but I do not think it is going to serve my cause very well :smiley:

Thanks

1 Like
@husky said: Okay, think I will revert back to one control again then! I was just trying to separate the buoyancy from the rest for better readability, but I do not think it is going to serve my cause very well :-D

Thanks


Mhm, no need to use another system half-suited for what you want to do if you can just as well make your own or wrap it in somehow. Like if you have ageneric ShipPhysicsControl and you can add some behavior otherwise, like with “plugins” or multiple systems working on the data before its put in the physics control or so.

I have to think this over… Basically, what you are saying is to create a physics control (like the BuoyancyControl I have) and use this to apply the forces, but do the calculations (like calculating the controlpoints and amount of force for buoyancy and the direction of the thrust for instance) in some other control(s), which are called from within the ShipPhysicsControl prePhysicTick()? These other controls dont’t have to have an update(), because I can use the prePhysicTick to call them?

Did that make any sense? It would clean up some stuff in my code and could make it more modular, I think.

@husky said: I have to think this over... Basically, what you are saying is to create a physics control (like the BuoyancyControl I have) and use this to apply the forces, but do the calculations (like calculating the controlpoints and amount of force for buoyancy and the direction of the thrust for instance) in some other control(s), which are called from within the ShipPhysicsControl prePhysicTick()? These other controls dont't have to have an update(), because I can use the prePhysicTick to call them?

Did that make any sense? It would clean up some stuff in my code and could make it more modular, I think.

I don’t know really, I just gave an example that you don’t have to try and put a square peg in a round hole “just because”. :slight_smile: As this is a tiny cog in your application machine I don’t want to break your machine by offering another square peg :slight_smile:

Bullet itself accumulates the impulses / forces you apply during the preTick phase and you can very well have multiple influences. For example I would not attach multiple PhysicsControls as they have the described behavior by default. What you can do though is have some other Control that just grabs the RigidBodyControl from the spatial its attached to (if any is there) and just does the applyForce() on it. No need for itself to be a “real” Physics Control or interact with the spatial position, it will be set by the RigidBodyControl. So e.g. with your ship you have a RigidBodyControl and one BouyancyControl that does it the described way, then you add e.g. a “HeavyHullLeakControl” that also influences the forces on the RigidBodyControl when the ship is hit. Simple examles that probably don’t scale well to a real game (you’d want a generic DamageControl etc.) but I hope you know what I mean?

1 Like

Yeah, I am starting to see where you are coming from. Somewhere in my head a little light starts to burn :). As I said: I have to think this over and do some trials to fully understand the benefits. My head is just not big enough to see it at once!

But I do see your approach and I think I understand it and will be able to do something with it. Thanks for the directions, Normen! I appreciate it.

@normen
Okay, I think I get you. Just one question to get me started:

If I attach a regular RigidBodyControl to the ships node and create another control (BuoyancyControl, which does not extends RigidBodyControl) and attach it to the same ship, how can I get the BuoyancyControl to hook up with the prePhysicTick and physicTick loop? Is it enough to do something like:

[java]public final class BuoyancyControl extends AbstractControl implements PhysicsTickListener[/java]

Or is this not going to work?

Sure, any listener that registers will receive the update calls. But maybe its easier to just set some value to the main control which it then uses? Or the main Control gets a list of listeners it calls so it basically issues the tick updates itself (also managing some basic things like “should I update physics at all?” or “am I supposed to use damage controls atm?”

It could be both ways around, the main physics control could grab all controls of some generic type (e.g. PhysicsInfluencer) and then goes through all and calls their applyPhysicsForce(Vector3f accumulatedValue) method. Or the sub-controls just grab the main control and call some applyPhysicsData() method, the main control could actually handle these in a thread safe manner so it would receive some values but only apply them in the update loop call for example.

Hope I didn’t confuse you more with such a long “you can do it any way” :wink: The short answer way “yes, that works if you register it as a listener in the physics space” :wink:

2 Likes

Let me just try to visualize the process I just went through:

:-? :arrow: :woot: :arrow: 8-O :arrow: :’( :arrow: :-x :arrow: :-/ :arrow: :idea: :arrow: :-o :arrow: :affe:

At first I thought I should not have left my comfort zone in Mechanical Engineering, but now… :slight_smile:

Anyway, registering the PhysicTickListeners in my controls did the trick!!! Big THANKS!

My ‘architecture’ now is as follows:
Class Ship with in it:
-----The 3D-model
-----A rigidBodyControl is attached to the hull
-----A BuoyancyControl Class is attached to the hull (extends AbstractControl implements PhysicsTickListener)
-----A ShipControl Class is attached to the hull (extends AbstractControl implements PhysicsTickListener)

In both BuoyancyControl and ShipControl I have registered the PhysicTickListeners:
[java]myShipsPhysics.getPhysicsSpace().addTickListener(this);[/java] in which myShipsPhysics is the RigidBodyControl which is passed by the Ships Class when creating the BuoyancyControl and ShipControl.

As you said, the other option could be easier, but I do not really get it yet. So, I will stick to above mentioned solution for now, I guess. Maybe after some more head breaking I will figure out how to do it in the other way. Should be something like:
Class Ship
-----Attach MainShipControl (extends AbstractControl, implements PhysicsTickListener
----------Register the listener, don’t forget!
----------Create instance of BuoyancyControl (which does not have to extend AbstractControl anymore)
----------Create instance of ShipControl (which does not have to extend AbstractControl anymore)
----------Create instances of any other controls required
----------In prePhysicsTick and physicTicks call the correct functions from BuoyancyControl and shipControl

BuoyancyControl takes care of following the waves, ShipControl takes care of steering and moving.

I guess… :slight_smile:

From performance point of view, is there any prefered method (does registering of multiple listeners affect performance, for instance)?

3 Likes

Lol ^^ Sounds valid :slight_smile: I would not register single listeners mainly because I’d have to pass them the physics space or register them somewhere. If thats easy cause you have it somewhere then its fine, somehow something will have to be looped :wink: Just think about the fact that you have to unregister them as well, else they won’t be garbage collected (they are referenced in the listener list) and will receive the physics tick for all eternity, even though you don’t see them. As you by then probably have lost all links to the actual object you can’t unregister it anymore and basically have a memory (and processing) leak.

2 Likes

Cool, thans for the advise! I will see whether I can go with only one listener because I can imagine I will forget to unregistered in the end XD .

Changed the topic to [SOLVED]

1 Like