我正在尝试编写一个简单的物理模拟,其中具有不同半径和质量的球在完全弹性和无摩擦的环境中反弹。我在此资源之后编写了自己的代码:http://www.vobarian.com/collisions/2dcollisions2.pdf我还测试了此处的代码:Ball to Ball Collision - Detection and Handling
编辑问题
在Rick Goldstein和Ralph的帮助下,我已经让我的代码工作了(有一个错字......)。非常感谢你的帮助。但是我仍然感到困惑,为什么其他算法不适合我。球以正确的方向反弹,但系统的总能量永远不会被保存。速度变得越来越快,直到球刚刚开始在屏幕上的静态位置闪烁。我实际上想在我的程序中使用这个代码,因为它比我编写的代码简洁得多。
这是我写的功能算法(虽然我确实从其他来源获取了第一位)。它在泡泡课中:
public void resolveCollision(Bubble b)
{
// get the minimum translation distance
Vector2 delta = (position.subtract(b.position));
float d = delta.getMagnitude();
// minimum translation distance to push balls apart after intersecting
Vector2 mtd = delta.multiply(((getRadius() + b.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / b.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
b.position = b.position.subtract(mtd.multiply(im2 / (im1 + im2)));
//get the unit normal and unit tanget vectors
Vector2 uN = b.position.subtract(this.position).normalize();
Vector2 uT = new Vector2(-uN.Y, uN.X);
//project ball 1 & 2 's velocities onto the collision axis
float v1n = uN.dot(this.velocity);
float v1t = uT.dot(this.velocity);
float v2n = uN.dot(b.velocity);
float v2t = uT.dot(b.velocity);
//calculate the post collision normal velocities (tangent velocities don't change)
float v1nPost = (v1n*(this.mass-b.mass) + 2*b.mass*v2n)/(this.mass+b.mass);
float v2nPost = (v2n*(b.mass-this.mass) + 2*this.mass*v1n)/(this.mass+b.mass);
//convert scalar velocities to vectors
Vector2 postV1N = uN.multiply(v1nPost);
Vector2 postV1T = uT.multiply(v1t);
Vector2 postV2N = uN.multiply(v2nPost);
Vector2 postV2T = uT.multiply(v2t);
//change the balls velocities
this.velocity = postV1N.add(postV1T);
b.velocity = postV2N.add(postV2T);
}
这是一个不起作用的
public void resolveCollision(Bubble b)
{
// get the minimum translation distance
Vector2 delta = (position.subtract(b.position));
float d = delta.getMagnitude();
// minimum translation distance to push balls apart after intersecting
Vector2 mtd = delta.multiply(((getRadius() + b.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / b.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
b.position = b.position.subtract(mtd.multiply(im2 / (im1 + im2)));
// impact speed
Vector2 v = (this.velocity.subtract(b.velocity));
float vn = v.dot(mtd.normalize());
// sphere intersecting but moving away from each other already
if (vn > 0.0f) return;
// collision impulse (1f is the coefficient of restitution)
float i = (-(1.0f + 1f) * vn) / (im1 + im2);
Vector2 impulse = mtd.multiply(i);
// change in momentum
this.velocity = this.velocity.add(impulse.multiply(im1));
b.velocity = b.velocity.subtract(impulse.multiply(im2));
}
如果您发现任何问题,请告诉我。感谢
答案 0 :(得分:6)
设置v1nPost的行中是否有拼写错误?看起来分母应该是this.mass + b.mass
,而不是this.mass * b.mass
。
此外,因为您正在计算this
和b
之间的冲突,您是否正在检查以确保您在b
和{{1}之间不会发生相同的冲突因此,在碰撞中加倍应用于每个参与气泡的增量?
答案 1 :(得分:3)
我做的第一个猜测:getMass()返回一个整数(或int)(而不是float或double)?
如果这是真的,那么问题是1 / getMass()
将导致整数值(并且可以只有1或大部分时间为0))。要解决此问题,请将1
或1.0
1.0f
因为一般规则很简单: 如果你有数学运算(+, - ,*,/),如果两个操作数都不是浮点数据结构(double或float),结果类型将是整数
无论如何:可能存在第二个问题,可能你的计算不准确。那么你应该使用double而不是float。
答案 2 :(得分:1)
有一部分看起来很奇怪:
两项计算:
float v1nPost = (v1n*(this.mass-b.mass) + 2*b.mass*v2n)/(this.mass*b.mass);
float v2nPost = (v2n*(b.mass-this.mass) + 2*this.mass*v1n)/(this.mass+b.mass);
是对称的,除了最后一个操作,第一个是*
,第二个是+