// generic parametric rendering engine... // I'm hoping this leads to many unique images. :) boolean startingUp = true; boolean drawRequested = false; PFont defaultFont10; PFont defaultFont16; long randSeed = (long)random(10000); void setup(){ background(0,0,0); size(600, 400); frameRate(10); defaultFont10 = loadFont("LucidaSans-10.vlw"); defaultFont16 = loadFont("LucidaSans-16.vlw"); textFont(defaultFont10, 10); } void draw(){ if(startingUp){ // just starting up, show a simple page to welcome/instruct the user. delay(200); background(0,0,0); textFont(defaultFont16, 16); fill(255, 255, 255); text("Parametric Rendering Engine... \n Click to draw a Rose.",100,100); startingUp = false; }else{ if(drawRequested){ // handle rendering background(0,0,0); translate(300, 200); //pushMatrix(); //renderRose(); //popMatrix(); //translate(300, 0); pushMatrix(); renderRoseByDepth(); popMatrix(); drawRequested = false; } } } void mousePressed(){ randSeed = (long)random(10000); drawRequested = true; } public void drawShape(ParamShape shape, int totalS_x, int totalS_y){ for(int x=0; x<=totalS_x; x++){ for(int y=0; y<=totalS_y; y++){ shape.drawShape((double)x/(double)totalS_x, (double)y/(double)totalS_y, 0, 0); shape.drawShape((double)x/(double)totalS_x, (double)y/(double)totalS_y, 0, 12); shape.drawShape((double)x/(double)totalS_x, (double)y/(double)totalS_y, 0, 25); shape.drawShape((double)x/(double)totalS_x, (double)y/(double)totalS_y, 0, 50); shape.drawShape((double)x/(double)totalS_x, (double)y/(double)totalS_y, 0, 75); shape.drawShape((double)x/(double)totalS_x, (double)y/(double)totalS_y, 0, 100); } } stroke(255,255,255); point(0,0); } public void renderRose(){ // render from the outside of the rose in, since inner petals cover outer petals. rotate(random(PI)); for(int i=100; i>0; i--){ int offset = i*i/100+1; renderPetal(offset); rotate(random(TWO_PI)-PI); if(i%30 == 29){ // give a little drawing feedback to user doesn't get frustrated. :) repaint(); delay(100); } } } public void renderRoseByDepth(){ int totalDepth = 50; for(int depth=0; depth<=totalDepth; depth++){ pushMatrix(); randomSeed(randSeed); rotate(random(TWO_PI)-PI); for(int i=100; i>0; i--){ int offset = (int)((i*i/100)*0.7) +1; renderPetalAtDepth(offset, (double)depth/(double)totalDepth); rotate(random(PI)); } popMatrix(); if(depth%5 == 0){ repaint(); delay(100); } } } public void renderPetal(int offsetY){ // within each petal, render from the base to the tip (S_y 0.0 --> 1.0); ParamShape petal = new ParamShapeRosePetal(); int totalS_x = 250; int totalS_y = 100; double totalRot = -(PI/4.0 + (random(1.0)*PI/8.0) - PI/16.0); double rotPerIter = totalRot/totalS_x; for(int x=0; x<=totalS_x; x++){ rotate((float)rotPerIter); for(int y=0; y<=totalS_y; y++){ petal.drawShape((double)x/(double)totalS_x, (double)y/(double)totalS_y, 0, offsetY); } } } public void renderPetalAtDepth(int offsetY, double depth){ // within each petal, render from the base to the tip (S_y 0.0 --> 1.0); ParamShape petal = new ParamShapeRosePetal(); int totalS_x = 300; double totalRot = -(PI/3.0 + (random(1.0)*PI/8.0) - PI/16.0); double rotPerIter = totalRot/totalS_x; for(int x=0; x<=totalS_x; x++){ rotate((float)rotPerIter); petal.drawShape((double)x/(double)totalS_x, depth, 0, offsetY); } } abstract class ParamShape{ /** * draw the parameterized shape. * @param S_x the parameter in the X direction (values from 0.0 to 1.0). * @param S_y the parameter in the Y direction (values form 0.0 to 1.0). * @param offsetX the number of pixels in the X direction to offset the shape. * @param offsetY the number of pixels in the Y direction to offset the shape. */ public abstract void drawShape(double S_x, double S_y, int offsetX, int offsetY); } class ParamShapeRosePetal extends ParamShape{ color cRoseBase = color(20, 0, 0); color cRoseTip = color(250, 40, 40); public void drawShape(double S_x, double S_y, int offsetX, int offsetY){ double scaleFactor = offsetY/100.0+0.01; stroke(colorLinInt(cRoseBase, cRoseTip, S_y)); if(S_y <= Math.sin(S_x*PI)){ point((float)((S_x-0.5)*scaleFactor*100)+offsetX, (float)((S_y)*scaleFactor*32.0)+offsetY); } } } public color colorLinInt(color cA, color cB, double S_AtoB){ double a = 1.0-S_AtoB; double b = S_AtoB; return color((int)(a*red(cA)+b*red(cB)), (int)(a*green(cA)+b*green(cB)), (int)(a*blue(cA)+b*blue(cB))); }