/*

import java.awt.*;
import java.util.*;
import java.applet.*;
import java.lang.*;


public class CG_hw04 extends BufferedApplet {

	double xy[][]= {{0,0,0,1},{1,1,1,1},{2,2,2,2},{1,2,3,4}};
	
	double[][] matrix = new double[4][4];
	
	double[][] thighMatrix = new double[4][4];
	double[][] legMatrix = new double[4][4];
	double[][] footMatrix = new double[4][4];
	double[][] bigBellyMatrix = new double[4][4];
	double[][] headMatrix = new double[4][4];
	double[][] shoulderMatrix = new double[4][4];
	double[][] armMatrix = new double[4][4];
	double[][] handMatrix = new double[4][4];
	double[][] earMatrix = new double[4][4];
	
	double theta2=Math.PI/8;
	double dx=.1;
	
	double temp[];
	
	public void render(Graphics g) 
	{
		// WHENEVER THERE IS "DAMAGE", WE NEED TO REDRAW

		if (damage) 
		{	
   			g.setColor(Color.white);
         	g.fillRect(0, 0, bounds().width, bounds().height);
   			
   			g.setColor(Color.green);
   			

     		Matrix3D.identity(headMatrix);

     		
     		
  			
   			
   	
 //  			ParametricTorus head = new ParametricTorus(0.07,0.05);
   			
   			
   			ParametricSphere head = new ParametricSphere(0,0,0,.3);
   	
   	   		Matrix3D.zRotate(headMatrix,theta2);
   			Matrix3D.yRotate(headMatrix,theta2);
   			Matrix3D.translate(headMatrix,dx,0,0);		
   			Matrix3D.scale(headMatrix,.1,1,.1);
   			head.draw(g,headMatrix);
   			
   			

  			

   			Matrix3D.yRotate(headMatrix,Math.PI/8);
   			Matrix3D.xRotate(headMatrix,theta2);
   			Matrix3D.scale(headMatrix,2,2,4);
  // 			Matrix3D.translate(headMatrix,.16,-.09,0);
   			head.draw(g,headMatrix);  


   			theta2+=Math.PI/50;
   		
 

   			
   			
		
   		}
   		animating = true;
   		

	}
	


}


import java.awt.*;
import java.util.*;

public class CG_hw04 extends BufferedApplet
{
	
// Render Method

	double theta;
	int n = 0;
	Matrix3D m = new Matrix3D();
	double matrix[][] = new double[4][4];

   public void render(Graphics g) 
   {
	   	if (damage)
	   	{
	   		clearScreen(g);
			int width = bounds().width;
			int height = bounds().height;
			m.identity(matrix);
			
	   		if (n == 0)
	   		{
	   			theta = 0;
	   			n++;
	   		}
	   		else
	   		{
//	   			theta += Math.PI/80;	
	   		}
	   		

			m.xRotate(matrix,theta+2*Math.PI/80);
			m.yRotate(matrix,theta);
			m.zRotate(matrix,theta);
			m.scale(matrix,.45,.45,.45);
		   	g.setColor(Color.magenta);
		   	ParametricSphere sphere2 = new ParametricSphere(0,0,0,.45);
		   	sphere2.draw(g,matrix);
		   	
		    m.identity(matrix);
		   	m.zRotate(matrix,theta+Math.PI/80);
		   	m.yRotate(matrix,theta+Math.PI/80);
		   	m.scale(matrix,.75,.75,.75);
		   	g.setColor(Color.blue);
		   	ParametricSphere sphere1 = new ParametricSphere(0,0,0,.45);
		   	sphere1.draw(g,matrix);

			m.identity(matrix);
			m.yRotate(matrix,theta);	
		   	g.setColor(Color.red);
		   	ParametricSphere sphere = new ParametricSphere(0,0,0,.45);
		   	sphere.draw(g,matrix);
		   	
		   	g.setColor(Color.magenta);
			g.drawRect(0,0,400-1,400-1);
		   	
		   	animating = true;
	   }
   }

// Clear Screen Method

	public void clearScreen(Graphics g)
	{
		g.setColor(Color.black);
		g.fillRect(0,0,400,400);
	}
	
// Viewpoint Methods

	public double viewPortX(double x)
	{
		return (bounds().width * x + bounds().width/2);	
	} 
	
	public double viewPortY(double y)
	{
		return (-(bounds().height * y) + bounds().height/2);
	}
	
// Mouse and Keyboard Methods

   public boolean mouseMove(Event e, int x, int y) 
   {

      return true;
   }
   
   public boolean mouseDown(Event e, int x, int y) 
   {
   		return true;
   	}
   
   public boolean mouseDrag(Event e, int x, int y) 
   {
		return true;
   }
   
   public boolean mouseUp(Event e, int x, int y) 
   {
		return true;
   }
   
   public boolean keyUp(Event e, int key) 
   {
		return true;
   }
}



*/





import java.awt.*;
import java.util.*;
import java.applet.*;
import java.lang.*;


public class CG_hw04 extends BufferedApplet {

	double xy[][]= {{0,0,0,1},{1,1,1,1},{2,2,2,2},{1,2,3,4}};
	
	double[][] matrix = new double[4][4];
	
	double[][] thighMatrix = new double[4][4];
	double[][] legMatrix = new double[4][4];
	double[][] footMatrix = new double[4][4];
	double[][] bigBellyMatrix = new double[4][4];
	double[][] headMatrix = new double[4][4];
	double[][] shoulderMatrix = new double[4][4];
	double[][] armMatrix = new double[4][4];
	double[][] handMatrix = new double[4][4];
	double[][] earMatrix = new double[4][4];
	
	
	double temp[];
	
	public void render(Graphics g) 
	{
		// WHENEVER THERE IS "DAMAGE", WE NEED TO REDRAW

		if (damage) 
		{	
   			g.setColor(Color.white);
         	g.fillRect(0, 0, bounds().width, bounds().height);
   			
   			g.setColor(Color.green);
   			
	
     		Matrix3D.identity(matrix);
     		Matrix3D.identity(thighMatrix);
     		Matrix3D.identity(legMatrix);
     		Matrix3D.identity(footMatrix);
     		Matrix3D.identity(bigBellyMatrix);
     		Matrix3D.identity(headMatrix);
     		Matrix3D.identity(shoulderMatrix);
     		Matrix3D.identity(armMatrix);
     		Matrix3D.identity(handMatrix);
     		Matrix3D.identity(earMatrix);
     		
     		
     		
     		
   			ParametricATorus thigh = new ParametricATorus(0.07,0.3);
   			ParametricATorus leg = new ParametricATorus(0.07,0.3);
   			ParametricATorus foot = new ParametricATorus(0.04,0.02);
   			
   			Matrix3D.zRotate(thighMatrix,Math.PI/2);
   			Matrix3D.xRotate(thighMatrix,Math.PI/4);
   			Matrix3D.translate(thighMatrix,-.48,0,0);
   			Matrix3D.scale(thighMatrix,2.2,1,1);   			
   			thigh.draw(g, thighMatrix);
   			

  			Matrix3D.zRotate(legMatrix,Math.PI/2);
   			Matrix3D.xRotate(legMatrix,Math.PI/8);
   			Matrix3D.scale(legMatrix,1.5,1,1);
   			Matrix3D.translate(legMatrix,-.45,0,0);
   			leg.draw(g,legMatrix);
   			
  			Matrix3D.zRotate(footMatrix,Math.PI/6);
   			Matrix3D.xRotate(footMatrix,Math.PI/6);
   			Matrix3D.scale(footMatrix,.9,.6,.5);
   			Matrix3D.translate(footMatrix,-.47,-1.25,0);
   			foot.draw(g,footMatrix);
   			
   			
   			
   			
   			
     		Matrix3D.identity(thighMatrix);
     		Matrix3D.identity(legMatrix);
     		Matrix3D.identity(footMatrix);   			
   			
   			
   			Matrix3D.zRotate(thighMatrix,Math.PI/2);
   			Matrix3D.xRotate(thighMatrix,Math.PI/4);
   			Matrix3D.translate(thighMatrix,-.48,-.25,0);
   			Matrix3D.scale(thighMatrix,2.2,1,1);   			
   			thigh.draw(g, thighMatrix);
   			


  			Matrix3D.zRotate(legMatrix,Math.PI/2);
   			Matrix3D.xRotate(legMatrix,Math.PI/8);
   			Matrix3D.scale(legMatrix,1.5,1,1);
   			Matrix3D.translate(legMatrix,-.45,-.19,0);
   			leg.draw(g,legMatrix);
   			
  			Matrix3D.zRotate(footMatrix,Math.PI/.55);
   			Matrix3D.xRotate(footMatrix,Math.PI/6);
   			Matrix3D.scale(footMatrix,.9,.6,.5);
			Matrix3D.translate(footMatrix,.67,-1.04,0);
   			leg.draw(g,footMatrix);
   			
   			
   			
   			ParametricATorus bigBelly = new ParametricATorus(0.07,0.02);
   			ParametricATorus head = new ParametricATorus(0.07,0.02);
   			
   			
   			double theta2=Math.PI/8;
   			
   			Matrix3D.zRotate(bigBellyMatrix,Math.PI/2);
   			Matrix3D.xRotate(bigBellyMatrix,theta2);
   			Matrix3D.scale(bigBellyMatrix,3,7,3);
   			Matrix3D.translate(bigBellyMatrix,-.042,-.013,0);
   		//	bigBelly.draw(g,bigBellyMatrix);  
   			
   			theta2+=.5;			
   			

   			Matrix3D.zRotate(headMatrix,Math.PI/2);
   			Matrix3D.xRotate(headMatrix,Math.PI/8);
   			Matrix3D.scale(headMatrix,2,1,4);
   			Matrix3D.translate(headMatrix,.16,-.09,0);
   			head.draw(g,headMatrix);  
   			
   			
   			ParametricATorus ear = new ParametricATorus(0.07,0.02);
   			
  			Matrix3D.zRotate(earMatrix,Math.PI/.55);
   			Matrix3D.xRotate(earMatrix,Math.PI/6);
   			Matrix3D.scale(earMatrix,.9,.6,.5);
			Matrix3D.translate(earMatrix,-.35,.55,0); 	
			ear.draw(g,earMatrix);					

  			Matrix3D.zRotate(earMatrix,Math.PI/2.35);
   			Matrix3D.xRotate(earMatrix,Math.PI/8);
   			Matrix3D.scale(earMatrix,1.6,.6,.5);
			Matrix3D.translate(earMatrix,.26,-.48,0); 	
			ear.draw(g,earMatrix);


   			
   			ParametricATorus shoulder = new ParametricATorus(0.07,0.02);
   			ParametricATorus arm = new ParametricATorus(0.07,0.02);
   			ParametricATorus hand = new ParametricATorus(0.07,0.02);
   			
   			
   			
   			Matrix3D.zRotate(shoulderMatrix,Math.PI/3.2);
   			Matrix3D.xRotate(shoulderMatrix,Math.PI/13);
   			Matrix3D.translate(shoulderMatrix,-.15,.1,0);
   			Matrix3D.scale(shoulderMatrix,1.5,.8,1);   			
   			shoulder.draw(g, shoulderMatrix); 
   		
   			Matrix3D.zRotate(shoulderMatrix,Math.PI/2);
   			Matrix3D.xRotate(shoulderMatrix,Math.PI/30);
   			Matrix3D.translate(shoulderMatrix,-.56,-.21,0);
   			Matrix3D.scale(shoulderMatrix,1.85,.8,1);   			
   			shoulder.draw(g, shoulderMatrix);
   			
   			Matrix3D.zRotate(armMatrix,Math.PI/.3);
  			Matrix3D.yRotate(shoulderMatrix,Math.PI/5);
   			Matrix3D.translate(armMatrix,-.2,.45,0);
   			Matrix3D.scale(armMatrix,1,1.3,1);   			
   			arm.draw(g, armMatrix);
   	
   			
   			Matrix3D.zRotate(handMatrix,Math.PI/2);
   			Matrix3D.xRotate(handMatrix,Math.PI/9);
   			Matrix3D.scale(handMatrix,.7,.9,.7);
			Matrix3D.translate(handMatrix,0.09,-.42,0.73); 
			hand.draw(g,handMatrix);
   			
   			
   			
   			Matrix3D.zRotate(armMatrix,Math.PI/8);
   			Matrix3D.translate(armMatrix,.32,-.571,0);
   			Matrix3D.scale(armMatrix,1,1,1);   			
   			arm.draw(g, armMatrix);
   			
   			
   			
   			Matrix3D.identity(handMatrix);			
   			Matrix3D.zRotate(handMatrix,Math.PI/6);
  			Matrix3D.yRotate(handMatrix,Math.PI/3);
   			Matrix3D.xRotate(handMatrix,Math.PI/3);
   			Matrix3D.scale(handMatrix,.5,.6,.5);
			Matrix3D.translate(handMatrix,-.25,-.64,-.02); 
			hand.draw(g,handMatrix);
			
			g.setColor(Color.red);			
   			

   			
   			int X[]={400,390,410};
   			int Y[]={70,80,80};
   			
   			int A[]={357,347,367};
   			int B[]={70,80,80};
   			
   			int E[]={379,373,385};
   			int F[]={80,100,100};
   			
   			
    		int C[]={360,380,400,380};
   			int D[]={100,110,100,120}; 
   			
   			g.drawPolygon(X,Y,3);
   			g.drawPolygon(A,B,3);
   			
   			g.drawPolygon(E,F,3);   			
   			g.drawPolygon(C,D,4); 			
   			
   			g.setColor(Color.green);
   			
   			animating = true;
		
   		}
   		
   		

	}
	


}




class ParametricASphere extends ParametricASurface
{
	static double cx, cy, cz,r;
	static double theta;
	static double phi;
	
	public ParametricASphere(double cx, double cy, double cz, double r)
	{
		this.cx=cx;
		this.cy=cy;
		this.cz=cz;
		this.r=r;
	}
	
	public static void draw(Graphics g, double matrix[][])
	{
		double e=0.05;
		for (double v = 0 ; v < 1 ; v += e)
   			for (double u = 0 ; u < 1 ; u += e)
      			drawQuad(g,matrix, x(u,v),y(u,v),z(u,v),x(u+e,v),y(u+e,v),z(u+e,v),x(u+e,v+e),y(u+e,v+e),z(u+e,v+e),x(u,v+e),y(u,v+e),z(u,v+e));
    }
    
	public static double x(double u, double v) 
	{ 
		theta = 2*Math.PI*u; 
		phi = (Math.PI*v) - (Math.PI/2); 
		return r*Math.cos(theta)*Math.cos(phi) + cx; 
	}
	
	public static double y(double u, double v) 
	{ 
		phi = (Math.PI*v)-(Math.PI/2); 
		return r*Math.sin(phi) + cy; 
	}
	
	public static double z(double u, double v) 
	{ 
		theta = 2*Math.PI*u;
		phi = (Math.PI*v)-(Math.PI/2); 
		return -r*Math.sin(theta)*Math.cos(phi) + cz; 
	}	
	
}







class ParametricASurface
{
	static double temp[][];
	static double quad[][]= new double [4][4];
	
	static double xy[][]=new double[4][3];
	
	static int X[] = new int[4];
	static int Y[] = new int[4];
	
	
	static double theta;
	static double phi;
	
	
	public static void draw(Graphics g, double matrix[][])
	{
		double e=0.05;
		for (double v = 0 ; v < 1 ; v += e)
   			for (double u = 0 ; u < 1 ; u += e)
      			drawQuad(g,matrix,x(u,v),y(u,v),z(u,v),x(u+e,v),y(u+e,v),z(u+e,v),x(u+e,v+e),y(u+e,v+e),z(u+e,v+e),x(u,v+e),y(u,v+e),z(u,v+e));
    }

	
	public static void drawQuad(Graphics g, double matrix[][],double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, double x4, double y4, double z4)
	{
		
  		
   		
		quad[0][0]=x1;
		quad[0][1]=y1;
		quad[0][2]=z1;
		quad[0][3]=1;
		
		quad[1][0]=x2;
		quad[1][1]=y2;
		quad[1][2]=z2;
		quad[1][3]=1;
		
		quad[2][0]=x3;
		quad[2][1]=y3;
		quad[2][2]=z3;
		quad[2][3]=1;
		
		quad[3][0]=x4;
		quad[3][1]=y4;
		quad[3][2]=z4;
		quad[3][3]=1;
		
   		
   			
 		
   		for(int i=0;i<4;i++)
   			Matrix3D.transform(quad[i],xy[i],matrix);
  		for (int i = 0 ; i < 4 ; i++)
       	{
     		X[i] = (int) viewPortX(xy[i][0]);
      		Y[i] = (int) viewPortY(xy[i][1]);
   		}
   		
 		
  		g.drawPolygon(X,Y,4); 	
  		
   		
   			
		
	}
		
		
	public static double x(double u,double v)
	{
		return u;
		
	}
	
	public static double y(double u,double v)
	{
		return v;
	}
	
	public static double z(double u,double v)
	{
		return (u+v);
	}

	public static double viewPortX(double x)
	{

		return (650 * x + 650/2);	
	} 
	
	public static double viewPortY(double y)
	{

		return (-(500 * y) +500/2);
	} 
	
}




class ParametricATorus extends ParametricASurface
{
	static double R,r;
	static double theta;
	static double phi;
	static double e=0.05;
	
	public ParametricATorus(double R, double r)
	{
		this.R=R;
		
		this.r=r;
	}
	
	public static void draw(Graphics g, double matrix[][])
	{
		
		for (double v = 0 ; v < 1 ; v += e)
   			for (double u = 0 ; u < 1 ; u += e)
      			drawQuad(g,matrix,x(u,v),y(u,v),z(u,v),x(u+e,v),y(u+e,v),z(u+e,v),x(u+e,v+e),y(u+e,v+e),z(u+e,v+e),x(u,v+e),y(u,v+e),z(u,v+e));
    }
 
	public static double x(double u,double v)
	{
		theta=2*Math.PI*u;
		phi=2*Math.PI*v;
		return (Math.cos(theta)*(R+(r*Math.cos(phi))));
		
	}
	
	public static double y(double u,double v)
	{
		phi=2*Math.PI*v;
		return (r*Math.sin(phi));
	}
	
	public static double z(double u,double v)
	{
		theta=2*Math.PI*u;
		phi=2*Math.PI*v;
		return (-Math.sin(theta)*(R+(r*Math.cos(phi))));
	}
		
	
}


