From 5110a8c636138faa4049e2bfff28a97219ed90f1 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 5 Sep 2023 18:39:51 +0200 Subject: [PATCH] Squashed commit of the following: commit 84148ad07a7ac94993dc9dfd0bdc6d7a8d9e47ac Author: Blaz Kristan Date: Sun Sep 3 12:34:17 2023 +0200 Implement palette colors commit af3c8f66f7e77dd6306ceadf2cea26a41336e439 Author: Blaz Kristan Date: Tue Aug 1 18:18:41 2023 +0200 revert wled00.ino commit 3097a1b17efa06b78d52611b3a9d3c519a15ed17 Author: Blaz Kristan Date: Tue Aug 1 18:13:37 2023 +0200 minor aesthetic fixes commit 54b80f74b2dc8766951d55438c6bc560b33e505b Author: Blaz Kristan Date: Tue Aug 1 18:09:32 2023 +0200 remove unused variable commit 9a78d28cd71da998cdd76ba826946f54ee2044bd Merge: 56a74bc5 1ed81793 Author: Blaz Kristan Date: Tue Aug 1 18:08:29 2023 +0200 Merge branch 'main' into PJH_ADD_Linearbounce commit 56a74bc54c5bbf189b1f98c6cd216956b4f6bd6c Author: pjhatch <66844564+pjhatch@users.noreply.github.com> Date: Sat Aug 15 12:34:13 2020 -0500 Update FX.cpp Added the improvements suggested by Gregor Hartmann commit a20358b61bf0c38356438c87e5c59663524e038e Author: pjhatch <66844564+pjhatch@users.noreply.github.com> Date: Sun Jul 12 08:33:48 2020 -0500 Adding 2 ball track modes With and without collisions commit 341d9d1697e9af4fdf2fbd5b4c1de935d0b5a229 Author: pjhatch <66844564+pjhatch@users.noreply.github.com> Date: Sun Jul 5 14:55:14 2020 -0500 Update FX.cpp Still 1 bug to fix - this was a test. commit 9cee4243837f35431302814cc7ace13a72ab5fed Author: pjhatch <66844564+pjhatch@users.noreply.github.com> Date: Sun Jul 5 14:53:14 2020 -0500 Update FX.cpp commit 37cb51cfd6991f6041d663de72debfdcf349c1da Author: pjhatch <66844564+pjhatch@users.noreply.github.com> Date: Thu Jul 2 14:16:25 2020 -0500 Adding Collision A couple of bugs still need sorting commit 84b7bfb989e662e37a47d78e381105b3951311a6 Author: pjhatch <66844564+pjhatch@users.noreply.github.com> Date: Sun Jun 28 19:59:46 2020 -0500 update for lost balls Added some protection - so that when intensity is lowered and raised some time later balls that have moved way off the track are recovered. commit 04d17e483956b74754002da4cb4dfcddaf932f7b Author: pjhatch <66844564+pjhatch@users.noreply.github.com> Date: Sun Jun 28 19:43:56 2020 -0500 Added Ball Track V1 In this version the balls bounce of the edges and do not interact with one another. --- wled00/FX.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 2 +- 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 160e24a2..21c4d7d2 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2834,6 +2834,103 @@ uint16_t mode_bouncing_balls(void) { static const char _data_FX_MODE_BOUNCINGBALLS[] PROGMEM = "Bouncing Balls@Gravity,# of balls,,,,,Overlay;!,!,!;!;1;m12=1"; //bar +/* + * bouncing balls on a track track Effect modified from Aircoookie's bouncing balls + * Courtesy of pjhatch (https://github.com/pjhatch) + * https://github.com/Aircoookie/WLED/pull/1039 + */ +// modified for balltrack mode +typedef struct RollingBall { + unsigned long lastBounceUpdate; + float mass; // could fix this to be = 1. if memory is an issue + float velocity; + float height; +} rball_t; + +static uint16_t rolling_balls(void) { + //allocate segment data + const uint16_t maxNumBalls = 16; // 255/16 + 1 + uint16_t dataSize = sizeof(rball_t) * maxNumBalls; + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + + rball_t *balls = reinterpret_cast(SEGENV.data); + + // number of balls based on intensity setting to max of 16 (cycles colors) + // non-chosen color is a random color + uint8_t numBalls = SEGMENT.intensity/16 + 1; + + if (SEGENV.call == 0) { + for (int i = 0; i < maxNumBalls; i++) { + balls[i].lastBounceUpdate = strip.now; + balls[i].velocity = 20.0f * float(random16(1000, 10000))/10000.0f; // number from 1 to 10 + if (random8()<128) balls[i].velocity = -balls[i].velocity; // 50% chance of reverse direction + balls[i].height = (float(random16(0, 10000)) / 10000.0f); // from 0. to 1. + balls[i].mass = (float(random16(1000, 10000)) / 10000.0f); // from .1 to 1. + } + } + + float cfac = float(scale8(8, 255-SEGMENT.speed) +1)*20000.0f; // this uses the Aircoookie conversion factor for scaling time using speed slider + + bool hasCol2 = SEGCOLOR(2); + if (!SEGMENT.check2) SEGMENT.fill(hasCol2 ? BLACK : SEGCOLOR(1)); + + for (int i = 0; i < numBalls; i++) { + float timeSinceLastUpdate = float((strip.now - balls[i].lastBounceUpdate))/cfac; + float thisHeight = balls[i].height + balls[i].velocity * timeSinceLastUpdate; // this method keeps higher resolution + // test if intensity level was increased and some balls are way off the track then put them back + if (thisHeight < -0.5f || thisHeight > 1.5f){ + thisHeight = balls[i].height = (float(random16(0, 10000)) / 10000.0f); // from 0. to 1. + balls[i].lastBounceUpdate = strip.now; + } + // check if reached ends of the strip + if ((thisHeight <= 0.0f && balls[i].velocity < 0.0f) || (thisHeight >= 1.0f && balls[i].velocity > 0.0f)) { + balls[i].velocity = -balls[i].velocity; // reverse velocity + balls[i].lastBounceUpdate = strip.now; + balls[i].height = thisHeight; + } + // check for collisions + if (SEGMENT.check1) { + for (int j = i+1; j < numBalls; j++) { + if (balls[j].velocity != balls[i].velocity) { + // tcollided + balls[j].lastBounceUpdate is acutal time of collision (this keeps precision with long to float conversions) + float tcollided = (cfac*(balls[i].height - balls[j].height) + + balls[i].velocity*float(balls[j].lastBounceUpdate - balls[i].lastBounceUpdate))/(balls[j].velocity - balls[i].velocity); + + if ((tcollided > 2.0f) && (tcollided < float(strip.now - balls[j].lastBounceUpdate))) { // 2ms minimum to avoid duplicate bounces + balls[i].height = balls[i].height + balls[i].velocity*(tcollided + float(balls[j].lastBounceUpdate - balls[i].lastBounceUpdate))/cfac; + balls[j].height = balls[i].height; + balls[i].lastBounceUpdate = (unsigned long)(tcollided + 0.5f) + balls[j].lastBounceUpdate; + balls[j].lastBounceUpdate = balls[i].lastBounceUpdate; + float vtmp = balls[i].velocity; + balls[i].velocity = ((balls[i].mass - balls[j].mass)*vtmp + 2.0f*balls[j].mass*balls[j].velocity)/(balls[i].mass + balls[j].mass); + balls[j].velocity = ((balls[j].mass - balls[i].mass)*balls[j].velocity + 2.0f*balls[i].mass*vtmp) /(balls[i].mass + balls[j].mass); + thisHeight = balls[i].height + balls[i].velocity*(strip.now - balls[i].lastBounceUpdate)/cfac; + } + } + } + } + + uint32_t color = SEGCOLOR(0); + if (SEGMENT.palette) { + //color = SEGMENT.color_wheel(i*(256/MAX(numBalls, 8))); + color = SEGMENT.color_from_palette(i*255/numBalls, false, PALETTE_SOLID_WRAP, 0); + } else if (hasCol2) { + color = SEGCOLOR(i % NUM_COLORS); + } + + if (thisHeight < 0.0f) thisHeight = 0.0f; + if (thisHeight > 1.0f) thisHeight = 1.0f; + uint16_t pos = round(thisHeight * (SEGLEN - 1)); + SEGMENT.setPixelColor(pos, color); + balls[i].lastBounceUpdate = strip.now; + balls[i].height = thisHeight; + } + + return FRAMETIME; +} +static const char _data_FX_MODE_ROLLINGBALLS[] PROGMEM = "Rolling Balls@!,# of balls,,,,Collisions,Overlay;!,!,!;!;1;m12=1"; //bar + + /* * Sinelon stolen from FASTLED examples */ @@ -7607,6 +7704,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_FIRE_FLICKER, &mode_fire_flicker, _data_FX_MODE_FIRE_FLICKER); addEffect(FX_MODE_GRADIENT, &mode_gradient, _data_FX_MODE_GRADIENT); addEffect(FX_MODE_LOADING, &mode_loading, _data_FX_MODE_LOADING); + addEffect(FX_MODE_ROLLINGBALLS, &rolling_balls, _data_FX_MODE_ROLLINGBALLS); addEffect(FX_MODE_FAIRY, &mode_fairy, _data_FX_MODE_FAIRY); addEffect(FX_MODE_TWO_DOTS, &mode_two_dots, _data_FX_MODE_TWO_DOTS); diff --git a/wled00/FX.h b/wled00/FX.h index a7906f8d..d7eebc4f 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -176,7 +176,7 @@ #define FX_MODE_FIRE_FLICKER 45 #define FX_MODE_GRADIENT 46 #define FX_MODE_LOADING 47 -// #define FX_MODE_POLICE 48 // removed in 0.14! +#define FX_MODE_ROLLINGBALLS 48 //was Police before 0.14 #define FX_MODE_FAIRY 49 //was Police All prior to 0.13.0-b6 (use "Two Dots" with Red/Blue and full intensity) #define FX_MODE_TWO_DOTS 50 #define FX_MODE_FAIRYTWINKLE 51 //was Two Areas prior to 0.13.0-b6 (use "Two Dots" with full intensity)