Advertisement
ezdiver67

L3D 16 Cube demo with fast Plasma

Sep 7th, 2015
483
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 38.59 KB | None | 0 0
  1. // Updated 2.11.2015 EZU for const correctness and reference parameter passing.
  2. // Avoids memory allocation and deallocation each time an object is passed as a parameter - performance gain.
  3.  
  4. #include <math.h>
  5. #include "application.h"
  6.  
  7. SYSTEM_THREAD(ENABLED);
  8. SYSTEM_MODE(AUTOMATIC);  //don't connect to the internet on boot
  9.  
  10.  
  11. // IMPORTANT: Set pixel COUNT, PIN and TYPE
  12. #define PIXEL_PIN D0
  13. #define totalPIXEL 4096
  14. #define stripPIXEL totalPIXEL/8    //THERE IS FOUR PINS TO DRIVE EACH STRIPS
  15. #define PIXEL_TYPE WS2812B
  16.  
  17. #define SIZE 16
  18. #define PI 3.14159
  19.  
  20. #define DEMO_ROUTINES 5
  21. #define FIREWORKS 0
  22. #define FASTPLASMA 1
  23. #define ROMAN_CANDLE 2
  24. #define FFT_JOY 3
  25. #define CIRCLES 4
  26.  
  27. #define PLASMA 5
  28. #define DISPLAY_TEST 6
  29.  
  30.  
  31.  
  32. /**********************************
  33.  * flip variables *
  34.  * ********************************/
  35.  //accelerometer pinout
  36. #define X A0
  37. #define Y A1
  38. #define Z A6
  39. #define NUM_SAMPLES 100
  40. int accelerometer[3];
  41. unsigned long totals[3];
  42. int runningAverage[3];
  43. boolean whack[3];
  44. boolean whacked=false;
  45. #define WHACK_X 20
  46. #define WHACK_Y 20
  47. #define WHACK_Z 20
  48.  
  49. bool autoCycle=true;    //start on autocycle by default
  50.  
  51. /*******************************
  52.  * fade variables *
  53.  * ****************************/
  54. bool fading=false;
  55. int fadeValue=255;
  56. int fadeSpeed=2;
  57.  
  58. /*  datatype definitions
  59. */
  60. /**   An RGB color. */
  61. struct Color
  62. {
  63.   unsigned char red, green, blue;
  64.  
  65.   Color(int r, int g, int b) : red(r), green(g), blue(b) {}
  66.   Color() : red(0), green(0), blue(0) {}
  67. };
  68.  
  69. /********************************
  70.  * zplasma variables *
  71.  * *****************************/
  72. float phase = 0.0;
  73. long fastPhase=0;
  74. float phaseIncrement = 0.035; // Controls the speed of the moving points. Higher == faster
  75. int fastPhaseIncrement = 1; // Controls the speed of the moving points. Higher == faster
  76. int fastColorStretch = 4; // will divide rather than multiply
  77. float colorStretch = 0.23; // Higher numbers will produce tighter color bands
  78. float plasmaBrightness = 0.2;
  79. Color plasmaColor;
  80.  
  81.  
  82.  
  83. /**   A point in 3D space.  */
  84. struct Point
  85. {
  86.   float x;
  87.   float y;
  88.   float z;
  89.   Point() : x(0), y(0), z(0) {}
  90.   Point(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
  91. };
  92.  
  93. /**   An integer point in 3D space.  */
  94. struct Point_i
  95. {
  96.   int x;
  97.   int y;
  98.   int z;
  99.   Point_i() : x(0), y(0), z(0) {}
  100.   Point_i(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {}
  101. };
  102.  
  103. struct Rocket
  104. {
  105.     float x,y,z;
  106.     float xVel, yVel, zVel;
  107.     float gravity;
  108.     Color col;
  109.     Rocket():x((SIZE-1)/2), y(0), z((SIZE-1)/2), col(Color(255,0,0)){}
  110. };
  111.  
  112.  
  113. #define NUM_ROCKETS 50
  114. Rocket rockets[NUM_ROCKETS];
  115. float offset=0;
  116.  
  117. int y=0;
  118. int yinc=1;
  119. int maxBrightness=50;
  120.  
  121. int demo=FIREWORKS;
  122.  
  123. #define MICROPHONE A7
  124. #define GAIN_CONTROL D5
  125.  
  126. /*********************************
  127.  * FFTJoy variables *
  128.  * *******************************/
  129. #define M 5
  130. float real[(int)pow(2,M)];
  131. float imaginary[(int)pow(2,M)];
  132. float maxValue=0;
  133. float sample;
  134.  
  135.  
  136. /******************************
  137.  * fireworks variables *
  138.  * ****************************/
  139. int centerX, centerY, centerZ;
  140. int launchX, launchZ;
  141. int red, green, blue;
  142. float radius=0;
  143. float speed;
  144. bool showRocket;
  145. bool exploded;
  146. bool dead;
  147. float xInc, yInc, zInc;
  148. float rocketX, rocketY, rocketZ;
  149. float launchTime;
  150. int maxSize;
  151. int fireworkRes;
  152. Color rocketColor, fireworkColor;
  153.  
  154. uint8_t PIXEL_RGB[totalPIXEL*3];  //EACH PIXELS HAS 3 BYTES DATA
  155.  
  156. // function prototypes
  157. int displayTestIteration=0;
  158.  
  159. void displayTest();
  160.  
  161. void initFireworks();
  162. void initCircles();
  163. void initRockets();
  164. void initCloudButton();
  165. void initAccelerometer();
  166. void setVoxel(int x, int y, int z, const Color& col);
  167. void setVoxel(const Point& p, const Color& col);
  168. Color getVoxel(int x, int y, int z);
  169. Color getVoxel(const Point& p);
  170. void line(const Point& p1, const Point& p2, const Color& col);
  171. void line(int x1, int y1, int z1, int x2, int y2, int z2, const Color& col);
  172. void sphere(const Point& center, float radius, const Color& col);
  173. void sphere(const Point& center, float radius, const Color& col, int res);
  174. void sphere(float x, float y, float z, float radius, const Color& col);
  175. void sphere(float x, float y, float z, float radius, const Color& col, int res);
  176. void background(const Color& col);
  177. Color colorMap(float val, float minVal, float maxVal);
  178. Color lerpColor(const Color& a, const Color& b, int val, int minVal, int maxVal);
  179. Point add(const Point& a, const Point& b);
  180. void fft_joy();
  181. short FFT(short int dir,int m,float *x,float *y);
  182. void fade();
  183. void mirror();
  184. void updateFireworks();
  185. void circles();
  186. void show();
  187. void setFadeSpeed();
  188. void prepRocket();
  189. float distance(float x, float y, float z, float x1, float y1, float z1);
  190.  
  191.  
  192. int frame;
  193.  
  194. Point poly1[4];
  195. float poly1Angles[4];
  196. float poly1AnglesInc[4];
  197.  
  198. Point poly2[4];
  199. float poly2Angles[4];
  200. float poly2AnglesInc[4];
  201.  
  202. Point poly3[4];
  203. float poly3Angles[4];
  204. float poly3AnglesInc[4];
  205.  
  206. float poly1Color, poly2Color, poly3Color;
  207. float poly1ColorInc=0.001, poly2ColorInc=0.0005, poly3ColorInc=0.0007;
  208.  
  209. Point center;
  210. unsigned int lastDemo=0;
  211. #define DEMO_TIME 30000
  212. int timeout=0;
  213.  
  214. bool onlinePressed=false;
  215. bool lastOnline=true;
  216. #define BUTTON D6 //press this button to connect to the internet
  217. #define MODE D4
  218.  
  219. void setup()
  220. {
  221.     randomSeed(analogRead(A0));
  222.     Serial.begin(115200);
  223.       pinMode(GAIN_CONTROL, OUTPUT);
  224.       digitalWrite(GAIN_CONTROL, LOW);
  225.     initFireworks();
  226.     initCircles();
  227.     initRockets();
  228.     initCloudButton();
  229.     initAccelerometer();
  230.     pinMode(D0,OUTPUT);  //PB7
  231.     pinMode(D1,OUTPUT); //PB6
  232.     pinMode(D2,OUTPUT);  //BP5
  233.     pinMode(D3,OUTPUT);  //PB4
  234.     pinMode(A2,OUTPUT);  //PA4
  235.     pinMode(A3,OUTPUT); //PA5
  236.     pinMode(A4,OUTPUT);  //BA6
  237.     pinMode(A5,OUTPUT);  //PA7
  238.  
  239.     pinMode(D7, OUTPUT);
  240.     digitalWrite(D7, HIGH);
  241. }
  242.  
  243. //initializes the running average values for the accelerometer
  244. //I just set them to the first reading of the accelerometer on boot -- this is an imperfect method,
  245. //but it gets the rolling average very close it its eventual value
  246. //I chose to base it off of each cube's individual ADC reading, rather than hardcode the values from my sample cube
  247. void initAccelerometer()
  248. {
  249.     runningAverage[0]=analogRead(X);
  250.     runningAverage[1]=analogRead(Y);
  251.     runningAverage[2]=analogRead(Z);
  252. }
  253.  
  254. //sets up the online/offline switch
  255. void initCloudButton()
  256. {
  257.   //set the input mode for the 'connect to cloud' button
  258.   pinMode(BUTTON, INPUT_PULLUP);
  259.   pinMode(MODE, INPUT_PULLUP);
  260.     if(!digitalRead(MODE))  //if the wifi button is held down on boot, do a hard reset.  At any other time, keep the firmware, but try to add new wifi creds
  261.     {
  262.         WiFi.on();
  263.         WiFi.clearCredentials();
  264.         System.factoryReset();
  265.     }
  266.     //a.k.a. onlinePressed is HIGH when the switch is set to 'online' and LOW when the switch is set to 'offline'
  267.     onlinePressed=!digitalRead(BUTTON);
  268.     if(onlinePressed)
  269.         WiFi.connect();
  270. }
  271.  
  272. //checks to see if the 'online/offline' switch is switched
  273. void checkCloudButton()
  274. {
  275.     //if the 'connect to cloud' button is pressed, try to connect to wifi.
  276.     //otherwise, run the program
  277.     //note -- how does this behave when there are no wifi credentials loaded on the spark?
  278.  
  279.     //onlinePressed is HIGH when the switch is _not_ connected and LOW when the switch is connected
  280.     //a.k.a. onlinePressed is HIGH when the switch is set to 'online' and LOW when the switch is set to 'offline'
  281.     onlinePressed=!digitalRead(BUTTON);
  282.  
  283.     if((onlinePressed)&&(!lastOnline))  //marked as 'online'
  284.     {
  285.         lastOnline=onlinePressed;
  286.         WiFi.connect();
  287.     }
  288.  
  289.     else if((!onlinePressed)&&(lastOnline))  //marked as 'offline'
  290.     {
  291.         lastOnline=onlinePressed;
  292.         WiFi.disconnect();
  293.     }
  294.  
  295.     lastOnline=onlinePressed;
  296.  
  297.     if(!digitalRead(MODE))
  298.         WiFi.listen();
  299. }
  300.  
  301.  
  302. /********************************
  303.  * zplasma functions *
  304.  * *****************************/
  305.  
  306. void zPlasma()
  307. {
  308.  
  309.     phase += phaseIncrement;
  310.     // The two points move along Lissajious curves, see: http://en.wikipedia.org/wiki/Lissajous_curve
  311.     // We want values that fit the LED grid: x values between 0..15, y values between 0..15, z values between 0..15
  312.     // The sin() function returns values in the range of -1.0..1.0, so scale these to our desired ranges.
  313.     // The phase value is multiplied by various constants; I chose these semi-randomly, to produce a nice motion.
  314.     Point p1 = { (sin(phase*1.000)+1.0) * 8.0, (sin(phase*1.310)+1.0) * 8.0,  (sin(phase*1.380)+1.0) * 8.0};
  315.     Point p2 = { (sin(phase*1.770)+1.0) * 8.0, (sin(phase*2.865)+1.0) * 8.0,  (sin(phase*1.410)+1.0) * 8.0};
  316.     Point p3 = { (sin(phase*0.250)+1.0) * 8.0, (sin(phase*0.750)+1.0) * 8.0,  (sin(phase*0.380)+1.0) * 8.0};
  317.  
  318.     byte row, col, dep;
  319.  
  320.     // For each row
  321.     for(row=0; row<16; row++) {
  322.         float row_f = float(row); // Optimization: Keep a floating point value of the row number, instead of recasting it repeatedly.
  323.  
  324.         // For each column
  325.         for(col=0; col<16; col++) {
  326.             float col_f = float(col); // Optimization.
  327.  
  328.             // For each depth
  329.             for(dep=0; dep<16; dep++) {
  330.                 float dep_f = float(dep); // Optimization.
  331.  
  332.                 // Calculate the distance between this LED, and p1.
  333.                 Point dist1 = { col_f - p1.x, row_f - p1.y,  dep_f - p1.z }; // The vector from p1 to this LED.
  334.                 float distance1 = sqrt( dist1.x*dist1.x + dist1.y*dist1.y + dist1.z*dist1.z);
  335.  
  336.                 // Calculate the distance between this LED, and p2.
  337.                 Point dist2 = { col_f - p2.x, row_f - p2.y,  dep_f - p2.z}; // The vector from p2 to this LED.
  338.                 float distance2 = sqrt( dist2.x*dist2.x + dist2.y*dist2.y + dist2.z*dist2.z);
  339.  
  340.                 // Calculate the distance between this LED, and p3.
  341.                 Point dist3 = { col_f - p3.x, row_f - p3.y,  dep_f - p3.z}; // The vector from p3 to this LED.
  342.                 float distance3 = sqrt( dist3.x*dist3.x + dist3.y*dist3.y + dist3.z*dist3.z);
  343.  
  344.                 // Warp the distance with a sin() function. As the distance value increases, the LEDs will get light,dark,light,dark,etc...
  345.                 // You can use a cos() for slightly different shading, or experiment with other functions.
  346.                 float color_1 = distance1; // range: 0.0...1.0
  347.                 float color_2 = distance2;
  348.                 float color_3 = distance3;
  349.                 float color_4 = (sin( distance1 * distance2 * colorStretch )) + 2.0 * 0.5;
  350.                 // Square the color_f value to weight it towards 0. The image will be darker and have higher contrast.
  351.                 color_1 *= color_1 * color_4;
  352.                 color_2 *= color_2 * color_4;
  353.                 color_3 *= color_3 * color_4;
  354.                 color_4 *= color_4;
  355.                 // Scale the color up to 0..7 . Max brightness is 7.
  356.                 //strip.setPixelColor(col + (8 * row), strip.Color(color_4, 0, 0) );
  357.                 plasmaColor.red=color_1*plasmaBrightness;
  358.                 plasmaColor.green=color_2*plasmaBrightness;
  359.                 plasmaColor.blue=color_3*plasmaBrightness;
  360.  
  361.                 setVoxel(row,col,dep,plasmaColor);
  362.             }
  363.         }
  364.     }
  365. }
  366.  
  367. // all inputs need to be multiplied by 572
  368. inline int ifsin( int x )
  369. {
  370.   // convert float to integer (32768 units times 2*pi / 360 degrees )
  371.   //int x= angle * 572;
  372.  
  373.   static const int qN = 13, qA= 12, qP= 15, qR= 2*qN-qP, qS= qN+qP+1-qA;
  374.   //x *= 166886; // -- conversion to radians
  375.   x= x<<(30-qN); // 32768 steps per circle (360degrees, 2pi radians)
  376.   // shift to full s32 range (Q13->Q30)
  377.   if( (x^(x<<1)) < 0)     // test for quadrant 1 or 2
  378.   x= (1<<31) - x;
  379.   x= x>>(30-qN);
  380.  
  381.   // convert result to -1024..+1024
  382.   return (x * ( (3<<qP) - (x*x>>qR) ) >> qS) >> 2;
  383. }
  384.  
  385. /********************************
  386.  * fastPlasma functions *
  387.  * *****************************/
  388.  
  389. inline unsigned int isqrt(unsigned long a) {
  390.      unsigned int rem = 0;
  391.      int root = 0;
  392.      int i;
  393.  
  394.      for (i = 0; i < 16; i++) {
  395.          root <<= 1;
  396.          rem <<= 2;
  397.          rem += a >> 30;
  398.          a <<= 2;
  399.  
  400.          if (root < rem) {
  401.              root++;
  402.              rem -= root;
  403.              root++;
  404.          }
  405.      }
  406.  
  407.      return (unsigned short) (root >> 1);
  408.  }
  409.  
  410. void fastPlasma()
  411. {
  412.  
  413.     fastPhase += fastPhaseIncrement;
  414.     // The two points move along Lissajious curves, see: http://en.wikipedia.org/wiki/Lissajous_curve
  415.     // We want values that fit the LED grid: x values between 0..15, y values between 0..15, z values between 0..15
  416.     // The sin() function returns values in the range of -1.0..1.0, so scale these to our desired ranges.
  417.     // The phase value is multiplied by various constants; I chose these semi-randomly, to produce a nice motion.
  418.     Point_i p1 = { (ifsin(fastPhase*572)+1024)/128, (ifsin(fastPhase*749)+1024) /128,  (ifsin(fastPhase*789)+1024) /128};
  419.     Point_i p2 = { (ifsin(fastPhase*1144)+1024)/128, (ifsin(fastPhase*1639)+1024) /128,  (ifsin(fastPhase*807)+1024) /128};
  420.     Point_i p3 = { (ifsin(fastPhase*143)+1024)/128, (ifsin(fastPhase*429)+1024) /128,  (ifsin(fastPhase*217)+1024) /128};
  421.  
  422.     byte row, col, dep;
  423.  
  424.     for(row=0; row<16; row++) {
  425.         for(col=0; col<16; col++) {
  426.             for(dep=0; dep<16; dep++) {
  427.  
  428.                 // Calculate the distance between this LED, and p1.
  429.                 Point_i dist1 = { col - p1.x, row - p1.y,  dep - p1.z }; // The vector from p1 to this LED.
  430.                 int distance1 = isqrt( dist1.x*dist1.x + dist1.y*dist1.y + dist1.z*dist1.z);
  431.  
  432.                 // Calculate the distance between this LED, and p2.
  433.                 Point_i dist2 = { col - p2.x, row - p2.y,  dep - p2.z}; // The vector from p2 to this LED.
  434.                 int distance2 = isqrt( dist2.x*dist2.x + dist2.y*dist2.y + dist2.z*dist2.z);
  435.  
  436.                 // Calculate the distance between this LED, and p3.
  437.                 Point_i dist3 = { col - p3.x, row - p3.y,  dep - p3.z}; // The vector from p3 to this LED.
  438.                 int distance3 = isqrt( dist3.x*dist3.x + dist3.y*dist3.y + dist3.z*dist3.z);
  439.  
  440.                 // Warp the distance with a sin() function. As the distance value increases, the LEDs will get light,dark,light,dark,etc...
  441.                 // You can use a cos() for slightly different shading, or experiment with other functions.
  442.                 int color_1  = distance1; // range: 0...16
  443.                 int color_2 = distance2;
  444.                 int color_3 = distance3;
  445.                 int color_4 = (ifsin( distance1 * distance2 * 143 ) + 1024) /128;
  446.                 // Square the color_f value to weigh it towards 0. The image will be darker and have higher contrast.
  447.                 color_1 *= color_1 * color_4;
  448.                 color_2 *= color_2 * color_4;
  449.                 color_3 *= color_3 * color_4;
  450.  
  451.                 // Scale the color up to 0..7 . Max brightness is 7.
  452.                 //strip.setPixelColor(col + (8 * row), strip.Color(color_4, 0, 0) );
  453.                 plasmaColor.red=color_1/290;
  454.                 plasmaColor.green=color_2/290;
  455.                 plasmaColor.blue=color_3/290;
  456.  
  457.                 setVoxel(row,col,dep,plasmaColor);
  458.             }
  459.         }
  460.     }
  461. }
  462.  
  463.  
  464.  
  465. void displayTest()
  466. {
  467.   displayTestIteration++;
  468.   Color testColor;
  469.   testColor.red=displayTestIteration%7;
  470.   testColor.green=(displayTestIteration+2)%7;
  471.   testColor.blue=(displayTestIteration+4)%7;
  472.  
  473.   for(int x=0; x<16; x++)
  474.     for(int y=0; y<16; y++)
  475.       for(int z=0; z<16; z++)
  476.         setVoxel(x,y,z,testColor);
  477.  
  478.   delay(50);
  479. }
  480.  
  481.  
  482.  
  483. void updateAccelerometer()
  484. {
  485.     accelerometer[0]=analogRead(X);
  486.     accelerometer[1]=analogRead(Y);
  487.     accelerometer[2]=analogRead(Z);
  488.     for(int i=0;i<3;i++)
  489.     {
  490.         totals[i]+=accelerometer[i];
  491.         //sweet running average algorithm:  average[i+1]=average[i]+(sample[i]-average[i])/NUM_SAMPLES
  492.         //I average over 100 samples, or ~2.5 seconds
  493.         runningAverage[i]=runningAverage[i]+((accelerometer[i]-runningAverage[i])/NUM_SAMPLES);
  494.         whack[i]=false;
  495.     }
  496.     if(abs(accelerometer[0]-runningAverage[0])>WHACK_X)
  497.         whack[0]=true;
  498.     if(abs(accelerometer[1]-runningAverage[1])>WHACK_Y)
  499.         whack[1]=true;
  500.     if(abs(accelerometer[2]-runningAverage[2])>WHACK_Z)
  501.         whack[2]=true;
  502.     whacked=whack[0] | whack[1] | whack[2];
  503. }
  504.  
  505. void initRockets()
  506. {
  507.     for(int i=0;i<NUM_ROCKETS;i++)
  508.     {
  509.         rockets[i].gravity=-0.01;
  510.         rockets[i].y=0;
  511.         rockets[i].x=center.x;
  512.         rockets[i].z=center.z;
  513.         rockets[i].col=Color(255,0,0);
  514.         rockets[i].xVel=-.5;//(random(10)/10)-0.5;
  515.         rockets[i].yVel=0.25;//random(10)/10;
  516.         rockets[i].zVel=0.25;//(random(10)/10)-0.5;
  517.      }
  518. }
  519.  
  520. void initCircles()
  521. {
  522.     center=Point((SIZE-1)/2,(SIZE-1)/2,(SIZE-1)/2);
  523.     for(int i=0;i<4;i++)
  524.     {
  525.         poly1Angles[i]=random(6.28);
  526.         poly2Angles[i]=random(6.28);
  527.         poly3Angles[i]=random(6.28);
  528.     }
  529.     poly1AnglesInc[0]=random(10)/100 - 0.05;
  530.     poly1AnglesInc[1]=random(20)/100 - 0.1;
  531.     poly1AnglesInc[2]=random(10)/100 - 0.05;
  532.     poly1AnglesInc[3]=random(20)/100 - 0.1;
  533.  
  534.     poly2AnglesInc[0]=random(20)/100 - 0.1;
  535.     poly2AnglesInc[1]=random(20)/100 - 0.1;
  536.     poly2AnglesInc[2]=random(20)/100 - 0.1;
  537.     poly2AnglesInc[3]=random(20)/100 - 0.1;
  538.  
  539.     poly3AnglesInc[0]=random(20)/100 - 0.1;
  540.     poly3AnglesInc[1]=random(20)/100 - 0.1;
  541.     poly3AnglesInc[2]=random(20)/100 - 0.1;
  542.     poly3AnglesInc[3]=random(20)/100 - 0.1;
  543. }
  544.  
  545.  
  546. void romanCandle()
  547. {
  548.   background(Color(0,0,0));
  549.     for(int i=0;i<pow(2,M);i++)
  550.     {
  551.         real[i]=analogRead(MICROPHONE)-993;  //adapted for the 0.8v bias point of the big cube
  552.         delayMicroseconds(212);
  553.         imaginary[i]=0;
  554.     }
  555.     FFT(1, M, real, imaginary);
  556.     for(int i=0;i<pow(2,M);i++)
  557.     {
  558.         imaginary[i]=sqrt(pow(imaginary[i],2)+pow(real[i],2));
  559.         if(imaginary[i]>maxValue)
  560.             maxValue=imaginary[i];
  561.     }
  562.     if(maxValue>100)
  563.         maxValue--;
  564.     int rocketsToFire=0;
  565.     for(int i=0;i<pow(2,M)/2;i++)
  566.     {
  567.         imaginary[i]=SIZE*imaginary[i]/maxValue;
  568.     if(imaginary[i]>SIZE/2)
  569.         rocketsToFire++;
  570.     }
  571.  
  572.         for(int i=0;i<NUM_ROCKETS;i++)
  573.         {
  574.         rockets[i].yVel+=rockets[i].gravity;
  575.         rockets[i].x+=rockets[i].xVel;
  576.         rockets[i].y+=rockets[i].yVel;
  577.         rockets[i].z+=rockets[i].zVel;
  578.         if(rockets[i].col.green>5)
  579.             rockets[i].col.green-=5;
  580.         if(rockets[i].col.blue>5)
  581.             rockets[i].col.blue-=5;
  582.         /*
  583.         Serial.print(rockets[i].col.red);
  584.         Serial.print(" ");
  585.         Serial.print(rockets[i].col.green);
  586.         Serial.print(" ");
  587.         Serial.println(rockets[i].col.blue);
  588.         setVoxel(rockets[i].x,rockets[i].y,rockets[i].z,rockets[i].col);
  589.         */
  590.  
  591.         if(rocketsToFire>0)
  592.         if(rockets[i].y<0)
  593.         {
  594.         rocketsToFire--;
  595.         rockets[i].gravity=-0.01;
  596.         rockets[i].y=0;
  597.         rockets[i].x=center.x;
  598.         rockets[i].z=center.z;
  599.         rockets[i].col=Color(random(100),random(100),random(100));
  600.         rockets[i].xVel=(float)random(10)/10;//((float)random(10)/10)-0.5;
  601.         rockets[i].yVel=(float)random(10)/10;
  602.         rockets[i].zVel=((float)random(5)/10);
  603.         }
  604.         }
  605.         for(int i=0;i<(NUM_ROCKETS%2==0?NUM_ROCKETS:NUM_ROCKETS-1);i+=2)
  606.         line(rockets[i].x*cos(offset), rockets[i].y, rockets[i].z*sin(offset),rockets[i+1].x, rockets[i+1].y, rockets[i+1].z,rockets[i].col);
  607.         offset+=0.1;
  608.         mirror();
  609. }
  610.  
  611. void mirror()
  612. {
  613.     for(int x=center.x;x<SIZE;x++)
  614.         for(int y=0;y<SIZE;y++)
  615.             for(int z=center.z;z<SIZE;z++)
  616.             {
  617.                 setVoxel(center.x-(x-center.x),y,z, getVoxel(x,y,z));
  618.                 setVoxel(center.x-(x-center.x),y,center.z-(z-center.z), getVoxel(x,y,z));
  619.                 setVoxel(x,y,center.z-(z-center.z), getVoxel(x,y,z));
  620.             }
  621. }
  622.  
  623. void loop()
  624. {
  625.     //if the 'connect to cloud' button is pressed, try to connect to wifi.
  626.     //otherwise, run the program
  627.     checkCloudButton();
  628.  
  629.  
  630.   if(fading)
  631.         fade();
  632.     else
  633.     {
  634.         switch(demo%DEMO_ROUTINES)
  635.         {
  636.            case(FIREWORKS):
  637.                 updateFireworks();
  638.                 break;
  639.  
  640.             case(CIRCLES):
  641.                 circles();
  642.                 break;
  643.  
  644.             case(ROMAN_CANDLE):
  645.                 romanCandle();
  646.                 break;
  647.  
  648.             case(FFT_JOY):
  649.                 fft_joy();
  650.                 break;
  651.  
  652.             case(PLASMA):
  653.                 zPlasma();
  654.                 break;
  655.  
  656.             case(FASTPLASMA):
  657.                 fastPlasma();
  658.                 break;
  659.  
  660.             case(DISPLAY_TEST):
  661.                 displayTest();
  662.                 break;
  663.  
  664.             default:
  665.                 break;
  666.         }
  667.         frame++;
  668.     }
  669.    show();
  670.  
  671.    if(autoCycle)
  672.       if(millis()-lastDemo>DEMO_TIME)
  673.       {
  674.         fading=true;
  675.         demo++;
  676.         lastDemo=millis();
  677.       }
  678.  
  679.     if(fading)
  680.     {
  681.         fadeValue-=fadeSpeed;
  682.         //if we're done fading)
  683.         if(fadeValue<=0)
  684.         {
  685.             fading=false;
  686.             fadeValue=255;
  687.         }
  688.         else
  689.             fade();
  690.     }
  691.  
  692.    //uncomment to enable whack-to-change
  693.  
  694.   updateAccelerometer();
  695.  
  696.    if((whacked)&&((millis()-timeout)>250))
  697.    {
  698.     autoCycle=false;
  699.     fading=true;
  700.     demo++;
  701.     timeout=millis();
  702.     }
  703.  
  704. }
  705.  
  706. void fade()
  707. {
  708.     setFadeSpeed();
  709.     Color voxelColor;
  710.         for(int x=0;x<SIZE;x++)
  711.             for(int y=0;y<SIZE;y++)
  712.                 for(int z=0;z<SIZE;z++)
  713.                     {
  714.                         voxelColor=getVoxel(x,y,z);
  715.                         if(voxelColor.red>0)
  716.                             voxelColor.red--;
  717.                         if(voxelColor.green>0)
  718.                              voxelColor.green--;
  719.                         if(voxelColor.blue>0)
  720.                             voxelColor.blue--;
  721.                         setVoxel(x,y,z, voxelColor);
  722.                     }
  723. }
  724.  
  725.  
  726.  
  727. /********************************************
  728.  *   FFT JOY functions
  729.  * *****************************************/
  730. void fft_joy(){
  731.     for(int i=0;i<pow(2,M);i++)
  732.     {
  733.         real[i]=analogRead(MICROPHONE)-993;  //adapted for the 0.8v bias point of the big cube
  734.         delayMicroseconds(212);
  735.         imaginary[i]=0;
  736.     }
  737.     FFT(1, M, real, imaginary);
  738.     for(int i=0;i<pow(2,M);i++)
  739.     {
  740.         imaginary[i]=sqrt(pow(imaginary[i],2)+pow(real[i],2));
  741.         if(imaginary[i]>maxValue)
  742.             maxValue=imaginary[i];
  743.     }
  744.     if(maxValue>100)
  745.         maxValue--;
  746.     for(int i=0;i<pow(2,M)/2;i++)
  747.     {
  748.         imaginary[i]=SIZE*imaginary[i]/maxValue;
  749.         int y;
  750.         for(y=0;y<=imaginary[i];y++)
  751.             setVoxel(i,y,SIZE-1,colorMap(y,0,SIZE));
  752.         for(;y<SIZE;y++)
  753.             setVoxel(i,y,SIZE-1,Color(0,0,0));
  754.     }
  755.     for(int z=0;z<SIZE-1;z++)
  756.         for(int x=0;x<SIZE;x++)
  757.             for(int y=0;y<SIZE;y++)
  758.             {
  759.                 Color col=getVoxel(x,y,z+1);
  760.                 setVoxel(x,y,z,col);
  761.             }
  762.  
  763.     sample++;
  764.     if(sample>=pow(2,M))
  765.         sample-=pow(2,M);
  766. }
  767.  
  768. short FFT(short int dir,int m,float *x,float *y)
  769. {
  770.    int n,i,i1,j,k,i2,l,l1,l2;
  771.    float c1,c2,tx,ty,t1,t2,u1,u2,z;
  772.  
  773.    /* Calculate the number of points */
  774.    n = 1;
  775.    for (i=0;i<m;i++)
  776.       n *= 2;
  777.  
  778.    /* Do the bit reversal */
  779.    i2 = n >> 1;
  780.    j = 0;
  781.    for (i=0;i<n-1;i++) {
  782.       if (i < j) {
  783.          tx = x[i];
  784.          ty = y[i];
  785.          x[i] = x[j];
  786.          y[i] = y[j];
  787.          x[j] = tx;
  788.          y[j] = ty;
  789.       }
  790.       k = i2;
  791.       while (k <= j) {
  792.          j -= k;
  793.          k >>= 1;
  794.       }
  795.       j += k;
  796.    }
  797.  
  798.    /* Compute the FFT */
  799.    c1 = -1.0;
  800.    c2 = 0.0;
  801.    l2 = 1;
  802.    for (l=0;l<m;l++) {
  803.       l1 = l2;
  804.       l2 <<= 1;
  805.       u1 = 1.0;
  806.       u2 = 0.0;
  807.       for (j=0;j<l1;j++) {
  808.          for (i=j;i<n;i+=l2) {
  809.             i1 = i + l1;
  810.             t1 = u1 * x[i1] - u2 * y[i1];
  811.             t2 = u1 * y[i1] + u2 * x[i1];
  812.             x[i1] = x[i] - t1;
  813.             y[i1] = y[i] - t2;
  814.             x[i] += t1;
  815.             y[i] += t2;
  816.          }
  817.          z =  u1 * c1 - u2 * c2;
  818.          u2 = u1 * c2 + u2 * c1;
  819.          u1 = z;
  820.       }
  821.       c2 = sqrt((1.0 - c1) / 2.0);
  822.       if (dir == 1)
  823.          c2 = -c2;
  824.       c1 = sqrt((1.0 + c1) / 2.0);
  825.    }
  826.  
  827.    /* Scaling for forward transform */
  828.    if (dir == 1) {
  829.       for (i=0;i<n;i++) {
  830.          x[i] /= n;
  831.          y[i] /= n;
  832.       }
  833.    }
  834.  
  835.    return(0);
  836. }
  837.  
  838. void circles()
  839. {
  840.    background(Color(0,0,0));
  841.    poly1[0]=Point(center.x+(SIZE/2)*cos(poly1Angles[0]),0,center.z+(SIZE/2)*sin(poly1Angles[0]));
  842.    poly1[1]=Point(0,center.y+(SIZE/2)*cos(poly1Angles[1]),center.z+(SIZE/2)*sin(poly1Angles[1]));
  843.    poly1[2]=Point(center.x+(SIZE/2)*cos(poly1Angles[2]),SIZE-1,center.z+(SIZE/2)*sin(poly1Angles[2]));
  844.    poly1[3]=Point(SIZE-1,center.y+(SIZE/2)*cos(poly1Angles[3]),center.z+(SIZE/2)*sin(poly1Angles[3]));
  845.  
  846.    poly2[0]=Point(center.x+(SIZE/2)*cos(poly2Angles[0]),center.y+(SIZE/2)*sin(poly2Angles[0]),0);
  847.    poly2[1]=Point(SIZE-1,center.y+(SIZE/2)*cos(poly2Angles[1]),center.z+(SIZE/2)*sin(poly2Angles[1]));
  848.    poly2[2]=Point(center.x+(SIZE/2)*cos(poly2Angles[2]),center.y+(SIZE/2)*sin(poly2Angles[2]),SIZE-1);
  849.    poly2[3]=Point(0,center.y+(SIZE/2)*cos(poly2Angles[3]),center.z+(SIZE/2)*sin(poly2Angles[3]));
  850.  
  851.    poly3[0]=Point(center.x+(SIZE/2)*cos(poly3Angles[0]),0, center.z+(SIZE/2)*sin(poly3Angles[0]));
  852.    poly3[1]=Point(center.x+(SIZE/2)*cos(poly3Angles[1]),center.y+(SIZE/2)*cos(poly3Angles[1]),0);
  853.    poly3[2]=Point(center.x+(SIZE/2)*cos(poly3Angles[2]),SIZE-1, center.z+(SIZE/2)*sin(poly3Angles[2]));
  854.    poly3[3]=Point(center.x+(SIZE/2)*cos(poly3Angles[3]),center.y+(SIZE/2)*cos(poly3Angles[3]),SIZE-1);
  855.  
  856.    for(int i=0;i<4;i++)
  857.    {
  858.     poly1Angles[i]+=poly1AnglesInc[i];
  859.     poly2Angles[i]+=poly2AnglesInc[i];
  860.     poly3Angles[i]+=poly3AnglesInc[i];
  861.     float sin1=(float)255*sin(poly1Color);
  862.     float sin2=(float)255*sin(poly2Color);
  863.     float sin3=(float)255*sin(poly3Color);
  864.     line(poly1[i], poly1[(i+1)%4], Color(abs(sin1),0,0));
  865.     line(poly2[i], poly2[(i+1)%4], Color(0,0,abs(sin2)));
  866.     line(poly3[i], poly3[(i+1)%4], Color(0,abs(sin3),0));
  867.    }
  868.    poly1Color+=poly1ColorInc;
  869.    poly2Color+=poly2ColorInc;
  870.    poly3Color+=poly3ColorInc;
  871. }
  872.  
  873. void background(const Color& col)
  874. {
  875.     for(int x=0;x<SIZE;x++)
  876.         for(int y=0;y<SIZE;y++)
  877.             for(int z=0;z<SIZE;z++)
  878.                 setVoxel(x,y,z,col);
  879. }
  880.  
  881. void setVoxel(int x, int y, int z, const Color& col)
  882. {
  883.     if((x>=0)&&(x<SIZE))
  884.         if((y>=0)&&(y<SIZE))
  885.             if((z>=0)&&(z<SIZE))
  886.             {
  887.                 int index=z*256+x*16+y;
  888.                 PIXEL_RGB[index*3]=col.green;
  889.                 PIXEL_RGB[index*3+1]=col.red;
  890.                 PIXEL_RGB[index*3+2]=col.blue;
  891.             }
  892. }
  893.  
  894. void setVoxel(const Point& p, const Color& col)
  895. {
  896.     setVoxel(p.x, p.y, p.z, col);
  897. }
  898.  
  899. void line(const Point& p1, const Point& p2, const Color& col)
  900. {
  901.     line(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, col);
  902. }
  903.  
  904. void line(int x1, int y1, int z1, int x2, int y2, int z2, const Color& col)
  905. {
  906.   Point currentPoint;
  907.   currentPoint.x=x1;
  908.   currentPoint.y=y1;
  909.   currentPoint.z=z1;
  910.  
  911.   int dx = x2 - x1;
  912.   int dy = y2 - y1;
  913.   int dz = z2 - z1;
  914.   int x_inc = (dx < 0) ? -1 : 1;
  915.   int l = abs(dx);
  916.   int y_inc = (dy < 0) ? -1 : 1;
  917.   int m = abs(dy);
  918.   int z_inc = (dz < 0) ? -1 : 1;
  919.   int n = abs(dz);
  920.   int dx2 = l << 1;
  921.   int dy2 = m << 1;
  922.   int dz2 = n << 1;
  923.  
  924.   if((l >= m) && (l >= n)) {
  925.     int err_1 = dy2 - l;
  926.     int err_2 = dz2 - l;
  927.  
  928.     for(int i = 0; i < l; i++) {
  929.       setVoxel(currentPoint, col);
  930.  
  931.       if(err_1 > 0) {
  932.         currentPoint.y += y_inc;
  933.         err_1 -= dx2;
  934.       }
  935.  
  936.       if(err_2 > 0) {
  937.         currentPoint.z += z_inc;
  938.         err_2 -= dx2;
  939.       }
  940.  
  941.       err_1 += dy2;
  942.       err_2 += dz2;
  943.       currentPoint.x += x_inc;
  944.     }
  945.   } else if((m >= l) && (m >= n)) {
  946.     int err_1 = dx2 - m;
  947.     int err_2 = dz2 - m;
  948.  
  949.     for(int i = 0; i < m; i++) {
  950.       setVoxel(currentPoint, col);
  951.  
  952.       if(err_1 > 0) {
  953.         currentPoint.x += x_inc;
  954.         err_1 -= dy2;
  955.       }
  956.  
  957.       if(err_2 > 0) {
  958.         currentPoint.z += z_inc;
  959.         err_2 -= dy2;
  960.       }
  961.  
  962.       err_1 += dx2;
  963.       err_2 += dz2;
  964.       currentPoint.y += y_inc;
  965.     }
  966.   } else {
  967.     int err_1 = dy2 - n;
  968.     int err_2 = dx2 - n;
  969.  
  970.     for(int i = 0; i < n; i++) {
  971.       setVoxel(currentPoint, col);
  972.  
  973.       if(err_1 > 0) {
  974.         currentPoint.y += y_inc;
  975.         err_1 -= dz2;
  976.       }
  977.  
  978.       if(err_2 > 0) {
  979.         currentPoint.x += x_inc;
  980.         err_2 -= dz2;
  981.       }
  982.  
  983.       err_1 += dy2;
  984.       err_2 += dx2;
  985.       currentPoint.z += z_inc;
  986.     }
  987.   }
  988.  
  989.   setVoxel(currentPoint, col);
  990. }
  991.  
  992.  
  993. Point add(const Point& a, const Point& b)
  994. {
  995.     return Point(a.x+b.x, a.y+b.y, a.z+b.z);
  996. }
  997.  
  998. // draws a hollow  centered around the 'center' PVector, with radius
  999. // radius and color col
  1000. void sphere(const Point& center, float radius, const Color& col)
  1001. {
  1002.      float res = 30;
  1003.      for (float m = 0; m < res; m++)
  1004.          for (float n = 0; n < res; n++)
  1005.          setVoxel(center.x + radius * sin((float) PI * m / res) * cos((float) 2 * PI * n / res),
  1006.               center.y + radius * sin((float) PI * m / res) * sin((float) 2 * PI * n / res),
  1007.               center.z + radius * cos((float) PI * m / res),
  1008.               col);
  1009. }
  1010.  
  1011. // draws a hollow  centered around the 'center' PVector, with radius
  1012. // radius and color col
  1013. void sphere(const Point& center, float radius, const Color& col, int res)
  1014. {
  1015.      for (float m = 0; m < res; m++)
  1016.          for (float n = 0; n < res; n++)
  1017.          setVoxel(center.x + radius * sin((float) PI * m / res) * cos((float) 2 * PI * n / res),
  1018.               center.y + radius * sin((float) PI * m / res) * sin((float) 2 * PI * n / res),
  1019.               center.z + radius * cos((float) PI * m / res),
  1020.               col);
  1021. }
  1022.  
  1023. void sphere(float x, float y, float z, float radius, const Color& col)
  1024. {
  1025.      sphere(Point(x,y,z),radius, col);
  1026. }
  1027.  
  1028. void sphere(float x, float y, float z, float radius, const Color& col, int res)
  1029. {
  1030.      sphere(Point(x,y,z),radius, col, res);
  1031. }
  1032.  
  1033. void show()
  1034. {
  1035.     uint8_t *ptrA,*ptrB,*ptrC,*ptrD,*ptrE,*ptrF,*ptrG,*ptrH;
  1036.     uint8_t mask;
  1037.     uint8_t c=0,a=0,b=0,j=0;
  1038.  
  1039.     GPIOA->BSRRH=0xE0;    //set A3~A5 to low
  1040.     GPIOB->BSRRH=0xF0;    //set D0~D4 to low
  1041.     GPIOC->BSRRH=0x04;     //set A2 to low
  1042.  
  1043.     ptrA=&PIXEL_RGB[0];
  1044.     ptrB=ptrA+stripPIXEL*3;
  1045.     ptrC=ptrB+stripPIXEL*3;
  1046.     ptrD=ptrC+stripPIXEL*3;
  1047.     ptrE=ptrD+stripPIXEL*3;
  1048.     ptrF=ptrE+stripPIXEL*3;
  1049.     ptrG=ptrF+stripPIXEL*3;
  1050.     ptrH=ptrG+stripPIXEL*3;
  1051.  
  1052.     delayMicroseconds(50);
  1053.     __disable_irq();
  1054.  
  1055.     uint16_t i=stripPIXEL*3;   //3 BYTES = 1 PIXEL
  1056.  
  1057.     while(i) { // While bytes left... (3 bytes = 1 pixel)
  1058.       i--;
  1059.       mask = 0x80; // reset the mask
  1060.       j=0;
  1061.         // reset the 8-bit counter
  1062.       do {
  1063.         a=0;
  1064.         b=0;
  1065.         c=0;
  1066.  
  1067. //========Set D0~D4, i.e. B7~B4=======
  1068.         if ((*ptrA)&mask) b|=0x10;// if masked bit is high
  1069.     //    else "nop";
  1070.         b<<=1;
  1071.         if ((*ptrB)&mask) b|=0x10;// if masked bit is high
  1072.     //    else "nop";
  1073.         b<<=1;
  1074.         if ((*ptrC)&mask) b|=0x10;// if masked bit is high
  1075.     //    else "nop";
  1076.         b<<=1;
  1077.         if ((*ptrD)&mask) b|=0x10;// if masked bit is high
  1078.    //     else "nop";
  1079.  
  1080. //=========Set A2, i.g. C2==========
  1081.         if ((*ptrE)&mask) c|=0x04;// if masked bit is high
  1082.    //     else "nop";
  1083.  
  1084.         GPIOA->BSRRL=0xE0;    //set A3~A5 to high
  1085.         GPIOB->BSRRL=0xF0;    //set D0~D4 to high
  1086.         GPIOC->BSRRL=0x04;    //set A2 to high
  1087.  
  1088.  
  1089. //=========Set A3~A5, i.e. A5~A7========
  1090.         if ((*ptrF)&mask) a|=0x80;// if masked bit is high
  1091.         // else "nop";
  1092.         a>>=1;
  1093.         if ((*ptrG)&mask) a|=0x80;// if masked bit is high
  1094.    //     else "nop";
  1095.         a>>=1;
  1096.         if ((*ptrH)&mask) a|=0x80;// if masked bit is high
  1097.  
  1098.         a=(~a)&0xE0;
  1099.         b=(~b)&0xF0;
  1100.         c=(~c)&0x04;
  1101.         GPIOA->BSRRH=a;
  1102.         GPIOB->BSRRH=b;
  1103.         GPIOC->BSRRH=c;
  1104.         mask>>=1;
  1105.          asm volatile(
  1106.             "mov r0, r0" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1107.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1108.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1109.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1110.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1111.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1112.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1113.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1114.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1115.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1116.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1117.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1118.             "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
  1119.             ::: "r0", "cc", "memory");
  1120.         GPIOA->BSRRH=0xE0;    //set all to low
  1121.         GPIOB->BSRRH=0xF0;    //set all to low
  1122.         GPIOC->BSRRH=0x04;    //set all to low
  1123.           // WS2812 spec             700ns HIGH
  1124.           // Adafruit on Arduino    (meas. 812ns)
  1125.           // This lib on Spark Core (meas. 792ns)
  1126.           /*
  1127.         if(j<7) {
  1128.           asm volatile(
  1129.             "mov r0, r0" "\n\t"
  1130.             ::: "r0", "cc", "memory");
  1131.         }
  1132.         */
  1133.  
  1134.       } while ( ++j < 8 ); // ...one color on a pixel done
  1135.       ptrA++;
  1136.       ptrB++;
  1137.       ptrC++;
  1138.       ptrD++;
  1139.       ptrE++;
  1140.       ptrF++;
  1141.       ptrG++;
  1142.       ptrH++;
  1143.     } // end while(i) ... no more pixels
  1144.     __enable_irq();
  1145. }
  1146.  
  1147.  
  1148.  
  1149. /** Map a value into a color.
  1150.   The set of colors fades from blue to green to red and back again.
  1151.  
  1152.   @param val Value to map into a color.
  1153.   @param minVal Minimum value that val will take.
  1154.   @param maxVal Maximum value that val will take.
  1155.  
  1156.   @return Color from value.
  1157. */
  1158. Color colorMap(float val, float minVal, float maxVal)
  1159. {
  1160.   const float range = 1024;
  1161.   val = range * (val-minVal) / (maxVal-minVal);
  1162.  
  1163.   Color colors[6];
  1164.  
  1165.   colors[0].red = 0;
  1166.   colors[0].green = 0;
  1167.   colors[0].blue = maxBrightness;
  1168.  
  1169.   colors[1].red = 0;
  1170.   colors[1].green = maxBrightness;
  1171.   colors[1].blue = maxBrightness;
  1172.  
  1173.   colors[2].red = 0;
  1174.   colors[2].green = maxBrightness;
  1175.   colors[2].blue = 0;
  1176.  
  1177.   colors[3].red = maxBrightness;
  1178.   colors[3].green = maxBrightness;
  1179.   colors[3].blue = 0;
  1180.  
  1181.   colors[4].red = maxBrightness;
  1182.   colors[4].green = 0;
  1183.   colors[4].blue = 0;
  1184.  
  1185.   colors[5].red = maxBrightness;
  1186.   colors[5].green = 0;
  1187.   colors[5].blue = maxBrightness;
  1188.  
  1189.   if(val <= range/6)
  1190.     return lerpColor(colors[0], colors[1], val, 0, range/6);
  1191.   else if(val <= 2 * range / 6)
  1192.     return(lerpColor(colors[1], colors[2], val, range / 6, 2 * range / 6));
  1193.   else if(val <= 3 * range / 6)
  1194.     return(lerpColor(colors[2], colors[3], val, 2 * range / 6, 3*range / 6));
  1195.   else if(val <= 4 * range / 6)
  1196.     return(lerpColor(colors[3], colors[4], val, 3 * range / 6, 4*range / 6));
  1197.   else if(val <= 5 * range / 6)
  1198.     return(lerpColor(colors[4], colors[5], val, 4 * range / 6, 5*range / 6));
  1199.   else
  1200.     return(lerpColor(colors[5], colors[0], val, 5 * range / 6, range));
  1201. }
  1202.  
  1203. /** Linear interpolation between colors.
  1204.  
  1205.   @param a, b The colors to interpolate between.
  1206.   @param val Position on the line between color a and color b.
  1207.   When equal to min the output is color a, and when equal to max the output is color b.
  1208.   @param minVal Minimum value that val will take.
  1209.   @param maxVal Maximum value that val will take.
  1210.  
  1211.   @return Color between colors a and b.
  1212. */
  1213. Color lerpColor(const Color& a, const Color& b, int val, int minVal, int maxVal)
  1214. {
  1215.   int red = a.red + (b.red-a.red) * (val-minVal) / (maxVal-minVal);
  1216.   int green = a.green + (b.green-a.green) * (val-minVal) / (maxVal-minVal);
  1217.   int blue = a.blue + (b.blue-a.blue) * (val-minVal) / (maxVal-minVal);
  1218.  
  1219.   return Color(red, green, blue);
  1220. }
  1221.  
  1222. /***************************************
  1223.  * fireworks functions *
  1224.  * ***********************************/
  1225.  
  1226.  
  1227. void updateFireworks()
  1228. {
  1229.     background(Color(0,0,0));
  1230. //loop through all the pixels, calculate the distance to the center point, and turn the pixel on if it's at the right radius
  1231.             if(showRocket)
  1232.         sphere(rocketX,rocketY,rocketZ,radius,rocketColor);
  1233.             if(exploded)
  1234.         sphere(centerX,centerY,centerZ,radius,fireworkColor, fireworkRes);
  1235.  
  1236.         if(exploded)
  1237.             radius+=speed;  //the sphere gets bigger
  1238.         if(showRocket)
  1239.         {
  1240.             rocketX+=xInc;
  1241.             rocketY+=yInc;
  1242.             rocketZ+=zInc;
  1243.         }
  1244.         //if our sphere gets too large, restart the animation in another random spot
  1245.         if(radius>maxSize)
  1246.             prepRocket();
  1247.         if(abs(distance(centerX,centerY,centerZ,rocketX, rocketY, rocketZ)-radius)<2)
  1248.             {
  1249.                 showRocket=false;
  1250.                 exploded=true;
  1251.             }
  1252. }
  1253.  
  1254. float distance(float x, float y, float z, float x1, float y1, float z1)
  1255. {
  1256.     return(sqrt(pow(x-x1,2)+pow(y-y1,2)+pow(z-z1,2)));
  1257. }
  1258.  
  1259. void prepRocket()
  1260. {
  1261.     fireworkRes=10+rand()%20;
  1262.             radius=0.25;
  1263. //      centerX=0;
  1264. //      centerY=14;
  1265. //      centerZ=8;
  1266.             centerX=rand()%8;
  1267.             centerY=rand()%8;
  1268.             centerZ=rand()%8;
  1269.             fireworkColor.red=rand()%maxBrightness;
  1270.             fireworkColor.green=rand()%maxBrightness;
  1271.             fireworkColor.blue=rand()%maxBrightness;
  1272.             launchX=rand()%8;
  1273.             launchZ=rand()%8;
  1274.             rocketX=launchX;
  1275.             rocketY=0;
  1276.             rocketZ=launchZ;
  1277.             launchTime=10+rand()%15;
  1278.             xInc=(centerX-rocketX)/launchTime;
  1279.             yInc=(centerY-rocketY)/launchTime;
  1280.             zInc=(centerZ-rocketZ)/launchTime;
  1281.             showRocket=true;
  1282.             exploded=false;
  1283.             speed=0.35;
  1284.             maxSize=SIZE/2+random(SIZE/2);
  1285.             //speed=rand()%5;
  1286.             //speed*=0.1;
  1287. }
  1288.  
  1289. void initFireworks()
  1290. {
  1291.     rocketColor.red=255;
  1292.     rocketColor.green=150;
  1293.     rocketColor.blue=100;
  1294.     prepRocket();
  1295. }
  1296.  
  1297. Color getVoxel(int x, int y, int z)
  1298. {
  1299.     Color col=Color(0,0,0);
  1300.     if((x>=0)&&(x<SIZE))
  1301.         if((y>=0)&&(y<SIZE))
  1302.             if((z>=0)&&(z<SIZE))
  1303.             {
  1304.                 int index=z*256+x*16+y;
  1305.                 col.red=PIXEL_RGB[index*3+1];
  1306.                 col.green=PIXEL_RGB[index*3];
  1307.                 col.blue=PIXEL_RGB[index*3+2];
  1308.             }
  1309.     return col;
  1310. }
  1311.  
  1312. Color getVoxel(const Point& p)
  1313. {
  1314.     return getVoxel(p.x, p.y, p.z);
  1315. }
  1316.  
  1317. void setFadeSpeed()
  1318. {
  1319.     if(autoCycle)
  1320.         fadeSpeed=2;
  1321.     else
  1322.         fadeSpeed=20;
  1323. }
  1324.  
  1325.  void incrementDemo()
  1326.  {
  1327.      demo++;
  1328.      setFadeSpeed();
  1329.      fading=true;
  1330.      if(demo>=DEMO_ROUTINES)
  1331.         demo=0;
  1332.  }
  1333.  
  1334.   void decrementDemo()
  1335.  {
  1336.      demo--;
  1337.      setFadeSpeed();
  1338.      fading=true;
  1339.      if(demo<0)
  1340.         demo=DEMO_ROUTINES-1;
  1341.  }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement