I'm getting an odd effect with my sphere-to-plane responses, which is driving me a little bit insane. I've got the equation
NewVelocity = oldVelocity - ( 2*energyCoefficient*planeNormal*( planeNormal.oldVelocity )
from quite a few sources, but the way I'm implementing it in the code must be wrong. I've been tinkering with it for hours upon hours, and I'm not getting anywhere. The only results I get are either sphere completely passing through the plane (i.e. newVelocity == oldVelocity), or the sphere reflecting up and backwards so that it winds up infinitely hopping back and forth between two spots on the plane (strangely, with this setup, fiddling with the energy coefficient has no effect whatsoever). I'm beginning to think the problem might be in my general structure. To wit, that's:
1. At the timestep, update spheres: a) iterate all spheres and apply gravity b) iterate all spheres and process collisions with each sphere: 1. iterate all planes, detect collisions, respond 2. iterate all spheres, detect collisions, respond c) iterate all spheres and update position
In a couple of places I've seen it recommended to detect collisions, store collision info in a separate container, and process responses after all collision information is detected. Is this my problem? But it behaves the same way whether there's 1 or hundreds of spheres going!
Here's the code that elicits the strange hopping behavior. Please forgive the bad syntax. My Vector3d class operator overloads don't seem to work when I combine expressions (can you tell I'm a noob?).
void sphereToPlaneCollisions( PhysObj& b ){ for( planeIter pi = allPlanes.begin(); pi != allPlanes.end(); ++pi ) if( sphereToPlaneCollision( b, **pi ) ) { b.pos = b.lastPos; b.vel = b.lastVel; b.lastVel = b.vel; double speed = b.vel.length(); b.vel.normalize(); // double energyCoefficient = 0.1; Vector3d n = (*pi)->getUnitNorm(); Vector3d newVel( b.vel ); b.vel *= -1.0; double nDotV = n.dot( b.vel ); n *= nDotV; newVel += n; newVel.normalize(); // newVel *= speed; // newVel *= ( 1 + energyCoefficient ); b.vel = newVel; }}
Thanks for your guidance.
EDIT: By the way, I've tested that the plane normal is being calculated properly.