Thomas Kolb
25abc446b0
This massively improves glitches in functions like sin(t + sin(t)), as used in the RgbwPsychedelicAnimation. That animation is now almost flicker-free.
59 lines
2.2 KiB
C++
59 lines
2.2 KiB
C++
#include <algorithm>
|
|
|
|
#include "Animation/RgbwSinusAnimation.h"
|
|
|
|
RgbwSinusAnimation::RgbwSinusAnimation(Fader *fader,
|
|
const rgbw_val_array &speeds,
|
|
uint32_t speed_divider,
|
|
uint16_t brightness_scale)
|
|
: Animation(fader),
|
|
m_speeds(speeds),
|
|
m_speedDivider(speed_divider),
|
|
m_brightnessScale(brightness_scale),
|
|
m_phi{0,0,0,0},
|
|
m_overflowInterval(fasttrigon::LUT_SIZE * speed_divider)
|
|
{
|
|
reset();
|
|
}
|
|
|
|
void RgbwSinusAnimation::loop(uint64_t frame)
|
|
{
|
|
std::size_t nled = m_fader->modules_per_strip();
|
|
std::size_t nstrip = m_fader->strips();
|
|
|
|
if(!m_stopping) {
|
|
for(unsigned i = 0; i < m_speeds.size(); i++) {
|
|
m_phi[i] += m_speeds[i];
|
|
|
|
if(m_phi[i] > m_overflowInterval) {
|
|
m_phi[i] -= m_overflowInterval;
|
|
}
|
|
}
|
|
|
|
for(std::size_t led = 0; led < nled; led++) {
|
|
for(std::size_t strip = 0; strip < nstrip; strip++) {
|
|
uint32_t pixelphase = led * fasttrigon::LUT_SIZE / nled + strip * fasttrigon::LUT_SIZE / nstrip;
|
|
|
|
Fader::Color color{
|
|
static_cast<int16_t>(((fasttrigon::SCALE + fasttrigon::fastsin(m_phi[0] / m_speedDivider + pixelphase)) * m_brightnessScale) >> fasttrigon::PRECISION_BITS),
|
|
static_cast<int16_t>(((fasttrigon::SCALE + fasttrigon::fastsin(m_phi[1] / m_speedDivider + pixelphase)) * m_brightnessScale) >> fasttrigon::PRECISION_BITS),
|
|
static_cast<int16_t>(((fasttrigon::SCALE + fasttrigon::fastsin(m_phi[2] / m_speedDivider + pixelphase)) * m_brightnessScale) >> fasttrigon::PRECISION_BITS),
|
|
static_cast<int16_t>(((fasttrigon::SCALE + fasttrigon::fastsin(m_phi[3] / m_speedDivider + pixelphase)) * m_brightnessScale) >> (fasttrigon::PRECISION_BITS + 2))}; // white is too bright otherwise
|
|
|
|
m_fader->set_color(strip, led, color);
|
|
}
|
|
}
|
|
} else {
|
|
m_fader->fade_color(Fader::Color{0, 0, 0, 0});
|
|
}
|
|
|
|
m_fader->update();
|
|
m_running = !m_stopping || m_fader->something_changed();
|
|
}
|
|
|
|
void RgbwSinusAnimation::reset(void)
|
|
{
|
|
m_stopping = false;
|
|
m_running = true;
|
|
}
|