/** Main program to test ray tracer * Used to generate results table and images * Also shows how to use most features * @author: Phil Gage */ public class Test { static int width = 320, height = 200; // image size // static int width = 640, height = 480; // image size // static int frames = 1; static int frames = 10; // static int frames = 30; // static int frames = 100; // static int frames = 1000; // Turn on one at a time for timing static boolean doPan = false; // static boolean doPan = true; static boolean doZoom = false; // static boolean doZoom = true; // static boolean doAnimate = false; static boolean doAnimate = true; // Vary parameters for timing static boolean fastPan = false; // static boolean fastPan = true; static boolean fastZoom = false; // static boolean fastZoom = true; static boolean fastAnimate = false; // static boolean fastAnimate = true; // Idle camera to show erased boxes for Figure tbd static boolean doErasure = false; // static boolean doErasure = true; // Camera and viewport static AbstractCamera cam; static Viewport view; // Define scene layout static World buildWorld () { // Must create uniform spatial grid first Grid grid = new Grid ( new Extent ( new Point(-601.0, -600.0, -601.0), //min corner new Point( 601.0, 101.0, 701.0)), //max corner new VoxelIndex (15,10,15)); //voxel dimensions // World world = new World(); // no grid World world = new World(grid); // use grid // Define two light sources Light light = new Light( new Vector3(-100.0, -100.0, -50.0), new Color (0.8,0.8,0.8)); Light.ambient = new Color (0.2,0.2,0.2); world.add(light); world.add(new Light( new Vector3(100.0, -100.0, 50.0), new Color (0.8,0.8,0.8))); // Checkerboard ground plane double groundY = 100.0; //ground Y coord double groundsize = 500.0; //ground XZ range BoundedPlane ground = new BoundedPlane ( new Point(0.0, groundY, 0.0), //point on plane new Vector3(0.0, -1.0, 0.0), //normal new Extent (new Point(-groundsize, groundY-10, -groundsize), //min new Point(groundsize, groundY+10, groundsize)), //max new Color (1.0,1.0,1.0)); ground.setMaterial( new CheckerMaterial( //simple checker texture new Color (1.0,1.0,1.0), new Color (1.0,0.0,0.0), 100)); // gridSize world.add(ground); // Define some spheres Sphere s = new Sphere(new Point(10.0, 10.0, 500.0), 100.0, new Color (1.0,0.0,0.0)); s.material.ks = 0.9; //mirror s.material.kd = 0.1; //diffuse world.add(s); // Transparent yellow sphere Sphere s2 = new Sphere(new Point(100.0, 50.0, 300.0), 50.0, new Color (1.0,1.0,0.0)); s2.material.kt = 0.5; //transparency s2.material.kd = 0.5; //diffuse s2.material.specular = 2.0; //Phong world.add(s2); world.add( //green sphere new Sphere( new Point(-100.0, 50.0, 300.0), 50.0, new Color (0.0,1.0,0.0))); world.add( //blue sphere for shadow new Sphere( new Point(-100.0, -100.0, 400.0), 50.0, new Color (0.0,1.0,1.0))); // Saturn-like ring around mirror sphere world.add( new Ring (new Point(10.0, 10.0, 500.0), //center new Vector3(-0.2, -1.0, -0.2), //normal 170.0, 190.0, // innerRadius, outerRadius, new Color (1.0,0.5,0.0))); // Magenta triangle // Points, colors, etc can be created once and shared Point p1 = new Point(600.0, -400.0, 700.0); Point p2 = new Point(-150.0, 100.0, 500.0); Point p3 = new Point(500.0, 110.0, 600.0); Color triColor = new Color (1.0,0.1,1.0); world.add(new Polygon (p1, p2, p3, triColor)); // Red box Box box = new Box ( new Extent (new Point(-400.0, -100.0, 400.0), //min new Point( -300.0, 100.0, 500.0)), //max new Color (1.0,0.0,0.0)); world.add(box); //More stuff from InteractWorld: // Snowman // Snowman from Movie2 Color snow = new Color (1.5,1.5,1.5); world.add(new Sphere(new Point( 0.0, 50.0, -500.0), 50.0, snow)); //body world.add(new Sphere(new Point( 0.0, -20.0, -500.0), 40.0, snow)); world.add(new Sphere(new Point( 0.0, -80.0, -500.0), 30.0, snow)); //head world.add(new Sphere(new Point( 15.0, -90.0, -480.0), 8.0, new Color(0.0,0.0,0.0))); //eyes world.add(new Sphere(new Point(-15.0, -90.0, -480.0), 8.0, new Color (0.0,0.0,0.0))); //eyes world.add(new Sphere(new Point( 0.0, -81.0, -472.0), 6.0, new Color (0.5,0.1,0.0))); //nose world.add(new Sphere(new Point( 0.0, -70.0, -475.0), 5.0, new Color (0.0,0.0,0.0))); //mouth world.add(new Sphere(new Point( 10.0, -72.0, -477.0), 5.0, new Color (0.0,0.0,0.0))); //mouth world.add(new Sphere(new Point(-10.0, -72.0, -477.0), 5.0, new Color (0.0,0.0,0.0))); //mouth /* // Magenta Box Box box2 = new Box ( new Extent (new Point(-600.0, -100.0, -100.0), //min new Point(-400.0, 100.0, 100.0)), //max new Color (1.0,0.0,1.0)); box2.material.ks = 0.5; //mirror box2.material.kd = 0.5; //diffuse world.add(box2); */ // Pyramid Point top = new Point(-500.0, -100.0, 0.0); /* Point p11 = new Point(-600.0, 100.0, -100.0); Point p12 = new Point(-400.0, 100.0, -100.0); Point p13 = new Point(-400.0, 100.0, 100.0); Point p14 = new Point(-600.0, 100.0, 100.0); */ Point p11 = new Point(-500.0, 100.0, -200.0); Point p12 = new Point(-300.0, 100.0, 0.0); Point p13 = new Point(-500.0, 100.0, 200.0); Point p14 = new Point(-700.0, 100.0, 0.0); Color pColor = new Color (0.7,0.1,0.0); world.add(new Polygon (top, p11, p12, pColor)); world.add(new Polygon (top, p12, p13, pColor)); world.add(new Polygon (top, p13, p14, pColor)); world.add(new Polygon (top, p14, p11, pColor)); // Put sphere on top Sphere topsph = new Sphere(new Point(-500.0, -150.0, 0.0), 50.0, new Color (0.0,0.0,0.0)); topsph.material.ks = 0.9; //mirror topsph.material.kd = 0.1; //diffuse world.add(topsph); // Define pile of RGB spheres world.add(new Sphere(new Point(550.0, 0.0, 200.0), 100.0, new Color (1.0,0.0,0.0))); world.add(new Sphere(new Point(500.0, 0.0, 0.0), 100.0, new Color (0.0,1.0,0.0))); world.add(new Sphere(new Point(550.0, 0.0, -200.0), 100.0, new Color(0.0,0.0,1.0))); // Define transparent sphere on pile of RGB spheres Sphere st = new Sphere(new Point(530.0, -200.0, 0.0), 100.0, new Color (1.0,1.0,1.0)); st.material.ks = 0.8; //transparent st.material.kd = 0.2; world.add(st); // Lord of the Rings world.add( new Ring (new Point(500.0, -200.0, 0.0), //center new Vector3(-0.4, 0.2, 0.2), //normal 120.0, 150.0, // innerRadius, outerRadius, new Color (1.0,1.0,1.0))); // end stuff from InteractWorld // Define animated sphere class to test temporal coherence // To animate, extend class and override animate() class BouncingSphere extends Sphere { BouncingSphere () { super(new Point(0.0, 80.0, 300.0), 20.0, new Color (1.0,1.0,1.0)); // material.ks = 0.99; //mirror // material.kd = 0.01; // material.specular = 10.0; //Phong } // Override for animation boolean animate (int frame) { if (doAnimate) { // center.y += 100.0*(double)frame; center.y = 4.0*(double)frame*(double)(frames-frame)/(double)(frames*frames); // center.y = -300.0*center.y + 130.0; center.y = -200.0*center.y + 80.0; // center.y = -1.0*center.y + 130.0; //fig return true; } else return false; } } Sphere a = new BouncingSphere (); world.add(a); // Define animated camera to test fast pan class MovieCamera extends CylindricalCamera { double az = 0.0, el = 0.0; double fov = 90.0; // double fov = 180.0; //bigzoom MovieCamera (World world, int width, int height) { super (world, width, height); } // Override for animation void animate (int frame) { if (doPan) { // az = 1.0*(double)frame; az = 3.6*(double)frame; // 3.6*100=360 deg // az = 3.0*(double)frame; //fig // el = 1.0*(double)frame; // el = -3.0*(double)frame; //fig pan(az,el); } if (doZoom && !fastZoom) { // fov = 90.0 - (double)frame; //? fov = 90.0 - 45.0*(double)(frame)/(double)(frames); //? // fov = 180.0 - 1.7*(double)frame; //bigzoom zoom(fov); // field of view in degrees } // cam.translate(new Point(0.0,0.0,-3000.0)); // eye if (doErasure && frame>0) this.active = false; } } // If fast viewport zoom, make camera framebuffer larger if (doZoom && fastZoom) cam = new MovieCamera (world,2*width,2*height); else cam = new MovieCamera (world,width,height); world.add(cam); cam.zoom(100.0); // field of view in degrees cam.fastPan = fastPan; //set pan acceleration // Add temporal coherence acceleration if (fastAnimate) { cam.enableTemporalCoherence (16,16); } // Define viewport to test fast zoom class ZoomViewport extends Viewport { ZoomViewport (AbstractCamera camera, int width, int height) { super (camera, width, height); } // Override for animation void animate (int frame) { double scaleFactor = 1.0 + (double)frame/(double)frames; view.scale (scaleFactor, scaleFactor); view.translate (Test.width/2.0/scaleFactor,Test.height/2.0/scaleFactor); // view.rotate (5.0*(double)frame); //fig? } } // If fast viewport zoom, make viewport on camera framebuffer if (doZoom && fastZoom) { cam.fileOutput = false; //turn off camera file output cam.active = false; //camera ray trace on demand view = new ZoomViewport(cam,width,height); world.add(view); } return world; } /** * Main program for command line application. * @param argv command line argument strings */ public static void main (String[] argv) { System.out.println ("Ray tracing..."); // Define scene with lights, object, camera and viewport World world = buildWorld (); // Render each animation frame and perform raytracing for (int frame=0; frame