Last active
March 1, 2023 07:08
-
-
Save focalintent/5f97216341278976e749 to your computer and use it in GitHub Desktop.
Showing off some pixel mapping and rotating
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// base GridMap class. Allows from mapping from an X x Y grid of | |
// T values to an MX x MY grid of T values (where | |
// MX and MY are greater than X and Y respectively), using linear | |
// interpolation to fill in the gaps. Optionally allows for rotating | |
// around the center point. Subclasses should provide an implementation | |
// for the interpolate method, appropriate to the type of data being mapped | |
template<int X, int Y, int MX, int MY, class T> class AbstractGridMap { | |
int revcosval,revsinval; | |
uint8_t angle; | |
inline void rtpt_rev(int & x, int & y) { | |
if(angle) { | |
int _x = x - MX/2; | |
int _y = y - MX/2; | |
x = (_x * revcosval) - (_y * revsinval); | |
y = (_x * revsinval) + (_y * revcosval); | |
x /= 256; | |
y /= 256; | |
x += (MX/2); | |
y += (MX/2); | |
} | |
} | |
public: | |
T m_Data[X][Y]; | |
public: | |
AbstractGridMap() { rotate(0); } | |
void rotate(uint8_t rotate) { | |
angle=rotate; | |
revcosval = 2 * ((int)cos8(256-angle)-128); | |
revsinval = 2 * ((int)sin8(256-angle)-128); | |
} | |
T* operator[](int x) { return m_Data[x]; } | |
virtual T interpolate(int bx, int by, int fx, int fy) = 0; | |
T operator()(int x, int y) { | |
// reverse rotate x/y | |
rtpt_rev(x,y); | |
// compute inner grid point | |
int bx = (x * (X-1))/MX; | |
int by = (y * (Y-1))/MY; | |
// get the delta between the inner grid point and the requested location | |
int dx = x - ((bx) * MX) / (X-1); | |
int dy = y - ((by) * MY) / (Y-1); | |
// convert the delta into a 0-255 frac8 value | |
uint8_t fx = (dx*256) / MX; | |
uint8_t fy = (dy*256) / MX; | |
return interpolate(bx,by,fx,fy); | |
} | |
}; | |
template<int X, int Y, int MX, int MY> class CRGBGridMap : public AbstractGridMap<X,Y,MX,MY,CRGB> { | |
public: | |
CRGBGridMap() { this->rotate(0); } | |
virtual CRGB interpolate(int bx, int by, int fx, int fy) { | |
CRGB x1(this->m_Data[bx][by].lerp8(this->m_Data[bx+1][by],fx)); | |
CRGB x2(this->m_Data[bx][by+1].lerp8(this->m_Data[bx+1][by+1],fx)); | |
return x1.lerp8(x2,fy); | |
} | |
}; | |
template<int X, int Y, int MX, int MY> class GridMap : public AbstractGridMap<X,Y,MX,MY,uint16_t> { | |
public: | |
GridMap() { memset(this->m_Data,0,sizeof(uint16_t)*X*Y); } | |
virtual uint16_t interpolate(int bx, int by, int fx, int fy) { | |
uint16_t x1 = lerp16by8(this->m_Data[bx][by],this->m_Data[bx+1][by],fx); | |
uint16_t x2 = lerp16by8(this->m_Data[bx][by+1], this->m_Data[bx+1][by+1],fx); | |
return lerp16by8(x1,x2,fy); | |
} | |
}; | |
// An example of the fire demo. This assumes that there's a pair of arrays setup: | |
// int X[NUM_LEDS] = { 1,2,... }; | |
// int Y[NUM_LEDS] = {10, 11, ... }; | |
// so that you can get the X/Y mapped coordinates of a given led with X[i] and Y[i]. Also, | |
// note that i've normalized the X/Y mappings to be 0-255. | |
#define FIRE_GRID 17 | |
void Fire2014() | |
{ | |
// Array of temperature readings at each simulation cell | |
static byte heat[FIRE_GRID][FIRE_GRID]; | |
// Map from a 17x17 CRGB grid of computed color cells to the 255x255 grid of | |
// leds. | |
static CRGBGridMap<FIRE_GRID, FIRE_GRID, 255, 255> heatColors; | |
// uncomment the following two lines to spin the fire around | |
// static uint8_t rotate = 0; | |
// heatColors.rotate(rotate++); | |
// Step 1. Cool down every cell a little | |
for(int col = 0; col < (FIRE_GRID); col++) { | |
for( int i = 0; i < FIRE_GRID; i++) { | |
heat[col][i] = qsub8( heat[col][i], random8(0, ((COOLING * 10) / FIRE_GRID) + 2)); | |
} | |
// Step 2. Heat from each cell drifts 'up' and diffuses a little | |
for( int k= FIRE_GRID - 3; k > 2; k--) { | |
heat[col][k] = (heat[col][k - 1] + heat[col][k - 2] + heat[col][k - 2] ) / 3; | |
} | |
// Step 3. Randomly ignite new 'sparks' of heat near the bottom | |
if( random8() < SPARKING ) { | |
int y = random8(3); | |
heat[col][y] = qadd8( heat[col][y], random8(160,255) ); | |
} | |
} | |
// Make heat colors | |
for(int i = 0; i < FIRE_GRID; i++) { | |
for(int j = 0; j < FIRE_GRID; j++) { | |
heatColors[i][j] = HeatColor(heat[i][j]); | |
} | |
} | |
// Map the heat colors into the array of leds | |
for(int i = 0; i < NUM_LEDS; i++) { | |
leds[i] = heatColors(X[i],Y[i]); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment