/* * colourcube.java * * Created on 31 December 2003, 12:06 */ import java.awt.*; import java.awt.image.*; import java.awt.color.*; import java.applet.*; /** * * @author Allen */ public class colourcubeApplet extends Applet { public void init() { initForm(); // TODO: Add any constructor code after initForm call. } // sin cosine lookup table, should be faster than doing the maths! private double[][] lookup = {{0.000000, 1.000000}, {0.017452, 0.999848}, {0.034899, 0.999391}, {0.052336, 0.998630}, {0.069756, 0.997564}, {0.087156, 0.996195}, {0.104528, 0.994522}, {0.121869, 0.992546}, {0.139173, 0.990268}, {0.156434, 0.987688}, {0.173648, 0.984808}, {0.190809, 0.981627}, {0.207912, 0.978148}, {0.224951, 0.974370}, {0.241922, 0.970296}, {0.258819, 0.965926}, {0.275637, 0.961262}, {0.292372, 0.956305}, {0.309017, 0.951057}, {0.325568, 0.945519}, {0.342020, 0.939693}, {0.358368, 0.933580}, {0.374607, 0.927184}, {0.390731, 0.920505}, {0.406737, 0.913545}, {0.422618, 0.906308}, {0.438371, 0.898794}, {0.453990, 0.891007}, {0.469472, 0.882948}, {0.484810, 0.874620}, {0.500000, 0.866025}, {0.515038, 0.857167}, {0.529919, 0.848048}, {0.544639, 0.838671}, {0.559193, 0.829038}, {0.573576, 0.819152}, {0.587785, 0.809017}, {0.601815, 0.798636}, {0.615661, 0.788011}, {0.629320, 0.777146}, {0.642788, 0.766044}, {0.656059, 0.754710}, {0.669131, 0.743145}, {0.681998, 0.731354}, {0.694658, 0.719340}, {0.707107, 0.707107}, {0.719340, 0.694658}, {0.731354, 0.681998}, {0.743145, 0.669131}, {0.754710, 0.656059}, {0.766044, 0.642788}, {0.777146, 0.629320}, {0.788011, 0.615661}, {0.798636, 0.601815}, {0.809017, 0.587785}, {0.819152, 0.573576}, {0.829038, 0.559193}, {0.838671, 0.544639}, {0.848048, 0.529919}, {0.857167, 0.515038}, {0.866025, 0.500000}, {0.874620, 0.484810}, {0.882948, 0.469472}, {0.891007, 0.453990}, {0.898794, 0.438371}, {0.906308, 0.422618}, {0.913545, 0.406737}, {0.920505, 0.390731}, {0.927184, 0.374607}, {0.933580, 0.358368}, {0.939693, 0.342020}, {0.945519, 0.325568}, {0.951057, 0.309017}, {0.956305, 0.292372}, {0.961262, 0.275637}, {0.965926, 0.258819}, {0.970296, 0.241922}, {0.974370, 0.224951}, {0.978148, 0.207912}, {0.981627, 0.190809}, {0.984808, 0.173648}, {0.987688, 0.156434}, {0.990268, 0.139173}, {0.992546, 0.121869}, {0.994522, 0.104528}, {0.996195, 0.087156}, {0.997564, 0.069756}, {0.998630, 0.052336}, {0.999391, 0.034899}, {0.999848, 0.017452}, {1.000000, -0.000000}, {0.999848, -0.017452}, {0.999391, -0.034899}, {0.998630, -0.052336}, {0.997564, -0.069756}, {0.996195, -0.087156}, {0.994522, -0.104528}, {0.992546, -0.121869}, {0.990268, -0.139173}, {0.987688, -0.156434}, {0.984808, -0.173648}, {0.981627, -0.190809}, {0.978148, -0.207912}, {0.974370, -0.224951}, {0.970296, -0.241922}, {0.965926, -0.258819}, {0.961262, -0.275637}, {0.956305, -0.292372}, {0.951057, -0.309017}, {0.945519, -0.325568}, {0.939693, -0.342020}, {0.933580, -0.358368}, {0.927184, -0.374607}, {0.920505, -0.390731}, {0.913545, -0.406737}, {0.906308, -0.422618}, {0.898794, -0.438371}, {0.891007, -0.453990}, {0.882948, -0.469472}, {0.874620, -0.484810}, {0.866025, -0.500000}, {0.857167, -0.515038}, {0.848048, -0.529919}, {0.838671, -0.544639}, {0.829038, -0.559193}, {0.819152, -0.573576}, {0.809017, -0.587785}, {0.798636, -0.601815}, {0.788011, -0.615661}, {0.777146, -0.629320}, {0.766044, -0.642788}, {0.754710, -0.656059}, {0.743145, -0.669131}, {0.731354, -0.681998}, {0.719340, -0.694658}, {0.707107, -0.707107}, {0.694658, -0.719340}, {0.681998, -0.731354}, {0.669131, -0.743145}, {0.656059, -0.754710}, {0.642788, -0.766044}, {0.629320, -0.777146}, {0.615661, -0.788011}, {0.601815, -0.798636}, {0.587785, -0.809017}, {0.573576, -0.819152}, {0.559193, -0.829038}, {0.544639, -0.838671}, {0.529919, -0.848048}, {0.515038, -0.857167}, {0.500000, -0.866025}, {0.484810, -0.874620}, {0.469472, -0.882948}, {0.453990, -0.891007}, {0.438371, -0.898794}, {0.422618, -0.906308}, {0.406737, -0.913545}, {0.390731, -0.920505}, {0.374607, -0.927184}, {0.358368, -0.933580}, {0.342020, -0.939693}, {0.325568, -0.945519}, {0.309017, -0.951057}, {0.292372, -0.956305}, {0.275637, -0.961262}, {0.258819, -0.965926}, {0.241922, -0.970296}, {0.224951, -0.974370}, {0.207912, -0.978148}, {0.190809, -0.981627}, {0.173648, -0.984808}, {0.156434, -0.987688}, {0.139173, -0.990268}, {0.121869, -0.992546}, {0.104528, -0.994522}, {0.087156, -0.996195}, {0.069756, -0.997564}, {0.052336, -0.998630}, {0.034899, -0.999391}, {0.017452, -0.999848}, {-0.000000, -1.000000}, {-0.017452, -0.999848}, {-0.034899, -0.999391}, {-0.052336, -0.998630}, {-0.069756, -0.997564}, {-0.087156, -0.996195}, {-0.104528, -0.994522}, {-0.121869, -0.992546}, {-0.139173, -0.990268}, {-0.156434, -0.987688}, {-0.173648, -0.984808}, {-0.190809, -0.981627}, {-0.207912, -0.978148}, {-0.224951, -0.974370}, {-0.241922, -0.970296}, {-0.258819, -0.965926}, {-0.275637, -0.961262}, {-0.292372, -0.956305}, {-0.309017, -0.951057}, {-0.325568, -0.945519}, {-0.342020, -0.939693}, {-0.358368, -0.933580}, {-0.374607, -0.927184}, {-0.390731, -0.920505}, {-0.406737, -0.913545}, {-0.422618, -0.906308}, {-0.438371, -0.898794}, {-0.453991, -0.891007}, {-0.469472, -0.882948}, {-0.484810, -0.874620}, {-0.500000, -0.866025}, {-0.515038, -0.857167}, {-0.529919, -0.848048}, {-0.544639, -0.838671}, {-0.559193, -0.829038}, {-0.573576, -0.819152}, {-0.587785, -0.809017}, {-0.601815, -0.798636}, {-0.615661, -0.788011}, {-0.629320, -0.777146}, {-0.642788, -0.766044}, {-0.656059, -0.754710}, {-0.669131, -0.743145}, {-0.681998, -0.731354}, {-0.694658, -0.719340}, {-0.707107, -0.707107}, {-0.719340, -0.694658}, {-0.731354, -0.681998}, {-0.743145, -0.669131}, {-0.754710, -0.656059}, {-0.766044, -0.642788}, {-0.777146, -0.629320}, {-0.788011, -0.615661}, {-0.798636, -0.601815}, {-0.809017, -0.587785}, {-0.819152, -0.573576}, {-0.829038, -0.559193}, {-0.838671, -0.544639}, {-0.848048, -0.529919}, {-0.857167, -0.515038}, {-0.866025, -0.500000}, {-0.874620, -0.484810}, {-0.882948, -0.469472}, {-0.891007, -0.453990}, {-0.898794, -0.438371}, {-0.906308, -0.422618}, {-0.913545, -0.406737}, {-0.920505, -0.390731}, {-0.927184, -0.374607}, {-0.933580, -0.358368}, {-0.939693, -0.342020}, {-0.945519, -0.325568}, {-0.951057, -0.309017}, {-0.956305, -0.292372}, {-0.961262, -0.275637}, {-0.965926, -0.258819}, {-0.970296, -0.241922}, {-0.974370, -0.224951}, {-0.978148, -0.207912}, {-0.981627, -0.190809}, {-0.984808, -0.173648}, {-0.987688, -0.156434}, {-0.990268, -0.139173}, {-0.992546, -0.121869}, {-0.994522, -0.104528}, {-0.996195, -0.087156}, {-0.997564, -0.069756}, {-0.998630, -0.052336}, {-0.999391, -0.034899}, {-0.999848, -0.017452}, {-1.000000, 0.000000}, {-0.999848, 0.017452}, {-0.999391, 0.034899}, {-0.998630, 0.052336}, {-0.997564, 0.069756}, {-0.996195, 0.087156}, {-0.994522, 0.104528}, {-0.992546, 0.121869}, {-0.990268, 0.139173}, {-0.987688, 0.156434}, {-0.984808, 0.173648}, {-0.981627, 0.190809}, {-0.978148, 0.207912}, {-0.974370, 0.224951}, {-0.970296, 0.241922}, {-0.965926, 0.258819}, {-0.961262, 0.275637}, {-0.956305, 0.292372}, {-0.951057, 0.309017}, {-0.945519, 0.325568}, {-0.939693, 0.342020}, {-0.933580, 0.358368}, {-0.927184, 0.374607}, {-0.920505, 0.390731}, {-0.913545, 0.406737}, {-0.906308, 0.422618}, {-0.898794, 0.438371}, {-0.891007, 0.453991}, {-0.882948, 0.469472}, {-0.874620, 0.484810}, {-0.866025, 0.500000}, {-0.857167, 0.515038}, {-0.848048, 0.529919}, {-0.838671, 0.544639}, {-0.829038, 0.559193}, {-0.819152, 0.573576}, {-0.809017, 0.587785}, {-0.798636, 0.601815}, {-0.788011, 0.615661}, {-0.777146, 0.629320}, {-0.766044, 0.642788}, {-0.754710, 0.656059}, {-0.743145, 0.669131}, {-0.731354, 0.681998}, {-0.719340, 0.694658}, {-0.707107, 0.707107}, {-0.694658, 0.719340}, {-0.681998, 0.731354}, {-0.669131, 0.743145}, {-0.656059, 0.754710}, {-0.642788, 0.766044}, {-0.629320, 0.777146}, {-0.615661, 0.788011}, {-0.601815, 0.798636}, {-0.587785, 0.809017}, {-0.573576, 0.819152}, {-0.559193, 0.829038}, {-0.544639, 0.838671}, {-0.529919, 0.848048}, {-0.515038, 0.857167}, {-0.500000, 0.866025}, {-0.484810, 0.874620}, {-0.469472, 0.882948}, {-0.453990, 0.891007}, {-0.438371, 0.898794}, {-0.422618, 0.906308}, {-0.406737, 0.913545}, {-0.390731, 0.920505}, {-0.374607, 0.927184}, {-0.358368, 0.933580}, {-0.342020, 0.939693}, {-0.325568, 0.945519}, {-0.309017, 0.951057}, {-0.292372, 0.956305}, {-0.275637, 0.961262}, {-0.258819, 0.965926}, {-0.241922, 0.970296}, {-0.224951, 0.974370}, {-0.207912, 0.978148}, {-0.190809, 0.981627}, {-0.173648, 0.984808}, {-0.156434, 0.987688}, {-0.139173, 0.990268}, {-0.121869, 0.992546}, {-0.104528, 0.994522}, {-0.087156, 0.996195}, {-0.069756, 0.997564}, {-0.052336, 0.998630}, {-0.034899, 0.999391}, {-0.017452, 0.999848}}; private static class myPoint { double x; double y; double z; } private final static int Z_OFF_SET = 256; // must be final static for use to dimension arrays ! private final static int NUMPOINTS = 8; // must be final static for use to dimension arrays ! private final static int NUMFACES = 6; private final static boolean SHOW_FRAME_TIME = false; // show frame time or fps // 3D co-ords (X1,Y1,Z1)for each point private static int[] Obj = {-10,-10,-10, 10,-10,-10, 10, 10,-10, -10, 10,-10, -10,-10, 10, 10,-10, 10, 10, 10, 10, -10, 10, 10}; // define faces from the translated points array private static int[][] faces = { {0, 1, 2, 3}, {4, 5, 6, 7}, {0, 4, 7, 3}, {3, 7, 6, 2}, {2, 6, 5, 1}, {1, 0, 4, 5}}; private static Color[] faceColour = { Color.red, Color.blue, Color.green, Color.yellow, Color.pink, Color.cyan}; private static myPoint[] points = new myPoint[NUMPOINTS]; private static myPoint[] translated = new myPoint[NUMPOINTS]; private static myPoint[] oldtranslated = new myPoint[NUMPOINTS]; private static int xoff, yoff, zoff; private static int NUM_X_PIXELS = 320; private static int NUM_Y_PIXELS = 240; private final static int SLEEP_TIME = 20; // period of thread sleep in ms private static int FRAMES_TO_CHECK = 100; // how many frames to average the frame time over private static int width = NUM_X_PIXELS; // why am I doing this ! private static int height = NUM_Y_PIXELS; private static int[] fullRGBPalette = new int[256]; private static long frameTime, timeTemp; private static int frameCount = 0; private static float fps = (float)0.0; private static BufferedImage img; private static Graphics g; private static Graphics g_img; /** Creates new form colourcube */ void initForm() { int loop; int xdeg, ydeg, zdeg; // initComponents(); // set the number of frames to do the timing over (aim for 2 second update based on sleep time) FRAMES_TO_CHECK = 2000 / SLEEP_TIME; // setTitle("ColourCube"); // setSize(width, height); setVisible(true); setBackground(Color.black); img = new BufferedImage(width, height, ColorSpace.TYPE_RGB); g_img = img.getGraphics(); for(loop = 0; loop < NUMPOINTS; loop++) { points [loop] = new myPoint(); translated [loop] = new myPoint(); oldtranslated [loop] = new myPoint(); points [loop].x = (double)Obj [((loop + 1) * 3) - 3]; points [loop].y = (double)Obj [((loop + 1) * 3) - 2]; points [loop].z = (double)Obj [((loop + 1) * 3) - 1]; translated[loop].x = (double)0.0; translated[loop].y = (double)0.0; translated[loop].z = (double)0.0; } xoff=NUM_X_PIXELS/2; yoff=NUM_Y_PIXELS/2; zoff=Z_OFF_SET; g = this.getGraphics(); timeTemp = System.currentTimeMillis(); xdeg = ydeg = zdeg = 0; for (loop=-256;loop<=-100;loop++) { zoff = loop; RotatePoints(xdeg,ydeg,zdeg); DrawPoints(1); repaint(); xdeg++; ydeg++; zdeg++; if(xdeg >= 360) xdeg = 0; if(ydeg >= 360) ydeg = 0; if(zdeg >= 360) zdeg = 0; try { Thread.sleep(SLEEP_TIME); } catch (Exception e) {} } for(;;) { // Calculate new positions RotatePoints(xdeg,ydeg,zdeg); DrawPoints(0); repaint(); xdeg++; ydeg+=2; zdeg++; if(xdeg >= 360) xdeg = 0; if(ydeg >= 360) ydeg = 0; if(zdeg >= 360) zdeg = 0; try { Thread.sleep(SLEEP_TIME); } catch (Exception e) {} } } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ /* private void initComponents() {//GEN-BEGIN:initComponents addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { exitForm(evt); } }); pack(); }//GEN-END:initComponents */ /** Exit the Application */ private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm System.exit(0); }//GEN-LAST:event_exitForm /** * @param args the command line arguments */ public static void main(String args[]) { new colourcube().show(); } public void paint(Graphics g) { int loop, x, y; int SCALE = 1; g.drawImage(img, 0, 0, width * SCALE, height * SCALE, 0, 0, width, height, this); g.setColor(Color.black); frameCount++; if(SHOW_FRAME_TIME) { // clear old text g.drawString("Frame time: "+ (((float)frameTime / FRAMES_TO_CHECK) - SLEEP_TIME) +" ms (+ " + SLEEP_TIME + "ms)", 10, height - 10); if(frameCount > FRAMES_TO_CHECK) { frameCount = 0; frameTime = System.currentTimeMillis() - timeTemp; timeTemp = System.currentTimeMillis(); } g.setColor(Color.white); g.drawString("Frame time: "+ (((float)frameTime / FRAMES_TO_CHECK) - SLEEP_TIME) +" ms (+ " + SLEEP_TIME + "ms)", 10, height - 10); } else { g.drawString("FPS: "+ fps, 10, height - 10); if(System.currentTimeMillis() > timeTemp + 2000) { // check fps every two secs frameTime = System.currentTimeMillis() - timeTemp; fps = (float)frameCount / frameTime * 1000; frameCount = 0; timeTemp = System.currentTimeMillis(); } g.setColor(Color.white); g.drawString("FPS: "+ fps, 10, height - 10); } } public void update(Graphics g) { paint(g); } // Procedure RotatePoints (X,Y,Z:Integer); // { This rotates object points by X,Y and Z; then places the result in // TRANSLATED } // rotate about x: newy = cos*y-sin*z (cos*cos-sin*sin) // newz = sin*y+cos*z (sin*cos+cos*sin) // i.e: newy+i*newz=e^(i*theta)*(y+i*z) (theta=int x) // =(cos+i*sin)*(y+i*z) // translated[loop1][0] and translated[loop1][1] are the two endpoints // of line segment loop1. private void RotatePoints(int x, int y, int z) { int loop1; myPoint temp = new myPoint(); for(loop1=0;loop1 0) { temp.x = (lookup[y][1] * translated[loop1].x) + (lookup[y][0] * translated[loop1].z); temp.y = translated[loop1].y; temp.z = ((-lookup[y][0]) * translated[loop1].x) + (lookup[y][1] * translated[loop1].z); translated[loop1].x = temp.x; translated[loop1].y = temp.y; translated[loop1].z = temp.z; } if(z > 0) { temp.x = (lookup[z][1] * translated[loop1].x) - (lookup[z][0] * translated[loop1].y); temp.y = (lookup[z][0] * translated[loop1].x) + (lookup[z][1] * translated[loop1].y); temp.z = translated[loop1].z; translated[loop1].x = temp.x; translated[loop1].y = temp.y; translated[loop1].z = temp.z; } } } // Procedure DrawPoints; // This draws the translated object private void DrawPoints(int moved_z) { int loop1; int nx,ny,nx2,ny2; int temp, temp1, temp2; int t_colour; int[] x_array; int[] y_array; int[] z_array; int[] face_x_array; int[] face_y_array; int[] face_z_array; int[] face_order; x_array = new int[NUMPOINTS]; y_array = new int[NUMPOINTS]; z_array = new int[NUMPOINTS]; face_x_array = new int[4]; face_y_array = new int[4]; face_z_array = new int[NUMFACES]; face_order = new int[NUMFACES]; g_img.clearRect(0, 0, width, height); for(loop1=0;loop1 0) && (nx < NUM_X_PIXELS) && (ny > 0) && (ny < NUM_Y_PIXELS)) g_img.drawLine(nx,ny,nx,ny); } */ // draw new point (we don't actually need to draw it, just work out the x, y, z) g_img.setColor(Color.black); if((translated[loop1].z + zoff) < 0) { temp = (int)(translated[loop1].z + zoff); nx = (int)((256 * translated[loop1].x) / temp) + xoff; ny = (int)((256 * translated[loop1].y) / temp) + yoff; x_array[loop1] = nx; y_array[loop1] = ny; z_array[loop1] = temp; // check bounds if((nx > -1) && (nx < NUM_X_PIXELS) && (ny > -1) && (ny < NUM_Y_PIXELS)) g_img.drawLine(nx,ny,nx,ny); else System.out.println("nx or ny out of bounds"); } else System.out.println("Z out of bounds"); } // need to work through the properly arranged array(s) to get this to work // (describing the points + faces is easier than working from lines as per the wireframe cube) // also need to add some Z domain drawing!! which means writing a Z aware polyfill // or defining the face drawing order (back to front), which is a lot easier for(loop1 = 0; loop1 < NUMFACES; loop1++) { face_z_array[loop1] = z_array[faces[loop1][0]]; face_z_array[loop1] += z_array[faces[loop1][1]]; face_z_array[loop1] += z_array[faces[loop1][2]]; face_z_array[loop1] += z_array[faces[loop1][3]]; face_z_array[loop1] /= 4; face_order[loop1] = loop1; } // we should now have an array of the average z values of the faces // we need to sort them into lowest Z first order // very simple sort loop numfaces times through array (not a big deal for just 6 faces) for(loop1 = 0; loop1 < NUMFACES; loop1++) { for(int loop2 = 1; loop2 < NUMFACES; loop2++) { if(face_z_array[loop2] < face_z_array[loop2 - 1]) { int z_temp = face_z_array[loop2]; face_z_array[loop2] = face_z_array[loop2 - 1]; face_z_array[loop2 - 1] = z_temp; int order_temp = face_order[loop2]; face_order[loop2] = face_order[loop2 - 1]; face_order[loop2 - 1] = order_temp; } } } // we can cheat a bit, only the front half of the faces are visible on a cube at // any one time, so only draw the 3 nearest faces. for(loop1 = NUMFACES / 2; loop1 < NUMFACES; loop1++) { g_img.setColor(faceColour[face_order[loop1]]); face_x_array[0] = x_array[faces[face_order[loop1]][0]]; face_x_array[1] = x_array[faces[face_order[loop1]][1]]; face_x_array[2] = x_array[faces[face_order[loop1]][2]]; face_x_array[3] = x_array[faces[face_order[loop1]][3]]; face_y_array[0] = y_array[faces[face_order[loop1]][0]]; face_y_array[1] = y_array[faces[face_order[loop1]][1]]; face_y_array[2] = y_array[faces[face_order[loop1]][2]]; face_y_array[3] = y_array[faces[face_order[loop1]][3]]; g_img.fillPolygon(face_x_array, face_y_array, 4); } } // Variables declaration - do not modify//GEN-BEGIN:variables // End of variables declaration//GEN-END:variables }