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(250,300); A=new Animator(); A=A.addMotionCanvas(M); C=new ControlCanvas(M); C.setBackground(Color.black); C.resize(250,51); 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 { int fore; int choice; int speed; Polyhedron[] Q=new Polyhedron[10]; Eye E; Block[] B=new Block[10]; Face[] F=new Face[10]; MotionCanvas() { addMouseListener(this); addMouseMotionListener(this); speed=100; E=new Eye(); E.p=new Vector(0,6,8); E.v=new Vector(0,1,-1); E.w=new Vector(1,1,1); E=E.orthogonal(); choice=1; Vector V1=new Vector(0,2,0); Vector W1=new Vector(3,1,3); B[1]=new Block(V1,W1); Q[1]=B[1].toPolyhedron(); Vector V2=new Vector(0,-3,0); Vector W2=new Vector(1,3,1); B[2]=new Block(V2,W2); Q[2]=B[2].toPolyhedron(); } public void paint(Graphics gfx) { Graphics2D g=(Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if(fore==0) { for(int j=1;j<=2;++j) E.render(g,Q[j]); } if(fore==1) { for(int j=1;j<=2;++j) E.render(g,Q[3-j]); } } 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() { E=E.forward((2*speed-75)/300.0); double d1=E.p.dist(E.p,B[1].v); double d2=E.p.dist(E.p,B[2].v); if(d1>d2) fore=0; if(d1<=d2) fore=1; } void reconstitute(int n) { if(n==1) { Vector V1=new Vector(0,-5,0); Vector W1=new Vector(1,1,1); B[1]=new Block(V1,W1); Q[1]=B[1].toPolyhedron(); Vector V2=new Vector(0,5,0); Vector W2=new Vector(1,1,1); B[2]=new Block(V2,W2); Q[2]=B[2].toPolyhedron(); } if(n==2) { Vector V1=new Vector(0,3,0); Vector W1=new Vector(3,1,3); B[1]=new Block(V1,W1); Q[1]=B[1].toPolyhedron(); Vector V2=new Vector(0,-3,0); Vector W2=new Vector(1,3,1); B[2]=new Block(V2,W2); Q[2]=B[2].toPolyhedron(); } if(n==3) { Vector V1=new Vector(0,2,0); Vector W1=new Vector(1,1,5); B[1]=new Block(V1,W1); Q[1]=B[1].toPolyhedron(); Vector V2=new Vector(0,-1,0); Vector W2=new Vector(5,1,1); B[2]=new Block(V2,W2); Q[2]=B[2].toPolyhedron(); } if(n==4) { Vector V1=new Vector(0,0,2); Vector W1=new Vector(4,4,1); B[1]=new Block(V1,W1); Q[1]=B[1].toPolyhedron(); Vector V2=new Vector(0,0,-2); Vector W2=new Vector(4,4,1); B[2]=new Block(V2,W2); Q[2]=B[2].toPolyhedron(); } } } class ControlCanvas extends DBCanvas implements MouseListener { MotionCanvas M; ListenSquare[] L=new ListenSquare[10]; ControlCanvas(MotionCanvas M) { addMouseListener(this); this.M=M; L[1]=new ListenSquare(150,0,50,25); L[2]=new ListenSquare(200,0,50,25); L[3]=new ListenSquare(150,25,100,25); L[4]=new ListenSquare(115,0,10,10); L[5]=new ListenSquare(130,0,10,10); L[6]=new ListenSquare(115,15,10,10); L[7]=new ListenSquare(130,15,10,10); } public void paint(Graphics gfx) { Graphics2D g=(Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); L[1].render(g,Color.red,Color.black); L[2].render(g,Color.red,Color.black); L[3].render(g,Color.blue,Color.black); for(int i=4;i<=7;++i) L[i].render(g,Color.yellow,Color.black); g.setColor(Color.yellow); g.fillRect(100+M.speed-1,30,2,15); g.setFont(new Font("Helvetica",Font.PLAIN,20)); g.drawString("Rich",13,21); g.drawString("Applet 38",7,41); } 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(); int test=0; for(int i=1;i<=7;++i) { if (L[i].inside(p)==1) test=i; } if(test==1) M.E=M.E.tilt(M.speed/200.0); if(test==2) M.E=M.E.tilt(-M.speed/200.0); if(test==3) M.speed=p.x-100; repaint(); if(test>=4) {M.reconstitute(test-3);} M.repaint(); } } class Block { Vector v,w; Block(Vector v,Vector w) { this.v=v; //center this.w=w; //dimensions } 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.red); 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.blue); 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.red); 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.blue); Polyhedron P=new Polyhedron(F,6); return(P); } } 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); } void print() { System.out.println(x+" "+y+" "+z); } } class Face { Vector[] V; Color C; int n; Face(Vector[] V,int n,Color C) { this.V=V; this.C=C; this.n=n; } int front(Eye E) { Vector W1=new Vector(); Vector W2=new Vector(); Vector W3=new Vector(); W1=W1.add(E.p,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; Eye(Vector p,Vector v,Vector w) { this.p=p; this.v=v; this.w=w; } Eye() { this.p=new Vector(); this.v=new Vector(); this.w=new Vector(); } Eye orthogonal() { Eye F=new Eye(); F.p=p; F.v=v.scale(1.0/v.norm()); double d=v.dot(v,w)/v.dot(v,v); F.w=v.add(w,v.scale(-d)); F.w=F.w.scale(1.0/F.w.norm()); return(F); } Eye forward(double d) { Eye F=new Eye(); Vector V=new Vector(); V=v.add(p,w.scale(d)); F.p=V.scale(10.0/V.norm()); F.v=F.p.scale(-.1); F.w=w; F=F.orthogonal(); return(F); } Eye tilt(double d) { Eye F=new Eye(); Vector V=new Vector(); V=V.cross(v,w); V=V.add(w,V.scale(d)); F.p=p; F.v=v; F.w=V; F=F.orthogonal(); return(F); } Vector see(Vector X) { double t; t=1-p.dot(v,v)/(p.dot(v,X)-p.dot(p,v)); Vector Y=new Vector(); Y=p.add(p.scale(t),X.scale(1-t)); Vector Z=p.add(Y,p.add(p,v.scale(-1))); Vector ww=p.cross(v,w); double a=p.dot(Z,w); double b=p.dot(Z,ww); Vector A=new Vector(); A.x=b; A.y=-a; A.z=1; return(A); } void render(Graphics g,Face F) { double cc=150; Vector W=new Vector(); int[] X=new int[F.n]; int[] Y=new int[F.n]; for(int i=1;i<=F.n;++i) { W=see(F.V[i]); X[i-1]=(int)(125+cc*W.x); Y[i-1]=(int)(125+cc*W.y); } g.setColor(F.C); g.fillPolygon(X,Y,F.n); } void borderRender(Graphics g,Face F) { double cc=150; Vector W=new Vector(); int[] X=new int[F.n]; int[] Y=new int[F.n]; for(int i=1;i<=F.n;++i) { W=see(F.V[i]); X[i-1]=(int)(125+cc*W.x); Y[i-1]=(int)(125+cc*W.y); } g.setColor(Color.black); g.drawPolygon(X,Y,F.n); } 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); } }