/* App3DRotate.java 
 * Author: David Wanqian Liu
 * Date: Dec 20, 1995
 */


import java.applet.Applet;
import java.awt.*;
import java.io.*;
import java.net.*;



public class  App3DRotate extends Applet implements Runnable {
  Model3DPolyMesh model;
  Matrix3D tmat = new Matrix3D();
  Vertex origin;

  String message = null;
  boolean norotate = false;


  public void init() {
    String srot = getParameter("norotate");
    if (srot != null)
      norotate = srot.startsWith("t");

    String modelname = getParameter("model");
    if (modelname == null)
      modelname = "model.obj";

    resize(size().width <= 20 ? 400 : size().width,
	   size().height <= 20 ? 400 : size().height);

    InputStream is = null;

    /* Read input data file, create 3D model, and scale the model to
       the size of Applet */
    try {
      Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
      is = new URL(getDocumentBase(), modelname).openStream();

      Model3DInputFilePolyMesh polymesh = new Model3DInputFilePolyMesh(is);
      model = new Model3DPolyMesh(polymesh.vertices, polymesh.nvertices,
				  polymesh.edges, polymesh.nedges,
				  polymesh.faces, polymesh.nfaces);
      origin = model.defineBB(size().width, size().height);

      /* Init the model with some angle */
      tmat.unit();
      tmat.translate(-origin.x, -origin.y, -origin.z);
      tmat.yrot(45.0f);
      tmat.xrot(90.0f);
      tmat.translate(origin.x, origin.y, origin.z);
      model.transform(tmat);

    } catch(Exception e) {
      model = null;
      message = e.toString();
      e.printStackTrace();
    }

    /* Close input data file */
    try {
      if (is != null) is.close();
    } catch(Exception e) {
    }
  }


  Thread artist=null;

  public void start() {
    if (artist == null) {
      artist = new Thread(this);
      artist.start();
    }
  }
  
  public void stop() {
    artist.stop();
    artist = null;
  }
  
  public void run() {
    while (artist != null) {
      proc();

      try {Thread.sleep(100);} 
      catch (InterruptedException e){}
    }
    artist = null;
  }
  
  public synchronized void proc() {
    if (norotate) {
      repaint();
      return;
    }

    if (message != null) {
      repaint();
      return;
    }

    /* Create tranformation matrix to rotate the model */
    tmat.unit();
    tmat.translate(-origin.x, -origin.y, -origin.z);
    tmat.xrot(-90.0f);
    tmat.yrot(-45.0f);
    tmat.xrot(5.0f);
    tmat.yrot(45.0f);
    tmat.xrot(90.0f);
    tmat.translate(origin.x, origin.y, origin.z);
      
    model.transform(tmat);
    
    repaint();
  }    


  int prevx, prevy;
  float xtheta, ytheta;

  public boolean mouseDown(Event e, int x, int y) {
    prevx = x;
    prevy = y;
    return true;
  }


  public boolean mouseDrag(Event e, int x, int y) {
    if (message != null) {
      repaint();
      return true;
    }

    float xtheta = (prevy - y) * 360.0f / size().width;
    float ytheta = (prevx - x) * 360.0f / size().height;

    /* Create tranformation matrix to rotate the model */
    tmat.unit();
    tmat.translate(-origin.x, -origin.y, -origin.z);
    tmat.xrot(xtheta);
    tmat.yrot(ytheta);
    tmat.translate(origin.x, origin.y, origin.z);
	
    model.transform(tmat);
    
    repaint();

    prevx = x;
    prevy = y;

    return true;
  }

  /* Double buffering for update */
  Image offscreen;
  Graphics offgraphics;
  Dimension offscreensize;


  public synchronized void update(Graphics g) {
  
    /* Create an image buffer for updating screen */
    Dimension d = size();
    if ((offscreen == null) ||
        (d.width != offscreensize.width) ||
        (d.height != offscreensize.height)) {
      offscreen = createImage(d.width, d.height);
      offscreensize = d;
      offgraphics = offscreen.getGraphics();
      offgraphics.setFont(getFont());
    }

    /* Use the last used color to fill the background.
       This will give the effect of laser reflecting from the sphere.
       */
    offgraphics.fillRect(0, 0, d.width, d.height);

    if (model != null) {
      model.paint(offgraphics);
      g.drawImage(offscreen, 0, 0, null);
    } 

    if (message != null) {
      g.drawString("Error in model:", 5, 20);
      g.drawString(message, 15, 40);
    }
  }
}
