//Heart bumpmap
//fastled 16x16 matrix demo
//Yaroslaw Turbin 29.12.2020
//https://vk.com/ldirko
//https://www.reddit.com/user/ldirko/

//https://wokwi.com/arduino/projects/286414164431208972
//non commercial use

#include "FastLED.h"

// Matrix size
#define NUM_ROWS 16
#define NUM_COLS 16
#define NUM_LEDS NUM_ROWS * NUM_COLS

// LEDs pin
#define DATA_PIN 3

// LED brightness
#define BRIGHTNESS 255

// Define the array of leds
CRGB leds[NUM_LEDS];
CRGB chsvLut[256];
#define bumpsize 18  //bumpsize is bigger leds by 1 witn each side
int8_t bump[bumpsize*bumpsize] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0b, 0x12, 0x18, 0x13, 0x09, 0x0a, 0x15, 0x18, 0x12, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0b, 0x1e, 0x26, 0x2c, 0x30, 0x2f, 0x30, 0x30, 0x2c, 0x26, 0x1b, 0x0b, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x17, 0x26, 0x32, 0x39, 0x3e, 0x41, 0x42, 0x3e, 0x39, 0x31, 0x26, 0x15, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x1c, 0x2d, 0x39, 0x3f, 0x43, 0x47, 0x47, 0x44, 0x3f, 0x37, 0x2d, 0x1a, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x2e, 0x38, 0x41, 0x47, 0x46, 0x46, 0x45, 0x40, 0x38, 0x2c, 0x16, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x09, 0x26, 0x36, 0x3e, 0x43, 0x46, 0x46, 0x42, 0x3f, 0x35, 0x25, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0b, 0x28, 0x38, 0x3e, 0x41, 0x42, 0x3f, 0x37, 0x28, 0x09, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x2c, 0x38, 0x3c, 0x3c, 0x37, 0x2a, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x2d, 0x34, 0x34, 0x2c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x11, 0x2b, 0x29, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; 

void setup() {
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
	generateCHSVlut();
}

void generateCHSVlut(){
for (int j= 0; j<256; j++)
// chsvLut[j]=CHSV(100,255,j);  //for one color
chsvLut[j] = HeatColor(j/1.4);  //256 pallette color
}

void Bumpmap(int8_t lightx, int8_t lighty){
int col;
int yindex=bumpsize+1;
int8_t vly=lighty;
for (int y = 0; y < NUM_ROWS; y++) {
++vly;
int8_t vlx=lightx;
for (int x = 0; x < NUM_COLS; x++) {
++vlx;
int8_t nx=bump[x+yindex+1]-bump[x+yindex-1];
int8_t ny=bump[x+yindex+bumpsize]-bump[x+yindex-bumpsize];
byte difx=abs8(vlx*6-nx);
byte dify=abs8(vly*6-ny);
int temp = difx*difx+dify*dify;  //to do: if number of height <=16 its possible to make lut table [16][16] with precalculate
// col = 255-(temp>>5);   // its  faster and more contrast)
col = temp? 255-sqrt16(temp)*3 : 255;  //more realistic light
if (col<0) col=0;
leds[XY(x,y)] = chsvLut[col]; //thx satubarosu ))
}
yindex+=bumpsize;
}
}

void loop() {
#define BumpmapSpeed 30
int8_t lightX = 1- beatsin8(BumpmapSpeed,1,17,64);
int8_t lightY = 1- beatsin8(BumpmapSpeed-10,1,17);
Bumpmap(lightX, lightY);
FastLED.show();
}

uint16_t XY (uint8_t x, uint8_t y) { return (y * NUM_COLS + x);}		//simple function to find led number in led matrix,
																	//change this to your routine
																	//or generate XY function for your matrix there:
																	//https://macetech.github.io/FastLED-XY-Map-Generator/