大量球对球碰撞处理(例如,很多球) [英] Mass Ball-to-Ball Collision Handling (as in, lots of balls)

查看:213
本文介绍了大量球对球碰撞处理(例如,很多球)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:发现我使用半径作为直径,这就是为什么mtd补偿过度的原因.

Update: Found out that I was using the radius as the diameter, which was why the mtd was overcompensating.

另一个更新:我的球重叠的原因似乎是因为每次碰撞都只检查一次.经过研究,有人说,防止与堆积的对象重叠的方法之一是递归执行碰撞检查.这在一定程度上有效,我怀疑如果物理精度更高的话,效果会更好.如果找到更多解决方案,我将再次更新.另外,我正在使用 Simucal的碰撞校正代码.

Another Update: The reason my balls are overlapping seem to be because there's only one check for every collision. After some research, some are saying that one of the ways you could prevent overlapping with objects piling up is to recursively perform the collision check. This works to an extent, and I suspect that it'd work even better if the physics were a lot more accurate. I'll update again if I find any more solutions. Also, I'm using Simucal's collision correction code.

StackOverflow.我写了一个处理程序,不久后就模拟了球的物理过程.基本上,我有大量的球(1000个),并且打开了重力.检测效果很好,但我的问题是,当它们在各个方向弹向其他球时,它们开始表现出怪异的感觉.

Hi, StackOverflow. I've written a Processing program awhile back simulating ball physics. Basically, I have a large number of balls (1000), with gravity turned on. Detection works great, but my issue is that they start acting weird when they're bouncing against other balls in all directions.

我非常确定这涉及处理.在大多数情况下,我使用的是Jay Conrod的代码.一个不同的部分是

I'm pretty confident this involves the handling. For the most part, I'm using Jay Conrod's code. One part that's different is

if (distance > 1.0)
        return;

我已更改为

if (distance < 1.0)
        return;

因为冲突甚至没有在第一部分代码中执行,所以我猜那是一个错字.

because the collision wasn't even being performed with the first bit of code, I'm guessing that's a typo.

当我使用他的代码时,球重叠了,这不是我想要的.我试图解决这个问题的方法是将球移到彼此的边缘:

The balls overlap when I use his code, which isn't what I was looking for. My attempt to fix it was to move the balls to the edge of each other:

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

这是不正确的,我很确定.

This isn't correct, I'm pretty sure of that.

我在上一个球对球主题中尝试了校正算法:

I tried the correction algorithm in the previous ball-to-ball topic:

// 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.我得到的结果代码是:

except my version doesn't use vectors, and every ball's weight is 1. The resulting code I get is this:

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值.

This code seems to over-correct collisions. Which doesn't make sense to me because in no other way do I modify the x and y values of each ball, other than this.

我的代码的其他部分可能是错误的,但我不知道.这是我正在使用的整个球对球碰撞处理的摘要:

Some other part of my code could be wrong, but I don't know. Here's the snippet of the entire ball-to-ball collision handling I'm using:

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;

推荐答案

您的结果代码"看起来正确.您是否有一个显示过度校正的简单测试用例(例如x 1 = 0,x 1 = 3,y 1 = y 2 = 0,r 1 = r 2 = 2)?

Your "resulting code" looks correct. Do you have a simple test case that shows the overcorrection (e.g. x1=0, x1=3, y1=y2=0, r1=r2=2)?

此外,如果您忽略重叠部分并保留其他所有内容,就好象球是柔软的橡胶一样,您还会得到良好的结果吗?

Also, do you get good results if you neglect the overlap and keep everything else, as if the balls were soft rubber?


这部分是错误的:

PVector velocity = new PVector(vx,vy);  
...
collider.vy += (bcf - bci) * collision.y;

当两个球靠近时,它们互相阻尼,直到它们都停止运动.但好的一面是,您发明了固体(开玩笑).关闭重叠的东西,在您完成此部分工作之前,请不要担心.

When two balls get close they damp each other's velocity until they both stop. But on the bright side, you've invented solids (just kidding). Turn off the overlap stuff and don't worry about it until you have this part working.

在不了解基本物理的情况下,使这部分工作几乎是不可能的.你需要帮忙吗?

Getting this part working will be just about impossible without an understanding of basic physics. Do you need a hand?

这篇关于大量球对球碰撞处理(例如,很多球)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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