• Create Account

### #ActualD.V.D

Posted 15 January 2013 - 06:48 PM

EDIT 2: 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.

struct colstack {

int current;

object pair1 [MAX_OBJ_COUNT*MAX_OBJ_COUNT];
object pair2 [MAX_OBJ_COUNT*MAX_OBJ_COUNT];

colstack () {
current = 0;
}

void add (object _o1, object _o2) {
pair1[current] = _o1;
pair2[current] = _o2;
current++;
}

void clear () {
current = 0;
}

};

colstack CollisionStack;

void PhysicsPipeline::update () {
for ( int i=0; i < TEST_COUNT; i++ ) {
// Update position of boxes
//cout << "UPDATE" << endl;
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
}
}
}
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.

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);

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);

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;
//}
}

### #4D.V.D

Posted 15 January 2013 - 06:47 PM

EDIT 2: 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.

struct colstack {

int current;

object pair1 [MAX_OBJ_COUNT*MAX_OBJ_COUNT];
object pair2 [MAX_OBJ_COUNT*MAX_OBJ_COUNT];

colstack () {
current = 0;
}

void add (object _o1, object _o2) {
pair1[current] = _o1;
pair2[current] = _o2;
current++;
}

void clear () {
current = 0;
}

};

colstack CollisionStack;

void PhysicsPipeline::update () {
for ( int i=0; i < TEST_COUNT; i++ ) {
// Update position of boxes
//cout << "UPDATE" << endl;
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
}
}
}
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();
}

### #3D.V.D

Posted 15 January 2013 - 06:45 PM

EDIT 2: 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?

### #2D.V.D

Posted 15 January 2013 - 06:35 PM

I have created a rigid body simulator which is pretty much just a bunch of boxes bouncing around your screen on a 2D plane. I have map coordinates given and whenever one of the components of the position vector go past this map, I simply invert the velocity of that component (ie. if pos.x is out of the map, set vel.x *= -1.0f; ). This works great except for corners which it should still work for, in theory. When running my program, it seems it cannot invert more than one component of velocity per check even if two are required to be inverted. Im not sure at all to why this is, but this is where the inversion is completed:

void object::updatepos () {
pos.x += vel.x;
pos.y += vel.y;
if ( pos.x > MAP_X ) {
vel.x *= -1.0f;
cout << "X value is outside the map" << endl;
return;
}
if ( pos.y > MAP_Y ) {
vel.y *= -1.0f;
cout << "Y value is outside the map" << endl;
return;
}
if ( pos.x < 0 ) {
vel.x *= -1.0f;
return;
}
if ( pos.y < 0 ) {
vel.y *= -1.0f;
return;
}
BoundingBox.NW = Vector2f( pos.x - Box_Constant, pos.y + Box_Constant );
BoundingBox.NE = Vector2f( pos.x + Box_Constant, pos.y + Box_Constant );
BoundingBox.SW = Vector2f( pos.x - Box_Constant, pos.y - Box_Constant );
BoundingBox.SE = Vector2f( pos.x + Box_Constant, pos.y - Box_Constant );
}

The Bounding Box part simply updates the boxes vertices to still follow this point as its centre. Whats interesting is the specific problem Im having, my y velocity is equal to 1.2 and the y position is equal to 99.2. The next check, the x position and y position both go outside of the map with the y position at 100.4 but only the x component of the velocity gets inverted. The y component doesn't get inverted till the next call and by that time the object's y position is 101.6 which is to far in to reverse. Does anyone have any idea as to why only one component gets inverted per call rather than both if needed?

### #1D.V.D

Posted 15 January 2013 - 06:34 PM

I have created a rigid body simulator which is pretty much just a bunch of boxes bouncing around your screen on a 2D plane. I have map coordinates given and whenever one of the components of the position vector go past this map, I simply invert the velocity of that component (ie. if pos.x is out of the map, set vel.x *= -1.0f; ). This works great except for corners which it should still work for, in theory. When running my program, it seems it cannot invert more than one component of velocity per check even if two are required to be inverted. Im not sure at all to why this is, but this is where the inversion is completed:

void object::updatepos () {
pos.x += vel.x;
pos.y += vel.y;
if ( pos.x > MAP_X ) {
vel.x *= -1.0f;
cout << "X value is outside the map" << endl;
return;
}
if ( pos.y > MAP_Y ) {
vel.y *= -1.0f;
cout << "Y value is outside the map" << endl;
return;
}
if ( pos.x > MAP_X && pos.y > MAP_Y ) {
vel.x *= -1.0f;
vel.y *= -1.0f;
}
if ( pos.x < 0 ) {
vel.x *= -1.0f;
return;
}
if ( pos.y < 0 ) {
vel.y *= -1.0f;
return;
}
BoundingBox.NW = Vector2f( pos.x - Box_Constant, pos.y + Box_Constant );
BoundingBox.NE = Vector2f( pos.x + Box_Constant, pos.y + Box_Constant );
BoundingBox.SW = Vector2f( pos.x - Box_Constant, pos.y - Box_Constant );
BoundingBox.SE = Vector2f( pos.x + Box_Constant, pos.y - Box_Constant );
}

The Bounding Box part simply updates the boxes vertices to still follow this point as its centre. Whats interesting is the specific problem Im having, my y velocity is equal to 1.2 and the y position is equal to 99.2. The next check, the x position and y position both go outside of the map with the y position at 100.4 but only the x component of the velocity gets inverted. The y component doesn't get inverted till the next call and by that time the object's y position is 101.6 which is to far in to reverse. Does anyone have any idea as to why only one component gets inverted per call rather than both if needed?

PARTNERS