public class SpheresApplet extends PixApplet { public double focalLength = 3; public final static int X = 0; public final static int Y = 1; public final static int Z = 2; public final static int Rad = 3; public final static int RED = 4; public final static int GREEN = 5; public final static int BLUE = 6; double[][] spheres = { {1.1,0.0,-15.0,1.0, 0.9,0.5,0.5}, {-1.1,1.1,-15.0,1.0, 0.4,0.9,0.4}, {-1.1,-1.1,-15.0,1.0, 0.4,0.4,0.9}, }; // trace a ray public void rayTrace(double[] v, double[] w, double[] rgb){ double t = 100000.0; // <--- infinity :-) double[] obj = null; double[] s = null; double t1,t2; double[] tmp = {0,0,0}; for(int i=0;i 0 && t1 < t){ t = t1; obj = s; } } if(obj == null){ rgb[0] = 0.8; // 0.5*Math.cos(w[0]*Math.PI/2.0); rgb[1] = 0.8; // 0.5*Math.cos(w[1]*Math.PI/2.0); rgb[2] = 0.8; // 0.5*Math.cos(w[2]*Math.PI/2.0); return; } //System.out.println("t: "+t); // Compute surface point S = v + tw double[] S = { v[0]+t*w[0], v[1]+t*w[1], v[2]+t*w[2], }; // Compute surface normal n = (S-[cx,cy,cz])/r double[] n = { // (S[X]-obj[X])/obj[Rad], // (S[Y]-obj[Y])/obj[Rad], // (S[Z]-obj[Z])/obj[Rad], (obj[X]-S[X])/obj[Rad], (obj[Y]-S[Y])/obj[Rad], (obj[Z]-S[Z])/obj[Rad], }; vectorNormalize(n,n); // Compute reflection vector R = -2(w * n)n + w double wn = dotProduct(w,n); double[] R = { -2.0 * wn * n[X] + w[X], -2.0 * wn * n[Y] + w[Y], -2.0 * wn * n[Z] + w[Z], }; vectorNormalize(R,R); // Create reflected ray with v = (S+eR) and w = R. double[] Rv = { S[X] + 0.2 * R[X], S[Y] + 0.2 * R[Y], S[Z] + 0.2 * R[Z], }; double[] newrgb = new double[3]; rayTrace(Rv,R,newrgb); // rgb[0] = (0.15 * (1.0 - obj[RED])) + ((0.85) * rgb[0]) * wn; // rgb[1] = (0.15 * (1.0 - obj[GREEN])) + ((0.85) * rgb[1]) * wn; // rgb[2] = (0.15 * (1.0 - obj[BLUE])) + ((0.85) * rgb[2]) * wn; rgb[0] = (newrgb[0]*wn*0.9*obj[RED]); rgb[1] = (newrgb[1]*wn*0.9*obj[GREEN]); rgb[2] = (newrgb[2]*wn*0.9*obj[BLUE]); /* rgb[0] = rgb[0] * obj[RED]; rgb[1] = rgb[1] * obj[GREEN]; rgb[2] = rgb[2] * obj[BLUE]; */ } /** * SET PIXELS FOR THIS ANIMATION FRAME * (THIS OVERRIDES A METHOD IN PIXAPPLET CLASS) */ public void setPix(int frame) { double[] rgb = new double[]{0,0,0}; double[] v = new double[]{0,0,0}; double[] w = new double[]{0,0,0}; v[0] = 0; v[1] = 0; // CAMERA EYEPOINT IS AT THE ORIGIN v[2] = 0; int n = 0; for (int j = 0 ; j < H ; j++) // LOOP OVER IMAGE ROWS for (int i = 0 ; i < W ; i++) { // LOOP OVER IMAGE COLUMNS w[0] = (double)(i - W/2) / W; // COMPUTE RAY DIRECTION AT EACH PIXEL w[1] = (double)(H/2 - j) / W; // w[2] = -focalLength; // PLACE IMAGE PLANE AT z = -focalLength vectorNormalize(w,w); rayTrace(v, w, rgb); // RAY TRACE AT THIS PIXEL pix[n++] = pack( (int)(255 * rgb[0]), (int)(255 * rgb[1]), (int)(255 * rgb[2])); } } /** * given 2 points, find their difference */ void vectorSubtract (double[] va, double[] vb, double[] out){ out[0] = va[0]-vb[0]; out[1] = va[1]-vb[1]; out[2] = va[2]-vb[2]; } /** * cross product of two vectors */ void crossProduct(double[] v1, double[] v2, double[] cross ) { cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; } /** * normalize */ double vectorNormalize(double[] in, double[] out ) { double length, ilength; length = Math.sqrt(in[0]*in[0] + in[1]*in[1] + in[2]*in[2]); if (length == 0){ return 0; } ilength = 1.0/length; out[0] = in[0]*ilength; out[1] = in[1]*ilength; out[2] = in[2]*ilength; return length; } /** * dot product */ double dotProduct (double[] v1, double[] v2){ return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; } public boolean keyUp(java.awt.Event e,int key){ System.out.println("key: "+key); System.out.println("spheres("+spheres[0][0]+","+spheres[0][1]+","+spheres[0][2]+"): "+spheres[0][3]+"; (focal: "+focalLength+")\n"); if(key == 'a') spheres[0][2]-=0.1; if(key == 'z') spheres[0][2]+=0.1; if(key == 'f') focalLength-=0.1; if(key == 'v') focalLength+=0.1; damage = true; return true; } }