JavaScript - 分离轴定理 - 碰撞有效,但不响应?

标签 javascript vector physics collision

所以,我正在尝试对我的 SAT、圆 - 多边形、多边形 - 多边形碰撞应用响应。我将本文中的这段代码移植到 JavaScript 中:

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

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

JSFiddle (重力不应用于模拟,用箭头键移动),JS 中的第一部分是矢量,然后是物理,然后是主。

这是我对形状的定义:(必须为“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);
}

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

回到 Angular 速度我知道如何旋转多边形,但我希望在碰撞后获得新的 av:
px = x * cos(a) - y * sin(a); 
py = x * sin(a) + y * cos(a);

我还为线条和贝塞尔曲线制作了一个不错的物理模拟器,它可能会有所帮助:http://murplyx.net/projects/csb/

所以对我来说最重要的部分是我将如何修复以便速度和 Angular 正确地变化? (我使用的是 Vectors 而不是 Trigonometry -.-)然后我可以考虑质量和 Angular 速度。谢谢。我远离 Box2D 框。

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

最佳答案

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

update()然后,如果发生碰撞,则将上面提到的值添加到圆圈的速度(如果它们不固定)。添加速度和长度(或面积)是没有意义的。您真正想要做的是根据对象的当前速度、对象之间的接触平面、质量以及可能的弹性来更改对象的速度向量。这可能还需要向后运行模拟一段时间,以消除由于固定时间步长而导致的对象重叠。因此,例如,对于两个质量相等的完全弹性圆碰撞头部,您只想反转速度矢量,但不根据碰撞的几何形状向它们添加任何内容。
getPCCol(p, c) 也是如此和 getPPCol(a, b)您再次计算某种距离,然后在发生碰撞时将其添加到速度中。这些值打算代表什么?

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

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

我希望这会有所帮助,当然如果有什么不清楚或需要进一步阐述,请随时提问。

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

  • 没有 Angular 动量的粒子动力学

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

    添加惯性张量和 Angular 速度。考虑使用四元数。实现对作用在任何点上的力的响应,而不仅仅是质心。
  • 刚体动力学与碰撞

    实现碰撞搜索算法,预测碰撞时间和碰撞点。使用简单模型(如基于脉冲的接触模型)计算碰撞响应。这可能需要引入时间步分割。
  • 刚体动力学与摩擦

    添加一个简单的摩擦模型,如 Coloumb 摩擦。
  • 添加重力和其他力场

    在这里,您必须决定是只想获得恒定的重力,还是还想计算物体之间的重力。您可以在第 1 步之后立即添加重力,因为它只是一个作用在质心上的力,但是因为随着两个物体越来越靠近,重力变得无限大,整个模拟很容易爆炸,即您的物体以很大的速度飞走。模拟重力和其他力场通常需要更高级的积分算法。通常,您会看到向模拟添加更多特征通常会增加对积分算法的要求,并且您将获得不稳定性。
  • 关于JavaScript - 分离轴定理 - 碰撞有效,但不响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23568388/

    相关文章:

    javascript - 为所有浏览器编码时要注意的标签?

    c# - 在Unity3D中击中来袭导弹(简单的射弹导弹)

    javascript - 使用 jquery 添加元素到空列表

    javascript - 如何为提交按钮添加事件监听器

    c++ - 如何逐个添加两个 STL vector 的元素?

    c++ - 为什么此代码无法将 char 推回到 vector <char> 中?

    物理硬件的数据库设计

    r - 为 ggplot2 组织物理实验数据

    javascript - 我应该/如何使用 .slice() 在按下按钮时交换图像 scr? (用于图库中的下一个/上一个按钮)

    c - 矩阵与 vector 相乘