From 66dcf910bd4744d8ced56cb9586aa937a1a2d4c5 Mon Sep 17 00:00:00 2001 From: vg Date: Tue, 7 Jul 2020 16:24:01 +0200 Subject: first commit --- avr-test/src/draw.cpp | 559 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 559 insertions(+) create mode 100644 avr-test/src/draw.cpp (limited to 'avr-test/src/draw.cpp') diff --git a/avr-test/src/draw.cpp b/avr-test/src/draw.cpp new file mode 100644 index 0000000..faaa346 --- /dev/null +++ b/avr-test/src/draw.cpp @@ -0,0 +1,559 @@ +#include "draw.h" +#include "string.h" + +// Set a single voxel to ON +void setvoxel(int x, int y, int z) +{ + if (inrange(x,y,z)) + cube[z][y] |= (1 << x); +} + +// Set a single voxel in the temporary cube buffer to ON +void tmpsetvoxel(int x, int y, int z) +{ + if (inrange(x,y,z)) + fb[z][y] |= (1 << x); +} + +// Set a single voxel to OFF +void clrvoxel(int x, int y, int z) +{ + if (inrange(x,y,z)) + cube[z][y] &= ~(1 << x); +} + +// Set a single voxel to OFF +void tmpclrvoxel(int x, int y, int z) +{ + if (inrange(x,y,z)) + fb[z][y] &= ~(1 << x); +} + +// This function validates that we are drawing inside the cube. +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; + } +} + +// Get the current status of a voxel +unsigned char getvoxel(int x, int y, int z) +{ + if (inrange(x,y,z)) + { + if (cube[z][y] & (1 << x)) + { + return 1; + } else + { + return 0; + } + } else + { + return 0; + } +} + +// In some effect we want to just take bool and write it to a voxel +// this function calls the apropriate voxel manipulation function. +void altervoxel(int x, int y, int z, int state) +{ + if (state == 1) + { + setvoxel(x,y,z); + } else + { + clrvoxel(x,y,z); + } +} + +// Flip the state of a voxel. +// If the voxel is 1, its turned into a 0, and vice versa. +void flpvoxel(int x, int y, int z) +{ + if (inrange(x, y, z)) + cube[z][y] ^= (1 << x); +} + +// Makes sure x1 is alwas smaller than x2 +// This is usefull for functions that uses for loops, +// to avoid infinite loops +void argorder(int ix1, int ix2, int *ox1, int *ox2) +{ + if (ix1>ix2) + { + int tmp; + tmp = ix1; + ix1= ix2; + ix2 = tmp; + } + *ox1 = ix1; + *ox2 = ix2; +} + +// Sets all voxels along a X/Y plane at a given point +// on axis Z +void setplane_z (int z) +{ + int i; + if (z>=0 && z=0 && z=0 && x=0 && x=0 && y=0 && y> 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; +} + +// Draw a line between any coordinates in 3d space. +// Uses integer values for input, so dont expect smooth animations. +void line(int x1, int y1, int z1, int x2, int y2, int z2) +{ + float xy; // how many voxels do we move on the y axis for each step on the x axis + float xz; // how many voxels do we move on the y axis for each step on the x axis + unsigned char x,y,z; + unsigned char lasty,lastz; + + // We always want to draw the line from x=0 to x=7. + // If x1 is bigget than x2, we need to flip all the values. + if (x1>x2) + { + int tmp; + tmp = x2; x2 = x1; x1 = tmp; + tmp = y2; y2 = y1; y1 = tmp; + tmp = z2; z2 = z1; z1 = tmp; + } + + + if (y1>y2) + { + xy = (float)(y1-y2)/(float)(x2-x1); + lasty = y2; + } else + { + xy = (float)(y2-y1)/(float)(x2-x1); + lasty = y1; + } + + if (z1>z2) + { + xz = (float)(z1-z2)/(float)(x2-x1); + lastz = z2; + } else + { + xz = (float)(z2-z1)/(float)(x2-x1); + lastz = z1; + } + + + + // For each step of x, y increments by: + for (x = x1; x<=x2;x++) + { + y = (xy*(x-x1))+y1; + z = (xz*(x-x1))+z1; + setvoxel(x,y,z); + } + +} + +// Delay loop. +// This is not calibrated to milliseconds, +// but we had allready made to many effects using this +// calibration when we figured it might be a good idea +// to calibrate it. +void delay_ms(uint16_t x) +{ + uint8_t y, z; + for ( ; x > 0 ; x--){ + for ( y = 0 ; y < 90 ; y++){ + for ( z = 0 ; z < 6 ; z++){ + asm volatile ("nop"); + } + } + } +} + +// Copies the contents of fb (temp cube buffer) into the rendering buffer +void tmp2cube (void) +{ + memcpy((void*)cube, (const void*)fb, 64); // copy the current cube into a buffer. +} + +// 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 == AXIS_Z) + { + state = getvoxel(x,y,iii); + altervoxel(x,y,ii,state); + } + + if (axis == AXIS_Y) + { + state = getvoxel(x,iii,y); + altervoxel(x,ii,y,state); + } + + if (axis == AXIS_X) + { + state = getvoxel(iii,y,x); + altervoxel(ii,y,x,state); + } + } + } + } + + 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) + clrvoxel(x,y,i); + + if (axis == AXIS_Y) + clrvoxel(x,i,y); + + if (axis == AXIS_X) + clrvoxel(i,y,x); + } + } +} + +// 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, (const void*)cube, CUBE_BYTES); // copy the current cube into a buffer. + + fill(0x00); + for (z=0; z