PDA

View Full Version : Dynamo collision constraint problems?



Aggrav8d
10-16-2004, 02:25 PM
Situation: I have two circles of equal size and mass moving towards each other. They are offset such that when they collide they just barely graze each other. Arbitrary angular velocities.

Problem: They do not bounce off of each other and lose their angular velocity. They become stuck together and begin orbiting around each other, faster and faster, until they "blow apart". When that happens all collisions every cease to function - everything just flies through everything else.

Question: Why does this happen? What do i do about it? I suspect that my normal calculation is wrong, somehow.

Hacked together test case:

I am using RK2 integration with a constraint manager max_error of 0.0001 and a step size of 1/30s.
both radius=10
both mass=1
both inertia tensor=(1,1,1)
p1(-20,-10,0)
p2(20,9.078786,0) //9.078785 does not get stuck
v1(5,0,0)
v2(-5,0,0)

I wrote the following code to override DL_dyna_system_callbacks::do_collision_detection() . I hope the error is not in there but I have included it to be thorough.

int i,j;
for(i=0;i<entities.size();++i) {
DynamicPhysicsEntity *dpe=(DynamicPhysicsEntity *)entities[i];
DL_vector *v=dpe->companion->get_velocity();

// test against other objects
for(j=i+1;j<entities.size();++j) {
DynamicPhysicsEntity *dpe2=(DynamicPhysicsEntity *)entities[j];
// bbox test
float r2(dpe->radius+dpe2->radius);
float dx(dpe2->pos.x-dpe->pos.x);
if(fabs(dx)>r2)
continue;
float dy(dpe2->pos.y-dpe->pos.y);
if(fabs(dy)>r2)
continue;
// circle test
float d2(dx*dx+dy*dy);
if(d2<=r2*r2) {
// close enough together
//DL_vector*v2=dpe2->companion->get_velocity();
//if(v->inprod(v2)<0)
{
// moving into each other
float denom(dpe->radius/r2);
n.init(dx,dy,0);
float len(n.norm());
n.timesis(1.0f/len);
// (len/r2) was to try and get the point in the center of the
// overlapping area of the two circles. it can be removed and
// there will be no change.
p2.init((dx*denom)*(len/r2)+dpe->pos.x,
(dy*denom)*(len/r2)+dpe->pos.y,
0);
dpe->companion->to_local(&p2,NULL,&p0);
dpe2->companion->to_local(&p2,NULL,&p1);
// changing the 2 to a 1 will make no difference, either.
new DL_collision(dpe->companion,&p0,dpe2->companion,&p1,&n,2);
}
}
}
}

NuriumGames
10-17-2004, 12:02 AM
Hi Aggrav8d.

Some things. Tensor is too low. For objects of mass 1 with a radi of 10, a normal tensor would be between 200 (200, 200, 200) and 1000, or the object would rotate too easily. Bigger mass or radi implies bigger tensor.

Collision points must be on the object surface, ie collision point for object A must be at object A surface, same for B.

In BreakQuest, I'm using an integration step of 3ms (yes 333 integrations per sec) and max speed should be around 2 (2 pixels/integration) to avoid problems.

Here you have my circle-circle collision code:



// cs_circleShape +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// If we are here, interference in this frame is guaranteed
TCollisionInfo cs_circleShape::collideX(cs_circleShape* target) {

ut_point selfCm = ba->dy->getNextPos();
ut_point targetCm = target->ba->dy->getNextPos();
// Next frame distance (squared)
double x = targetCm.x - selfCm.x;
x *= x;
double y =targetCm.y - selfCm.y;
y *= y;
double nextDist = x+y;

// Current distance (squared too)
//selfCm = ba->companion->get_position();
//targetCm = target->ba->companion->get_position();
selfCm = ba->dy->getPos();
targetCm = target->ba->dy->getPos();
x = targetCm.x - selfCm.x;
x *= x;
y = targetCm.y - selfCm.y;
y *= y;

// if we are not approaching (x+y is lastDistance), no collision
if( nextDist >= x+y ) return TCollisionInfo();

DL_vector normal(targetCm.x - selfCm.x, targetCm.y - selfCm.y, 0);
normal.normalize();

// objectA* objectB* shapeA* shapeB(sb)* pointA(pa) pointB(pb) normal(no)
return TCollisionInfo(
ownedBy, target->ownedBy, this->ba, target->ba,
DL_point(selfCm.x + normal.x * ba->r, selfCm.y + normal.y * ba->r, 0),
DL_point(targetCm.x + normal.x * -target->ba->r, targetCm.y + normal.y * -target->ba->r, 0),
normal );
}


> // changing the 2 to a 1 will make no difference, either.
> new DL_collision(dpe->companion,&p0,dpe2->companion,&p1,&n,2);

Last parameter is boolean, 0 means hard collision, 1 is soft. In BreakQuest all collisions are soft (1) except for paddle/ball and all collisions with filed walls.

Hope it helps, and take it easy.

Aggrav8d
10-20-2004, 12:13 AM
Thanks, Felix, it was a big help. I was doing a test using velocity, it took a few minutes before I realized why your method works better. Very clever!
One more question: I can't get the Connector constraint or the Orientation Constraint to work right. I create three Connectors and I get the following errors:

Warning: initially invalid orientation constraint
Error: (-0.000000,0.000000,0.000000)
Warning: initially invalid orientation constraint
Error: (0.000000,-0.000000,-0.000000)
Warning: initially invalid orientation constraint
Error: (0.000000,0.000000,-0.000000)

the dynas and the geos they are attached to have identical positions and orientation matrixes. I initialize the connector like this:


DL_point a(0,0,0), b(1,0,0), c(0,1,0);
connector->init(d1->companion,&a,&b,&c);
connector->init(d2->companion,&a,&b,&c);

I have to admit I can't even make sense of the instructions for the orientation constraint, the wording is so ambiguous! If you have succeeded in making either of these two constraints work, please let me know! I believe they are the reason for a number of "singularity" errors.

Thanks!

Aggrav8d
10-20-2004, 10:27 AM
never mind, i found the problem somewhere else .... :P

NuriumGames
10-20-2004, 02:40 PM
> never mind, i found the problem somewhere else .... :P

This may help you anyway :)

Never used any of these, and probably you don't need them.

For example look at this image:
http://www.nurium.com/nnu/dynaEx.gif

The left one seems to be made of 5 objects with their corresponding constraints, but there is only 1 dyna and just one PTP constraint to hold it from the center to allow rotation. Every shape has his own game object and can receive hits and so, but all use the same dyna.

In the right one happens the same (red stripes), only one dyna but two displaced shapes, so they are allways exactly at 180ยบ from each other.

This way is more stable, and less computations are done.

Aggrav8d
10-20-2004, 04:08 PM
Doesn't there also have to be a geo to attach the PTP? I tried using the PTP to attach a dyna to a point in the world and it...it did not like that.

I am still trying to get connection and orientation constraints to work correctly. I have not been able to make the dyna system like their initial states.

I am very impressed with your collision detection! I can barely get plane/circle/triangle/rectangle interactions working. What's your secret?

NuriumGames
10-21-2004, 03:02 AM
Sure, there is also a geo. I have a fixed one where I attach these kind of things.

Never used an orientation constraint, I think i tried once or twice and did not succeed.

Collision detection has been quite hard, you will need some 'advanced' geometry, there is no secret, is just lots of work and fine tuning. I had a big list of links related to it, but sadly enough lost it (among some weeks worth of work) thanks to a HD failure.

I filled lots of papers with numbers and made a lot work with the collision system, do not expect it to be easy, it is not.