#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