// 3D Cube,  Evgeny Demidov, 11 Dec 2001
import java.awt.*;
import java.awt.event.*;
import java.util.StringTokenizer;
public class Cube extends java.applet.Applet
  implements MouseListener, MouseMotionListener{
  int w,h, h2,w2, mx0,my0, iCol[];
  int[][] Fx,Fy;
  double fiX = .2, fiY = .3, dfi = .01, scale;
  Image buffImage;     Graphics buffGraphics;
  Color[] col;

public void init() {
  w = getSize().width;  h=getSize().height;  h2=h/2; w2=w/2;
  iCol = new int[3];
  Fx = new int[3][];  Fy = new int[3][];
  for (int i = 0; i < 3; i++){ Fx[i] = new int[4]; Fy[i] = new int[4];}
  scale = w2 / 3.;
  col = new Color[256];
  for (int i = 0; i < 256; i++) col[i] = new Color(i, i, i);
//System.out.println(" Hi"+w+"  "+h);
  buffImage = createImage(w, h);   buffGraphics = buffImage.getGraphics();
  addMouseListener(this);   addMouseMotionListener(this);
  rotate();
}
public void destroy() {
  removeMouseListener(this);  removeMouseMotionListener(this);
}
public void mouseClicked(MouseEvent e){}       // event handling
public void mousePressed(MouseEvent e) {
  mx0 = e.getX();  my0 = e.getY();
  e.consume();
}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e)  {}
public void mouseDragged(MouseEvent e) {
  int x1 = e.getX();  int y1 = e.getY();
  fiY += dfi*(x1 - mx0);   mx0 = x1;
  fiX += dfi*(y1 - my0);   my0 = y1;
  rotate();
  repaint();
  e.consume();
}
public void mouseMoved(MouseEvent e) {}

public void rotate(){
  double ct = Math.cos(fiX), cf = Math.cos(fiY),
         st = Math.sin(fiX), sf = Math.sin(fiY),
         ix = scale*cf,                    kx =  scale*sf,
         iy = scale*st*sf, jy =  scale*ct, ky = -scale*st*cf,
         iz = -255*ct*sf,  jz = 255*st,    kz = 255*ct*cf;
  int  Vx[] = {(int)(ix+kx), (int)(ix+kx), (int)(ix-kx), (int)(ix-kx),
              (int)(-ix+kx),(int)(-ix+kx),(int)(-ix-kx),(int)(-ix-kx)},
  Vy[] = {(int)(iy+jy+ky), (int)(iy-jy+ky), (int)(iy-jy-ky), (int)(iy+jy-ky),
         (int)(-iy+jy+ky),(int)(-iy-jy+ky),(int)(-iy-jy-ky),(int)(-iy+jy-ky)},
  x0123[] = {Vx[0],Vx[1],Vx[2],Vx[3]}, y0123[] = {Vy[0],Vy[1],Vy[2],Vy[3]},
  x4567[] = {Vx[4],Vx[5],Vx[6],Vx[7]}, y4567[] = {Vy[4],Vy[5],Vy[6],Vy[7]},
  x0374[] = {Vx[0],Vx[3],Vx[7],Vx[4]}, y0374[] = {Vy[0],Vy[3],Vy[7],Vy[4]},
  x1265[] = {Vx[1],Vx[2],Vx[6],Vx[5]}, y1265[] = {Vy[1],Vy[2],Vy[6],Vy[5]},
  x0451[] = {Vx[0],Vx[4],Vx[5],Vx[1]}, y0451[] = {Vy[0],Vy[4],Vy[5],Vy[1]},
  x3762[] = {Vx[3],Vx[7],Vx[6],Vx[2]}, y3762[] = {Vy[3],Vy[7],Vy[6],Vy[2]};
  if (iz > 0){ Fx[0] = x0123; Fy[0] = y0123;}
  else{ Fx[0] = x4567; Fy[0] = y4567; iz = -iz;}
  if (jz > 0){ Fx[1] = x0374; Fy[1] = y0374;}
  else{ Fx[1] = x1265; Fy[1] = y1265; jz = -jz;}
  if (kz > 0){ Fx[2] = x0451; Fy[2] = y0451;}
  else{ Fx[2] = x3762; Fy[2] = y3762; kz = -kz;}
  iCol[0] = (int)iz;  iCol[1] = (int)jz;  iCol[2] = (int)kz;
}

public void paint(Graphics g) {
  int px[] = new int[4],  py[] = new int[4];
  buffGraphics.setColor(Color.blue);
  buffGraphics.fillRect(0, 0, w, h);
  for (int i = 0; i < 3; i++){
    for (int j = 0; j < 4; j++){
      px[j] = w2 + Fx[i][j];   py[j] = h2 - Fy[i][j];}
    buffGraphics.setColor(col[iCol[i]]);
    buffGraphics.fillPolygon(px,py, 4);}
  g.drawImage(buffImage, 0, 0, this);
  showStatus( "fiX=" + (int)(360*fiX) + "   fiY=" + (int)(360*fiY));
}
public void update(Graphics g)   {  paint(g);  }

}
