public class ParticleSystem extends Particle {  public static final double NULL_DOUBLE = Math.random()*1e10;  Particle[] particles;    boolean gusty=true;  double[][] gust = new double[100][2];  double constGust;    double birthrate=500;    double minx=-10, miny=-10, minz=-10, maxx=10, maxy=10, maxz=25;  double mini=0;    public ParticleSystem() {    particles = new Particle[100];  }    public void simulate(double t) {    removeDead(t);    makeNew(t);    advance(t);  }    public void removeDead(double t) {    Particle curp;    for(int i=0; i<particles.length; i++) {      if (particles[i]==null) continue;      curp = particles[i];      if (   curp.x < minx || curp.x > maxx           || curp.y < miny || curp.y > maxy          || curp.z < minz || curp.z > maxz          || curp.intensity < mini          || curp.color <= 0 ) {        particles[i] = null;      }    }  }    public void makeNew(double t) {    makeNew((int)(t*birthrate));  }  public void makeNew(int count) {    int i=0;    while(count > 0) {      while(particles[i]!=null) {        i++;        if (i==particles.length) expandParticleArray();      }      particles[i] = newParticle();      count--;    }  }    public Particle newParticle() {    double z=Math.random(), t=Math.random()*2*Math.PI;    z*=z;    if (Math.random()<.5) z = -z;    double r = Math.sqrt(1-z*z);    x = r*Math.cos(t);    y = r*Math.sin(t);    Particle p = new Particle(x, y, z, x, y, z);    p.color = 420; //0xFFFF0F;    return p;  }    public void advance(double t) {    double[][] accs = new double[particles.length][3];    for(int i=0; i<particles.length; i++) {      if (particles[i]==null) {        accs[i][0] = NULL_DOUBLE;        continue;      }      accs[i][0] = particles[i].x;      accs[i][1] = particles[i].y;      accs[i][2] = particles[i].z;    }    accs = acceleration(accs);    for(int i=0; i<particles.length; i++) {      if (particles[i] != null) {        //particles[i].advance(t, acceleration(particles[i]));        //particles[i].advanceAcc(t, accs[i][0], accs[i][1], accs[i][2]);        particles[i].simpleAdvance(t, accs[i][0], accs[i][1], accs[i][2]);        particles[i].color -= 2; //= decreaseColor(t, particles[i].color);      }    }  }    public int decreaseColor(double t, int c) {    if ((c & 0x00FF00) == 0) c -= 0x010000;    else if ((c & 0x0000FF) == 0) c -= 0x000100;    else c--;    return c;  }    public Point3D acceleration(Point3D p) { return acceleration(p.x, p.y, p.z); }  public Point3D acceleration(double x, double y, double z) {    // all this object creation could be expensive    //return new Point3D(0, 0, 0);     return new Point3D(x/(z+10), y/(z+10), 1);  }    public double[][] acceleration(double[][] pos) {    double x, y, z, r, dr, xwalk=0, ywalk=0;    if (gusty) {      /*      for(int i=0; i<gust.length; i++) {        gust[i][0] *= .8;        gust[i][1] *= .8;        gust[i][0] += xwalk*2;        gust[i][1] += ywalk*2;        xwalk = xwalk+(Math.random()-.5)/10;        ywalk = ywalk+(Math.random()-.5)/10;      }      */      constGust *= .95;      constGust += (Math.random()-.5);      for(int i=0; i<pos.length; i++) {        if (pos[i][0]==NULL_DOUBLE) continue;        //dr = -Math.exp(Math.sqrt(pos[i][0]*pos[i][0]+pos[i][1]*pos[i][1]));pos[i][0] *= r;        x = pos[i][0];        y = pos[i][1];        z = pos[i][2];        r=x*x+y*y+z*z;        dr = 9/r-5/(z+1);        pos[i][0] = x*dr+constGust; //+gust[(int)(100*(z-minz)/(maxz-minz))][0];        pos[i][1] = y*dr+constGust; //+gust[(int)(100*(z-minz)/(maxz-minz))][1];        pos[i][2] = z/r+2-Math.random()/15;      }    }    else {      for(int i=0; i<pos.length; i++) {        if (pos[i][0]==NULL_DOUBLE) continue;        //dr = -Math.exp(Math.sqrt(pos[i][0]*pos[i][0]+pos[i][1]*pos[i][1]));pos[i][0] *= r;        x = pos[i][0];        y = pos[i][1];        z = pos[i][2];        r=x*x+y*y+z*z;        dr = 9/r-5/(z+1);        pos[i][0] = x*dr;        pos[i][1] = y*dr;        pos[i][2] = z/r+2-Math.random()/15;      }    }    return pos;  }    public synchronized void expandParticleArray() {    Particle[] tmp = new Particle[particles.length*2];    System.arraycopy(particles, 0, tmp, 0, particles.length);    particles = tmp;  }  }