2010-07-12 104 views
5

我需要制定一种算法来检测两个球体碰撞的时间,以及碰撞后瞬间需要的方向。球体 - 球体碰撞检测 - >反应

说吧,想象一下,当你在一场比赛中打开你的桌子时,所有的球都会“随机地”碰撞另一个球。

因此,在开始自己编写代码之前,我一直在考虑是否已经有这样的实现。

Thx提前!

Cyas.-

+0

最困难的部分是旋转... – 2010-07-13 02:32:14

+0

我不在乎旋转,我只需要colissions和“平坦的反应”。 – Artemix 2010-07-13 17:39:49

+0

方向只是沿着连接中心的线。 – Mau 2010-07-15 12:45:23

回答

7

你可以在这里找到一个很好的教程:Link

+0

当然,它会男人,thx。但是,我不需要3D碰撞,我的意思是实际上是圆圈的分裂,而不是球体:p我的不好。 – Artemix 2010-07-12 21:18:37

+0

@Artemix:如果你看看那个页面,它似乎在做大部分的2D解释! +1的好文章。 – 2010-07-12 21:43:36

+0

是的,我注意到了。 – Artemix 2010-07-13 17:42:59

7

碰撞部分很容易。检查球体中心之间的距离是否小于它们的半径之和。

至于反弹,您需要交换垂直于球体碰撞的速度总量。 (假设所有的领域都有相等的质量,这将是一个不同群众的组合不同)

struct Vec3 { 
    double x, y, z; 
} 

Vec3 minus(const Vec3& v1, const Vec3& v2) { 
    Vec3 r; 
    r.x = v1.x - v2.x; 
    r.y = v1.y - v2.y; 
    r.z = v1.z - v2.z; 
    return r; 
} 

double dotProduct(const Vec3& v1, const Vec3& v2) { 
    return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; 
} 

Vec3 scale(const Vec3& v, double a) { 
    Vec3 r; 
    r.x = v.x * a; 
    r.y = v.y * a; 
    r.z = v.z * a; 
    return r; 
} 

Vec3 projectUonV(const Vec3& u, const Vec3& v) { 
    Vec3 r; 
    r = scale(v, dotProduct(u, v)/dotProduct(v, v)); 
    return r; 
} 

int distanceSquared(const Vec3& v1, const Vec3& v2) { 
    Vec3 delta = minus(v2, v1); 
    return dotProduct(delta, delta); 
} 

struct Sphere { 
    Vec3 position; 
    Vec3 velocity; 
    int radius; 
} 

bool doesItCollide(const Sphere& s1, const Sphere& s2) { 
    int rSquared = s1.radius + s2.radius; 
    rSquared *= rSquared; 
    return distanceSquared(s1.position, s2.position) < rSquared; 
} 

void performCollision(Sphere& s1, Sphere& s2) { 
    Vec3 nv1; // new velocity for sphere 1 
    Vec3 nv2; // new velocity for sphere 2 
    // this can probably be optimised a bit, but it basically swaps the velocity amounts 
    // that are perpendicular to the surface of the collistion. 
    // If the spheres had different masses, then u would need to scale the amounts of 
    // velocities exchanged inversely proportional to their masses. 
    nv1 = s1.velocity; 
    nv1 += projectUonV(s2.velocity, minus(s2.position, s1.position)); 
    nv1 -= projectUonV(s1.velocity, minus(s1.position, s2.position)); 
    nv2 = s2.velocity; 
    nv2 += projectUonV(s1.velocity, minus(s2.position, s1.position)); 
    nv2 -= projectUonV(s2.velocity, minus(s1.position, s2.position)); 
    s1.velocity = nv1; 
    s2.velocity = nv2; 
} 

编辑:如果你需要更多的准确性,然后在碰撞你应该计算多远移动两个碰撞领域向后移动以使它们彼此接触,然后触发执行碰撞功能。这将确保角度更准确。

+0

工程很好 - 但我认为存在一个问题:我从10个球(没有重叠)开始,只有一个球有速度 - 一段时间后,他们都在移动很多弹跳。在间隔时间内,我总结了所有的速度(abs(x)+ abs(y)) - 如果我从8开始说它快速增长(它必须违反其中一个守恒定律?),但过了一段时间停止增长,只是在20左右波动..我很困惑,并不确定我是否应该......(注意:在发现碰撞后,我会以微小的步幅向后移动第一个球,直到它们不再重叠,然后再调用performCollision ) – T4NK3R 2017-09-18 18:59:16

+0

尝试总结(sqrt(vx^2 + vy^2))为每个。 – clinux 2017-09-25 21:07:41