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/dist/output.wasm | Bin 57485 -> 57700 bytes 2d/_collisions/polygon_polygon/main.cpp | 27 ++++++------ 2d/_collisions/polygon_polygon/snippet1.cpp | 52 ++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 2d/_collisions/polygon_polygon/snippet1.cpp (limited to '2d/_collisions/polygon_polygon') 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; +} -- cgit v1.2.1