import java.awt.*; import java.awt.event.*; /** Interactive ray tracing animation viewer * Master's Thesis, Univ of Colo, 2002 * @author: Phil Gage */ public class Interact extends Frame { /** Initialization flag */ boolean initialized = false; boolean initialized2 = false; /** Image pixmap for graphics */ Image img; Image img2; Frame viewportFrame; static Viewport viewport; // Ray trace globals // static int width = 160, height = 100; // image size static int width = 320, height = 200; // image size // static int width = 640, height = 480; // image size // World world; InteractWorld world; //temp AbstractCamera camera; double az = 0.0, el = 0.0, fov = 45.0, xc = 0.0, zc = 0.0; boolean changed = false; double scaleFactor = 2.0; //viewport double rotateFactor = 0.0; //viewport double xFactor = 0.0; double yFactor = 0.0; double panAngle = 45.0; boolean changed2 = false; static boolean doAnimate = false; /** Initialize world and camera once at start */ void init() { //System.out.println ("init"); // Must create uniform spatial grid first Grid grid = new Grid ( new Extent ( new Point(-901.0, -500.0, -901.0), //min corner new Point( 901.0, 101.0, 901.0)), //max corner new VoxelIndex (15,10,15)); //voxel dimensions // Define example scene // world = new InteractWorld (); world = new InteractWorld (grid); // Define Equal-Area camera that allows fast pan camera = new CylindricalCamera (world,width,height); camera.fileOutput = false; camera.enableTemporalCoherence (16,16); // camera.translate (new Point(xc, 0.0, zc)); world.add(camera); // Define Viewport on camera that allows fast zoom viewport = new Viewport(camera,width/2,height/2); viewport.fileOutput = false; world.add(viewport); // Perform first raytracing and get image world.animate (); if (camera != null) img = camera.framebuffer.getImage (this); if (viewport != null && viewportFrame != null) { img2 = viewport.framebuffer.getImage (viewportFrame); changed2 = true; initialized2 = true; } initialized = true; } /** * Method paint redraws window each time window is exposed. * This version saves graphics in images for fast redraw. * @param g graphics object */ public void paint (Graphics g) { //System.out.println ("paint"); // Initialize only once if (!initialized) init(); // Refresh image after window expose/resize event if (img != null) g.drawImage (img, 0, 0, getWidth(), getHeight(), this); // Init viewport image if not done if (!initialized2 && viewport != null && viewportFrame != null) { img2 = viewport.framebuffer.getImage (viewportFrame); changed2 = true; initialized2 = true; } } /** * Method update redraws window each time after repaint. * This overrides default method that erases window and. * causes an annoying flicker when white background shows. * @param g graphics object */ public void update (Graphics g) { //System.out.println ("update"); // If an action performed raytracing, get image and display if (changed) { System.out.println ("Image changed!"); img = camera.framebuffer.getImage (this); g.drawImage (img, 0, 0, getWidth(), getHeight(), this); img2 = viewport.framebuffer.getImage (viewportFrame); // Graphics g2 = viewportFrame.getGraphics(); // g2.drawImage (img2, 0, 0, getWidth(), getHeight(), viewportFrame); changed = false; repaint(); } if (doAnimate) { world.animate(); changed = true; } } /** Perform raytracing and request display update */ void redraw() { long msec = System.currentTimeMillis(); world.animate (); changed = true; repaint(); // trigger update() double secs = (System.currentTimeMillis() - msec)/1000.0; System.out.println("Secs: " + secs); } /** Create control window with action push buttons */ void createControls() { // Define names for buttons String buttonNames[] = {"Pan Left","Pan Right", "Tilt Down", "Tilt Up", "Zoom In", "Zoom Out", "Fast Pan", "Slow Pan", /* "Active", "Inactive",*/ "Large Pan", "Small Pan", "Fast Animate", "Slow Animate", "Animate On", "Animate Off", "Move Forward", "Move Backward", "Save File", "Reset", "Help"}; // Create window (frame) and panel for buttons Frame control = new Frame ("Camera Controls"); Panel panel = new Panel (); // Create button press event handler ActionListener actionListener = new ActionListener () { public void actionPerformed (ActionEvent e) { double zoomFactor = fov / 45.0; String cmd = e.getActionCommand(); System.out.println ("Command="+e.getActionCommand()); if (cmd.equals("Pan Left")) { // az -= 30.0*zoomFactor; az -= panAngle*zoomFactor; camera.pan(az,el); redraw(); } else if (cmd.equals("Pan Right")) { // az += 30.0*zoomFactor; az += panAngle*zoomFactor; camera.pan(az,el); redraw(); } else if (cmd.equals("Tilt Up")) { // el += 10.0*zoomFactor; el -= 10.0*zoomFactor; //temp camera.pan(az,el); redraw(); } else if (cmd.equals("Tilt Down")) { // el -= 10.0*zoomFactor; el += 10.0*zoomFactor; //temp camera.pan(az,el); redraw(); } else if (cmd.equals("Zoom In")) { if (fov>1.0) { fov /= 2.0; camera.zoom(fov); redraw(); } } else if (cmd.equals("Zoom Out")) { if (fov<359.0) { fov *= 2.0; camera.zoom(fov); redraw(); } } else if (cmd.equals("Fast Pan")) { camera.fastPan = true; } else if (cmd.equals("Slow Pan")) { camera.fastPan = false; } else if (cmd.equals("Large Pan")) { panAngle = 45.0; } else if (cmd.equals("Small Pan")) { panAngle = 1.0; } else if (cmd.equals("Fast Animate")) { camera.enableTemporalCoherence (16,16); camera.bitmap.clearBitmaps(); changed = true; camera.zoom(fov); //temp fix redraw(); } else if (cmd.equals("Slow Animate")) { camera.bitmap = null; //crude camera.raytracer.bitmap = null; redraw(); } else if (cmd.equals("Animate On")) { world.doAnimate = true; doAnimate = true; redraw(); } else if (cmd.equals("Animate Off")) { world.doAnimate = false; doAnimate = false; // redraw(); } else if (cmd.equals("Active")) { camera.active = true; redraw(); } else if (cmd.equals("Inactive")) { camera.active = false; //camera ray trace on demand camera.eraseImage(); //? redraw(); } else if (cmd.equals("Move Forward")) { double x = 200.0*Math.sin(az*Constants.DTOR)*zoomFactor; double z = 200.0*Math.cos(az*Constants.DTOR)*zoomFactor; xc += x; zc += z; camera.translate (new Point(xc, 0.0, zc)); redraw(); } else if (cmd.equals("Move Backward")) { double x = 200.0*Math.sin(az*Constants.DTOR)*zoomFactor; double z = 200.0*Math.cos(az*Constants.DTOR)*zoomFactor; xc -= x; zc -= z; camera.translate (new Point(xc, 0.0, zc)); redraw(); } else if (cmd.equals("Save File")) { camera.framebuffer.savetga("save.tga"); System.out.println ("Image saved to file: camera.tga"); } else if (cmd.equals("Reset")) { doAnimate = false; az = 0.0; el = 0.0; fov = 45.0; xc = 0.0; zc = 0.0; scaleFactor = 2.0; //viewport rotateFactor = 0.0; //viewport xFactor = 0.0; yFactor = 0.0; camera.zoom(fov); camera.pan(az,el); camera.translate (new Point(xc, 0.0, zc)); changed = true; redraw(); } else if (cmd.equals("Help")) { createCameraHelpFrame (); } else { System.out.println ("Unknown cmd: "+cmd); } } }; // Create buttons and add to panel Button button; for (int i=0; i2.0) { //autozoom // scaleFactor /= 2.0; // fov /= 2.0; // camera.zoom(fov); // redraw(); // } scaleFactor /= 1.2; viewport.scale(scaleFactor,scaleFactor); // redraw(); changed2 = true; } else if (cmd.equals("Zoom Out")) { // if (scaleFactor<1.0) { // scaleFactor *= 2.0; // fov *= 2.0; // camera.zoom(fov); // redraw(); // } scaleFactor *= 1.2; viewport.scale(scaleFactor,scaleFactor); // redraw(); changed2 = true; } else if (cmd.equals("Rotate Left")) { rotateFactor += 10.0; viewport.rotate(rotateFactor); // redraw(); changed2 = true; } else if (cmd.equals("Rotate Right")) { rotateFactor -= 10.0; viewport.rotate(rotateFactor); // redraw(); changed2 = true; } else if (cmd.equals("Cylindrical View")) { viewport.rectify = false; changed2 = true; } else if (cmd.equals("Standard View")) { viewport.rectify = true; changed2 = true; } else if (cmd.equals("Update Image")) { // redraw(); changed2 = true; } else if (cmd.equals("Save File")) { viewport.framebuffer.savetga("save2.tga"); System.out.println ("Image saved to file: viewport.tga"); } else if (cmd.equals("Help")) { createViewportHelpFrame (); } else { System.out.println ("Unknown cmd: "+cmd); } //??? // viewport.render(0); // Graphics g2 = viewportFrame.getGraphics(); // img2 = viewport.framebuffer.getImage (viewportFrame); // g2.drawImage (img2, 0, 0, getWidth(), getHeight(), viewportFrame); if (changed2) viewportFrame.repaint(); } }; // Create buttons and add to panel Button button; for (int i=0; i