import java.applet.Applet; import java.awt.*; import java.awt.event.*; public class test1 extends Applet { Animator A; MotionCanvas M; ControlCanvas C; public void init() { setBackground(Color.black); M=new MotionCanvas(); M.setBackground(Color.black); M.resize(300,300); A=new Animator(); C=new ControlCanvas(M); A=A.addMotionCanvas(M); A=A.addControlCanvas(C); C.setBackground(Color.black); C=C.addAnimator(A); C.resize(300,120); add(M); add(C); try {A.start();} catch(Exception e) {} } } class DBCanvas extends Canvas { public void update(Graphics g) { Graphics g2; Image offscreen = null; offscreen = createImage(size().width, size().height); g2 = offscreen.getGraphics(); paint(g2); g.drawImage(offscreen, 0, 0, this); g2.dispose(); offscreen.flush(); } } class MotionCanvas extends DBCanvas implements MouseListener, MouseMotionListener { Polyhedron[] Q=new Polyhedron[10]; Eye E; Face[] F=new Face[10]; Dodecahedron I; House B; Block[] Bl=new Block[10]; int state; MotionCanvas() { addMouseListener(this); addMouseMotionListener(this); E=new Eye(); E.p=new Vector(-8,0,6); E.v=new Vector(8,0,-6); E.w=new Vector(1,0,0); E=E.orthogonal(); Color[][] C=new Color[6][60]; for(int i=1;i<=2;++i) { C[1][6*i-5]=Color.yellow; C[1][6*i-4]=Color.cyan; C[1][6*i-3]=Color.orange; C[1][6*i-2]=Color.green; C[1][6*i-1]=Color.pink; C[1][6*i-0]=Color.magenta; } Vector P1=new Vector(0,0,0); Vector V1=new Vector(0,0,1); Vector W1=new Vector(1,0,0); I=new Dodecahedron(P1,V1,W1,C[1],1); Vector V2=new Vector(5,5,-2); B=new House(V2); Vector V3=new Vector(-2.5,-2.5,4.7); Vector W3=new Vector(.5,.5,.3); Bl[3]=new Block(V3,W3,3); Vector V4=new Vector(2.5,2.5,-1.7); Vector W4=new Vector(.5,.5,.3); Bl[4]=new Block(V4,W4,1); Q[1]=I.toPolyhedron(); Q[2]=B.toPolyhedron(); Q[3]=Bl[3].toPolyhedron(); Q[4]=Bl[4].toPolyhedron(); state=1; } public void paint(Graphics g) { double d1=E.p.dist(E.p,I.v); double d3=E.p.dist(E.p,Bl[3].v); double d4=E.p.dist(E.p,Bl[4].v); E.render(g,Q[2]); if((d1<=d3)&&(d3<=d4)) { E.render(g,Q[4]); E.render(g,Q[3]); E.render(g,Q[1]); } if((d3<=d1)&&(d1<=d4)) { E.render(g,Q[4]); E.render(g,Q[1]); E.render(g,Q[3]); } if((d4<=d3)&&(d3<=d1)) { E.render(g,Q[1]); E.render(g,Q[3]); E.render(g,Q[4]); } if((d3<=d4)&&(d4<=d1)) { E.render(g,Q[1]); E.render(g,Q[4]); E.render(g,Q[3]); } if((d1<=d4)&&(d4<=d3)) { E.render(g,Q[3]); E.render(g,Q[4]); E.render(g,Q[1]); } if((d4<=d1)&&(d1<=d3)) { E.render(g,Q[3]); E.render(g,Q[1]); E.render(g,Q[4]); } } public void mouseClicked(MouseEvent e) {} public void mouseDragged(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseMoved(MouseEvent e) {} void evolve() { Bl[3]=Bl[3].evolve(-2.5,2.5,-2.5,2.5,.2); Q[3]=Bl[3].toPolyhedron(); Bl[4]=Bl[4].evolve(-2.5,2.5,-2.5,2.5,.2); Q[4]=Bl[4].toPolyhedron(); I=I.evolve(.01); Q[1]=I.toPolyhedron(); } } class ControlCanvas extends DBCanvas implements MouseListener, MouseMotionListener { MotionCanvas M; double scale; ListenSquare[] L=new ListenSquare[30]; Animator A; ControlCanvas(MotionCanvas M) { addMouseListener(this); addMouseMotionListener(this); this.M=M; scale=10; } ControlCanvas addAnimator(Animator A) { ControlCanvas X=this; X.A=A; return(X); } public void paint(Graphics g) { g.setFont(new Font("Helvetica",Font.PLAIN,20)); g.setColor(Color.white); g.drawString("Rich",120,20); g.drawString("Applet 39",120,40); g.setFont(new Font("Helvetica",Font.PLAIN,15)); g.drawString("click/drag the mouse", 120,75); g.drawString("over the blue disk to", 120, 90); g.drawString("change the view",120,105); g.setColor(Color.blue); g.fillOval(10,10,100,100); g.drawOval(10,10,100,100); g.setColor(Color.black); g.drawOval(55,55,10,10); g.fillOval(55,55,10,10); int x=(int)(5*(-M.E.p.x+12)); int y=(int)(5*(-M.E.p.y+12)); g.setColor(Color.yellow); g.fillOval(y-2,x-5,4,4); g.drawOval(y-2,x-5,4,4); } public void mouseMoved(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseEntered(MouseEvent e) { } public void mouseClicked(MouseEvent e) { e.consume(); Point p=new Point(); p.x=e.getX(); p.y=e.getY(); double tt=(p.x-60)*(p.x-60)+(p.y-60)*(p.y-60); if((tt<2490)&&(tt>25)) { M.E.p.x=-p.y/5.0+12; M.E.p.y=-p.x/5.0+12; M.E.p.z=Math.sqrt(100-M.E.p.x*M.E.p.x-M.E.p.y*M.E.p.y); M.E=M.E.orthogonal(); } M.repaint(); repaint(); } public void mouseDragged(MouseEvent e) { e.consume(); Point p=new Point(); p.x=e.getX(); p.y=e.getY(); double tt=(p.x-60)*(p.x-60)+(p.y-60)*(p.y-60); if((tt<2490)&&(tt>25)) { M.E.p.x=-p.y/5.0+12; M.E.p.y=-p.x/5.0+12; M.E.p.z=Math.sqrt(100-M.E.p.x*M.E.p.x-M.E.p.y*M.E.p.y); M.E=M.E.orthogonal(); } repaint(); M.repaint(); } } class House { Vector v,w; House(Vector v) { this.v=v; //center } Polyhedron toPolyhedron() { Vector[][][] V=new Vector[16][16][16]; double d1=1; double d2=1; double d3=1; double d4=1; Face F[]=new Face[150]; Color C=Color.red; int test=0; for(int i=0;i<=11;++i) { for(int j=0;j<=11;++j) { d1=v.x*(i-5.5); d2=v.x*(j-5.5); d3=d1+v.x; d4=d2+v.y; V[i][j][1]=v.make(d1,d2,v.z); V[i][j][2]=v.make(d1,d4,v.z); V[i][j][3]=v.make(d3,d4,v.z); V[i][j][4]=v.make(d3,d2,v.z); C=new Color(0,0,200); test=(i+j); test=test=test-2*(test/2); if(test==0) C=new Color(0,0,100); F[12*i+j+1]=new Face(V[i][j],4,C); } } Polyhedron P=new Polyhedron(F,144); return(P); } } class Block { Vector v,w; int state; Block(Vector v,Vector w,int s) { this.v=v; //center this.w=w; //dimensions this.state=s; } Polyhedron toPolyhedron() { Vector[][][] V=new Vector[3][3][3]; double dist[][][]=new double[3][3][3]; double record=100; double d1=1; double d2=1; double d3=1; for(int i=1;i<=2;++i) { for(int j=1;j<=2;++j) { for(int k=1;k<=2;++k) { d1=3-2*i; d2=3-2*j; d3=3-2*k; V[i][j][k]=new Vector(v.x+d1*w.x,v.y+d2*w.y,v.z+d3*w.z); } } } Face F[]=new Face[7]; Vector W[][]=new Vector[7][5]; W[1][1]=V[1][1][1]; W[1][2]=V[1][1][2]; W[1][3]=V[1][2][2]; W[1][4]=V[1][2][1]; F[1]=new Face(W[1],4,Color.yellow); W[2][1]=V[2][1][1]; W[2][2]=V[2][1][2]; W[2][3]=V[1][1][2]; W[2][4]=V[1][1][1]; F[2]=new Face(W[2],4,Color.cyan); W[3][1]=V[1][1][1]; W[3][2]=V[1][2][1]; W[3][3]=V[2][2][1]; W[3][4]=V[2][1][1]; F[3]=new Face(W[3],4,Color.magenta); W[4][1]=V[2][1][1]; W[4][2]=V[2][2][1]; W[4][3]=V[2][2][2]; W[4][4]=V[2][1][2]; F[4]=new Face(W[4],4,Color.yellow); W[5][1]=V[1][2][2]; W[5][2]=V[2][2][2]; W[5][3]=V[2][2][1]; W[5][4]=V[1][2][1]; F[5]=new Face(W[5],4,Color.cyan); W[6][1]=V[1][1][2]; W[6][2]=V[2][1][2]; W[6][3]=V[2][2][2]; W[6][4]=V[1][2][2]; F[6]=new Face(W[6],4,Color.magenta); Polyhedron P=new Polyhedron(F,6); return(P); } Block evolve(double xm,double xM,double ym,double yM,double d) { Block Bl=new Block(v,w,state); int temp=state; if(state==1) Bl.v.x=v.x-d; if(state==3) Bl.v.x=v.x+d; if(state==2) Bl.v.y=v.y-d; if(state==4) Bl.v.y=v.y+d; if((state==1)&&(Bl.v.xxM)) ++temp; if((state==2)&&(Bl.v.yyM)) temp=1; Bl.state=temp; return(Bl); } } class Dodecahedron { Vector p,v,w; Color[] C; int state; Dodecahedron(Vector p,Vector v,Vector w,Color[] C,int s) { this.p=p; this.v=v; this.w=w; this.C=C; this.state=s; } Polyhedron toPolyhedron() { Vector[] X=new Vector[50]; X[1]=v; X[12]=X[1].scale(-1.0); X[13]=w; X[14]=X[1].cross(X[1].unit(),X[13]); /***define the vertices of an icosahedron**/ double ii=0; double cos=1; double sin=0; for(int i=1;i<=5;++i) { ii=i; cos=Math.cos(2*Math.PI*ii/5.0); sin=Math.sin(2*Math.PI*ii/5.0); X[1+i]=p.add(X[13].scale(cos),X[14].scale(sin)); } int mod1=0; int mod2=0; int mod3=0; double x=Math.cos(2*Math.PI/5); for(int i=1;i<=5;++i) { cos=Math.sqrt((1-2*x-x*x)/(1-2*x)); sin=Math.sqrt(x*x/(1-2*x)); X[1+i]=p.add(X[1+i].scale(cos),X[1].scale(sin)); X[i+6]=X[1+i].scale(-1); } for(int j=1;j<=12;++j) { X[j]=X[j].add(X[j],p); } /****define the vertices of the dodecahedron***/ Vector[][] W=new Vector[21][7]; for(int i=1;i<=5;++i) { W[i][1]=X[1]; mod1=1+i; mod2=2+i; if(mod2==7) mod2=2; W[i][2]=X[mod1]; W[i][3]=X[mod2]; } for(int i=1;i<=5;++i) { mod1=1+i; mod2=2+i; if(mod2>6) mod2=mod2-5; mod3=9+i; if(mod3>11) mod3=mod3-5; W[5+i][1]=X[mod2]; W[5+i][2]=X[mod1]; W[5+i][3]=X[mod3]; } for(int i=1;i<=5;++i) { mod1=11-i; if(mod1<7) mod1=mod1+5; mod2=10-i; if(mod2<7) mod2=mod2+5; mod3=3-i; if(mod3<2) mod3=mod3+5; W[10+i][1]=X[mod2]; W[10+i][2]=X[mod1]; W[10+i][3]=X[mod3]; } for(int i=1;i<=5;++i) { W[15+i][1]=X[12]; mod1=11-i; mod2=10-i; if(mod1<7) mod1=mod1+5; if(mod2<7) mod2=mod2+5; W[15+i][2]=X[mod1]; W[15+i][3]=X[mod2]; } for(int i=1;i<=20;++i) { W[i][0]=v.add(W[i][1],W[i][2]); W[i][0]=v.add(W[i][0],W[i][3]); } /***faces of dodecahedron ****/ Face F[] =new Face[21]; Vector[][] Y=new Vector[13][6]; Y[1][5]=W[1][0]; Y[1][4]=W[2][0]; Y[1][3]=W[3][0]; Y[1][2]=W[4][0]; Y[1][1]=W[5][0]; F[1]=new Face(Y[1],5,C[1]); Y[2][1]=W[1][0]; Y[2][2]=W[2][0]; Y[2][3]=W[7][0]; Y[2][4]=W[15][0]; Y[2][5]=W[6][0]; F[2]=new Face(Y[2],5,C[2]); Y[3][1]=W[2][0]; Y[3][2]=W[3][0]; Y[3][3]=W[8][0]; Y[3][4]=W[14][0]; Y[3][5]=W[7][0]; F[3]=new Face(Y[3],5,C[3]); Y[4][1]=W[3][0]; Y[4][2]=W[4][0]; Y[4][3]=W[9][0]; Y[4][4]=W[13][0]; Y[4][5]=W[8][0]; F[4]=new Face(Y[4],5,C[4]); Y[5][1]=W[4][0]; Y[5][2]=W[5][0]; Y[5][3]=W[10][0]; Y[5][4]=W[12][0]; Y[5][5]=W[9][0]; F[5]=new Face(Y[5],5,C[5]); Y[6][1]=W[5][0]; Y[6][2]=W[1][0]; Y[6][3]=W[6][0]; Y[6][4]=W[11][0]; Y[6][5]=W[10][0]; F[6]=new Face(Y[6],5,C[6]); Y[7][1]=W[20][0]; Y[7][2]=W[19][0]; Y[7][3]=W[18][0]; Y[7][4]=W[17][0]; Y[7][5]=W[16][0]; F[7]=new Face(Y[7],5,C[7]); Y[8][5]=W[20][0]; Y[8][4]=W[19][0]; Y[8][3]=W[14][0]; Y[8][2]=W[7][0]; Y[8][1]=W[15][0]; F[8]=new Face(Y[8],5,C[11]); Y[9][5]=W[16][0]; Y[9][4]=W[20][0]; Y[9][3]=W[15][0]; Y[9][2]=W[6][0]; Y[9][1]=W[11][0]; F[9]=new Face(Y[9],5,C[10]); Y[10][5]=W[17][0]; Y[10][4]=W[16][0]; Y[10][3]=W[11][0]; Y[10][2]=W[10][0]; Y[10][1]=W[12][0]; F[10]=new Face(Y[10],5,C[9]); Y[11][5]=W[18][0]; Y[11][4]=W[17][0]; Y[11][3]=W[12][0]; Y[11][2]=W[9][0]; Y[11][1]=W[13][0]; F[11]=new Face(Y[11],5,C[8]); Y[12][5]=W[19][0]; Y[12][4]=W[18][0]; Y[12][3]=W[13][0]; Y[12][2]=W[8][0]; Y[12][1]=W[14][0]; F[12]=new Face(Y[12],5,C[12]); Polyhedron P=new Polyhedron(F,12); return(P); } Dodecahedron evolve(double d) { Dodecahedron D=new Dodecahedron(p,v,w,C,state); int temp=state; if(state==1) D.p.z=p.z+d; if(state==2) D.p.z=p.z-d; if((state==1)&&(D.p.z>1)) ++temp; if((state==2)&&(D.p.z<0)) temp=1; D.state=temp; return(D); } } class Vector { double x,y,z; Vector() { this.x=0; this.y=0; this.z=0; } Vector(double x,double y,double z) { this.x=x; this.y=y; this.z=z; } Vector make(double x,double y,double z) { Vector V=new Vector(); V.x=x; V.y=y; V.z=z; return(V); } Vector cross(Vector V,Vector W) { Vector X=new Vector(); X.x=V.y*W.z-V.z*W.y; X.y=V.z*W.x-V.x*W.z; X.z=V.x*W.y-V.y*W.x; return(X); } double dot(Vector V,Vector W) { double d=0; d=V.x*W.x+V.y*W.y+V.z*W.z; return(d); } Vector scale(double t) { Vector W=new Vector(); W.x=t*this.x; W.y=t*this.y; W.z=t*this.z; return(W); } Vector add(Vector V,Vector W) { Vector X=new Vector(); X.x=V.x+W.x; X.y=V.y+W.y; X.z=V.z+W.z; return(X); } double norm() { double d=Math.sqrt(this.dot(this,this)); return(d); } double dist(Vector V,Vector W) { Vector X=new Vector(); X=X.add(V,W.scale(-1.0)); double d=X.norm(); return(d); } Vector normalize() { Vector X=this; X.x=x/z; X.y=y/z; X.z=1; return(X); } Vector unit() { Vector W=new Vector(); double d=this.norm(); W=this.scale(1.0/d); return(W); } void print() { System.out.println(x+" "+y+" "+z); } Vector ortho(Vector v) { Vector w=new Vector(); w=w.add(this,v.scale(-w.dot(v,this))); return(w.unit()); } } class Face { Vector[] V; Color C; int n; Face(Vector[] V,int n,Color C) { this.V=V; this.C=C; this.n=n; } Face() {} int front(Eye E) { Vector pp=E.p.scale(E.dist); Vector W1=new Vector(); Vector W2=new Vector(); Vector W3=new Vector(); W1=W1.add(pp,V[1].scale(-1)); W2=W2.add(V[2],V[1].scale(-1)); W3=W3.add(V[3],V[1].scale(-1)); double d=W1.dot(W1,W1.cross(W2,W3)); int test; test=0; if(d>0) test=1; return(test); } } class Polyhedron { Face[] F; int n; Polyhedron(Face[] F,int n) { this.F=F; this.n=n; } Polyhedron() {} } class Eye { Vector p,v,w; double dist; Eye(Vector p,Vector v,Vector w) { this.p=p; this.v=v; this.w=w; this.dist=1.0; } Eye() { this.p=new Vector(); this.v=new Vector(); this.w=new Vector(); this.dist=1.0; } Eye orthogonal() { Eye F=new Eye(); F.p=p; F.v=p.scale(-1.0/p.norm()); Vector w1=new Vector(0,0,1); F.w=w1.ortho(F.v); F.dist=dist; return(F); } Vector see(Vector X) { double t; Vector A=new Vector(); Vector pp=p.scale(dist); t=1-p.dot(v,v)/(p.dot(v,X)-p.dot(pp,v)); if((t>0)&&(t<1)) { Vector Y=new Vector(); Y=p.add(pp.scale(t),X.scale(1-t)); Vector Z=p.add(Y,p.add(pp,v.scale(-1))); Vector ww=p.cross(v,w); double a=p.dot(Z,w); double b=p.dot(Z,ww); A.x=b; A.y=-a; A.z=1; } if((t>=1)||(t<=0)) {A=A.make(0,0,-1);} return(A); } void render(Graphics g,Face F) { double cc=250; Vector W=new Vector(); int[] X=new int[F.n]; int[] Y=new int[F.n]; int count=0; for(int i=1;i<=F.n;++i) { W=see(F.V[i]); if(W.z!=-1) { X[count]=(int)(150+cc*W.x); Y[count]=(int)(150+cc*W.y); ++count; } } g.setColor(F.C); g.fillPolygon(X,Y,count); } void borderRender(Graphics g,Face F) { double cc=250; Vector W=new Vector(); int[] X=new int[F.n]; int[] Y=new int[F.n]; int count=0; for(int i=1;i<=F.n;++i) { W=see(F.V[i]); if(W.z!=-1) { X[count]=(int)(150+cc*W.x); Y[count]=(int)(150+cc*W.y); ++count; } } g.setColor(Color.black); g.drawPolygon(X,Y,count); } void render(Graphics g,Polyhedron P) { for(int i=1;i<=P.n;++i) { if(P.F[i].front(this)==1) render(g,P.F[i]); } for(int i=1;i<=P.n;++i) { if(P.F[i].front(this)==1) borderRender(g,P.F[i]); } for(int i=1;i<=P.n;++i) { if(P.F[i].front(this)==0) render(g,P.F[i]); } for(int i=1;i<=P.n;++i) { if(P.F[i].front(this)==0) borderRender(g,P.F[i]); } } } class ListenSquare { double x1,x2; double y1,y2; ListenSquare(double x1,double y1,double x2,double y2) { this.x1=x1; this.x2=x2; this.y1=y1; this.y2=y2; } int inside(Point p) { int val; val=1; if(p.x<=this.x1) val=0; if(p.x>this.x1+this.x2) val=0; if(p.y<=this.y1) val=0; if(p.y>this.y1+this.y2) val=0; return(val); } void render(Graphics g,Color C1,Color C2) { int xx1,yy1,xx2,yy2; xx1=(int)(this.x1); yy1=(int)(this.y1); xx2=(int)(int)(this.x2); yy2=(int)(int)(this.y2); g.setColor(C1); g.fillRect(xx1,yy1,xx2,yy2); g.setColor(C2); g.drawRect(xx1,yy1,xx2,yy2); } } class Animator extends Thread { MotionCanvas M; ControlCanvas C; public void run() { while(true) { M.evolve(); M.repaint(); try {sleep(5);} catch(Exception e) {} } } Animator addMotionCanvas(MotionCanvas M) { Animator B=this; B.M=M; return(B); } Animator addControlCanvas(ControlCanvas C) { Animator B=this; B.C=C; return(B); } }