diff options
author | Matthew Kosarek <mattkae@protonmail.com> | 2021-06-27 15:24:07 -0400 |
---|---|---|
committer | Matthew Kosarek <mattkae@protonmail.com> | 2021-06-27 15:24:07 -0400 |
commit | 52d43a63d02e973f28aa30b768eddc042a4f155b (patch) | |
tree | 852de9a02ff9c6298c5b41dcc466786ed8af3be6 /2d/_collisions | |
parent | 28d0d84638ba1ba45696f3fa86cb18e694f280a5 (diff) |
Some minor updates to SAT explanation, and made icons work everywhere
Diffstat (limited to '2d/_collisions')
-rw-r--r-- | 2d/_collisions/polygon_polygon.html | 60 | ||||
-rw-r--r-- | 2d/_collisions/polygon_polygon.html.content | 6 | ||||
-rwxr-xr-x | 2d/_collisions/polygon_polygon/dist/output.wasm | bin | 57485 -> 57700 bytes | |||
-rw-r--r-- | 2d/_collisions/polygon_polygon/main.cpp | 27 | ||||
-rw-r--r-- | 2d/_collisions/polygon_polygon/snippet1.cpp | 52 | ||||
-rw-r--r-- | 2d/_collisions/rectangle_line.html | 2 | ||||
-rw-r--r-- | 2d/_collisions/rectangle_rectangle.html | 2 |
7 files changed, 127 insertions, 22 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 Binary files differindex a30f0c4..8e0443b 100755 --- a/2d/_collisions/polygon_polygon/dist/output.wasm +++ b/2d/_collisions/polygon_polygon/dist/output.wasm 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> |