Not sure how to improve performance

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Not sure how to improve performance

Post by snoozbuster »

So, in this game I'm tinkering with, I basically have a simple voxel engine set up. This is all fine, but BEPU doesn't really appreciate 2300 Box entities all right up next to each other. Well, it can handle 2300, but then when you add another set of 2300, and another... It starts slowing down from the sheer number of bounding box intersection tests, even though all the cubes are kinematic and don't collide. I took a look at the source and the reason it's a problem is because CollisionGroup/CollisionRule testing isn't done until after the related bounding box check. First, I tried scaling the cubes down to 0.99 units square, which helped a little. Then, I tried using a CompoundBody, but adding 2300 objects to a CompoundBody takes a solid minute or two; plus I'm currently using raycasting, normals, and positions to implement my 3D voxel editor; that might keep working due to CompoundBody using EntityCollidables internally but I'm not sure. I also have to keep track of data in my original object; color, grid position, things like that, but I think I can find an unused Tag somewhere. It's mainly the very long creation time that I'm not super fond of; is there a better way to do this besides CompoundBody?
Another thing I just tried was only adding visible (ie, non-surrounded) cubes to the Space; this cuts down on the number of objects in the Space by about half, but still slows down after around the same period of time (worlds are 32x32 when created, and have about three layers of cubes; so there are around 1024 cubes visible if you view from the top, and then I estimate another 32x2x4 cubes for the sides; overall there's about 1200 cubes added instead of 2400).

Anyway. Any suggestions?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Not sure how to improve performance

Post by Norbo »

Shenanigans are afoot- the construction time for a 2300-box CompoundBody should be around 2-6 milliseconds, not a minute. Even on the Xbox 360 or an old phone, a minute is way longer than expected.

If the blocks are static, using a StaticGroup would also work. The construction time should be almost the same as a CompoundBody (a tiny bit faster), but with a StaticGroup you'd also be able to remove objects dynamically as of yesterday's source version.

If you do go with the StaticGroup, keep in mind that it's possible to ruin the quality of the tree with pathologically bad runtime adds and removes. If possible, order the adds and removes in a spatially random way to keep quality high. To improve the quality of the tree if it gets stuck in a bad state at runtime, you could call Reconstruct to rebuild the tree, or do incremental rebuilds by removing and reinserting random subsets of the tree over time.

[Side note: the need for batching static objects outside of the broad phase at high object counts should go away eventually. I originally planned the necessary optimizations for this year, but internal development shifted course, so it looks like it will be later next year before I get to it.]
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Not sure how to improve performance

Post by snoozbuster »

Norbo wrote:Shenanigans are afoot- the construction time for a 2300-box CompoundBody should be around 2-6 milliseconds, not a minute.
Maybe I was doing something wrong, then, wouldn't be surprised. I'll look into that and StaticGroup and see what I can come up with! Come to think of it, it may have been the Select operation I was running on a 2600-object list.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Not sure how to improve performance

Post by snoozbuster »

I took a look into it and I had a pretty serious loop problem that resulted in me creating like 2000 CompoundBodies. After fixing that and getting rendering to work, it seems to work alright; unfortunately I can't see a significant performance boost, and raycasting doesn't work; I don't remember if I mentioned it but I use raycasting as part of my 3D grid-based editor and I was hoping that since CompoundBodies internally contain EntityCollidables the raycast would return the children and not the CompoundBody; this isn't the case. So even if there was a performance boost that's another problem I can't see a solution to.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Not sure how to improve performance

Post by Norbo »

unfortunately I can't see a significant performance boost
If it's still taking more than a handful of milliseconds, I recommend trying to reproduce the issue in the BEPUphysicsDemos to narrow it down.
I use raycasting as part of my 3D grid-based editor and I was hoping that since CompoundBodies internally contain EntityCollidables the raycast would return the children and not the CompoundBody
The contract of the Space.RayCast is to return the first space-held collidable as the hit object, but if you'd like to get the individual children, you can bypass Space.RayCast by using the BroadPhase.QueryAccelerator.RayCast (it is what the Space.RayCast uses internally to accelerate casts). It will return all collidables with bounding boxes intersected by the ray. You can then test each returned object yourself.

However, rather than using the same per-collidable test as the Space.RayCast, you can choose the test. For example, you could use the CompoundCollidable's other RayCast overloads which provide the hit child. The StaticGroupShape of the StaticGroup also offers similar functionality.

(There's also the option of using the result of Space.RayCast directly and doing the child-finding raycast. It will work, it just tests a ray against the object twice instead of once.)
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Not sure how to improve performance

Post by snoozbuster »

Norbo wrote:If it's still taking more than a handful of milliseconds, I recommend trying to reproduce the issue in the BEPUphysicsDemos to narrow it down.
Oh, no no, the creation is working fine; the runtime performance isn't noticeably faster. At one or two worlds (each the 32x32x8 grid mentioned) it's fine, but once you get to four or five and beyond it starts getting really choppy. The idea of the game is to have your own host world where you can build things and every few minutes it connects you to someone else's world so you can see what they've done, ideally with no limit, but if it keeps adding worlds and the framerate keeps dropping it gets hard to even build and interact with your world.

As for raycasting, that's good to know. I'll take a look into that.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Not sure how to improve performance

Post by snoozbuster »

I got raycasting working, but noticed a slightly different problem: I save the last support found by the support finder so that when the character falls off the edge of the world, I can take the position of that support and spawn the character above it. When the support is a CompoundBody, though, you get spawned in the center; which isn't awful, but it'd nice to be able to get it back to how it used it be if possible.

As for performance, I ran a profiler through my game and it looks like I'm hitting a rendering bottleneck now, which means I either get to figure out frustrum culling or instanced rendering, or both. If you're curious, Space.DoTimeStep() spends most of its time inside InternalNode.GetOverlaps() down through GetCollisionRule() and get_IsActive, but all those average 2ms or less so it's only through sheer volume. Even with a large number of worlds I only average 14ms/call to Space.Update(), which is acceptable (for now, at least :p).

EDIT: Got the respawning to work by saving SupportData.Position instead of the Collidable itself. Works great now!
Post Reply