2013-04-05 23 views
2

这里是一个short video,其中可以看到两个(也许更多)粒子组相互间发生故障。如何在弹性粒子碰撞模拟器中避免粒子一起抖动?

源代码可以在​​找到。

这是我用计算碰撞代码:

function collisionPhysics() 
{ 
    for (var i = 0; i < N - 1; ++i) 
    { 
     for (var j = i + 1; j < N; ++j) 
     { 
      var Dx = objects[j].x - objects[i].x; // Difference in X direction between objects[i] and objects[j]. 
      var Dy = objects[j].y - objects[i].y; // Difference in Y direction between objects[i] and objects[j]. 
      var D2 = Dx * Dx + Dy * Dy;    // Distance between objects[i] and objects[j] squared. 

      if (D2 <= (objects[i].rad + objects[j].rad) * (objects[i].rad + objects[j].rad)) // Colision check could be inserted here, reusing D2. 
      { 
       var delta = 2 * (Dx * (objects[i].Vx - objects[j].Vx) + Dy * (objects[i].Vy - objects[j].Vy))/(D2 * (objects[i].m + objects[j].m)); 
       objects[i].Vx += -objects[i].m * delta * Dx; 
       objects[i].Vy += -objects[i].m * delta * Dy; 
       objects[j].Vx += objects[j].m * delta * Dx; 
       objects[j].Vy += objects[j].m * delta * Dy; 
      } 
     } 
    } 
} 

编辑2013年4月6日: nwellcome提到的问题是造成奇怪的行为。而这个调整的功能应该解决这个问题,不知道这是否可以提高性能,明智的,但它的工作原理:

function collisionPhysics() 
{ 
    for (var i = 0; i < N - 1; ++i) 
    { 
     for (var j = i + 1; j < N; ++j) 
     { 
      var Dx = objects[j].x - objects[i].x + timeStep * (objects[j].u - objects[i].u); 
      var Dy = objects[j].y - objects[i].y + timeStep * (objects[j].v - objects[i].v); 
      var D2 = Dx * Dx + Dy * Dy;    // Distance between objects[i] and objects[j] squared. 

      if (D2 <= (objects[i].r + objects[j].r) * (objects[i].r + objects[j].r)) // Colision check could be inserted here, reusing D2. 
      { 
       objects[i].col = true; 
       objects[j].col = true; 
       var dx = objects[j].x - objects[i].x; 
       var dy = objects[j].y - objects[i].y; 
       var du = objects[j].u - objects[i].u; 
       var dv = objects[j].v - objects[i].v; 
       var dr = objects[j].r + objects[i].r; 
       var dt = (-Math.sqrt(2 * dx * du * dy * dv - du * du * (dy * dy - dr * dr) - dv * dv * (dx * dx - dr * dr)) - dx * du - dy * dv)/(du * du + dv * dv); 
       Dx = objects[j].x - objects[i].x + dt * (objects[j].u - objects[i].u); 
       Dy = objects[j].y - objects[i].y + dt * (objects[j].v - objects[i].v); 
       D2 = Dx * Dx + Dy * Dy; 
       var delta = 2 * (Dx * (objects[i].u - objects[j].u) + Dy * (objects[i].v - objects[j].v))/(D2 * (objects[i].m + objects[j].m)); 
       objects[i].u += -objects[i].m * delta * Dx; 
       objects[i].v += -objects[i].m * delta * Dy; 
       objects[j].u += objects[j].m * delta * Dx; 
       objects[j].v += objects[j].m * delta * Dy; 
       objects[i].x += (timeStep - dt) * objects[i].u; 
       objects[i].y += (timeStep - dt) * objects[i].v; 
       objects[j].x += (timeStep - dt) * objects[j].u; 
       objects[j].y += (timeStep - dt) * objects[j].v; 
      } 
     } 
    } 
} 

回答

0

的问题是你的冲突解决的方法并不能确保颗粒不会仍然相交于下一帧的开始。

当您发现碰撞时,您需要回到粒子边界发生碰撞并解决碰撞的时间点。对于这样做的方法,请参阅this game development answer

+0

这确实是造成这个问题,做了一点数学后,我得到了一个工作对撞机。当粒子同时碰撞两个粒子时,它似乎也能正常工作。谢谢,这实际上是一个非常合理的方法,不知道为什么我以前没有想到这一点。 – fibonatic 2013-04-06 00:09:45