From e7c1e9cc3a90f3e5f638f43f21054a4032f9d9f8 Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Sun, 18 Apr 2021 11:29:56 -0400 Subject: Some more good WIP --- frontend/2d/_collisions/pill_line/dist/output.wasm | Bin 60622 -> 59663 bytes frontend/2d/_collisions/pill_line/main.cpp | 111 ++++++--------------- frontend/roadmap.html | 2 +- 3 files changed, 33 insertions(+), 80 deletions(-) diff --git a/frontend/2d/_collisions/pill_line/dist/output.wasm b/frontend/2d/_collisions/pill_line/dist/output.wasm index c671a7e..89ef8ce 100755 Binary files a/frontend/2d/_collisions/pill_line/dist/output.wasm and b/frontend/2d/_collisions/pill_line/dist/output.wasm differ diff --git a/frontend/2d/_collisions/pill_line/main.cpp b/frontend/2d/_collisions/pill_line/main.cpp index 0476b98..8700649 100644 --- a/frontend/2d/_collisions/pill_line/main.cpp +++ b/frontend/2d/_collisions/pill_line/main.cpp @@ -19,12 +19,14 @@ struct Rigidbody { float32 rotationalVelocity = 0.f; float32 rotation = 0.f; float32 mass = 1.f; - float32 cofOfRestition = 0.7f; + 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) { @@ -164,15 +166,11 @@ struct LineSegment { shape.unload(); } - bool isPointOnLine(Vector2 p) { - // If the dot product is nearly zero, that means it is in the direction of the line - if (ABS((end - start).dot(p - start)) <= 0.001) { - - // We're on the general line, now let's see if we're within the proper bounds: - return p.x >= start.x && p.x <= end.x && p.x >= start.y && p.y <= start.y; - } - - return false; + Vector2 getPointOnLine(float32 t) { + return { + start.x + (end.x - start.x) * t, + start.y + (end.y - start.y) * t, + }; } }; @@ -211,8 +209,8 @@ void load() { renderer.load(&context); pill.body.position = Vector2 { context.width / 2.f, context.height / 2.f }; - pill.body.rotationalVelocity = 0.3f; pill.load(&renderer, 64, 100.f, 50.f); + pill.body.rotationalVelocity = 0.3f; segmentList[0].load(&renderer, Vector4().fromColor(191, 251, 146, 255.f), Vector2 { 50.f, 0.f }, Vector2 { 50.f, static_cast(context.height) }); segmentList[1].load(&renderer, Vector4().fromColor(159, 224, 210, 255.f), Vector2 { context.width - 50.f, 0.f }, Vector2 { context.width - 50.f, static_cast(context.height) }); @@ -229,64 +227,13 @@ float32 areaOfTriangle(Vector2 a, Vector2 b, Vector2 c) { IntersectionResult getIntersection(Pill* pill, LineSegment* segment) { IntersectionResult result; - - /** - - Formula for finding equation of pill: - 1) Using the parametrized equation of a line: - x(t) = x1 + (x2 - x1) * t - y(t) = y1 + (y2 - y1) * t - 2) Knowing the equation of a translated and rotated ellipse: - - Define x and y as follows: - - x = x_1 + l, where l is the translation in x - y = y_1 + h, where h is the translation in y - - Therefore, the general equation of a rotated ellipse is: - - (x * cos(theta) + y * sin(theta)) / (a * a) - + (y * cos(theta) - x * sin(theta)) / b * b = 1 - - ( + l + x * cos(theta) + y * sin(theta)) / (a * a) - + (y + h + y * cos(theta) + y * sin(theta)) / (a * a) - - 3) Plug in the parametrized equation of our line for x_1 and y_2. - - 4) If the determinant >= 0, we have an intersection, otherwise, nothing. - - **/ - - - /*float32 rotationAngleOfPill = pill->body.rotation; - Vector2 translationOfPill = pill->body.position; - - float32 cosRotation = cosf(rotationAngleOfPill); - float32 sinRotation = sinf(rotationAngleOfPill); - float32 cosRotationSquared = cosRotation * cosRotation; - float32 sinRotationSquared = sinRotation * sinRotation; - float32 aSquared = pill->a * pill->a; - float32 bSquared = pill->b * pill->b; - - float32 x = (segment->end.x - segment->start.x) - translationOfPill.x; - float32 xSquared = x * x; - float32 y = (segment->end.y - segment->start.y) - translationOfPill.y; - float32 ySquared = y * y; - - float32 A_XPart = (segment->end.x - segment->start.x - translationOfPill.x) * cosRotationSquared; - float32 A_YPart = (segment->end.y - segment->start.y - translationOfPill.y) * sinRotationSquared; - float32 A = ((A_XPart * A_XPart) / aSquared) + ((A_YPart * A_YPart) / bSquared); - - float32 B_XPart = 2 * (segment->start.x - translationOfPill.x) * (segment->end.x - segment->start.x - translationOfPill.x); - float32 B = 2 * cosRotation * sinRotation * (1.f / aSquared - 1.f / bSquared) * (x * y); - float32 C = (sinRotationSquared / aSquared + cosRotationSquared / bSquared) * ySquared;*/ - Mat4x4 inverseModel = pill->shape.model.inverse(); Vector2 start = inverseModel * segment->start; Vector2 end = inverseModel * segment->end; - float32 A = pow((end.x - start.x), 2.f) / pow(pill->a, 2) + pow((end.y - start.y), 2.f) / pow(pill->b, 2); - float32 B = ((2 * start.x) * (end.x - start.x)) / pow(pill->a, 2) + ((2 * start.y) * (end.y - start.y)) / pow(pill->b, 2); - float32 C = pow(start.x, 2) / pow(pill->a, 2) + pow(start.y, 2) / pow(pill->b, 2) - 1.f; + Vector2 diff = end - start; + float32 A = (diff.x * diff.x) / (pill->a * pill->a) + (diff.y * diff.y) / (pill->b * pill->b); + float32 B = ((2 * start.x) * (end.x - start.x)) / (pill->a * pill->a) + ((2 * start.y) * (end.y - start.y)) / (pill->b * pill->b); + float32 C = (start.x * start.x) / (pill->a * pill->a) + (start.y * start.y) / (pill->b * pill->b) - 1.f; float32 determinant = B * B - 4 * A * C; if (determinant < 0.f) { @@ -294,17 +241,24 @@ IntersectionResult getIntersection(Pill* pill, LineSegment* segment) { return result; } - float32 t1 = -B + determinant / (2 * A); - float32 t2 = -B - determinant / (2 * A); + float32 t1 = (-B + sqrtf(determinant)) / (2 * A); + float32 t2 = (-B - sqrtf(determinant)) / (2 * A); - Vector2 pointAtT1 = pill->shape.model * Vector2 { segment->start.x + (t1 * (segment->end.x - segment->start.x)), segment->start.y + (t1 * (segment->end.y - segment->start.y)) }; - Vector2 pointAtT2 = { segment->start.x + (t2 * (segment->end.x - segment->start.x)), segment->start.y + (t2 * (segment->end.y - segment->start.y)) }; + Vector2 pointOnLine = segment->getPointOnLine(t1); // This point is in world space and line space, since the line is in world space + Vector2 pointOnEllipse = pointOnLine - pill->body.position; // This point is in ellipse space + pointOnEllipse.printDebug("Point on ellipse"); + + float32 parametricTEllipse = atan2f( pointOnEllipse.y / pill->b , pointOnEllipse.x / pill->a ); + Vector2 tangent = { -pill->a * sinf(parametricTEllipse), pill->b * cosf(parametricTEllipse) }; + Vector2 normal = tangent.getPerp(); + normal.printDebug("Normal"); + // or: Vector2 normal = { pointOnEllipse.x * (pill->b / pill->a), pointOnEllipse.y * (pill->a / pill->b) }; result.intersect = true; result.relativeVelocity = pill->body.velocity - segment->body.velocity;; - result.collisionNormal = (pointAtT1 - pill->body.position).normalize(); - result.firstPointOfApplication = pointAtT1 - pill->body.position; - result.secondPointOfApplication = pointAtT1 - ((segment->end - segment->start) / 2.f); + result.collisionNormal = normal.normalize(); + result.firstPointOfApplication = pointOnEllipse; + result.secondPointOfApplication = pointOnLine; return result; } @@ -318,16 +272,15 @@ void resolveCollision(Rigidbody* first, Rigidbody* second, IntersectionResult* i float32 cofOfRestition = (first->cofOfRestition + second->cofOfRestition) / 2.f; float32 lNumerator = (relativeVelocity * -(1.0 + cofOfRestition)).dot(collisionNormal); float32 lLinearDenomPart = collisionNormal.dot(collisionNormal * (1 / first->mass + 1 / second->mass)); - float32 lRotationalDenomPart = powf(firstPerp.dot(collisionNormal), 2) / first->momentOfInertia - + powf(secondPerp.dot(collisionNormal), 2) / second->momentOfInertia; + float32 lRotationalDenomPart = powf(firstPerp.dot(collisionNormal), 2) / first->momentOfInertia + powf(secondPerp.dot(collisionNormal), 2) / second->momentOfInertia; - float32 lImpulseMagnitude = lNumerator / (lLinearDenomPart);// + lRotationalDenomPart); + float32 lImpulseMagnitude = lNumerator / (lLinearDenomPart + lRotationalDenomPart); first->velocity = first->velocity + (collisionNormal * (lImpulseMagnitude / first->mass)); second->velocity = second->velocity - (collisionNormal * (lImpulseMagnitude / second->mass)); - //first->rotationalVelocity = first->rotationalVelocity + firstPerp.dot(collisionNormal * lImpulseMagnitude) / first->momentOfInertia; - //second->rotationalVelocity = second->rotationalVelocity - secondPerp.dot(collisionNormal * lImpulseMagnitude) / second->momentOfInertia; + first->rotationalVelocity = first->rotationalVelocity + firstPerp.dot(collisionNormal * lImpulseMagnitude) / first->momentOfInertia; + second->rotationalVelocity = second->rotationalVelocity - secondPerp.dot(collisionNormal * lImpulseMagnitude) / second->momentOfInertia; } void update(float32 deltaTimeSeconds, void* userData) { @@ -399,4 +352,4 @@ EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, voi printf("Stop clicked\n"); unload(); return true; -} \ No newline at end of file +} diff --git a/frontend/roadmap.html b/frontend/roadmap.html index 4543028..2b9ccd5 100644 --- a/frontend/roadmap.html +++ b/frontend/roadmap.html @@ -46,7 +46,7 @@
-

Ground Work

+

April 2021: Ground Work and Initial Collisions

  • Orthographic rendering basics
  • Uniform build Process for WebAssembly
  • -- cgit v1.2.1