/* Cube 3D for LoLShield, oldskool wireframe style credits: code written by Tomi Panula-Ontto (drg / sonik, www.sonikclique.com, www.sonik.tv) drawline function written by Oskari Vuori instructions: arduino & lolshield required. just run it. seek far down for loop() in the bottom of the code for more amazing stuff. ...and yes, even I think this is pretty stupid :D but what do you expect for a weekend project? -Tomi next project for arduino/lolshield? openoffice would be nice... */ #include struct D3 { int coordAmount; // amount of coordinates int vertAmount; // amount of vertices (for linedrawing) float *coordinates; // pointer to coordinate table (xyz) int *vertices; // pointer to vertice table (line from-to) }; // coordinates for triangle, XYZ float trianglecoords[] = { -4,0,0, 4,0,0, 0,-4,0 }; // vertices (line from to) int trianglevertices[] = { 0,1, 1,2, 2,0 }; // triangle object defined struct D3 triangle = { 3, 3, (float *) &trianglecoords, (int *) &trianglevertices }; float linecoords[] = { -4,0,0, 4,0,0 }; int linevertices[] = { 0,1 }; // 3D line object, pretty boring struct D3 line = { 2, 1, (float*) &linecoords, (int*) &linevertices }; // coordinates for Cube float cubecoords[] = { -3,-3,3, 3,-3,3, 3,3,3, -3,3,3, -3,-3,-3, 3,-3,-3, 3,3,-3, -3,3,-3 }; // Vertices for Cube int cubevertices[] = { 0,1, 1,2, 2,3, 3,0, 4,5, 5,6, 6,7, 7,4, 0,4, 1,5, 2,6, 3,7 }; // Cube 3D object. struct D3 cube = { 8, 12, (float*) &cubecoords, (int*) &cubevertices }; float pyramidcoords[] = { -3,-3,3, 3,-3,3, 3,3,3, -3,3,3, 0,0,-3 }; int pyramidvertices[] = { 0,1, 1,2, 2,3, 3,0, 0,4, 1,4, 2,4, 3,4 }; // Pyramid 3D object struct D3 pyramid = { 5, 8, (float*) &pyramidcoords, (int*) &pyramidvertices }; float ax=0,ay=0,az=0; float distance=100; int projected[100*2]; void setup (void) { LedSign::Init(); } // bresenhamn oldie by Oskari Vuori // clipping ain't pretty, just q&d addition by me -Tomi void drawline (int x0, int y0, int x1, int y1, int c) { boolean b = abs(y1 - y0) > abs(x1 - x0); int tmp; if (b) { tmp = x0; x0 = y0; y0 = tmp; tmp = x1; x1 = y1; y1 = tmp; } if (x0 > x1) { tmp = x0; x0 = x1; x1 = tmp; tmp = y0; y0 = y1; y1 = tmp; } int deltax = x1 - x0; int deltay = abs(y1 - y0); int err = round(deltax / 2); int ystep; int x; int y = y0; if (y0 < y1) ystep = 1; else ystep = -1; for (x = x0; x <= x1; x++) { if (b) { if(y>=0 && y<14 && x>=0 && x<9) { LedSign::Set(y, x, c); } } else { if(x>=0 && x<14 && y>=0 && y<9) { LedSign::Set(x, y, c); } } err = err - deltay; if (err < 0) { y = y + ystep; err = err + deltax; } } } void rotate(struct D3 *obu) { float *ob = obu->coordinates; int *proj = (int * ) &projected; for(int i=0; icoordAmount; i++ ) { float x=*ob++; float y=*ob++; float z=*ob++; float nx,ny,nz; ny = cos(ax)*y - sin(ax)*z; nz = sin(ax)*y + cos(ax)*z; y=ny; z=nz; nx = cos(ay)*x + sin(ay)*z; nz = -sin(ay)*x + cos(ay)*z; x=nx; z=nz; nx = cos(az)*x - sin(az)*y; ny = sin(az)*x + cos(az)*y; x = nx; y = ny; // works well enough.. float d = distance-z; int ix,iy; ix = x*distance/d; iy = y*distance/d; *proj++ = ix+7; *proj++ = iy+4; } } void drawlines(struct D3 *obu) { int *vert = obu->vertices; for(int i=0; ivertAmount; i++) { int s = *vert++; int e = *vert++; drawline( projected[s*2], projected[s*2+1], projected[e*2], projected[e*2+1], 1); } } void drawdots(struct D3 *obu) { int *proj = (int *) &projected; for(int i=0; icoordAmount; i++) { int x = *proj++; int y = *proj++; if(x>=0 && x<14 && y>=0 && y<9) { LedSign::Set(x, y, 1); } } } // render 3d object void render(struct D3 *obu, boolean lines) { rotate(obu); LedSign::Clear(); if( lines ) { drawlines(obu); } else { drawdots(obu); } } void loop (void) { render(&cube, true); // try also pyramid, triangle and line. Draw just dots with false and sorry, no torus this time. delay(50); // delay between renders ax+=0.01; // change amount of rotation per axis ay+=0.05; az+=0.05; }