Preventing transference of zero force

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
multox
Posts: 8
Joined: Tue Jul 13, 2010 12:30 am

Preventing transference of zero force

Post by multox »

Hello. I've been working with Bepu for the last few weeks since switching over from libjigx. Bepu seems to perform quite a bit better which is important to my simulation which has large numbers of objects. Thank you for making Bepu. I hope to soon become one of your paying customers.

I need help with a performance issue. It seems like whenever one entity moves, it activates all of the entities that it is near... and those activate their neighbors, and so on. They are getting woken up even though they appear to have no force applied to them. ( I have check the contacts and the each contact has zero force.) The net effect is that I'm getting hundreds or thousands of entities waking up even though they are nowhere near the original force and should not move whatsoever.

How can I dampen or prevent the activation of deactivated objects until they receive a force of sufficient magnitude to move them?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Preventing transference of zero force

Post by Norbo »

The main difficulty is that in order to determine the forces applied to each object, the collision response system must be run. Unfortunately, the collision response system is one of the largest expenses in the engine; if deactivation depends on collision response, it won't save much time.

Activation currently occurs based on simulation islands. These islands groups of entities that could possibly interact. The bounding boxes of entities are chosen as the metric of 'closeness,' so there can be a small airgap while still belonging to the same island.

Using a collision pair's contact count for a tighter fit was another option. However, contact count has a much higher change frequency, which increases the number of simulation island merge/splits substantially in certain simulations. Additionally, large piles would still generally be mega-islands, so it's unclear how much this would help the problem.

The deactivation system is slated for significant revisions in coming versions, so I may be able to overcome some of these issues.

So basically, this is a bit of a hard problem and the above doesn't help too much in actually solving your current issue. :wink: The engine can't make too many assumptions about the configuration of the physics objects, but you may be able to. If your simulation design can safely guarantee that, even though entities might be in the same simulation island, far away entities won't be meaningfully affected by an interaction, you could add in some sort of hack.

One possible hack would be to remove entities from the space when they're far away from the 'player', if such a thing exists. Of course, you'd have to worry about stacking dependencies when removing objects, and removing entities does wake up a simulation island- if only momentarily. If your game doesn't have a localized physical 'player' and interactions can happen anywhere at any time, things become even trickier, unfortunately.

Other than hacks, you could also change the simulation design somewhat so that mega-islands are rare, and moving things around only activates maybe a few dozen entities rather than a mountain. Depending on the simulation, this might not be feasible.

You could also try to tweak the simulation settings so that even when things activate, it runs at an acceptable speed:
-Lowering the space.simulationSettings.collisionResponse.iterations typically improves performance at the cost of collision response accuracy.
-If you have continuous collision detection on (it's off by default), turning it off might save a few percent.
-Ensure multithreading is enabled if you have a multicore CPU.

You can change the deactivation settings (space.simulationSettings.deactivation) so that even if things wake up, they go back to sleep quickly:
-Velocity clamping changes small velocities to zero so that the system can go to sleep faster.
-Clamping time is the length of time before such small velocities get set to zero.
-You could also try forcing the numEntitiesToTryToDeactivatePerFrame to something extremely high to ensure that every simulation island is checked every frame.

Numerous speedups will also be coming in upcoming versions (mostly due to the collision detection system rewrite). If the performance gap isn't too large, it might just be bridged by gradual improvements to the engine.
multox
Posts: 8
Joined: Tue Jul 13, 2010 12:30 am

Re: Preventing transference of zero force

Post by multox »

Thank you for the quick reply and for explaining the situation.

I did already try the velocity clamping and collisionResponse.iterations. Also, I am already using multithreading. Those did help, but not enough. Testing out numEntitiesToTryToDeactivePerFrame shows that it has a similar effect to the clamping. I am unable to turn off continuous collision detection due to a few fast moving objects that tend to miss collisions with it off. (Is it possible to turn it on only for specific objects?)

Please forgive my ignorance with Physics engines. This may be a newbie maneuver, but here's the solution that I would like to implement, only I don't know how. I have a simulation island, perhaps a line of boxes a mile long. I kick a box and the engine detects a collision between my foot and the island. It then calculates the new inertia for the box that my foot connected with. That box "absorbs" part of the inertia and passes a percentage of it along to each of its contacts. After a few boxes in each direction, there is no remaining inertia so the remainder of the boxes never need get brought into the calculations.

So after reading through the explanation of collision rules, I was hoping that maybe I could intercept the calculations at one of those stages to short-circuit the rest of the island. However, I really do not have a good understanding of how to apply the collision rules.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Preventing transference of zero force

Post by Norbo »

Is it possible to turn (CCD) on only for specific objects?
Not at this time, though this is something I'd like to revisit in the upcoming collision detection rewrite.
I have a simulation island, perhaps a line of boxes a mile long. I kick a box and the engine detects a collision between my foot and the island. It then calculates the new inertia for the box that my foot connected with. That box "absorbs" part of the inertia and passes a percentage of it along to each of its contacts. After a few boxes in each direction, there is no remaining inertia so the remainder of the boxes never need get brought into the calculations.
The problem is that the collision response system (the "solver") doesn't distinguish between your foot hitting the box versus a box hitting another box half a mile away. They are equal in priority as far as it is concerned, and all of the possibly involved entity velocities are solved globally.

If a contact path connects your foot and the box at the other end of the line, the system has to include it in the calculation (activating it) because it's part of the possibly changed global solution. It is unknown whether or not an individual entity's velocity actually changes until the new solution is computed. A box separated from from the line can stay inactive because it cannot possibly be a part of the change.

Using contacts to determine simulation islands is the direct result of this, and the decision to use the looser collision pairs was mainly due to simplicity and efficiency concerns.

Also, if the boxes are actually in complete touching contact all along the line, performing such an experiment in an idealized "real physics" scenario could in fact propagate an impulse all the way down the line. It wouldn't happen in either real life or the engine just due to the chaotic nature of the simulation (and a quirk of collision solvers), but something to keep in mind :)

To simulate that particular situation efficiently, you could leave a small gap between the boxes so that they do not create a single mile-long simulation island. When you kick a box, it will slide a little, hit the next box, and so on until the energy is exhausted through friction. The blocks not actually moved by the kick and subsequent impacts would remain inactive since they were never part of an active simulation island.
So after reading through the explanation of collision rules, I was hoping that maybe I could intercept the calculations at one of those stages to short-circuit the rest of the island. However, I really do not have a good understanding of how to apply the collision rules.
The collision rule system is designed to prevent collisions or the response to collisions based on the current involved entity collision rules. It wouldn't be practical to try to analyze every entity's velocity after each individual iteration within the collision solver and force individual collision pairs to noResponse dynamically. It would also be technically impossible if the multithreaded solver is enabled, since iterations are flying all over the place asynchronously and nondeterministically.
Post Reply