Sphere - 球体碰撞检测 ->反应 [英] Sphere - sphere collision detection -> reaction

查看:27
本文介绍了Sphere - 球体碰撞检测 ->反应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要制定一个算法来检测两个球体何时发生碰撞,以及碰撞后一个球体的方向.

I need to make an algorithm that detects when two spheres collide, and, the direction that wich one will take an instant after the collision.

假设,想象一下,当您在一场台球比赛中打开桌子时,所有的球都随机"地相互碰撞.

Let say, Imagine like when you open your table in a pool match, all the balls are colliding one to another "randomly".

所以,在开始自己编写代码之前,我在想是否已经有这样的实现.

So, before starting to write the code myself, I was thinking if there is already a implementation of this out there.

提前谢谢!

Cyas.-

推荐答案

碰撞部分很简单.检查球心之间的距离是否小于它们的半径之和.

The collision part is easy. Check if the distance between the spheres centers is less than the sum of their radius.

至于反弹,您需要交换对垂直于球体碰撞的总速度有贡献的速度量.(假设所有球体的质量相同,不同质量的组合会有所不同)

As for the bounce, you need to swap the velocity amounts that contribute to the total velocity perpendicular to the collision of the spheres. (Assuming all your spheres have equal mass, it would be different for a combination of different masses)

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

如果您需要更高的精度,那么在发生碰撞时,您应该计算两个碰撞球体向后移动多远,以便它们相互接触,然后触发执行碰撞功能.这样可以确保角度更准确.

If you need more accuracy, then upon a collision you should calculate how far to move both the colliding spheres backwards so that they just touch each other, then trigger the perform collision function. That would insure the angles will be more accurate.

这篇关于Sphere - 球体碰撞检测 ->反应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆