From 66dcf910bd4744d8ced56cb9586aa937a1a2d4c5 Mon Sep 17 00:00:00 2001 From: vg Date: Tue, 7 Jul 2020 16:24:01 +0200 Subject: first commit --- cube_gl/effect.cpp | 776 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 776 insertions(+) create mode 100644 cube_gl/effect.cpp (limited to 'cube_gl/effect.cpp') diff --git a/cube_gl/effect.cpp b/cube_gl/effect.cpp new file mode 100644 index 0000000..4288fa0 --- /dev/null +++ b/cube_gl/effect.cpp @@ -0,0 +1,776 @@ + +#include "effect.h" +#include "font.h" +#include +#include +#include + +#define CUBE_SIZE 8 +#define CUBE_BYTES CUBE_SIZE*CUBE_SIZE +#define AXIS_Z 2 +#define AXIS_Y 1 +#define AXIS_X 0 + +unsigned char leds[8][8]; +volatile bool led_change = false; + +//unsigned char pow2[8] = { 1, 2, 4, 8, 16, 32, 64, 128 }; +//const unsigned char pow2[8] = {128, 64, 32, 16, 8, 4, 2, 1}; + +/***************************************************************************** + * ACCESSORS + *****************************************************************************/ + +unsigned char inrange(int x, int y, int z) +{ + if (x >= 0 && x < CUBE_SIZE && y >= 0 && y < CUBE_SIZE && z >= 0 && z < CUBE_SIZE) + { + return 1; + } else + { + // One of the coordinates was outside the cube. + return 0; + } +} + +bool get_led(unsigned char x, unsigned char y, unsigned char z) +{ + /* + assert(x >= 0 && x <= 7); + assert(y >= 0 && y <= 7); + assert(z >= 0 && z <= 7); + */ + + if (inrange(x, y, z)) { + return leds[y][z] & (1 << x); + } + + return false; +} + +void set_led(unsigned char x, unsigned char y, unsigned char z, bool on) +{ + + if (!inrange(x, y, z)) { + return; + } + + /* + assert(x >= 0 && x <= 7); + assert(y >= 0 && y <= 7); + assert(z >= 0 && z <= 7); + */ + + if (on) { + leds[y][z] |= ((unsigned char)1) << x; + } + else { + leds[y][z] &= ~(((unsigned char)1) << x); + } +} + +void clear_led() +{ + memset(leds, 0, sizeof(leds)); +} + +void set_voxel(int x, int y, int z) +{ + set_led(x, y, z, true); +} + +void clr_voxel(int x, int y, int z) +{ + set_led(x, y, z, false); +} + +void fill(char val) +{ + memset(leds, val, sizeof(leds)); +} + +void delay(unsigned t) +{ + led_change = true; + SDL_Delay(t); +} + +/***************************************************************************** + * EFFECTS + *****************************************************************************/ + +void test_effect() +{ + static int active_layer = 0; + + for (int k = 0; k < 8; ++k) { + //std::cout << "boo" << std::endl; + for (int j = 0; j < 8; ++j) { + //std::cout << "boo2" << std::endl; + if (k == active_layer) { + //std::cerr << "active" << std::endl; + leds[j][k] = 0xFF; + } + else leds[j][k] = 0; + } + } + ++active_layer; + if (active_layer >= 8) { + active_layer = 0; + } +} + + +void sendvoxels_z(int x, int y, int z, int delay) +{ + assert(z == 0 || z == 7); + + if (z == 7) { + for (int i = 0; i < 7; ++i) { + set_led(x, y, i, false); + set_led(x, y, i+1, true); + led_change = true; + SDL_Delay(delay); + } + } + else { + for(int i = 6; i >= 0; --i) { + set_led(x, y, i + 1, false); + set_led(x, y, i, true); + led_change = true; + SDL_Delay(delay); + } + } +} + + +void sendvoxels_random_z_effect(int maxiters, + int delay, /* speed of movement */ + int wait) /* delay between 2 movement */ +{ + clear_led(); // clear the cube + for (int j = 0; j < 8; ++j) { + for (int i = 0; i < 8; ++i) { + if (rand()%2) { + set_led(i, j, 0, true); + } + else { + set_led(i, j, 7, true); + } + } + } + + int previous_x = 0, previous_y = 0; + for (int n = 0; n < maxiters ; ++n ) { + int x = rand()%8, y = rand()%8; + + if (previous_x == x && previous_y == y) { + --n; + continue; + } + + if (get_led(x, y, 0)) { + sendvoxels_z(x, y, 7, delay); + } + else if (get_led(x, y, 7)) { + sendvoxels_z(x, y, 0, delay); + } + SDL_Delay(wait); + } + +} + +void rain_effect(int iterations) +{ + + for (int i = 0; i < iterations ; ++i) { + + // clear layer 7 + for (int j = 0 ; j < 8; ++j) { + leds[j][7] = 0; + } + + // place pixels at random x and y coord at layer 7 + int n = rand()%4; + for (int i2 = 0; i2 < n; ++i2) { + set_led(rand()%8, rand()%8, 7, 1); + } + + led_change = true; + SDL_Delay(90); + + // shift down + for (int k = 0; k < 7; ++k) { + for (int j = 0 ; j < 8; ++j) { + leds[j][k] = leds[j][k+1]; + } + } + } +} + +void set_plane(int axis, unsigned char index, bool on = true) +{ + switch(axis) { + case 0: // X + for (int k = 0; k < 8; ++k) { + for (int j = 0; j < 8; ++j) { + set_led(index, j, k, on); + } + } + break; + case 1: // Y + for (int k = 0; k < 8; ++k) { + for (int i = 0; i < 8; ++i) { + set_led(i, index, k, on); + } + } + break; + case 2: // Z + for (int j = 0; j < 8; ++j) { + for (int i = 0; i < 8; ++i) { + set_led(i, j, index, on); + } + } + break; + default: + assert(false); + } +} + +void planboing(int plane, int speed) +{ + for (int i = 0; i < 8; ++i) { + clear_led(); // clear cube + set_plane(plane, i); + led_change = true; + SDL_Delay(speed); + } + for (int i = 7; i >= 0; --i) { + clear_led(); // clear cube + set_plane(plane, i); + led_change = true; + SDL_Delay(speed); + } +} + +// Shift the entire contents of the cube along an axis +// This is great for effects where you want to draw something +// on one side of the cube and have it flow towards the other +// side. Like rain flowing down the Z axiz. +void shift (char axis, int direction) +{ + int i, x ,y; + int ii, iii; + //int state; + + for (i = 0; i < CUBE_SIZE; i++) { + if (direction == -1) { + ii = i; + } + else { + ii = (7-i); + } + + + for (x = 0; x < CUBE_SIZE; x++) + { + for (y = 0; y < CUBE_SIZE; y++) + { + if (direction == -1) + { + iii = ii+1; + } else + { + iii = ii-1; + } + + if (axis == 2) + { + set_led(x, y, ii, get_led(x, y, iii)); + //state = get_led(x,y,iii); + //set_led(x,y,ii,state?false:true); + } + + if (axis == 1) + { + set_led(x, ii, y, get_led(x, iii, y)); + //state = get_led(x,iii,y); + //altervoxel(x,ii,y,state); + //set_led(x,ii,y,state?false:true); + } + + if (axis == 0) + { + set_led(ii, y, x, get_led(iii, y, x)); + //state = get_led(iii,y,x); + //set_led(ii,y,x,state?false:true); + } + } + } + } + + if (direction == -1) { + i = 7; + } + else { + i = 0; + } + + /* + for (x = 0; x < CUBE_SIZE; x++) { + for (y = 0; y < CUBE_SIZE; y++) { + if (axis == AXIS_Z) set_led(x,y,i, false); + if (axis == AXIS_Y) set_led(x,i,y, false); + if (axis == AXIS_X) set_led(i,y,x, false); + } + } + + */ + set_plane(axis, i, false); +} + + +// Flips a byte 180 degrees. +// MSB becomes LSB, LSB becomes MSB. +char flipbyte (char byte) +{ + char flop = 0x00; + + flop = (flop & 0b11111110) | (0b00000001 & (byte >> 7)); + flop = (flop & 0b11111101) | (0b00000010 & (byte >> 5)); + flop = (flop & 0b11111011) | (0b00000100 & (byte >> 3)); + flop = (flop & 0b11110111) | (0b00001000 & (byte >> 1)); + flop = (flop & 0b11101111) | (0b00010000 & (byte << 1)); + flop = (flop & 0b11011111) | (0b00100000 & (byte << 3)); + flop = (flop & 0b10111111) | (0b01000000 & (byte << 5)); + flop = (flop & 0b01111111) | (0b10000000 & (byte << 7)); + return flop; +} + +// Flip the cube 180 degrees along the y axis. +void mirror_y (void) +{ + unsigned char buffer[CUBE_SIZE][CUBE_SIZE]; + unsigned char x,y,z; + + memcpy(buffer, leds, CUBE_BYTES); // copy the current cube into a buffer. + + //fill(0x00); + clear_led(); + for (z=0; zix2) + { + int tmp; + tmp = ix1; + ix1= ix2; + ix2 = tmp; + } + *ox1 = ix1; + *ox2 = ix2; +} + +// Returns a byte with a row of 1's drawn in it. +// byteline(2,5) gives 0b00111100 +char byteline (int start, int end) +{ + return ((0xff< 7 ? it2 - 8: 7 - it2; + + clear_led(); + + box_wireframe(0, 0, 0, xyz, xyz, xyz); + + if (flip > 0) mirror_z(); + if (rot == 1 || rot == 3) mirror_y(); + if (rot == 2 || rot == 3) mirror_x(); + + led_change = true; + SDL_Delay(delay); + } + } +} + +void effect_box_woopwoop (int delay, int grow) +{ + int i,ii; + + //fill(0x00); + clear_led(); + for (i=0;i<4;i++) + { + ii = i; + if (grow > 0) + ii = 3-i; + + box_wireframe(4+ii,4+ii,4+ii,3-ii,3-ii,3-ii); + led_change = true; + SDL_Delay(delay); + clear_led(); + //delay_ms(delay); + //fill(0x00); + } +} + +void draw_positions_axis (char axis, unsigned char positions[64], int invert) +{ + int x, y, p; + + //fill(0x00); + clear_led(); + + for (x=0; x<8; x++) + { + for (y=0; y<8; y++) + { + if (invert) + { + p = (7-positions[(x*8)+y]); + } else + { + p = positions[(x*8)+y]; + } + + //if (axis == AXIS_Z) + if (axis == 2) + set_led(x,y,p, true); + + if (axis == 1) + set_led(x,p,y, true); + + if (axis == 0) + set_led(p,y,x, true); + } + } + +} + + + +void effect_axis_updown_randsuspend(char axis, + int delay, int sleep, int invert) +{ + unsigned char positions[64]; + unsigned char destinations[64]; + + int i,px; + + // Set 64 random positions + for (i=0; i<64; i++) + { + positions[i] = 0; // Set all starting positions to 0 + destinations[i] = rand()%8; + } + + // Loop 8 times to allow destination 7 to reach all the way + for (i=0; i<8; i++) + { + // For every iteration, move all position one step closer to their destination + for (px=0; px<64; px++) + { + if (positions[px]destinations[px]) + { + positions[px]--; + } + } + draw_positions_axis (axis, positions,invert); + led_change = true; + SDL_Delay(delay); + //delay_ms(delay); + } +} + +void effect_stringfly2(const char* str) +{ + //int x,y,i; + unsigned char x,y,i; + unsigned char chr[5]; + int delay = 80; + + clear_led(); + + while (*str) + { + font_getchar(*str++, chr); + + // Put a character on the back of the cube + for (x = 0; x < 5; x++) + { + for (y = 0; y < 8; y++) + { + if ((chr[x] & (0x80>>y))) + { + //setvoxel(7,x+2,y); + //set_led(7,x+2,y); + set_led(x+2, 7, y); + } + } + } + + //led_change = true; + //SDL_Delay(1000); + //clear_led(); + //continue; + + // Shift the entire contents of the cube forward by 6 steps + // before placing the next character + for (i = 0; i<6; i++) + { + led_change = true; + //delay_ms(1000); + //SDL_Delay(1000); + SDL_Delay(delay); + //shift(AXIS_X,-1); + shift(1,-1); + //set_plane(1, 7, false); + } + } + + //return; + // Shift the last character out of the cube. + for (i = 0; i<8; i++) + { + led_change = true; + SDL_Delay(delay); + //delay_ms(1000); + //shift(AXIS_X,-1); + shift(1,-1); + } +} + +float distance2d (float x1, float y1, float x2, float y2) +{ + float dist; + dist = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); + + return dist; +} + +float distance3d (float x1, float y1, float z1, float x2, float y2, float z2) +{ + float dist; + dist = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2)); + + return dist; +} + + + + +// Display a sine wave running out from the center of the cube. +void ripples (int iterations, int delay) +{ + float distance, height, ripple_interval; + int x,y,i; + + clear_led(); + //fill(0x00); + + for (i=0;i