> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.MLLUSITFU0I/rev.1646
 * 
 * authors: 
 *   
 *   vs
 *   ben
 *   ben
 *   
 *   
 *   

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



float[] locs = new float[900];

void setup(){
    size(400,400,P3D);
    newSphere(119.055);       // only needed for testing radius; 119.055 has half volume of 150
  target = 119.055;         // test only
  newSphere(150);
 // println(counter / MAX);
}
// R is sphere radius
void newSphere(float R){
  average_distance = 0.0;   // test only
  for (int i=0; i<locs.length; i+=3) {
    float theta = random(0.0, TWO_PI); // angle
    float v = random(-1.0, 1.0); // 3d offset
    float phi = acos(v); // 3d angle
    
    // the magic number
    //float n = 1.0 - (random(0.0, 1.0)*random(0.0575,1.0)); // this looks pretty good?  agree
    float n = pow(random(0.0, 1.0), 0.33333333); // testing
    // maybe getting the average 3d distance would help (to diagnose)
    // I don't know what weight the distribution should have
    // in order to aesthetically or mathematically fill a given volume within the sphere
    // with a similar # of points
    // but this looks damn close
    // :D
    
    // ^ tests show that it is very slightly too close to the edge using random(0,1) * random(0,1)
    // this can be tweaked very slightly by doing random(0,1) * random(0.044, 1), or instead using rand(0,1) * rand(0.0575, 1)
    // using 0.044 for just one of the random calls looks about the same, but seems more equally distributed.
    // 0.044 seems to line up well with random()'s faults in distribution
    // 0.0575 seems to behave much better when the RNG is better
    // there seem to be issues when the random number generator is vanilla random()
    // LCG-type random will limit results when sampled in some tuple of size so that all points will fall...
    // on specific parallel (hyper)planes, sometimes noticeably in 3d
    // above, rand() and splitMix32() implement a 32-bit random number generator that's rather fast and better-distributed
    float r = R * n; // random dist within radius
    float x = r*cos(theta)*sin(phi);
    float y = r*sin(theta)*sin(phi);
    float z = r*cos(phi);
    locs[i]=x;
    locs[i+1]=y;
    locs[i+2]=z;
    //float d = sqrt(x * x + y * y + z * z);   // test only
    //average_distance += d;                   // test only
   // if(d < target) {                         // test only
  //    counter+=1;                            // test only
  //  }                                        // test only
  }
}

void draw() {
  background(0,0,30);
//  rect(0,0,width,height);
  fill(230);
  stroke(0);
  translate(width/2, height/2);
  for (int i=0; i<locs.length; i+=3) {
    pushMatrix();
    rotateY(mouseX*PI/(float)width);
    rotateX(mouseY*PI/(float)height);
    translate(locs[i], locs[i+1], locs[i+2]);
    box(5, 5, 5);  
    popMatrix();
  }
  stroke(100);
  //sphere(150);
}

void keyPressed() {
  if (key=='r'){
    //counter = 0;
    newSphere(150);
    //println(counter / MAX);
  }
}