From 0f2fd45969be658ecb3d371eaf93f76d2d82c994 Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Thu, 6 May 2021 20:35:19 -0400 Subject: Semi-decent wall collisions, just for fun --- frontend/2d/_collisions/rectangle_rectangle.html | 1 + .../_collisions/rectangle_rectangle.html.content | 1 + .../rectangle_rectangle/dist/output.wasm | Bin 51583 -> 55475 bytes .../2d/_collisions/rectangle_rectangle/main.cpp | 68 +++++++++++++++++++-- 4 files changed, 64 insertions(+), 6 deletions(-) (limited to 'frontend/2d') diff --git a/frontend/2d/_collisions/rectangle_rectangle.html b/frontend/2d/_collisions/rectangle_rectangle.html index 8b10ab6..51cac77 100644 --- a/frontend/2d/_collisions/rectangle_rectangle.html +++ b/frontend/2d/_collisions/rectangle_rectangle.html @@ -120,6 +120,7 @@ Vector2 getNormalToLineSegment(LineSegment* segment) {

References

diff --git a/frontend/2d/_collisions/rectangle_rectangle.html.content b/frontend/2d/_collisions/rectangle_rectangle.html.content index b994f45..2cc5847 100644 --- a/frontend/2d/_collisions/rectangle_rectangle.html.content +++ b/frontend/2d/_collisions/rectangle_rectangle.html.content @@ -70,6 +70,7 @@ Vector2 getNormalToLineSegment(LineSegment* segment) {

References

diff --git a/frontend/2d/_collisions/rectangle_rectangle/dist/output.wasm b/frontend/2d/_collisions/rectangle_rectangle/dist/output.wasm index c13cd15..66f6ab8 100755 Binary files a/frontend/2d/_collisions/rectangle_rectangle/dist/output.wasm and b/frontend/2d/_collisions/rectangle_rectangle/dist/output.wasm differ diff --git a/frontend/2d/_collisions/rectangle_rectangle/main.cpp b/frontend/2d/_collisions/rectangle_rectangle/main.cpp index 6b7b8dd..9f6db62 100644 --- a/frontend/2d/_collisions/rectangle_rectangle/main.cpp +++ b/frontend/2d/_collisions/rectangle_rectangle/main.cpp @@ -112,6 +112,19 @@ struct Rectangle { body = previousBody; } + Vector2 getPoint(int index) { + switch (index) { + case 0: return shape.model * Vector2 { -width / 2.f, -height / 2.f }; + case 1: return shape.model * Vector2 { -width / 2.f, height / 2.f }; + case 2: return shape.model * Vector2 { width / 2.f, height / 2.f }; + case 3: return shape.model * Vector2 { width / 2.f, -height / 2.f }; + default: { + printf("Unable to find point: index=%d", index); + return Vector2(); + } + } + } + // Note that these getters are needlessly verbose for demonstration's sake void getPoints(Vector2* pointList) { Vector2 botLeft = shape.model * Vector2 { -width / 2.f, -height / 2.f }; @@ -148,7 +161,6 @@ struct Rectangle { } }; - EM_BOOL onPlayClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); @@ -236,6 +248,8 @@ IntersectionResult getIntersection(Rectangle* first, Rectangle* second) { float32 minOverlap = FLT_MAX; Vector2 minOverlapAxis; + bool minOverlapAxisIsFromFirstRectangle = true; + for (int i = 0; i < 4; i++) { Vector2 normal = firstNormals[i]; @@ -251,6 +265,7 @@ IntersectionResult getIntersection(Rectangle* first, Rectangle* second) { if (overlap < minOverlap) { minOverlap = overlap; minOverlapAxis = normal; + minOverlapAxisIsFromFirstRectangle = true; } } @@ -268,6 +283,7 @@ IntersectionResult getIntersection(Rectangle* first, Rectangle* second) { if (overlap < minOverlap) { minOverlap = overlap; minOverlapAxis = normal; + minOverlapAxisIsFromFirstRectangle = false; } } @@ -275,6 +291,29 @@ IntersectionResult getIntersection(Rectangle* first, Rectangle* second) { ir.relativeVelocity = first->body.velocity - second->body.velocity; ir.collisionNormal = minOverlapAxis; + // Find the point of collision, this is kind of tricky, and it is just an approximation for now. + // At this point, we know that we intersected along the minOverlapAxis, but we do not know where + // that exactly happened. To remedy this will, we create two parallel lines: one at the top of the + // normal area, and one at the bottom. For point on both of the Rectangles, we will check: + // (1) if it is between these two planes + // (2) if, for that rectangle, it is the closest point to the original normal vector + // (3) or if it is equally distant from normal vector as another point (then this is a "flat" collision) + // + // The collision point MUST be between these two planes. We can then say the corner/face of the non-monoverlapAxis + // Rectangle is the collision point. This enables us to then solve for their respective points of application fairly + // easily. If the collision "point" is an entire face, we make the collision point be the center point. + // + Vector2 topPlane; + Vector2 bottomPlane; + + for (int p = 0; p < 4; p++) { + Vector2 point = minOverlapAxisIsFromFirstRectangle ? first->getPoint(p) : second->getPoint(p); + + } + + ir.firstPointOfApplication = Vector2(); + ir.secondPointOfApplication = Vector2(); + return ir; } @@ -289,14 +328,14 @@ void resolveCollision(Rigidbody* first, Rigidbody* second, IntersectionResult* i float32 cofOfRestition = (first->cofOfRestition + second->cofOfRestition) / 2.f; float32 numerator = (relativeVelocity * (-1 * (1.f + cofOfRestition))).dot(collisionNormal); float32 linearDenomPart = collisionNormal.dot(collisionNormal * (1.f / first->mass + 1.f / second->mass)); - //float32 rotationalDenomPart = (firstPerpNorm * firstPerpNorm) / first->momentOfInertia + (sndPerpNorm * sndPerpNorm) / second->momentOfInertia; + float32 rotationalDenomPart = (firstPerpNorm * firstPerpNorm) / first->momentOfInertia + (sndPerpNorm * sndPerpNorm) / second->momentOfInertia; - 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) { @@ -305,7 +344,7 @@ void update(float32 deltaTimeSeconds, void* userData) { rectangleList[r].update(deltaTimeSeconds); } - // Check collisions + // Check collisions with other rectangles for (int i = 0; i < 4; i++) { Rectangle* first = &rectangleList[i]; for (int j = i + 1; j < 4; j++) { @@ -348,6 +387,23 @@ void update(float32 deltaTimeSeconds, void* userData) { second->update(frameTimeRemaining); } } + + // Check collisions with walls + for (int r = 0; r < 4; r++) { + Rectangle* rect = &rectangleList[r]; + if (rect->body.position.x <= 0.f) { + rect->body.velocity = rect->body.velocity - Vector2 { 1.f, 0.f } * (2 * (rect->body.velocity.dot(Vector2 { 1.f, 0.f }))); + } + if (rect->body.position.y <= 0.f) { + rect->body.velocity = rect->body.velocity - Vector2 { 0.f, 1.f } * (2 * (rect->body.velocity.dot(Vector2 { 0.f, 1.f }))); + } + if (rect->body.position.x >= 640.f) { + rect->body.velocity = rect->body.velocity - Vector2 { -1.f, 0.f } * (2 * (rect->body.velocity.dot(Vector2{ -1.f, 0.f }))); + } + if (rect->body.position.y >= 480.f) { + rect->body.velocity = rect->body.velocity - Vector2 { 0.f, -1.f } * (2 * (rect->body.velocity.dot(Vector2 { 0.f, -1.f }))) ; + } + } // Renderer renderer.render(); -- cgit v1.2.1