FastLED 3.9.15
Loading...
Searching...
No Matches

◆ flowAdvect()

void fl::FlowFieldFP::flowAdvect ( i32 dt_raw)
private

Definition at line 813 of file flowfield.cpp.hpp.

813 {
814 int w = mState.width;
815 int h = mState.height;
816
817 // fade = pow(0.5, dt / halfLife) — pure fixed-point
818 constexpr s16x16 half_fp(0.5f);
819 constexpr s16x16 min_persistence(0.001f);
820 s16x16 dt_fp = s16x16::from_raw(dt_raw);
821 s16x16 halfLife_fp = mPersistence_fp.raw() > min_persistence.raw()
823 : min_persistence;
824 i32 fade_raw = s16x16::pow(half_fp, dt_fp / halfLife_fp).raw();
825
826 i32 shift_raw = mFlowShift_fp.raw();
827
828 i32 w_q16 = static_cast<i32>(w) << 16;
829 i32 h_q16 = static_cast<i32>(h) << 16;
830
831 // Grab raw array pointers — avoids vector operator[] overhead in hot loops.
832 i32 *__restrict__ r = mState.r.data();
833 i32 *__restrict__ g = mState.g.data();
834 i32 *__restrict__ b = mState.b.data();
835 i32 *__restrict__ tr = mState.tr.data();
836 i32 *__restrict__ tg = mState.tg.data();
837 i32 *__restrict__ tb = mState.tb.data();
838
839 // Pass 1: horizontal row shift
840 // Lerp: a + ((b-a)*f >> 16) uses 1 i64 mul instead of 2.
841 // Note: f = (-sh) & 0xFFFF is constant per row; the compiler hoists it at -O3.
842 for (int y = 0; y < h; y++) {
843 i32 sh = static_cast<i32>((static_cast<i64>(mState.y_prof[y]) * shift_raw) >> 16);
844 int row_base = y * w;
845 for (int x = 0; x < w; x++) {
846 i32 sx_raw = (static_cast<i32>(x) << 16) - sh;
847 // Modular wrap (single iteration sufficient for typical shift values)
848 if (sx_raw < 0) sx_raw += w_q16;
849 else if (sx_raw >= w_q16) sx_raw -= w_q16;
850 // Safety for extreme shift values
851 if (sx_raw < 0) sx_raw += w_q16;
852 if (sx_raw >= w_q16) sx_raw -= w_q16;
853
854 int ix0 = sx_raw >> 16; // Already in [0, w-1] after wrap
855 int ix1 = (ix0 + 1 < w) ? ix0 + 1 : 0;
856 i32 f = sx_raw & 0xFFFF;
857
858 int src0 = row_base + ix0;
859 int src1 = row_base + ix1;
860 int dst = row_base + x;
861
862 tr[dst] = r[src0] + static_cast<i32>((static_cast<i64>(r[src1] - r[src0]) * f) >> 16);
863 tg[dst] = g[src0] + static_cast<i32>((static_cast<i64>(g[src1] - g[src0]) * f) >> 16);
864 tb[dst] = b[src0] + static_cast<i32>((static_cast<i64>(b[src1] - b[src0]) * f) >> 16);
865 }
866 }
867
868 // Pass 2: vertical column shift + fade
869 // Note: f = (-sh) & 0xFFFF is constant per column; the compiler hoists it at -O3.
870 for (int x = 0; x < w; x++) {
871 i32 sh = static_cast<i32>((static_cast<i64>(mState.x_prof[x]) * shift_raw) >> 16);
872 for (int y = 0; y < h; y++) {
873 i32 sy_raw = (static_cast<i32>(y) << 16) - sh;
874 if (sy_raw < 0) sy_raw += h_q16;
875 else if (sy_raw >= h_q16) sy_raw -= h_q16;
876 if (sy_raw < 0) sy_raw += h_q16;
877 if (sy_raw >= h_q16) sy_raw -= h_q16;
878
879 int iy0 = sy_raw >> 16;
880 int iy1 = (iy0 + 1 < h) ? iy0 + 1 : 0;
881 i32 f = sy_raw & 0xFFFF;
882
883 int src0 = iy0 * w + x;
884 int src1 = iy1 * w + x;
885 int dst = y * w + x;
886
887 // Lerp + fade in two steps (2 i64 muls per channel instead of 3)
888 i32 interp_r = tr[src0] + static_cast<i32>((static_cast<i64>(tr[src1] - tr[src0]) * f) >> 16);
889 i32 interp_g = tg[src0] + static_cast<i32>((static_cast<i64>(tg[src1] - tg[src0]) * f) >> 16);
890 i32 interp_b = tb[src0] + static_cast<i32>((static_cast<i64>(tb[src1] - tb[src0]) * f) >> 16);
891
892 r[dst] = static_cast<i32>((static_cast<i64>(interp_r) * fade_raw) >> 16);
893 g[dst] = static_cast<i32>((static_cast<i64>(interp_g) * fade_raw) >> 16);
894 b[dst] = static_cast<i32>((static_cast<i64>(interp_b) * fade_raw) >> 16);
895 }
896 }
897}
FlowFieldFPState mState
Definition flowfield.h:400
s16x16 mFlowShift_fp
Definition flowfield.h:406
s16x16 mPersistence_fp
Definition flowfield.h:408
static constexpr FASTLED_FORCE_INLINE s16x16 from_raw(i32 raw) FL_NOEXCEPT
Definition s16x16.h:54
constexpr i32 raw() const FL_NOEXCEPT
Definition s16x16.h:60
static FASTLED_FORCE_INLINE s16x16 pow(s16x16 base, s16x16 exp) FL_NOEXCEPT
Definition s16x16.h:235
void fade_raw(CRGB *leds, fl::u16 num_leds, fl::u8 fadeBy)
fl::i64 i64
Definition s16x16x4.h:222

References fl::fade_raw(), fl::s16x16::from_raw(), mFlowShift_fp, mPersistence_fp, mState, fl::s16x16::pow(), fl::s16x16::raw(), fl::x, and fl::y.

Referenced by drawImpl().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: