From aeb4fc2aec4378aa0742f71324baa76fd5891316 Mon Sep 17 00:00:00 2001 From: mattkae Date: Sat, 8 Jan 2022 08:29:53 -0500 Subject: Added controls for damped motion --- 2d/softbody/softbody_1/damped.cpp | 55 +++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 17 deletions(-) (limited to '2d/softbody/softbody_1/damped.cpp') diff --git a/2d/softbody/softbody_1/damped.cpp b/2d/softbody/softbody_1/damped.cpp index d623c06..0344bd0 100644 --- a/2d/softbody/softbody_1/damped.cpp +++ b/2d/softbody/softbody_1/damped.cpp @@ -25,6 +25,13 @@ namespace Damped { void unload(); }; + enum DampedSpringType { + None = 0, + Overdamped = 1, + Underdamped = 2, + Critical = 3 + }; + struct DampedSpring { DampedSpringWeight* weight; @@ -35,12 +42,14 @@ namespace Damped { int32 numVertices = 0; // Initialization variables + float32 initialDisplacement = 0.f; float32 k = 4; // DampedSpring Constant, in N / m (Hooke's Law) float32 c = 1.f; // Viscous damping coefficient (Damping force) + + // Discovered during initialization + DampedSpringType type = DampedSpringType::None; float32 R = 2.f; float32 gamma = 6.2; - - // Constants calculated at load time float32 discriminant = 0.f; float32 omega1 = 0.f; @@ -49,7 +58,7 @@ namespace Damped { float32 timeElapsed = 0.f; - void load(Renderer2d* renderer, DampedSpringWeight* inWieight, float32 length, float32 loopRadius); + void load(Renderer2d* renderer, DampedSpringWeight* inWieight, float32 length, float32 loopRadius, float32 initialDisplacement); void update(float32 dtSeconds); void render(Renderer2d* renderer); void unload(); @@ -82,8 +91,8 @@ namespace Damped { 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, 16.f); + weight.load(&renderer, initVariables.mass, Vector4 { 55.f, 235.f, 35.f, 255.f }, Vector4 { 235.f, 5.f, 235.f, 255.f }); + spring.load(&renderer, &weight, initVariables.springLength, 16.f, initVariables.initialDisplacement); mainLoop.run(update); } @@ -107,8 +116,9 @@ namespace Damped { context->destroy(); } - void DampedSpringWeight::load(Renderer2d* renderer, float32 inRadius, Vector4 startColor, Vector4 endColor) { - radius = inRadius; + void DampedSpringWeight::load(Renderer2d* renderer, float32 inMass, Vector4 startColor, Vector4 endColor) { + mass = inMass; + radius = mass * 16.f; const int32 numSegments = 96; const float32 radiansPerSegment = (2.f * PI) / static_cast(numSegments); const int32 numVertices = numSegments * 3; @@ -154,20 +164,28 @@ namespace Damped { const float32 epsilon = 0.0001f; - void DampedSpring::load(Renderer2d* renderer, DampedSpringWeight* inWeight, float32 length, float32 loopRadius) { + void DampedSpring::load(Renderer2d* renderer, DampedSpringWeight* inWeight, float32 length, float32 loopRadius, float32 initialDisplacement) { + initialDisplacement = initialDisplacement; weight = inWeight; discriminant = c * c - (4 * weight->mass * k); - if (discriminant < epsilon && discriminant > -epsilon) { // Real repeated root: Overdamped motion - + if (discriminant < epsilon && discriminant > -epsilon) { // Real repeated root (~ zero): Overdamped motion + printf("Overdamped motion.\n"); + type = DampedSpringType::Overdamped; } - else if (discriminant > 0) { // Two real roots: Critically damped motion - + else if (discriminant > 0) { // Two real roots (greater than zero): Critically damped motion + printf("Critically damped motion.\n"); + type = DampedSpringType::Critical; } else { // Complex pair (less than zero): Underdamped motion - omega1 = sqrtf(-discriminant) / (2.f * weight->mass); // Get the real part of the number + printf("Underdamped motion.\n"); + + type = DampedSpringType::Underdamped; + omega1 = sqrtf(-discriminant) / (2.f * weight->mass); // Note that we negate the discriminant to get the REAL positive part. } + + timeElapsed = 0.f; const int32 verticesPerSegment = 6; @@ -206,6 +224,8 @@ namespace Damped { void DampedSpring::update(float32 dtSeconds) { timeElapsed += dtSeconds; + float32 lastDisplacement = displacement; + if (discriminant < epsilon && discriminant > -epsilon) { // Real repeated root: Overdamped motion } @@ -217,10 +237,11 @@ namespace Damped { displacement = R * pow(E, exponent) * (cosf(omega1 * timeElapsed - gamma)); } + float32 dx = displacement - lastDisplacement; 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)); + float32 y1Offset = dx * (1.f - pidx / static_cast(numSegments)); + float32 y2Offset = dx * (1.f - (pidx + 1) / static_cast(numSegments)); vertices[vidx++].position.y += y1Offset; vertices[vidx++].position.y += y2Offset; vertices[vidx++].position.y += y1Offset; @@ -228,8 +249,8 @@ namespace Damped { vertices[vidx++].position.y += y2Offset; vertices[vidx++].position.y += y2Offset; } - - weight->shape.model = weight->shape.model.translateByVec2(Vector2(0, displacement)); + + weight->shape.model = weight->shape.model.translateByVec2(Vector2(0, dx)); } void DampedSpring::render(Renderer2d* renderer) { -- cgit v1.2.1