/*
	stereo 2 rotates 100 dots with sliders to manipulate the view
	shows anaglyph red/blue or black stereogram images
	
	Chris Thiel 2/28/2000 LaCaņada <cct@ktb.net>
*/

import java.awt.*;
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.event.*;
import java.lang.Math;

public class stereo2 extends Applet
{
	//Globals
	double ox[];// object space 
	double oy[];
	double oz[];
	double distance=6.0;	//depth of focus point
	double de = .5;         //delta horz viewpoint
	double df = 0.0;			//delta vert viewpoint
	double xl = -0.4 + de; 	//horz left eye
	double xr =  0.4 + de; 	//horz right
	double yl = 0.0;		//vert left	
	double yr = 0.0;		//vert right
	double E = 4;			//depth of "eyes"
	int sep = 80;			//separation of images
	double theta = 30;		//angle of rotation
	double degrees = Math.PI/180.0;
	// global states of controlers
	boolean dMoving=false;
	boolean EMoving=false;
	boolean FMoving=false;
	boolean sMoving=false;
	boolean rMoving=false;
	boolean color=true;
	boolean box=true;
	boolean dot=false;
	Rectangle colorbox, boxbox, dotbox;
	
	//int Z [] [];
	
	
	public void init() {
		double a,b,c;
		int i;
		setBackground(Color.white);
		ox = new double [108];
		oy = new double [108];
		oz = new double [108];
		colorbox = new Rectangle ( 467, 8, 10, 10);
		boxbox = new Rectangle ( 50, 8, 10, 10);
		dotbox = new Rectangle ( 200, 8, 10, 10);
		
		// cube 
		
		ox[0] = -1.0; oy[0] = -1.0 ; oz[0] = -1.0;
		ox[1] = -1.0; oy[1] =  1.0 ; oz[1] = -1.0;
		ox[2] =  1.0; oy[2] =  1.0 ; oz[2] = -1.0;
		ox[3] =  1.0; oy[3] = -1.0 ; oz[3] = -1.0;
		ox[4] = -1.0; oy[4] = -1.0 ; oz[4] =  1.0;
		ox[5] = -1.0; oy[5] =  1.0 ; oz[5] =  1.0;
		ox[6] =  1.0; oy[6] =  1.0 ; oz[6] =  1.0;
		ox[7] =  1.0; oy[7] = -1.0 ; oz[7] =  1.0;
		
		// 100 random dots in a shere
		
		for (i=8; i<108; i++){
			a=2*Math.random()-1;
		 	b=2*Math.random()-1;
		 	c=2*Math.random()-1;
			while ( a*a+b*b+c*c > 1) { // get a new batch if outside radius 1
				a=2*Math.random()-1;
				b=2*Math.random()-1;
				c=2*Math.random()-1;
			}
			ox[i]=a;
			oy[i]=b;
			oz[i]=c;
		}
		
		repaint();
	}
	public int prx ( int i) {
		//set rotation of this point
		double x = ox[i]* Math.cos(theta*degrees) + oz[i]*Math.sin(theta*degrees);
		double z = oz[i]* Math.cos(theta*degrees) - ox[i]*Math.sin(theta*degrees);
		// sets perspective of x of vertes a
		double dx = xr - x;
		double dz = distance - z;
		double a = x + ((dz - E)/dz) * dx;
		return (int)(220+sep + 60*a);	
	}
	public int pry ( int i) {
		//set rotation of this point
		double z = oz[i]* Math.cos(theta*degrees) - ox[i]*Math.sin(theta*degrees);
	
		// sets perspective of x of vertes a
		double dy = yr - oy[i];
		double dz = distance - z;
		 
		double a = oy[i] + ((dz - E)/dz) * dy;

		return (int)(150 - 60*a);	
	}
	public int plx ( int i) {
		//set rotation of this point
		double x = ox[i]* Math.cos(theta*degrees) + oz[i]*Math.sin(theta*degrees);
		double z = oz[i]* Math.cos(theta*degrees) - ox[i]*Math.sin(theta*degrees);
		// sets perspective of x of vertes a
		double dx = xl - x;
		double dz = distance - z;
		double a = x + ((dz - E)/dz) * dx;
		return (int)(220-sep + 60*a);	
	}
	public int ply ( int i) {
		//set rotation of this point
		double z = oz[i]* Math.cos(theta*degrees) - ox[i]*Math.sin(theta*degrees);
		
		// sets perspective of x of vertes a
		double dy = yl - oy[i];
		double dz = distance - z;
		 
		double a = oy[i] + ((dz - E)/dz) * dy;

		return (int)(150 - 60*a);	
	}
	public void paint( Graphics g ) {
		g.setColor(Color.orange);
		g.fillRect ( 450, 20, 145, 275);
		g.setColor(Color.black);
		g.drawString( "Use the sliders on the right to manipulate the object", 30, 30 );
		g.drawString("Blue-Red Anaglyth", 479, 18);
		g.drawString("box", 50+12, 18);
		g.drawString("dots", 200+12, 18);
		g.drawString("rotation", 455, 40);
		g.drawString("distance", 490, 30);
		g.drawString("view", 527, 40);
		g.drawString("separation", 540, 30);
		
		
		// checkboxes
		g.drawRect (colorbox.x, colorbox.y, colorbox.width, colorbox.height);
		g.drawRect (boxbox.x, boxbox.y, boxbox.width, boxbox.height);
		g.drawRect (dotbox.x, dotbox.y, dotbox.width, dotbox.height);
		
		if (color) {
			g.drawLine(colorbox.x, colorbox.y, colorbox.x+colorbox.width, colorbox.y+colorbox.height);
			g.drawLine(colorbox.x, colorbox.y+colorbox.height, colorbox.x+colorbox.width, colorbox.y);
			
		}
		if (box) {
			g.drawLine(boxbox.x, boxbox.y, boxbox.x+boxbox.width, boxbox.y+boxbox.height);
			g.drawLine(boxbox.x, boxbox.y+boxbox.height, boxbox.x+boxbox.width, boxbox.y);
			
		}
		if (dot) {
			g.drawLine(dotbox.x, dotbox.y, dotbox.x+dotbox.width, dotbox.y+dotbox.height);
			g.drawLine(dotbox.x, dotbox.y+dotbox.height, dotbox.x+dotbox.width, dotbox.y);
			
		}
		// Rails for controling sliders
		g.drawLine ( 475, 50, 475, 270);
		g.drawLine ( 505, 50, 505, 270);
		g.drawLine ( 530, 50, 530, 270);
		g.drawLine ( 555, 50, 555, 270);
		g.drawLine ( 580, 50, 580, 270);
		// labels for the sliders
		g.drawString (theta+"°", 458, 290);
		g.drawString (" "+distance, 495, 290);
		g.drawString (" "+de, 520, 290);
		g.drawString (" "+df, 542, 290);
		g.drawString (" "+sep, 570, 290);

		if (color) g.setColor(Color.cyan);
	    if (box) {// cube on left
			g.drawLine( plx(0), ply(0), plx(1), ply(1) ); 
			g.drawLine( plx(1), ply(1), plx(2), ply(2) ); 
			g.drawLine( plx(2), ply(2), plx(3), ply(3) ); 
			g.drawLine( plx(3), ply(3), plx(0), ply(0) ); 
			g.drawLine( plx(4), ply(4), plx(5), ply(5) ); 
			g.drawLine( plx(5), ply(5), plx(6), ply(6) ); 
			g.drawLine( plx(6), ply(6), plx(7), ply(7) ); 
			g.drawLine( plx(7), ply(7), plx(4), ply(4) ); 
			g.drawLine( plx(0), ply(0), plx(4), ply(4) ); 
			g.drawLine( plx(1), ply(1), plx(5), ply(5) ); 
			g.drawLine( plx(2), ply(2), plx(6), ply(6) ); 
			g.drawLine( plx(3), ply(3), plx(7), ply(7) ); 
			//x on back of cube
			g.drawLine( plx(0), ply(0), plx(2), ply(2) );
			g.drawLine( plx(1), ply(1), plx(3), ply(3) );
		}
		if (dot){// the dots
			for (int i=8; i<108; i++){
				g.fillOval(plx(i), ply(i), 2, 2);
		}}
		if (color) g.setColor(Color.red);
		if (box){//cube on right
			g.drawLine( prx(0), pry(0), prx(1), pry(1) ); 
			g.drawLine( prx(1), pry(1), prx(2), pry(2) ); 
			g.drawLine( prx(2), pry(2), prx(3), pry(3) ); 
			g.drawLine( prx(3), pry(3), prx(0), pry(0) ); 
			g.drawLine( prx(4), pry(4), prx(5), pry(5) ); 
			g.drawLine( prx(5), pry(5), prx(6), pry(6) ); 
			g.drawLine( prx(6), pry(6), prx(7), pry(7) ); 
			g.drawLine( prx(7), pry(7), prx(4), pry(4) ); 
			g.drawLine( prx(0), pry(0), prx(4), pry(4) ); 
			g.drawLine( prx(1), pry(1), prx(5), pry(5) ); 
			g.drawLine( prx(2), pry(2), prx(6), pry(6) ); 
			g.drawLine( prx(3), pry(3), prx(7), pry(7) ); 
		
			g.drawLine( prx(0), pry(0), prx(2), pry(2) );
			g.drawLine( prx(1), pry(1), prx(3), pry(3) );
		}
		if (dot){// the dots
			for (int i=8; i<108; i++){
				g.fillOval(prx(i), pry(i), 2, 2);
		}}
		
	
	g.setColor(Color.black);
		g.fillOval(472,50+(int)(0.61*theta), 7,5);
	g.setColor(Color.blue);
		g.fillOval(502,50+(int)(22.0*(distance-4.0)), 7,5);
		g.fillOval(527,50+(int)(55.0*(2+de)), 7,5);
		g.fillOval(552,50+(int)(55.0*(2+df)), 7,5);
	g.setColor(Color.gray);
		g.fillOval(577,50+(sep), 7,5);
		
	
	}
	/*
     * Mouse methods
     */
    public boolean mouseDown(java.awt.Event evt, int x, int y) {
      
       	if ( colorbox.inside(x,y) ) {  color=!color; } else {
        if ( dMoving || EMoving || FMoving || sMoving || rMoving) {
        	dMoving =false;
        	EMoving =false;
        	FMoving =false;
        	sMoving =false;
        	rMoving =false;
        } else {
      
        	if ( x > 470 && x < 480 ) { rMoving =true; }
        	if ( x > 500 && x < 510 ) { dMoving =true; }
        	if ( x > 525 && x < 535 ) { EMoving =true; }
        	if ( x > 550 && x < 560 ) { FMoving = true; }
        	if ( x > 575 && x < 585 ) { sMoving = true; }
        	
       }}
       if (boxbox.inside(x,y) ) box=!box;
       if (dotbox.inside(x,y) ) dot=!dot;
	 	
        repaint();
        return true;
    }
	
  	
  	
    public boolean mouseMove(java.awt.Event evt, int x, int y) {
        
        // getAppletContext().showStatus("Location of mouse: (" + x + ", " + y + ")");
        
         if (dMoving){
         	requestFocus();
        	distance = 4+(y-50)/22.0;
        	  
        	repaint();
         } else {
          if (rMoving){
          	requestFocus();
          	theta = (y-50)/0.61;
          	repaint();
          }else {
          if (EMoving){
         	requestFocus();
        	de = -2+(y-50)/55.0;  
        	xl = -0.4 + de;
			xr =  0.4 + de;
			
        	repaint();
        	
         } else {
         if (FMoving){
         	requestFocus();
        	df = -2+(y-50)/55.0;  
        	
			yl = df;
			yr = df;
        	repaint();
         }else {
          if (sMoving){
         	requestFocus();
        	sep = y - 50;  
        	repaint();
        	
         }}}}}
         
         
         
         //check for limits
         if (theta > 360) theta=360;
         if (theta < 0) theta=0;
         if (distance > 14) distance=14;
         if (distance < 4) distance=4;
         if (de >  2) de = 2.0;
         if (de < -2) de =-2.0;
         if (df >  2) df =  2.0;
         if (df < -2) df = -2.0;
         if (sep > 220) sep=220;
         if (sep < 0) sep =0;
         //smooth the reals
         theta = (int)(theta);
         distance = (int)(distance*10)/10.0;
         de = (int)(de*10)/10.0;
         df = (int)(df*10)/10.0;
        return true;
    }

    public void mouseEnter() {
        repaint();
    }

    public void mouseExit() {
       
        repaint();
    }

}
