import java.awt.*; import java.applet.*; import java.awt.event.*; public class DullBall extends Applet implements Runnable,MouseListener,MouseMotionListener { static final int L=100; static final int R=21; static final int N=30; static final int D=1024; static final double G=0.2; static final int[][][] frame={ {{-1,-1,-1},{-1,-1,1}}, {{-1,-1,1},{-1,1,1}}, {{-1,1,1},{-1,1,-1}}, {{-1,1,-1},{-1,-1,-1}}, {{-1,-1,-1},{1,-1,-1}}, {{-1,-1,1},{1,-1,1}}, {{-1,1,1},{1,1,1}}, {{-1,1,-1},{1,1,-1}}, {{1,-1,-1},{1,-1,1}}, {{1,-1,1},{1,1,1}}, {{1,1,1},{1,1,-1}}, {{1,1,-1},{1,-1,-1}} }; Cluster cluster; Matrix matrix; int last_x,last_y; boolean running; Image image; double a,b,c; boolean circle; int width,height; public void init() { setBackground(Color.white); addMouseListener(this); addMouseMotionListener(this); } public synchronized void start() { cluster=new Cluster(); matrix=new Matrix(1); a=0; b=G; c=0; if (!running) { running=true; new Thread(this,"Physics").start(); } } public void stop() { running=false; } public void run() { while (running) { for (int t=0;t<100;t++) synchronized (this) { cluster.step(a,b,c,0.8*(100-t)/100); } repaint(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public void mousePressed(MouseEvent e) { last_x=e.getX(); last_y=e.getY(); circle= Math.pow(last_x-width/2,2)+Math.pow(last_y-height/2,2) >3*Math.pow(L*D/(D+L),2); } public void mouseReleased(MouseEvent e) { if (circle) { circle=false; repaint(); } } public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseClicked(MouseEvent e) {} public void mouseMoved(MouseEvent e) {} public void mouseDragged(MouseEvent e) { if (circle) matrix.rotate(0,0, Math.atan2(last_x-width/2,last_y-height/2) -Math.atan2(e.getX()-width/2,e.getY()-height/2)); else matrix.rotate( Math.PI*(e.getY()-last_y)/L/2, -Math.PI*(e.getX()-last_x)/L/2, 0 ); a=matrix.applyInverseX(0,G,0); b=matrix.applyInverseY(0,G,0); c=matrix.applyInverseZ(0,G,0); repaint(); last_x=e.getX(); last_y=e.getY(); } public void update(Graphics g) { paint(g); } void drawFrame(Graphics g,boolean foreground) { g.setColor(Color.darkGray); for (int i=0;i<12;i++) { double x1=L*matrix. applyX(frame[i][0][0],frame[i][0][1],frame[i][0][2]); double y1=L*matrix. applyY(frame[i][0][0],frame[i][0][1],frame[i][0][2]); double z1=L*matrix. applyZ(frame[i][0][0],frame[i][0][1],frame[i][0][2]); double x2=L*matrix. applyX(frame[i][1][0],frame[i][1][1],frame[i][1][2]); double y2=L*matrix. applyY(frame[i][1][0],frame[i][1][1],frame[i][1][2]); double z2=L*matrix. applyZ(frame[i][1][0],frame[i][1][1],frame[i][1][2]); if ((z1+z2<0)==foreground) { double m1=D/(z1+D); double m2=D/(z2+D); g.drawLine( (int)(x1*m1),(int)(y1*m1), (int)(x2*m2),(int)(y2*m2)); } } } public synchronized void paint (Graphics g) { if (image==null) { width=getSize().width; height=getSize().height; image=createImage(width,height); } Graphics og=image.getGraphics(); og.clearRect(0,0,width,height); og.translate(width/2,height/2); drawFrame(og,false); double last_z=Double.POSITIVE_INFINITY; for (int i=0;i0) { int r=Math.max((int)(R*m),1); og.setColor(p.color); og.fillOval( (int)(x*m)-r, (int)(y*m)-r, r*2,r*2); } p.depth=z; } drawFrame(og,true); if (circle) { int l=(int)(Math.sqrt(3)*L*D/(D+L)); og.drawOval(-l,-l,2*l,2*l); } og.dispose(); g.drawImage(image,0,0,this); cluster.sort(); } } class Cluster { final Ball[] ball=new Ball[DullBall.N]; Cluster() { for (int i=0;imid.depth)) front++; while((back>begin) && (ball[back].depth