[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A catastrophe is an event where there is a discontinuity in the system and the ODE solver can't cope with it. So you need to resolve the catastrophe situation before the system can be evolved any further. The main catastrophe event (actually the only one used in most rigid-body simulations) we deal with is a collision. So I use the terms catastrophe and collision interchangeably here.
Note: There is no collision detection capability in `csphyziks'. Ben Sprague has been making good progress on one and hopefully it will be integrated in the future. SOLID is a pretty decent GPL collision detection engine that works well for colliding contacts, although it requires a few more features before it can be used for resting contact.
First thing you need to do is subclass `ctCatastropheManager' and
implement check_catastrophe()
which returns a value greater 0 if there
was a catastrophe, and handle_catastrophe()
which will be called when
the simulation has been backed up to a point just before the first catastrophe
was encountered (within the catastrophe defined epsilon of time). Then you
add your `ctCatastropheManager' to the world using:
ctWorld::register_catastrophe_manager( ctCatastropheManager* your_cat_manager); |
Now every time you call ctWorld::evolve(real t1, real t2)
it will
make a callback to check_catastrophe()
where you do your collision (or
whatever) check using the position and orientations of the rigid bodies at
that time. If there was a collision, keep track of what objects collided and
return the maximum interpenetration distance (or just a number greater than 0
if you like). If there was no collision return 0. Now the physics engine
will rewind the state of the system and call check_catastrophe()
again,
and repeat until you finally return 0, indicating there was no catastrophe.
Now the physics engine will make a callback to handle_catastrophe()
where you must resolve all catastrophes that occurred during the most recent
call to check_catastrophe()
, so you need to maintain a list of those
objects that collided last check. In the case of resolving collisions you
need to fill out a `ctCollidingContact' object and pass it to
ctWorld::resolve_collision()
for each collision, which will apply an
impulse to both bodies and send them on a path away from each other.
A couple of things need to be explained. The collision normal and contact point must be figured out by the collision detection routines, which are not part of the `csphyziks' library. The collision normal is the vector that specifies what component of the objects momentum to bounce back.
The collision normal is calculated once you know what features of each object collided. If it was a vertex or edge of one object hitting a face of another object, the collision normal is just the normal of that face. If it is an edge-edge collision the normal is the cross-product (normalized) of those two edges. Or you can just take a best guess if you don't have a very accurate collision detection system.
To find the exact time of collision involves rewinding the `csphyziks' simulation and trying with smaller time steps until `csphyziks' has reached a minimum collision distance. This can be quite a time-consuming process.
The collision response code does not accurately handle multiple points of simultaneous collision on one object.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |