diff options
| author | mrfaptastic <gmail@qwe23.com> | 2019-05-11 15:20:53 +0100 |
|---|---|---|
| committer | mrfaptastic <gmail@qwe23.com> | 2019-05-11 15:20:53 +0100 |
| commit | 85d0d448911ae42206cb355b9a4fdec136ad5499 (patch) | |
| tree | 5e5c522cd1e177c67cf9ee8df35a36b3a9b68007 | |
| parent | 95dd8aa339fd9a52d4779174c1493b8b1a56d060 (diff) | |
Added new demo
Based on Aurora code.
39 files changed, 5126 insertions, 1 deletions
diff --git a/ESP32-RGB64x32MatrixPanel-I2S-DMA.cpp b/ESP32-RGB64x32MatrixPanel-I2S-DMA.cpp index 34b286d..30c6db9 100644 --- a/ESP32-RGB64x32MatrixPanel-I2S-DMA.cpp +++ b/ESP32-RGB64x32MatrixPanel-I2S-DMA.cpp @@ -196,7 +196,9 @@ void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16_t // Need to check that the co-ordinates are within range, or it'll break everything big time. if ( x_coord < 0 || y_coord < 0 || x_coord >= MATRIX_WIDTH || y_coord >= MATRIX_HEIGHT) { - return; + // Serial.printf("Invalid: x %d, y %d - r %d, g %d, b %d\n", (int)x_coord, (int)y_coord, (int)red, (int)green, (int)blue ); + // x_coord = y_coord = 1; + return; } // What half of the HUB75 panel are we painting to? diff --git a/examples/AuroraDemo/Attractor.h b/examples/AuroraDemo/Attractor.h new file mode 100644 index 0000000..8f5ba2f --- /dev/null +++ b/examples/AuroraDemo/Attractor.h @@ -0,0 +1,50 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from "Attractor" in "The Nature of Code" by Daniel Shiffman: http://natureofcode.com/ + * Copyright (c) 2014 Daniel Shiffman + * http://www.shiffman.net + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "Vector.h" + +class Attractor { +public: + float mass; // Mass, tied to size + float G; // Gravitational Constant + PVector location; // Location + + Attractor() { + location = PVector(MATRIX_CENTRE_X, MATRIX_CENTRE_Y); + mass = 10; + G = .5; + } + + PVector attract(Boid m) { + PVector force = location - m.location; // Calculate direction of force + float d = force.mag(); // Distance between objects + d = constrain(d, 5.0, 32.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects + force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction) + float strength = (G * mass * m.mass) / (d * d); // Calculate gravitional force magnitude + force *= strength; // Get force vector --> magnitude * direction + return force; + } +}; diff --git a/examples/AuroraDemo/AuroraDemo.ino b/examples/AuroraDemo/AuroraDemo.ino new file mode 100644 index 0000000..917611d --- /dev/null +++ b/examples/AuroraDemo/AuroraDemo.ino @@ -0,0 +1,101 @@ +/* ------------------------- CUSTOM GPIO PIN MAPPING ------------------------- */ +#define R1_PIN 18 +#define G1_PIN 25 +#define B1_PIN 5 +#define R2_PIN 17 +#define G2_PIN 26 +#define B2_PIN 16 +#define A_PIN 14 +#define B_PIN 27 +#define C_PIN 12 +#define D_PIN 4 +#define E_PIN -1 +#define LAT_PIN 13 +#define OE_PIN 15 +#define CLK_PIN 2 + +/* -------------------------- Display Config Initialisation -------------------- */ + +#define MATRIX_WIDTH 64 +#define MATRIX_HEIGHT 32 + +/* -------------------------- Class Initialisation -------------------------- */ +#include <ESP32-RGB64x32MatrixPanel-I2S-DMA.h> +RGB64x32MatrixPanel_I2S_DMA matrix; + +#include <FastLED.h> + +#include "Effects.h" +Effects effects; + +#include "Drawable.h" +#include "Playlist.h" +//#include "Geometry.h" + +#include "Patterns.h" +Patterns patterns; + +/* -------------------------- Some variables -------------------------- */ +unsigned long ms_current = 0; +unsigned long ms_previous = 0; +unsigned long ms_animation_max_duration = 10000; // 10 seconds +unsigned long next_frame = 0; + +void setup() +{ + // Setup serial interface + Serial.begin(115200); + delay(250); + matrix.begin(R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN ); // setup the LED matrix + + Serial.println("**************** Starting Aurora Effects Demo ****************"); + + // setup the effects generator + effects.Setup(); + + delay(500); + Serial.println("Effects being loaded: "); + listPatterns(); + + + patterns.setPattern(0); // // simple noise + patterns.start(); + + Serial.print("Starting with pattern: "); + Serial.println(patterns.getCurrentPatternName()); + +} + +void loop() +{ + // menu.run(mainMenuItems, mainMenuItemCount); + ms_current = millis(); + + + if ( (ms_current - ms_previous) > ms_animation_max_duration ) + { + // patterns.moveRandom(1); + + patterns.stop(); + patterns.move(1); + patterns.start(); + + + Serial.print("Changing pattern to: "); + Serial.println(patterns.getCurrentPatternName()); + + ms_previous = ms_current; + + // Select a random palette as well + //effects.RandomPalette(); + } + + if ( next_frame < ms_current) + next_frame = patterns.drawFrame() + ms_current; + +} + + +void listPatterns() { + patterns.listPatterns(); +} diff --git a/examples/AuroraDemo/Boid.h b/examples/AuroraDemo/Boid.h new file mode 100644 index 0000000..43a876a --- /dev/null +++ b/examples/AuroraDemo/Boid.h @@ -0,0 +1,326 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from "Flocking" in "The Nature of Code" by Daniel Shiffman: http://natureofcode.com/ + * Copyright (c) 2014 Daniel Shiffman + * http://www.shiffman.net + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// Flocking +// Daniel Shiffman <http://www.shiffman.net> +// The Nature of Code, Spring 2009 + +// Boid class +// Methods for Separation, Cohesion, Alignment added + +class Boid { + public: + + PVector location; + PVector velocity; + PVector acceleration; + float maxforce; // Maximum steering force + float maxspeed; // Maximum speed + + float desiredseparation = 4; + float neighbordist = 8; + byte colorIndex = 0; + float mass; + + boolean enabled = true; + + Boid() {} + + Boid(float x, float y) { + acceleration = PVector(0, 0); + velocity = PVector(randomf(), randomf()); + location = PVector(x, y); + maxspeed = 1.5; + maxforce = 0.05; + } + + static float randomf() { + return mapfloat(random(0, 255), 0, 255, -.5, .5); + } + + static float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; + } + + void run(Boid boids [], uint8_t boidCount) { + flock(boids, boidCount); + update(); + // wrapAroundBorders(); + // render(); + } + + // Method to update location + void update() { + // Update velocity + velocity += acceleration; + // Limit speed + velocity.limit(maxspeed); + location += velocity; + // Reset acceleration to 0 each cycle + acceleration *= 0; + } + + void applyForce(PVector force) { + // We could add mass here if we want A = F / M + acceleration += force; + } + + void repelForce(PVector obstacle, float radius) { + //Force that drives boid away from obstacle. + + PVector futPos = location + velocity; //Calculate future position for more effective behavior. + PVector dist = obstacle - futPos; + float d = dist.mag(); + + if (d <= radius) { + PVector repelVec = location - obstacle; + repelVec.normalize(); + if (d != 0) { //Don't divide by zero. + // float scale = 1.0 / d; //The closer to the obstacle, the stronger the force. + repelVec.normalize(); + repelVec *= (maxforce * 7); + if (repelVec.mag() < 0) { //Don't let the boids turn around to avoid the obstacle. + repelVec.y = 0; + } + } + applyForce(repelVec); + } + } + + // We accumulate a new acceleration each time based on three rules + void flock(Boid boids [], uint8_t boidCount) { + PVector sep = separate(boids, boidCount); // Separation + PVector ali = align(boids, boidCount); // Alignment + PVector coh = cohesion(boids, boidCount); // Cohesion + // Arbitrarily weight these forces + sep *= 1.5; + ali *= 1.0; + coh *= 1.0; + // Add the force vectors to acceleration + applyForce(sep); + applyForce(ali); + applyForce(coh); + } + + // Separation + // Method checks for nearby boids and steers away + PVector separate(Boid boids [], uint8_t boidCount) { + PVector steer = PVector(0, 0); + int count = 0; + // For every boid in the system, check if it's too close + for (int i = 0; i < boidCount; i++) { + Boid other = boids[i]; + if (!other.enabled) + continue; + float d = location.dist(other.location); + // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself) + if ((d > 0) && (d < desiredseparation)) { + // Calculate vector pointing away from neighbor + PVector diff = location - other.location; + diff.normalize(); + diff /= d; // Weight by distance + steer += diff; + count++; // Keep track of how many + } + } + // Average -- divide by how many + if (count > 0) { + steer /= (float) count; + } + + // As long as the vector is greater than 0 + if (steer.mag() > 0) { + // Implement Reynolds: Steering = Desired - Velocity + steer.normalize(); + steer *= maxspeed; + steer -= velocity; + steer.limit(maxforce); + } + return steer; + } + + // Alignment + // For every nearby boid in the system, calculate the average velocity + PVector align(Boid boids [], uint8_t boidCount) { + PVector sum = PVector(0, 0); + int count = 0; + for (int i = 0; i < boidCount; i++) { + Boid other = boids[i]; + if (!other.enabled) + continue; + float d = location.dist(other.location); + if ((d > 0) && (d < neighbordist)) { + sum += other.velocity; + count++; + } + } + if (count > 0) { + sum /= (float) count; + sum.normalize(); + sum *= maxspeed; + PVector steer = sum - velocity; + steer.limit(maxforce); + return steer; + } + else { + return PVector(0, 0); + } + } + + // Cohesion + // For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location + PVector cohesion(Boid boids [], uint8_t boidCount) { + PVector sum = PVector(0, 0); // Start with empty vector to accumulate all locations + int count = 0; + for (int i = 0; i < boidCount; i++) { + Boid other = boids[i]; + if (!other.enabled) + continue; + float d = location.dist(other.location); + if ((d > 0) && (d < neighbordist)) { + sum += other.location; // Add location + count++; + } + } + if (count > 0) { + sum /= count; + return seek(sum); // Steer towards the location + } + else { + return PVector(0, 0); + } + } + + // A method that calculates and applies a steering force towards a target + // STEER = DESIRED MINUS VELOCITY + PVector seek(PVector target) { + PVector desired = target - location; // A vector pointing from the location to the target + // Normalize desired and scale to maximum speed + desired.normalize(); + desired *= maxspeed; + // Steering = Desired minus Velocity + PVector steer = desired - velocity; + steer.limit(maxforce); // Limit to maximum steering force + return steer; + } + + // A method that calculates a steering force towards a target + // STEER = DESIRED MINUS VELOCITY + void arrive(PVector target) { + PVector desired = target - location; // A vector pointing from the location to the target + float d = desired.mag(); + // Normalize desired and scale with arbitrary damping within 100 pixels + desired.normalize(); + if (d < 4) { + float m = map(d, 0, 100, 0, maxspeed); + desired *= m; + } + else { + desired *= maxspeed; + } + + // Steering = Desired minus Velocity + PVector steer = desired - velocity; + steer.limit(maxforce); // Limit to maximum steering force + applyForce(steer); + //Serial.println(d); + } + + void wrapAroundBorders() { + if (location.x < 0) location.x = MATRIX_WIDTH - 1; + if (location.y < 0) location.y = MATRIX_HEIGHT - 1; + if (location.x >= MATRIX_WIDTH) location.x = 0; + if (location.y >= MATRIX_HEIGHT) location.y = 0; + } + + void avoidBorders() { + PVector desired = velocity; + + if (location.x < 8) desired = PVector(maxspeed, velocity.y); + if (location.x >= MATRIX_WIDTH - 8) desired = PVector(-maxspeed, velocity.y); + if (location.y < 8) desired = PVector(velocity.x, maxspeed); + if (location.y >= MATRIX_HEIGHT - 8) desired = PVector(velocity.x, -maxspeed); + + if (desired != velocity) { + PVector steer = desired - velocity; + steer.limit(maxforce); + applyForce(steer); + } + + if (location.x < 0) location.x = 0; + if (location.y < 0) location.y = 0; + if (location.x >= MATRIX_WIDTH) location.x = MATRIX_WIDTH - 1; + if (location.y >= MATRIX_HEIGHT) location.y = MATRIX_HEIGHT - 1; + } + + bool bounceOffBorders(float bounce) { + bool bounced = false; + + if (location.x >= MATRIX_WIDTH) { + location.x = MATRIX_WIDTH - 1; + velocity.x *= -bounce; + bounced = true; + } + else if (location.x < 0) { + location.x = 0; + velocity.x *= -bounce; + bounced = true; + } + + if (location.y >= MATRIX_HEIGHT) { + location.y = MATRIX_HEIGHT - 1; + velocity.y *= -bounce; + bounced = true; + } + else if (location.y < 0) { + location.y = 0; + velocity.y *= -bounce; + bounced = true; + } + + return bounced; + } + + void render() { + //// Draw a triangle rotated in the direction of velocity + //float theta = velocity.heading2D() + radians(90); + //fill(175); + //stroke(0); + //pushMatrix(); + //translate(location.x,location.y); + //rotate(theta); + //beginShape(TRIANGLES); + //vertex(0, -r*2); + //vertex(-r, r*2); + //vertex(r, r*2); + //endShape(); + //popMatrix(); + //matrix.drawBackgroundPixelRGB888(location.x, location.y, CRGB::Blue); + } +}; + +static const uint8_t AVAILABLE_BOID_COUNT = 40; +Boid boids[AVAILABLE_BOID_COUNT]; diff --git a/examples/AuroraDemo/Drawable.h b/examples/AuroraDemo/Drawable.h new file mode 100644 index 0000000..40356f4 --- /dev/null +++ b/examples/AuroraDemo/Drawable.h @@ -0,0 +1,55 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef Drawable_H +#define Drawable_H + +class Drawable{ +public: + char* name; + + virtual bool isRunnable() { + return false; + } + + virtual bool isPlaylist() { + return false; + } + + // a single frame should be drawn as fast as possible, without any delay or blocking + // return how many millisecond delay is requested before the next call to drawFrame() + virtual unsigned int drawFrame() { + matrix.fillScreen(0); + //backgroundLayer.fillScreen({ 0, 0, 0 }); + return 0; + }; + + virtual void printTesting() + { + Serial.println("Testing..."); + } + + virtual void start() {}; + virtual void stop() {}; +}; + +#endif diff --git a/examples/AuroraDemo/Effects.h b/examples/AuroraDemo/Effects.h new file mode 100644 index 0000000..8169069 --- /dev/null +++ b/examples/AuroraDemo/Effects.h @@ -0,0 +1,823 @@ + +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from "Funky Clouds" by Stefan Petrick: https://gist.github.com/anonymous/876f908333cd95315c35 + * Portions of this code are adapted from "NoiseSmearing" by Stefan Petrick: https://gist.github.com/StefanPetrick/9ee2f677dbff64e3ba7a + * Copyright (c) 2014 Stefan Petrick + * http://www.stefan-petrick.de/wordpress_beta + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef Effects_H +#define Effects_H + +/* ---------------------------- GLOBAL CONSTANTS ----------------------------- */ + +const int MATRIX_CENTER_X = MATRIX_WIDTH / 2; +const int MATRIX_CENTER_Y = MATRIX_HEIGHT / 2; +const byte MATRIX_CENTRE_X = MATRIX_CENTER_X - 1; +const byte MATRIX_CENTRE_Y = MATRIX_CENTER_Y - 1; + +const uint16_t NUM_LEDS = (MATRIX_WIDTH * MATRIX_HEIGHT) + 1; // one led spare to capture out of bounds + +/* Convert x,y co-ordinate to flat array index. + * x and y positions start from 0, so must not be >= 'real' panel width or height + * (i.e. 64 pixels or 32 pixels.). Max value: MATRIX_WIDTH-1 etc. + */ +uint16_t XY( uint8_t x, uint8_t y) +{ + if( x >= MATRIX_WIDTH || x < 0) return 0; + if( y >= MATRIX_HEIGHT || y < 0) return 0; + + return (y * MATRIX_WIDTH) + x + 1; // everything offset by one to capute out of bounds stuff - never displayed by ShowFrame() + +} + + +uint8_t beatcos8(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255, uint32_t timebase = 0, uint8_t phase_offset = 0) +{ + uint8_t beat = beat8(beats_per_minute, timebase); + uint8_t beatcos = cos8(beat + phase_offset); + uint8_t rangewidth = highest - lowest; + uint8_t scaledbeat = scale8(beatcos, rangewidth); + uint8_t result = lowest + scaledbeat; + return result; +} + +uint8_t mapsin8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) { + uint8_t beatsin = sin8(theta); + uint8_t rangewidth = highest - lowest; + uint8_t scaledbeat = scale8(beatsin, rangewidth); + uint8_t result = lowest + scaledbeat; + return result; +} + +uint8_t mapcos8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) { + uint8_t beatcos = cos8(theta); + uint8_t rangewidth = highest - lowest; + uint8_t scaledbeat = scale8(beatcos, rangewidth); + uint8_t result = lowest + scaledbeat; + return result; +} + +// Array of temperature readings at each simulation cell +byte heat[NUM_LEDS]; + +uint32_t noise_x; +uint32_t noise_y; +uint32_t noise_z; +uint32_t noise_scale_x; +uint32_t noise_scale_y; + +uint8_t noise[MATRIX_WIDTH][MATRIX_HEIGHT]; +uint8_t noisesmoothing; + +class Effects { +public: + //CRGB *leds; + CRGB leds[NUM_LEDS]; + //CRGB leds2[NUM_LEDS]; // Faptastic: getting rid of this and any dependant effects or algos. to save memory 24*64*32 bytes of ram (50k). + + + /* The only 'framebuffer' we have is what is contained in the leds and leds2 variables. + * We don't store what the color a particular pixel might be, other than when it's turned + * into raw electrical signal output gobbly-gook (i.e. the DMA matrix buffer), but this * is not reversible. + * + * As such, any time these effects want to write a pixel color, we first have to update + * the leds or leds2 array, and THEN write it to the RGB panel. This enables us to 'look up' the array to see what a pixel color was previously, each drawFrame(). + */ + void drawBackgroundFastLEDPixelCRGB(int16_t x, int16_t y, CRGB color) + { + leds[XY(x, y)] = color; + matrix.drawPixelRGB888(x, y, color.r, color.g, color.b); + } + + // write one pixel with the specified color from the current palette to coordinates + void Pixel(int x, int y, uint8_t colorIndex) { + CRGB temp = ColorFromCurrentPalette(colorIndex); + leds[XY(x, y)] = temp; + matrix.drawPixelRGB888(x, y, temp.r, temp.g, temp.b); // now draw it? + } + + void PrepareFrame() { + // leds = (CRGB*) backgroundLayer.backBuffer(); + } + + void ShowFrame() { + //#if (FASTLED_VERSION >= 3001000) + // nblendPaletteTowardPalette(currentPalette, targetPalette, 24); + //#else + currentPalette = targetPalette; + //#endif + + // backgroundLayer.swapBuffers(); + // leds = (CRGB*) backgroundLayer.backBuffer(); + // LEDS.countFPS(); + + + for (int y=0;y<MATRIX_HEIGHT; y++) + for (int x=0;x<MATRIX_WIDTH; x++) + { + + CRGB tmp_led = leds[XY(x,y)]; + + //Serial.printf("\r\nFlushing x, y coord %d, %d", x, y); + //display.drawPixelRGB888( x, 31-y, tmp_led.r, tmp_led.g, tmp_led.b); + matrix.drawPixelRGB888( x, y, tmp_led.r, tmp_led.g, tmp_led.b); + + } // end loop to copy fast led to the dma matrix + + + } + + // scale the brightness of the screenbuffer down + void DimAll(byte value) + { + for (int i = 0; i < NUM_LEDS; i++) + { + leds[i].nscale8(value); + } + } + + void ClearFrame() + { + memset(leds, 0x00, sizeof(leds)); // flush + } + + + +/* + void CircleStream(uint8_t value) { + DimAll(value); ShowFrame(); + + for (uint8_t offset = 0; offset < MATRIX_CENTER_X; offset++) { + boolean hasprev = false; + uint16_t prevxy = 0; + + for (uint8_t theta = 0; theta < 255; theta++) { + uint8_t x = mapcos8(theta, offset, (MATRIX_WIDTH - 1) - offset); + uint8_t y = mapsin8(theta, offset, (MATRIX_HEIGHT - 1) - offset); + + uint16_t xy = XY(x, y); + + if (hasprev) { + leds[prevxy] += leds[xy]; + } + + prevxy = xy; + hasprev = true; + } + } + + for (uint8_t x = 0; x < MATRIX_WIDTH; x++) { + for (uint8_t y = 0; y < MATRIX_HEIGHT; y++) { + uint16_t xy = XY(x, y); + leds[xy] = leds2[xy]; + leds[xy].nscale8(value); + leds2[xy].nscale8(value); + } + } + } +*/ + + // palettes + static const int paletteCount = 10; + int paletteIndex = -1; + TBlendType currentBlendType = LINEARBLEND; + CRGBPalette16 currentPalette; + CRGBPalette16 targetPalette; + char* currentPaletteName; + + static const int HeatColorsPaletteIndex = 6; + static const int RandomPaletteIndex = 9; + + void Setup() { + currentPalette = RainbowColors_p; + loadPalette(0); + NoiseVariablesSetup(); + } + + void CyclePalette(int offset = 1) { + loadPalette(paletteIndex + offset); + } + + void RandomPalette() { + loadPalette(RandomPaletteIndex); + } + + void loadPalette(int index) { + paletteIndex = index; + + if (paletteIndex >= paletteCount) + paletteIndex = 0; + else if (paletteIndex < 0) + paletteIndex = paletteCount - 1; + + switch (paletteIndex) { + case 0: + targetPalette = RainbowColors_p; + currentPaletteName = (char *)"Rainbow"; + break; + //case 1: + // targetPalette = RainbowStripeColors_p; + // currentPaletteName = (char *)"RainbowStripe"; + // break; + case 1: + targetPalette = OceanColors_p; + currentPaletteName = (char *)"Ocean"; + break; + case 2: + targetPalette = CloudColors_p; + currentPaletteName = (char *)"Cloud"; + break; + case 3: + targetPalette = ForestColors_p; + currentPaletteName = (char *)"Forest"; + break; + case 4: + targetPalette = PartyColors_p; + currentPaletteName = (char *)"Party"; + break; + case 5: + setupGrayscalePalette(); + currentPaletteName = (char *)"Grey"; + break; + case HeatColorsPaletteIndex: + targetPalette = HeatColors_p; + currentPaletteName = (char *)"Heat"; + break; + case 7: + targetPalette = LavaColors_p; + currentPaletteName = (char *)"Lava"; + break; + case 8: + setupIcePalette(); + currentPaletteName = (char *)"Ice"; + break; + case RandomPaletteIndex: + loadPalette(random(0, paletteCount - 1)); + paletteIndex = RandomPaletteIndex; + currentPaletteName = (char *)"Random"; + break; + } + } + + void setPalette(String paletteName) { + if (paletteName == "Rainbow") + loadPalette(0); + //else if (paletteName == "RainbowStripe") + // loadPalette(1); + else if (paletteName == "Ocean") + loadPalette(1); + else if (paletteName == "Cloud") + loadPalette(2); + else if (paletteName == "Forest") + loadPalette(3); + else if (paletteName == "Party") + loadPalette(4); + else if (paletteName == "Grayscale") + loadPalette(5); + else if (paletteName == "Heat") + loadPalette(6); + else if (paletteName == "Lava") + loadPalette(7); + else if (paletteName == "Ice") + loadPalette(8); + else if (paletteName == "Random") + RandomPalette(); + } + + void listPalettes() { + Serial.println(F("{")); + Serial.print(F(" \"count\": ")); + Serial.print(paletteCount); + Serial.println(","); + Serial.println(F(" \"results\": [")); + + String paletteNames [] = { + "Rainbow", + // "RainbowStripe", + "Ocean", + "Cloud", + "Forest", + "Party", + "Grayscale", + "Heat", + "Lava", + "Ice", + "Random" + }; + + for (int i = 0; i < paletteCount; i++) { + Serial.print(F(" \"")); + Serial.print(paletteNames[i]); + if (i == paletteCount - 1) + Serial.println(F("\"")); + else + Serial.println(F("\",")); + } + + Serial.println(" ]"); + Serial.println("}"); + } + + void setupGrayscalePalette() { + targetPalette = CRGBPalette16(CRGB::Black, CRGB::White); + } + + void setupIcePalette() { + targetPalette = CRGBPalette16(CRGB::Black, CRGB::Blue, CRGB::Aqua, CRGB::White); + } + + // Oscillators and Emitters + + // the oscillators: linear ramps 0-255 + byte osci[6]; + + // sin8(osci) swinging between 0 to MATRIX_WIDTH - 1 + byte p[6]; + + // set the speeds (and by that ratios) of the oscillators here + void MoveOscillators() { + osci[0] = osci[0] + 5; + osci[1] = osci[1] + 2; + osci[2] = osci[2] + 3; + osci[3] = osci[3] + 4; + osci[4] = osci[4] + 1; + if (osci[4] % 2 == 0) + osci[5] = osci[5] + 1; // .5 + for (int i = 0; i < 4; i++) { + p[i] = map8(sin8(osci[i]), 0, MATRIX_WIDTH - 1); //why? to keep the result in the range of 0-MATRIX_WIDTH (matrix size) + } + } + + + // All the caleidoscope functions work directly within the screenbuffer (leds array). + // Draw whatever you like in the area x(0-15) and y (0-15) and then copy it arround. + + // rotates the first 16x16 quadrant 3 times onto a 32x32 (+90 degrees rotation for each one) + void Caleidoscope1() { + for (int x = 0; x < MATRIX_CENTER_X; x++) { + for (int y = 0; y < MATRIX_CENTER_Y; y++) { + leds[XY(MATRIX_WIDTH - 1 - x, y)] = leds[XY(x, y)]; + leds[XY(MATRIX_WIDTH - 1 - x, MATRIX_HEIGHT - 1 - y)] = leds[XY(x, y)]; + leds[XY(x, MATRIX_HEIGHT - 1 - y)] = leds[XY(x, y)]; + } + } + } + + + // mirror the first 16x16 quadrant 3 times onto a 32x32 + void Caleidoscope2() { + for (int x = 0; x < MATRIX_CENTER_X; x++) { + for (int y = 0; y < MATRIX_CENTER_Y; y++) { + leds[XY(MATRIX_WIDTH - 1 - x, y)] = leds[XY(y, x)]; + leds[XY(x, MATRIX_HEIGHT - 1 - y)] = leds[XY(y, x)]; + leds[XY(MATRIX_WIDTH - 1 - x, MATRIX_HEIGHT - 1 - y)] = leds[XY(x, y)]; + } + } + } + + // copy one diagonal triangle into the other one within a 16x16 + void Caleidoscope3() { + for (int x = 0; x <= MATRIX_CENTRE_X; x++) { + for (int y = 0; y <= x; y++) { + leds[XY(x, y)] = leds[XY(y, x)]; + } + } + } + + // copy one diagonal triangle into the other one within a 16x16 (90 degrees rotated compared to Caleidoscope3) + void Caleidoscope4() { + for (int x = 0; x <= MATRIX_CENTRE_X; x++) { + for (int y = 0; y <= MATRIX_CENTRE_Y - x; y++) { + leds[XY(MATRIX_CENTRE_Y - y, MATRIX_CENTRE_X - x)] = leds[XY(x, y)]; + } + } + } + + // copy one diagonal triangle into the other one within a 8x8 + void Caleidoscope5() { + for (int x = 0; x < MATRIX_WIDTH / 4; x++) { + for (int y = 0; y <= x; y++) { + leds[XY(x, y)] = leds[XY(y, x)]; + } + } + + for (int x = MATRIX_WIDTH / 4; x < MATRIX_WIDTH / 2; x++) { + for (int y = MATRIX_HEIGHT / 4; y >= 0; y--) { + leds[XY(x, y)] = leds[XY(y, x)]; + } + } + } + + void Caleidoscope6() { + for (int x = 1; x < MATRIX_CENTER_X; x++) { + leds[XY(7 - x, 7)] = leds[XY(x, 0)]; + } //a + for (int x = 2; x < MATRIX_CENTER_X; x++) { + leds[XY(7 - x, 6)] = leds[XY(x, 1)]; + } //b + for (int x = 3; x < MATRIX_CENTER_X; x++) { + leds[XY(7 - x, 5)] = leds[XY(x, 2)]; + } //c + for (int x = 4; x < MATRIX_CENTER_X; x++) { + leds[XY(7 - x, 4)] = leds[XY(x, 3)]; + } //d + for (int x = 5; x < MATRIX_CENTER_X; x++) { + leds[XY(7 - x, 3)] = leds[XY(x, 4)]; + } //e + for (int x = 6; x < MATRIX_CENTER_X; x++) { + leds[XY(7 - x, 2)] = leds[XY(x, 5)]; + } //f + for (int x = 7; x < MATRIX_CENTER_X; x++) { + leds[XY(7 - x, 1)] = leds[XY(x, 6)]; + } //g + } + + // create a square twister to the left or counter-clockwise + // x and y for center, r for radius + void SpiralStream(int x, int y, int r, byte dimm) { + for (int d = r; d >= 0; d--) { // from the outside to the inside + for (int i = x - d; i <= x + d; i++) { + leds[XY(i, y - d)] += leds[XY(i + 1, y - d)]; // lowest row to the right + leds[XY(i, y - d)].nscale8(dimm); + } + for (int i = y - d; i <= y + d; i++) { + leds[XY(x + d, i)] += leds[XY(x + d, i + 1)]; // right colum up + leds[XY(x + d, i)].nscale8(dimm); + } + for (int i = x + d; i >= x - d; i--) { + leds[XY(i, y + d)] += leds[XY(i - 1, y + d)]; // upper row to the left + leds[XY(i, y + d)].nscale8(dimm); + } + for (int i = y + d; i >= y - d; i--) { + leds[XY(x - d, i)] += leds[XY(x - d, i - 1)]; // left colum down + leds[XY(x - d, i)].nscale8(dimm); + } + } + } + + // expand everything within a circle + void Expand(int centerX, int centerY, int radius, byte dimm) { + if (radius == 0) + return; + + int currentRadius = radius; + + while (currentRadius > 0) { + int a = radius, b = 0; + int radiusError = 1 - a; + + int nextRadius = currentRadius - 1; + int nextA = nextRadius - 1, nextB = 0; + int nextRadiusError = 1 - nextA; + + while (a >= b) + { + // move them out one pixel on the radius + leds[XY(a + centerX, b + centerY)] = leds[XY(nextA + centerX, nextB + centerY)]; + leds[XY(b + centerX, a + centerY)] = leds[XY(nextB + centerX, nextA + centerY)]; + leds[XY(-a + centerX, b + centerY)] = leds[XY(-nextA + centerX, nextB + centerY)]; + leds[XY(-b + centerX, a + centerY)] = leds[XY(-nextB + centerX, nextA + centerY)]; + leds[XY(-a + centerX, -b + centerY)] = leds[XY(-nextA + centerX, -nextB + centerY)]; + leds[XY(-b + centerX, -a + centerY)] = leds[XY(-nextB + centerX, -nextA + centerY)]; + leds[XY(a + centerX, -b + centerY)] = leds[XY(nextA + centerX, -nextB + centerY)]; + leds[XY(b + centerX, -a + centerY)] = leds[XY(nextB + centerX, -nextA + centerY)]; + + // dim them + leds[XY(a + centerX, b + centerY)].nscale8(dimm); + leds[XY(b + centerX, a + centerY)].nscale8(dimm); + leds[XY(-a + centerX, b + centerY)].nscale8(dimm); + leds[XY(-b + centerX, a + centerY)].nscale8(dimm); + leds[XY(-a + centerX, -b + centerY)].nscale8(dimm); + leds[XY(-b + centerX, -a + centerY)].nscale8(dimm); + leds[XY(a + centerX, -b + centerY)].nscale8(dimm); + leds[XY(b + centerX, -a + centerY)].nscale8(dimm); + + b++; + if (radiusError < 0) + radiusError += 2 * b + 1; + else + { + a--; + radiusError += 2 * (b - a + 1); + } + + nextB++; + if (nextRadiusError < 0) + nextRadiusError += 2 * nextB + 1; + else + { + nextA--; + nextRadiusError += 2 * (nextB - nextA + 1); + } + } + + currentRadius--; + } + } + + // give it a linear tail to the right + void StreamRight(byte scale, int fromX = 0, int toX = MATRIX_WIDTH, int fromY = 0, int toY = MATRIX_HEIGHT) + { + for (int x = fromX + 1; x < toX; x++) { + for (int y = fromY; y < toY; y++) { + leds[XY(x, y)] += leds[XY(x - 1, y)]; + leds[XY(x, y)].nscale8(scale); + } + } + for (int y = fromY; y < toY; y++) + leds[XY(0, y)].nscale8(scale); + } + + // give it a linear tail to the left + void StreamLeft(byte scale, int fromX = MATRIX_WIDTH, int toX = 0, int fromY = 0, int toY = MATRIX_HEIGHT) + { + for (int x = toX; x < fromX; x++) { + for (int y = fromY; y < toY; y++) { + leds[XY(x, y)] += leds[XY(x + 1, y)]; + leds[XY(x, y)].nscale8(scale); + } + } + for (int y = fromY; y < toY; y++) + leds[XY(0, y)].nscale8(scale); + } + + // give it a linear tail downwards + void StreamDown(byte scale) + { + for (int x = 0; x < MATRIX_WIDTH; x++) { + for (int y = 1; y < MATRIX_HEIGHT; y++) { + leds[XY(x, y)] += leds[XY(x, y - 1)]; + leds[XY(x, y)].nscale8(scale); + } + } + for (int x = 0; x < MATRIX_WIDTH; x++) + leds[XY(x, 0)].nscale8(scale); + } + + // give it a linear tail upwards + void StreamUp(byte scale) + { + for (int x = 0; x < MATRIX_WIDTH; x++) { + for (int y = MATRIX_HEIGHT - 2; y >= 0; y--) { + leds[XY(x, y)] += leds[XY(x, y + 1)]; + leds[XY(x, y)].nscale8(scale); + } + } + for (int x = 0; x < MATRIX_WIDTH; x++) + leds[XY(x, MATRIX_HEIGHT - 1)].nscale8(scale); + } + + // give it a linear tail up and to the left + void StreamUpAndLeft(byte scale) + { + for (int x = 0; x < MATRIX_WIDTH - 1; x++) { + for (int y = MATRIX_HEIGHT - 2; y >= 0; y--) { + leds[XY(x, y)] += leds[XY(x + 1, y + 1)]; + leds[XY(x, y)].nscale8(scale); + } + } + for (int x = 0; x < MATRIX_WIDTH; x++) + leds[XY(x, MATRIX_HEIGHT - 1)].nscale8(scale); + for (int y = 0; y < MATRIX_HEIGHT; y++) + leds[XY(MATRIX_WIDTH - 1, y)].nscale8(scale); + } + + // give it a linear tail up and to the right + void StreamUpAndRight(byte scale) + { + for (int x = 0; x < MATRIX_WIDTH - 1; x++) { + for (int y = MATRIX_HEIGHT - 2; y >= 0; y--) { + leds[XY(x + 1, y)] += leds[XY(x, y + 1)]; + leds[XY(x, y)].nscale8(scale); + } + } + // fade the bottom row + for (int x = 0; x < MATRIX_WIDTH; x++) + leds[XY(x, MATRIX_HEIGHT - 1)].nscale8(scale); + + // fade the right column + for (int y = 0; y < MATRIX_HEIGHT; y++) + leds[XY(MATRIX_WIDTH - 1, y)].nscale8(scale); + } + + // just move everything one line down + void MoveDown() { + for (int y = MATRIX_HEIGHT - 1; y > 0; y--) { + for (int x = 0; x < MATRIX_WIDTH; x++) { + leds[XY(x, y)] = leds[XY(x, y - 1)]; + } + } + } + + // just move everything one line down + void VerticalMoveFrom(int start, int end) { + for (int y = end; y > start; y--) { + for (int x = 0; x < MATRIX_WIDTH; x++) { + leds[XY(x, y)] = leds[XY(x, y - 1)]; + } + } + } + + // copy the rectangle defined with 2 points x0, y0, x1, y1 + // to the rectangle beginning at x2, x3 + void Copy(byte x0, byte y0, byte x1, byte y1, byte x2, byte y2) { + for (int y = y0; y < y1 + 1; y++) { + for (int x = x0; x < x1 + 1; x++) { + leds[XY(x + x2 - x0, y + y2 - y0)] = leds[XY(x, y)]; + } + } + } + + // rotate + copy triangle (MATRIX_CENTER_X*MATRIX_CENTER_X) + void RotateTriangle() { + for (int x = 1; x < MATRIX_CENTER_X; x++) { + for (int y = 0; y < x; y++) { + leds[XY(x, 7 - y)] = leds[XY(7 - x, y)]; + } + } + } + + // mirror + copy triangle (MATRIX_CENTER_X*MATRIX_CENTER_X) + void MirrorTriangle() { + for (int x = 1; x < MATRIX_CENTER_X; x++) { + for (int y = 0; y < x; y++) { + leds[XY(7 - y, x)] = leds[XY(7 - x, y)]; + } + } + } + + // draw static rainbow triangle pattern (MATRIX_CENTER_XxWIDTH / 2) + // (just for debugging) + void RainbowTriangle() { + for (int i = 0; i < MATRIX_CENTER_X; i++) { + for (int j = 0; j <= i; j++) { + Pixel(7 - i, j, i * j * 4); + } + } + } + + void BresenhamLine(int x0, int y0, int x1, int y1, byte colorIndex) + { + BresenhamLine(x0, y0, x1, y1, ColorFromCurrentPalette(colorIndex)); + } + + void BresenhamLine(int x0, int y0, int x1, int y1, CRGB color) + { + int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1; + int err = dx + dy, e2; + for (;;) { + leds[XY(x0, y0)] += color; + if (x0 == x1 && y0 == y1) break; + e2 = 2 * err; + if (e2 > dy) { + err += dy; + x0 += sx; + } + if (e2 < dx) { + err += dx; + y0 += sy; + } + } + } + + // write one pixel with the specified color from the current palette to coordinates + /* + void Pixel(int x, int y, uint8_t colorIndex) { + leds[XY(x, y)] = ColorFromCurrentPalette(colorIndex); + matrix.drawBackgroundPixelRGB888(x,y, leds[XY(x, y)]); // now draw it? + } + */ + + CRGB ColorFromCurrentPalette(uint8_t index = 0, uint8_t brightness = 255, TBlendType blendType = LINEARBLEND) { + return ColorFromPalette(currentPalette, index, brightness, currentBlendType); + } + + CRGB HsvToRgb(uint8_t h, uint8_t s, uint8_t v) { + CHSV hsv = CHSV(h, s, v); + CRGB rgb; + hsv2rgb_spectrum(hsv, rgb); + return rgb; + } + + void NoiseVariablesSetup() { + noisesmoothing = 200; + + noise_x = random16(); + noise_y = random16(); + noise_z = random16(); + noise_scale_x = 6000; + noise_scale_y = 6000; + } + + void FillNoise() { + for (uint8_t i = 0; i < MATRIX_WIDTH; i++) { + uint32_t ioffset = noise_scale_x * (i - MATRIX_CENTRE_Y); + + for (uint8_t j = 0; j < MATRIX_HEIGHT; j++) { + uint32_t joffset = noise_scale_y * (j - MATRIX_CENTRE_Y); + + byte data = inoise16(noise_x + ioffset, noise_y + joffset, noise_z) >> 8; + + uint8_t olddata = noise[i][j]; + uint8_t newdata = scale8(olddata, noisesmoothing) + scale8(data, 256 - noisesmoothing); + data = newdata; + + noise[i][j] = data; + } + } + } + + // non leds2 memory version. + void MoveX(byte delta) + { + + CRGB tmp = 0; + + for (int y = 0; y < MATRIX_HEIGHT; y++) + { + + // Shift Left: https://codedost.com/c/arraypointers-in-c/c-program-shift-elements-array-left-direction/ + // Computationally heavier but doesn't need an entire leds2 array + + tmp = leds[XY(0, y)]; + for (int m = 0; m < delta; m++) + { + // Do this delta time for each row... computationally expensive potentially. + for(int x = 0; x < MATRIX_WIDTH; x++) + { + leds[XY(x, y)] = leds [XY(x+1, y)]; + } + + leds[XY(MATRIX_WIDTH-1, y)] = tmp; + } + + + /* + // Shift + for (int x = 0; x < MATRIX_WIDTH - delta; x++) { + leds2[XY(x, y)] = leds[XY(x + delta, y)]; + } + + // Wrap around + for (int x = MATRIX_WIDTH - delta; x < MATRIX_WIDTH; x++) { + leds2[XY(x, y)] = leds[XY(x + delta - MATRIX_WIDTH, y)]; + } + */ + } // end row loop + + /* + // write back to leds + for (uint8_t y = 0; y < MATRIX_HEIGHT; y++) { + for (uint8_t x = 0; x < MATRIX_WIDTH; x++) { + leds[XY(x, y)] = leds2[XY(x, y)]; + } + } + */ + } + + void MoveY(byte delta) + { + + CRGB tmp = 0; + for (int x = 0; x < MATRIX_WIDTH; x++) + { + tmp = leds[XY(x, 0)]; + for (int m = 0; m < delta; m++) // moves + { + // Do this delta time for each row... computationally expensive potentially. + for(int y = 0; y < MATRIX_HEIGHT; y++) + { + leds[XY(x, y)] = leds [XY(x, y+1)]; + } + + leds[XY(x, MATRIX_HEIGHT-1)] = tmp; + } + } // end column loop + } /// MoveY + + +}; + +#endif diff --git a/examples/AuroraDemo/Geometry.h b/examples/AuroraDemo/Geometry.h new file mode 100644 index 0000000..4e47557 --- /dev/null +++ b/examples/AuroraDemo/Geometry.h @@ -0,0 +1,150 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from Noel Bundy's work: https://github.com/TwystNeko/Object3d + * Copyright (c) 2014 Noel Bundy + * + * Portions of this code are adapted from the Petty library: https://code.google.com/p/peggy/ + * Copyright (c) 2008 Windell H Oskay. All right reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef Geometry_H +#define Geometry_H + +struct Vertex +{ + float x, y, z; + Vertex() + { + this->set(0, 0, 0); + } + + Vertex(float x, float y, float z) + { + this->set(x, y, z); + } + + void set(float x, float y, float z) + { + this->x = x; + this->y = y; + this->z = z; + } +}; + +struct EdgePoint +{ + int x, y; + boolean visible; + + EdgePoint() + { + this->set(0, 0); + this->visible = false; + } + + void set(int a, int b) + { + this->x = a; + this->y = b; + } +}; + +struct Point +{ + float x, y; + + Point() + { + set(0, 0); + } + + Point(float x, float y) + { + set(x, y); + } + + void set(float x, float y) + { + this->x = x; + this->y = y; + } + +}; + +struct squareFace +{ + int length; + int sommets[4]; + int ed[4]; + + squareFace() + { + set(-1, -1, -1, -1); + } + + squareFace(int a, int b, int c, int d) + { + this->length = 4; + this->sommets[0] = a; + this->sommets[1] = b; + this->sommets[2] = c; + this->sommets[3] = d; + } + + void set(int a, int b, int c, int d) + { + this->length = 4; + this->sommets[0] = a; + this->sommets[1] = b; + this->sommets[2] = c; + this->sommets[3] = d; + } + +}; + +struct triFace +{ + int length; + int sommets[3]; + int ed[3]; + + triFace() + { + set(-1,-1,-1); + } + triFace(int a, int b, int c) + { + this->length =3; + this->sommets[0]=a; + this->sommets[1]=b; + this->sommets[2]=c; + } + void set(int a, int b, int c) + { + this->length =3; + this->sommets[0]=a; + this->sommets[1]=b; + this->sommets[2]=c; + } +}; + +#endif
\ No newline at end of file diff --git a/examples/AuroraDemo/PatternAttract.h b/examples/AuroraDemo/PatternAttract.h new file mode 100644 index 0000000..7df342c --- /dev/null +++ b/examples/AuroraDemo/PatternAttract.h @@ -0,0 +1,73 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternAttract_H + +class PatternAttract : public Drawable { +private: + const int count = 8; + Attractor attractor; + +public: + PatternAttract() { + name = (char *)"Attract"; + } + + void start() { + int direction = random(0, 2); + if (direction == 0) + direction = -1; + + for (int i = 0; i < count; i++) { + Boid boid = Boid(15, 31 - i); + boid.mass = 1; // random(0.1, 2); + boid.velocity.x = ((float) random(40, 50)) / 100.0; + boid.velocity.x *= direction; + boid.velocity.y = 0; + boid.colorIndex = i * 32; + boids[i] = boid; + //dim = random(170, 250); + } + } + + unsigned int drawFrame() { + // dim all pixels on the display + uint8_t dim = beatsin8(2, 170, 250); + effects.DimAll(dim); effects.ShowFrame(); + + for (int i = 0; i < count; i++) { + Boid boid = boids[i]; + + PVector force = attractor.attract(boid); + boid.applyForce(force); + + boid.update(); + effects.drawBackgroundFastLEDPixelCRGB(boid.location.x, boid.location.y, effects.ColorFromCurrentPalette(boid.colorIndex)); + + boids[i] = boid; + } + + return 15; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternBounce.h b/examples/AuroraDemo/PatternBounce.h new file mode 100644 index 0000000..7340514 --- /dev/null +++ b/examples/AuroraDemo/PatternBounce.h @@ -0,0 +1,73 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternBounce_H + +class PatternBounce : public Drawable { +private: + static const int count = 32; + PVector gravity = PVector(0, 0.0125); + +public: + PatternBounce() { + name = (char *)"Bounce"; + } + + void start() { + unsigned int colorWidth = 256 / count; + for (int i = 0; i < count; i++) { + Boid boid = Boid(i, 0); + boid.velocity.x = 0; + boid.velocity.y = i * -0.01; + boid.colorIndex = colorWidth * i; + boid.maxforce = 10; + boid.maxspeed = 10; + boids[i] = boid; + } + } + + unsigned int drawFrame() { + // dim all pixels on the display + effects.DimAll(170); effects.ShowFrame(); + + for (int i = 0; i < count; i++) { + Boid boid = boids[i]; + + boid.applyForce(gravity); + + boid.update(); + + effects.drawBackgroundFastLEDPixelCRGB(boid.location.x, boid.location.y, effects.ColorFromCurrentPalette(boid.colorIndex)); + + if (boid.location.y >= MATRIX_HEIGHT - 1) { + boid.location.y = MATRIX_HEIGHT - 1; + boid.velocity.y *= -1.0; + } + + boids[i] = boid; + } + + return 15; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternCube.h b/examples/AuroraDemo/PatternCube.h new file mode 100644 index 0000000..7f9aefc --- /dev/null +++ b/examples/AuroraDemo/PatternCube.h @@ -0,0 +1,219 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from Noel Bundy's work: https://github.com/TwystNeko/Object3d + * Copyright (c) 2014 Noel Bundy + * + * Portions of this code are adapted from the Petty library: https://code.google.com/p/peggy/ + * Copyright (c) 2008 Windell H Oskay. All right reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternCube_H +#define PatternCube_H + +class PatternCube : public Drawable { + private: + float focal = 30; // Focal of the camera + int cubeWidth = 28; // Cube size + float Angx = 20.0, AngxSpeed = 0.05; // rotation (angle+speed) around X-axis + float Angy = 10.0, AngySpeed = 0.05; // rotation (angle+speed) around Y-axis + float Ox = 15.5, Oy = 15.5; // position (x,y) of the frame center + int zCamera = 110; // distance from cube to the eye of the camera + + // Local vertices + Vertex local[8]; + // Camera aligned vertices + Vertex aligned[8]; + // On-screen projected vertices + Point screen[8]; + // Faces + squareFace face[6]; + // Edges + EdgePoint edge[12]; + int nbEdges; + // ModelView matrix + float m00, m01, m02, m10, m11, m12, m20, m21, m22; + + // constructs the cube + void make(int w) + { + nbEdges = 0; + + local[0].set(-w, w, w); + local[1].set(w, w, w); + local[2].set(w, -w, w); + local[3].set(-w, -w, w); + local[4].set(-w, w, -w); + local[5].set(w, w, -w); + local[6].set(w, -w, -w); + local[7].set(-w, -w, -w); + + face[0].set(1, 0, 3, 2); + face[1].set(0, 4, 7, 3); + face[2].set(4, 0, 1, 5); + face[3].set(4, 5, 6, 7); + face[4].set(1, 2, 6, 5); + face[5].set(2, 3, 7, 6); + + int f, i; + for (f = 0; f < 6; f++) + { + for (i = 0; i < face[f].length; i++) + { + face[f].ed[i] = this->findEdge(face[f].sommets[i], face[f].sommets[i ? i - 1 : face[f].length - 1]); + } + } + } + + // finds edges from faces + int findEdge(int a, int b) + { + int i; + for (i = 0; i < nbEdges; i++) + if ((edge[i].x == a && edge[i].y == b) || (edge[i].x == b && edge[i].y == a)) + return i; + edge[nbEdges++].set(a, b); + return i; + } + + // rotates according to angle x&y + void rotate(float angx, float angy) + { + int i; + float cx = cos(angx); + float sx = sin(angx); + float cy = cos(angy); + float sy = sin(angy); + + m00 = cy; + m01 = 0; + m02 = -sy; + m10 = sx * sy; + m11 = cx; + m12 = sx * cy; + m20 = cx * sy; + m21 = -sx; + m22 = cx * cy; + + for (i = 0; i < 8; i++) + { + aligned[i].x = m00 * local[i].x + m01 * local[i].y + m02 * local[i].z; + aligned[i].y = m10 * local[i].x + m11 * local[i].y + m12 * local[i].z; + aligned[i].z = m20 * local[i].x + m21 * local[i].y + m22 * local[i].z + zCamera; + + screen[i].x = floor((Ox + focal * aligned[i].x / aligned[i].z)); + screen[i].y = floor((Oy - focal * aligned[i].y / aligned[i].z)); + } + + for (i = 0; i < 12; i++) + edge[i].visible = false; + + Point *pa, *pb, *pc; + for (i = 0; i < 6; i++) + { + pa = screen + face[i].sommets[0]; + pb = screen + face[i].sommets[1]; + pc = screen + face[i].sommets[2]; + + boolean back = ((pb->x - pa->x) * (pc->y - pa->y) - (pb->y - pa->y) * (pc->x - pa->x)) < 0; + if (!back) + { + int j; + for (j = 0; j < 4; j++) + { + edge[face[i].ed[j]].visible = true; + } + } + } + } + + byte hue = 0; + int step = 0; + + public: + PatternCube() { + name = (char *)"Cube"; + make(cubeWidth); + } + + unsigned int drawFrame() { + uint8_t blurAmount = beatsin8(2, 10, 255); + +#if FASTLED_VERSION >= 3001000 + blur2d(effects.leds, MATRIX_WIDTH, MATRIX_HEIGHT, blurAmount); +#else + effects.DimAll(blurAmount); effects.ShowFrame(); +#endif + + zCamera = beatsin8(2, 100, 140); + AngxSpeed = beatsin8(3, 1, 10) / 100.0f; + AngySpeed = beatcos8(5, 1, 10) / 100.0f; + + // Update values + Angx += AngxSpeed; + Angy += AngySpeed; + if (Angx >= TWO_PI) + Angx -= TWO_PI; + if (Angy >= TWO_PI) + Angy -= TWO_PI; + + rotate(Angx, Angy); + + // Draw cube + int i; + + CRGB color = effects.ColorFromCurrentPalette(hue, 128); + + // Backface + EdgePoint *e; + for (i = 0; i < 12; i++) + { + e = edge + i; + if (!e->visible) { + matrix.drawLine(screen[e->x].x, screen[e->x].y, screen[e->y].x, screen[e->y].y, color); + } + } + + color = effects.ColorFromCurrentPalette(hue, 255); + + // Frontface + for (i = 0; i < 12; i++) + { + e = edge + i; + if (e->visible) + { + matrix.drawLine(screen[e->x].x, screen[e->x].y, screen[e->y].x, screen[e->y].y, color); + } + } + + step++; + if (step == 8) { + step = 0; + hue++; + } + + effects.ShowFrame(); + + return 20; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternElectricMandala.h b/examples/AuroraDemo/PatternElectricMandala.h new file mode 100644 index 0000000..2ba0a62 --- /dev/null +++ b/examples/AuroraDemo/PatternElectricMandala.h @@ -0,0 +1,116 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from "Funky Noise" by Stefan Petrick: https://github.com/StefanPetrick/FunkyNoise + * Copyright (c) 2014 Stefan Petrick + * http://www.stefan-petrick.de/wordpress_beta + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternElectricMandala_H + +class PatternElectricMandala : public Drawable { + private: + + // The coordinates for 16-bit noise spaces. +#define NUM_LAYERS 1 + + // used for the random based animations + int16_t dx; + int16_t dy; + int16_t dz; + int16_t dsx; + int16_t dsy; + + public: + PatternElectricMandala() { + name = (char *)"ElectricMandala"; + } + + void start() { + // set to reasonable values to avoid a black out + noisesmoothing = 200; + + // just any free input pin + //random16_add_entropy(analogRead(18)); + + // fill coordinates with random values + // set zoom levels + noise_x = random16(); + noise_y = random16(); + noise_z = random16(); + noise_scale_x = 6000; + noise_scale_y = 6000; + + // for the random movement + dx = random8(); + dy = random8(); + dz = random8(); + dsx = random8(); + dsy = random8(); + } + + unsigned int drawFrame() { +#if FASTLED_VERSION >= 3001000 + // a new parameter set every 15 seconds + EVERY_N_SECONDS(15) { + //SetupRandomPalette3(); + dy = random16(500) - 250; // random16(2000) - 1000 is pretty fast but works fine, too + dx = random16(500) - 250; + dz = random16(500) - 250; + noise_scale_x = random16(10000) + 2000; + noise_scale_y = random16(10000) + 2000; + } +#endif + + noise_y += dy; + noise_x += dx; + noise_z += dz; + + effects.FillNoise(); + ShowNoiseLayer(0, 1, 0); + + effects.Caleidoscope3(); + effects.Caleidoscope1(); + + effects.ShowFrame(); + + return 0; + } + + // show just one layer + void ShowNoiseLayer(byte layer, byte colorrepeat, byte colorshift) { + for (uint8_t i = 0; i < MATRIX_WIDTH; i++) { + for (uint8_t j = 0; j < MATRIX_HEIGHT; j++) { + + uint8_t color = noise[i][j]; + + uint8_t bri = color; + + // assign a color depending on the actual palette + CRGB pixel = ColorFromPalette(effects.currentPalette, colorrepeat * (color + colorshift), bri); + + effects.leds[XY(i, j)] = pixel; + } + } + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternFire.h b/examples/AuroraDemo/PatternFire.h new file mode 100644 index 0000000..83aa67c --- /dev/null +++ b/examples/AuroraDemo/PatternFire.h @@ -0,0 +1,118 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from FastLED Fire2012 example by Mark Kriegsman: https://github.com/FastLED/FastLED/tree/master/examples/Fire2012WithPalette + * Copyright (c) 2013 FastLED + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternFire_H +#define PatternFire_H + +#ifndef Effects_H +#include "Effects.h" +#endif + +class PatternFire : public Drawable { + private: + + public: + PatternFire() { + name = (char *)"Fire"; + } + + // There are two main parameters you can play with to control the look and + // feel of your fire: COOLING (used in step 1 above), and SPARKING (used + // in step 3 above). + // + // cooling: How much does the air cool as it rises? + // Less cooling = taller flames. More cooling = shorter flames. + // Default 55, suggested range 20-100 + int cooling = 100; + + // sparking: What chance (out of 255) is there that a new spark will be lit? + // Higher chance = more roaring fire. Lower chance = more flickery fire. + // Default 120, suggested range 50-200. + unsigned int sparking = 100; + + unsigned int drawFrame() { + // Add entropy to random number generator; we use a lot of it. + random16_add_entropy( random16()); + + effects.DimAll(235); + + for (int x = 0; x < MATRIX_WIDTH; x++) { + // Step 1. Cool down every cell a little + for (int y = 0; y < MATRIX_HEIGHT; y++) { + int xy = XY(x, y); + heat[xy] = qsub8(heat[xy], random8(0, ((cooling * 10) / MATRIX_HEIGHT) + 2)); + } + + // Step 2. Heat from each cell drifts 'up' and diffuses a little + for (int y = 0; y < MATRIX_HEIGHT; y++) { + heat[XY(x, y)] = (heat[XY(x, y + 1)] + heat[XY(x, y + 2)] + heat[XY(x, y + 2)]) / 3; + } + + // Step 2. Randomly ignite new 'sparks' of heat + if (random8() < sparking) { + // int x = (p[0] + p[1] + p[2]) / 3; + + int xy = XY(x, MATRIX_HEIGHT - 1); + heat[xy] = qadd8(heat[xy], random8(160, 255)); + } + + // Step 4. Map from heat cells to LED colors + for (int y = 0; y < MATRIX_HEIGHT; y++) { + int xy = XY(x, y); + byte colorIndex = heat[xy]; + + // Recommend that you use values 0-240 rather than + // the usual 0-255, as the last 15 colors will be + // 'wrapping around' from the hot end to the cold end, + // which looks wrong. + colorIndex = scale8(colorIndex, 200); + + // override color 0 to ensure a black background? + if (colorIndex != 0) + // effects.leds[xy] = CRGB::Black; + // else + effects.leds[xy] = effects.ColorFromCurrentPalette(colorIndex); + } + } + + // Noise + noise_x += 1000; + noise_y += 1000; + noise_z += 1000; + noise_scale_x = 4000; + noise_scale_y = 4000; + effects.FillNoise(); + + effects.MoveX(2); + effects.MoveFractionalNoiseX(2); + + + effects.ShowFrame(); + + return 15; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternFlock.h b/examples/AuroraDemo/PatternFlock.h new file mode 100644 index 0000000..3ae31b1 --- /dev/null +++ b/examples/AuroraDemo/PatternFlock.h @@ -0,0 +1,125 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from "Flocking" in "The Nature of Code" by Daniel Shiffman: http://natureofcode.com/ + * Copyright (c) 2014 Daniel Shiffman + * http://www.shiffman.net + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// Flocking +// Daniel Shiffman <http://www.shiffman.net> +// The Nature of Code, Spring 2009 + +// Demonstration of Craig Reynolds' "Flocking" behavior +// See: http://www.red3d.com/cwr/ +// Rules: Cohesion, Separation, Alignment + +#ifndef PatternFlock_H +#define PatternFlock_H + +class PatternFlock : public Drawable { + public: + PatternFlock() { + name = (char *)"Flock"; + } + + static const int boidCount = 10; + Boid predator; + + PVector wind; + byte hue = 0; + bool predatorPresent = true; + + void start() { + for (int i = 0; i < boidCount; i++) { + boids[i] = Boid(15, 15); + boids[i].maxspeed = 0.380; + boids[i].maxforce = 0.015; + } + + predatorPresent = random(0, 2) >= 1; + if (predatorPresent) { + predator = Boid(31, 31); + predatorPresent = true; + predator.maxspeed = 0.385; + predator.maxforce = 0.020; + predator.neighbordist = 16.0; + predator.desiredseparation = 0.0; + } + } + + unsigned int drawFrame() { + effects.DimAll(230); effects.ShowFrame(); + + bool applyWind = random(0, 255) > 250; + if (applyWind) { + wind.x = Boid::randomf() * .015; + wind.y = Boid::randomf() * .015; + } + + CRGB color = effects.ColorFromCurrentPalette(hue); + + for (int i = 0; i < boidCount; i++) { + Boid * boid = &boids[i]; + + if (predatorPresent) { + // flee from predator + boid->repelForce(predator.location, 10); + } + + boid->run(boids, boidCount); + boid->wrapAroundBorders(); + PVector location = boid->location; + // PVector velocity = boid->velocity; + // backgroundLayer.drawLine(location.x, location.y, location.x - velocity.x, location.y - velocity.y, color); + // effects.leds[XY(location.x, location.y)] += color; + effects.drawBackgroundFastLEDPixelCRGB(location.x, location.y, color); + + if (applyWind) { + boid->applyForce(wind); + applyWind = false; + } + } + + if (predatorPresent) { + predator.run(boids, boidCount); + predator.wrapAroundBorders(); + color = effects.ColorFromCurrentPalette(hue + 128); + PVector location = predator.location; + // PVector velocity = predator.velocity; + // backgroundLayer.drawLine(location.x, location.y, location.x - velocity.x, location.y - velocity.y, color); + // effects.leds[XY(location.x, location.y)] += color; + effects.drawBackgroundFastLEDPixelCRGB(location.x, location.y, color); + } + + EVERY_N_MILLIS(200) { + hue++; + } + + EVERY_N_SECONDS(30) { + predatorPresent = !predatorPresent; + } + + return 0; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternFlowField.h b/examples/AuroraDemo/PatternFlowField.h new file mode 100644 index 0000000..38f1083 --- /dev/null +++ b/examples/AuroraDemo/PatternFlowField.h @@ -0,0 +1,92 @@ +/* +* Aurora: https://github.com/pixelmatix/aurora +* Copyright (c) 2014 Jason Coon +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +* the Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef PatternFlowField_H + +class PatternFlowField : public Drawable { + public: + PatternFlowField() { + name = (char *)"FlowField"; + } + + uint16_t x; + uint16_t y; + uint16_t z; + + uint16_t speed = 1; + uint16_t scale = 26; + + static const int count = 40; + + byte hue = 0; + + void start() { + x = random16(); + y = random16(); + z = random16(); + + for (int i = 0; i < count; i++) { + boids[i] = Boid(random(MATRIX_WIDTH), 0); + } + } + + unsigned int drawFrame() { + effects.DimAll(240); + + // CRGB color = effects.ColorFromCurrentPalette(hue); + + for (int i = 0; i < count; i++) { + Boid * boid = &boids[i]; + + int ioffset = scale * boid->location.x; + int joffset = scale * boid->location.y; + + byte angle = inoise8(x + ioffset, y + joffset, z); + + boid->velocity.x = (float) sin8(angle) * 0.0078125 - 1.0; + boid->velocity.y = -((float)cos8(angle) * 0.0078125 - 1.0); + boid->update(); + + effects.drawBackgroundFastLEDPixelCRGB(boid->location.x, boid->location.y, effects.ColorFromCurrentPalette(angle + hue)); // color + + if (boid->location.x < 0 || boid->location.x >= MATRIX_WIDTH || + boid->location.y < 0 || boid->location.y >= MATRIX_HEIGHT) { + boid->location.x = random(MATRIX_WIDTH); + boid->location.y = 0; + } + } + + EVERY_N_MILLIS(200) { + hue++; + } + + x += speed; + y += speed; + z += speed; + + effects.ShowFrame(); + + return 50; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternIncrementalDrift.h b/examples/AuroraDemo/PatternIncrementalDrift.h new file mode 100644 index 0000000..f68c04f --- /dev/null +++ b/examples/AuroraDemo/PatternIncrementalDrift.h @@ -0,0 +1,51 @@ +/* +* +* Aurora: https://github.com/pixelmatix/aurora +* Copyright (c) 2014 Jason Coon +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +* the Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef PatternIncrementalDrift_H +#define PatternIncrementalDrift_H + +class PatternIncrementalDrift : public Drawable { + public: + PatternIncrementalDrift() { + name = (char *)"Incremental Drift"; + } + + unsigned int drawFrame() { + uint8_t dim = beatsin8(2, 230, 250); + effects.DimAll(dim); effects.ShowFrame(); + + for (int i = 2; i <= MATRIX_WIDTH / 2; i++) + { + CRGB color = effects.ColorFromCurrentPalette((i - 2) * (240 / (MATRIX_WIDTH / 2))); + + uint8_t x = beatcos8((17 - i) * 2, MATRIX_CENTER_X - i, MATRIX_CENTER_X + i); + uint8_t y = beatsin8((17 - i) * 2, MATRIX_CENTER_Y - i, MATRIX_CENTER_Y + i); + + effects.drawBackgroundFastLEDPixelCRGB(x, y, color); + } + + return 0; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternIncrementalDrift2.h b/examples/AuroraDemo/PatternIncrementalDrift2.h new file mode 100644 index 0000000..0ce06c2 --- /dev/null +++ b/examples/AuroraDemo/PatternIncrementalDrift2.h @@ -0,0 +1,63 @@ +/* +* +* Aurora: https://github.com/pixelmatix/aurora +* Copyright (c) 2014 Jason Coon +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +* the Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef PatternIncrementalDrift2_H +#define PatternIncrementalDrift2_H + +class PatternIncrementalDrift2 : public Drawable { + public: + PatternIncrementalDrift2() { + name = (char *)"Incremental Drift Rose"; + } + + unsigned int drawFrame() { + uint8_t dim = beatsin8(2, 170, 250); + effects.DimAll(dim); effects.ShowFrame(); + + for (uint8_t i = 0; i < 32; i++) + { + CRGB color; + + uint8_t x = 0; + uint8_t y = 0; + + if (i < 16) { + x = beatcos8((i + 1) * 2, i, MATRIX_WIDTH - i); + y = beatsin8((i + 1) * 2, i, MATRIX_HEIGHT - i); + color = effects.ColorFromCurrentPalette(i * 14); + } + else + { + x = beatsin8((32 - i) * 2, MATRIX_WIDTH - i, i + 1); + y = beatcos8((32 - i) * 2, MATRIX_HEIGHT - i, i + 1); + color = effects.ColorFromCurrentPalette((31 - i) * 14); + } + + effects.drawBackgroundFastLEDPixelCRGB(x, y, color); + } + + return 0; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternInfinity.h b/examples/AuroraDemo/PatternInfinity.h new file mode 100644 index 0000000..92f6b9c --- /dev/null +++ b/examples/AuroraDemo/PatternInfinity.h @@ -0,0 +1,58 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternInfinity_H + +class PatternInfinity : public Drawable { +public: + PatternInfinity() { + name = (char *)"Infinity"; + } + + unsigned int drawFrame() { + // dim all pixels on the display slightly + // to 250/255 (98%) of their current brightness + effects.DimAll(250); effects.ShowFrame(); + + // the Effects class has some sample oscillators + // that move from 0 to 255 at different speeds + effects.MoveOscillators(); + + // the horizontal position of the head of the infinity sign + // oscillates from 0 to the maximum horizontal and back + int x = (MATRIX_WIDTH - 1) - effects.p[1]; + + // the vertical position of the head oscillates + // from 8 to 23 and back (hard-coded for a 32x32 matrix) + int y = map8(sin8(effects.osci[3]), 8, 23); + + // the hue oscillates from 0 to 255, overflowing back to 0 + byte hue = sin8(effects.osci[5]); + + // draw a pixel at x,y using a color from the current palette + effects.Pixel(x, y, hue); + + return 15; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternInvaders.h b/examples/AuroraDemo/PatternInvaders.h new file mode 100644 index 0000000..cad004c --- /dev/null +++ b/examples/AuroraDemo/PatternInvaders.h @@ -0,0 +1,154 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Inspired by 'Space Invader Generator': https://the8bitpimp.wordpress.com/2013/05/07/space-invader-generator + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternInvaders_H +#define PatternInvaders_H + +class PatternInvadersSmall : public Drawable { + private: + uint8_t x = 1; + uint8_t y = 1; + + public: + PatternInvadersSmall() { + name = (char *)"Invaders Small"; + } + + void start() { + matrix.fillScreen(0); + } + + unsigned int drawFrame() { + CRGB color1 = effects.ColorFromCurrentPalette(random(0, 255)); + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 5; j++) { + CRGB color = CRGB::Black; + + if (random(0, 2) == 1) color = color1; + + effects.drawBackgroundFastLEDPixelCRGB(x + i, y + j, color); + + if (i < 2) + effects.drawBackgroundFastLEDPixelCRGB(x + (4 - i), y + j, color); + } + } + + x += 6; + if (x > 25) { + x = 1; + y += 6; + } + + if (y > 25) y = x = 1; + + effects.ShowFrame(); + + return 125; + } +}; + +class PatternInvadersMedium : public Drawable { + private: + uint8_t x = 0; + uint8_t y = 0; + + public: + PatternInvadersMedium() { + name = (char *)"Invaders Medium"; + } + + void start() { + matrix.fillScreen(0); + } + + unsigned int drawFrame() { + CRGB color1 = effects.ColorFromCurrentPalette(random(0, 255)); + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 5; j++) { + CRGB color = CRGB::Black; + + if (random(0, 2) == 1) color = color1; + + matrix.fillRect(x + (i * 2), y + (j * 2), x + (i * 2 + 1), y + (j * 2 + 1), color); + + if (i < 2) + matrix.fillRect(x + (8 - i * 2), y + (j * 2), x + (9 - i * 2), y + (j * 2 + 1), color); + } + } + + x += 11; + if (x > 22) { + x = 0; + y += 11; + } + + if (y > 22) y = x = 0; + + effects.ShowFrame(); + + return 500; + } +}; + +class PatternInvadersLarge : public Drawable { + private: + + public: + PatternInvadersLarge() { + name = (char *)"Invaders Large"; + } + + void start() { + matrix.fillScreen(0); + } + + unsigned int drawFrame() { + matrix.fillScreen(0); + + CRGB color1 = effects.ColorFromCurrentPalette(random(0, 255)); + + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 5; y++) { + CRGB color = CRGB::Black; + + if (random(0, 2) == 1) { + color = color1; + } + + matrix.fillRect(1 + x * 6, 1 + y * 6, 5 + x * 6, 5 + y * 6, color); + + if (x < 2) + matrix.fillRect(1 + (4 - x) * 6, 1 + y * 6, 5 + (4 - x) * 6, 5 + y * 6, color); + } + } + + effects.ShowFrame(); + + return 2000; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternLife.h b/examples/AuroraDemo/PatternLife.h new file mode 100644 index 0000000..7c9ef30 --- /dev/null +++ b/examples/AuroraDemo/PatternLife.h @@ -0,0 +1,129 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from Andrew: http://pastebin.com/f22bfe94d + * which, in turn, was "Adapted from the Life example on the Processing.org site" + * + * Made much more colorful by J.B. Langston: https://github.com/jblang/aurora/commit/6db5a884e3df5d686445c4f6b669f1668841929b + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternLife_H +#define PatternLife_H + +class Cell { +public: + byte alive : 1; + byte prev : 1; + byte hue: 6; + byte brightness; +}; + +class PatternLife : public Drawable { +private: + Cell world[MATRIX_WIDTH][MATRIX_HEIGHT]; + unsigned int density = 50; + int generation = 0; + + void randomFillWorld() { + for (int i = 0; i < MATRIX_WIDTH; i++) { + for (int j = 0; j < MATRIX_HEIGHT; j++) { + if (random(100) < density) { + world[i][j].alive = 1; + world[i][j].brightness = 255; + } + else { + world[i][j].alive = 0; + world[i][j].brightness = 0; + } + world[i][j].prev = world[i][j].alive; + world[i][j].hue = 0; + } + } + } + + int neighbours(int x, int y) { + return (world[(x + 1) % MATRIX_WIDTH][y].prev) + + (world[x][(y + 1) % MATRIX_HEIGHT].prev) + + (world[(x + MATRIX_WIDTH - 1) % MATRIX_WIDTH][y].prev) + + (world[x][(y + MATRIX_HEIGHT - 1) % MATRIX_HEIGHT].prev) + + (world[(x + 1) % MATRIX_WIDTH][(y + 1) % MATRIX_HEIGHT].prev) + + (world[(x + MATRIX_WIDTH - 1) % MATRIX_WIDTH][(y + 1) % MATRIX_HEIGHT].prev) + + (world[(x + MATRIX_WIDTH - 1) % MATRIX_WIDTH][(y + MATRIX_HEIGHT - 1) % MATRIX_HEIGHT].prev) + + (world[(x + 1) % MATRIX_WIDTH][(y + MATRIX_HEIGHT - 1) % MATRIX_HEIGHT].prev); + } + +public: + PatternLife() { + name = (char *)"Life"; + } + + unsigned int drawFrame() { + if (generation == 0) { + effects.ClearFrame(); + + randomFillWorld(); + } + + // Display current generation + for (int i = 0; i < MATRIX_WIDTH; i++) { + for (int j = 0; j < MATRIX_HEIGHT; j++) { + effects.leds[XY(i, j)] = effects.ColorFromCurrentPalette(world[i][j].hue * 4, world[i][j].brightness); + } + } + + // Birth and death cycle + for (int x = 0; x < MATRIX_WIDTH; x++) { + for (int y = 0; y < MATRIX_HEIGHT; y++) { + // Default is for cell to stay the same + if (world[x][y].brightness > 0 && world[x][y].prev == 0) + world[x][y].brightness *= 0.9; + int count = neighbours(x, y); + if (count == 3 && world[x][y].prev == 0) { + // A new cell is born + world[x][y].alive = 1; + world[x][y].hue += 2; + world[x][y].brightness = 255; + } else if ((count < 2 || count > 3) && world[x][y].prev == 1) { + // Cell dies + world[x][y].alive = 0; + } + } + } + + // Copy next generation into place + for (int x = 0; x < MATRIX_WIDTH; x++) { + for (int y = 0; y < MATRIX_HEIGHT; y++) { + world[x][y].prev = world[x][y].alive; + } + } + + + generation++; + if (generation >= 256) + generation = 0; + + effects.ShowFrame(); + + return 60; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternMaze.h b/examples/AuroraDemo/PatternMaze.h new file mode 100644 index 0000000..eaa1089 --- /dev/null +++ b/examples/AuroraDemo/PatternMaze.h @@ -0,0 +1,264 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Many thanks to Jamis Buck for the documentation of the Growing Tree maze generation algorithm: http://weblog.jamisbuck.org/2011/1/27/maze-generation-growing-tree-algorithm + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternMaze_H +#define PatternMaze_H + +class PatternMaze : public Drawable { +private: + enum Directions { + None = 0, + Up = 1, + Down = 2, + Left = 4, + Right = 8, + }; + + struct Point{ + int x; + int y; + + static Point New(int x, int y) { + Point point; + point.x = x; + point.y = y; + return point; + } + + Point Move(Directions direction) { + switch (direction) + { + case Up: + return New(x, y - 1); + + case Down: + return New(x, y + 1); + + case Left: + return New(x - 1, y); + + case Right: + default: + return New(x + 1, y); + } + } + + static Directions Opposite(Directions direction) { + switch (direction) { + case Up: + return Down; + + case Down: + return Up; + + case Left: + return Right; + + case Right: + default: + return Left; + } + } + }; + +// int width = 16; +// int height = 16; + + static const int width = MATRIX_WIDTH / 2; + static const int height = MATRIX_HEIGHT / 2; + + + Directions grid[width][height]; + + Point point; + + Point cells[256]; + int cellCount = 0; + + int algorithm = 0; + int algorithmCount = 1; + + byte hue = 0; + byte hueOffset = 0; + + Directions directions[4] = { Up, Down, Left, Right }; + + void removeCell(int index) {// shift cells after index down one + for (int i = index; i < cellCount - 1; i++) { + cells[i] = cells[i + 1]; + } + + cellCount--; + } + + void shuffleDirections() { + for (int a = 0; a < 4; a++) + { + int r = random(a, 4); + Directions temp = directions[a]; + directions[a] = directions[r]; + directions[r] = temp; + } + } + + Point createPoint(int x, int y) { + Point point; + point.x = x; + point.y = y; + return point; + } + + CRGB chooseColor(int index) { + byte h = index + hueOffset; + + switch (algorithm) { + case 0: + default: + return effects.ColorFromCurrentPalette(h); + + case 1: + return effects.ColorFromCurrentPalette(hue++); + } + } + + int chooseIndex(int max) { + switch (algorithm) { + case 0: + default: + // choose newest (recursive backtracker) + return max - 1; + + case 1: + // choose random(Prim's) + return random(max); + + // case 2: + // // choose oldest (not good, so disabling) + // return 0; + } + } + + void generateMaze() { + while (cellCount > 1) { + drawNextCell(); + } + } + + void drawNextCell() { + int index = chooseIndex(cellCount); + + if (index < 0) + return; + + point = cells[index]; + + Point imagePoint = createPoint(point.x * 2, point.y * 2); + + //effects.drawBackgroundFastLEDPixelCRGB(imagePoint.x, imagePoint.y, CRGB(CRGB::Gray)); + + shuffleDirections(); + + CRGB color = chooseColor(index); + + for (int i = 0; i < 4; i++) { + Directions direction = directions[i]; + + Point newPoint = point.Move(direction); + if (newPoint.x >= 0 && newPoint.y >= 0 && newPoint.x < width && newPoint.y < height && grid[newPoint.y][newPoint.x] == None) { + grid[point.y][point.x] = (Directions) ((int) grid[point.y][point.x] | (int) direction); + grid[newPoint.y][newPoint.x] = (Directions) ((int) grid[newPoint.y][newPoint.x] | (int) point.Opposite(direction)); + + Point newImagePoint = imagePoint.Move(direction); + + effects.drawBackgroundFastLEDPixelCRGB(newImagePoint.x, newImagePoint.y, color); + + cellCount++; + cells[cellCount - 1] = newPoint; + + index = -1; + break; + } + } + + if (index > -1) { + Point finishedPoint = cells[index]; + imagePoint = createPoint(finishedPoint.x * 2, finishedPoint.y * 2); + effects.drawBackgroundFastLEDPixelCRGB(imagePoint.x, imagePoint.y, color); + + removeCell(index); + } + } + +public: + PatternMaze() { + name = (char *)"Maze"; + } + + unsigned int drawFrame() { + if (cellCount < 1) { + + effects.ClearFrame(); + + // reset the maze grid + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + grid[y][x] = None; + } + } + + int x = random(width); + int y = random(height); + + cells[0] = createPoint(x, y); + + cellCount = 1; + + hue = 0; + hueOffset = random(0, 256); + + } + + drawNextCell(); + + if (cellCount < 1) { + algorithm++; + if (algorithm >= algorithmCount) + algorithm = 0; + + return 1000; + } + + effects.ShowFrame(); + + return 0; + } + + void start() { + matrix.fillScreen(0); + cellCount = 0; + hue = 0; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternMunch.h b/examples/AuroraDemo/PatternMunch.h new file mode 100644 index 0000000..b581b53 --- /dev/null +++ b/examples/AuroraDemo/PatternMunch.h @@ -0,0 +1,74 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Munch pattern created by J.B. Langston: https://github.com/jblang/aurora/blob/master/PatternMunch.h + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternMunch_H +#define PatternMunch_H + + +class PatternMunch : public Drawable { +private: + byte count = 0; + byte dir = 1; + byte flip = 0; + byte generation = 0; + +public: + PatternMunch() { + name = (char *)"Munch"; + } + + unsigned int drawFrame() { + + for (byte x = 0; x < MATRIX_WIDTH; x++) { + for (byte y = 0; y < MATRIX_HEIGHT; y++) { + effects.leds[XY(x, y)] = (x ^ y ^ flip) < count ? effects.ColorFromCurrentPalette(((x ^ y) << 2) + generation) : CRGB::Black; + + // The below is more pleasant + // effects.leds[XY(x, y)] = effects.ColorFromCurrentPalette(((x ^ y) << 2) + generation) ; + } + } + + count += dir; + + if (count <= 0 || count >= MATRIX_WIDTH) { + dir = -dir; + } + + if (count <= 0) { + if (flip == 0) + flip = MATRIX_WIDTH-1; + else + flip = 0; + } + + generation++; + + // show it ffs! + effects.ShowFrame(); + + return 60; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternNoiseSmearing.h b/examples/AuroraDemo/PatternNoiseSmearing.h new file mode 100644 index 0000000..ab7ed7b --- /dev/null +++ b/examples/AuroraDemo/PatternNoiseSmearing.h @@ -0,0 +1,338 @@ +/* +* Aurora: https://github.com/pixelmatix/aurora +* Copyright (c) 2014 Jason Coon +* +* Portions of this code are adapted from "Noise Smearing" by Stefan Petrick: https://gist.githubusercontent.com/embedded-creations/5cd47d83cb0e04f4574d/raw/ebf6a82b4755d55cfba3bf6598f7b19047f89daf/NoiseSmearing.ino +* Copyright (c) 2014 Stefan Petrick +* http://www.stefan-petrick.de/wordpress_beta +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +* the Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef PatternNoiseSmearing_H +#define PatternNoiseSmearing_H + +byte patternNoiseSmearingHue = 0; + +class PatternMultipleStream : public Drawable { +public: + PatternMultipleStream() { + name = (char *)"MultipleStream"; + } + + // this pattern draws two points to the screen based on sin/cos if a counter + // (comment out NoiseSmearWithRadius to see pattern of pixels) + // these pixels are smeared by a large radius, giving a lot of movement + // the image is dimmed before each drawing to not saturate the screen with color + // the smear has an offset so the pixels usually have a trail leading toward the upper left + unsigned int drawFrame() { + static unsigned long counter = 0; +#if 0 + // this counter lets put delays between each frame and still get the same animation + counter++; +#else + // this counter updates in real time and can't be slowed down for debugging + counter = millis() / 10; +#endif + + byte x1 = 4 + sin8(counter * 2) / 10; + byte x2 = 8 + sin8(counter * 2) / 16; + byte y2 = 8 + cos8((counter * 2) / 3) / 16; + + effects.leds[XY(x1, x2)] = effects.ColorFromCurrentPalette(patternNoiseSmearingHue); + effects.leds[XY(x2, y2)] = effects.ColorFromCurrentPalette(patternNoiseSmearingHue + 128); + + // Noise + noise_x += 1000; + noise_y += 1000; + noise_scale_x = 4000; + noise_scale_y = 4000; + effects.FillNoise(); + + effects.MoveX(8); + effects.MoveFractionalNoiseX(); + + effects.MoveY(8); + effects.MoveFractionalNoiseY(); + + patternNoiseSmearingHue++; + + return 0; + } +}; + +class PatternMultipleStream2 : public Drawable { +public: + PatternMultipleStream2() { + name = (char *)"MultipleStream2"; + } + + unsigned int drawFrame() { + effects.DimAll(230); effects.ShowFrame(); + + byte xx = 4 + sin8(millis() / 9) / 10; + byte yy = 4 + cos8(millis() / 10) / 10; + effects.leds[XY(xx, yy)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue); + + xx = 8 + sin8(millis() / 10) / 16; + yy = 8 + cos8(millis() / 7) / 16; + effects.leds[XY(xx, yy)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue + 80); + + effects.leds[XY(15, 15)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue + 160); + + noise_x += 1000; + noise_y += 1000; + noise_z += 1000; + noise_scale_x = 4000; + noise_scale_y = 4000; + effects.FillNoise(); + + effects.MoveX(3); + effects.MoveFractionalNoiseY(4); + + effects.MoveY(3); + effects.MoveFractionalNoiseX(4); + + patternNoiseSmearingHue++; + + return 0; + } +}; + +class PatternMultipleStream3 : public Drawable { +public: + PatternMultipleStream3() { + name = (char *)"MultipleStream3"; + } + + unsigned int drawFrame() { + //CLS(); + effects.DimAll(235); effects.ShowFrame(); + + for (uint8_t i = 3; i < 32; i = i + 4) { + effects.leds[XY(i, 15)] += effects.ColorFromCurrentPalette(i * 8); + } + + // Noise + noise_x += 1000; + noise_y += 1000; + noise_z += 1000; + noise_scale_x = 4000; + noise_scale_y = 4000; + effects.FillNoise(); + + effects.MoveX(3); + effects.MoveFractionalNoiseY(4); + + effects.MoveY(3); + effects.MoveFractionalNoiseX(4); + + effects.ShowFrame(); + + return 1; + } +}; + +class PatternMultipleStream4 : public Drawable { +public: + PatternMultipleStream4() { + name = (char *)"MultipleStream4"; + } + + unsigned int drawFrame() { + + //CLS(); + effects.DimAll(235); effects.ShowFrame(); + + effects.leds[XY(15, 15)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue); + + + // Noise + noise_x += 1000; + noise_y += 1000; + noise_scale_x = 4000; + noise_scale_y = 4000; + effects.FillNoise(); + + effects.MoveX(8); + effects.MoveFractionalNoiseX(); + + effects.MoveY(8); + effects.MoveFractionalNoiseY(); + + patternNoiseSmearingHue++; + + return 0; + } +}; + +class PatternMultipleStream5 : public Drawable { +public: + PatternMultipleStream5() { + name = (char *)"MultipleStream5"; + } + + unsigned int drawFrame() { + + //CLS(); + effects.DimAll(235); effects.ShowFrame(); + + + for (uint8_t i = 3; i < 32; i = i + 4) { + effects.leds[XY(i, 31)] += effects.ColorFromCurrentPalette(i * 8); + } + + // Noise + noise_x += 1000; + noise_y += 1000; + noise_z += 1000; + noise_scale_x = 4000; + noise_scale_y = 4000; + effects.FillNoise(); + + effects.MoveX(3); + effects.MoveFractionalNoiseY(4); + + effects.MoveY(4); + effects.MoveFractionalNoiseX(4); + + return 0; + } +}; + +class PatternMultipleStream8 : public Drawable { +public: + PatternMultipleStream8() { + name = (char *)"MultipleStream8"; + } + + unsigned int drawFrame() { + effects.DimAll(230); effects.ShowFrame(); + + // draw grid of rainbow dots on top of the dimmed image + for (uint8_t y = 1; y < 32; y = y + 6) { + for (uint8_t x = 1; x < 32; x = x + 6) { + + effects.leds[XY(x, y)] += effects.ColorFromCurrentPalette((x * y) / 4); + } + } + + // Noise + noise_x += 1000; + noise_y += 1000; + noise_z += 1000; + noise_scale_x = 4000; + noise_scale_y = 4000; + effects.FillNoise(); + + effects.MoveX(3); + effects.MoveFractionalNoiseX(4); + + effects.MoveY(3); + effects.MoveFractionalNoiseY(4); + + return 0; + } +}; + +class PatternPaletteSmear : public Drawable { +public: + PatternPaletteSmear() { + name = (char *)"PaletteSmear"; + } + + unsigned int drawFrame() { + + effects.DimAll(170); effects.ShowFrame(); + + // draw a rainbow color palette + for (uint8_t y = 0; y < MATRIX_HEIGHT; y++) { + for (uint8_t x = 0; x < MATRIX_WIDTH; x++) { + effects.leds[XY(x, y)] += effects.ColorFromCurrentPalette(x * 8, y * 8 + 7); + } + } + + + // Noise + noise_x += 1000; + noise_y += 1000; + noise_scale_x = 4000; + noise_scale_y = 4000; + + effects.FillNoise(); + + effects.MoveX(3); + //effects.MoveFractionalNoiseY(4); + + effects.MoveY(3); + effects.MoveFractionalNoiseX(4); + effects.ShowFrame(); + + return 0; + } +}; + +class PatternRainbowFlag : public Drawable { +public: + PatternRainbowFlag() { + name = (char *)"RainbowFlag"; + } + + unsigned int drawFrame() { + effects.DimAll(10); effects.ShowFrame(); + + CRGB rainbow[7] = { + CRGB::Red, + CRGB::Orange, + CRGB::Yellow, + CRGB::Green, + CRGB::Blue, + CRGB::Violet + }; + + uint8_t y = 2; + + for (uint8_t c = 0; c < 6; c++) { + for (uint8_t j = 0; j < 5; j++) { + for (uint8_t x = 0; x < MATRIX_WIDTH; x++) { + effects.leds[XY(x, y)] += rainbow[c]; + } + + y++; + if (y >= MATRIX_HEIGHT) + break; + } + } + + // Noise + noise_x += 1000; + noise_y += 1000; + noise_scale_x = 4000; + noise_scale_y = 4000; + effects.FillNoise(); + + effects.MoveX(3); + effects.MoveFractionalNoiseY(4); + + effects.MoveY(3); + effects.MoveFractionalNoiseX(4); + + return 0; + } +}; +#endif diff --git a/examples/AuroraDemo/PatternPendulumWave.h b/examples/AuroraDemo/PatternPendulumWave.h new file mode 100644 index 0000000..acd83e9 --- /dev/null +++ b/examples/AuroraDemo/PatternPendulumWave.h @@ -0,0 +1,56 @@ +/* +* +* Inspired by and based on a loading animation for Prismata by Lunarch Studios: +* http://www.reddit.com/r/gifs/comments/2on8si/connecting_to_server_so_mesmerizing/cmow0sz +* +* Lunarch Studios Inc. hereby publishes the Actionscript 3 source code pasted in this +* comment under the Creative Commons CC0 1.0 Universal Public Domain Dedication. +* Lunarch Studios Inc. waives all rights to the work worldwide under copyright law, +* including all related and neighboring rights, to the extent allowed by law. +* You can copy, modify, distribute and perform the work, even for commercial purposes, +* all without asking permission. +* +* Aurora: https://github.com/pixelmatix/aurora +* Copyright (c) 2014 Jason Coon +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +* the Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef PatternPendulumWave_H +#define PatternPendulumWave_H + +class PatternPendulumWave : public Drawable { + public: + PatternPendulumWave() { + name = (char *)"Pendulum Wave"; + } + + unsigned int drawFrame() { + effects.DimAll(170); effects.ShowFrame(); + + for (int x = 0; x < MATRIX_WIDTH; x++) + { + uint8_t y = beatsin8(x + MATRIX_WIDTH, 0, MATRIX_HEIGHT); + effects.drawBackgroundFastLEDPixelCRGB(x, y, effects.ColorFromCurrentPalette(x * 7)); + } + + return 15; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternPlasma.h b/examples/AuroraDemo/PatternPlasma.h new file mode 100644 index 0000000..99500b1 --- /dev/null +++ b/examples/AuroraDemo/PatternPlasma.h @@ -0,0 +1,66 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from LedEffects Plasma by Robert Atkins: https://bitbucket.org/ratkins/ledeffects/src/26ed3c51912af6fac5f1304629c7b4ab7ac8ca4b/Plasma.cpp?at=default + * Copyright (c) 2013 Robert Atkins + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternPlasma_H +#define PatternPlasma_H + +class PatternPlasma : public Drawable { +private: + int time = 0; + int cycles = 0; + +public: + PatternPlasma() { + name = (char *)"Plasma"; + } + + unsigned int drawFrame() { + for (int x = 0; x < MATRIX_WIDTH; x++) { + for (int y = 0; y < MATRIX_HEIGHT; y++) { + int16_t v = 0; + uint8_t wibble = sin8(time); + v += sin16(x * wibble * 2 + time); + v += cos16(y * (128 - wibble) * 2 + time); + v += sin16(y * x * cos8(-time) / 2); + + effects.Pixel(x, y, (v >> 8) + 127); + } + } + + time += 1; + cycles++; + + if (cycles >= 2048) { + time = 0; + cycles = 0; + } + + effects.ShowFrame(); + + return 30; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternPulse.h b/examples/AuroraDemo/PatternPulse.h new file mode 100644 index 0000000..8992a4d --- /dev/null +++ b/examples/AuroraDemo/PatternPulse.h @@ -0,0 +1,82 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Based at least in part on someone else's work that I can no longer find. + * Please let me know if you recognize any of this code! + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternPulse_H +#define PatternPulse_H + +class PatternPulse : public Drawable { + private: + int hue; + int centerX = 0; + int centerY = 0; + int step = -1; + int maxSteps = 16; + float fadeRate = 0.8; + int diff; + + public: + PatternPulse() { + name = (char *)"Pulse"; + } + + unsigned int drawFrame() { + effects.DimAll(235); + + if (step == -1) { + centerX = random(32); + centerY = random(32); + hue = random(256); // 170; + step = 0; + } + + if (step == 0) { + matrix.drawCircle(centerX, centerY, step, effects.ColorFromCurrentPalette(hue)); + step++; + } + else { + if (step < maxSteps) { + // initial pulse + matrix.drawCircle(centerX, centerY, step, effects.ColorFromCurrentPalette(hue, pow(fadeRate, step - 2) * 255)); + + // secondary pulse + if (step > 3) { + matrix.drawCircle(centerX, centerY, step - 3, effects.ColorFromCurrentPalette(hue, pow(fadeRate, step - 2) * 255)); + } + step++; + } + else { + step = -1; + } + } + + effects.standardNoiseSmearing(); + + effects.ShowFrame(); + + return 30; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternRadar.h b/examples/AuroraDemo/PatternRadar.h new file mode 100644 index 0000000..1dc4484 --- /dev/null +++ b/examples/AuroraDemo/PatternRadar.h @@ -0,0 +1,56 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternRadar_H + +class PatternRadar : public Drawable { + private: + byte theta = 0; + byte hueoffset = 0; + + public: + PatternRadar() { + name = (char *)"Radar"; + } + + unsigned int drawFrame() { + effects.DimAll(254); effects.ShowFrame(); + + for (int offset = 0; offset < MATRIX_CENTER_X; offset++) { + byte hue = 255 - (offset * 16 + hueoffset); + CRGB color = effects.ColorFromCurrentPalette(hue); + uint8_t x = mapcos8(theta, offset, (MATRIX_WIDTH - 1) - offset); + uint8_t y = mapsin8(theta, offset, (MATRIX_HEIGHT - 1) - offset); + uint16_t xy = XY(x, y); + effects.leds[xy] = color; + + EVERY_N_MILLIS(25) { + theta += 2; + hueoffset += 1; + } + } + + return 0; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternSimplexNoise.h b/examples/AuroraDemo/PatternSimplexNoise.h new file mode 100644 index 0000000..44c3ec5 --- /dev/null +++ b/examples/AuroraDemo/PatternSimplexNoise.h @@ -0,0 +1,79 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from FastLED Fire2012 example by Mark Kriegsman: https://github.com/FastLED/FastLED/blob/master/examples/Noise/Noise.ino + * Copyright (c) 2013 FastLED + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternSimplexNoise_H +#define PatternSimplexNoise_H + +class PatternSimplexNoise : public Drawable { + public: + PatternSimplexNoise() { + name = (char *)"Noise"; + } + + void start() { + // Initialize our coordinates to some random values + noise_x = random16(); + noise_y = random16(); + noise_z = random16(); + } + + unsigned int drawFrame() { +#if FASTLED_VERSION >= 3001000 + // a new parameter set every 15 seconds + EVERY_N_SECONDS(15) { + noise_x = random16(); + noise_y = random16(); + noise_z = random16(); + } +#endif + + uint32_t speed = 100; + + effects.FillNoise(); + ShowNoiseLayer(0, 1, 0); + + // noise_x += speed; + noise_y += speed; + noise_z += speed; + + effects.ShowFrame(); + + return 0; + } + + // show just one layer + void ShowNoiseLayer(byte layer, byte colorrepeat, byte colorshift) { + for (uint8_t i = 0; i < MATRIX_WIDTH; i++) { + for (uint8_t j = 0; j < MATRIX_HEIGHT; j++) { + uint8_t pixel = noise[i][j]; + + // assign a color depending on the actual palette + effects.leds[XY(i, j)] = effects.ColorFromCurrentPalette(colorrepeat * (pixel + colorshift), pixel); + } + } + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternSnake.h b/examples/AuroraDemo/PatternSnake.h new file mode 100644 index 0000000..e25756f --- /dev/null +++ b/examples/AuroraDemo/PatternSnake.h @@ -0,0 +1,145 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from LedEffects Snake by Robert Atkins: https://bitbucket.org/ratkins/ledeffects/src/26ed3c51912af6fac5f1304629c7b4ab7ac8ca4b/Snake.cpp?at=default + * Copyright (c) 2013 Robert Atkins + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternSnake_H +#define PatternSnake_H + +class PatternSnake : public Drawable { +private: + static const byte SNAKE_LENGTH = 16; + + CRGB colors[SNAKE_LENGTH]; + uint8_t initialHue; + + enum Direction { + UP, DOWN, LEFT, RIGHT + }; + + struct Pixel { + uint8_t x; + uint8_t y; + }; + + struct Snake { + Pixel pixels[SNAKE_LENGTH]; + + Direction direction; + + void newDirection() { + switch (direction) { + case UP: + case DOWN: + direction = random(0, 2) == 1 ? RIGHT : LEFT; + break; + + case LEFT: + case RIGHT: + direction = random(0, 2) == 1 ? DOWN : UP; + + default: + break; + } + } + + void shuffleDown() { + for (byte i = SNAKE_LENGTH - 1; i > 0; i--) { + pixels[i] = pixels[i - 1]; + } + } + + void reset() { + direction = UP; + for (int i = 0; i < SNAKE_LENGTH; i++) { + pixels[i].x = 0; + pixels[i].y = 0; + } + } + + void move() { + switch (direction) { + case UP: + pixels[0].y = (pixels[0].y + 1) % MATRIX_HEIGHT; + break; + case LEFT: + pixels[0].x = (pixels[0].x + 1) % MATRIX_WIDTH; + break; + case DOWN: + pixels[0].y = pixels[0].y == 0 ? MATRIX_HEIGHT - 1 : pixels[0].y - 1; + break; + case RIGHT: + pixels[0].x = pixels[0].x == 0 ? MATRIX_WIDTH - 1 : pixels[0].x - 1; + break; + } + } + + void draw(CRGB colors[SNAKE_LENGTH]) { + for (byte i = 0; i < SNAKE_LENGTH; i++) { + effects.leds[XY(pixels[i].x, pixels[i].y)] = colors[i] %= (255 - i * (255 / SNAKE_LENGTH)); + } + } + }; + + static const int snakeCount = 6; + Snake snakes[snakeCount]; + +public: + PatternSnake() { + name = (char *)"Snake"; + for (int i = 0; i < snakeCount; i++) { + Snake* snake = &snakes[i]; + snake->reset(); + } + } + + void start() + { + effects.ClearFrame(); + } + + unsigned int drawFrame() { + + + fill_palette(colors, SNAKE_LENGTH, initialHue++, 5, effects.currentPalette, 255, LINEARBLEND); + + for (int i = 0; i < snakeCount; i++) { + Snake* snake = &snakes[i]; + + snake->shuffleDown(); + + if (random(10) > 7) { + snake->newDirection(); + } + + snake->move(); + snake->draw(colors); + } + + effects.ShowFrame(); + + return 30; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternSpark.h b/examples/AuroraDemo/PatternSpark.h new file mode 100644 index 0000000..74f3b16 --- /dev/null +++ b/examples/AuroraDemo/PatternSpark.h @@ -0,0 +1,113 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Portions of this code are adapted from FastLED Fire2012 example by Mark Kriegsman: https://github.com/FastLED/FastLED/tree/master/examples/Fire2012WithPalette + * Copyright (c) 2013 FastLED + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternSpark_H +#define PatternSpark_H + +class PatternSpark : public Drawable { + private: + + public: + PatternSpark() { + name = (char *)"Spark"; + } + + // There are two main parameters you can play with to control the look and + // feel of your fire: COOLING (used in step 1 above), and SPARKING (used + // in step 3 above). + // + // COOLING: How much does the air cool as it rises? + // Less cooling = taller flames. More cooling = shorter flames. + // Default 55, suggested range 20-100 + uint8_t cooling = 100; + + // SPARKING: What chance (out of 255) is there that a new spark will be lit? + // Higher chance = more roaring fire. Lower chance = more flickery fire. + // Default 120, suggested range 50-200. + uint8_t sparking = 50; + + unsigned int drawFrame() { + // Add entropy to random number generator; we use a lot of it. + random16_add_entropy( random16()); + + effects.DimAll(235); effects.ShowFrame(); + + for (uint8_t x = 0; x < MATRIX_WIDTH; x++) { + // Step 1. Cool down every cell a little + for (int y = 0; y < MATRIX_HEIGHT; y++) { + int xy = XY(x, y); + heat[xy] = qsub8(heat[xy], random8(0, ((cooling * 10) / MATRIX_HEIGHT) + 2)); + } + + // Step 2. Heat from each cell drifts 'up' and diffuses a little + for (int y = 0; y < MATRIX_HEIGHT; y++) { + heat[XY(x, y)] = (heat[XY(x, y + 1)] + heat[XY(x, y + 2)] + heat[XY(x, y + 2)]) / 3; + } + + // Step 2. Randomly ignite new 'sparks' of heat + if (random8() < sparking) { + uint8_t xt = random8(MATRIX_CENTRE_X - 2, MATRIX_CENTER_X + 3); + + int xy = XY(xt, MATRIX_HEIGHT - 1); + heat[xy] = qadd8(heat[xy], random8(160, 255)); + } + + // Step 4. Map from heat cells to LED colors + for (int y = 0; y < MATRIX_HEIGHT; y++) { + int xy = XY(x, y); + byte colorIndex = heat[xy]; + + // Recommend that you use values 0-240 rather than + // the usual 0-255, as the last 15 colors will be + // 'wrapping around' from the hot end to the cold end, + // which looks wrong. + colorIndex = scale8(colorIndex, 240); + + // override color 0 to ensure a black background? + if (colorIndex != 0) + // effects.leds[xy] = CRGB::Black; + // else + effects.leds[xy] = effects.ColorFromCurrentPalette(colorIndex); + } + } + + // Noise + noise_x += 1000; + noise_y += 1000; + noise_z += 1000; + noise_scale_x = 4000; + noise_scale_y = 4000; + effects.FillNoise(); + + effects.MoveX(3); + effects.MoveFractionalNoiseX(4); + + effects.ShowFrame(); + + return 15; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternSpin.h b/examples/AuroraDemo/PatternSpin.h new file mode 100644 index 0000000..c3497e7 --- /dev/null +++ b/examples/AuroraDemo/PatternSpin.h @@ -0,0 +1,100 @@ +/* +* Aurora: https://github.com/pixelmatix/aurora +* Copyright (c) 2014 Jason Coon +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +* the Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef PatternSpin_H + + + +class PatternSpin : public Drawable { +public: + PatternSpin() { + name = (char *)"Spin"; + } + + float degrees = 0; + float radius = 16; + + float speedStart = 1; + float velocityStart = 0.6; + + float maxSpeed = 30; + + float speed = speedStart; + float velocity = velocityStart; + + void start() { + speed = speedStart; + velocity = velocityStart; + degrees = 0; + } + + unsigned int drawFrame() { + effects.DimAll(190); effects.ShowFrame(); + + CRGB color = effects.ColorFromCurrentPalette(speed * 8); + + // start position + int x; + int y; + + // target position + float targetDegrees = degrees + speed; + float targetRadians = radians(targetDegrees); + int targetX = (int) (MATRIX_CENTER_X + radius * cos(targetRadians)); + int targetY = (int) (MATRIX_CENTER_Y - radius * sin(targetRadians)); + + float tempDegrees = degrees; + + do{ + float radians = radians(tempDegrees); + x = (int) (MATRIX_CENTER_X + radius * cos(radians)); + y = (int) (MATRIX_CENTER_Y - radius * sin(radians)); + + effects.drawBackgroundFastLEDPixelCRGB(x, y, color); + effects.drawBackgroundFastLEDPixelCRGB(y, x, color); + + tempDegrees += 1; + if (tempDegrees >= 360) + tempDegrees = 0; + } while (x != targetX || y != targetY); + + degrees += speed; + + // add velocity to the particle each pass around the accelerator + if (degrees >= 360) { + degrees = 0; + speed += velocity; + if (speed <= speedStart) { + speed = speedStart; + velocity *= -1; + } + else if (speed > maxSpeed){ + speed = maxSpeed - velocity; + velocity *= -1; + } + } + + return 0; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternSpiral.h b/examples/AuroraDemo/PatternSpiral.h new file mode 100644 index 0000000..4971ca2 --- /dev/null +++ b/examples/AuroraDemo/PatternSpiral.h @@ -0,0 +1,138 @@ +/* + * Portions of this code are adapted from "Funky Clouds" by Stefan Petrick: + * https://gist.github.com/anonymous/876f908333cd95315c35 + * + * Copyright (c) 2014 Stefan Petrick + * http://www.stefan-petrick.de/wordpress_beta + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternSpiral_H +#define PatternSpiral_H + +class PatternSpiral : public Drawable { +private: + // Timer stuff (Oszillators) + struct timer { + unsigned long takt; + unsigned long lastMillis; + unsigned long count; + int delta; + byte up; + byte down; + }; + timer multiTimer[5]; + + int timers = sizeof(multiTimer) / sizeof(multiTimer[0]); + + // counts all variables with different speeds linear up and down + void UpdateTimers() + { + unsigned long now = millis(); + for (int i = 0; i < timers; i++) + { + while (now - multiTimer[i].lastMillis >= multiTimer[i].takt) + { + multiTimer[i].lastMillis += multiTimer[i].takt; + multiTimer[i].count = multiTimer[i].count + multiTimer[i].delta; + if ((multiTimer[i].count == multiTimer[i].up) || (multiTimer[i].count == multiTimer[i].down)) + { + multiTimer[i].delta = -multiTimer[i].delta; + } + } + } + } + +public: + PatternSpiral() { + name = (char *)"Spiral"; + } + + void start() { + // set all counting directions positive for the beginning + for (int i = 0; i < timers; i++) multiTimer[i].delta = 1; + + // set range (up/down), speed (takt=ms between steps) and starting point of all oszillators + + unsigned long now = millis(); + + multiTimer[0].lastMillis = now; + multiTimer[0].takt = 42; //x1 + multiTimer[0].up = MATRIX_WIDTH - 1; + multiTimer[0].down = 0; + multiTimer[0].count = 0; + + multiTimer[1].lastMillis = now; + multiTimer[1].takt = 55; //y1 + multiTimer[1].up = MATRIX_HEIGHT - 1; + multiTimer[1].down = 0; + multiTimer[1].count = 0; + + multiTimer[2].lastMillis = now; + multiTimer[2].takt = 3; //color + multiTimer[2].up = 255; + multiTimer[2].down = 0; + multiTimer[2].count = 0; + + multiTimer[3].lastMillis = now; + multiTimer[3].takt = 71; //x2 + multiTimer[3].up = MATRIX_WIDTH - 1; + multiTimer[3].down = 0; + multiTimer[3].count = 0; + + multiTimer[4].lastMillis = now; + multiTimer[4].takt = 89; //y2 + multiTimer[4].up = MATRIX_HEIGHT - 1; + multiTimer[4].down = 0; + multiTimer[4].count = 0; + } + + unsigned int drawFrame() { + // manage the Oszillators + UpdateTimers(); + + // draw just a line defined by 5 oszillators + effects.BresenhamLine( + multiTimer[3].count, // x1 + multiTimer[4].count, // y1 + multiTimer[0].count, // x2 + multiTimer[1].count, // y2 + multiTimer[2].count); // color + + // manipulate the screen buffer + // with fixed parameters (could be oszillators too) + // Params: center x, y, radius, scale color down + // --> NOTE: Affects always a SQUARE with an odd length + // effects.SpiralStream(15, 15, 10, 128); + + effects.SpiralStream(31, 15, 64, 128); // for 64 pixel wide matrix! + // effects.SpiralStream(47, 15, 10, 128); // for 64 pixel wide matrix! + + // why not several times?! + // effects.SpiralStream(16, 6, 6, 128); + // effects.SpiralStream(10, 24, 10, 128); + + // increase the contrast + effects.DimAll(250); effects.ShowFrame(); + + return 0; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternSpiro.h b/examples/AuroraDemo/PatternSpiro.h new file mode 100644 index 0000000..488a729 --- /dev/null +++ b/examples/AuroraDemo/PatternSpiro.h @@ -0,0 +1,107 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternSpiro_H + +class PatternSpiro : public Drawable { + private: + byte theta1 = 0; + byte theta2 = 0; + byte hueoffset = 0; + + uint8_t radiusx = MATRIX_WIDTH / 4; + uint8_t radiusy = MATRIX_HEIGHT / 4; + uint8_t minx = MATRIX_CENTER_X - radiusx; + uint8_t maxx = MATRIX_CENTER_X + radiusx + 1; + uint8_t miny = MATRIX_CENTER_Y - radiusy; + uint8_t maxy = MATRIX_CENTER_Y + radiusy + 1; + + uint8_t spirocount = 1; + uint8_t spirooffset = 256 / spirocount; + boolean spiroincrement = false; + + boolean handledChange = false; + + public: + PatternSpiro() { + name = (char *)"Spiro"; + } + + unsigned int drawFrame() { + effects.DimAll(254); effects.ShowFrame(); + + boolean change = false; + + for (int i = 0; i < spirocount; i++) { + uint8_t x = mapsin8(theta1 + i * spirooffset, minx, maxx); + uint8_t y = mapcos8(theta1 + i * spirooffset, miny, maxy); + + uint8_t x2 = mapsin8(theta2 + i * spirooffset, x - radiusx, x + radiusx); + uint8_t y2 = mapcos8(theta2 + i * spirooffset, y - radiusy, y + radiusy); + + CRGB color = effects.ColorFromCurrentPalette(hueoffset + i * spirooffset, 128); + effects.leds[XY(x2, y2)] += color; + + if((x2 == MATRIX_CENTER_X && y2 == MATRIX_CENTER_Y) || + (x2 == MATRIX_CENTRE_X && y2 == MATRIX_CENTRE_Y)) change = true; + } + + theta2 += 1; + + EVERY_N_MILLIS(25) { + theta1 += 1; + } + + EVERY_N_MILLIS(100) { + if (change && !handledChange) { + handledChange = true; + + if (spirocount >= MATRIX_WIDTH || spirocount == 1) spiroincrement = !spiroincrement; + + if (spiroincrement) { + if(spirocount >= 4) + spirocount *= 2; + else + spirocount += 1; + } + else { + if(spirocount > 4) + spirocount /= 2; + else + spirocount -= 1; + } + + spirooffset = 256 / spirocount; + } + + if(!change) handledChange = false; + } + + EVERY_N_MILLIS(33) { + hueoffset += 1; + } + + return 0; + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternSwirl.h b/examples/AuroraDemo/PatternSwirl.h new file mode 100644 index 0000000..8ae8eb1 --- /dev/null +++ b/examples/AuroraDemo/PatternSwirl.h @@ -0,0 +1,77 @@ +/* +* Aurora: https://github.com/pixelmatix/aurora +* Copyright (c) 2014 Jason Coon +* +* Portions of this code are adapted from SmartMatrixSwirl by Mark Kriegsman: https://gist.github.com/kriegsman/5adca44e14ad025e6d3b +* https://www.youtube.com/watch?v=bsGBT-50cts +* Copyright (c) 2014 Mark Kriegsman +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +* the Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef PatternSwirl_H + +class PatternSwirl : public Drawable { + private: + const uint8_t borderWidth = 2; + + public: + PatternSwirl() { + name = (char *)"Swirl"; + } + + void start() { + } + + unsigned int drawFrame() { + // Apply some blurring to whatever's already on the matrix + // Note that we never actually clear the matrix, we just constantly + // blur it repeatedly. Since the blurring is 'lossy', there's + // an automatic trend toward black -- by design. + uint8_t blurAmount = beatsin8(2, 10, 255); + +#if FASTLED_VERSION >= 3001000 + blur2d(effects.leds, MATRIX_WIDTH, MATRIX_HEIGHT, blurAmount); +#else + effects.DimAll(blurAmount); +#endif + + // Use two out-of-sync sine waves + uint8_t i = beatsin8(27, borderWidth, MATRIX_HEIGHT - borderWidth); + uint8_t j = beatsin8(41, borderWidth, MATRIX_WIDTH - borderWidth); + // Also calculate some reflections + uint8_t ni = (MATRIX_WIDTH - 1) - i; + uint8_t nj = (MATRIX_WIDTH - 1) - j; + + // The color of each point shifts over time, each at a different speed. + uint16_t ms = millis(); + effects.leds[XY(i, j)] += effects.ColorFromCurrentPalette(ms / 11); + effects.leds[XY(j, i)] += effects.ColorFromCurrentPalette(ms / 13); + effects.leds[XY(ni, nj)] += effects.ColorFromCurrentPalette(ms / 17); + effects.leds[XY(nj, ni)] += effects.ColorFromCurrentPalette(ms / 29); + effects.leds[XY(i, nj)] += effects.ColorFromCurrentPalette(ms / 37); + effects.leds[XY(ni, j)] += effects.ColorFromCurrentPalette(ms / 41); + + + effects.ShowFrame(); + return 0; + + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternTest.h b/examples/AuroraDemo/PatternTest.h new file mode 100644 index 0000000..490e1a2 --- /dev/null +++ b/examples/AuroraDemo/PatternTest.h @@ -0,0 +1,20 @@ + +#ifndef PatternTest_H +#define PatternTest_H + +class PatternTest : public Drawable { + private: + + public: + PatternTest() { + name = (char *)"Test Pattern"; + } + + unsigned int drawFrame() { + + matrix.fillScreen(matrix.color565(128, 0, 0)); + + } +}; + +#endif diff --git a/examples/AuroraDemo/PatternWave.h b/examples/AuroraDemo/PatternWave.h new file mode 100644 index 0000000..8246a5f --- /dev/null +++ b/examples/AuroraDemo/PatternWave.h @@ -0,0 +1,120 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PatternWave_H +#define PatternWave_H + +class PatternWave : public Drawable { +private: + byte thetaUpdate = 0; + byte thetaUpdateFrequency = 0; + byte theta = 0; + + byte hueUpdate = 0; + byte hueUpdateFrequency = 0; + byte hue = 0; + + byte rotation = 0; + + uint8_t scale = 256 / MATRIX_WIDTH; + + uint8_t maxX = MATRIX_WIDTH - 1; + uint8_t maxY = MATRIX_HEIGHT - 1; + + uint8_t waveCount = 1; + +public: + PatternWave() { + name = (char *)"Wave"; + } + + void start() { + rotation = random(0, 4); + waveCount = random(1, 3); + + } + + unsigned int drawFrame() { + int n = 0; + + switch (rotation) { + case 0: + for (int x = 0; x < MATRIX_WIDTH; x++) { + n = quadwave8(x * 2 + theta) / scale; + effects.drawBackgroundFastLEDPixelCRGB(x, n, effects.ColorFromCurrentPalette(x + hue)); + if (waveCount == 2) + effects.drawBackgroundFastLEDPixelCRGB(x, maxY - n, effects.ColorFromCurrentPalette(x + hue)); + } + break; + + case 1: + for (int y = 0; y < MATRIX_HEIGHT; y++) { + n = quadwave8(y * 2 + theta) / scale; + effects.drawBackgroundFastLEDPixelCRGB(n, y, effects.ColorFromCurrentPalette(y + hue)); + if (waveCount == 2) + effects.drawBackgroundFastLEDPixelCRGB(maxX - n, y, effects.ColorFromCurrentPalette(y + hue)); + } + break; + + case 2: + for (int x = 0; x < MATRIX_WIDTH; x++) { + n = quadwave8(x * 2 - theta) / scale; + effects.drawBackgroundFastLEDPixelCRGB(x, n, effects.ColorFromCurrentPalette(x + hue)); + if (waveCount == 2) + effects.drawBackgroundFastLEDPixelCRGB(x, maxY - n, effects.ColorFromCurrentPalette(x + hue)); + } + break; + + case 3: + for (int y = 0; y < MATRIX_HEIGHT; y++) { + n = quadwave8(y * 2 - theta) / scale; + effects.drawBackgroundFastLEDPixelCRGB(n, y, effects.ColorFromCurrentPalette(y + hue)); + if (waveCount == 2) + effects.drawBackgroundFastLEDPixelCRGB(maxX - n, y, effects.ColorFromCurrentPalette(y + hue)); + } + break; + } + + effects.DimAll(254); + effects.ShowFrame(); + + if (thetaUpdate >= thetaUpdateFrequency) { + thetaUpdate = 0; + theta++; + } + else { + thetaUpdate++; + } + + if (hueUpdate >= hueUpdateFrequency) { + hueUpdate = 0; + hue++; + } + else { + hueUpdate++; + } + + return 0; + } +}; + +#endif diff --git a/examples/AuroraDemo/Patterns.h b/examples/AuroraDemo/Patterns.h new file mode 100644 index 0000000..419b546 --- /dev/null +++ b/examples/AuroraDemo/Patterns.h @@ -0,0 +1,298 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef Patterns_H +#define Patterns_H + +#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0])) + +#include "Vector.h" +#include "Boid.h" +#include "Attractor.h" + +/* + * Note from mrfaptastic: + * + * Commented out patterns are due to the fact they either didn't work properly with a non-square display, + * or from my personal opinion, are crap. + */ + +#include "PatternTest.h" +//#include "PatternNoiseSmearing.h" // Doesn't seem to work, omitting. +#include "PatternSpiro.h" +#include "PatternRadar.h" +#include "PatternSwirl.h" +#include "PatternPendulumWave.h" +#include "PatternFlowField.h" +#include "PatternIncrementalDrift.h" +//#include "PatternIncrementalDrift2.h" // Doesn't seem to work, omitting. +#include "PatternMunch.h" +#include "PatternElectricMandala.h" +//#include "PatternSpin.h" // Doesn't seem to work, omitting. +#include "PatternSimplexNoise.h" +#include "PatternWave.h" +#include "PatternAttract.h" +//#include "PatternBounce.h" // Doesn't seem to work, omitting. +#include "PatternFlock.h" +#include "PatternInfinity.h" +#include "PatternPlasma.h" +#include "PatternSnake.h" +//#include "PatternInvaders.h" // Doesn't seem to work, omitting. +//#include "PatternCube.h" // Doesn't seem to work, omitting. +//#include "PatternFire.h" // Doesn't seem to work, omitting. +#include "PatternLife.h" +#include "PatternMaze.h" +//#include "PatternPulse.h" // Doesn't seem to work, omitting. +//#include "PatternSpark.h" // Doesn't seem to work, omitting. +#include "PatternSpiral.h" + +class Patterns : public Playlist { + private: + PatternTest patternTest; + // PatternRainbowFlag rainbowFlag; // doesn't work + // PatternPaletteSmear paletteSmear; + // PatternMultipleStream multipleStream; // doesn't work + // PatternMultipleStream2 multipleStream2; // doesn't work + // PatternMultipleStream3 multipleStream3; // doesn't work + // PatternMultipleStream4 multipleStream4; // doesn't work + // PatternMultipleStream5 multipleStream5; // doesn't work + // PatternMultipleStream8 multipleStream8; // doesn't work + PatternSpiro spiro; + // PatternRadar radar; + PatternSwirl swirl; + PatternPendulumWave pendulumWave; + PatternFlowField flowField; + PatternIncrementalDrift incrementalDrift; + // PatternIncrementalDrift2 incrementalDrift2; + PatternMunch munch; + PatternElectricMandala electricMandala; + // PatternSpin spin; + PatternSimplexNoise simplexNoise; + PatternWave wave; + PatternAttract attract; + // PatternBounce bounce; + PatternFlock flock; + PatternInfinity infinity; + PatternPlasma plasma; + // PatternInvadersSmall invadersSmall; + // PatternInvadersMedium invadersMedium; + // PatternInvadersLarge invadersLarge; + PatternSnake snake; + // PatternCube cube; + // PatternFire fire; + PatternLife life; + PatternMaze maze; + // PatternPulse pulse; + // PatternSpark spark; + PatternSpiral spiral; + + int currentIndex = 0; + Drawable* currentItem; + + int getCurrentIndex() { + return currentIndex; + } + + //const static int PATTERN_COUNT = 37; + + const static int PATTERN_COUNT = 17; + + Drawable* shuffledItems[PATTERN_COUNT]; + + Drawable* items[PATTERN_COUNT] = { + // &patternTest, // ok + &spiro, // cool + // &paletteSmear, // fail + // &multipleStream, // fail + // &multipleStream8,// fail + // &multipleStream5,// fail + // &multipleStream3,// fail + // &radar, // fail + // &multipleStream4, // fail + // &multipleStream2, // fail + &life, // ok + &flowField, + &pendulumWave, //11 ok + &incrementalDrift, //12 ok + // &incrementalDrift2, // 13 fail + &munch, // 14 ok + &electricMandala, // 15 ok + // &spin, // 16 ok but repeditivev + &simplexNoise, // 17 - cool! + &wave, // 18 ok + // &rainbowFlag, //20 // fail + &attract, // 21 ok + &swirl, // 22 + // &bounce, // boncing line crap + &flock, // works + &infinity, // works + &plasma, // works + // &invadersSmall, // works ish + // &invadersMedium, // fail + // &invadersLarge, // fail + &snake, // ok + // &cube, // works ish + // &fire, // ok ish + &maze, // ok + // &pulse,// fail + // &spark, // same as fire + &spiral, // ok + }; + + public: + Patterns() { + // add the items to the shuffledItems array + for (int a = 0; a < PATTERN_COUNT; a++) { + shuffledItems[a] = items[a]; + } + + shuffleItems(); + + this->currentItem = items[0]; + this->currentItem->start(); + } + + char* Drawable::name = (char *)"Patterns"; + + void stop() { + if (currentItem) + currentItem->stop(); + } + + void start() { + if (currentItem) + currentItem->start(); + } + + void move(int step) { + currentIndex += step; + + if (currentIndex >= PATTERN_COUNT) currentIndex = 0; + else if (currentIndex < 0) currentIndex = PATTERN_COUNT - 1; + + if (effects.paletteIndex == effects.RandomPaletteIndex) + effects.RandomPalette(); + + moveTo(currentIndex); + + //if (!isTimeAvailable && currentItem == &analogClock) + // move(step); + } + + void moveRandom(int step) { + currentIndex += step; + + if (currentIndex >= PATTERN_COUNT) currentIndex = 0; + else if (currentIndex < 0) currentIndex = PATTERN_COUNT - 1; + + if (effects.paletteIndex == effects.RandomPaletteIndex) + effects.RandomPalette(); + + if (currentItem) + currentItem->stop(); + + currentItem = shuffledItems[currentIndex]; + + if (currentItem) + currentItem->start(); + + // if (!isTimeAvailable && currentItem == &analogClock) + // moveRandom(step); + } + + void shuffleItems() { + for (int a = 0; a < PATTERN_COUNT; a++) + { + int r = random(a, PATTERN_COUNT); + Drawable* temp = shuffledItems[a]; + shuffledItems[a] = shuffledItems[r]; + shuffledItems[r] = temp; + } + } + + + unsigned int drawFrame() { + return currentItem->drawFrame(); + } + + void listPatterns() { + Serial.println(F("{")); + Serial.print(F(" \"count\": ")); + Serial.print(PATTERN_COUNT); + Serial.println(","); + Serial.println(F(" \"results\": [")); + + for (int i = 0; i < PATTERN_COUNT; i++) { + Serial.print(F(" \"")); + Serial.print(i, DEC); + Serial.print(F(": ")); + Serial.print(items[i]->name); + if (i == PATTERN_COUNT - 1) + Serial.println(F("\"")); + else + Serial.println(F("\",")); + } + + Serial.println(" ]"); + Serial.println("}"); + } + + char * getCurrentPatternName() + { + return currentItem->name; + } + + void moveTo(int index) { + if (currentItem) + currentItem->stop(); + + currentIndex = index; + + currentItem = items[currentIndex]; + + if (currentItem) + currentItem->start(); + } + + bool setPattern(String name) { + for (int i = 0; i < PATTERN_COUNT; i++) { + if (name.compareTo(items[i]->name) == 0) { + moveTo(i); + return true; + } + } + + return false; + } + + + bool setPattern(int index) { + if (index >= PATTERN_COUNT || index < 0) + return false; + + moveTo(index); + + return true; + } +}; + +#endif diff --git a/examples/AuroraDemo/Playlist.h b/examples/AuroraDemo/Playlist.h new file mode 100644 index 0000000..29c0c87 --- /dev/null +++ b/examples/AuroraDemo/Playlist.h @@ -0,0 +1,39 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef Playlist_H +#define Playlist_H + +class Playlist : public Drawable { +public: + virtual bool isPlaylist() { + return true; + } + + boolean isCurrentItemFinished = true; + + virtual void move(int step) = 0; + virtual void moveRandom(int step) = 0; + virtual int getCurrentIndex(); +}; + +#endif diff --git a/examples/AuroraDemo/README.md b/examples/AuroraDemo/README.md new file mode 100644 index 0000000..2344367 --- /dev/null +++ b/examples/AuroraDemo/README.md @@ -0,0 +1,6 @@ +A port of Aurora visualisations +====== + +Not all of the visualisations have been ported. About 17 of 37 work, or have been included as I think they look best. + +Original source: https://github.com/pixelmatix/aurora
\ No newline at end of file diff --git a/examples/AuroraDemo/Vector.h b/examples/AuroraDemo/Vector.h new file mode 100644 index 0000000..8acbadc --- /dev/null +++ b/examples/AuroraDemo/Vector.h @@ -0,0 +1,169 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef Vector_H +#define Vector_H + +template <class T> +class Vector2 { +public: + T x, y; + + Vector2() :x(0), y(0) {} + Vector2(T x, T y) : x(x), y(y) {} + Vector2(const Vector2& v) : x(v.x), y(v.y) {} + + Vector2& operator=(const Vector2& v) { + x = v.x; + y = v.y; + return *this; + } + + bool isEmpty() { + return x == 0 && y == 0; + } + + bool operator==(Vector2& v) { + return x == v.x && y == v.y; + } + + bool operator!=(Vector2& v) { + return !(x == y); + } + + Vector2 operator+(Vector2& v) { + return Vector2(x + v.x, y + v.y); + } + Vector2 operator-(Vector2& v) { + return Vector2(x - v.x, y - v.y); + } + + Vector2& operator+=(Vector2& v) { + x += v.x; + y += v.y; + return *this; + } + Vector2& operator-=(Vector2& v) { + x -= v.x; + y -= v.y; + return *this; + } + + Vector2 operator+(double s) { + return Vector2(x + s, y + s); + } + Vector2 operator-(double s) { + return Vector2(x - s, y - s); + } + Vector2 operator*(double s) { + return Vector2(x * s, y * s); + } + Vector2 operator/(double s) { + return Vector2(x / s, y / s); + } + + Vector2& operator+=(double s) { + x += s; + y += s; + return *this; + } + Vector2& operator-=(double s) { + x -= s; + y -= s; + return *this; + } + Vector2& operator*=(double s) { + x *= s; + y *= s; + return *this; + } + Vector2& operator/=(double s) { + x /= s; + y /= s; + return *this; + } + + void set(T x, T y) { + this->x = x; + this->y = y; + } + + void rotate(double deg) { + double theta = deg / 180.0 * M_PI; + double c = cos(theta); + double s = sin(theta); + double tx = x * c - y * s; + double ty = x * s + y * c; + x = tx; + y = ty; + } + + Vector2& normalize() { + if (length() == 0) return *this; + *this *= (1.0 / length()); + return *this; + } + + float dist(Vector2 v) const { + Vector2 d(v.x - x, v.y - y); + return d.length(); + } + float length() const { + return sqrt(x * x + y * y); + } + + float mag() const { + return length(); + } + + float magSq() { + return (x * x + y * y); + } + + void truncate(double length) { + double angle = atan2f(y, x); + x = length * cos(angle); + y = length * sin(angle); + } + + Vector2 ortho() const { + return Vector2(y, -x); + } + + static float dot(Vector2 v1, Vector2 v2) { + return v1.x * v2.x + v1.y * v2.y; + } + static float cross(Vector2 v1, Vector2 v2) { + return (v1.x * v2.y) - (v1.y * v2.x); + } + + void limit(float max) { + if (magSq() > max*max) { + normalize(); + *this *= max; + } + } +}; + +typedef Vector2<float> PVector; + +#endif |
