summaryrefslogtreecommitdiff
path: root/2d/_collisions/polygon_polygon/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2d/_collisions/polygon_polygon/main.cpp')
-rw-r--r--2d/_collisions/polygon_polygon/main.cpp146
1 files changed, 85 insertions, 61 deletions
diff --git a/2d/_collisions/polygon_polygon/main.cpp b/2d/_collisions/polygon_polygon/main.cpp
index b7e3ce5..916a057 100644
--- a/2d/_collisions/polygon_polygon/main.cpp
+++ b/2d/_collisions/polygon_polygon/main.cpp
@@ -19,7 +19,7 @@ struct Rigidbody {
float32 rotation = 0.f;
float32 mass = 1.f;
float32 cofOfRestition = 1.f;
- float32 momentOfInertia = 0.f;
+ float32 momentOfInertia = 1.f;
void reset() {
force = { 0, 0 };
@@ -75,7 +75,14 @@ struct ConvexPolygon {
float32 width = 0.f;
float32 height = 0.f;
+ Vector2* originalVertices;
+ Vector2* transformedVertices;
+ Edge* edges;
+
void load(OrthographicRenderer* renderer) {
+ transformedVertices = new Vector2[numVertices]; // This will be used for SAT calculations later
+ originalVertices = new Vector2[numVertices];
+
// 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
@@ -83,26 +90,33 @@ struct ConvexPolygon {
// 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];
+ OrthographicVertex* shaderVertices = 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 };
+ shaderVertices[indexPosition].position = { cosf(firstAngle) * width, sinf(firstAngle) * height };
- vertices[indexPosition + 1].position = { 0.f, 0.f };
+ originalVertices[vidx] = shaderVertices[indexPosition].position;
+
+ shaderVertices[indexPosition + 1].position = { 0.f, 0.f };
float32 secondAngle = angleIncrements * (vidx + 1);
- vertices[indexPosition + 2].position = { cosf(secondAngle) * width, sinf(secondAngle) * height };
+ shaderVertices[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();
+ shaderVertices[indexPosition + subIdx].color = color.toNormalizedColor();
}
}
- shape.load(vertices, verticesNeeded, renderer);
- delete[] vertices;
+ shape.load(shaderVertices, verticesNeeded, renderer);
+ delete[] shaderVertices;
+
+ 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);
}
void update(float32 dtSeconds) {
@@ -110,18 +124,38 @@ struct ConvexPolygon {
body.update(dtSeconds);
shape.model = Mat4x4().translateByVec2(body.position).rotate2D(body.rotation);
+
+ // Populate the current position of our edges
+ for (int vidx = 0; vidx < numVertices; vidx++) {
+ Vector2 start = shape.model * originalVertices[vidx];
+ transformedVertices[vidx] = start;
+
+ Vector2 end = shape.model * originalVertices[vidx == numVertices - 1 ? 0 : vidx + 1];
+ edges[vidx] = { (end - start).getPerp().normalize(), start, end };
+ }
}
+ void restorePreviousBody() {
+ body = previousBody;
+ }
+
void render(OrthographicRenderer* renderer) {
shape.render(renderer);
}
void unload() {
shape.unload();
- }
-};
+ delete[] originalVertices;
+ originalVertices = NULL;
+ delete[] transformedVertices;
+ transformedVertices = NULL;
+
+ delete[] edges;
+ edges = NULL;
+ }
+};
EM_BOOL onPlayClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData);
EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData);
@@ -151,12 +185,24 @@ void load() {
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].numVertices = (index + 1) * 3;
@@ -168,14 +214,16 @@ void load() {
};
polygons[index].load(&renderer);
}
+
+ printf("Main loop beginning\n");
mainLoop.run(update);
}
-Vector2 getProjection(Vector2* vertices, Vector2 axis) {
+Vector2 getProjection(Vector2* vertices, int numVertices, Vector2 axis) {
float32 min = axis.dot(vertices[0]);
float32 max = min;
- for (int v = 1; v < 4; v++) {
+ for (int v = 1; v < numVertices; v++) {
float32 d = axis.dot(vertices[v]);
if (d < min) {
@@ -188,7 +236,7 @@ Vector2 getProjection(Vector2* vertices, Vector2 axis) {
return Vector2 { min, max };
}
-/*bool projectionsOverlap(Vector2 first, Vector2 second) {
+bool projectionsOverlap(Vector2 first, Vector2 second) {
return first.x <= second.y && second.x <= first.y;
}
@@ -199,30 +247,19 @@ float32 getProjectionOverlap(Vector2 first, Vector2 second) {
}
const float32 EPSILON = 1.f;
-IntersectionResult getIntersection(Rectangle* first, Po* second) {
+IntersectionResult getIntersection(ConvexPolygon* first, ConvexPolygon* 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;
+ bool minOverlapWasFirst = false;
- for (int i = 0; i < 4; i++) {
- Vector2 normal = firstEdges[i].normal;
+ for (int i = 0; i < first->numVertices; i++) {
+ Vector2 normal = first->edges[i].normal;
- Vector2 firstProj = getProjection(firstPoints, normal);
- Vector2 secondProj = getProjection(secondPoints, normal);
+ Vector2 firstProj = getProjection(first->transformedVertices, first->numVertices, normal);
+ Vector2 secondProj = getProjection(second->transformedVertices, second->numVertices, normal);
if (!projectionsOverlap(firstProj, secondProj)) {
return ir;
@@ -231,17 +268,16 @@ IntersectionResult getIntersection(Rectangle* first, Po* second) {
float32 overlap = getProjectionOverlap(firstProj, secondProj);
if (overlap < minOverlap) {
minOverlap = overlap;
- minOverlapAxis = normal;
- minOverlapEdge = &firstEdges[i];
- minOverlapWasFirstRect = true;
+ minOverlapEdge = &first->edges[i];
+ minOverlapWasFirst = true;
}
}
- for (int i = 0; i < 4; i++) {
- Vector2 normal = secondEdges[i].normal;
+ for (int i = 0; i < second->numVertices; i++) {
+ Vector2 normal = second->edges[i].normal;
- Vector2 firstProj = getProjection(firstPoints, normal);
- Vector2 secondProj = getProjection(secondPoints, normal);
+ Vector2 firstProj = getProjection(first->transformedVertices, first->numVertices, normal);
+ Vector2 secondProj = getProjection(second->transformedVertices, second->numVertices, normal);
if (!projectionsOverlap(firstProj, secondProj)) {
return ir;
@@ -250,33 +286,21 @@ IntersectionResult getIntersection(Rectangle* first, Po* second) {
float32 overlap = getProjectionOverlap(firstProj, secondProj);
if (overlap < minOverlap) {
minOverlap = overlap;
- minOverlapAxis = normal;
- minOverlapEdge = &secondEdges[i];
+ minOverlapEdge = &second->edges[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.
- //
+ ir.collisionNormal = minOverlapEdge->normal;
+ // Time to find just where we intersected
Vector2 closestPoint;
float32 minDistance = FLT_MAX;
- for (int p = 0; p < 4; p++) {
- Vector2 point = minOverlapWasFirstRect ? secondPoints[p] : firstPoints[p];
+
+ for (int p = 0; p < (minOverlapWasFirst ? second->numVertices : first->numVertices); p++) {
+ Vector2 point = minOverlapWasFirst ? second->transformedVertices[p] : first->transformedVertices[p];
float32 distFromPointToStart = (minOverlapEdge->start - point).length();
float32 distFromPointToEnd = (minOverlapEdge->end - point).length();
@@ -287,12 +311,12 @@ IntersectionResult getIntersection(Rectangle* first, Po* second) {
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;
@@ -322,10 +346,10 @@ void update(float32 deltaTimeSeconds, void* userData) {
}
// Check collisions with other rectangles
- /*for (int i = 0; i < 4; i++) {
- Rectangle* first = &rectangleList[i];
+ for (int i = 0; i < 4; i++) {
+ ConvexPolygon* first = &polygons[i];
for (int j = i + 1; j < 4; j++) {
- Rectangle* second = &rectangleList[j];
+ ConvexPolygon* second = &polygons[j];
IntersectionResult ir = getIntersection(first, second);
if (!ir.intersect) {
@@ -363,7 +387,7 @@ void update(float32 deltaTimeSeconds, void* userData) {
first->update(frameTimeRemaining);
second->update(frameTimeRemaining);
}
- }*/
+ }
// Check collisions with walls
for (int p = 0; p < 4; p++) {