//
import render.*;

public class rosie1 extends RenderApplet
{
   Geometry wheel, hub, plate1, plate2, bearing;
   Geometry frame[] = new Geometry[3];
   Material frameColor, motorColor, plateColor, wheelColor, magnetColor;

   public void initialize() {

      // CREATE ALL THE SURFACE TYPES

      frameColor = new Material();
      frameColor.setColor(.2,.2,.2, .8,.8,.8,20).setAmbient(.1,.1,.1);
      frameColor.noiseA = 1;
      frameColor.noiseF = 2;

      plateColor = new Material();
      plateColor.setColor(.2,.15,.05, 1,.75,.25,10).setAmbient(.2,.15,.05);
      plateColor.noiseA = 1;
      plateColor.noiseF = 2;

      motorColor = new Material();
      motorColor.setColor(.18,.1,.05, .64,.4,.2,7).setColor(.17,.1,.05);

      wheelColor = new Material();
      wheelColor.setColor(.2,.1,.1, .6,.3,.3,10).setAmbient(.2,.1,.1);

      magnetColor = new Material();
      magnetColor.setColor(.3,0,0, .5,0,0,10);

      // CREATE THE TOP AND BOTTOM WOBBLING PLATES

      plate1 = makePlate(world.add().setMaterial(plateColor));
      plate2 = makePlate(world.add().setMaterial(plateColor));

      // CREATE THE THREE PARTS OF THE SUPPORT FRAME

      for (int i = 0 ; i < 3 ; i++) {
         frame[i] = makeFrame(world.add().setMaterial(frameColor));
         push();
	    rotateZ(i*2*Math.PI/3);
	    transform(frame[i]);
         pop();
      }

      // CREATE THE BALL BEARING BETWEEN THE TOP AND BOTTOM PLATES

      bearing = world.add().ball(10).setMaterial(frameColor);
      push();
         scale(.15,.15,.15);
         transform(bearing);
      pop();

      // CREATE THE BIG WHEEL

      wheel = world.add().ball(10).setMaterial(wheelColor);
      push();
         translate(0,0,-4.7);
	 rotateX(Math.PI/2);
	 scale(3,3,.2);
	 transform(wheel);
      pop();

      // CREATE THE HUB SUPPORT STRUTS

      hub = world.add().setMaterial(frameColor);
      hub.add().cylinder(20);
      push();
         translate(-.17,.6,-3);
	 rotateY(-.13);
	 rotateZ(Math.PI/6);
	 scale(.05,.3,1.6);
	 transform(hub.child[0]);
      pop();
      hub.add().cylinder(20);
      push();
         translate(-.17,-.6,-3);
	 rotateY(-.13);
	 rotateZ(-Math.PI/6);
	 scale(.05,.3,1.6);
	 transform(hub.child[1]);
      pop();

      // CREATE THE HUB SPHERE

      hub.add().globe(30,20, 0,1,0,.4);
      push();
         translate(0,0,-4.7);
	 rotateX(Math.PI/2);
	 scale(.9,.9,.9);
	 transform(hub.child[2]);
      pop();
      hub.add().globe(30,20, 0,1,.6,1);
      push();
         translate(0,0,-4.7);
	 rotateX(Math.PI/2);
	 scale(.9,.9,.9);
	 transform(hub.child[3]);
      pop();

      // CREATE THE HUB AXLE

      hub.add().cylinder(10);
      push();
         translate(0,0,-4.7);
	 rotateX(Math.PI/2);
	 scale(.2,.2,.6);
	 transform(hub.child[4]);
      pop();

      // SET THE CAMERA FIELD OF VIEW

      setFOV(1.1);
      renderer.isHeadsUp = true;

      // LIGHTS

      addLight( 1, 1, 1, 1,1,1);
      addLight(-1, 1, 1, 1,1,1);
      addLight( 1,-1, 1, 1,1,1);
      addLight(-1,-1, 1, 1,1,1);
      addLight( 1, 1,-1, 1,1,1);
      addLight(-1, 1,-1, 1,1,1);
      addLight( 1,-1,-1, 1,1,1);
      addLight(-1,-1,-1, 1,1,1);

      // WHITE BACKGROUND TO MATCH THE WEB PAGE

      setBgColor(1,1,1);
   }

   public void animate(double time) {
      double rate = 3;
      double tilt = .025;
      double s = tilt * Math.sin(rate*time);

      // ROTATE THE TWO FLYWHEELS

      push();
         rotateZ(1.5 * time);
	 transform(plate1.child[0]);
	 transform(plate2.child[0]);
      pop();

      // MAKE THE ENTIRE VEHICLE VIBRATE SLIGHTLY

      push();
         rotateX(-Math.PI/2);
	 translate(0,0,3);
	 translate(0,0,-8);
	 rotateX(.002*Math.sin(20*time));
	 rotateY(.002*Math.cos(20*time));
	 translate(0,0,8);
	 transform(world);
      pop();

      // MAKE THE TWO PLATES WOBBLE

      push();
	 rotateX(Math.PI);
         translate(0,0,.5);
	 rotateZ(-rate*time);
	 rotateY(s);
	 rotateZ(rate*time);
	 transform(plate1);
      pop();

      push();
         translate(0,0,.5);
	 rotateZ(rate*time);
	 rotateY(s);
	 rotateZ(-rate*time);
	 transform(plate2);
      pop();

      // BEND THE FRAME LINKAGE PARTS TO FOLLOW THE TWO WOBBLING PLATES

      for (int i = 0 ; i < 3 ; i++) {
         double t = Math.PI/4 - tilt*5/3 * Math.sin(2*rate*time-i*2*Math.PI/3);

	 animateLinkage(frame[i], t, 1, 0); // LINKAGE TO TOP PLATE
	 animateLinkage(frame[i], t,-1, 1); // LINKAGE TO BOTTOM PLATE
      }
   }

   // BEND THE FRAME LINKAGE PARTS TO FOLLOW A WOBBLING PLATE

   void animateLinkage(Geometry frame, double t, double s, int i) {
      push();
         translate(1.6,s*.07,0);
         rotateY(s*t);
         translate(-.2,0,0);
         push();
	    scale(1,.05,1);
	    rotateX(Math.PI/2);
	    transform(frame.child[i]);
         pop();
	 translate(-.2,-s*.14,0);
         rotateY(-2*s*t);
	 push();
	    scale(1,.05,1);
	    rotateX(Math.PI/2);
	    transform(frame.child[i+2]);
	 pop();
	 translate(.4,0,0);
	 push();
	    scale(.17,.17,.17);
	    transform(frame.child[i+4]);
	 pop();
      pop();
   }

   // CREATE THE PARTS FOR ONE WOBBLING PLATE

   Geometry makePlate(Geometry s) {

      // FLYWHEEL

      Geometry g;
      g = s.add().setMaterial(motorColor);
      for (int i = 0 ; i < 3 ; i++) {
         g.add().cylinder(18);
         push();
	    translate(0,0,.55);
	    rotateZ(i*Math.PI/3);
	    scale(2.05,.14,.14);
	    rotateY(Math.PI/2);
	    transform(g.child[i]);
         pop();
      }
      g.add().torus(18,24,.1);
      push();
	 translate(0,0,.55);
	 scale(2.05,2.05,1.4);
	 rotateZ(Math.PI/6);
	 //rotateY(Math.PI/2);
	 transform(g.child[3]);
      pop();

      // AXLE FROM MOTOR TO FLYWHEEL

      g = s.add().cylinder(10).setMaterial(frameColor);
      push();
         translate(0,0,.3);
	 scale(.07,.07,.4);
	 transform(g);
      pop();

      // THE PLATE

      g = s.add().cylinder(30);
      push();
         translate(0,0,.22);
         scale(1.8,1.8,.03);
	 transform(g);
      pop();

      // CONNECTION TO BALL BEARING

      g = s.add().cylinder(10);
      push();
         translate(0,0,-.11);
         scale(.22,.22,.32);
	 transform(g);
      pop();

      // MOTOR

      g = s.add().cylinder(20).setMaterial(motorColor);
      push();
         translate(0,0,-.1);
         scale(.5,.5,.3);
	 transform(g);
      pop();

      for (int i = 0 ; i < 3 ; i++) {

	 // BEARING CONNECTION TO FRAME LINKAGE

         g = s.add().globe(20,10,0,1,.4,1);
	 push();
	    rotateZ(i*2*Math.PI/3);
	    translate(1.6,-.07,.065);
            scale(.2,.2,.2);
	    rotateY(Math.PI/4);
	    transform(g);
	 pop();

	 // ELECTROMAGNET WINDINGS

         g = s.add().cylinder(10).setMaterial(magnetColor);
	 push();
	    rotateZ(Math.PI/3 + i*2*Math.PI/3);
	    translate(1,0,-.08);
            scale(.3,.3,.27);
	    transform(g);
	 pop();

	 // ELECTROMAGNET CORE

         g = s.add().cylinder(10).setMaterial(frameColor);
	 push();
	    rotateZ(Math.PI/3 + i*2*Math.PI/3);
	    translate(1,0,-.13);
            scale(.2,.2,.28);
	    transform(g);
	 pop();
      }
      return s;
   }

   // MAKE THE SUPPORT FRAME

   Geometry makeFrame(Geometry s) {
      Geometry g;

      // THE BENDABLE LINKAGES TO THE WOBBLING PLATES

      g = makeLink(s.add(),.2,.1);
      g = makeLink(s.add(),.2,.1);
      g = makeLink(s.add(),.4,.1);
      g = makeLink(s.add(),.4,.1);
      g = s.add().ball(10);
      g = s.add().ball(10);

      // THE STATIC SUPPORT FRAME

      g = makeLink(s.add(),.4,.1);
      push();
         translate(2,-.2,0);
	 scale(1,.05,1);
	 rotateX(Math.PI/2);
	 transform(g);
      pop();
      g = makeLink(s.add(),.4,.1);
      push();
         translate(2,.2,0);
	 scale(1,.05,1);
	 rotateX(Math.PI/2);
	 transform(g);
      pop();
      g = s.add().cube();
      push();
         translate(2.15,0,0);
         scale(.36,.26,.1);
	 transform(g);
      pop();
      g = s.add().cube();
      push();
         translate(2.4,0,-.6);
	 scale(.1,.15,.7);
	 transform(g);
      pop();
      g = s.add().cube();
      push();
         translate(1.25,0,-1.4);
	 scale(1.25,.15,.1);
	 transform(g);
      pop();
      return s;
   }

   // CREATE ONE LINK SHAPE WITH ROUNDED ENDS

   Geometry makeLink(Geometry s, double d, double r) {
      Geometry g;
      g = s.add().cube();
      push();
         scale(d,r,1);
	 transform(g);
      pop();
      g = s.add().cylinder(10);
      push();
         translate(d,0,0);
	 scale(r,r,1);
	 transform(g);
      pop();
      g = s.add().cylinder(10);
      push();
         translate(-d,0,0);
	 scale(r,r,1);
	 transform(g);
      pop();
      return s;
   }

   public void toggleOutline() {
      renderer.outline(-renderer.getOutline());
   }
}