diff options
Diffstat (limited to '2d/softbody/softbody_1/main.cpp')
-rw-r--r-- | 2d/softbody/softbody_1/main.cpp | 228 |
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; +} |