You have 2 balls, A and B. Initially, you know the positions of both balls and is represented by the 2 vectors PA and PB. The initial velocity of each ball is represented by the vectors VA and VB. The friction acting on each ball is represented by an acceleration vector pointing in the opposite direction of the velocity vector, and of a constant magnitude. These friction vectors will be called FA and FB.
We can express the position of a ball as a function of time with the following formula:
F(p, v, f, t) = p + vt + 0.5ft2
p is the position of the ball at t=0
v is the velocity of the ball at t=0
f is the vector representing the friction acting on the ball
t is the time
We can use this formula to express the positions of balls A and B as a function of time:
f(PA, VA, FA, t) = PA + VAt + 0.5FAt2
f(PB, VB, FB, t) = PB + VBt + 0.5FBt2
Now we can define a function that will express the distance between two balls as a function of time:
distance(PA, VA, FA, PB, VB, FB, t) = |f(PA, VA, FA, t) - f(PB, VB, FB, t)|
To determine when a collision occurs all we have to do is set this equation equal to a balls diameter (2 * radius) and solve for t.
The first step is rewriting these equations so they use real numbers as opposed to vectors.
The position function f(p, v, f, t) can be broken down into two functions that calculate the balls position along the x-axis as a function of time, and the balls position along the y-axis as a function of time:
fx(p, v, f, t) = px + vxt + 0.5fxt2
fy(p, v, f, t) = py + vyt + 0.5fyt2
In order to rewrite the distance formula, recall that |Z| denotes the magnitude of a vector Z. The magnitude can be calculated by using the x and y components like so:
|Z| = sqr(Zx2 + Zy2)
Using this we can rewrite our distance formula as follows:
distance(PA, VA, FA, PB, VB, FB, t) = sqr((fx(PA, VA, FA, t) - fx(PB, VB, FB, t))2 + (fy(PA, VA, FA, t) - fy(PB, VB, FB, t))2)
Setting this equal to our balls diameter (D) we get:
D = sqr((fx(PA, VA, FA, t) - fx(PB, VB, FB, t))2 + (fy(PA, VA, FA, t) - fy(PB, VB, FB, t))2)
Squaring each side this becomes
D2 = (fx(PA, VA, FA, t) - fx(PB, VB, FB, t))2 + (fy(PA, VA, FA, t) - fy(PB, VB, FB, t))2
Substituting in the formulas for fx and fy we get:
D2 = ((PA.x + VA.xt + 0.5FA.xt2) - (PB.x + VB.xt + 0.5FB.xt2))2 + ((PA.y + VA.yt + 0.5FA.yt2) - (PB.y + VB.yt + 0.5FB.yt2))2
Now lets remove some of those brackets
D2 = (PA.x + VA.xt + 0.5FA.xt2 - PB.x - VB.xt - 0.5FB.xt2)2 + (PA.y + VA.yt + 0.5FA.yt2 - PB.y - VB.yt - 0.5FB.yt2)2
Now we have to evaluate the squares which will produce a monster of an equation with 72 terms:
D2 = PA.x2 + PA.xVA.xt + PA.x0.5FA.xt2 - PA.xPB.x - PA.xVB.xt - PA.x0.5FB.xt2
+ VA.xtPA.x + VA.x2t2 + VA.xt30.5FA.x - VA.xtPB.x - VA.xt2VB.x - VA.xt30.5FB.x
+ 0.5FA.xt2PA.x + 0.5FA.xt3VA.x + 0.25FA.x2t4 - 0.5FA.xt2PB.x - 0.5FA.xt3VB.x - 0.25FA.xt4FB.x
- PB.xPA.x - PB.xVA.xt - PB.x0.5FA.xt2 + PB.x2 + PB.xVB.xt + PB.x0.5FB.xt2
- VB.xtPA.x - VB.xt2VA.x - VB.xt30.5FA.x + VB.xtPB.x + VB.x2t2 + VB.xt30.5FB.x
- 0.5FB.xt2PA.x - 0.5FB.xt3VA.x - 0.25FB.xt4FA.x + 0.5FB.xt2PB.x + 0.5FB.xt3VB.x + 0.25FB.x2t4
+ PA.y2 + PA.yVA.yt + PA.y0.5FA.yt2 - PA.yPB.y - PA.yVB.yt - PA.y0.5FB.yt2
+ VA.ytPA.y + VA.y2t2 + VA.yt30.5FA.y - VA.ytPB.y - VA.yt2VB.y - VA.yt30.5FB.y
+ 0.5FA.yt2PA.y + 0.5FA.yt3VA.y + 0.25FA.y2t4 - 0.5FA.ytPB.y - 0.5FA.yt2VB.y - 0.25FA.yt4FB.y
- PB.yPA.y - PB.yVA.yt - PB.y0.5FA.yt2 + PB.y2 + PB.yVB.yt + PB.y0.5FB.yt2
- FB.ytPA.y - VB.yt2VA.y - VB.yt30.5FA.y + VB.ytPB.y + VB.y2t2 + VB.yt30.5FB.y
- 0.5FB.yt2PA.y - 0.5FB.yt3VA.y - 0.25FB.yt4FA.y + 0.5FB.yt2PB.y + 0.5FB.yt3VB.y + 0.25FB.y2t4
First lets simplify by grouping like terms:
D2 = PA.x2 + 2PA.xVA.xt + PA.xFA.xt2 - 2PA.xPB.x - 2PA.xVB.xt - PA.xFB.xt2
+ VA.x2t2 + VA.xFA.xt3 - 2VA.xPB.xt - 2VA.xVB.xt2 - VA.xFB.xt3
+ 0.25FA.x2t4 - FA.xPB.xt2 - FA.xVB.xt3 - 0.5FA.xFB.xt4
+ PB.x2 + 2PB.xVB.xt + PB.xFB.xt2
+ VB.x2t2 + VB.xFB.xt3
+ 0.25FB.x2t4
+ PA.y2 + 2PA.yVA.yt + PA.yFA.yt2 - 2PA.yPB.y - 2PA.yVB.yt - PA.yFB.yt2
+ VA.y2t2 + VA.yFA.yt3 - 2VA.yPB.yt - 2VA.yVB.yt2 - VA.yFB.yt3
+ 0.25FA.y2t4 - FA.yPB.yt - FA.yVB.yt2 - 0.5FA.yFB.yt4
+ PB.y2 + 2PB.yVB.yt + PB.yFB.yt2
+ VB.y2t2 + VB.yFB.yt3
+ 0.25FB.y2t4
Now lets rewrite in Quartic (biquadratic) form:
(0.25FA.x2 - 0.5FA.xFB.x + 0.25FB.x2 + 0.25FA.y2 - 0.5FA.yFB.y + 0.25FB.y2)t4 +
(VA.xFA.x - VA.xFB.x - FA.xVB.x + VB.xFB.x + VA.yFA.y - VA.yFB.y - FA.yFB.y - FA.yVB.y + VB.yFB.y)t3 +
(PA.xFA.x - PA.xFB.x + VA.x2 - 2VA.xVB.x - FA.xPB.x + PB.xFB.x + VB.x2 + PA.yFA.y - PA.yFA.y - PA.yFB.y + VA.y2 - 2VA.yVB.y - FA.yPB.y + PB.yFB.y + VB.y2)t2 +
(2PA.xVA.x - 2PA.xVB.x - 2VA.xPB.x + 2PB.xVB.x + 2PA.yVA.y - 2PA.yVB.y - 2VA.yPB.y + 2PB.yVB.y)t +
(PA.x2 - 2PA.xPB.x + PB.x2 + PA.y2 - 2PA.yPB.y + PB.y2 - D2) = 0
We can make the following substitutions to pretty up our equation:
a = 0.25FA.x2 - 0.5FA.xFB.x + 0.25FB.x2 + 0.25FA.y2 - 0.5FA.yFB.y + 0.25FB.y2
b = VA.xFA.x - VA.xFB.x - FA.xVB.x + VB.xFB.x + VA.yFA.y - VA.yFB.y - FA.yFB.y - FA.yVB.y + VB.yFB.y
c = PA.xFA.x - PA.xFB.x + VA.x2 - 2VA.xVB.x - FA.xPB.x + PB.xFB.x + VB.x2 + PA.yFA.y - PA.yFA.y - PA.yFB.y + VA.y2 - 2VA.yVB.y - FA.yPB.y + PB.yFB.y + VB.y2
d = 2PA.xVA.x - 2PA.xVB.x - 2VA.xPB.x + 2PB.xVB.x + 2PA.yVA.y - 2PA.yVB.y - 2VA.yPB.y + 2PB.yVB.y
e = PA.x2 - 2PA.xPB.x + PB.x2 + PA.y2 - 2PA.yPB.y + PB.y2 - D2
We can divide the co-efficient of t4 into all terms to eliminate it. We will do this with some more substitutions:
g = b/a
h = c/a
i = d/a
j = e/a
After the substitutions our equation is in the following form:
t4 + gt3 + ht2 + it + j = 0
To find the times that the collision occurs we must find the roots of this equation. There is an algorithm for finding the roots of a quartic equation which I will apply here.
First we must rewrite it as its resolvent cubic equation and solve for one of the real roots. We can do this like so:
y3 - hy2 + (gi - 4j)y - g2j + 4hj - i2 = 0
We can make some substitutions to pretty this up:
k = -h
m = gi - 4j
n = -g2j + 4hj - i2
This gives us the form:
y3 + ky2 + my + n = 0
Now we apply the method to solve cubic equations which requires us to rewrite this equation yet again in the following form:
x3 + px + q = 0
Where x = y + k/3, p = (1/3)(3m - k2), q = (1/27)(2k3 - 9km + 27n)
We now calculate 2 values r and s like so:
The roots of this cubic equation are then:
x = r + s
x = -((r + s) / 2) + ((r + s) / 2)sqr(-3)
x = -((r + s) / 2) + ((r - s) / 2)sqr(-3)
At least one of these roots must be real. Find any real root and use it to calculate y. Recall:
y = x - (k / 3)
Now we calculate a value u:
u = sqr((g2 / 4) - h + y)
Now we calculate 2 values w and z. The forumulas used depend on the value of u.
If u != 0 then
w = sqr(((3g2) / 4) - u2 - 2h + ((4gh - 8i - g3) / 4u))
z = sqr(((3g2) / 4) - u2 - 2h - ((4gh - 8i - g3) / 4u))
If u = 0 then
w = sqr(((3g2) / 4) - 2h + 2sqr(y2 - 4j))
z = sqr(((3g2) / 4) - 2h - 2sqr(y2 - 4j))
The roots of our quartic equation are given by:
t = -(g / 4) + (u / 2) +/- (w / 2)
t = -(g / 4) - (u / 2) +/- (z / 2)
This will give us between 0 and 4 distinct roots. We have to eliminate some of them. We can calculate the time at which the ball will stop moving due to friction:
tf = - v / f
We can now throw away any roots that don't satisfy 0 <= t < tf
We should be left with at most 2 real roots.
If there are 0 or 1 real roots then no collision occurs.
If there are 2 distinct real roots then the collision occurs at the smaller of the 2 roots.