I want to know an approximate 3D position and 3D normal of collision site between two 3D convex hulls (A
vs B
).
The CPU in parenthesis shows relative CPU-time needed in my finished program.
Part 1: Early-out (CPU 1%)
In the first step, I use a very cheap algorithm - separation axis theorem.
For example, I use 15 axis for 2 cubes. (In real cases, the shapes are more complex.)
If there is at least 1 axis that can separate, return "no-collide"
.
Otherwise, do the next part.
Part 2: Vertex vs Volume (CPU 10%)
- Check every vertices of
A
- whether it is insideB
. - Check every vertices of
B
- whether it is insideA
.
Part 3: Edge vs Edge (CPU >20%)
There is a strange case e.g. https://gamedev.stackexchange.com/questions/75437/collision-detection-3d-rectangles-using-sat . I stole the image from there:-
Thus, I also need edge vs edge.
- For every pair of A & B edges (12 * 12 = 144 pairs), find a nearest point in edge of
A
against the edge ofB
. Check whether the vertex is insideB
. - (vice versa) For every pair of B & A edges, check whether such vertex is inside
A
.
Wow, that is a lot of computation.
However, it is not over yet.
Problem
The reported collision position is not so accurate (left:current , right:wish) :-
To solve it, I thought about generating a new convex shape =
A intersect B
.
There are some C++ free libraries out there (e.g. OpenMesh), but I think it is too CPU-expensive.
Note that I don't need it to be precisely correct.It also sometimes reports wrong normal (left:current , right:wish) :-
^ This problem might be solved by adding edge (of A) vs face (of B) check, but that would make the whole collision detection even more expensive.
Question
It looks like common algorithms in the internet (from which I copy) recognizes only micro feature.
IMHO, the vertex-volume/edge-edge algorithm focus on topology rather that the fact that both shapes are solid volumes.
What is the algorithm that is more accurate (1st priority) and perhaps cheaper?
My approach might be wrong at the foundation level.
To speed things up, I already did some pruning e.g. select only pair of edge A & B that is close together.
References :-
Algorithms for Collision Detection between Arbitrarily sized Convex Polygons checks only whether collision occurs.
https://pybullet.org/Bullet/BulletFull/btBoxBoxDetector_8cpp_source.html : inspiring full code of box vs box collision detection in Bullet Physics library - it is hard to understand.
https://math.stackexchange.com/questions/397413/determine-direction-of-minimum-overlap-of-convex-polygons Unanswered Math question that is very similar to this.
Edit (10 days later)
Now, I can find all intersecting convex point (the convex is depicted as a pink triangle/rectangle) :-
Here is how I find the normal.
For-each separating axis (all=15 axis), I project the pink convex on to the axis.
The axis that yields the shortest projection distance (pink arrow) should be the direction of normal.
My above assumption is often correct (e.g. left), but sometimes wrong (e.g. right).
How to improve it CPU-cheaply?