<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">public class rt 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 R = 3;
    public final static int RED = 4;
    public final static int GREEN = 5;
    public final static int BLUE = 6;

    public double[][] spheres;
    public double[][] lights;

    private booolean printlog = false;

    public rt () {
        super();
        spheres = new double[10][7];
        for(int i=0;i&lt;spheres.length;i++){
            spheres[i][0] = 5*(Math.random()-0.5);
            spheres[i][1] = 5*(Math.random()-0.5);
            spheres[i][2] = -30*(Math.random()+2);
            spheres[i][3] = Math.random() * 3;
            spheres[i][4] = Math.random();
            spheres[i][5] = Math.random();
            spheres[i][6] = Math.random();
        }
        lights = new double[5][6];
        for(int i=0;i&lt;lights.length;i++){
            lights[i][0] = Math.random()*100;
            lights[i][1] = Math.random()*100;
            lights[i][2] = Math.random()*100;
            lights[i][3] = Math.random();
            lights[i][4] = Math.random();
            lights[i][5] = Math.random();
        }
    }

    // print log
    public void log(String s){
        if(printlog)
            System.out.println(s);
    }

    // trace a ray
    public void rayTrace(double[] v, double[] w, double[] rgb){
        
        double t = 100000.0;  // &lt;--- infinity :-)
        double[] obj = null;
        double[] s = null;
        double t1,t2;

        double[] tmp = {0,0,0};        
        for(int i=0;i&lt;spheres.length;i++){
            s = spheres[i];
            double A = dotProduct(w,w);
            vectorSubtract(v,s,tmp);
            double B = 2.0 * dotProduct(tmp,w);
            double C = dotProduct(tmp,tmp) - s[R]*s[R];
            
            // did we miss the sphere?
            double b24ac = B*B - 4.0*A*C;
            
            if(b24ac &lt;= 0)
                continue;
                
            double sq_b24ac = Math.sqrt(b24ac);
            t1 = -B - sq_b24ac/(2.0*A);

            // is sphere in front of the ray?
            if(t1 &gt; 0 &amp;&amp; t1 &lt; t){
                t = t1;
                obj = s;
            }
        }
        if(obj == null){
            rgb[0] = 0.5; // 0.5*Math.cos(w[0]*Math.PI/2.0);
            rgb[1] = 0.5; // 0.5*Math.cos(w[1]*Math.PI/2.0);
            rgb[2] = 0.5; // 0.5*Math.cos(w[2]*Math.PI/2.0);
            return;
        }
        
        // 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[R],
            (S[Y]-obj[Y])/obj[R],
            (S[Z]-obj[Z])/obj[R],
        };
        vectorNormalize(n,n);

        
        // Compute reflection vector R = -2(w * n)n + w
        double wn = dotProduct(w,n);
        //double wn = dotProduct(new double[]{1,0,0},n);
        
        double[] R = {
            -2 * wn * n[X] + w[X],
            -2 * wn * n[Y] + w[Y],
            -2 * wn * n[Z] + w[Z],
        };
        vectorNormalize(R,R);

        //Ambientcolor + SUMi ( LightColori   *   ( Diffusecolor * max(0,Li.n) + Specularcolor * (max(0,Hi.e)p ) ) 
        // Hi = 2(Li . n) n - Li 

        // Create reflected ray with v = (S+eR) and w = R.
        double[] Rv = {
            S[X] + 0.02 * R[X],
            S[Y] + 0.02 * R[Y],
            S[Z] + 0.02 * R[Z],
        };
        
        rayTrace(Rv,R,rgb);
        
        rgb[0] = (0.4 * (1.0 - obj[RED])) + ((0.6) * rgb[0]) * wn;        
        rgb[1] = (0.4 * (1.0 - obj[GREEN])) + ((0.6) * rgb[1]) * wn;        
        rgb[2] = (0.4 * (1.0 - obj[BLUE])) + ((0.6) * rgb[2]) * wn;

        /*
        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 &lt; H ; j++)   // LOOP OVER IMAGE ROWS
            for (int i = 0 ; i &lt; 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);
        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;
    }
    
}

</pre></body></html>