summaryrefslogtreecommitdiff
path: root/2d/_collisions/polygon_polygon.html.content
blob: 7f29ae0806a107ccd697dfcdab4a9730eb32e0e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<script src="./polygon_polygon/dist/output.js"></script>
<script>
  window.onload = function() {
      var lPlayElement = document.getElementById('gl_canvas_play'),
          lStopElement = document.getElementById('gl_canvas_stop');
      lPlayElement.addEventListener('click', function() {
          lPlayElement.style.display = 'none';
          lStopElement.style.display = 'block';
      });
      lStopElement.addEventListener('click', function() {
          lStopElement.style.display = 'none';
          lPlayElement.style.display = 'block';
      });
  }
  
</script>
<article>
  <h1>Separating Axis Theorem</h1>
  <section>
    <p>
      The Separating Axis Theorem (SAT) provides a way to find the intersection between any <i>n</i>-sided <a href='https://ianqvist.blogspot.com/2009/09/convex-polygon-based-collision.html'>convex</a> polygon or circle. In this tutorial, I will explain how this theorem works, and how you can use it to both detect and resolve collisions in your simulation.
    </p>
  </section>
  <section>
    <h2>Explanation of Separating Axis Theorem</h2>
    <p>
      SAT makes use of vector projection to figure out whether or not two concave polygons are intersecting. I believe the best way to describe it is to show you the instance where two polygons do <b>not</b> intersect. 
      
      <br/>
      <br/>

      Images two shapes <b>A</b> and <b>B</b> as shown below (they are triangles here, but they can be anything really).
      <br/>
      <br />

      <div class='image'>
        <img src="polygon_polygon/images/1.png" />
      </div>

      <br/>
      We know inutitively that if we were able to draw a line between the two objects, that means that they're not intersecting. In this case, that line is a vertical-ish line:
      <br/>
      <br />

      <div class='image'>
        <img src='polygon_polygon/images/2.png' />
      </div>

      <br/>
      That line could be any of the infinite number of lines between the objects, so we can't really select that <i>exact</i> line. So the problem becomes: how do we <i>infer</i> that the vertical line shown in the previous diagram is a line that splits the objects? That is where the Separating Axis Theorem comes in.

      <br />
      <br/>

      To do separating axis theorem, we iterate all of the edges of <b>both</b> shapes. For each edge, we get the normal at that edge (In two-dimensions, this amounts to getting the perpendicular of the line segment defined by the two points of the edge).
      <br />
      <br />

      <div class='image'>
        <img src='polygon_polygon/images/2a.png' />
      </div>

      <br />
      
      We then, in our heads, extend this normal to create an axis across our scene (keep in mind that you won't have to do any "extending" of this axis in code; the normal will do just fine).

      <div class='image'>
        <img src='polygon_polygon/images/2d.png' />
      </div>

      <br />

      At this point, you will see that I named the three vertices on each of the triangles. Triangle <b>A</b> is made of vertices <i>a1, a2, a3</i> and triangle <b>B</b> is made of vertices <i>b1, b2, b3</i>. At this point, we project the shape onto the axis. To do this, we project the vertices of each shape onto the axis to figure out which one <i>maximizes</i> the dot product and which one <i>minimizes</i> the dot product. The projection of the shape is then the range defined by this min and max value.

      <br />
      <br />
      
      <div class='image'>
        <img src='polygon_polygon/images/2e.png' />
      </div>

      <br />

      Finally, we check if the two ranges overlap. If they don't overlap, then the shapes do <b>not</b> intersect. If they do overlap, we repeat the process for all of the other edges. If all of these ranges overlap, then the shape overlaps, and there is no separating line between them. 

      <br />
      <br />
      
      <div class='image'>
        <img src='polygon_polygon/images/2f.png' />
      </div>

      <br />
      
    </p>
  </section>
  <section>
    <h2>Algorithm for Finding the Intersection</h2>
    <p>

      Given two polygons <b>A</b> and <b>B</b>:
      <ol>
        <li>For each edge on <b>A</b>, get the normal <i>n</i> of that edge.</li>
        <li>Project each vertex <i>v</i> of <b>A</b> onto <i>n</i>. Return the minimum and maximum projection of all vertices as the projection of the shape.</li>
        <li>Repeat Step 2 for polygon <b>B</b>.</li>
        <li>If the min and max projections found in Steps 2 and 3 do <b>NOT</b> overlap, the polygons are not intersecting. Return false.</li>
        <li>If the projections overlap for each edge of both shapes, the shapes are intersecting. Return true.</li>
      </ol>

      And that is all there is to <i>finding</i> the intersection between two convex polygons.
    </p>
  </section>
  <section>
    <h2>SAT Collision Resolution</h2>
    <p>
      Now that we know our objects have intersecting, we want to be able to send them tumbling away from each other to simulate a collision. To do this, we will need to find the following things:
      <ul>
        <li><b>Collision Normal</b>: in what direction, point towards object <b>A</b>, did the polygons intersect</li>
        <li><b>Point of Application</b>: at what point on each object did the objects first intersect</li>
        <li><b>Relative Velocity</b>: easily found by taking the difference between the two velocities.
      </ul>

      <h3>Collision Normal</h3>
      <p>
        
      </p>
    </p>
  </section>
  <section>
	<h2>
	  Live Example of Intersection Detection
	</h2>
    <div class="opengl_canvas_container">
      <canvas id="gl_canvas" width="800" height="600"></canvas>
      <button id="gl_canvas_play" class="play_button">
        Play
      </button>
      <button id="gl_canvas_stop" class="stop_button">
        Stop
      </button>
    </div>
  </section>
  <footer id="references">
    <h2>References</h2>
    <ul>
      <li><a href="https://en.wikipedia.org/wiki/Vector_projection">Vector Projection Wikapedia</a></li>
    </ul>
  </footer>
</article>