import java.awt.*;
import java.awt.event.*;
import java.applet.*;

// This example demonstrates the use of threads to simulate
// animation. Threads a re separate processes that can be
// created to run independantly of the rest of the applet
// (and not interfere with its running).

// This example rotates the plane around the axes at regular
// intervals. The direction and axis can be controlled by
// user mouse clicks.

public class VRTimer extends Applet
       implements MouseListener, Runnable {

  // These arrays define the X and Y cooridinates of the drawing.

  private int[] oldX={160, 100, 60, 60, 40, 40, 60, 60, 100, 160};
  private int[] oldY={100, 90, 40, 90, 90, 110, 110, 160, 110, 100};

  // Those coordinates will be transformed based on the current
  // rotation, and stored in this array (which will be used for
  // the actual drawing).

  private int[] X={160, 100, 60, 60, 40, 40, 60, 60, 100, 160};
  private int[] Y={100, 90, 40, 90, 90, 110, 110, 160, 110, 100};
  private int num = 10;

  private int pitch = 0; // Current rotation around the Y axis
  private int yaw = 0;   // Current rotation around the X axis

  // The increment (in degrees) that the drawing will be rotated
  // around the axes each interval.

  private int pitchInc = 0;
  private int yawInc = 5;

  private long delay = 50; // The delay (in ms) between each interval

  // This object is a reference to the separate thread that will
  // run the animation

  private Thread animateThread;

  public void init() {
    addMouseListener(this);
    }

  // The start method of the applet is called whenever the user starts or
  // restarts the page in some way. We use it to start the animation.

  public void start() { 
    animateThread = new Thread(this); // Construct the thread object.
    animateThread.start();     // Start the thread (this calls run)
    }

  // To be polite, we stop the thread (by setting it to null) when the
  // page is exited in any way.

  public void stop() {
    animateThread = null;
    }

  // The run method is called (as a separate process) when start is
  // executed. This is where we put the code to execute in the thread.

  public void run() {

    // Since we may create multiple threads (by stopping and restarting)
    // keep track of which thread this is.

    Thread currentThread = Thread.currentThread();

    // Loop forever (or at least until the thread is set to null, which
    // will mean that the condition will no longer be true).

    while (currentThread == animateThread) {

      // Inside the loop, we recalculate the pitch and yaw, repaint the
      // applet, and then sleep for the remainder of the delay. This
      // means that we wil have to keep track of how much time it took
      // to do the calculation and the repaint, and subtract from the
      // delay. We use System.currentTimeInMilis to get the system clock
      // time both before and after those steps.

      long startTime = System.currentTimeMillis(); // Time before repaint

      pitch = pitch + pitchInc; // Compute and repaint
      yaw = yaw + yawInc;
      repaint();

      long endTime = System.currentTimeMillis(); // Time after repaint

      long actualDelay = delay - (endTime - startTime); // Sleep time

      if (actualDelay > 0) { // Only sleep if time left

        // This try is required because the system may need to awaken
        // the thread for some reason (unlikely). In taht case, we just
        // break out of the loop.

        try {
          Thread.sleep(actualDelay); // Sleep for remaining delay
          }
        catch(InterruptedException ex) {break;}
        }
      }
    }

  public void paint(Graphics g) {

    // Recompute the contents of the X and Y array from the contents of
    // the oldX and oldY arrays (which store the original point coordinates)
    // using a simple trig transform.

    for (int i = 0; i < num; i++) {
      X[i] = 100 + (int)((oldX[i] - 100) * Math.cos(yaw * Math.PI / 180));
      Y[i] = 100 + (int)((oldY[i] - 100) * Math.cos(pitch * Math.PI / 180));
      }

    g.drawPolygon(X, Y, num);
    }

  public void mouseEntered(MouseEvent e) {}
  public void mouseExited(MouseEvent e) {}
  public void mousePressed(MouseEvent e) {}
  public void mouseReleased(MouseEvent e) {}

  // When the mouse is clicked, we check whether it is    \ top /
  // in the top, bottom, left, or right area of the        \   /
  // applet. If it is in the top or bottom, we rotate   left\ / right
  // + or - 15 degrees around the X axis. If it is in       / \
  // the left or right, we rotate + or - 15 degrees        /   \
  // around the Y axis.                                   /bottom\

  // This has been modified to change the direction of rotation.

  public void mouseClicked(MouseEvent e) {
    int x = e.getX();
    int y = e.getY();

    if (x < y && x < 200-y) { // left
      yawInc = 5;
      pitchInc = 0;
      pitch = 0;
      }
    if (x > y && x > 200-y) { // right
      yawInc = -5;
      pitchInc = 0;
      pitch = 0;
      }
    if (x > y && x < 200-y) { // top
      pitchInc = 5;
      yawInc = 0;
      yaw = 0;
      }
    if (x < y && x > 200-y) { // bottom
      pitchInc = -5;
      yawInc = 0;
      yaw = 0;
      }

    }

  }

