summaryrefslogtreecommitdiff
path: root/2d/softbody/softbody_1/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2d/softbody/softbody_1/main.cpp')
-rw-r--r--2d/softbody/softbody_1/main.cpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/2d/softbody/softbody_1/main.cpp b/2d/softbody/softbody_1/main.cpp
new file mode 100644
index 0000000..0b04426
--- /dev/null
+++ b/2d/softbody/softbody_1/main.cpp
@@ -0,0 +1,228 @@
+#include "../../../shared_cpp/Renderer2d.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 MassSpringVertex {
+
+};
+
+struct MassSpringBody {
+
+};
+
+struct SpringWeight {
+ Mesh2d shape;
+ float32 radius;
+ float32 mass = 2.f;
+
+ void load(Renderer2d* renderer, float32 inRadius, Vector4 startColor, Vector4 endColor);
+ void update(float32 dtSeconds);
+ void render(Renderer2d* renderer);
+ void unload();
+};
+
+struct Spring {
+ SpringWeight* weight;
+
+ Mesh2d shape;
+
+ Vertex2d* vertices = NULL;
+ int32 numSegments = 0;
+ int32 numVertices = 0;
+ float32 k = 5; // Spring Constant, in N / m
+ float32 angularVelocity = 0.f; // To be calculated
+ float32 displacement = 0.f;
+ float32 timeElapsed = 0.f;
+
+ void load(Renderer2d* renderer, SpringWeight* inWieight, float32 length, float32 loopRadius);
+ void update(float32 dtSeconds);
+ void render(Renderer2d* renderer);
+ void 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;
+Renderer2d renderer;
+MainLoop mainLoop;
+SpringWeight weight;
+Spring spring;
+
+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);
+
+ weight.load(&renderer, 32.f, Vector4 { 55.f, 235.f, 35.f, 255.f }, Vector4 { 235.f, 5.f, 235.f, 255.f });
+ spring.load(&renderer, &weight, 100.f, 16.f);
+
+ mainLoop.run(update);
+}
+
+void update(float32 deltaTimeSeconds, void* userData) {
+ // -- Update
+ spring.update(deltaTimeSeconds);
+ weight.update(deltaTimeSeconds);
+
+ // -- Render
+ renderer.render();
+ weight.render(&renderer);
+ spring.render(&renderer);
+}
+
+void unload() {
+ mainLoop.stop();
+ renderer.unload();
+ weight.unload();
+ spring.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;
+}
+
+
+void SpringWeight::load(Renderer2d* renderer, float32 inRadius, Vector4 startColor, Vector4 endColor) {
+ radius = inRadius;
+ const int32 numSegments = 96;
+ const float32 radiansPerSegment = (2.f * PI) / static_cast<float>(numSegments);
+ const int32 numVertices = numSegments * 3;
+
+ float32 t = 0.f;
+ float32 tIncrement = 1.f / (numSegments / 2.f);
+ startColor = startColor.toNormalizedColor();
+ endColor = endColor.toNormalizedColor();
+
+ Vertex2d vertices[numVertices];
+ for (int idx = 0; idx < numSegments; idx++) {
+ int vIdx = idx * 3;
+
+ Vector4 color = lerp(startColor, endColor, t);
+ if (idx >= numSegments / 2) {
+ t -= tIncrement;
+ } else {
+ t += tIncrement;
+ }
+
+ vertices[vIdx].color = color;
+ vertices[vIdx].position = Vector2 { radius * cosf(radiansPerSegment * idx), radius * sinf(radiansPerSegment * idx) };
+ vertices[vIdx + 1].color = color;
+ vertices[vIdx + 1].position = Vector2 { 0.f, 0.f };
+ vertices[vIdx + 2].color = color;
+ vertices[vIdx + 2].position = Vector2 { radius * cosf(radiansPerSegment * (idx + 1)), radius * sinf(radiansPerSegment * (idx + 1)) };
+ }
+
+ shape.load(vertices, numVertices, renderer);
+}
+
+void SpringWeight::update(float32 dtSeconds) {
+
+}
+
+void SpringWeight::render(Renderer2d* renderer) {
+ shape.render(renderer);
+}
+
+void SpringWeight::unload() {
+ shape.unload();
+}
+
+void Spring::load(Renderer2d* renderer, SpringWeight* inWeight, float32 length, float32 loopRadius) {
+ weight = inWeight;
+ angularVelocity = sqrtf(k / weight->mass);
+ timeElapsed = 0.f;
+
+ const int32 verticesPerSegment = 6;
+ numSegments = 256;
+ numVertices = numSegments * verticesPerSegment;
+ vertices = new Vertex2d[numVertices];
+
+ float32 lengthIncrement = length / static_cast<float32>(numSegments);
+
+ const float32 frequency = 0.25f;
+ const float32 loopWidth = 20.f;
+ const float32 offset = 0.25f;
+
+ int32 vidx = 0;
+ for (int pidx = 0; pidx < numSegments; pidx++) {
+ float32 y1 = lengthIncrement * pidx;
+ float32 x1 = loopWidth * sinf(frequency * y1 + offset);
+
+ float32 y2 = y1 + lengthIncrement;
+ float32 x2 = loopWidth * sinf(frequency * y2 + offset);
+
+ vertices[vidx++].position = Vector2(x1, y1);
+ vertices[vidx++].position = Vector2(x1, y2);
+ vertices[vidx++].position = Vector2(x2, y1);
+ vertices[vidx++].position = Vector2(x2, y1);
+ vertices[vidx++].position = Vector2(x1, y2);
+ vertices[vidx++].position = Vector2(x2, y2);
+ }
+
+ shape.load(vertices, numVertices, renderer, GL_DYNAMIC_DRAW);
+ shape.model = Mat4x4().translateByVec2(Vector2(400, 300));
+
+ weight->shape.model = shape.model.translateByVec2(Vector2(0, -weight->radius));
+}
+
+void Spring::update(float32 dtSeconds) {
+ timeElapsed += dtSeconds;
+ displacement = 2 * cosf(angularVelocity * timeElapsed);
+
+ int32 vidx = 0;
+ for (int pidx = 0; pidx < numSegments; pidx++) {
+ float32 y1Offset = displacement * (1.f - pidx / static_cast<float32>(numSegments));
+ float32 y2Offset = displacement * (1.f - (pidx + 1) / static_cast<float32>(numSegments));
+ vertices[vidx++].position.y += y1Offset;
+ vertices[vidx++].position.y += y2Offset;
+ vertices[vidx++].position.y += y1Offset;
+ vertices[vidx++].position.y += y1Offset;
+ vertices[vidx++].position.y += y2Offset;
+ vertices[vidx++].position.y += y2Offset;
+ }
+
+ weight->shape.model = weight->shape.model.translateByVec2(Vector2(0, displacement));
+}
+
+void Spring::render(Renderer2d* renderer) {
+ glBindBuffer(GL_ARRAY_BUFFER, shape.vbo);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices * sizeof(Vertex2d), &vertices[0]);
+
+ shape.render(renderer);
+}
+
+void Spring::unload() {
+ shape.unload();
+ delete[] vertices;
+}