From fd3c1e74e7ebe9125b98dba311efcbe73e89859e Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Sun, 14 Nov 2021 14:38:06 -0500 Subject: (mkosarek) Working on undamped and damped --- 2d/softbody/softbody_1/undamped.cpp | 227 ++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 2d/softbody/softbody_1/undamped.cpp (limited to '2d/softbody/softbody_1/undamped.cpp') diff --git a/2d/softbody/softbody_1/undamped.cpp b/2d/softbody/softbody_1/undamped.cpp new file mode 100644 index 0000000..ec53f50 --- /dev/null +++ b/2d/softbody/softbody_1/undamped.cpp @@ -0,0 +1,227 @@ +#include "undamped.h" +#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 +#include +#include +#include +#include +#include +#include + +namespace Undamped { + + 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 = 4; // Spring Constant, in N / m + float32 initialDisplacement = 3.f; + float32 initialVelocity = 0.f; + 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(); + }; + + WebglContext* context; + Renderer2d renderer; + MainLoop mainLoop; + SpringWeight weight; + Spring spring; + + EM_BOOL onUndampedPlayClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); + EM_BOOL onUndampedStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); + void load(); + void update(float32 deltaTimeSeconds, void* userData); + void unload(); + + void init(WebglContext* inContext) { + context = inContext; + emscripten_set_click_callback("#gl_canvas_play_undamped", NULL, false, onUndampedPlayClicked); + emscripten_set_click_callback("#gl_canvas_stop_undamped", NULL, false, onUndampedStopClicked); + } + + void load() { + context->init("#gl_canvas_undamped"); + + 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, 250.f, 64.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(); + + context->destroy(); + } + + + 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(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(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 = initialDisplacement * cosf(angularVelocity * timeElapsed - initialVelocity); + + int32 vidx = 0; + for (int pidx = 0; pidx < numSegments; pidx++) { + float32 y1Offset = displacement * (1.f - pidx / static_cast(numSegments)); + float32 y2Offset = displacement * (1.f - (pidx + 1) / static_cast(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; + } + + + EM_BOOL onUndampedPlayClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) { + printf("Play clicked\n"); + + load(); + return true; + } + + EM_BOOL onUndampedStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) { + printf("Stop clicked\n"); + unload(); + return true; + } + +} -- cgit v1.2.1