D.V.D
Make a wish
- Reaction score
- 73
Hey guys I made a rigid body dynamics system but it suffers from major issues when theres more than 2 bodies colliding at once. The way it works is that it finds which objects are colliding with eachother and puts them into pairs. Each pair being 2 objects colliding with eachother but this doesn't seem to always work. When the three objects collide, they pass through eachother and the program starts to lag intensively because of calculations it does when objects are moving inside of eachother. I was wondering, since all my objects are boxes with a fixed radius, do I need to push the objects back a bit so that they aren't overlapping, and then do the momentum calculations? Whats the way of solving such a problem?
TestStack is a list of all the objects in my engine. TEST_COUNT is the number of objects in my engine. Ispointinbox is the function used to calculate if a point is in a box, I tested it around and it works since no rotation transformations are put on the box. If source code for this function is needed, Ill provide it.
This is the collision function. It works by saying that the object with the most momentum in a collision will lose momentum while the object with the least momentum gains momentum. This is described with the proportion variables. The debug function simply prints a variable.
TestStack is a list of all the objects in my engine. TEST_COUNT is the number of objects in my engine. Ispointinbox is the function used to calculate if a point is in a box, I tested it around and it works since no rotation transformations are put on the box. If source code for this function is needed, Ill provide it.
Code:
colstack CollisionStack;
void PhysicsPipeline::update () {
for ( int i=0; i < TEST_COUNT; i++ ) {
// Update position of boxes
TestStack[i].updatepos();
}
// For every object object in test count
for ( int i=0; i < TEST_COUNT; i++ ) {
// Check collision with every other object in collision
for ( int j=0; j < TEST_COUNT; j++ ) {
// If objects being checked aren't the same object
if ( j != i ) {
// Add to pair of collisions
CollisionStack.add(TestStack[i], TestStack[j]);
}
}
}
for ( int i=0; i < CollisionStack.current-1; i++ ) {
// Check for Collision of every vertice of the coliding boxe
bool hascollided = false;
if ( CollisionStack.pair1[i].BoundingBox.ispointinbox(CollisionStack.pair2[i].BoundingBox.NW) == true ) {
collide(0,1);
hascollided = true;
}
if ( CollisionStack.pair1[i].BoundingBox.ispointinbox(CollisionStack.pair2[i].BoundingBox.NE) == true && hascollided == false ) {
collide(0,1);
hascollided = true;
}
if ( CollisionStack.pair1[i].BoundingBox.ispointinbox(CollisionStack.pair2[i].BoundingBox.SW) == true && hascollided == false ) {
collide(0,1);
hascollided = true;
}
if ( CollisionStack.pair1[i].BoundingBox.ispointinbox(CollisionStack.pair2[i].BoundingBox.SE) == true && hascollided == false ) {
collide(0,1);
hascollided = true;
}
}
CollisionStack.clear();
}
This is the collision function. It works by saying that the object with the most momentum in a collision will lose momentum while the object with the least momentum gains momentum. This is described with the proportion variables. The debug function simply prints a variable.
Code:
inline void collide (int i, int j) {
//FIX LATER!!
//if ( deb == true ) {
Vector2f m1 = Vector2f(TestStack[i].mass * TestStack[i].vel.x, TestStack[i].mass * TestStack[i].vel.y);
Vector2f m2 = Vector2f(TestStack[j].mass * TestStack[j].vel.x, TestStack[j].mass * TestStack[j].vel.y);
cout << "m1: " << m1.x << ", " << m1.y << endl;
cout << "m2: " << m2.x << ", " << m2.y << endl;
double mag1 = sqrt( (m1.x*m1.x) + (m1.y*m1.y) );
double mag2 = sqrt( (m2.x*m2.x) + (m2.y*m2.y) );
debug("mag1",mag1);
debug("mag2",mag2);
double angle1 = radtodegree(atan(m1.y/m1.x));
double angle2 = radtodegree(atan(m2.y/m2.x));
if ( m1.x < 0 ) {
angle1 -= 180.0f;
}
if ( m2.x < 0 ) {
angle2 -= 180.0f;
}
debug("angle1",angle1);
debug("angle2",angle2);
double proportion1, proportion2;
if ( mag1 > mag2 ) {
proportion1 = mag2/mag1;
proportion2 = 1.0f - proportion2;
}
if ( mag1 < mag2 ) {
proportion2 = mag1/mag2;
proportion1 = 1.0f - proportion2;
}
if ( mag1 == mag2 ) {
proportion1 = 0.50f;
proportion2 = 0.50f;
}
debug("proportion1",proportion1);
debug("proportion2",proportion2);
double mag1t = mag1*proportion1;
double mag2t = mag2*proportion2;
debug("mag1t",mag1t);
debug("mag2t",mag2t);
mag1 -= mag1t;
mag2 -= mag2t;
mag1 += mag2t;
mag2 += mag1t;
debug("mag1",mag1);
debug("mag2",mag2);
debug("a1",degreetorad(angle1));
debug("a2",degreetorad(angle2));
debug("Angle1C",cos(degreetorad(angle1)));
debug("Angle1S",sin(degreetorad(angle1)));
debug("Angle2C",cos(degreetorad(angle2)));
debug("Angle2S",sin(degreetorad(angle2)));
TestStack[i].vel.x = mag1 * cos(degreetorad(angle1)) * -1.0f / TestStack[i].mass;
TestStack[i].vel.y = mag1 * sin(degreetorad(angle1)) * -1.0f / TestStack[i].mass;
TestStack[j].vel.x = mag2 * cos(degreetorad(angle2)) * -1.0f / TestStack[j].mass;
TestStack[j].vel.y = mag2 * sin(degreetorad(angle2)) * -1.0f / TestStack[j].mass;
cout << "Ivel: " << TestStack[i].vel.x << ", " << TestStack[i].vel.y << endl;
cout << "Jvel: " << TestStack[j].vel.x << ", " << TestStack[j].vel.y << endl;
deb = false;
//}
}