Measuring performance of rigid body simulation is important. But the dark secret of game physics, if you ask me, is that it is not actually the most important part. The most important and far more useful features for a game are simple collision queries like raycasts and sweeps. So let’s see what we get here.
There’s really an army of tests that one could create here, to stress and benchmark various parts of the system. For example for raycasts, like for contact generation, you usually have a choice between using a generic piece of code to implement all your raycasts (e.g. GJK), or you bite the bullet and implement a dedicated raycast function for each shape (e.g. ray-vs-box, ray-vs-sphere, etc). If you do so, one of these functions may be particularly slow compared to the others, e.g. ray-vs-convex-mesh, and thus you’d need a dedicated test scene to discover this.
PEEL does contain a test scene for each case. But I am not going to report all of them here, since at the end of the day they’re mostly saying the same thing. The following, thus, is only a selected subset of the tests implemented in PEEL.
The first scene (“SceneRaycastVsStaticSpheres”) is as simple as it gets. There’s a bunch of static spheres and we do a raycast against each of them, via the scene-level API. This is important: most physics engines also allow you do raycast directly against the shape itself (bypassing the scene level). But we are interested in the generic raycast performance here, and a large part of that is related to traversing the scene-level structures. Hence, we use the scene/world-level API in all the following tests. (This also means that various local acceleration structures like phantoms in Havok or volume-caches in PhysX are ignored here. We could run some other tests some other day for those things).
In the collision-queries tests I excluded the second PhysX 3.3 build using PCM, since PCM has no impact at all on any of these queries.
Anyway, without further ado, here’s what we get:
The profile graphes in these tests is often very flat, since the rays are not moving, the scene is static, and thus we do exactly the same work each frame.
As usual the main thing we want to check is that each PhysX version is faster than the previous version. This is clearly the case here, good.
Bullet appears to be significantly slower (up to 3X slower than PhysX 3.3), even on this simple test.
The second scene (“SceneRaycastVsDynamicSpheres”) is exactly the same, but we made all the spheres dynamic objects (and thus they are now falling under gravity). This is just to check whether this makes any difference in terms of performance. Turns out it does not, numbers are pretty much the same as before. This is why we will not bother with dynamic objects anymore in subsequent tests.
Replacing the spheres with boxes or capsules gives similar results (Bullet < 2.8.4 < 3.2 < 3.3). However things change when replacing the spheres with convexes, as seen in our next scene (“SceneRaycastVsStaticConvexes”).
As I was just saying before, a dedicated ray-vs-convex raycast function might be slower than the other ones, and this is what we see here.
Each PhysX version is faster than the one before, that’s good.
Contrary to what happened for the other shapes, Bullet is faster than 2.8.4 in this case. It remains significantly slower than PhysX 3.x though.
The next scene (“PotPourri_StaticRaycasts2”) creates a whole bunch of random shapes (spheres/boxes/capsules) at random positions in a cubic volume of space, and creates 20000 random raycasts in that space. The resulting screenshot admittedly looks like a giant exploding mess:
An interesting thing to note is that each library returns a different number of hits. This has to do with a number of things. First there is how each of them treats raycasts whose origin lies inside a shape. Some libraries like Havok do not count this as a hit, for example. Others may not give unified results in this case, i.e. maybe a ray starting inside a box gives a hit, but a ray starting inside a sphere does not. I did not investigate the details of it, but we clarified and unified all of these rules in PhysX 3.3.
Another thing that may contribute to the different number of hits is just FPU accuracy and what happens in limit cases. If the ray just ends on the surface of the shape, or if it just touches an AABB from the scene’s AABB-tree, this can be seen as a hit, or not. Using SIMD or not can also make a difference in these limit cases. Etc. In any case the results are approximately the same, and one could verify that they are indeed all “correct”.
Anyway, each PhysX version is faster than the one before – checked. PhysX 3.3 is about 2X faster than 2.8.4.
Bullet is again significantly slower, about 5X slower than 3.3.