Written Collision detection: SAT

This commit is contained in:
Karma Riuk 2023-06-07 11:59:25 +02:00
parent 4c072dce3e
commit c6f845dc83
6 changed files with 172 additions and 1 deletions

Binary file not shown.

BIN
figures/SAT_intro.pdf Normal file

Binary file not shown.

BIN
figures/SAT_mvp.pdf Normal file

Binary file not shown.

View File

@ -264,11 +264,67 @@ to the overall polygon.
where, $P_{n+1} = P_1$ in the case of $i = n$. where, $P_{n+1} = P_1$ in the case of $i = n$.
\subsection{Collision detection} \subsection{Collision detection}
Collision detection, as the name suggests, are the algorithms used to detect
whether two polygons are colliding. The result of this procedure must be an
impact point and a normal vector, that will then be used for the collision
resolution \ref{sub:resolution}.
\subsubsection{Separating Axis Theorem} \subsubsection{Separating Axis Theorem}
This algorithm was the first one studied for this project and was inspired by
the works of David Eberly \cite{convexcollisionsSAT}. The separating axis
theorem (SAT) states that if you can draw a line between two convex objects,
they do not overlap. We will call this line a \textit{separating line}. More
technically, two convex shapes do not overlap if there exists an axis onto which
the two objects' projections do not overlap. We'll call this axis a \textit{separating
axis}. This concept can be visualized in Figure \ref{fig:SAT-intro}.
\begin{figure}[H]
\centering
\inputtikz[.7]{SAT_intro}
\caption{SAT: Separating axis ($A$) vs non-separating axis ($B$), with
separating line ($C$)}
\label{fig:SAT-intro}
\end{figure}
As we can see in Figure \ref{fig:SAT-intro}, the axis $B$ show that the
projections of the both polygons overlap, but we were able to find an axis $A$
where this is not the case. As soon as we find an axis for which the projections
do not overlap, it means that the polygons are not colliding. For 2D objects, we
only need to consider the axes that are orthogonal to each edge. In Figure
\ref{fig:SAT-intro}, only two of those axes are shown for better readability,
but they would be 7, one for each edge.
To move (or push) one polygon away from the other, we also need to find a vector
that, when added to the polygons position, will make the shapes not overlap. We
want the minimum displacement possible, We'll call this vector the minimum push
vector (MPV). For 2-dimensional polygons, this vector will lie in some of the
orthogonal axes.
\begin{figure}[H]
\centering
\inputtikz[.7]{SAT_mvp}
\caption{SAT: Minimum push vector $\vec v_i$ on axis defined by $\vec o_i$,
orthogonal to edge $i$}
\label{fig:SAT-mpv}
\end{figure}
The candidate MPVs $\vec v_i$ are the vectors that define the axis $\vec o_i$
(orthogonal to edge $i$), with $\| \vec o_i \| = 1$, multiplied by the minimum
overlap between the two polygons, as shown in \ref{fig:SAT-mpv}. The final MPV
is simply the $\vec v_i$ with the smallest norm.
\paragraph{Pitfalls of SAT} The issue with the SAT algorithm is that although it
is good to find whether two polygons are colliding and the MPV, it isn't trivial
to gather the point of impact, i.e. the vertex that is penetrating the other
polygon. It is doable, but during the implementation, it came with some caveats
that introduced some bugs, so we decided to switch strategy and go with an
algorithm of our own.
\subsubsection{Vertex collisions} \subsubsection{Vertex collisions}
\subsection{Collision resolution} \subsection{Collision resolution}
\label{sub:resolution} \label{sub:resolution}
\cite{collision:resolution}
\subsubsection{Physics} \subsubsection{Physics}
\subsubsection{Solving for the impulse parameter} \subsubsection{Solving for the impulse parameter}

70
tikzs/SAT_intro.tikz Normal file
View File

@ -0,0 +1,70 @@
\begin{tikzpicture}
\begin{pgfonlayer}{nodelayer}
\node [style=none] (46) at (11.416, 10.2774) {};
\node [style=none] (43) at (13.8776, 6.58504) {};
\node [style=none] (34) at (6.53846, 16.6923) {};
\node [style=none] (0) at (-2, -1) {};
\node [style=none] (1) at (2.25, 3.5) {};
\node [style=none] (3) at (-8, 7) {};
\node [style=none] (4) at (-8, -2) {};
\node [style=none] (5) at (8, 8) {};
\node [style=none] (6) at (5, 6) {};
\node [style=none] (7) at (10, 4) {};
\node [style=none] (8) at (-9, -5) {};
\node [style=none] (9) at (13, -5) {};
\node [style=none] (10) at (-8, -5) {};
\node [style=none] (11) at (-8, -4.5) {};
\node [style=none] (12) at (-7.5, -5) {};
\node [style=none] (13) at (-7.5, -4.5) {};
\node [style=none] (14) at (2.25, -5) {};
\node [style=none] (15) at (10, -5) {};
\node [style=none] (16) at (5, -5) {};
\node [style=none] (17) at (-8, -5.25) {};
\node [style=none] (18) at (2.25, -5.25) {};
\node [style=none] (19) at (10, -5.25) {};
\node [style=none] (20) at (5, -5.25) {};
\node [style=none] (21) at (-9.75, -5.5) {\Huge$A$};
\node [style=none] (22) at (11, 10) {};
\node [style=none] (27) at (17, 1) {};
\node [style=none] (28) at (5, 19) {};
\node [style=none] (32) at (10.625, 9.75) {};
\node [style=none] (33) at (11.25, 9.625) {};
\node [style=none] (31) at (10.875, 9.375) {};
\node [style=none] (35) at (12.0769, 8.38462) {};
\node [style=none] (40) at (6.74647, 16.831) {};
\node [style=none] (41) at (12.2849, 8.52329) {};
\node [style=none] (42) at (13.4615, 6.30769) {};
\node [style=none] (47) at (4.25, 19.25) {\Huge$B$};
\node [style=none] (48) at (3.5, 10) {};
\node [style=none] (49) at (3.5, -6) {};
\node [style=none] (50) at (2.75, 10) {\Huge$C$};
\end{pgfonlayer}
\begin{pgfonlayer}{edgelayer}
\draw [style=Very thick] (3.center) to (4.center);
\draw (4.center) to (0.center);
\draw (0.center) to (1.center);
\draw (6.center) to (7.center);
\draw (7.center) to (5.center);
\draw [style=Very thick] (5.center) to (6.center);
\draw (1.center) to (3.center);
\draw (8.center) to (9.center);
\draw [style=Dashed] (4.center) to (10.center);
\draw (11.center) to (13.center);
\draw (13.center) to (12.center);
\draw [style=Dashed] (1.center) to (14.center);
\draw [style=Dashed] (6.center) to (16.center);
\draw [style=Dashed] (15.center) to (7.center);
\draw [style=Very thick] (17.center) to (18.center);
\draw [style=Very thick] (20.center) to (19.center);
\draw (28.center) to (27.center);
\draw [style=Dashed] (5.center) to (22.center);
\draw (32.center) to (31.center);
\draw (33.center) to (31.center);
\draw [style=Dashed] (3.center) to (34.center);
\draw [style=Dashed] (0.center) to (35.center);
\draw [style=Very thick] (40.center) to (41.center);
\draw [style=Dashed] (7.center) to (42.center);
\draw [style=Very thick] (46.center) to (43.center);
\draw [style=Very thick] (48.center) to (49.center);
\end{pgfonlayer}
\end{tikzpicture}

45
tikzs/SAT_mvp.tikz Normal file
View File

@ -0,0 +1,45 @@
\begin{tikzpicture}
\begin{pgfonlayer}{nodelayer}
\node [style=none] (1) at (-2, 4) {};
\node [style=none] (2) at (4.5, 0) {};
\node [style=none] (3) at (-1, -2) {};
\node [style=none] (4) at (4, 3) {};
\node [style=none] (5) at (2, -3) {};
\node [style=none] (6) at (8, -2) {};
\node [style=none] (7) at (8, 0) {};
\node [style=none] (8) at (5, 6) {};
\node [style=none] (9) at (-4, 9) {};
\node [style=none] (10) at (14, 3) {};
\node [style=none] (11) at (10.1, 4.3) {};
\node [style=none] (12) at (6.35, 5.55) {};
\node [style=none] (13) at (-0.7, 7.9) {};
\node [style=none] (14) at (-0.620943, 8.13717) {};
\node [style=none] (15) at (6.42906, 5.78717) {};
\node [style=none] (16) at (5.15811, 6.47434) {};
\node [style=none] (17) at (10.2581, 4.77434) {};
\node [style=none] (18) at (4.92094, 5.76283) {};
\node [style=none] (19) at (6.27094, 5.31283) {};
\node [style=none] (20) at (5.25, 5.25) {\Large$\vec v_i$};
\node [style=none] (21) at (-3.25, 8.75) {};
\node [style=none] (22) at (-3.75, 8.5) {\Large$\vec o_i$};
\node [style=none] (23) at (1.75, -2.75) {\Large$i$};
\end{pgfonlayer}
\begin{pgfonlayer}{edgelayer}
\draw (1.center) to (2.center);
\draw (2.center) to (3.center);
\draw [style=Very thick] (5.center) to (4.center);
\draw (4.center) to (7.center);
\draw (7.center) to (6.center);
\draw (6.center) to (5.center);
\draw (1.center) to (3.center);
\draw (9.center) to (10.center);
\draw [style=Dashed] (4.center) to (8.center);
\draw [style=Dashed] (6.center) to (11.center);
\draw [style=Dashed] (2.center) to (12.center);
\draw [style=Dashed] (1.center) to (13.center);
\draw [style=Very thick] (14.center) to (15.center);
\draw [style=Very thick] (16.center) to (17.center);
\draw [style=Vector] (18.center) to (19.center);
\draw [style=Thick Vector] (9.center) to (21.center);
\end{pgfonlayer}
\end{tikzpicture}