Finished collision detection

This commit is contained in:
Karma Riuk 2023-06-13 13:44:11 +02:00
parent 26545bd50d
commit db3e1eb850
3 changed files with 142 additions and 5 deletions

Binary file not shown.

View File

@ -4,6 +4,7 @@
\usepackage[]{url}
\usepackage[]{subcaption}
\usepackage[]{float}
\usepackage[]{multicol}
\usepackage{tikz}
\usepackage{tkz-euclide}
@ -66,6 +67,8 @@
}
\counterwithin{figure}{section}
\counterwithin{equation}{section}
\usepackage{subfiles} % Best loaded last in the preamble

View File

@ -306,12 +306,12 @@ orthogonal axes.
\centering
\inputtikz[.7]{SAT_mvp}
\caption{SAT: Minimum push vector $\vec v_i$ on axis defined by $\vec o_i$,
orthogonal to edge $i$}
orthogonal to edge $e_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
(orthogonal to edge $e_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.
@ -320,11 +320,145 @@ 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.
algorithm of our own. Moreover, SAT only supports convex polygons, which limits
the original objective of the project, which was to have any arbitrary polygon.
\subsubsection{Vertex collisions}
The solution that was adopted for the project, after trying SAT, was a more
intuitive one, developed by Prof. Carzaniga. The idea is simple: check if a
vertex of a polygon is colliding with an edge of another polygon.
\begin{figure}[H]
\centering
\inputtikz[.5]{vertex_intro}
\caption{Vertex-edge collision between polygons $A$ and $B$}
\label{fig:vertex-edge}
\end{figure}
If we have a polygon defined as a set of points $P \subset \mathbb{R}^2$, we
define a vertex as a pair of segments $\left(\overline{V_{i-1}V_i},
\overline{V_{i+1}V_i}\right)$. To check if vertex $V_i$ of polygon $A$ is inside
polygon $B$, we just check if the both segments $\overline{V_{i-1}V_i}$ and
$\overline{V_{i+1}V_i}$ intersect edge $e_j$. If such is the case, we know that
$V_i$ is inside, and we can use it as impact point. We can now take the vector
perpendicular to the edge $e_j$ and normalize it, which is the normal we need
for the collision resolution.
\paragraph{Edge cases} With this approach (and many other collision detection
algorithms), it is easy to see that the case described in the Figure
\ref{fig:vertex-edge} is only a general one. It will ultimately happen most
often, but there are especially two edge cases that are note-worthy and occurred
during the simulation a greater number of times than expected.
\paragraph{Parallel collision} Parallel collision occur when two edge collide
with each other, an example can be seen in Figure \ref{fig:vertex-parallel}.
This collision does not get detected by the vertex-edge detection method because
the edge of $A$ parallel to the edge of $B$ do not collide, since they are
parallel.
\begin{figure}[H]
\centering
\inputtikz[.5]{vertex_parallel}
\caption{Parallel edges collision between polygons $A$ and $B$}
\label{fig:vertex-parallel}
\end{figure}
To determine if polygon $A$ is having a parallel collision with polygon $B$ we
check if only the segment $\overline{V_{i-1}V_i}$ intersects with edge $e_j$ and
if the segment $\overline{V_{i+1}V_i}$ is parallel to edge $e_j$.
To find the impact point, we first need to find the minimum overlap between the
parallel edges. We can calculate it by projecting the points that make the
parallel edges of $A$ and $B$ on the axis generated by the edge of $A$ (c.f.
Figure \ref{fig:parallel-impact}).Finally, the impact point, is the midpoint of
the said overlap.
\begin{figure}[H]
\centering
\begin{subfigure}[]{.5\textwidth}
\centering
\inputtikz[.7]{vertex_parallel_full}
\caption{Edge fully contained by other edge}
\end{subfigure}
\begin{subfigure}[]{.49\textwidth}
\centering
\inputtikz[.7]{vertex_parallel_partial}
\caption{Edge partly contained by other edge}
\end{subfigure}
\caption{Parallel collision, finding the impact point}
\label{fig:parallel-impact}
\end{figure}
The normal vector is given in the same way as the vertex-edge collision, i.e.
taking the perpendicular vector to~$e_j$ and normalizing it.
% TODO: ask Carza about the possibility of resolving vertex-vertex normal with SAT
\paragraph{Vertex on vertex collision} These collision happen when, at the
moment of the frame, two polygons are "inside each other", i.e. they both have
have a vertex present inside the area of the other polygon, as shown in Figure
\ref{fig:vertex-vertex}.
\begin{figure}[H]
\centering
\inputtikz[.5]{vertex_vertex}
\caption{Vertex on vertex collision between polygons $A$ and $B$}
\label{fig:vertex-vertex}
\end{figure}
\noindent
Two problems arise when trying to deal with this edge case:
\begin{enumerate}
\item determining which of the two vertices we chose as the impact point;
\label{itm:impact}
\item determining what normal vector.
\label{itm:normal}
\end{enumerate}
% \noindent
For point \ref{itm:impact}, it actually doesn't really matter. What is
represented in Figures~\ref{fig:vertex-edge}-\ref{fig:vertex-vertex} are an
over exaggeration of what happens in the engine. Since the time delta between
two frames is so small, the collisions look more like what is in
Figure~\ref{fig:real-vertex-vertex}, where the concerned vertices are located
practically in the same spot, and the difference is negligible. So for convenience
with the general vertex-edge case, we will take the vertex of $A$ being inside
$B$ as the impact point.
For point \ref{itm:normal}, that's where the real problem of the edge case
occur. We are unable to determine what vectors is supposed to be the normal
vector. One might say "just take the vector that goes from the vertex of $A$
(that is inside $B$) to the one of $B$ (that is inside $A$)", but it doesn't
work out in general. It works (kind of) when we have non-rotating objects going
straight at each other, but as soon as you have rotational motion, this
reasoning collapses. The solution that was decided (together with advisor Prof.
Carzaniga) was to treat the collision as a vertex-edge collision, and choosing
whatever the first edge of $B$ comes up first in the calculations as the edge to
find the normal. The results look realistic enough to be accepted.
\begin{figure}[H]
\centering
\begin{subfigure}[]{.33\textwidth}
\centering
\inputtikz[.7]{vertex_edge_real}
\caption{Realistic vertex-edge collision}
\end{subfigure}
\begin{subfigure}[]{.32\textwidth}
\centering
\inputtikz[.7]{vertex_parallel_real}
\caption{Realistic edge-edge collision}
\end{subfigure}
\begin{subfigure}[]{.34\textwidth}
\centering
\inputtikz[.7]{vertex_vertex_real}
\caption{Realistic vertex-vertex collision}
\label{fig:real-vertex-vertex}
\end{subfigure}
\caption{Realistic collisions}
\label{fig:real-collisions}
\end{figure}
\subsection{Collision resolution}
\label{sub:resolution}
\subsubsection{Physics}
\subsubsection{Solving for the impulse parameter}