Collision Detection Between Rigid Bodies
Comp259, HW 2
Jeff Feasel
Assumptions
- The bounding volume is a cube.
- The objects are rougly ball-shaped; They are closed convex
polyhedra composed of triangles whose vertices are located on the surface
of a sphere with a given radius. Each object is specified with a center
location and a radius. The complexity of the ball objects is uniform
accross all objects, and is set at compile time.
- Though balls may vary in size (radius), they all have the same mass.
- Collisions are perfectly elastic.
- Translational and rotational velocity, position, orientation, and
radius are all randomly determined upon startup.
Collision Resolution
- When collision with a wall is detected, the appropriate component
of the velocity is flipped. All outside factors aside, this should cause
the ball to be moved back inbounds at the next timestep update. However,
there are problems if the velocity of the ball changes due to a collision
with another ball in the scene. Either the ball may have its velocity
component flipped multiple times, causing it to head further into the wall
even after its "correction", or the ball may be set to move away from the
wall, but not with enough velocity that it will be able to free itself from
the wall upon the next update (in which case it would be flipped to head
back into the wall once more). To correct this problem, I check the
direction of the velocity before flipping its component, to ensure that it
will ultimately point inbounds.
- When two balls collide, the velocity of the two objects is swapped.
This is not exactly physically accurate, but it succeeds in resolving
the collisions and produces behavior that looks somewhat realistic.
- It is possible that, as a result of interference from other objects
in the scene, two balls that have collidied (co-penetrated) are not able to
free themselves from eachother upon the next timestep. Their velocities
are repeatedly swapped, which makes them appear to stick together. To
remedy this, I maintain a flag for each pair of balls that is set if the two
objects are in a state of collision (i.e. they overlap) during the current
timestep. Then on the following timestep collision between these objects
is ignored if the flag had been set on the previous step. This basically
ensures that collisions are handled only once, and the objects are free to
pass through eachother until they finally separate.
Simple Implementation
- OpenGL was used for visualization of the simulation. The idle
callback routine performs a single step of the simulation. Thus the
speed of the simulation is limited only by the time it takes to perform
the computation (rather than being synched with the clock).
- During all timing tests, the visualization was turned off.
- SWIFT++ is used to preform collision detection. All ball-to-ball
test pairs are activated.
Binned Implementation
- If all objects are assumed to have the same size, the implementation
can be sped up.
- Space is divided into a 3D grid of cubes with width equal to the
diameter of the balls.
- A ball whose center is located in a particular cell can only possibly
interact with balls located either in that same cell or one of the 26 adjacent
cells.
- Each ball is placed into a bin corresponding to the cell its center
lies in, as well as the bins of the 26 adjacent cells. Only pairs
of objects that have been placed in the same bin are active for testing
by SWIFT.
- When a ball moves, if it passes into a different cell it must be
re-binned accordingly.
Performance
Time per step, as a function of Number of Objects
# balls
|
Simple Impl.
msec/step
|
Binned Impl.
msec/step
|
10
|
1.1
|
0.17
|
20
|
4.3
|
0.33
|
30
|
10
|
0.53
|
40
|
18
|
0.72
|
50
|
28
|
0.93
|
60
|
44
|
1.1
|
70
|
59
|
1.4
|
48 triangles per ball
Box size: 20x20x20
Avg ball diameter: 1.0
The diameter is an average in the un-binned, variable-size case.
In the binned case, all balls have the same diameter.
Time per step, as a function of Triangles per Object
triangles/ball
|
Simple Impl.
msec/step
|
Binned Impl.
msec/step
|
8
|
15
|
0.87
|
48
|
30
|
0.88
|
120
|
43
|
0.88
|
224
|
58
|
0.88
|
360
|
68
|
0.90
|
528
|
86
|
0.93
|
728
|
93
|
0.92
|
960
|
105
|
0.97
|
50 balls
Box size: 40x40x40
Ball diameter: 1.0
The diameter is an average in the un-binned, variable-size case.
In the binned case, all balls have the same diameter.
Note: The times for the binned implementation remained nearly
flat, with some up and down fluctuation. One would expect the times
to increase monotonicly, but the number of triangles I used isn't large
enough to put it into this regime. Even with 960 triangles per ball,
the running time is dominated by overhead costs and timing noise. Beyond
960 triangles per object, the precomputation and startup cost of populating
the scene is extremely long, so I didn't test larger values.
Time per step, as a function of Object Size
Relative Diameter
|
Simple Impl.
msec/step
|
Binned Impl.
msec/step
|
0.05
|
30
|
0.88
|
0.10
|
31
|
0.66
|
0.15
|
32
|
0.71
|
0.20
|
32
|
0.95
|
0.25
|
33
|
1.5
|
50 balls
48 triangles per ball
Box size: 40x40x40
Diameter is measured relative to the width of the enclosing box.
The figure given is an average diameter in the un-binned, variable-size
case.
In the binned case, all balls have the same diameter.
Note: As before, the binned implementation is not running
in its asymptotic regime so the measurements are mostly noise. The
measurements for the simple implementation increase slightly but consistently.
It was not possible to test larger diameter values because by 0.25
the box's volume was nearly packed and the balls have little freedom to move.
Source Code
Get it here.