【发布时间】:2011-05-27 17:47:52
【问题描述】:
更新:发现我使用半径作为直径,这就是 mtd 过度补偿的原因。
另一个更新:我的球重叠的原因似乎是因为每次碰撞只有一次检查。经过一些研究,有人说可以防止与堆积的对象重叠的一种方法是递归地执行碰撞检查。这在一定程度上有效,我怀疑如果物理学更准确,它会更好。如果我找到更多解决方案,我会再次更新。另外,我正在使用Simucal's collision correction code.
嗨,StackOverflow。不久前我写了一个处理程序来模拟球物理。基本上,我有大量的球(1000 个),打开了重力。检测效果很好,但我的问题是,当它们在各个方向与其他球反弹时,它们开始表现得很奇怪。
我非常有信心这涉及到处理。大多数情况下,我使用的是 Jay Conrod 的代码。一个不同的部分是
if (distance > 1.0)
return;
我改成了
if (distance < 1.0)
return;
因为碰撞甚至没有用第一段代码执行,我猜这是一个错字。
当我使用他的代码时,球会重叠,这不是我想要的。我尝试修复它是将球移到彼此的边缘:
float angle = atan2(y - collider.y, x - collider.x);
float distance = dist(x,y, balls[ID2].x,balls[ID2].y);
x = collider.x + radius * cos(angle);
y = collider.y + radius * sin(angle);
这是不正确的,我很确定。
我尝试了上一个球对球主题中的校正算法:
// get the mtd
Vector2d delta = (position.subtract(ball.position));
float d = delta.getLength();
// minimum translation distance to push balls apart after intersecting
Vector2d mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / ball.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
ball.position = ball.position.subtract(mtd.multiply(im2 / (im1 + im2)));
除了我的版本不使用向量,每个球的重量都是 1。我得到的结果代码是这样的:
PVector delta = new PVector(collider.x - x, collider.y - y);
float d = delta.mag();
PVector mtd = new PVector(delta.x * ((radius + collider.radius - d) / d), delta.y * ((radius + collider.radius - d) / d));
// push-pull apart based on mass
x -= mtd.x * 0.5;
y -= mtd.y * 0.5;
collider.x += mtd.x * 0.5;
collider.y += mtd.y * 0.5;
此代码似乎过度纠正了冲突。这对我来说没有意义,因为除此之外,我无法修改每个球的 x 和 y 值。
我的代码的其他部分可能是错误的,但我不知道。这是我正在使用的整个球对球碰撞处理的 sn-p:
if (alreadyCollided.contains(new Integer(ID2))) // if the ball has already collided with this, then we don't need to reperform the collision algorithm
return;
Ball collider = (Ball) objects.get(ID2);
PVector collision = new PVector(x - collider.x, y - collider.y);
float distance = collision.mag();
if (distance == 0) {
collision = new PVector(1,0);
distance = 1;
}
if (distance < 1)
return;
PVector velocity = new PVector(vx,vy);
PVector velocity2 = new PVector(collider.vx, collider.vy);
collision.div(distance); // normalize the distance
float aci = velocity.dot(collision);
float bci = velocity2.dot(collision);
float acf = bci;
float bcf = aci;
vx += (acf - aci) * collision.x;
vy += (acf - aci) * collision.y;
collider.vx += (bcf - bci) * collision.x;
collider.vy += (bcf - bci) * collision.y;
alreadyCollided.add(new Integer(ID2));
collider.alreadyCollided.add(new Integer(ID));
PVector delta = new PVector(collider.x - x, collider.y - y);
float d = delta.mag();
PVector mtd = new PVector(delta.x * ((radius + collider.radius - d) / d), delta.y * ((radius + collider.radius - d) / d));
// push-pull apart based on mass
x -= mtd.x * 0.2;
y -= mtd.y * 0.2;
collider.x += mtd.x * 0.2;
collider.y += mtd.y * 0.2;
【问题讨论】:
-
如果您有新问题,您应该将其设为新帖子,而不是更改此问题。如果不查看您的修订历史,我无法说出您最初的要求。
标签: collision-detection simulation physics