//Attractors and Fractals //Grant Schindler, 2008
//Variables and Coefficients (Initial Values) ------------------------------------ float a = 1.78125, b = -0.78125, c = 1.90625, d = 2.65625, e = 0.7, f = -1.1; //Coefficients float x = 0.6, y = 0.9, z = 0.3; //Variables float xn,yn,zn,la,lb,lc,ld; //Temporary Copies of Variables, Coefficients
int N = 512, u, v; //Image Size, Pixel Coordinates PImage img = createImage(N,N,RGB); //Image Itself float K = N*0.2; //Image Scaling Constant
float[] r = {0.0,0.0,0.0}; //Color (float) int[] clr = {0,0,0}; //Color (int) float[][][] fimg; //Point Accumulation Array
int nrSamples = 1000000; int nrPasses = 16; int nrIterations = nrSamples/nrPasses; int imageProgress=0, total=0; //Bookkeeping boolean noise = true, init = true, hide = false; //Display Options
void update(){ la = a; lb = b; lc = c; ld = d; //Add Noise to Coefficients for Smoothness if (noise) { la += random(-0.001, 0.001); lb += random(-0.001, 0.001); lc += random(-0.001, 0.001); ld += random(-0.001, 0.001);} xn = sin (la*y) - cos(lb*x); //************************************************* yn = sin (lc*x) - cos(ld*y); //** Update Temp Variables -- Magic Lies Here **** zn = sin ( e*x) - cos( f*z); //************************************************* x = xn; y = yn; z = zn; //Set Original to Temp u = (int)((x+2.5) * K); //Convert to 2D Image Space for Plotting v = (int)((y+2.5) * K); r[0] = z * 0.9 + (1.0-z) * 0.6; //Map Z-Coordinate to Color r[1] = z * 0.2 + (1.0-z) * 0.4; r[2] = z * 0.5 + (1.0-z) * 0.9; }
void accumulatePoints(){ if (imageProgress < nrPasses){ colorMode(RGB, 1.0); for (int i = 0; i < nrIterations; i++){ update(); //Compute Next Point fimg[u][v][0] += r[0]; fimg[u][v][1] += r[1]; //Add New Point to Total fimg[u][v][2] += r[2]; fimg[u][v][3] += 1.0; if (i < 2000) {stroke(r[0],r[1],r[2]); point(u,v);} //Draw Points } colorMode(RGB, 255); imageProgress++; if (imageProgress <= nrPasses) total += nrIterations; } }
void draw(){ background(0); float a0 = a, b0 = b, c0 = c, d0 = d; //Adjust Coefficients Based On Mouse Position if (active == 1) { ma = mouseX; mb = mouseY; a = fromMouse(ma); b = fromMouse(mb);} if (active == 2) { mc = mouseX; md = mouseY; c = fromMouse(mc); d = fromMouse(md);} if (!(a == a0 && b == b0 && c == c0 && d == d0)) {init = true;} //Mouse Moved - Parameters Changed //Initialize Collection Bins if (init) { for (int i=0; i < N; i++) { for (int j=0; j < N; j++) { for (int k=0; k < 4; k++) { fimg[i][j][k] = 1.0; //Set All to 1.0 (Log-Valued Zero) }}} imageProgress = 0; total = 0; init = false; }
accumulatePoints(); //-- Render Accumulated Points ------------------------------------------------------- if (imageProgress == nrPasses && total == nrSamples){
//Find Max Value - // float t1 = millis(); float max = -1.0; for (int i=0; i < N; i++) { for (int j=0; j < N; j++) { if (fimg[i][j][3] > max){ max = fimg[i][j][3];}}}
//Adjust Values and Fill Image float logval, logmax = log(max); float M = (logmax * logmax) / 255.0; //Precomputation for ratio (log(val)/log(max))^2 img.loadPixels(); for (int i=0; i < N; i++) { for (int j=0; j < N; j++) { for (int k=0; k < 3; k++) { logval = log(fimg[i][j][k]); clr[k] = (int) (logval * logval / M); } img.pixels[j*N + i] = color(clr[0],clr[1],clr[2]); }} img.updatePixels(); // float t2 = millis(); println("Render: " + (t2-t1)); total++; }
if (total >= nrSamples) {image(img,0,0,N,N);} //Draw Rendered Image //Draw Indicators for Coefficients if (!hide) { stroke(200); fill(100,0,0); ellipse(ma, mb, (active == 1) ? 20 : 10, (active == 1) ? 20: 10); fill(0,0,100); ellipse(mc, md, (active == 2) ? 20 : 10, (active == 2) ? 20: 10);} }
//------------------------------------------------------------------ //-- User Interface ------------------------------------------------ //------------------------------------------------------------------ int toMouse(float a) {return (int)((float)N * (a + 4.0)/8.0);} float fromMouse(int X) {return -4.0 + 8.0 * (float)X/(float)N;} int ma,mb,mc,md,active = 0; //Mouse Coordinates of Coefficients
void setup(){ size(N,N); frameRate(30); fimg = new float[N][N][4]; ma = toMouse(a); mb = toMouse(b); mc = toMouse(c); md = toMouse(d); }
void keyPressed() {if (key == 'n') noise = !noise; if (key == 'h') hide = !hide;}
void mousePressed(){ if (active != 0) active = 0; else if (sq(mouseX-mc) + sq(mouseY-md) < sq(10.0)) {active = 2;} else if (sq(mouseX-ma) + sq(mouseY-mb) < sq(10.0)) {active = 1;} }
|