【问题标题】:Ball to Ball Collision resolution球对球碰撞解决方案
【发布时间】:2018-11-27 20:42:41
【问题描述】:

我在 youtube 上浏览了一些碰撞检测教程,在其中一个教程中,这个家伙使用以下代码来解决两个球之间的碰撞:

/**
 * Rotates coordinate system for velocities
 *
 * Takes velocities and alters them as if the coordinate system they're on was rotated
 *
 * @param  Object | velocity | The velocity of an individual particle
 * @param  Float  | angle    | The angle of collision between two objects in radians
 * @return Object | The altered x and y velocities after the coordinate system has been rotated
 */

function rotate(velocity, angle) {
    const rotatedVelocities = {
        x: velocity.x * Math.cos(angle) - velocity.y * Math.sin(angle),
        y: velocity.x * Math.sin(angle) + velocity.y * Math.cos(angle)
    };

    return rotatedVelocities;
}

/**
 * Swaps out two colliding particles' x and y velocities after running through
 * an elastic collision reaction equation
 *
 * @param  Object | particle      | A particle object with x and y coordinates, plus velocity
 * @param  Object | otherParticle | A particle object with x and y coordinates, plus velocity
 * @return Null | Does not return a value
 */

function resolveCollision(particle, otherParticle) {
    const xVelocityDiff = particle.velocity.x - otherParticle.velocity.x;
    const yVelocityDiff = particle.velocity.y - otherParticle.velocity.y;

    const xDist = otherParticle.x - particle.x;
    const yDist = otherParticle.y - particle.y;

    // Prevent accidental overlap of particles
    if (xVelocityDiff * xDist + yVelocityDiff * yDist >= 0) {

        // Grab angle between the two colliding particles
        const angle = -Math.atan2(otherParticle.y - particle.y, otherParticle.x - particle.x);

        // Store mass in var for better readability in collision equation
        const m1 = particle.mass;
        const m2 = otherParticle.mass;

        // Velocity before equation
        const u1 = rotate(particle.velocity, angle);
        const u2 = rotate(otherParticle.velocity, angle);

        // Velocity after 1d collision equation
        const v1 = { x: u1.x * (m1 - m2) / (m1 + m2) + u2.x * 2 * m2 / (m1 + m2), y: u1.y };
        const v2 = { x: u2.x * (m1 - m2) / (m1 + m2) + u1.x * 2 * m2 / (m1 + m2), y: u2.y };

        // Final velocity after rotating axis back to original location
        const vFinal1 = rotate(v1, -angle);
        const vFinal2 = rotate(v2, -angle);

        // Swap particle velocities for realistic bounce effect
        particle.velocity.x = vFinal1.x;
        particle.velocity.y = vFinal1.y;

        otherParticle.velocity.x = vFinal2.x;
        otherParticle.velocity.y = vFinal2.y;
    }
}

我基本了解这段代码。但是,我无法理解这个 if 条件是如何确定球是否重叠的。

if (xVelocityDiff * xDist + yVelocityDiff * yDist >= 0)

谁能解释一下?

【问题讨论】:

  • @GuyCoder 我已经用 1000 个球在空间中以随机速度移动并碰撞在一起进行了验证。你能解释一下为什么(xVelocityDiff * xDist >=0)(yVelocityDiff * yDist >= 0) 有意义吗?
  • 当我看到不同维度的问题时,在这种情况下是水平和垂直,或者 X 和 Y,并且它们将它们混合在一个没有注释的表达式中,它会引起我的注意。经过多年的编码,某些模式会突然出现,其中一些模式是为了寻找错误。这匹配了一个模式来检查错误。正如我所指出的,我并没有说这是一个错误,它还应该记录它在做什么。当我在这个answer 中看到dot product 并学习了物理学,我只需要知道它是正确的。
  • 为了将我之前的评论更多地放在编程的上下文中,将不同的维度视为不同的类型,即使您可以将它们视为具有类型长度或位置,我认为它们是偶数更具体的类型。我不喜欢许多语言的一个问题是它们允许您使用基本类型而无需重新定义它们。在 C 中,使用 int 类型作为指针是一个经典案例。当我开始学习 ADA 时,最奇怪的事情之一是你不能只使用 int 类型,你必须从 int 创建一个新类型,然后使用该类型。

标签: graphics language-agnostic collision-detection game-physics


【解决方案1】:

通过获取位置和速度的差异,您可以在otherParticle 的框架中查看所有内容。在该帧中,otherParticle 静止在原点,particlevelocityDiff 一起移动。下面是它的样子:

术语xVelocityDiff * xDist + yVelocityDiff * yDist 是两个向量的点积。如果velocityDiff 指向与dist 稍微相反的方向,则此点积为负,即如果粒子像上图那样越来越近。如果点积为正,则粒子正在远离otherParticle,您无需执行任何操作。

【讨论】:

  • 啊完全错过了看到它是一个点积。谢谢。
  • @NicoSchertler - 当已经检测到碰撞时调用resolveCollision 函数,所以我仍然不清楚为什么我们需要进一步检查点积以防止重叠。如果点积为正,也计算一维碰撞,但是您提到在这种情况下无需执行任何操作,请您澄清两点吗?谢谢。
  • @MrShabana 它主要用于保持离散时间步模拟的一致性。如果点积为负,则碰撞将自行解决,因为它很可能只是非常轻微的接触,或者其中一个速度已经被不同的碰撞解决方案修改。或者分辨率已经改变了速度,但碰撞在下一个时间步仍然存在。绝对正确,可以将时间倒回到碰撞实际发生的时间点,然后从那里解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-19
  • 1970-01-01
  • 2010-09-25
  • 2012-02-11
  • 1970-01-01
相关资源
最近更新 更多