I took a shot at porting Distortion Waves last night. First I did a more-or-less straight transliteration of the FastLED code (though I got rid of the gamma LUT and replaced the cosine LUT with a PB wave function) and that was OK, though there were lots of artefacts in the middle which I think were due to numeric overflows.
Then I started hacking away to make it more PB-like. I’ve now got it very simple and PB-friendly, but in the process of scaling from FastLED’s 0…255 intensities and Soulmate’s 1-20 coordinates to PB’s 0…1 world I lost track of what the scaling coefficients should be at each stage, so it’s now 95% correct but 100% wrong (i.e. the code looks good but the results don’t resemble the original).
I’m tired of looking at it, and feeling distinctly inadequate after seeing @zranger1’s Great Metaballs of Fire, so I’ll post it here as a starting point if someone with fresh eyes wants to carry it forward…
// Cobbled together from the original at: https://editor.soulmatelights.com/gallery/1089-distorsion-waves
// simple replacement for LUT
function cos_wave(proportion) { return 1-wave(proportion+0.25); }
function beatsin(bpm) { return wave(time(0.91552734375/bpm)); }
// adjustments
timeBase = 0.1;
speed = 5;
w = 2;
export function beforeRender(delta) {
a1=time(timeBase); a2=time(2*timeBase); a3=time(3*timeBase);
cx1 = beatsin(10-speed); cy1 = beatsin(12-speed);
cx2 = beatsin(13-speed); cy2 = beatsin(15-speed);
cx3 = beatsin(17-speed); cy3 = beatsin(14-speed);
}
export function render2D(index, x, y) {
/*
byte rdistort = cos_wave[ (cos_wave[((x << 3) + a1) & 255] + cos_wave[ ((y << 3) - a2) & 255] + a3 ) & 255 ] >> 1;
byte gdistort = cos_wave[ (cos_wave[((x << 3) - a2) & 255] + cos_wave[ ((y << 3) + a3) & 255] + a1 + 32) & 255 ] >> 1;
byte bdistort = cos_wave[ (cos_wave[((x << 3) + a3) & 255] + cos_wave[ ((y << 3) - a1) & 255] + a2 + 64) & 255 ] >> 1;
*/
coeff1 = 0.06;
r1 = coeff1*cos_wave(x+a1);
g1 = coeff1*cos_wave(x-a2);
b1 = coeff1*cos_wave(x+a3);
coeff2 = 1;
r2 = coeff2*cos_wave(y-a2);
g2 = coeff2*cos_wave(y+a1);
b2 = coeff2*cos_wave(y-a2);
coeff3 = 1;
rdistort = coeff3*cos_wave(r1+r2+a3);
gdistort = coeff3*cos_wave(g1+g2+a1+1/8);
bdistort = coeff3*cos_wave(b1+b2+a2+1/4);
/*
byte valueR = rdistort + w * (a1 - (((xoffs - cx1) * (xoffs - cx1) + (yoffs - cy1) * (yoffs - cy1)) >> 7));
byte valueG = gdistort + w * (a2 - (((xoffs - cx2) * (xoffs - cx2) + (yoffs - cy2) * (yoffs - cy2)) >> 7));
byte valueB = bdistort + w * (a3 - (((xoffs - cx3) * (xoffs - cx3) + (yoffs - cy3) * (yoffs - cy3)) >> 7));
*/
dx1 = x-cx1; dy1 = y-cy1; dx2 = x-cx2; dy2 = y-cy2; dx3 = x-cx3; dy3 = y-cy3;
r = cos_wave(rdistort + w*(a1-(dx1*dx1 + dy1*dy1)));
g = cos_wave(gdistort + w*(a2-(dx2*dx2 + dy2*dy2)));
b = cos_wave(bdistort + w*(a3-(dx3*dx3 + dy3*dy3)));
rgb(r*r, g*g, b*b);
}