3namespace lampda::modes::custom::nudz {
33 ctx.state.last_tick = 0;
36 ctx.template set_config_bool<ConfigKeys::rampSaturates>(
true);
39 static void loop(
auto& ctx)
41 float spdRange = ctx.state.maxSpeed - ctx.state.minSpeed;
42 float speed = ctx.state.minSpeed + (float(ctx.get_active_custom_ramp()) / 255) * spdRange;
44 if (speed < -spdRange * 0.1)
45 speed += spdRange * 0.1;
46 else if (speed > spdRange * 0.1)
47 speed -= spdRange * 0.1;
51 uint16_t imWidth = ImageType::width;
52 uint16_t imHeight = ImageType::height;
55 int32_t xdecal = ctx.state.xdecal + int32_t((ctx.lamp.tick - ctx.state.last_tick) * speed);
57 if (ctx.state.randomScroll)
60 int32_t(ctx.state.xdecal) + int32_t((ctx.lamp.tick - ctx.state.last_tick) * speed) * ctx.state.xdirection;
61 if (ctx.state.ydirection != 0)
62 ydecal = int32_t(ctx.state.ydecal) +
63 int32_t((ctx.lamp.tick - ctx.state.last_tick) * speed) * ctx.state.ydirection;
67 ctx.state.xdirection *= -random8(2);
68 ctx.state.ydirection = random8(3) - 1;
69 if (ctx.state.xdirection == 0 && ctx.state.ydirection == 0)
70 ctx.state.ydirection = random8(2) * 2 - 1;
72 else if (xdecal + ctx.lamp.maxWidth >= imWidth)
74 xdecal = imWidth - ctx.lamp.maxWidth - 1;
75 ctx.state.xdirection *= -random8(2);
76 ctx.state.ydirection = random8(3) - 1;
77 if (ctx.state.xdirection == 0 && ctx.state.ydirection == 0)
78 ctx.state.ydirection = random8(2) * 2 - 1;
83 ctx.state.ydirection *= -random8(2);
84 ctx.state.xdirection = random8(3) - 1;
85 if (ctx.state.xdirection == 0 && ctx.state.ydirection == 0)
86 ctx.state.xdirection = random8(2) * 2 - 1;
88 else if (ydecal + ctx.lamp.maxHeight >= imHeight)
90 ydecal = imHeight - ctx.lamp.maxHeight - 1;
91 ctx.state.ydirection *= -random8(2);
92 ctx.state.xdirection = random8(3) - 1;
93 if (ctx.state.xdirection == 0 && ctx.state.ydirection == 0)
94 ctx.state.xdirection = random8(2) * 2 - 1;
97 if (xdecal != ctx.state.xdecal || ydecal != ctx.state.ydecal)
99 ctx.state.xdecal = xdecal;
100 ctx.state.ydecal = ydecal;
101 ctx.state.last_tick = ctx.lamp.tick;
104 uint32_t w = min<uint32_t>(ctx.lamp.maxWidth + 1, imWidth);
105 uint32_t h = min<uint32_t>(ctx.lamp.maxHeight, imHeight);
106 if (ImageType::colormapSize == 0)
107 for (uint32_t y = 0; y < h; ++y)
108 for (uint32_t x = 0; x < w; ++x)
109 ctx.lamp.setPixelColorXY(
110 x, y, ImageType::rgbData[((y + ydecal) % imHeight) * imWidth + (x + xdecal) % imWidth]);
114 constexpr uint8_t bmask = (1 << ImageType::bitsPerPixel) - 1;
115 for (uint32_t y = 0; y < h; ++y)
117 uint32_t yoffset = ((y + ydecal) % imHeight) * imWidth;
118 for (uint32_t x = 0; x < w; ++x)
120 uint32_t offset = yoffset + (x + xdecal) % imWidth;
121 uint32_t byteOffset = offset * ImageType::bitsPerPixel / 8;
122 uint32_t bitOffset = (offset * ImageType::bitsPerPixel) % 8;
123 uint8_t index = ImageType::indexData[byteOffset];
124 if (bitOffset + ImageType::bitsPerPixel > 8)
126 uint16_t sindex = (index << 8) | ImageType::indexData[byteOffset + 1];
127 index = (sindex >> (16 - bitOffset - ImageType::bitsPerPixel)) & bmask;
130 index = (index >> (8 - bitOffset - ImageType::bitsPerPixel)) & bmask;
132 ctx.lamp.setPixelColorXY(x, y, ImageType::colormap[index]);
142#include "src/generated/heineken.hpp"
146#include "src/generated/huit_six.hpp"
150#include "src/generated/violonsaouls.hpp"
210 ctx.state.imuEvent.reset(ctx);
213 ctx.state.level = 10.f;
214 ctx.state.ampl = 0.02f;
215 ctx.state.accmax = 0.2f;
216 ctx.state.fall_ampl = 10.f;
217 ctx.state.wave_ampl = 0.3f;
218 ctx.state.decay = 0.7f;
219 ctx.state.bounce_ratio = 0.7f;
220 ctx.state.beer_color = 0x503000;
221 ctx.state.foam_color = 0x706050;
222 ctx.state.background_color = 0x000000;
223 ctx.state.levels = std::vector<float>(ctx.lamp.maxWidth, ctx.state.level);
224 ctx.state.speeds = std::vector<float>(ctx.lamp.maxWidth, 0.f);
225 ctx.state.nbubbles = 20;
226 ctx.state.bubbles = std::vector<BubbleTy>(ctx.state.nbubbles,
BubbleTy());
229 ctx.template set_config_bool<ConfigKeys::rampSaturates>(
true);
232 static void loop(
auto& ctx)
234 ctx.state.imuEvent.update(ctx);
245 if (ctx.get_active_custom_ramp() >= 240)
252 uint32_t nx = ctx.lamp.maxWidth;
253 uint32_t ny = ctx.lamp.maxHeight;
255 const auto& reading = ctx.state.imuEvent.lastReading;
256 const auto accel = reading.accel;
258 auto& levels = ctx.state.levels;
259 auto& speeds = ctx.state.speeds;
262 float newLevel = float(ctx.get_active_custom_ramp()) / 255 * (ny - 1);
263 float diffLevel = newLevel - ctx.state.level;
268 for (uint32_t x = 0; x < nx; ++x)
269 if (levels[x] < -diffLevel)
270 missing += -diffLevel - levels[x];
271 diffLevel += missing / nx;
273 ctx.state.level = newLevel;
274 for (uint32_t x = 0; x < nx; ++x)
275 levels[x] += diffLevel;
279 if (acc.
x * acc.
x + acc.
y * acc.
y < 4.f)
281 acc.
x *= ctx.state.ampl;
282 acc.
y *= ctx.state.ampl;
283 float accmax = ctx.state.accmax;
286 else if (acc.
x > accmax)
290 else if (acc.
y > accmax)
293 std::vector<float> ospeeds = speeds;
299 for (uint32_t x = 0; x < nx; ++x)
302 float angle = float(x) / nx * M_PI * 2;
309 float acc0 = norm.
dot(acc);
314 if (acc.
dot(tan) > 0)
316 speeds[x] -= levels[x] * acc0 * sign;
317 ospeeds[x] -= levels[x] * acc0 * sign;
318 float diff = speeds[x];
327 if (levels[x] < -diff)
332 ospeeds[x1] += diff * ctx.state.wave_ampl;
343 if (levels[x] < diff)
347 ospeeds[x1] += diff * ctx.state.wave_ampl;
353 ctx.state.speeds = ospeeds;
356 for (uint32_t x = 0; x < nx; ++x)
361 float ld = levels[x1] - levels[x];
364 diff = min<float>(ld, ctx.state.fall_ampl);
366 diff = max<float>(ld, -ctx.state.fall_ampl);
367 if (diff > 0 && diff > ld * ctx.state.bounce_ratio)
368 diff = ld * ctx.state.bounce_ratio;
369 else if (diff < 0 && diff < ld * ctx.state.bounce_ratio)
370 diff = ld * ctx.state.bounce_ratio;
373 speeds[x] -= diff * ctx.state.wave_ampl;
374 speeds[x] *= ctx.state.decay;
381 auto& levels = ctx.state.levels;
382 uint32_t nx = ctx.lamp.maxWidth;
383 uint32_t ny = ctx.lamp.maxHeight;
385 for (uint32_t x = 0; x <= nx; ++x)
390 int32_t y, y1 = int(levels[x0]);
394 for (y = 0; y < y1 - 3; ++y)
395 ctx.lamp.setPixelColorXY(x, y, ctx.state.background_color);
397 ctx.lamp.setPixelColorXY(x, y, ctx.state.foam_color);
399 ctx.lamp.setPixelColorXY(x, y, ctx.state.beer_color);
406 auto& bubbles = ctx.state.bubbles;
407 auto& levels = ctx.state.levels;
408 uint32_t nx = ctx.lamp.maxWidth;
409 uint32_t ny = ctx.lamp.maxHeight;
411 for (uint32_t i = 0; i < ctx.state.nbubbles; ++i)
413 auto& bubble = bubbles[i];
417 bubble.x = random8(nx);
418 bubble.y = float(random8(uint8_t(levels[bubble.x])));
419 bubble.speed = float(random8()) / 256 * 0.05 + 0.05;
420 bubble.color = ctx.state.foam_color;
421 bubble.color_fade = float(random8()) / 256 * 0.029 + 0.975;
423 if (
int(bubble.y) >= levels[bubble.x])
428 ctx.lamp.setPixelColorXY(bubble.x, ny - 1 -
int(bubble.y), bubble.color);
431 bubble.y += bubble.speed;
433 uint8_t r = uint8_t(
float((bubble.color & 0xff0000) >> 16) * bubble.color_fade +
434 float((ctx.state.beer_color & 0xff0000) >> 16) * (1. - bubble.color_fade));
435 uint8_t g = uint8_t(
float((bubble.color & 0xff00) >> 8) * bubble.color_fade +
436 float((ctx.state.beer_color & 0xff00) >> 8) * (1. - bubble.color_fade));
437 uint8_t b = uint8_t(
float(bubble.color & 0xff) * bubble.color_fade +
438 float(ctx.state.beer_color & 0xff) * (1. - bubble.color_fade));
439 bubble.color = (r << 16) + (g << 8) + b;
442 if ((
float(r) -
float((ctx.state.beer_color & 0xff0000) >> 16)) *
443 (float(r) - float((ctx.state.beer_color & 0xff0000) >> 16)) +
444 (
float(g) - float((ctx.state.beer_color & 0xff00) >> 8)) *
445 (
float(g) - float((ctx.state.beer_color & 0xff00) >> 8)) +
446 (
float(b) - float(ctx.state.beer_color & 0xff)) * (
float(b) - float(ctx.state.beer_color & 0xff)) <
455 const auto& reading = ctx.state.imuEvent.lastReading;
456 const auto accel = reading.accel;
458 int32_t ax = int32_t(accel.x);
459 int32_t ay = int32_t(accel.y);
460 int32_t az = int32_t(accel.z);
477 for (x = 10 + ax; x < 10; ++x)
478 ctx.lamp.setPixelColorXY(x, 0, 0x800000);
479 for (x = 10; x < 10 + ax; ++x)
480 ctx.lamp.setPixelColorXY(x, 0, 0x008000);
481 for (x = 10 + ay; x < 10; ++x)
482 ctx.lamp.setPixelColorXY(x, 1, 0x800000);
483 for (x = 10; x < 10 + ay; ++x)
484 ctx.lamp.setPixelColorXY(x, 1, 0x008000);
485 for (x = 10 + az; x < 10; ++x)
486 ctx.lamp.setPixelColorXY(x, 2, 0x800000);
487 for (x = 10; x < 10 + az; ++x)
488 ctx.lamp.setPixelColorXY(x, 2, 0x008000);
Parent object for all custom user modes.
Definition: mode_type.hpp:53
Definition: nudz_scrollimage.hpp:178
int x
x coordinate
Definition: nudz_scrollimage.hpp:180
uint32_t color
color of this buble
Definition: nudz_scrollimage.hpp:183
float y
y coordinate
Definition: nudz_scrollimage.hpp:181
float speed
speed in px/second
Definition: nudz_scrollimage.hpp:182
float color_fade
fade rate
Definition: nudz_scrollimage.hpp:184
Definition: nudz_scrollimage.hpp:188
float bounce_ratio
if ratio > 0.5 a wave dropping can increase. Its neighbours height over its new height,...
Definition: nudz_scrollimage.hpp:195
std::vector< float > levels
level of every matrix columns
Definition: nudz_scrollimage.hpp:200
uint32_t nbubbles
number of bubbles
Definition: nudz_scrollimage.hpp:202
float level
average level of beer
Definition: nudz_scrollimage.hpp:189
float accmax
clamp accel to avoid too large changes
Definition: nudz_scrollimage.hpp:191
imu::ImuEventTy imuEvent
Handle imu events.
Definition: nudz_scrollimage.hpp:205
float ampl
accel amplitude factor
Definition: nudz_scrollimage.hpp:190
std::vector< BubbleTy > bubbles
store the bubbles
Definition: nudz_scrollimage.hpp:203
uint32_t beer_color
color of the beer :)
Definition: nudz_scrollimage.hpp:197
float wave_ampl
wave speed
Definition: nudz_scrollimage.hpp:193
std::vector< float > speeds
spped of every matric columns
Definition: nudz_scrollimage.hpp:201
float decay
speed decay factor
Definition: nudz_scrollimage.hpp:194
uint32_t foam_color
color of the foam of the beer
Definition: nudz_scrollimage.hpp:198
uint32_t background_color
color background
Definition: nudz_scrollimage.hpp:199
float fall_ampl
height a wave will go down at each step
Definition: nudz_scrollimage.hpp:192
Display a glass of beer, reactive to gravity. The user ramp changes the beer level.
Definition: nudz_scrollimage.hpp:176
static constexpr bool hasCustomRamp
hint manager that we have a custom ramp
Definition: nudz_scrollimage.hpp:492
static void updateLevels(auto &ctx)
update the level of the liquid using IMU events
Definition: nudz_scrollimage.hpp:250
static void displayLevels(auto &ctx)
Display the liquid level on the strip.
Definition: nudz_scrollimage.hpp:379
static void drawAccel(auto &ctx)
Draw the acceleration vector from the IMU.
Definition: nudz_scrollimage.hpp:453
static void on_enter_mode(auto &ctx)
Definition: nudz_scrollimage.hpp:208
static void makeBubbles(auto &ctx)
Invoque new bubbles !
Definition: nudz_scrollimage.hpp:404
Definition: nudz_scrollimage.hpp:159
float maxSpeed
maximum allowed speed
Definition: nudz_scrollimage.hpp:161
bool randomScroll
random variation of the scroll
Definition: nudz_scrollimage.hpp:162
float minSpeed
minimum allowed speed
Definition: nudz_scrollimage.hpp:160
uint32_t last_tick
last called time in microseconds
Definition: nudz_scrollimage.hpp:165
int8_t xdirection
x scroll direction
Definition: nudz_scrollimage.hpp:166
uint32_t ydecal
start y coordinates
Definition: nudz_scrollimage.hpp:164
int8_t ydirection
y scroll direction
Definition: nudz_scrollimage.hpp:167
uint32_t xdecal
start x coordinates
Definition: nudz_scrollimage.hpp:163
Display an image "Violon saoul" scrolling around. User ramp changes scroll speed and direction.
Definition: nudz_scrollimage.hpp:157
2d vector in any space
Definition: vector_math.h:15
float dot(const vec2d &other) const
Dot product in 2D, representing the arcos of the angle between this vector and another.
Definition: vector_math.h:27
float x
x coordinate in 2D
Definition: vector_math.h:16
float y
y coordinate in 2D
Definition: vector_math.h:17