summaryrefslogtreecommitdiff
path: root/frontend/2d/_collisions/polygon_polygon/main.cpp
diff options
context:
space:
mode:
authorMatthew Kosarek <mattkae@protonmail.com>2021-05-16 19:50:15 -0400
committerMatthew Kosarek <mattkae@protonmail.com>2021-05-16 19:50:15 -0400
commita00c0aab1eb5a7a55bef8ca08115bdd722ab5699 (patch)
tree45b5c4cc8c380d0630a8e0185af7229f26dc754a /frontend/2d/_collisions/polygon_polygon/main.cpp
parent4941a1874b6ca9d142d94df70b2aec5e0b35b94e (diff)
Moved the frontend directory up so that it no longer exists
Diffstat (limited to 'frontend/2d/_collisions/polygon_polygon/main.cpp')
-rw-r--r--frontend/2d/_collisions/polygon_polygon/main.cpp414
1 files changed, 0 insertions, 414 deletions
diff --git a/frontend/2d/_collisions/polygon_polygon/main.cpp b/frontend/2d/_collisions/polygon_polygon/main.cpp
deleted file mode 100644
index b7e3ce5..0000000
--- a/frontend/2d/_collisions/polygon_polygon/main.cpp
+++ /dev/null
@@ -1,414 +0,0 @@
-#include "../../../shared_cpp/OrthographicRenderer.h"
-#include "../../../shared_cpp/types.h"
-#include "../../../shared_cpp/WebglContext.h"
-#include "../../../shared_cpp/mathlib.h"
-#include "../../../shared_cpp/MainLoop.h"
-#include <cstdio>
-#include <cmath>
-#include <emscripten/html5.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <cmath>
-#include <cfloat>
-
-struct Rigidbody {
- Vector2 force = { 0, 0 };
- Vector2 velocity = { 0, 0 };
- Vector2 position = { 0, 0 };
- float32 rotationalVelocity = 0.f;
- float32 rotation = 0.f;
- float32 mass = 1.f;
- float32 cofOfRestition = 1.f;
- float32 momentOfInertia = 0.f;
-
- void reset() {
- force = { 0, 0 };
- velocity = { 0, 0 };
- rotationalVelocity = 0.f;
- rotation = 0.f;
- }
-
- void applyForce(Vector2 f) {
- force += f;
- }
-
- void applyGravity(float32 deltaTimeSeconds) {
- velocity += (Vector2 { 0.f, -50.f } * deltaTimeSeconds);
- }
-
- void update(float32 deltaTimeSeconds) {
- applyGravity(deltaTimeSeconds);
-
- Vector2 acceleration = force / mass;
- velocity += (acceleration * deltaTimeSeconds);
- position += (velocity * deltaTimeSeconds);
- force = Vector2 { 0.f, 0.f };
-
- rotation += (rotationalVelocity * deltaTimeSeconds);
- }
-
- void setMomentOfInertia(float32 moi) {
- momentOfInertia = moi;
- }
-};
-
-struct IntersectionResult {
- bool intersect = false;
- Vector2 collisionNormal;
- Vector2 relativeVelocity;
- Vector2 firstPointOfApplication;
- Vector2 secondPointOfApplication;
-};
-
-struct Edge {
- Vector2 normal;
- Vector2 start;
- Vector2 end;
-};
-
-struct ConvexPolygon {
- OrthographicShape shape;
- Rigidbody body;
- Rigidbody previousBody;
- Vector4 color;
- int32 numVertices = 3;
- float32 width = 0.f;
- float32 height = 0.f;
-
- void load(OrthographicRenderer* renderer) {
- // Generate the shape with numVertices many sides in a "fan" shape (i.e. 3 vertices per vertex)
- // The shape will have all equal sides, just to make it easier on me. Therefore, it will fit inside
- // the conditions of a circle, which is fun. Before anyone gets mad: I know I can avoid recalculating
- // a lot of these cosines and sines. I will be okay; I will live. The bigger problem with this demo
- // is the 2k lines of JavaScript that are required to display it.
- int32 verticesNeeded = numVertices * 3;
- float32 angleIncrements = (2.f * PI) / static_cast<float32>(numVertices);
- OrthographicVertex* vertices = new OrthographicVertex[verticesNeeded];
- for (int32 vidx = 0; vidx < numVertices; vidx++) {
- int32 indexPosition = vidx * 3;
-
- float32 firstAngle = angleIncrements * vidx;
- vertices[indexPosition].position = { cosf(firstAngle) * width, sinf(firstAngle) * height };
-
- vertices[indexPosition + 1].position = { 0.f, 0.f };
-
- float32 secondAngle = angleIncrements * (vidx + 1);
- vertices[indexPosition + 2].position = { cosf(secondAngle) * width, sinf(secondAngle) * height };
-
- // Apply some global stylings
- for (int subIdx = 0; subIdx < 3; subIdx++) {
- vertices[indexPosition + subIdx].color = color.toNormalizedColor();
- }
- }
-
- shape.load(vertices, verticesNeeded, renderer);
- delete[] vertices;
- }
-
- void update(float32 dtSeconds) {
- previousBody = body;
-
- body.update(dtSeconds);
- shape.model = Mat4x4().translateByVec2(body.position).rotate2D(body.rotation);
- }
-
- void render(OrthographicRenderer* renderer) {
- shape.render(renderer);
- }
-
- void unload() {
- shape.unload();
- }
-};
-
-
-
-EM_BOOL onPlayClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData);
-EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData);
-
-void load();
-void update(float32 time, void* userData);
-void unload();
-
-WebglContext context;
-OrthographicRenderer renderer;
-MainLoop mainLoop;
-ConvexPolygon polygons[4];
-
-int main() {
- context.init("#gl_canvas");
- emscripten_set_click_callback("#gl_canvas_play", NULL, false, onPlayClicked);
- emscripten_set_click_callback("#gl_canvas_stop", NULL, false, onStopClicked);
- return 0;
-}
-
-void load() {
- renderer.load(&context);
-
- for (int index = 0; index < 4; index++) {
- polygons[index].width = 50.f;
- polygons[index].height = 50.f;
-
- if (index == 0) {
- polygons[index].body.position = { context.width / 4.f, context.height / 4.f };
- } else if (index == 1) {
- polygons[index].body.position = { context.width / 4.f, context.height * (3.f /4.f) };
- } else if (index == 2) {
- polygons[index].body.position = { context.width * (3.f / 4.f), context.height * (3.f / 4.f) };
- } else if (index == 3) {
- polygons[index].body.position = { context.width * (3.f / 4.f), context.height / 4.f };
- }
-
- polygons[index].numVertices = (index + 1) * 3;
- polygons[index].color = Vector4 {
- index == 0 || index == 3 ? 255.f : 0.f,
- index == 1 || index == 3 ? 255.f : 0.f,
- index == 2 ? 255.f : 0.f,
- 255.f
- };
- polygons[index].load(&renderer);
- }
- mainLoop.run(update);
-}
-
-Vector2 getProjection(Vector2* vertices, Vector2 axis) {
- float32 min = axis.dot(vertices[0]);
- float32 max = min;
-
- for (int v = 1; v < 4; 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;
-}
-
-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;
-}
-
-const float32 EPSILON = 1.f;
-IntersectionResult getIntersection(Rectangle* first, Po* second) {
- IntersectionResult ir;
-
- // For two rectangles to overlap, it means that at least one of the corners of one is inside of the other
- Edge firstEdges[4];
- first->getEdges(firstEdges);
- Vector2 firstPoints[4];
- first->getPoints(firstPoints);
-
- Edge secondEdges[4];
- second->getEdges(secondEdges);
- Vector2 secondPoints[4];
- second->getPoints(secondPoints);
-
- float32 minOverlap = FLT_MAX;
- Vector2 minOverlapAxis;
- Edge* minOverlapEdge = NULL;
- bool minOverlapWasFirstRect = false;
-
- for (int i = 0; i < 4; i++) {
- Vector2 normal = firstEdges[i].normal;
-
- Vector2 firstProj = getProjection(firstPoints, normal);
- Vector2 secondProj = getProjection(secondPoints, normal);
-
- if (!projectionsOverlap(firstProj, secondProj)) {
- return ir;
- }
-
- float32 overlap = getProjectionOverlap(firstProj, secondProj);
- if (overlap < minOverlap) {
- minOverlap = overlap;
- minOverlapAxis = normal;
- minOverlapEdge = &firstEdges[i];
- minOverlapWasFirstRect = true;
- }
- }
-
- for (int i = 0; i < 4; i++) {
- Vector2 normal = secondEdges[i].normal;
-
- Vector2 firstProj = getProjection(firstPoints, normal);
- Vector2 secondProj = getProjection(secondPoints, normal);
-
- if (!projectionsOverlap(firstProj, secondProj)) {
- return ir;
- }
-
- float32 overlap = getProjectionOverlap(firstProj, secondProj);
- if (overlap < minOverlap) {
- minOverlap = overlap;
- minOverlapAxis = normal;
- minOverlapEdge = &secondEdges[i];
- }
- }
-
- ir.intersect = true;
- 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 closestPoint;
- float32 minDistance = FLT_MAX;
-
- for (int p = 0; p < 4; p++) {
- Vector2 point = minOverlapWasFirstRect ? secondPoints[p] : firstPoints[p];
-
- float32 distFromPointToStart = (minOverlapEdge->start - point).length();
- float32 distFromPointToEnd = (minOverlapEdge->end - point).length();
- float32 potentialMin = MIN(distFromPointToStart, distFromPointToEnd);
-
- if (potentialMin < minDistance) {
- closestPoint = point;
- minDistance = potentialMin;
- }
- }
-
- ir.firstPointOfApplication = closestPoint - first->body.position;
- ir.secondPointOfApplication = closestPoint - second->body.position;;
-
- return ir;
-}*/
-
-void resolveCollision(Rigidbody* first, Rigidbody* second, IntersectionResult* ir) {
- Vector2 relativeVelocity = ir->relativeVelocity;
- Vector2 collisionNormal = ir->collisionNormal;
- Vector2 firstPerp = ir->firstPointOfApplication.getPerp();
- Vector2 secondPerp = ir->secondPointOfApplication.getPerp();
- float32 firstPerpNorm = firstPerp.dot(collisionNormal);
- float32 sndPerpNorm = secondPerp.dot(collisionNormal);
-
- 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 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;
-}
-
-void update(float32 deltaTimeSeconds, void* userData) {
- // Update
- for (int p = 0; p < 4; p++) {
- polygons[p].update(deltaTimeSeconds);
- }
-
- // Check collisions with other rectangles
- /*for (int i = 0; i < 4; i++) {
- Rectangle* first = &rectangleList[i];
- for (int j = i + 1; j < 4; j++) {
- Rectangle* second = &rectangleList[j];
-
- IntersectionResult ir = getIntersection(first, second);
- if (!ir.intersect) {
- continue;
- }
-
- // Handle collison here
- IntersectionResult irCopy = ir;
- float32 copyDt = deltaTimeSeconds;
-
- do {
- first->restorePreviousBody();
- second->restorePreviousBody();
-
- ir = irCopy;
- copyDt = copyDt /= 2.f;
-
- first->update(copyDt);
- second->update(copyDt);
-
- irCopy = getIntersection(first, second);
-
- if (copyDt <= 0.f) {
- printf("Error: Should not be happening.\n");
- break;
- }
-
- } while (irCopy.intersect);
-
- printf("Found intersection at timestamp: %f\n", copyDt);
-
- resolveCollision(&first->body, &second->body, &ir);
- float32 frameTimeRemaining = deltaTimeSeconds - copyDt;
-
- first->update(frameTimeRemaining);
- second->update(frameTimeRemaining);
- }
- }*/
-
- // Check collisions with walls
- for (int p = 0; p < 4; p++) {
- ConvexPolygon* polygon = &polygons[p];
- if (polygon->body.position.x <= 0.f) {
- polygon->body.velocity = polygon->body.velocity - Vector2 { 1.f, 0.f } * (2 * (polygon->body.velocity.dot(Vector2 { 1.f, 0.f })));
- }
- if (polygon->body.position.y <= 0.f) {
- polygon->body.velocity = polygon->body.velocity - Vector2 { 0.f, 1.f } * (2 * (polygon->body.velocity.dot(Vector2 { 0.f, 1.f })));
- }
- if (polygon->body.position.x >= 640.f) {
- polygon->body.velocity = polygon->body.velocity - Vector2 { -1.f, 0.f } * (2 * (polygon->body.velocity.dot(Vector2{ -1.f, 0.f })));
- }
- if (polygon->body.position.y >= 480.f) {
- polygon->body.velocity = polygon->body.velocity - Vector2 { 0.f, -1.f } * (2 * (polygon->body.velocity.dot(Vector2 { 0.f, -1.f }))) ;
- }
- }
-
- // Renderer
- renderer.render();
- for (int p = 0; p < 4; p++) {
- polygons[p].render(&renderer);
- }
-}
-
-void unload() {
- mainLoop.stop();
- renderer.unload();
- for (int p = 0; p < 4; p++) {
- polygons[p].unload();
- }
-}
-
-//
-// Interactions with DOM handled below
-//
-EM_BOOL onPlayClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) {
- printf("Play clicked\n");
-
- load();
- return true;
-}
-
-EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) {
- printf("Stop clicked\n");
- unload();
- return true;
-}