Dynamo collision constraint problems?

Discussion in 'Game Development (Technical)' started by Aggrav8d, Oct 16, 2004.

  1. Aggrav8d

    Original Member

    Joined:
    Sep 20, 2004
    Messages:
    31
    Likes Received:
    0
    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.
    Code:
      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);
            }
          }
        }
      }
    
     
  2. NuriumGames

    Original Member

    Joined:
    Aug 6, 2004
    Messages:
    201
    Likes Received:
    0
    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:

    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.
     
  3. Aggrav8d

    Original Member

    Joined:
    Sep 20, 2004
    Messages:
    31
    Likes Received:
    0
    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:

    Code:
    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!
     
  4. Aggrav8d

    Original Member

    Joined:
    Sep 20, 2004
    Messages:
    31
    Likes Received:
    0
    never mind, i found the problem somewhere else .... :p
     
  5. NuriumGames

    Original Member

    Joined:
    Aug 6, 2004
    Messages:
    201
    Likes Received:
    0
    > 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.
     
  6. Aggrav8d

    Original Member

    Joined:
    Sep 20, 2004
    Messages:
    31
    Likes Received:
    0
    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?
     
  7. NuriumGames

    Original Member

    Joined:
    Aug 6, 2004
    Messages:
    201
    Likes Received:
    0
    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.
     

Share This Page

  • About Indie Gamer

    When the original Dexterity Forums closed in 2004, Indie Gamer was born and a diverse community has grown out of a passion for creating great games. Here you will find over 10 years of in-depth discussion on game design, the business of game development, and marketing/sales. Indie Gamer also provides a friendly place to meet up with other Developers, Artists, Composers and Writers.
  • Buy us a beer!

    Indie Gamer is delicately held together by a single poor bastard who thankfully gets help from various community volunteers. If you frequent this site or have found value in something you've learned here, help keep the site running by donating a few dollars (for beer of course)!

    Sure, I'll Buy You a Beer