TL;DR: Same question as the last thread, but trying to stay on topic this time: How do I detect collisions between meter-sized objects moving tens of kilometers per second relative to each other?
This is a follow up to this thread. That thread ended up being mostly about how to handle and store positions and velocities in (outer) space and physics in general, and started a really nice little discussion! 4 months later I’ve gotten into uni, and after playing Artemis at Cosmonova (that was AWESOME) I involuntary started thinking about this again after trying so hard to suppress these kind of impulses to allow me to focus on my current projects. Oh, well, it can’t be helped!
In this thread I’d like to focus on collision detecting. To quote myself in the previous thread (you might want my first post to get the background)…
[quote]Detecting collisions would be done in multiple stages. The first stage could be a quad tree to filter out most bodies. We could then do a bounding box collision test between AABBs of the movement lines. Then we could do a line intersection test between the two movement lines, and finally more sensitive tests to determine exactly exactly where the missile hit the ship, so we can calculate a collision response.
[/quote]
This sounds good on paper, but there are lots of things that need to be ironed out here…
- Quadtrees???
Seriously, I don’t seem to get them. I understand their uses and I’ve even coded implementations once or twice, but I don’t get how to use them with 1. dynamic data and 2. objects that aren’t points. As far as I know the first one is solved by either reconstructing the whole quadtree from scratch each frame (with node pooling to be nice to the GC) OR dynamically dividing and merging nodes as the objects move around. The first option is easy to implement but sounds a bit slow.
The second one is complicated as hell. When an object moves outside its current node, it’ll have to be removed and added again so that it can find the right new node in the node hierarchy, which doesn’t sound much faster than simply doing that for every object (option 1). Secondly, it all explodes when dealing with objects that aren’t points, which leads me into the second main problem. How the hell do I handle a quadtree with lines?! If I store them in the smallest node that can completely contain them, I may end up in a pathological cases where a number of lines intersect a border causing them to be propagated to a very large node high up in the hierarchy, basically reducing it all to an O(n^2) test (also see No 2 further down).
The other way I know of is to store the line in all the nodes that it intersects. That means that the same line is stored multiple times in many nodes. Not only does that make it possible for the same line pair to be tested multiple times (can be prevented with a DrHalfway’s BitFlags?), but it also increases the cost of adding and removing lines, which will have to be done a lot since the data is dynamic!
So, alternatives to quadtrees? Workarounds? Am I just confused?
- The lines themselves
Consider a small fleet of a few hundred fighter ships orbiting in formation around Earth going at 7 km/sec. Earth in turn is orbiting at almost 30 km/sec around the sun. Imagine the movement lines that these form. With a frame time of 12 seconds per update, they’d all be between 276km and 444km relative to the sun. However, relative to the earth, the lines are much shorter, and relative to one of the ships they should be close to 0 since they aren’t moving relative to each other. If the lines are handled relative to the sun, a quadtree will choke on the huge lines since they’ll be put either in nodes very high up in the node hierarchy or be put in so many nodes that it’ll all just fall back to O(n^2).
An idea would be to group together objects that travel at similar speeds, and generate the lines relative to the group’s velocity. However, that pretty much forces us to calculate the relative velocity lines for each object and generate a quad tree FOR EACH GROUP! Sadly, this might even be faster than not doing it, since O(n^2) > O(n^2 / groupSize). Of course only the closest 1000km or so has to be transformed, but for massive concentration of ships? Ouch. Even though the lines won’t pass the line intersection test, the intersection test itself is quite expensive.
Shit, this is looking bad…
- Determining the exact collision point
Let’s assume we solve all the above problems and the movement lines of two objects intersect. This obviously does not prove that the objects collided since they’d also have to be at the intersection point at the same time. One possible solution to this would be to compute the exact time the two objects were at intersection point. Let’s say that one of the objects crossed the line at t0 = 0.25 and object two crossed it at t1 = 0.30, we could for example cheaply take the average of those two times (t = 0.275) and do a standard collision test (with circles, boxes, etc) between them at that time. This might miss some collisions, so we might want to do that test multiple times with slightly different values, but that’s okay since these expensive tests will only occur when to lines actually intersect, which they very rarely do, even with the extremely long line problem described above. Hmm, maybe this wasn’t a that big of a problem as I thought…
Let’s focus on 1 and 2 then. Ideas, papers, breakthroughs in spatial data structures, anything goes!