PhysX tip: solver (position) iteration count / creating constraints N times
January 17th, 2017
The torus in this video is made of several rigid convex objects connected by fixed joints. Since the joints are fixed, the ideal behavior would be that each torus acts like a rigid compound object (with no deformation). With iterative / approximate solvers however, what you get is that the torus appears quite flexible, and it deforms like a soft body. Sometimes that’s the effect you want to achieve. Sometimes not.
If it’s not, there are two ways to improve this, as demonstrated in the video.
The first way is to increase the number of position iterations in the solver. This is done by calling PxRigidDynamic::setSolverIterationCounts(), with a higher ‘minPositionIters‘ value. The default is 4 iterations, which is usually enough for regular rigid bodies, but often insufficient for jointed systems. As you can see in the video, increasing the number of iterations makes the torus much more rigid. This is a relatively cheap solution, since each iteration is quite fast in PhysX. For example even with 32 iterations as in the video, PhysX remains faster than some other engines which, while providing a more rigid behavior by default, are still slower overall. That is, 32 iterations in PhysX can be faster than 4 iterations in other engines, for roughly the same torus rigidity.
However, increasing the number of iterations affects the performance of the whole ’simulation island’ that the object ends up a part of. Thus, the actual cost can be a bit unpredictable.
There is then a second way to increase the rigidity of the torus: just create the same constraints (i.e. the same joints) multiple times. This is pretty much equivalent to increasing the iteration counts, but the cost remains local to the object. In isolation this is more expensive than the first solution, because the joints’ setup code is performed multiple times now. But it can be a faster approach overall, in the context of a full game.
And then you can of course do both: create the constraints multiple times and also increase the solver iteration counts.
Now, this alternative approach has some issues that should be mentioned. First, for obvious reasons creating the constraints multiple times will use more memory. And second, the effect will depend on the order in which the constraints are created. For example say you have constraints 1 to N, and you want to create them 4 times. If you create them from 1 to N and repeat the sequence from scratch 4 times, it will work better than creating 4 times the same constraint before switching to the next. In other words, 1234..N1234..N1234..N1234..N is better than 1111222233334444..NNNN. This is semi-obvious but worth pointing out. For the same reason, this trick does not work equally well in all physics engines: some of them reorder constraints in arbitrary ways, etc. You can use PEEL 1.1 to check and explore how different engines react to this approach.