2010-07-12 21 views
5

Tôi cần tạo một thuật toán phát hiện khi hai quả cầu va chạm và hướng mà bạn sẽ chụp ngay sau va chạm.Sphere - phát hiện xung đột hình cầu -> phản ứng

Giả sử, Hãy tưởng tượng như khi bạn mở bàn trong một trận đấu hồ bơi, tất cả các quả bóng đang va chạm với nhau "ngẫu nhiên".

Vì vậy, trước khi bắt đầu tự viết mã, tôi đã suy nghĩ xem đã có triển khai thực hiện điều này chưa.

Thx trước!

Cyas.-

+0

Phần khó nhất là spin ... –

+0

Tôi không quan tâm đến spin, tôi chỉ cần colissions và "phản ứng phẳng". – Artemix

+0

Hướng chỉ đơn giản dọc theo đường nối các trung tâm. – Mau

Trả lời

7

Bạn có thể tìm thấy một hướng dẫn tốt ở đây: Link

+0

Chắc chắn nó sẽ là người đàn ông, thx. Nhưng, tôi không cần va chạm 3D, tôi có nghĩa là vòng tròn colission thực sự, không phải hình cầu ở tất cả: p xấu của tôi. – Artemix

+0

@Artemix: Nếu bạn nhìn vào trang đó, nó dường như đang thực hiện hầu hết các giải thích trong 2D! +1 cho bài viết hay. –

+0

Vâng, tôi nhận thấy điều đó. – Artemix

7

Sự va chạm phần là dễ dàng. Kiểm tra xem khoảng cách giữa các quả cầu có nhỏ hơn tổng bán kính của chúng hay không.

Đối với thư bị trả lại, bạn cần trao đổi số tiền vận tốc góp phần vào tổng vận tốc vuông góc với va chạm của các hình cầu. (Giả sử tất cả các lĩnh vực của bạn có khối lượng bằng nhau, nó sẽ là khác nhau cho một sự kết hợp của quần chúng khác nhau)

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; 
} 

EDIT: Nếu bạn cần độ chính xác hơn, sau đó khi một vụ va chạm, bạn nên tính toán bao xa để di chuyển cả các lĩnh vực va chạm ngược lại để chúng chỉ chạm vào nhau, sau đó kích hoạt chức năng thực hiện va chạm. Điều đó sẽ đảm bảo các góc sẽ chính xác hơn.

+0

Hoạt động tuyệt vời - nhưng tôi nghĩ có vấn đề: Tôi bắt đầu với 10 quả bóng (không chồng chéo), nơi chỉ có một quả bóng - sau một thời gian ngắn và rất nhiều phản ứng đang chuyển động. Trong khoảng thời gian tôi tổng hợp tất cả các vận tốc (abs (x) + abs (y)) - nếu tôi bắt đầu với, nói 8 trong tất cả, nó nhanh chóng phát triển (mà phải vi phạm một trong các luật bảo tồn?) Nhưng sau một thời gian nó dừng lại phát triển, chỉ dao động khoảng 20 .. Tôi bối rối và không chắc chắn nếu tôi nên .. (Lưu ý: sau khi một va chạm được phát hiện tôi di chuyển bóng đầu tiên lạc hậu, trong bước phút, cho đến khi họ không còn chồng lên nhau, trước khi gọi performCollision) – T4NK3R

+0

Hãy thử tổng hợp (sqrt (vx^2 + vy^2)) cho mỗi. – clinux

Các vấn đề liên quan