#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 #include #include #include #include #include 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, -96.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 Rectangle { OrthographicShape shape; Rigidbody body; Vector4 color; float32 width = 0.f; float32 height = 0.f; void load(OrthographicRenderer* renderer, Vector4 inColor, float32 inWidth, float32 inHeight) { color = inColor; width = inWidth;; height = inHeight; 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; } shape.load(vertices, 6, renderer); } void update(float32 dtSeconds) { body.update(dtSeconds); shape.model = Mat4x4().translateByVec2(body.position).rotate2D(body.rotation); } void render(OrthographicRenderer* renderer) { shape.render(renderer); } void unload() { shape.unload(); } }; struct LineSegment { OrthographicShape shape; Rigidbody body; Vector2 start; Vector2 end; float32 length; Vector2 normal; OrthographicVertex vertices[2]; void load(OrthographicRenderer* renderer, Vector4 color, Vector2 inStart, Vector2 inEnd) { start = inStart; end = inEnd; length = (start - end).length(); vertices[0].position = start; vertices[0].color = color; vertices[1].position = end; vertices[1].color = color; normal = (end - start).getPerp().normalize(); shape.load(vertices, 2, renderer); body.reset(); body.mass = 1000000000.f; body.cofOfRestition = 1.f; body.rotationalVelocity = 0; body.velocity = Vector2(); body.momentOfInertia = body.mass * (length / 2.f); } void render(OrthographicRenderer* renderer) { shape.render(renderer, GL_LINES); } void unload() { shape.unload(); } Vector2 getPointOnLine(float32 t) { return { start.x + (end.x - start.x) * t, start.y + (end.y - start.y) * t, }; } Vector2 getNormal() { return (end - start).getPerp().normalize(); } }; 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; LineSegment segmentList[4]; Rectangle rectangle; 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); 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) }); segmentList[2].load(&renderer, Vector4().fromColor(248, 255, 156, 255.f), Vector2 { 50.f, 50.f }, Vector2 { context.width - 50.f, 150.f }); segmentList[3].load(&renderer, Vector4().fromColor(205, 178, 214, 255.f), Vector2 { 50.f, 150.f }, Vector2 { context.width - 50.f, 50.f }); rectangle.load(&renderer, Vector4 { 230.f, 182.f, 35.f, 255.f }, 64.f, 32.f); rectangle.body.position = Vector2 { context.width / 2.f, context.height / 2.f }; mainLoop.run(update); } void update(float32 deltaTimeSeconds, void* userData) { // Update rectangle.update(deltaTimeSeconds); // Renderer renderer.render(); rectangle.render(&renderer); for (int32 segmentIndex = 0; segmentIndex < 4; segmentIndex++) { segmentList[segmentIndex].render(&renderer); } } void unload() { mainLoop.stop(); renderer.unload(); for (int32 segmentIndex = 0; segmentIndex < 4; segmentIndex++) { segmentList[segmentIndex].unload(); } rectangle.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; }