summaryrefslogtreecommitdiff
path: root/2d/rigidbody/rigidbody_3/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2d/rigidbody/rigidbody_3/main.cpp')
-rw-r--r--2d/rigidbody/rigidbody_3/main.cpp203
1 files changed, 203 insertions, 0 deletions
diff --git a/2d/rigidbody/rigidbody_3/main.cpp b/2d/rigidbody/rigidbody_3/main.cpp
new file mode 100644
index 0000000..06f77dc
--- /dev/null
+++ b/2d/rigidbody/rigidbody_3/main.cpp
@@ -0,0 +1,203 @@
+#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 linearForce = { 0, 0 };
+ Vector2 velocity = { 0, 0 };
+ Vector2 position = { 0, 0 };
+ float32 mass = 1.f;
+
+ float32 torque = 0.f;
+ float32 rotationalVelocity = 0.f;
+ float32 rotation = 0.f;
+ float32 momentOfInertia = 1.f;
+
+ void reset() {
+ linearForce = { 0, 0 };
+ velocity = { 0, 0 };
+ rotationalVelocity = 0.f;
+ rotation = 0.f;
+ }
+
+ void applyForce(Vector2 force, Vector2 pointOfApplication) {
+ linearForce += force;
+ torque += pointOfApplication.getPerp().dot(force);
+ }
+
+ void applyGravity() {
+ applyForce(Vector2 { 0.f, -100.f }, Vector2 { 0.f, 0.f });
+ }
+
+ void update(float32 deltaTimeSeconds) {
+ applyGravity();
+
+ Vector2 acceleration = linearForce / mass;
+ velocity += (acceleration * deltaTimeSeconds);
+ position += (velocity * deltaTimeSeconds);
+ linearForce = Vector2 { 0.f, 0.f };
+
+ // New: Update the rotational velocity as well
+ float32 rotationalAcceleration = torque / momentOfInertia;
+ rotationalVelocity += (rotationalAcceleration * deltaTimeSeconds);
+ rotation += (rotationalVelocity * deltaTimeSeconds);
+ torque = 0.f;
+ }
+};
+
+struct Rectangle {
+ OrthographicShape shape;
+ Rigidbody body;
+ Vector2 originalPoints[4];
+ Vector2 transformedPoints[4];
+
+ void load(OrthographicRenderer* renderer, Vector4 color, float32 width, float32 height) {
+ color = color.toNormalizedColor();
+
+ float32 halfWidth = width / 2.f;
+ float32 halfHeight = height / 2.f;
+
+ OrthographicVertex vertices[6];
+ vertices[0].position = Vector2 { -halfWidth, -halfHeight };
+ vertices[1].position = Vector2 { -halfWidth, halfHeight };
+ vertices[2].position = Vector2 { halfWidth, halfHeight };
+ vertices[3].position = Vector2 { -halfWidth, -halfHeight };
+ vertices[4].position = Vector2 { halfWidth, -halfHeight };
+ vertices[5].position = Vector2 { halfWidth, halfHeight };
+
+ for (int32 i = 0; i < 6; i++) {
+ vertices[i].color = color;
+ }
+
+ originalPoints[0] = vertices[0].position;
+ originalPoints[1] = vertices[1].position;
+ originalPoints[2] = vertices[2].position;
+ originalPoints[3] = vertices[4].position;
+
+ shape.load(vertices, 6, renderer);
+ body.reset();
+
+ body.momentOfInertia = (width * width + height * height) * (body.mass / 12.f);
+ }
+
+ void update(float32 dtSeconds) {
+ body.update(dtSeconds);
+ shape.model = Mat4x4().translateByVec2(body.position).rotate2D(body.rotation);
+
+ // Note: This helps us check if the cursor is within the bounds of the
+ // rectangle later on.
+ for (int idx = 0; idx < 4; idx++) {
+ transformedPoints[idx] = shape.model * originalPoints[idx];
+ }
+ }
+
+ 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;
+Rectangle r1;
+Rectangle r2;
+
+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);
+
+ r1.load(&renderer, Vector4 { 55.f, 235.f, 35.f, 255.f }, 128.f, 64.f);
+ r1.body.mass = 3.f;
+ r1.body.position = Vector2 { context.width / 4.f, context.height / 4.f };
+ r1.body.velocity = Vector2 { 100.f, 250.f };
+
+ r2.load(&renderer, Vector4 { 235.f, 5.f, 35.f, 255.f }, 96.f, 64.f);
+ r2.body.mass = 1.f;
+ r2.body.position = Vector2 { context.width * (3.f / 4.f), context.height * (3.f / 4.f) };
+ r2.body.velocity = Vector2 { -300.f, -150.f };
+
+ mainLoop.run(update);
+}
+
+void handleCollisionWithWall(Rectangle* r) {
+ if (r->body.position.x <= 0.f) {
+ r->body.position.x = 0.f;
+ r->body.velocity = r->body.velocity - Vector2 { 1.f, 0.f } * (2 * (r->body.velocity.dot(Vector2 { 1.f, 0.f })));
+ }
+ if (r->body.position.y <= 0.f) {
+ r->body.position.y = 0.f;
+ r->body.velocity = r->body.velocity - Vector2 { 0.f, 1.f } * (2 * (r->body.velocity.dot(Vector2 { 0.f, 1.f })));
+ }
+ if (r->body.position.x >= 800.f) {
+ r->body.position.x = 800.f;
+ r->body.velocity = r->body.velocity - Vector2 { -1.f, 0.f } * (2 * (r->body.velocity.dot(Vector2{ -1.f, 0.f })));
+ }
+ if (r->body.position.y >= 600.f) {
+ r->body.position.y = 600.f;
+ r->body.velocity = r->body.velocity - Vector2 { 0.f, -1.f } * (2 * (r->body.velocity.dot(Vector2 { 0.f, -1.f }))) ;
+ }
+}
+
+void update(float32 deltaTimeSeconds, void* userData) {
+ r1.update(deltaTimeSeconds);
+ r2.update(deltaTimeSeconds);
+
+ handleCollisionWithWall(&r1);
+ handleCollisionWithWall(&r2);
+
+
+ // Renderer
+ renderer.render();
+ r1.render(&renderer);
+ r2.render(&renderer);
+}
+
+void unload() {
+ mainLoop.stop();
+ renderer.unload();
+ r1.unload();
+ r2.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;
+}