2011-06-08 71 views
0

好吧,我知道這是一個非具體的問題,但我正在做一個類似於例如憤怒的小鳥遊戲verlet整合物理引擎。我正在寫一個練習引擎來獲得它的jist(爲更簡單的C++版本轉到Benedikt Bitterli),無論我做什麼,我都不知道如何實現摩擦。如果有人至少可以告訴我在哪裏或在哪種方法下我應該添加一些東西以及techneque或somthing的名稱,我會在下面發佈主要的碰撞和計算方法。摩擦物理引擎幫助

private void updateVerlet() { 
    float tempX; 
    float tempY; 

    for (int b = 0; b < bodies.size(); b++) { 
     for (int i = 0; i < bodies.get(b).vertices.size(); i++) { 
      Vertex v = bodies.get(b).vertices.get(i); 
      tempX = v.x; 
      tempY = v.y; 
      v.x += v.x - v.ox + v.accx * timestep * timestep; 
      v.y += v.y - v.oy + v.accy * timestep * timestep; 
      v.ox = tempX; 
      v.oy = tempY; 
     } 
    } 
} 



private void updateEdges() { 
    for (int b = 0; b < bodies.size(); b++) { 
     for (int i = 0; i < bodies.get(b).edges.size(); i++) { 
      Edge e = bodies.get(b).edges.get(i); 

      float distX = e.v2.x - e.v1.x; 
      float distY = e.v2.y - e.v1.y; 

      float dist = (float)Math.hypot(distX, distY); 
      float diff = dist - e.length; 

      float len = 1f/(float)Math.hypot(distX, distY);// Normalize with (float)Math.hypot(distX, distY); again???? 
      distX *= len; 
      distY *= len; 

      e.v1.x += distX * diff * 0.5; 
      e.v1.y += distY * diff * 0.5; 
      e.v2.x -= distX * diff * 0.5; 
      e.v2.y -= distY * diff * 0.5; 
     } 
    } 
} 
private void iterateCollisions() { 
    for (int iteration = 0; iteration < iterations; iteration++) { 

     // Temporary solution to prevent bodies from falling out of the screen 
     for (int b = 0; b < bodies.size(); b++) { 
      for (int i = 0; i < bodies.get(b).vertices.size(); i++) { 
       bodies.get(b).vertices.get(i).x = Math.max(Math.min(bodies.get(b).vertices.get(i).x, (float)screenWidth), 0.0f); 
       bodies.get(b).vertices.get(i).y = Math.max(Math.min(bodies.get(b).vertices.get(i).y, (float)screenHeight), 0.0f); 
      } 
     } 

     updateEdges(); 

     for (int b = 0; b < bodies.size(); b++) { 
      bodies.get(b).calculateCenter(); 
     } 

     for (int b1 = 0; b1 < bodies.size(); b1++) { 
      for (int b2 = 0; b2 < bodies.size(); b2++) { 
       if (bodies.get(b1) != bodies.get(b2)) { 
        if (bodiesOverlap(bodies.get(b1), bodies.get(b2))) { 
         if (detectCollision(bodies.get(b1), bodies.get(b2))) { 
          processCollision(); 
         } 
        } 
       } 
      } 
     } 

    } 
} 
private boolean bodiesOverlap(PhysicsBody b1, PhysicsBody b2) { 
    return 
    (b1.minX <= b2.maxX) && 
    (b1.minY <= b2.maxY) && 
    (b1.maxX >= b2.minX) && 
    (b2.maxY >= b1.minY); 
} 

private boolean detectCollision(PhysicsBody b1, PhysicsBody b2) { 
    float minDistance = 10000.0f; 
    Edge e; 

    for (int i = 0; i < b1.edges.size() + b2.edges.size(); i++) { 
     if (i < b1.edges.size()) { 
      e = b1.edges.get(i); 
     } else { 
      e= b2.edges.get(i - b1.edges.size()); 
     } 

     if (!e.boundary) 
      continue; 

     axis.x = e.v1.y - e.v2.y; 
     axis.y = e.v2.x - e.v1.x; 

     float len = 1f/(float)Math.hypot(axis.x, axis.y); 
     axis.x *= len; 
     axis.y *= len; 

     MinMax dataA = b1.projectToAxis(axis); 
     MinMax dataB = b2.projectToAxis(axis); 

     float distance = intervalDistance(dataA, dataB); 

     if (distance > 0f) 
      return false; 
     else if (Math.abs(distance) < minDistance) { 
      minDistance = Math.abs(distance); 

      CollisionInfo.normalX = axis.x; 
      CollisionInfo.normalY = axis.y; 
      CollisionInfo.e = e; 
     } 
    } 

    CollisionInfo.depth = minDistance; 

    if (CollisionInfo.e.parent != b2) { 
     PhysicsBody temp = b2; 
     b2 = b1; 
     b1 = temp; 
    } 

    float diffX = b1.centerX - b2.centerX; 
    float diffY = b1.centerY - b2.centerY; 
    float mult = CollisionInfo.normalX * diffX + CollisionInfo.normalY * diffY; 

    if (mult < 0) { 
     CollisionInfo.normalX = 0 - CollisionInfo.normalX; 
     CollisionInfo.normalY = 0 - CollisionInfo.normalY; 
    } 

    minDistance = 10000.0f; 

    for (int i = 0; i < b1.vertices.size(); i++) { 
     diffX = b1.vertices.get(i).x - b2.centerX; 
     diffY = b1.vertices.get(i).y - b2.centerY; 
     float distance = CollisionInfo.normalX * diffX + CollisionInfo.normalX * diffY; 

     if (distance < minDistance) { 
      minDistance = distance; 
      CollisionInfo.v = b1.vertices.get(i); 
     } 
    } 
    return true; 
} 

private void processCollision() { 
    Vertex v1 = CollisionInfo.e.v1; 
    Vertex v2 = CollisionInfo.e.v2; 

    float collisionVectorX = CollisionInfo.normalX * CollisionInfo.depth; 
    float collisionVectorY = CollisionInfo.normalY * CollisionInfo.depth; 

    float t; 
    if (Math.abs(v1.x - v2.x) > Math.abs(v1.y - v2.y)) { 
     t = (CollisionInfo.v.x - collisionVectorX - v1.x)/(v2.x - v1.x); 
    } 
    else { 
     t = (CollisionInfo.v.y - collisionVectorY - v1.y)/(v2.y - v1.y); 
    } 

    float lambda = 1.0f/(t * t + (1 - t) * (1 - t)); 
    float edgeMass = t * v2.parent.mass + (1f - t) * v1.parent.mass; 
    float invCollisionMass = 1.0f/(edgeMass + CollisionInfo.v.parent.mass); 

    float ratio1 = CollisionInfo.v.parent.mass * invCollisionMass; 
    float ratio2 = edgeMass*invCollisionMass; 

    v1.x -= collisionVectorX * ((1 - t) * ratio1 * lambda); 
    v1.y -= collisionVectorY * ((1 - t) * ratio1 * lambda); 
    v2.x -= collisionVectorX * (t * ratio1 * lambda); 
    v2.y -= collisionVectorY * (t * ratio1 * lambda); 

    CollisionInfo.v.x += collisionVectorX * ratio2; 
    CollisionInfo.v.y += collisionVectorY * ratio2; 
} 
+1

摩擦力只是作爲一種力量而建模。計算位置時,將摩擦矢量添加到您的加速度矢量中。 – Gabe 2011-06-08 01:48:59

+0

@gabe:我不需要空氣阻力,那很容易。我需要與其他物體摩擦。 – 2011-06-08 01:55:36

+0

我已經試過讀這個,但方程是非常複雜的,我只採取了新生代數到目前爲止 – 2011-06-08 01:59:43

回答

0

試試這個代碼,摩擦底世界的邊界 每一個粒子上,限制水平運動。

if(Particle.Y >= world_height) { Particle.OldX = Particle.OldX - (Particle.OldX - Particle.X)/2; }