// // RayTracer: A simple ray tracer for spheres and polygons. // // (This was a port from one of my graphics classes.) // // Author: Will Luo // Last Modified: Sat Dec 16 15:01:35 EST 1995 // import java.awt.*; import java.awt.image.ColorModel; import java.awt.image.MemoryImageSource; import java.util.Vector; // use java vector as a list import java.lang.Thread; class SceneConsts { static double GIa; /* ambient light intensity (assume it is white) */ static double GKa; /* ambient light reflectance */ static double GKd; /* global object reflectance */ static double Gs; /* global "shadow reflectance" This prevents a flat looking shadow */ static double Ip; public SceneConsts() { GIa = 0.1; GKa = 1.0; GKd = 1.0; Gs = 0.0005; Ip = 1.0; } } /* * These constants describe the environment of a scene. */ class Scene { static SceneConsts sConsts; Vec VRP; Vec light; Vector targetList; // objects in the scene } public class RayTracer extends java.applet.Applet implements Runnable { Thread kicker; DrawPanel dp; static Scene scene; public RayTracer() { scene = new Scene(); scene.targetList = new Vector(); } public void init() { // set up the lights and view reference point scene.VRP = new Vec(0.0, 0.0, -1.0); scene.light = new Vec(16.0, 8.0, -16.0); // Build targetList by hand for now. We should eventually let the // users build their objects interactively. scene.targetList.addElement(new SphereTarget(0.05, -0.3, 0.0, 0.3)); scene.targetList.addElement(new SphereTarget(0.05, 0.06, 0.0, 0.24)); scene.targetList.addElement(new SphereTarget(0.05, 0.19, -0.205, 0.01)); scene.targetList.addElement(new SphereTarget(0.05, 0.09, -0.237, 0.01)); scene.targetList.addElement(new SphereTarget(0.05, 0.0, -0.230, 0.01)); scene.targetList.addElement(new SphereTarget(0.05, 0.32, -0.205, 0.018)); scene.targetList.addElement(new SphereTarget(0.05, 0.34, 0.0, 0.2)); scene.targetList.addElement(new SphereTarget(0.1, 0.4, -0.195, 0.02)); scene.targetList.addElement(new SphereTarget(-0.02, 0.393, -0.185, 0.02)); scene.targetList.addElement(new SphereTarget(0.0, 0.0, 10, 10)); for(int i=0; i= 0; pixY--){ for (pixY=0; pixY < 2*h; pixY++){ double tmpx = -1.0; tmpy -= ystep; // for(pixX=0; pixX < 2*w; pixX++){ for(pixX=0; pixX < 2*w; pixX++){ tmpx += xstep; Vec projP = new Vec(tmpx, tmpy, tmpz); int c = paintPix(projP); int realX = pixX/2, realY = pixY/2; pixels[realX + w*realY] = (255<<24)|(c<<16)|(c<<8)|(c<<0); // visual feedback on progress g.setColor(new Color(c,c,c)); g.drawLine(realX, realY, realX, realY); } } System.out.println(pixX + " x " + pixY); newImage(me, w, h, pixels); } synchronized void newImage(Thread me, int width, int height, int pixels[]) { if (kicker != me) { return; } Image img; img = createImage(new MemoryImageSource(width, height, ColorModel.getRGBdefault(), pixels, 0, width)); dp.setImage(img); kicker = null; } int paintPix(Vec projP) { double t[] = new double[1]; int color=0; Vec R1 = new Vec(projP); R1.sub(scene.VRP); R1.normalize(); t[0] = 0.0; int obj = intersectObjects(scene.VRP, R1, t, 0, false); /* if it does then find out how to paint the pixel */ if(t[0] > 0.0){ color = ((Target) scene.targetList.elementAt(obj)).shade(obj, R1, t); } color += 16; // ambient light if(color > 255) color = 255; return color; } int intersectObjects(Vec R0, Vec R1, double result[], int object, boolean shadowCheck) { double minDist=0.0, dist; int hit=-1; for(int i=0; i0.0)){ minDist = dist; hit = i; } else if((dist>0.0) && (dist 0.0) /* something is in the way */ intensity = sConsts.Gs * intensity; /* pixel gets ambient light only */ else{ /* pixel gets all kinds of light */ intensity = intensity * sConsts.Ip * sConsts.GKd; } intensity = intensity + sConsts.GIa*sConsts.GKa; if(intensity > 1.0) intensity = 1.0; /* find the corresponding color in the color lookup table */ intensity = intensity * 255; return((int)intensity); } int intersectObjects(Vec R0, Vec R1, double result[], int object, boolean shadowCheck) { double minDist=0.0, dist; int hit=-1; for(int i=0; i0.0)){ minDist = dist; hit = i; } else if((dist>0.0) && (dist