views:

1080

answers:

8

I'm building a 2D physics engine and I want to add broad-phase collision detection, though I only know of 2 or 3 types:

  • Check everything against everything else (O(n^2) complexity)
  • Sweep and Prune (sort and sweep)
  • something about Binary Space Partition (not sure how to do this)

But surely there's more options right? what are they? And can either a basic description of each be provided or links to descriptions?

I've seen this but I'm asking for a list of algorithms available, not the best one for my needs.

In this case, "Broad phase collision detection" is a method used by physics engines to determine which bodies in their simulation are close enough to warrant further investigation and possibly collision resolution.

+3  A: 

I recommend quadtree partitioning. It's pretty simple and it works really well. Here is a Flash demo of brute-force collision detection vs. quadtree collision detection. (You can tell it to show the quadtree structure.) Did you notice how quadtree collision detection is only 3% of brute force in that demo?

Also, if you are serious about your engine then I highly recommend you pick up real-time collision detection. It's not expensive and it's a really great book which covers everything you would ever want to know. (Including GPU based collision detection.)

Arriu
Nice book recommendation, I may need to check that out.
Paul McMillan
+5  A: 

The best approach depends on the specific use, but the bottom line is that you want to subdivide your world space such that (a) every body is in exactly one subdivision, (b) every subdivision is large enough that a a body in a particular subdivision can only collide with bodies in that same subdivision or an adjacent subdivision, and (c) the number of bodies in a particular subdivision is as small as possible.

How you do that depends on how many bodies you have, how they're moving, what your performance requirements are, and how much time you want to spend on your engine. If you're talking about bodies moving around in a largely open space, the simplest technique would be divide the world into a grid where each cell is larger than your largest object, and track the list of objects in each cell. If you're building something on the scale of a classic arcade game, this solution may well suffice.

If you're dealing with bodies moving in a larger open world, a simple grid will become overwhelming pretty quickly, and you'll probably want some sort of a tree-based structure like quadtrees, as Arriu suggests.

If you're talking about moving bodies around within bounded spaces instead of open spaces, then you may consider a BSP tree; the tree partitions the world into 'space you can walk in' and 'walls', and clipping a body into the tree determines whether it's in a legal position. Depending on the world geometry, you can also use a BSP for your broad-phase detection of collisions between bodies in the world.

Another option for bodies moving in bounded space would be a portal engine; if your world can consist of convex polygonal regions where each side of the polygon is either a solid wall or a 'portal' to another concave space, you can easily determine whether a body is within a region with a point-in-polygon test and simplify collision detection by only looking at bodies in the same region or connected regions.

Skirwan
+5  A: 

An alternative to QuadTrees or BSPTrees are SphereTrees (CircleTrees in 2D, the implementation would be more or less the same). The advantage that SphereTrees have are that they handle large loads of dynamic objects very well. If you're objects are constantly moving, BSPTrees and QuadTrees are much slower in their updates than a Sphere/Circle Tree would be.

If you have a good mix of static and dynamic objects, a reasonably good solution is to use a QuadTree/BSPTree for the statics and a Sphere/Cicle Tree for the dynamic objects. Just remember that for any given object, you would need to check it against both trees.

Russell Newquist
+1  A: 

An alternative are plain grids, say 20x20 or 100x100 (depends on your world and memory size). The implementation is simpler than a recursive structure such as quad/bsp-trees (or sphere trees for that matter).

Objects crossing cell borders are a bit simpler in this case, and do not degenerate as much as an naive implementation of a bsp/quad/oct-tree might do.

Using that (or other techinques), you should be able to quickly cull many pairs and get a set of potential collisions that need further investigation.

Marcus Lindblom
+2  A: 

All of the acceleration algorithms depend on using an inexpensive test to quickly rule out objects (or groups of objects) and thereby cut down on the number of expensive tests you have to do. I view the algorithms in categories, each of which has many variations.

  1. Spatial partitioning. Carve up space and cheaply exclude candidates that are in different regions. For example, BSP, grids, octrees, etc.

  2. Object partitioning. Similar to #1, but the clustering is focused on the objects themselves more than the space they reside in. For example, bounding volume hierarchies.

  3. Sort and sweep methods. Put the objects in order spatially and rule out collisions among ones that aren't adjacent.

1 and 2 are often hierarchical, recursing into each partition as needed. With 3, you can optionally iterate along different dimensions.

Trade-offs depend a lot on scene geometry. Do objects cluster or are they evenly or sparsely distributed? Are they all about the same size or are there huge variations in size? Is the scene dynamic? Can you afford a lot of preprocessing time?

The "inexpensive" tests are actually along a spectrum of really-cheap to kind-of-expensive. Choosing the best algorithm means minimizing the ratio of the cost of the inexpensive testing to the reduction in the number of expensive tests. Beyond the algorithmic concerns, you get into tuning, like worrying about cache locality.

Adrian McCarthy
+1  A: 

I just came up with a solution that doesn't depend on grid size and is probably O(nlogn) (that is the optimum when there are no collisions) though worst at O(n*n*logn) (when everything collides).

I also implemented and tested it, here is the link to the source. But I haven't compared it to the brute force solution.

A description of how it works: (I'm looking for collisions of rectangles)

  • on x axis I sort the rectangles according to their right edge ( O(nlogn) )

  • for every rect in the sorted list I take the left edge and do a binary search until I find the rightmost edge at the left of the left edge and insert these rectangles between these indices in a possible_Collision_On_X_Axis set ( those are n rectangles, logn for the binary search, n inserts int the set at O(log n)per insert)

  • on y axis I do the same

  • in each of the sets I now have possible collisions on x (in one set) and on y(int the other), I intersect these sets and now I have the collisions on both the x axis and y axis (that means I take the common elements) (O(n))

sorry for the poor description, I hope you understand better from the source, also an example illustrated here: image

csiz
I understand qute well, and in fact i also have something similar (Sweep And Prune is the official name). One tip though; are you using insertion sort? it's the best algorithm available for nearly sorted lists (like you have there), and a great explanation/visualization is available at http://www.sorting-algorithms.com/insertion-sort
RCIX
thanks for the name, I thought that was a different algorithm named similarly in my language. The list isn't necessarily almost sorted as the rectangles would move around in time (thus becoming random) so I'm using std::sort
csiz
But the idea is you call it once per update so you can rely on the list being nearly sorted and use insertion sort for maximum performance.
RCIX
+1  A: 

You might want to check out what Scott did in Chipmunk with spacial hashing. The source is freely available. I think he used a similar technique to Box-2D if not for collision, definitely for contact persistence.

Nick
A: 

If the space that your objects move within is bounded, then you could use a grid to subdivide your objects. Put each object into every grid cell which the object covers (fully or partially). To check if object A collides with any other object, determine which grid cells object A covers, then get the list of unique objects in those cells, and finally test object A against each unique object. This approach works best if most objects are usually contained in a single grid cell.

If your space is not bounded, then you will need to implement some sort of dynamic grid that can grow on demand in each of the four directions (in 2D).

The advantage of this approach over more adaptive algorithsm (i.e. BSP, Quadtree, Circletree) is that the cells can be accessed in O(1) time (i.e. constant time) rather than O(log N) time (i.e. logarithmic time). However these latter algorithms are able to adapt themselves to large variability in the density of objects. The grid approach works best when object density is fairly constant across the space.

voidstar69
I'm not sure "hashtable" exactly counts as a particularly relevant collision detection algorithm.
Paul McMillan
This is not a hashtable approach. Any collision detection algorithm subdivides space in order to reduce the number of object-to-object comparisons required (as mentioned in the question). The other answers to this question have mentioned adaptive partitioning of space. My answer refers to a regular, non-adaptive partitioning of space. This has the obvious trade-offs of efficiency vs adaptability to a non-uniform distribution of objects within the space.
voidstar69