2010-07-12 106 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