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

public class ThreeDCanvas extends Canvas {
   Button exitbutton, objbutton;
   OOGL_OFF current;
   boolean painted = true;
   Matrix3D amat, tmat;
   float xfac, scalefudge;
   Image offScrImage;
   Dimension offScrSize;
   Graphics offScrGC;
   int prevx, prevy;

   ThreeDCanvas() {
     super();
   }

   ThreeDCanvas(OOGL_OFF obj) {
     setObject(obj);
   }

   public Dimension minimumSize() {
     Dimension dim = new Dimension(10,10);
     return dim;
   }

   public Dimension preferredSize() {
     return minimumSize();
   }

   public void setObject(OOGL_OFF obj) {
     float xw, yw, zw;

     current = null;
     scalefudge = 0.1f;
     amat = null; tmat = null;
     amat = new Matrix3D();
     tmat = new Matrix3D();

     current = obj;
     current.findBB();
     xw = current.xmax - current.xmin;
     yw = current.ymax - current.ymin;
     zw = current.zmax - current.zmin;
/*
     System.out.println("xw =" + String.valueOf(xw) +
     			" yw =" + String.valueOf(yw) +
     			" zw =" + String.valueOf(zw));
*/
     if (yw > xw) xw = yw;
     if (zw > xw) xw = zw;
     float f1 = 250 / xw;
     float f2 = 250 / xw;
     xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge;
     offScrImage = createImage(size().width, size().height);
     offScrSize = new Dimension(size().width, size().height);
     offScrGC = offScrImage.getGraphics();

     repaint();

   }


   public final synchronized void update (Graphics theG)
   {
      Dimension d = size();
      if((offScrImage == null) || (d.width != offScrSize.width) ||
         (d.height != offScrSize.height))
        {
          offScrImage = createImage(d.width, d.height);
          offScrSize = d;
          offScrGC = offScrImage.getGraphics();
          offScrGC.setFont(getFont());
        }
      if (offScrGC != null) {
        offScrGC.fillRect(0,0,d.width, d.height);
        paint(offScrGC);
        theG.drawImage(offScrImage, 0, 0, null);
      }
   }

   public void paint(Graphics g) {
     if (current != null) {
       current.mat.unit();
       current.mat.translate(-(current.xmin + current.xmax) / 2,
                        -(current.ymin + current.ymax) / 2,
                        -(current.zmin + current.zmax) / 2);
       current.mat.mult(amat);
/*
       current.mat.scale(xfac, -xfac, 8 * xfac / size().width);
       current.mat.scale(xfac, -xfac, 16 * xfac / size().width);
*/
       int scale = (int)( xfac * size().width / 25 );
       current.mat.scale(scale, scale, 16 * xfac / size().width);
       current.mat.translate(size().width / 2, size().height / 2, 8);
       current.transformed = false;
       g.setColor(Color.black);
       g.fillRect(0,0,size().width,size().height);
       current.paint(g);
       setPainted();
     }
   }

   void setPainted() {
     painted = true;
     notifyAll();
   }

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

   public boolean mouseDrag(Event e, int x, int y) {
     tmat.unit();
     float xtheta = (prevx - x) * 360.0f / size().width;
     float ytheta = (prevy - y) * 360.0f / size().height;
     tmat.xrot(ytheta);
     tmat.yrot(xtheta);
     amat.mult(tmat);

     if (painted) {
       painted = false;
       repaint();
     }
     prevx = x; prevy = y;
     return true;
   }

}
