There are still two "big" problems with my physics that I think I'm going to have to address before I can get back to working on physics-based movement...1. Stuff going through other stuff, and contact between objects not being stable
I've tried turning the number of iterations the constraints solver does up from 15 to 200... that seems to fix the problem, but it also makes the game unacceptably slow. Somehow I need to achieve the effect of 200 iterations, while only using the processing time of 15 iterations
The current setup is basically just a for loop iterating for MAX_CONSTRAINT_SOLVER_ITERATIONS
around a for loop iterating through the list of constraints. It's "dumb" but has zero overhead.
In the past I tried a "smart" system where I broke the constraint graph into isolated subgraphs (caveat: constraint edges to immobile objects don't count for merging subgraphs), and then tracked which edges were "awake" due to an applied impulse at an adjacent edge during the previous iteration. That method had some initial setup overhead (I don't know how bad), and some overhead per constraint evaluated, but the benefit is that it let me skip evaluating some constraints which would end up doing nothing when I evaluated them. Also the results might be less consistent than the current setup, since constraints wouldn't always execute in the same order.
When I was trying to do stuff on the GPU I had another setup where I broke the constraint graph into batches with no adjacent edges. But that turned out slower than the pure-CPU implementation! I've tried a multi-threaded CPU implementation with this sort of batching as well, and it didn't seem to help much. This setup is also "dumb" in that it evaluates all the constraints, every iteration. I probably could've found edges which were completely isolated and made them only evaluate once, but beyond that I don't know if it would be possible to make this scheme do "smart" evaluation like what I mentioned in the isolated-subgraphs scheme.
What to do?2. Contact regions that aren't just "points"
E.g. if I have a box resting on a slightly sloped surface, the entire bottom surface of the box will be in contact with the surface, and thus an "inward" velocity at any of the edges will be counteracted by the normal force / restitution / whatever we're calling it these days. A sphere, on the other hand, would only have a single point in contact with the surface, and thus would roll down the slope. But in my physics engine, if I only create a single contact point at the center of the box's bottom face, it will try to roll like a ball anyway... but unlike a ball, a box has a bigger radius at its corners than in the center of its faces, so it'll end up sinking into the slope as it tries to roll.
Currently I can
have multiple contact points between a pair of objects, and it does what I want... but each one is an additional constraint for the constraint solver to process, and even with a lot of iterations of the constraint solver I need an "adhesion" threshold to keep the impulses at one corner from lifting another corner out of the ground. Also right now I don't have my collision detection set up to generate multiple contact points, except for collisions between multispheres and infinite planes, e.g. the ground plane I sometimes use to test physics with, which won't actually be used in the game anyway
I can probably modify my existing collision detection to produce multiple contact points for multisphere-multisphere and multisphere-triangle (of triangle mesh) collisions easily enough.
I'm thinking maybe I should change how ContactPoint
works, so that instead of having a bunch of ContactPoint
constraints between a pair of objects that has a non-pointlike region of contact, I would have a single constraint object that contains the shape data for the region (information which the current setup represents as a list of multiple ContactPoint
constraints). What do you guys think?