summaryrefslogtreecommitdiff
path: root/2d
diff options
context:
space:
mode:
authorMatthew Kosarek <mattkae@protonmail.com>2021-06-27 15:24:07 -0400
committerMatthew Kosarek <mattkae@protonmail.com>2021-06-27 15:24:07 -0400
commit52d43a63d02e973f28aa30b768eddc042a4f155b (patch)
tree852de9a02ff9c6298c5b41dcc466786ed8af3be6 /2d
parent28d0d84638ba1ba45696f3fa86cb18e694f280a5 (diff)
Some minor updates to SAT explanation, and made icons work everywhere
Diffstat (limited to '2d')
-rw-r--r--2d/_collisions/polygon_polygon.html60
-rw-r--r--2d/_collisions/polygon_polygon.html.content6
-rwxr-xr-x2d/_collisions/polygon_polygon/dist/output.wasmbin57485 -> 57700 bytes
-rw-r--r--2d/_collisions/polygon_polygon/main.cpp27
-rw-r--r--2d/_collisions/polygon_polygon/snippet1.cpp52
-rw-r--r--2d/_collisions/rectangle_line.html2
-rw-r--r--2d/_collisions/rectangle_rectangle.html2
-rw-r--r--2d/rigidbody/rigidbody_1.html2
-rw-r--r--2d/rigidbody/rigidbody_2.html2
-rw-r--r--2d/rigidbody/rigidbody_3.html2
10 files changed, 130 insertions, 25 deletions
diff --git a/2d/_collisions/polygon_polygon.html b/2d/_collisions/polygon_polygon.html
index 5d360af..4c4698a 100644
--- a/2d/_collisions/polygon_polygon.html
+++ b/2d/_collisions/polygon_polygon.html
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<link rel="stylesheet" href="/index.css">
<title>Physics for Games</title>
- <link rel="shortcut icon" href="favicon/favicon.ico" type="image/x-icon">
+ <link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon">
<meta name="description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
<meta name="og:description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
</head>
@@ -159,13 +159,65 @@
<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>
+ And that is all there is to <i>finding</i> the intersection between two convex polygons. Here is the code snippet that does this if you are interested:
+
+ <pre><code><span class="code_keyword">Vector2</span> getProjection(Vector2* vertices, <span class="code_keyword">int</span> numVertices, <span class="code_keyword">Vector2</span> axis) {
+ <span class="code_comment">// Find the min and max vertex projections</span>
+ <span class="code_keyword">float32</span> min = axis.dot(vertices[0]);
+ <span class="code_keyword">float32</span> max = min;
+
+ for (int v = 1; v < numVertices; v++) {
+ <span class="code_keyword">float32</span> d = axis.dot(vertices[v]);
+
+ if (d < min) {
+ min = d;
+ } else if (d > max) {
+ max = d;
+ }
+ }
+
+ <span class="code_keyword">return</span> <span class="code_keyword">Vector2</span> { min, max };
+}
+
+<span class="code_keyword">bool</span> projectionsOverlap(Vector2 first, <span class="code_keyword">Vector2</span> second) {
+ <span class="code_keyword">return</span> first.x <= second.y && second.x <= first.y;
+}
+
+<span class="code_keyword">bool</span> doIntersect(ConvexPolygon* first, ConvexPolygon* second) {
+ IntersectionResult ir;
+
+ <span class="code_comment">// Check agaisnt the edges of the first polygon</span>
+ for (int i = 0; i < first->numVertices; i++) {
+ <span class="code_keyword">Vector2</span> normal = first->edges[i].normal;
+
+ <span class="code_keyword">Vector2</span> firstProj = getProjection(first->transformedVertices, first->numVertices, normal);
+ <span class="code_keyword">Vector2</span> secondProj = getProjection(second->transformedVertices, second->numVertices, normal);
+
+ if (!projectionsOverlap(firstProj, secondProj)) {
+ <span class="code_keyword">return</span> false;
+ }
+ }
+
+ <span class="code_comment">// Check against the edges of the second polygon</span>
+ for (int i = 0; i < second->numVertices; i++) {
+ <span class="code_keyword">Vector2</span> normal = second->edges[i].normal;
+
+ <span class="code_keyword">Vector2</span> firstProj = getProjection(first->transformedVertices, first->numVertices, normal);
+ <span class="code_keyword">Vector2</span> secondProj = getProjection(second->transformedVertices, second->numVertices, normal);
+
+ if (!projectionsOverlap(firstProj, secondProj)) {
+ <span class="code_keyword">return</span> false;
+ }
+ }
+
+ <span class="code_keyword">return</span> true;
+}
+</code></pre> </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:
+ Now that we know our objects have intersected, 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>
diff --git a/2d/_collisions/polygon_polygon.html.content b/2d/_collisions/polygon_polygon.html.content
index 7f29ae0..29c284d 100644
--- a/2d/_collisions/polygon_polygon.html.content
+++ b/2d/_collisions/polygon_polygon.html.content
@@ -107,13 +107,15 @@
<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.
+ And that is all there is to <i>finding</i> the intersection between two convex polygons. Here is the code snippet that does this if you are interested:
+
+ #SNIPPET polygon_polygon/snippet1.cpp
</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:
+ Now that we know our objects have intersected, 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>
diff --git a/2d/_collisions/polygon_polygon/dist/output.wasm b/2d/_collisions/polygon_polygon/dist/output.wasm
index a30f0c4..8e0443b 100755
--- a/2d/_collisions/polygon_polygon/dist/output.wasm
+++ b/2d/_collisions/polygon_polygon/dist/output.wasm
Binary files differ
diff --git a/2d/_collisions/polygon_polygon/main.cpp b/2d/_collisions/polygon_polygon/main.cpp
index c458299..348e8d2 100644
--- a/2d/_collisions/polygon_polygon/main.cpp
+++ b/2d/_collisions/polygon_polygon/main.cpp
@@ -34,6 +34,7 @@ struct Rigidbody {
void reset() {
numImpulses = 0;
velocity = { 0, 0 };
+ rotationalVelocity = 0.f;
}
void setMomentOfInertia(float32 moi) {
@@ -158,7 +159,7 @@ struct ConvexPolygon {
edges = new Edge[numVertices]; // This will be filled in later when we are doing our SAT calculation.
// Calculate moment of inertia
- body.setMomentOfInertia((PI * body.mass) / 2.f);
+ body.momentOfInertia = (PI * (width * height * body.mass)) / 4.f;
}
void update(float32 dtSeconds) {
@@ -223,31 +224,29 @@ void load() {
renderer.load(&context);
for (int index = 0; index < 4; index++) {
- polygons[index].width = 50.f;
- polygons[index].height = 50.f;
+ polygons[index].body.reset();
if (index == 0) {
polygons[index].body.position = { context.width / 4.f, context.height / 4.f };
polygons[index].body.velocity = { 100.f, 200.f };
polygons[index].body.mass = 2.f;
- polygons[index].body.rotationalVelocity = 0.2f;
} else if (index == 1) {
polygons[index].body.position = { context.width / 4.f, context.height * (3.f /4.f) };
polygons[index].body.velocity = { 50.f, -50.f };
polygons[index].body.mass = 4.f;
- polygons[index].body.rotationalVelocity = -0.5f;
} else if (index == 2) {
polygons[index].body.position = { context.width * (3.f / 4.f), context.height * (3.f / 4.f) };
polygons[index].body.velocity = { -100.f, -50.f };
polygons[index].body.mass = 6.f;
- polygons[index].body.rotationalVelocity = 0.9f;
} else if (index == 3) {
polygons[index].body.position = { context.width * (3.f / 4.f), context.height / 4.f };
polygons[index].body.velocity = { -150.f, 50.f };
polygons[index].body.mass = 8.f;
- polygons[index].body.rotationalVelocity = 1.4f;
}
+ polygons[index].width = (polygons[index].body.mass / 2.f) * 20.f;
+ polygons[index].height = (polygons[index].body.mass / 2.f) * 20.f;
+
polygons[index].numVertices = (index + 1) * 3;
polygons[index].color = Vector4 {
index == 0 || index == 3 ? 255.f : 0.f,
@@ -284,9 +283,9 @@ bool projectionsOverlap(Vector2 first, Vector2 second) {
}
float32 getProjectionOverlap(Vector2 first, Vector2 second) {
- float32 firstOverlap = fabs(first.x - second.y);
- float32 secondOverlap = fabs(second.x - first.y);
- return firstOverlap > secondOverlap ? secondOverlap : firstOverlap;
+ float32 e = MIN(first.y, second.y);
+ float32 f = MAX(first.x, second.x);
+ return e - f;
}
const float32 EPSILON = 1.f;
@@ -374,13 +373,12 @@ void resolveCollision(Rigidbody* first, Rigidbody* second, IntersectionResult* i
float32 linearDenomPart = collisionNormal.dot(collisionNormal * (1.f / first->mass + 1.f / second->mass));
float32 rotationalDenomPart = (firstPerpNorm * firstPerpNorm) / first->momentOfInertia + (sndPerpNorm * sndPerpNorm) / second->momentOfInertia;
- // @TODO: Most of my 2D rotational work is pretty broken. Let's ignore it for the time being;
- float32 impulseMagnitude = numerator / (linearDenomPart);// + rotationalDenomPart);
+ float32 impulseMagnitude = numerator / (linearDenomPart + rotationalDenomPart);
first->velocity = first->velocity + (collisionNormal * (impulseMagnitude / first->mass));
second->velocity = second->velocity - (collisionNormal * (impulseMagnitude / second->mass));
- // first->rotationalVelocity = first->rotationalVelocity + firstPerp.dot(collisionNormal * impulseMagnitude) / first->momentOfInertia;
- // second->rotationalVelocity = second->rotationalVelocity - secondPerp.dot(collisionNormal * impulseMagnitude) / second->momentOfInertia;
+ first->rotationalVelocity = first->rotationalVelocity + firstPerp.dot(collisionNormal * impulseMagnitude) / first->momentOfInertia;
+ second->rotationalVelocity = second->rotationalVelocity - secondPerp.dot(collisionNormal * impulseMagnitude) / second->momentOfInertia;
}
void update(float32 deltaTimeSeconds, void* userData) {
@@ -430,6 +428,7 @@ void update(float32 deltaTimeSeconds, void* userData) {
first->update(frameTimeRemaining);
second->update(frameTimeRemaining);
+ i = 0;
}
}
diff --git a/2d/_collisions/polygon_polygon/snippet1.cpp b/2d/_collisions/polygon_polygon/snippet1.cpp
new file mode 100644
index 0000000..3277cf9
--- /dev/null
+++ b/2d/_collisions/polygon_polygon/snippet1.cpp
@@ -0,0 +1,52 @@
+
+Vector2 getProjection(Vector2* vertices, int numVertices, Vector2 axis) {
+ // Find the min and max vertex projections
+ float32 min = axis.dot(vertices[0]);
+ float32 max = min;
+
+ for (int v = 1; v < numVertices; v++) {
+ float32 d = axis.dot(vertices[v]);
+
+ if (d < min) {
+ min = d;
+ } else if (d > max) {
+ max = d;
+ }
+ }
+
+ return Vector2 { min, max };
+}
+
+bool projectionsOverlap(Vector2 first, Vector2 second) {
+ return first.x <= second.y && second.x <= first.y;
+}
+
+bool doIntersect(ConvexPolygon* first, ConvexPolygon* second) {
+ IntersectionResult ir;
+
+ // Check agaisnt the edges of the first polygon
+ for (int i = 0; i < first->numVertices; i++) {
+ Vector2 normal = first->edges[i].normal;
+
+ Vector2 firstProj = getProjection(first->transformedVertices, first->numVertices, normal);
+ Vector2 secondProj = getProjection(second->transformedVertices, second->numVertices, normal);
+
+ if (!projectionsOverlap(firstProj, secondProj)) {
+ return false;
+ }
+ }
+
+ // Check against the edges of the second polygon
+ for (int i = 0; i < second->numVertices; i++) {
+ Vector2 normal = second->edges[i].normal;
+
+ Vector2 firstProj = getProjection(first->transformedVertices, first->numVertices, normal);
+ Vector2 secondProj = getProjection(second->transformedVertices, second->numVertices, normal);
+
+ if (!projectionsOverlap(firstProj, secondProj)) {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/2d/_collisions/rectangle_line.html b/2d/_collisions/rectangle_line.html
index dbaac7c..2fa5e62 100644
--- a/2d/_collisions/rectangle_line.html
+++ b/2d/_collisions/rectangle_line.html
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<link rel="stylesheet" href="/index.css">
<title>Physics for Games</title>
- <link rel="shortcut icon" href="favicon/favicon.ico" type="image/x-icon">
+ <link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon">
<meta name="description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
<meta name="og:description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
</head>
diff --git a/2d/_collisions/rectangle_rectangle.html b/2d/_collisions/rectangle_rectangle.html
index fb741fc..2cd2511 100644
--- a/2d/_collisions/rectangle_rectangle.html
+++ b/2d/_collisions/rectangle_rectangle.html
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<link rel="stylesheet" href="/index.css">
<title>Physics for Games</title>
- <link rel="shortcut icon" href="favicon/favicon.ico" type="image/x-icon">
+ <link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon">
<meta name="description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
<meta name="og:description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
</head>
diff --git a/2d/rigidbody/rigidbody_1.html b/2d/rigidbody/rigidbody_1.html
index 79fd09b..b98d292 100644
--- a/2d/rigidbody/rigidbody_1.html
+++ b/2d/rigidbody/rigidbody_1.html
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<link rel="stylesheet" href="/index.css">
<title>Physics for Games</title>
- <link rel="shortcut icon" href="favicon/favicon.ico" type="image/x-icon">
+ <link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon">
<meta name="description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
<meta name="og:description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
</head>
diff --git a/2d/rigidbody/rigidbody_2.html b/2d/rigidbody/rigidbody_2.html
index 53df782..c112c6e 100644
--- a/2d/rigidbody/rigidbody_2.html
+++ b/2d/rigidbody/rigidbody_2.html
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<link rel="stylesheet" href="/index.css">
<title>Physics for Games</title>
- <link rel="shortcut icon" href="favicon/favicon.ico" type="image/x-icon">
+ <link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon">
<meta name="description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
<meta name="og:description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
</head>
diff --git a/2d/rigidbody/rigidbody_3.html b/2d/rigidbody/rigidbody_3.html
index eab6527..83279c7 100644
--- a/2d/rigidbody/rigidbody_3.html
+++ b/2d/rigidbody/rigidbody_3.html
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<link rel="stylesheet" href="/index.css">
<title>Physics for Games</title>
- <link rel="shortcut icon" href="favicon/favicon.ico" type="image/x-icon">
+ <link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon">
<meta name="description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
<meta name="og:description" content="A place to learn all about real-time physics simulations through descriptions, code snippets, and example programs all written in C++ and OpenGL.">
</head>