Сфера - обнаружение столкновения сферы -> реакция - PullRequest
6 голосов
/ 13 июля 2010

Мне нужно создать алгоритм, который определяет, когда сталкиваются две сферы, и направление, в котором будет проходить мгновение после столкновения.

Допустим, представьте себе, как будто вы открываете свой стол в бассейнесовпадают, все шары сталкиваются друг с другом «случайным образом».

Итак, прежде чем начать писать код сам, я подумал, есть ли уже реализация этого там.

Спасибо заранее!

Cyas .-

Ответы [ 2 ]

9 голосов
/ 15 июля 2010

Столкновение легко.Проверьте, меньше ли расстояние между центрами сфер, чем сумма их радиусов.

Что касается отскока, вам необходимо поменять местами скорости, которые вносят вклад в общую скорость, перпендикулярную столкновению сфер.(Предполагая, что все ваши сферы имеют одинаковую массу, она будет отличаться для комбинации разных масс)

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

РЕДАКТИРОВАТЬ: Если вам нужна большая точность, то при столкновении вы должны рассчитать, как далеко сдвинутьсталкивающие сферы назад, так что они просто касаются друг друга, а затем запускают функцию выполнения столкновения.Это обеспечит более точные углы.

7 голосов
/ 13 июля 2010

Хороший учебник вы можете найти здесь: Ссылка

...