Where's my beloved OnContact Action?

I just did an update on the Physics System from the latest CVS stuff and all the ContactAction code is gone. It seems to have been replaced by ContactPair which is fine but I don’t see a setContactPair method anywhere anymore.



Is that gone for good??

It seems like the setContactAction was replaced with addContactPair in PhysicsWorld. Would it be possible to get back the setContactAction functionality?





With addContactPair you have to specify which two objects the contactPair is going to be between. This makes it impossible to do for something like a ship and contacts with map objects.



In addition, you wouldn’t be able to use it for things like bullets flying around hitting other ships as you’d have to add a contact pair for each bullet with each ship.



The old way where you could set a contactAction for each object was much easier to use and made more sense when implementing it into a game.



I realize with the old system you couldn’t do any logic in the contactAction but that was easily avoided by setting up actionQueues.



I know a new physicsCollisionResults class was added whereby you can get access to all the collisions that occurred but that requires looping through every collision and checking both objects just to find the one type of collision you’re interested in.



This seems like a lot more overhead to me although it could be that in the old contactAction way the overhead was just hidden behind the scenes (not sure about that)



Also, from a design perspective, I like adding the contactAction of the PhysicsObject at the time of object creation rather than having a ton of if statements checking the PhysicsCollisionResults array.

Heh, you can do all of the above and still get less memory consumption than before.



Notice that the method is called “add…” not “set”. This is because you can specify the same contactPair for multiple objects. E.g. your bullets and map.



Ok, let me explain to you something about the previous contactAction stuff. Basically, it was wrong. Ode produces 1 contact per two objects colliding. The way we used to do it is call two contactAction methods. Now this was ok for logic (it was brilliant!) but for simulating physics, it was a nightmare!



E.g. for a car to be properly simulated over terrain, the terrain ContactAction had to be nullified (i.e. its method doesn’t contain anything) and each wheel having the contact info for stuff. This seems ok, but it gets REALLY complicated for larger stuff. Which object should have the empty contactAction?! Umm…



So a ContactPair was introduces whereby its method will be called when the PhysicsObjects registered with it touch. You can have a ball and terrain, bullet and car, arrow and tree all using the same CollisionPair. Im sure you can see the point behind this…



Also, the current implementation is faster, the dreaded hashmap in the PhysicsWorld is gone now forever and replaced with a very fast ArrayList. Im sure you know that the speed of Hashmaps is O(log n) whereby arraylists is O(1).



Thinking about the contactAction and each physics system having one, i think this is more of the Entity’s job. It should handle the collision to remove all the if/else statements from it. E.g:



PhysicsCollisionResults results = PhysicsWorld.getInstance().update(tpf);
for (int i = 0; i < results.getNumberOfCollisions(); i++) {
  String name1 = results.getCollisionData(i).getSourcePhysicsObject()
               .getName();
  String name2 = results.getCollisionData(i).getTargetPhysicsObject()
               .getName();

  Entity t1 = EntitySystem.getEntity(name1);
  t.contact();
  Entity t2 = EntitySystem.getEntity(name2);
  t2.contact();
}



And thats it basically. no more if statements or what not...

If you really really really really and i mean really want the old way and you can't live with the current way (even tho its better in terms of physics simulation/memory usage/speed ;)) then i'l bring the old way back.

DP


PhysicsCollisionResults results = PhysicsWorld.getInstance().update(tpf);
for (int i = 0; i < results.getNumberOfCollisions(); i++) {
  String name1 = results.getCollisionData(i).getSourcePhysicsObject()
               .getName();
  String name2 = results.getCollisionData(i).getTargetPhysicsObject()
               .getName();

  Entity t1 = EntitySystem.getEntity(name1);
  t.contact();
  Entity t2 = EntitySystem.getEntity(name2);
  t2.contact();
}



So the above "cleaner" method is to have each entity handle it's own collision responses in regards to game logic. This makes sense. Your basic recommendation then is not to use ContactPairs and addContactPair for logic but to instead have the entity system handle game logic?

I like this. Thanks for the clarification. I guess I reacted badly initially because when I update my physics stuff my code totally broke hehe. Oh well, with progress comes .... refactoring code I guess hehe.

I started switching over to the new system … it’s sooooo much cleaner now :smiley:

Basically, ContactPairs should only be used to modify how the objects react after the collision. I.e how hard to bounce…any slip in the forward direction? any slip in the normal contact direction?..etc.



Well, im glad it worked out good for you. Because i knew i was going to go under some pretty heavy fire to justify why ive done this! :slight_smile:



Anyways, this is for the best, i assure you. This is so that the car stuff handles like a proper car (i.e. burn outs and stuff!).



DP

Oh … one question which comes to mind.





Will a collision be reported twice?



So if a bullet hits a ship will that show up as 2 results in the PhysicsCollisionResults.



The first time with the bullet as the target and the second time with the bullet as the source?

Well, it will actually be reported 1 - 4 times for a box! This is because every contact actually produces the corners of the box that are touching. If the box is flat on, it could end up with 4 physics results. This is a bug and i am trying to fix it :slight_smile:



DP

But the desired behavior is that a collision between two objects will only be reported once right?



So a bullet hitting a wall gets reported as either



Collision – bullet = source, wall = target

OR

Collision – bullet = target, wall = source



but not both.



The bug doesn’t really effect me at the moment cause I’m using bounding spheres so take your time. Of course if it did I’d be cracking the whip on you, hehe :wink:

It will only be there once for source and target, they wont be swapped over. But i think the solution to this problemo is coming along quite nicely actually…stay tuned!



DP

okies, fix is in CVS. Now only one entry is added to the results for every collision between the objects.



Mr. Smith…NEXT!



DP