//Oldschool tunnel demo effect 
//fastled 16x16 matrix demo
//Yaroslaw Turbin 05.01.2021
//https://vk.com/ldirko
//https://www.reddit.com/user/ldirko/

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

#include "FastLED.h"
 
#define NUM_ROWS 16
#define NUM_COLS 16
#define NUM_LEDS NUM_ROWS * NUM_COLS
#define DATA_PIN 3
#define BRIGHTNESS 255
 
CRGB leds [NUM_LEDS];
byte dist [NUM_LEDS];
byte ang  [NUM_LEDS];
byte tex  [NUM_COLS][NUM_ROWS];

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

void genSqr_Angle(){
#define mn 22
#define scaledist 16
#define scaleang 16

for (int i = 0; i < NUM_COLS; i++) {
	for (int j = 0; j < NUM_ROWS; j++) {
		int temp = pow((i-NUM_COLS/2)*mn,2)+pow((j-NUM_ROWS/2)*mn,2);    
			byte distance = temp? 255-sqrt16(temp):255;
			dist [j*NUM_COLS+i] = distance/scaledist ; 
			byte angle = (atan2((i-NUM_COLS/2), (j-NUM_ROWS/2)) / PI)*128+127;
			ang [j*NUM_COLS+i] = angle/scaleang;
}}
}

void generateTex(){
#define noisescale 50
int t = millis()/2; 
for (byte i = 0; i < NUM_COLS; i++) {
	for (byte j = 0; j < NUM_ROWS; j++) {
		tex[i][j]= inoise8(i*noisescale+t, j*noisescale-t/8);
}}
}

void tunnel(){
for (int j = 0; j < NUM_ROWS; j++){ 
 int yindex = j*NUM_COLS;
  for (int i = 0; i < NUM_COLS; i++) {
		byte u = dist [yindex+i];
		byte v = ang  [yindex+i];
		byte color =  tex[u][v];
		leds[XY(i,j)] = ColorFromPalette (HeatColors_p, sub8(color/2,10),255);
}}
}

void loop() {
generateTex();
tunnel();
LEDS.show();
}

uint16_t XY (uint8_t x, uint8_t y) { return (y * NUM_COLS + x);}