If it works and the performance is not a problem, don't change it. Premature optimisation is bad.

It just won't scale well, for culling zillions of items, like when you're rendering forests with millions of trees. Let's say you'd have 1% in your 'catch all' node, that would be 10K items. That will really grind your physics engine to a hold.

With 1000 items in the world that 1% is not going to affect performance noticably.

Hi, appreciate more people! Σ ♥ = ¾Learn how to award medals... and work your way up the social rankings!

Because of this thread I am planning on implementing some tests. I am also planning on releasing the source for everyone to see and review.

So far I am planning to test two collision strategies for each data structure:-bruteforce (O(n^2) for reference)-sweep and prune with circles or axis aligned boxes (with insertion sort for O(n), perhaps quicksort for O(n log n)

and the following cases of datastructures:-No data structure at all-2d grid-Regular quadtree (create static quadtree to nth level and add objects accordingly)-Dynamic quadtree (create static quadtree to nth level to avoid runtime allocation, add objects to nodes until the node is full. Once the node is full, redistribute the objects into child nodes)

I'll impose no similar limitations as pointed out by Orangy Tang in my solution. This means that I probably can't squeeze in my "hackish approximation of Quadtree".

There is one major problem though: how do the advocates of the elegant and simple Quadtree approach handle moving objects especially now that one object may be in multiple nodes?

Do you: - simply remove the object when it has moved and reinsert it? - clear the whole tree and insert all of the objects again? - update the tree from within so that you only ascend only the needed amount and then add the node? How are objects that reside in multiple nodes handled? - calculate edge and vertex neighbors initialization time, store references to them and update the node that way? Again, how are objects that reside in multiple nodes handled?

My objects only ever live in one node, and as such, they have a reference to the node that they are currently in, to enable me to very efficiently remove them from the node when they are being moved. I then simply add them back into the quadtree. Seems to work fine, especially as my objects are well distributed spatially, so I don't run into the case where lots of them end up in bigger parent nodes than necessary, and it's very fast.

Sounds very interesting. Go on - write it with a generic QuadTree interface so we can poke our own algorithms into it so they can shoot it out. I wouldn't mind writing a loose quad tree variant and seeing how it compares.

Sounds very interesting. Go on - write it with a generic QuadTree interface so we can poke our own algorithms into it so they can shoot it out. I wouldn't mind writing a loose quad tree variant and seeing how it compares.

I'll have to work on this during the weekend. I implemented bruteforce and prune and sweep collision strategies (the difference is 300 fps for 10000 objects in 20kx20k area as you may imagine). I didn't notice too big of a difference in between insertion sort and quicksort.

What do you want from a generic data structure interface?

Currently I have:

1 2 3 4 5 6 7 8 9 10 11 12 13 14

publicinterfaceISpatialDataStructure {

publicvoidadd(Entityentity);

publicvoidremove(Entityentity);

publicvoidcollide();

publicvoidupdate(floatdt);

publicvoiddraw(Graphicsgraphics);

}

This gives tons of options to anyone developing a data structure. Is there anything else that might be needed?

I'll probably add an intersection query function for a Rectangle (think of FPS style selection) that returns list of objects it intersects. I am going to use Slick for the testbed so I hope that's okay for everyone.

Hello (I was previously captain, but decided to change my user name to what is use normally)

I had a few extra hours during the weekend so I put together a little testbed.

So far I have implementations for - Prune and Sweep Strategy - Regular Quadtree

Regular quadtree introduces a ton of overhead at the moment because objects are re-added to it every single time. For some reason I have a gut feeling that updating objects from the leaf node they are in is not going to be efficient since you don't know for certain where else the object also resides.

Any opinions on the implementation? I'd like to see more data structures submitted by others. The code should be free to use in open source compatible way (none of the algorithms are particularly hard), but I'd like to see any improvements made to existing implementations also if someone decides to submit their own implementation.

It would be possible to make this better by incoporating prune and sweep. This would be done by changing the addToCell and removeFromCell functions to only remove and add the object if it doesn't intersect with the square. This way the order of the objects is preserved for insertion sort. Furthermore one has to change the sorting algorithms so that they sort the other objects and not the tested object.

Unfortunately my internet connection is incredibly slow right now (stupid data caps). I'll get the slick libraries in a few days when I'm back up and running properly again. Hopefully I'll find time next week to have a play with some implementations.

A couple of thoughts though: can the drawing of Entities be moved out of the datastructure? Perhaps there could be an method to get an Iterator instead which can be used externally to draw them. If debug information needs to be included then this could be provided by the datastructure as a String, or some predefined Debug class.

As a side note, your life might have been easier with sweep and prune if you'd just made a Comparitor and used standard Collections/Arrays sort methods. I believe those methods use quicksort on large arrays, and move to insertion sort once partitions are small enough to not warrant the overhead.

I've downloaded slick and run the test. I'm not sure of the value of the visualisation though, since once I raise the number of entities to 10k it drops to under 1 fps (it's rendering about once every 15 updates - each timed update and render takes less than 100ms).

With 1k or fewer entities any naive implementation will be fine (say, <1ms for updates and collision detection), so the visualisation doesn't seem all that useful. Here's a test class "CollisionTest2" that drops any graphical output - still using your existing interfaces apart from one extra method in ISpatialDataStructure:

The perils of microbenchmarks! You're saying a regular quadtree approach to collision detection takes 28 seconds for 50 updates and just 1,000 entities? The whole reason I switched to quadtrees for my game "engine" is that I needed to do about 2,000 entities in a millisecond!

The perils of microbenchmarks! You're saying a regular quadtree approach to collision detection takes 28 seconds for 50 updates and just 1,000 entities? The whole reason I switched to quadtrees for my game "engine" is that I needed to do about 2,000 entities in a millisecond!

Cas

The beauty of microbenchmarks is the fact that if you don't show it, it didn't happen

I wouldn't call these micro-benchmarks, since they create 20 complete situations and run them for 50 iterations. This is a benchmark for roughly uniformly distributed, slowly moving objects in an area 200 times their maximum radius.

I think I didn't make the quad tree's extra "clear()" method properly (realised after going to bed last night). I'll check that and repost its time.

Cas, we're only saying that that implementation takes that long. If you looked at the code you'd see it was completely unoptimised (lots of unnecessary method calls), not to mention the fact that the tree gets rebuilt from scratch each update. As far as I can tell it was just supposed to be a baseline.

I added a print out of the average number of collisions. That quad tree implementation gives double the number of collisions as sweep and prune - so I'm guessing there's also a bug in there somewhere.

Finally, when using a sort method for sweep and prune that makes use of the fact that entities are mostly ordered it carves about 20% (at 10k entities) of that time off. Most of the remaining time is spent comparing entities so it looks like moving to some form of 2D sorting (like quad trees) would make sense at that point.

50 iterations isn't up to much.. that's not even 1 second of game play! I'd run them for a lot longer, and also plonk things of varying sizes in there, and also have them move in a bit less of a random way perhaps, such as flocking.

I added a print out of the average number of collisions. That quad tree implementation gives double the number of collisions as sweep and prune - so I'm guessing there's also a bug in there somewhere.

There's definitely a bug in there. I'll attempt to fix this once I have more time. I am planning on extending the test bench to some queries: query against a circle (point & radius) and a rectangle, since those are pretty important in my game.

Hi, I was playing around a bit with this matter the other day and I found "kinetic data structures" to be very interesting for something like this. I'm short on time right now, but as a brief explanation: For each entry calculate the distance to the border of the quadtree node it's in. Then from the distance and the (maximal) movement speed calculate when the next update might be possible. Simulate on and just check the time if there's any need to update. If no update is required you're done, otherwise you just need to update a few entities (usually).I have tried to implement it and it seems to work so far, but I neither have any benchmarks nor any real tests I made about stability etc. ...I just liked the idea What do you think about this approach?

I am perhaps coming into this a little late. But anyway, since i just finished my quad tree implementation for a RTS game I though I would give my experiences and suggestions. Feel free to ignore or otherwise pipe to /dev/null.

My current Quad tree is dynamic and gets 100 game frames per second with 20K units in a type of "boid" simulation. 60% of the CPU usage is updating the boids. Not the quad tree. Given that my target game frame per second is 5-10. This is basically done until it pops up on a profiler.

I use a few tricks that have already been suggested. The only "tricky" thing I do is keep track of adjacent nodes at the same level (or higher). Then when i call revalidate and I find a unit that has moved out of the current leaf, I can send it directly to the adjacent node (which may or may not be a leaf). This provides O(1) performance average case per unit thats moved, and O(ln n) worst case. rather than re add from the root that gives O(ln n) average case. It made quite a big difference and it means that increasing the time between game ticks does not *increase* the work needed per tick (too much).

Now i can do 2 fast queries on this structure. k nearest neighbor and "area queries". Both work in about O(ln n) time but the kNN has a larger over head that area queries. Note that about O(ln n) time here means we are ignoring the size of the returned result. This does affect performance. I don't use these for collision detection, but rather "unit" sensors... ie what airplane is closest to me.

For collision I do an "internal" area query. This still has expected performance O(ln n) for very large units. But average O(1) for smaller units. Since we expect large units to be rare and move slower than small units, so this works pretty good.

In practice I am getting less than a 5% cpu overhead for all these features and can burn CPU time on AI and rendering.

However I have not got to the "what is visible" bit yet. And I use massive vision distance for units, I hope that area queries are more than good enough (should be since I don't need to have a regular area).

Also just one other comment. Insertion sort has performance O(n^2) not O(n) as some post claimed. The best *any* sort can do is O(n) on a sorted list. Since it must take O(n) comparison just to show that a list is sorted. (merge sort and insertion sort gets O(n) for sorted lists. Basic Quick sort degenerates to O(n^2) ) . You can only do better with radix sorts (not a comparison sort). In fact I did collision detection with a sweep whatever using radix sort. It was fast.

I have no special talents. I am only passionately curious.--Albert Einstein

Also just one other comment. Insertion sort has performance O(n^2) not O(n) as some post claimed. The best *any* sort can do is O(n) on a sorted list. Since it must take O(n) comparison just to show that a list is sorted. (merge sort and insertion sort gets O(n) for sorted lists. Basic Quick sort degenerates to O(n^2) ) . You can only do better with radix sorts (not a comparison sort). In fact I did collision detection with a sweep whatever using radix sort. It was fast.

I think the post that referred to insertion sort as being O(n) was working with uniformly distributed slow moving entities. So the list is known to be mostly in order at each step. While in reality I'm sure that the number of crossing entities is relative to n (probably sqrt(n) ?) , in the simulation he posted - with so few crossings per time step - it's seems reasonable to refer to it as O(n).

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org