7

我正在编写自己的基本物理引擎,但现在遇到了一个我无法解决的问题。可能是因为我不知道如何用谷歌搜索这个问题。

所以这是我的问题。我希望这张图片可以解释它:

碰撞响应

我有两个对象。灰色的是固定不动的,绿色的是从上面掉下来的。绿色物体具有三个向量:力、加速度和速度。它与固定的灰色物体发生碰撞。

真正的问题是如何在绿色物体掉落时获得旋转?

4

2 回答 2

12

听起来您可能不了解刚体动力学背后的基础物理学。我这么说只是因为你在谈论这类问题时没有提到任何常用的术语。您需要将方向和角速度的概念(位置和线速度的旋转模拟)引入系统中的每个动态体,并计算各种中间量,如惯性矩、角加速度和扭矩。

也许最好的介绍性参考是Chris Hecker为 Game Developer Magazine 撰写的系列文章。假设您已经解决了非旋转动力学(第 1 部分中介绍)和碰撞检测(本系列未介绍),您应该从第 2 部分开始并继续第 3 部分。它们将为您提供坚实的物理学基础和实现旋转碰撞响应所需的数学。

于 2012-07-25T17:32:04.800 回答
10

当对象发生碰撞时,您按如下所述执行一次。

让我们称绿色矩形为“a”,另一个为“b”。

1.

首先你需要矩形“旋转质量”,惯性质量。

ai = 4/3 * 宽度 * 高度 * (宽度^2 + 高度^2) * a.密度

2.

然后你需要从矩形的质心(所有角的平均位置)指向接触位置(矩形碰撞的地方)的向量,我们称之为“r”。

3.

然后你需要找到碰撞法线。该法线是从 b 施加到 a 的脉冲的方向。法线是长度为 1 个单位的向量。在您的示例中,法线可能会向上。让我们将法线向量称为“n”。

4.

现在你需要 a 上接触点的速度。如果 a 不旋转,则公式为:

vp = a.vel

如果 a 正在旋转,则公式为:

vp = a.vel + cross(a.r_vel, r)

a.r_vel 是以弧度给出的 a 的旋转速度,正方向为逆时针方向。

cross() 表示叉积,函数为:

交叉 (v,i) = [-i * vy , i * vx]

扩展公式为:

vp = av + [-r * a.r_vel.y , r * a.r_vel.x]

5.

现在您需要计算对象是否相互移动。将 vp 投影到 n 上。

vp_p = 点(vp,n)

点 (v1, v2) = v1.x * v2.x + v1.y * v2.y

vp_p 是一个标量(一个值,而不是一个向量)。

如果 vp_p 为负,则对象正在相互靠近,如果 > 0,则它们正在分开。

6.

现在你需要计算阻止a移动到b的冲动,冲动是:

j = -vp_p / ( 1/a.mass + cross(r,n)^2 / ai )

两个向量之间的叉积是:

交叉(v1,v2)= v1.x * v2.y - v1.y * v2.x

它返回一个标量。

将冲量与法线相乘得到冲量向量:

jn = j * n

7.

现在您需要将脉冲应用于:

a.new_vel = a.old_vel + jn / a.mass;

a.new_r_vel = a.old_r_vel + cross(r,jn) / ai;

如果您希望碰撞完全有弹性,则必须将冲量乘以 2。让我们将此乘数称为“e”。e 需要介于 1 和 2 之间。1 表示没有能量守恒,2 表示所有能量都守恒。

示例代码:

var vp = a.vel + cross(a.r_vel, r);
var vp_p = dot(vp,n); // negative val = moving towards each other
if (vp_p >= 0) { // do they move apart?
    return false;
}

// normal impulse
var j = - e * vp_p / (
            1/a.mass + cross(r,n)^2 / a.i
        );
var jn = j * n;
//
a.vel = a.vel + jn / a.mass;
a.r_vel = a.r_vel + cross(r,jn) / a.i;

如果 b 不是静态的,算法会略有不同:

ar = 从 a 的质心指向接触位置的向量

var vp = a.vel + cross(a.r_vel, a.r) - b.vel - cross(b.r_vel, b.r);
var vp_p = dot(vp,n); // negative val = moving towards each other
if (vp_p >= 0) { // do they move apart?
    return false;
}

// normal impulse
var j = - e * vp_p / (
            1/a.mass + cross(a.r,n)^2 / a.i +
            1/b.mass + cross(b.r,n)^2 / b.i
        );
var jn = j * n;
//
a.vel = a.vel + jp / a.mass;
a.r_vel = a.r_vel + cross(a.r,jn) / a.i;
b.vel = b.vel - jp / b.mass;
b.r_vel = b.r_vel - cross(b.r,jn) / b.i;

公式如何工作/来源:

http://www.myphysicslab.com/collision.html#resting_contact

于 2015-06-25T13:58:31.203 回答