Well, I finally put the capsule code in. It was quite a struggle, due to the messiness of the physics code, which has gone through more revisions than I care to remember. First, I had to rid myself of ellipsoids ( which worked ok until you want to do ellipsoid vs ellipsoid collision ), and go back to spheres. Once I got that rolling ( again - I had spheres working ages ago ), then I switched to capsules. After many stupid mistakes ( forgetting to sort my contacts, etc. ) and many times falling through the floor, it now works great for both capsule->world and capsule->capsule.
Convex Rigid Bodies with No Stacking
This project has been my first real taste of 3d physics. I have done some physics-like things before, like collision avoidance using steering ( on Star Wars : Rebellion ), and I did some rather interesting physics for our puzzle game Hubie in 1995 or so.
Hubie was an interesting case, because it was a 2d side-view board filled with many physically reactive objects, such as springs, moving walkways, balloons, fans, magnets, and of course, the character Hubie himself.
In general, I would move objects by just going through the board from left to right, top to bottom, and if I found an object there, check the tile where it wants to go to see if it could move or not, and if so, move it.
Of course, there were plenty of exceptions.
One example was the balloons. The way they worked was that one balloon could support one movable object in mid-air. Two or more balloons would cause the object & the balloons to rise in unison. Similarly, more objects than balloons caused the whole thing to drop in unison. To do this, I did what is now called Shock Propogation. I basically sorted the objects by going through them from top to bottom in the rising case, or bottom to top in the falling case.
I was reminded of the stacking trick while I re-read the physics paper Non-Convex Rigid Bodies with Stacking. Now, I don't want to have nearly the complexity of physics that they talk about in that paper, but they do present a good way to handle collisions vs contacts.
This is something that right now is quite a muddle in my current engine. Here is what I do now for sentient objects :
1. Remove object from the physics scene ( to prevent self-collision )
2. Check below the object for a floor (defined by some triangle near his feet facing roughly up )
3. If there is floor, then make his coefficient of restitution 0 ( he doesn't bounce )
4. Also if there is a floor, don't apply gravity ( saves a bit of cpu and prevents the dude from sliding down ramps )
5. If there is a floor, make his velocity match his desired velocity ( like if he's walking or running )
6. Move the char's capsule to the new position
7. Check for interference with other capsules ( and if so, cancel velocity in direction one capsule, and the opposite direction for the other capsule ) - no momentum transfer
8. Check for interference with static world triangles
....a) get all contacts in an area slightly bigger than the actual capsule
....b) sort the contacts by deepest to shallowest
....c) go through potentially contacting triangles in this order, and move capsule out of collision, and adjust velocity
....d) repeat for other tris, using the new position each time. Some contacts won't be contacts any more after step c.
9. Replace object in the physics scene at new position
10. Repeat for next object
For physical objects, like non-sentient things, or guys falling, they undergo a bit of bouncing & friction.
One of the problems with my current approach is that a guy walking down a ramp has gravity turned on and off by
the CheckForFloor() funciton, which serves as a weak sort of contact detection. This causes the dude to start walking,
then be off the ground and start falling, interrupting his animation.
Ok, after writing this paragraph, I just made a slight fix that makes this go away. Basically what I just changed is that I still do CheckForFloor(), to see if the guy is capable of walking or not.
But, if he is on the floor, I only update his horizontal x & z velocity, not the vertical y velocity. I also never turn off gravity. That way, gravity is always pulling him into the floor, which gets properly resolved by the triangle collision.
This makes him properly walk down a ramp. Here is a shot of him doing exactly that :
A better way of handling being on the floor might be to just give the guy horizontal friction that applies to any external force acting on him. Like if a strong wind were blowing on him, but he is on the floor and conscious, the idea is that he could move his feet or lean in such a way that he would not be blown away.
The Non-Convex Rigid Bodies paper talks about doing object physics in a different order :
1) Resolve collisions by using the current velocity, temporarily moving the objects to their new position, and checking for interference
2) Make a new velocity based on any collisions
3) Update new velocity with forces, like gravity
4) Now detect contacts by temporarily moving the object under the new velocity, and finding interference
5) Move object out of penetrations
I like the idea of treating contacts separately, and I think I will need to change to something like this in the future. Especially for character control. For instance, you can do things like detect small ledges the character is touching, and give him a little boost up onto the ledge or large stair.