From 52d43a63d02e973f28aa30b768eddc042a4f155b Mon Sep 17 00:00:00 2001
From: Matthew Kosarek
Date: Sun, 27 Jun 2021 15:24:07 -0400
Subject: Some minor updates to SAT explanation, and made icons work everywhere
---
2d/_collisions/polygon_polygon.html | 60 ++++++++++++++++++++++--
2d/_collisions/polygon_polygon.html.content | 6 ++-
2d/_collisions/polygon_polygon/dist/output.wasm | Bin 57485 -> 57700 bytes
2d/_collisions/polygon_polygon/main.cpp | 27 +++++------
2d/_collisions/polygon_polygon/snippet1.cpp | 52 ++++++++++++++++++++
2d/_collisions/rectangle_line.html | 2 +-
2d/_collisions/rectangle_rectangle.html | 2 +-
7 files changed, 127 insertions(+), 22 deletions(-)
create mode 100644 2d/_collisions/polygon_polygon/snippet1.cpp
(limited to '2d/_collisions')
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 @@
Physics for Games
-
+
@@ -159,13 +159,65 @@
If the projections overlap for each edge of both shapes, the shapes are intersecting. Return true.
- And that is all there is to finding the intersection between two convex polygons.
-
+ And that is all there is to finding the intersection between two convex polygons. Here is the code snippet that does this if you are interested:
+
+
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;
+ }
+ }
+
+ returnVector2 { 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;
+}
+
SAT Collision Resolution
- 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:
Collision Normal: in what direction, point towards object A, did the polygons intersect
Point of Application: at what point on each object did the objects first intersect
If the projections overlap for each edge of both shapes, the shapes are intersecting. Return true.
- And that is all there is to finding the intersection between two convex polygons.
+ And that is all there is to finding the intersection between two convex polygons. Here is the code snippet that does this if you are interested:
+
+ #SNIPPET polygon_polygon/snippet1.cpp
SAT Collision Resolution
- 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:
Collision Normal: in what direction, point towards object A, did the polygons intersect
Point of Application: at what point on each object did the objects first intersect
diff --git a/2d/_collisions/polygon_polygon/dist/output.wasm b/2d/_collisions/polygon_polygon/dist/output.wasm
index a30f0c4..8e0443b 100755
Binary files a/2d/_collisions/polygon_polygon/dist/output.wasm and b/2d/_collisions/polygon_polygon/dist/output.wasm 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 @@
Physics for Games
-
+
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 @@
Physics for Games
-
+
--
cgit v1.2.1