Hello and welcome to my bit on #altdevblogaday!
This one is just a short introductory post for an article on the basics of Collision Detection that I posted on my own blog, which you can read here…
Circle vs Capsule
Rather than just leave you with a link, I wanted to explore one simple test that I didn’t get time to describe in my own blog post, which is Circle vs Capsule (or sphere vs capsule in 3d).
This one relies on a certain amount of understanding about projection and in particular the dot product operator. What we actually want to calculate is the clostest distance between the centre of the circle and the line which represents the axis of the capsule. We can do this by projecting the centre of the circle onto the axis and then checking this distance to see if its smaller than the sum of the radii of the two shapes:
Capsule defined by its centre point C, unit axis A, length m and radius r1. Circle defined by its centre H and radius r2.
Firstly, we must form the capsule end-points:
P0 = C – A*(m/2)
P1 = C + A*(m/2)
Get vector from end-point to circle:
D = H – P0
Project vector onto axis:
b = D . A
In Figure 1 you can see the progress so far, we’re nearly there, but the projection b needs to be clamped against the extents of the axis: 0 and m.
b = clamp(b, 0, m)
Get point on axis:
R = P0 + A*b
Distance from point on axis to circle:
d = ||H-R||
You might now recognise this as the plain circle vs circle test. The test for intersection is therefore:
||H-R|| < (r1+r2)
We can find the measure of penetration in the same way:
p = ||H-R|| – (r1+r2)
The circle and capsule penetrate by p units and we can find the contact normal:
N = (H-R) / ||H-R||
This test is actually quite useful and extends into 3d directly with no extra work. For more common collision detection tests and descriptions, please have a look at my blog article where you will find such gems as the first interactive, on-line tutorial covering the conservative advancement technique for detecting collision between moving/rotating polygons.
Until next time, have fun!