我正在编写扩展Circle-Rectangle collision detection (intersection)的软件,以包含对碰撞的响应。圆边和圆矩形是相当直接的。但圈圈让我难过。
例如,在离散事件模拟中,让两个圆碰撞,一个红色和一个绿色。我们可能会遇到以下情况:
碰撞后我们可以立即:
此处RIP和GIP是前一个时钟周期的圆圈位置。在当前时钟滴答处,在RDP和GDP处检测到碰撞。但是,当两个圆圈处于RCP和GCP时,时钟滴答之间发生冲突。在时钟滴答处,红色圆圈向下移动RVy,向右移动RVx;绿色圆圈向下移动GVy,向左移动GVx。 RVy不等于GVy; RVx也不等于GVx。
当圆心之间的距离小于或等于圆的半径之和时,即在前图中,d <=(Rr + Gr),发生碰撞。在碰撞中,d < (Rr + Gr),我们需要在调整圆的速度分量之前将DP定位回CP。在d ==(Rr + Gr)的情况下,由于DP在CP处,因此不需要重新定位。
这就是问题所在:如何重新回到CP。一些作者建议应用下图中由p给出的渗透的一半。
对我而言,这是完全错误的。它假设两个圆的速度矢量相等,在这个例子中不是这种情况。我认为渗透与计算有关,但我怎么办。我知道这个问题可以重新定义为我们想要为Gcdy和GCdx解决的类似三角形的问题。
碰撞本身将被建模为弹性,并且惯性交换的数学已经到位。唯一的问题是在碰撞时将圆圈定位在哪里。
答案 0 :(得分:3)
“这就是问题所在:我该如何采取行动。”
您可能想知道在调整圆圈的速度成分之前如何“将DP定位回CP。”
因此,有两个问题,如何确定CP(发生碰撞的位置)以及如何从该点开始调整圆圈的运动。第一部分有一个相当简单的解决方案(允许不同的半径和速度分量),但第二部分取决于是否建模弹性或非弹性响应。在评论中你写道:
碰撞将被建模为弹性。惯性交换的数学 已经到位了。问题是在哪里定位圈子。
鉴于我将仅解决第一个问题,解决碰撞发生的确切位置。假设两个圆的运动一致,则知道发生碰撞的确切时间就足够了,即圆的中心之间的距离何时等于它们的半径之和。
通过均匀运动,可以通过从另一个圆(绿色)中减去其速度来将一个圆(红色)视为静止。实际上,我们将第一个圆的中心视为固定,并仅考虑第二个圆(均匀)运动。
现在通过求解二次方程找到确切的碰撞时间。设V =(GVx-RVx,GVy-RVy)是圆的相对运动,并且让P =(GIPx-RIPx,GIPy-RIPy)它们在碰撞之前的“瞬间”中的相对位置。我们通过定义:
为相对位置P“线性化”线性路径P(t)= P + t * V
并询问此直线何时与半径Rr + Gr原点周围的圆相交,或者何时:
(Px + t * Vx)^ 2 +(Py + t * Vy)^ 2 =(Rr + Gr)^ 2
这是未知时间t的二次方程式,所有其他涉及的数量都是已知的。情况是这样的(在CP位置或之前发生碰撞)将存在积极的实际解决方案(通常是两个解决方案,一个在CP之前,一个在之后,但可能是放牧接触给出“双根”)。您想要的解决方案(根)是较早的解决方案,其中t(在“即时”RIP处为零,GIP位置)较小。
答案 1 :(得分:1)
如果您正在寻找关于圆形物体的非弹性碰撞的基本参考,Joe van den Heuvel和Miles Jackson的Pool Hall Lessons: Fast, Accurate Collision Detection Between Circles or Spheres非常容易理解。
从最不正式到最正式,这里有一些关于实现编程工艺的后续参考资料,这些编程是解决问题的解决方案(碰撞响应)。
你将不得不接受一些近似值 - Beckman在视频中证明即使对于非常简单的情况,也不可能通过分析预测会发生什么,这更糟糕,因为你正在模拟一个连续的系统离散的步骤。
答案 2 :(得分:1)
在给定初始位置和速度矢量的情况下,您实际上可以获得达到碰撞所需时间的表达式。
调用你的对象A和B,并说他们有位置向量 a 和 b 和速度向量 u 和 v < / strong>,分别。假设A以每时间步长 u 单位的速度移动(因此,在时间= t时,A在 a ;在时间= t + 1时,A在 a + u )。
我不确定你是否想要看到推导;它看起来不会那么好......我对LaTeX的了解非常有限。 (如果你真的想要我,我可以在以后编辑它)。但是现在,这就是我所拥有的,使用通用C#-ish语法,使用Vector2类型,声明为Vector2(X,Y),并具有向量加法,标量乘法,点积和长度的函数。
double timeToCollision(Vector2 a, Vector2 b, Vector2 u, Vector2 v)
{
// w is the vector connecting their centers;
// z is normal to w and equal in length.
Vector2 w = b - a;
Vector2 z = new Vector2(-1 * w.Y, w.X);
Vector2 s = u - v;
// Dot() represents the dot product.
double m = Dot(z, s) / Dot(w, s);
double t = w.Length() / Dot(w, s) *
(w.Length() - sqrt( ((2 * r) ^ 2) * (1 + m ^ 2) - (m * w.Length()) ^ 2) ) /
(1 + m * m)
return t;
}
对于碰撞的响应:如果你可以快进到冲击点,你不必担心处理相交的圆圈。
如果您感兴趣,当不会成为碰撞时,此表达式会给出一些很酷的结果。如果两个物体彼此远离,但如果它们的速度被反转就会发生碰撞,那么你将获得t的负值。如果对象位于不平行的路径上,但永远不会相遇(相互通过),则会在平方根内得到负值。抛弃平方根项,您将获得彼此最接近的时间。如果它们以相同的速度并行移动,则分母中的值为零,t的值为未定义。
嗯,希望这很有帮助!我碰巧和你有同样的问题,并决定看看我是否可以在纸上解决问题。
编辑:在发布之前我应该更仔细地阅读之前的回复......上面公式的混乱确实是硬数据描述的二次方程的解决方案。为冗余职位道歉。
答案 3 :(得分:1)
要以恒定的速度重新定位两个重叠的圆圈,您需要做的就是找到发生碰撞的时间,并将它们的速度因子添加到它们的位置。
首先,我们将考虑一个具有组合半径和相对位置和速度的圆,而不是两个圆移动。让输入圆圈的位置为P1
和P2
,速度为V1
和V2
,以及半径为r1
和r2
。让组合圆具有位置P = P2 - P1
,力度V = V2 - V1
和半径r = r1 + r2
。
我们必须找到圆与原点相交的时间,换句话说,找到t
的{{1}}的值。应该有0,1或2个值,具体取决于圆圈是否不通过原点,与它相切,还是飞过它。
r = |P + tV|
通过平方双方。
r^2 = ||P + tV||
使用L2范数等价于矢量与自身的点积,然后分布点积。
r^2 = (P + tV)*(P + tV) = t^2 V*V + 2tP*V + P*P
将其转化为二次方程式。
如果没有解决方案,那么判别式t^2 V*V + 2tP*V + P*P - r^2 = 0
将为负数。如果它为零或正,那么我们对第一个解决方案感兴趣,所以我们将减去判别式。
b^2 - 4ac
所以a = V*V
b = 2 P*V
c = P*P - r^2
t = (-b - sqrt(b^2 - 4ac)) / (2a)
是碰撞的时间。