JavaScript - 分离轴定理 - 碰撞工作,但没有响应?

sup*_*per 13 javascript physics vector collision

所以,我正在尝试对我的SAT,Circle - Poly,Poly - Poly碰撞应用响应.我将这篇文章的代码移植到JavaScript:

http://rocketmandevelopment.com/blog/separation-of-axis-theorem-for-collision-detection/

现在,检测适用于所有类型,但响应失败并且以疯狂的速度和错误的角度,它不依赖于物体的质量(区域^ 2而不是质量)并且未应用角速度

JSFiddle(重力不适用于模拟,使用箭头键移动),JS的第一部分是Vectors,然后是Physics,然后是Main.

这是我对形状的定义:(必须为"JSFiddle"链接添加一些代码:P)

var Circle = function(body, c, r, cor, cof) {
    this.body = body // Static or dynamic
    this.c = c; // Center
    this.r = r; // Radius
    this.m = getCMass(r); // Mass = Area
    this.v = new Vector(); // Velocity
    this.cor = cor; // Coefficient of restitution
    this.cof = cof; // Coefficient of friction
    this.a = 0; // Angle
    this.av = 0; // Angular velocity
    this.type = "Circle";
}

var Polygon = function(body, c, vs, cor, cof) {
    this.body = body // Static or dynamic
    this.c = c; // Center
    this.vs = vs; // Vertices
    this.m = getPMass(vs); // Mass = Area
    this.v = new Vector(); // Velocity
    this.cor = cor; // Coefficient of restitution
    this.cof = cof; // Coefficient of friction
    this.a = 0; // Angle
    this.av = 0; // Angular velocity
    this.type = "Polygon";
}

function getCMass(r) { // More like, getCArea
    return (r * r * Math.PI);
}

function getPMass(vs) {
    var area = 0;
    var j = vs.length - 1;

    for (var i = 0; i < vs.length; i++) {
        area += (vs[j].x + vs[i].x) * (vs[j].y - vs[i].y); 
        j = i;
    }

    return (area / 2);
}
Run Code Online (Sandbox Code Playgroud)

所有碰撞功能都会给出失败的响应结果,因此必须存在某种连接.

回到角速度,我知道如何旋转多边形,但我希望在碰撞后获得新的av:

px = x * cos(a) - y * sin(a); 
py = x * sin(a) + y * cos(a);
Run Code Online (Sandbox Code Playgroud)

此外,我为线条和beziers做了一个很好的物理模拟器,它可能会有所帮助:http://murplyx.net/projects/csb/

所以对我来说最重要的部分是我如何修复,以便速度和角度正确地进行?(我使用的是矢量而不是三角函数 - .-)然后我可以考虑质量和角速度.谢谢.我不在Box2D盒子里.

编辑:添加了计算面积^ 2的函数,以将质量设置为相等.

Dan*_*ner 4

在圆碰撞函数中,getCCCol(a, b)您正在计算a.center - b.center圆心之间的向量,然后通过标量对其进行缩放,该标量表示沿圆心之间的向量以长度单位测量的两个圆的重叠。我无法理解这个向量的含义,但它代表了长度或一种定向区域。

然后update(),如果发生碰撞,则将上述值添加到圆的速度(如果圆的速度不固定)。添加速度和长度(或面积)是没有意义的。你真正想做的是根据物体当前的速度、它们之间的接触面、它们的质量以及它们的弹性来改变它们的速度矢量。这可能还需要向后运行模拟一段时间,以消除由于固定时间步长而导致的对象重叠。因此,例如,对于两个质量相等的全弹性圆碰撞头,您只想反转速度矢量,但不根据碰撞的几何形状向它们添加任何内容。

同样的情况getPCCol(p, c)也适用getPPCol(a, b),您再次计算某种距离,然后将其添加到发生碰撞时的速度中。这些值想要代表什么?

最后,我无法指出任何一个问题可以解决问题。在发生碰撞时更新速度的代码与该过程背后的物理原理不匹配。我还真的建议明确地引入一个时间步长,因为你的位置更新步长position = position + velocity确实应该是position = position + velocity x timestep。通过明确这一点,即使您选择它,您也可以更轻松地检查计算单位是否有意义。

重新考虑如何执行模拟可能也是一个好主意。不要前进一个固定的时间步长,然后在发生碰撞时后退 - 您当前没有这样做,但您可能迟早必须这样做 - 首先计算下一次碰撞的时间,然后只前进模拟到此为止。现在,如果速度很高或物体足够小,如果一个时间步长使物体在速度方向上前进的距离大于假定碰撞对象的尺寸,则物体可以相互穿过。如果您正在模拟粒子,那么您的固定时间步长方法就足够好了,因此碰撞不是一个(大)问题,但如果您必须使用固定时间步长来处理碰撞,则还不够好。

我希望这对您有所帮助,当然,如果有不清楚的地方或需要进一步详细说明,请随时询问。


这就是我可能尝试实现刚体动力学的方式,即我添加功能的顺序。每一步都或多或少地增加了一个功能,但它们比听起来要复杂得多。每个步骤都有数千页的研究,以及数十或数百种实施方案。

  1. 无角动量的粒子动力学

    用粒子的质量、(质心)位置和速度定义粒子。使用简单的积分算法模拟它们的运动以及对作用在质心上的力的响应。

  2. 具有角动量的粒子动力学

    添加惯性张量和角速度。考虑使用四元数。实现对作用在任意点而不仅仅是质心的力的响应。

  3. 具有碰撞的刚体动力学

    实现预测碰撞时间和碰撞点的碰撞搜索算法。使用简单的模型(例如基于脉冲的接触模型)计算碰撞响应。这可能需要引入时间步细分。

  4. 具有摩擦力的刚体动力学

    添加一个简单的摩擦模型,例如库伦摩擦。

  5. 添加重力和其他力场

    在这里,您必须决定是否只想拥有恒定的引力,或者是否还想计算物体之间的引力。您可以在步骤 1 之后立即添加重力,因为它只是作用在质心上的力,但由于当两个物体越来越靠近时,重力变得无限大,整个模拟很容易爆炸,即您的物体以很大的速度飞走。模拟重力和其他力场通常需要更先进的积分算法。一般来说,您会发现向模拟添加更多功能通常会增加对集成算法的要求,并且会变得不稳定。