├── AccelerateDecelerate └── AccelerateDecelerate.pde ├── ArcsRandom └── ArcsRandom.pde ├── ArrowWaves └── ArrowWaves.pde ├── BadlyDrawnCircles └── BadlyDrawnCircles.pde ├── BlobGrowth └── BlobGrowth.pde ├── BlobMorph └── BlobMorph.pde ├── BranchingSegments ├── BranchingSegments.pde ├── GridClass.pde ├── MathUtils.pde └── README.md ├── CartoonCloud └── CartoonCloud.pde ├── CassiniOvalGrid └── CassiniOvalGrid.pde ├── CassiniShaded ├── CassiniShaded.pde └── data │ ├── OvalFragShader.frag │ └── OvalVertShader.vert ├── CassiniShadedLiquidNeon ├── CassiniShadedLiquidNeon.pde └── data │ ├── OvalFragShader.frag │ └── OvalVertShader.vert ├── CircleOfCircles └── CircleOfCircles.pde ├── CirclePackingBubbles └── CirclePackingBubbles.pde ├── CirclePackingWithGrid2 ├── CirclePackingWithGrid2.pde └── GridClass.pde ├── ColorStreamsFromImage ├── ColorStreamsFromImage.pde └── data │ ├── PixelWaveFragShader.frag │ ├── VertShader.vert │ └── fruit3.png ├── ConcentricParticles ├── ConcentricParticles.pde └── README.md ├── CosmicEggs └── CosmicEggs.pde ├── DebrisField └── DebrisField.pde ├── DeepBlueRadiance └── DeepBlueRadiance.pde ├── DemoContainedWaves └── DemoContainedWaves.pde ├── DemoTaperedLines └── DemoTaperedLines.pde ├── DifferenceMode3Waves └── DifferenceMode3Waves.pde ├── DottedShadedWaves ├── DottedShadedWaves.pde └── README.md ├── DreamscapesPartOne └── DreamscapesPartOne.pde ├── DreamscapesPartTwoHills └── DreamscapesPartTwoHills.pde ├── FigureAndGround ├── FigureAndGround.pde └── GridClass.pde ├── FilamentSweep ├── FilamentSweep.pde └── README.md ├── FlowFieldActivate └── FlowFieldActivate.pde ├── GlowingCircles └── GlowingCircles.pde ├── GradientArcWaves └── GradientArcWaves.pde ├── GradientZoo └── GradientZoo.pde ├── GroovingSun └── GroovingSun.pde ├── HalftoneSpiral └── HalftoneSpiral.pde ├── IllusionOfForm ├── IllusionOfForm.pde └── README.md ├── LICENSE ├── LazyTrackers └── LazyTrackers.pde ├── LineWarp └── LineWarp.pde ├── LinksInTheDarkness └── LinksInTheDarkness.pde ├── Luminous └── Luminous.pde ├── MakingItAllFit └── MakingItAllFit.pde ├── MoireDragRectangles └── MoireDragRectangles.pde ├── NoiseShift └── NoiseShift.pde ├── PaletteShifter └── PaletteShifter.pde ├── PerlinNoiseBounds └── PerlinNoiseBounds.pde ├── PerlinStorm └── PerlinStorm.pde ├── PoissonTesting ├── GridClass.pde ├── MathUtils.pde ├── Poisson.pde └── PoissonTesting.pde ├── PolygonPacking ├── GridClass.pde ├── PolygonPacking.pde └── README.md ├── Pulses └── Pulses.pde ├── PushedAside └── PushedAside.pde ├── README.md ├── RadialWaves └── RadialWaves.pde ├── ShaderDemos └── ShaderDemoGradient │ ├── ShaderDemoGradient.pde │ └── data │ ├── GradientShader.frag │ └── GradientShader.vert ├── ShadowCubes └── ShadowCubes.pde ├── ShiftyRadial └── ShiftyRadial.pde ├── SigmoidMotion ├── SigmoidMotion.pde └── data │ ├── shader.frag │ └── shader.vert ├── Skylines └── Skylines.pde ├── Snakey └── Snakey.pde ├── SoftlySpiraling └── SoftlySpiraling.pde ├── Spinners └── Spinners.pde ├── SpinningSquares └── SpinningSquares.pde ├── Squircle └── Squircle.pde ├── StressDeformation └── StressDeformation.pde ├── Suns2304 └── Suns2304.pde ├── Topography └── Topography.pde ├── TriangleDance └── TriangleDance.pde ├── TrianglesInConcentricCircles └── TrianglesInConcentricCircles.pde ├── TurnTurnTurn └── TurnTurnTurn.pde ├── WanderingStars └── WanderingStars.pde ├── WhereDoWeGo └── WhereDoWeGo.pde ├── WonkyBlob └── WonkyBlob.pde └── misc ├── CirclePackingWithGrid21659442631307.png ├── Convergence1657649717044.svg ├── DreamscapesPartTwo1652972999987seed3767882.png ├── PackedArcs1649820553959.png ├── arcsRandom2940173.png └── github_avi.png /AccelerateDecelerate/AccelerateDecelerate.pde: -------------------------------------------------------------------------------- 1 | int rows = 4; 2 | float [] offsets = new float[rows + 1]; 3 | float [] rates = new float[rows + 1]; 4 | 5 | void setup() { 6 | size(900, 900, P2D); 7 | smooth(8); 8 | ellipseMode(RADIUS); 9 | } 10 | 11 | void draw() { 12 | background(0, 10, 40); 13 | noStroke(); 14 | fill(255, 225, 200); 15 | float inc = 1.0 * width / rows; 16 | for (int i = 0; i <= rows; i++) { 17 | rates[i] = 3 * 0.5 * (1 + sin(radians(frameCount * 0.25) + i * PI / rows)); 18 | } 19 | 20 | for (int i = 0; i <= rows; i++) { 21 | float y = inc * i; 22 | offsets[i] += rates[i]; 23 | for (int j = 0; j <= rows + 1; j++) { 24 | float x = -inc + (j * inc + offsets[i]) % (width + inc * 2); 25 | circle(x, y, inc / 2); 26 | } 27 | } 28 | println(frameCount / 60); 29 | } 30 | -------------------------------------------------------------------------------- /ArcsRandom/ArcsRandom.pde: -------------------------------------------------------------------------------- 1 | float pixInc = 2; 2 | ArrayList arcs = new ArrayList(); 3 | int side = 3; 4 | int ySide = 3; 5 | int margin = 25; 6 | float maxR; 7 | Mover m; 8 | PGraphics pg; 9 | 10 | void setup() { 11 | size(900, 900, P3D); 12 | pg = createGraphics(1080, 1080, P3D); 13 | pg.smooth(8); 14 | pg.beginDraw(); 15 | pg.noFill(); 16 | pg.endDraw(); 17 | m = new Mover(new PVector(random(pg.width), random(pg.height)), new PVector(random(2, 4), random(2, 4))); 18 | float inc = (pg.height - margin * 2) / ySide; 19 | maxR = 0.975 * inc / 2; 20 | for (int i = 0; i < ySide; i++) { 21 | float y = margin + inc / 2 + inc * i; 22 | for (int j = 0; j < side; j++) { 23 | float x = margin + inc / 2 + inc * j; 24 | float arcStart = x / pg.width * 2 * PI; 25 | for (float r = 0.975 * inc / 2; r > 8; r -= 8) { 26 | float arcLen = random(PI / 2, 3 * PI / 2); 27 | Arc a = new Arc(x, y, r, arcStart + random(PI / 2), arcLen); 28 | arcs.add(a); 29 | } 30 | } 31 | } 32 | } 33 | 34 | void draw() { 35 | pg.beginDraw(); 36 | pg.background(0); 37 | pg.stroke(255, 225, 200); 38 | for (Arc a : arcs) { 39 | a.update(); 40 | a.show(); 41 | } 42 | //pg.save("output" + int(random(10000000)) + ".png"); 43 | pg.endDraw(); 44 | image(pg, 0, 0, width, height); 45 | println(frameRate); 46 | //noLoop(); 47 | } 48 | 49 | class Arc { 50 | 51 | PVector c; 52 | float r, start, end, arcLen, len, currStart, currArcLen; 53 | float xFactor, yFactor; 54 | 55 | Arc(float x, float y, float r, float start, float arcLen) { 56 | this.c = new PVector(x, y); 57 | this.r = r; 58 | this.start = start; 59 | this.arcLen = arcLen; 60 | this.end = start + arcLen; 61 | } 62 | 63 | void update() { 64 | //xFactor = 1.0 * mouseX / width; 65 | currStart = start + 2 * PI * xFactor; 66 | currArcLen = arcLen + 2 * PI * yFactor; 67 | } 68 | 69 | void show() { 70 | int n = int(currArcLen * r / pixInc); 71 | float inc = currArcLen / n; 72 | pg.beginShape(); 73 | for (int i = 0; i < n; i++) { 74 | float lenFactor = (1 - abs(1.0 * i - n / 2) / (n / 2)); 75 | lenFactor = pow(lenFactor, 1.0 / 2); 76 | float weight = 0.5 + 5.0 * lenFactor; 77 | pg.strokeWeight(weight); 78 | float t = currStart + i * inc; 79 | float x = c.x + r * cos(t); 80 | float y = c.y + r * sin(t); 81 | pg.vertex(x, y); 82 | } 83 | pg.endShape(); 84 | } 85 | 86 | } 87 | 88 | class Mover { 89 | 90 | PVector pos; 91 | PVector vel; 92 | 93 | Mover(PVector pos, PVector vel) { 94 | this.pos = pos; 95 | this.vel = vel; 96 | } 97 | 98 | void move() { 99 | pos.add(vel); 100 | if (pos.x < 0 || pos.x > width) { 101 | vel.x *= -1; 102 | } 103 | if (pos.y < 0 || pos.y > height) { 104 | vel.y *= -1; 105 | } 106 | } 107 | 108 | void show() { 109 | pg.stroke(255, 0, 0); 110 | pg.strokeWeight(20); 111 | pg.point(pos.x, pos.y); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /ArrowWaves/ArrowWaves.pde: -------------------------------------------------------------------------------- 1 | PVector [] sineVals; 2 | int n; 3 | int margin = 25; 4 | PGraphics pg; 5 | 6 | void setup() { 7 | size(900, 900, P2D); 8 | colorMode(HSB, 360, 100, 100, 100); 9 | pg = createGraphics(1080, 1080, P2D); 10 | pg.smooth(8); 11 | pg.beginDraw(); 12 | pg.colorMode(HSB, 360, 100, 100, 100); 13 | n = pg.width; 14 | sineVals = new PVector[n]; 15 | pg.endDraw(); 16 | } 17 | 18 | void draw() { 19 | pg.beginDraw(); 20 | pg.background(225, 100, 25); 21 | pg.noStroke(); 22 | pg.fill(225, 70, 100); 23 | int margin = 25 + int((pg.height / 4.0) * (0.5 * (1 + sin(PI / 2 + radians(frameCount * 0.3))))); 24 | float off = radians(frameCount); 25 | float off2 = radians(frameCount * 0.7); 26 | float amp = 200; 27 | for (int px = 0; px < n; px++) { 28 | float cx = map(px, 0, n, 0, 2 * PI); 29 | float cy = 0.5 * (cos(1.7 * cx + off2) + sin(2 * cx + off)); 30 | float py = map(cy, -1, 1, pg.height / 2 - amp, pg.height / 2 + amp); 31 | sineVals[px] = new PVector(map(px, 0, pg.width, -margin, pg.width + margin), py); 32 | } 33 | 34 | int levels = 30; 35 | for (int level = 0; level <= levels; level++) { 36 | int indexOff = int(level * 3 + frameCount * 1.5) % 20; 37 | pg.fill(225 + 25.0 * level / levels, 20 + 50.0 * level / levels, 100); 38 | for (int i = indexOff; i < sineVals.length - indexOff - 1; i += 20) { 39 | float lerpValue = abs(1.0 * level - levels / 2) / (levels / 2); 40 | boolean above = level < levels / 2; 41 | PVector p = sineVals[i]; 42 | p = PVector.lerp(p, above ? new PVector(p.x, margin) : new PVector(p.x, pg.height - margin), lerpValue); 43 | PVector p2 = sineVals[i + 1]; 44 | p2 = PVector.lerp(p2, above ? new PVector(p2.x, margin) : new PVector(p2.x, pg.height - margin), lerpValue); 45 | PVector diff = p2.copy().sub(p).normalize(); 46 | PVector n = new PVector(-diff.y, diff.x); 47 | PVector a = p.copy().add(diff.mult(15)); 48 | PVector b = p.copy().add(n.copy().mult(5)); 49 | PVector c = p.copy().sub(n.copy().mult(5)); 50 | pg.triangle(a.x, a.y, b.x, b.y, c.x, c.y); 51 | } 52 | } 53 | pg.endDraw(); 54 | image(pg, 0, 0, width, height); 55 | if (frameCount % 60 == 0) { 56 | println(frameCount / 60); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /BadlyDrawnCircles/BadlyDrawnCircles.pde: -------------------------------------------------------------------------------- 1 | color bgColor = color(0); 2 | color strokeColor = color(255, 225, 200); // color(200, 240, 255); // 3 | PGraphics pg; 4 | 5 | void setup() { 6 | size(900, 900, P3D); 7 | pg = createGraphics(1080, 1080, P3D); 8 | pg.smooth(8); 9 | 10 | } 11 | 12 | int folds = 2; 13 | int n = 400; 14 | 15 | void keyPressed() { 16 | if (key == CODED) { 17 | if (keyCode == UP) { 18 | n++; 19 | } 20 | if (keyCode == DOWN && n > 3) { 21 | n--; 22 | } 23 | if (keyCode == LEFT) { 24 | n = 10; 25 | } 26 | if (keyCode == RIGHT) { 27 | n = 400; 28 | } 29 | } 30 | if (key == 'i') { 31 | color temp = bgColor; 32 | bgColor = strokeColor; 33 | strokeColor = temp; 34 | } 35 | } 36 | 37 | void draw() { 38 | pg.beginDraw(); 39 | pg.background(bgColor); 40 | pg.noFill(); 41 | pg.translate(pg.width / 2, pg.height / 2); 42 | pg.stroke(strokeColor); 43 | 44 | float inc = 2 * PI / n; 45 | PVector [] values = new PVector[n]; 46 | PVector [] distValues = new PVector[n]; 47 | float tFactor = sin(radians(frameCount)); 48 | for (int i = 0; i < n; i++) { 49 | float angle = i * inc + radians(frameCount * 0.2); 50 | float r = 15; 51 | float cosAngle = cos(angle); 52 | float sinAngle = sin(angle); 53 | float x = r * cosAngle; 54 | float y = r * sinAngle; 55 | values[i] = new PVector(x, y); 56 | float distR = 20 57 | + 10.0 * tFactor * cos(folds * angle + radians(frameCount * 0.7)); 58 | distValues[i] = new PVector(distR * cosAngle, distR * sinAngle); 59 | } 60 | 61 | color col1 = color(255, 200, 100); 62 | color col2 = color(200, 0, 0); 63 | 64 | int layers = 33; 65 | for (int i = 0; i < layers; i++) { 66 | pg.beginShape(); 67 | for (int j = 0; j < values.length; j++) { 68 | int index = (j + i * 3) % values.length; 69 | pg.strokeWeight(2 + 5.0 * abs(1.0 * (frameCount * 0.005 * n + index) % n - n / 2) / (n / 2)); 70 | float indexFactor = abs(1.0 * j - values.length / 2) / (values.length / 2); 71 | pg.stroke(lerpColor(col1, col2, indexFactor)); 72 | float ratio = abs(1.0 * i - layers) / layers; 73 | PVector val = PVector.lerp(values[j], distValues[j], ratio); 74 | PVector plot = val.copy().mult(1 + i); 75 | pg.vertex(plot.x, plot.y); 76 | } 77 | pg.endShape(CLOSE); 78 | } 79 | pg.endDraw(); 80 | image(pg, 0, 0, width, height); 81 | println(frameCount / 60 + " | " + frameRate); 82 | } 83 | -------------------------------------------------------------------------------- /BlobGrowth/BlobGrowth.pde: -------------------------------------------------------------------------------- 1 | import com.hamoid.*; 2 | import java.util.Date; 3 | VideoExport videoExport; 4 | final String sketchname = getClass().getName(); 5 | 6 | void rec() { 7 | if (frameCount == 1) { 8 | Date date = new Date(); 9 | videoExport = new VideoExport(this, sketchname + date.getTime() + ".mp4", pg); 10 | videoExport.setFrameRate(60); 11 | videoExport.startMovie(); 12 | } 13 | videoExport.saveFrame(); 14 | } 15 | 16 | int n = 10; 17 | ArrayList particles = new ArrayList(); 18 | float redBase = 255; 19 | float greenBase = 225; 20 | float blueBase = 100; 21 | float alphaBase = 25; 22 | PGraphics pg; 23 | 24 | void setup() { 25 | size(900, 900, P2D); 26 | pg = createGraphics(1080, 1080, P2D); 27 | pg.smooth(8); 28 | pg.beginDraw(); 29 | pg.ellipseMode(RADIUS); 30 | 31 | pg.noStroke(); 32 | pg.endDraw(); 33 | for (int i = 0; i < n; i++) { 34 | float th = i * 2 * PI / n; 35 | particles.add(new Particle(PVector.fromAngle(th).mult(30).add(new PVector(pg.width / 2, pg.height / 2)), PVector.fromAngle(th))); 36 | } 37 | } 38 | 39 | void draw() { 40 | pg.beginDraw(); 41 | if (frameCount == 1) { 42 | pg.background(0, 15, 35); 43 | } 44 | for (Particle p : particles) { 45 | p.update(); 46 | p.show(); 47 | } 48 | pg.endDraw(); 49 | image(pg, 0, 0, width, height); 50 | rec(); 51 | println(frameCount / 60); 52 | } 53 | 54 | class Particle { 55 | 56 | PVector p, v; 57 | float r; 58 | 59 | Particle(PVector p, PVector v) { 60 | this.p = p; 61 | this.v = v; 62 | } 63 | 64 | void update() { 65 | this.r = 2 + 15 * 0.5 * (1 + cos(radians(frameCount))); 66 | float time = sin(radians(frameCount * 0.5)); 67 | float time2 = radians(frameCount * 0.55); 68 | v.rotate(PI / 300 + time2 * time * PI / 1050); 69 | p.add(v); 70 | } 71 | 72 | void show() { 73 | float f = 0.5 * (1 + cos(radians(frameCount * 2))); 74 | float f2 = 0.5 * (1 + cos(PI / 2 + radians(frameCount * 0.75))); 75 | pg.fill(f2 * redBase, f * greenBase, blueBase, alphaBase); 76 | pg.circle(p.x, p.y, r); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /BlobMorph/BlobMorph.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | Shape sh, sh2; 4 | ArrayList pointList = new ArrayList(); 5 | float maxDist; 6 | boolean noisy = false; 7 | 8 | void setup() { 9 | size(900, 900, P2D); 10 | pg = createGraphics(1080, 1080, P2D); 11 | maxDist = dist(pg.width, pg.height, 0, 0); 12 | pg.smooth(8); 13 | pg.beginDraw(); 14 | pg.ellipseMode(RADIUS); 15 | pg.endDraw(); 16 | PVector a = new PVector(300, 300); 17 | PVector b = new PVector(650, 650); 18 | ArrayList points = new ArrayList(); 19 | for (int i = 0; i <= 500; i++) { 20 | Point p = new Point(PVector.fromAngle(TAU * i / 500).mult(100).add(a)); 21 | points.add(p); 22 | } 23 | sh = new Shape(points, a); 24 | pointList.addAll(points); 25 | points = new ArrayList(); 26 | for (int i = 0; i <= 1000; i++) { 27 | Point p = new Point(PVector.fromAngle(TAU * i / 1000).mult(150).add(b)); 28 | points.add(p); 29 | } 30 | pointList.addAll(points); 31 | sh2 = new Shape(points, b); 32 | } 33 | 34 | void draw() { 35 | PVector m = new PVector(mouseX * 1.0 * pg.width / width, mouseY * 1.0 * pg.height / height); 36 | pg.beginDraw(); 37 | pg.background(255); 38 | pg.noStroke(); 39 | pg.fill(0); 40 | sh.repel(m); 41 | sh2.repel(m); 42 | for (Point p : pointList) { 43 | if (!mousePressed) { 44 | p.regress(); 45 | } else { 46 | //p.repel(m); 47 | } 48 | } 49 | sh.show(); 50 | sh2.show(); 51 | pg.fill(255, 0, 0); 52 | pg.circle(m.x, m.y, 10); 53 | pg.endDraw(); 54 | image(pg, 0, 0, width, height); 55 | println(frameCount / 60); 56 | } 57 | 58 | void mouseClicked() { 59 | noisy = !noisy; 60 | } 61 | 62 | class Point { 63 | 64 | PVector init, init2, p; 65 | float lerpRate; 66 | 67 | Point(PVector init) { 68 | this.init = init; 69 | this.p = init.copy(); 70 | this.lerpRate = random(0.02, 0.03); 71 | } 72 | 73 | void repel(PVector m) { 74 | PVector diff = p.copy().sub(m); 75 | PVector n = diff.copy().normalize(); 76 | float f = pow(1 - diff.mag() / maxDist, 5); 77 | if (noisy) { 78 | n = PVector.fromAngle(TAU * 2 * noise(init.x * 0.01, init.y * 0.01)).mult(f * 5); 79 | } else { 80 | n.mult(f * 5); 81 | } 82 | p.add(n); 83 | } 84 | 85 | void regress() { 86 | p.lerp(init, 0.055); 87 | } 88 | 89 | } 90 | 91 | class Shape { 92 | 93 | ArrayList points; 94 | PVector c; 95 | 96 | Shape(ArrayList points, PVector c) { 97 | this.points = points; 98 | this.c = c; 99 | } 100 | 101 | void repel(PVector m) { 102 | PVector diff = c.copy().sub(m); 103 | PVector n = diff.copy().normalize(); 104 | float f = pow(1 - diff.mag() / maxDist, 5); 105 | PVector norm = n.copy().mult(f * 5); 106 | c.add(norm); 107 | for (Point p : points) { 108 | p.init.add(norm); 109 | p.repel(m); 110 | } 111 | } 112 | 113 | void show() { 114 | pg.beginShape(); 115 | for (Point p : points) { 116 | pg.vertex(p.p.x, p.p.y); 117 | } 118 | pg.endShape(CLOSE); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /BranchingSegments/GridClass.pde: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | 3 | class Grid { 4 | 5 | Cell [][] cells; 6 | HashSet occupants; 7 | int pixW, pixH; 8 | float cellW, cellH; 9 | 10 | Grid(int w, int h, int pixW, int pixH) { 11 | cells = new Cell[w][h]; 12 | 13 | this.pixW = pixW; 14 | this.pixH = pixH; 15 | this.cellW = 1.0 * pixW / w; 16 | this.cellH = 1.0 * pixH / h; 17 | for (int i = 0; i < w; i++) { 18 | for (int j = 0; j < h; j++) { 19 | PVector pos = new PVector(i * cellW, j * cellH); 20 | cells[i][j] = new Cell(pos, cellW, cellH); 21 | } 22 | } 23 | for (int x = 0; x < w; x++) { 24 | for (int y = 0; y < h; y++) { 25 | 26 | Cell c = cells[x][y]; 27 | c.neighbors = getNeighbors(x, y); 28 | } 29 | } 30 | occupants = new HashSet(); 31 | } 32 | 33 | void add(T t, float xPixPos, float yPixPos) { 34 | int x = int(xPixPos / cellW); 35 | int y = int(yPixPos / cellW); 36 | cells[x][y].occupants.add(t); 37 | occupants.add(t); 38 | } 39 | 40 | void add(PVector p) { 41 | int x = int(p.x / cellW); 42 | int y = int(p.y / cellW); 43 | cells[x][y].occupants.add(p); 44 | occupants.add((T) p); 45 | } 46 | 47 | ArrayList getCellMembers(int x, int y) { 48 | return new ArrayList(cells[x][y].occupants); 49 | } 50 | 51 | Cell getCell(float xPixPos, float yPixPos) { 52 | int x = int(xPixPos / cellW); 53 | int y = int(yPixPos / cellW); 54 | return cells[x][y]; 55 | } 56 | 57 | ArrayList getNeighbors(int x, int y) { 58 | ArrayList results = new ArrayList(); 59 | boolean onLeftBorder = x == 0; 60 | boolean onRightBorder = x == cells.length - 1; 61 | boolean onTopBorder = y == 0; 62 | boolean onBottomBorder = y == cells[0].length - 1; 63 | if (!onLeftBorder) { 64 | if (!onTopBorder) { 65 | results.add(cells[x-1][y-1]); 66 | } 67 | if (!onBottomBorder) { 68 | results.add(cells[x-1][y+1]); 69 | } 70 | results.add(cells[x-1][y]); 71 | } 72 | if (!onRightBorder) { 73 | if (!onTopBorder) { 74 | results.add(cells[x+1][y-1]); 75 | } 76 | if (!onBottomBorder) { 77 | results.add(cells[x+1][y+1]); 78 | } 79 | results.add(cells[x+1][y]); 80 | } 81 | if (!onTopBorder) { 82 | results.add(cells[x][y-1]); 83 | } 84 | if (!onBottomBorder) { 85 | results.add(cells[x][y+1]); 86 | } 87 | return results; 88 | } 89 | 90 | ArrayList getCellAndNeighbors(int x, int y) { 91 | ArrayList results = new ArrayList(); 92 | boolean onLeftBorder = x == 0; 93 | boolean onRightBorder = x == cells[0].length - 1; 94 | boolean onTopBorder = y == 0; 95 | boolean onBottomBorder = y == cells.length - 1; 96 | if (!onLeftBorder) { 97 | if (!onTopBorder) { 98 | results.add(cells[x-1][y-1]); 99 | } 100 | if (!onBottomBorder) { 101 | results.add(cells[x-1][y+1]); 102 | } 103 | results.add(cells[x-1][y]); 104 | } 105 | if (!onRightBorder) { 106 | if (!onTopBorder) { 107 | results.add(cells[x+1][y-1]); 108 | } 109 | if (!onBottomBorder) { 110 | results.add(cells[x+1][y+1]); 111 | } 112 | results.add(cells[x+1][y]); 113 | } 114 | if (!onTopBorder) { 115 | results.add(cells[x+1][y-1]); 116 | } 117 | if (!onBottomBorder) { 118 | results.add(cells[x+1][y+1]); 119 | } 120 | return results; 121 | } 122 | 123 | ArrayList findCloseOccupants(PVector pos) { 124 | Cell c = this.getCell(pos.x, pos.y); 125 | ArrayList close = c.getOccupantsAndOccupantsOfNeighbors(); 126 | return close; 127 | } 128 | 129 | void show() { 130 | for (Cell [] array : cells) { 131 | for (Cell c : array) { 132 | c.show(); 133 | } 134 | } 135 | } 136 | 137 | void showVectors() { 138 | for (Cell [] array : cells) { 139 | for (Cell c : array) { 140 | c.showVectors(); 141 | } 142 | } 143 | } 144 | 145 | } 146 | 147 | class Cell { 148 | 149 | PVector pos; 150 | int id; 151 | float w, h; 152 | color fillColor; 153 | ArrayList neighbors; 154 | HashSet occupants; 155 | boolean active; 156 | 157 | Cell(PVector pos, float w, float h) { 158 | this.pos = pos; 159 | this.w = w; 160 | this.h = h; 161 | this.occupants = new HashSet(); 162 | this.neighbors = new ArrayList(); 163 | } 164 | 165 | void add(T t) { 166 | occupants.add(t); 167 | } 168 | 169 | void remove(T t) { 170 | occupants.remove(t); 171 | } 172 | 173 | void show() { 174 | noFill(); 175 | stroke(255); 176 | if (active) { 177 | stroke(255, 0, 0); 178 | } 179 | strokeWeight(1); 180 | rect(pos.x, pos.y, w, h); 181 | } 182 | 183 | ArrayList getOccupantsAndOccupantsOfNeighbors() { 184 | ArrayList results = new ArrayList(); 185 | for (Cell c : neighbors) { 186 | results.addAll(c.occupants); 187 | } 188 | results.addAll(occupants); 189 | return results; 190 | } 191 | 192 | ArrayList getOccupantsOfNeighbors() { 193 | ArrayList results = new ArrayList(); 194 | for (Cell c : neighbors) { 195 | results.addAll(c.occupants); 196 | } 197 | return results; 198 | } 199 | 200 | void showVectors() { 201 | strokeWeight(4); 202 | for (T o : occupants) { 203 | PVector p = (PVector) o; 204 | point(p.x, p.y); 205 | } 206 | } 207 | 208 | boolean contains(float x, float y) { 209 | return x >= pos.x && y >= pos.y && x <= pos.x + w && y <= pos.y + h; 210 | } 211 | 212 | } 213 | -------------------------------------------------------------------------------- /BranchingSegments/MathUtils.pde: -------------------------------------------------------------------------------- 1 | import java.util.Comparator; 2 | 3 | boolean outOfBounds(PVector p, float left, float right, float top, float bottom) { 4 | return p.x < left || p.x > right || p.y < top || p.y > bottom; 5 | } 6 | 7 | // line segment AB intersects line segment CD, see: https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line 8 | boolean intersect(PVector a, PVector b, PVector c, PVector d) { 9 | float tNom = (a.x - c.x) * (c.y - d.y) - (a.y - c.y) * (c.x - d.x); 10 | float tDenom = (a.x - b.x) * (c.y - d.y) - (a.y - b.y) * (c.x - d.x); 11 | float uNom = (a.x - c.x) * (a.y - b.y) - (a.y - c.y) * (a.x - b.x); 12 | float uDenom = (a.x - b.x) * (c.y - d.y) - (a.y - b.y) * (c.x - d.x); 13 | return abs(tNom) < abs(tDenom) && sign(tNom) == sign(tDenom) && abs(uNom) < abs(uDenom) && sign(uNom) == sign(uDenom); 14 | } 15 | 16 | int sign(float x) { 17 | return x == 0 ? 0 : (x > 0 ? 1 : -1); 18 | } 19 | 20 | boolean withinDistance(PVector p, float d, PVector other) { 21 | return p.copy().sub(other).magSq() < d * d; 22 | } 23 | 24 | boolean anyWithinDistance(PVector p, float d, ArrayList others) { 25 | for (PVector other : others) { 26 | if (withinDistance(p, d, other)) { 27 | return true; 28 | } 29 | } 30 | return false; 31 | } 32 | 33 | ArrayList getPointsWithinDistance(PVector p, float d, ArrayList others) { 34 | ArrayList results = new ArrayList(); 35 | for (PVector o : others) { 36 | if (o != p && withinDistance(p, d, o)) { 37 | results.add(o); 38 | } 39 | } 40 | return results; 41 | } 42 | 43 | // ray-casting test for containment: https://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm 44 | boolean polygonContains(ArrayList polygon, PVector p) { 45 | PVector rayEnd = new PVector(width * 10, height * 10); 46 | int intersections = 0; 47 | for (int i = 0; i < polygon.size(); i++) { 48 | PVector a = polygon.get(i); 49 | PVector b = polygon.get((i + 1) % polygon.size()); 50 | if (intersect(a, b, p, rayEnd)) { 51 | intersections++; 52 | } 53 | } 54 | return intersections % 2 == 1; 55 | } 56 | 57 | ArrayList closestNPoints(final PVector p, ArrayList candidates, int n) { 58 | ArrayList points = new ArrayList(candidates); 59 | Comparator comp = new Comparator() { 60 | public int compare(PVector v, PVector other) { 61 | float d1 = v.copy().sub(p).magSq(); 62 | float d2 = other.copy().sub(p).magSq(); 63 | return Float.compare(d1, d2); 64 | } 65 | }; 66 | points.sort(comp); 67 | return new ArrayList(points.subList(0, n)); 68 | } 69 | -------------------------------------------------------------------------------- /BranchingSegments/README.md: -------------------------------------------------------------------------------- 1 | Controlled random growth limited by line intersection test. Depending on the parameters, can look "square" and artificial, organic, or controlled but curvy. 2 | 3 | I've set up four "modes" with preset parameters to demonstrate different behaviors. Here are some example outputs: 4 | 5 | ![BranchingSegments1650280966015](https://user-images.githubusercontent.com/101308215/163801793-696c5179-918e-49b4-945e-238ce86cc926.png) 6 | 7 | 8 | ![BranchingSegments1650280134602](https://user-images.githubusercontent.com/101308215/163801795-62e00c93-f6c4-4730-aa37-c0684d34e367.png) 9 | 10 | 11 | ![BranchingSegments1650279935433](https://user-images.githubusercontent.com/101308215/163801797-025838e3-30dc-441f-8fb1-5008def6ed78.png) 12 | 13 | 14 | ![BranchingSegments1650278642978](https://user-images.githubusercontent.com/101308215/163801798-788c495b-c922-46bd-8388-b7f16cc164ae.png) 15 | -------------------------------------------------------------------------------- /CartoonCloud/CartoonCloud.pde: -------------------------------------------------------------------------------- 1 | void setup() { 2 | size(900, 900, P3D); 3 | smooth(8); 4 | } 5 | 6 | void draw() { 7 | background(100, 125, 155); 8 | fill(225, 200, 255); 9 | stroke(75, 0, 100); 10 | strokeWeight(3); 11 | ArrayList points = new ArrayList(); 12 | int n = 20; 13 | PVector o = new PVector(width / 2, height / 2); 14 | for (int i = 0; i < n; i++) { 15 | float th = i * 2 * PI / n + 2 * PI / n * (0.5 - noise((i + 1) * 1000, frameCount * 0.01)) + radians(frameCount * 0.75); 16 | float add = 100 * noise((i + 1) * 0.01); 17 | float x = (250 + add) * cos(th); 18 | float y = (100 + add) * sin(th); 19 | PVector p = new PVector(x, y).add(o); 20 | points.add(p); 21 | } 22 | boolean invert = false; 23 | beginShape(); 24 | for (int i = 0; i < n; i++) { 25 | PVector a = points.get(i); 26 | PVector b = points.get((i + 1) % points.size()); 27 | arcConnection(a, b, invert); 28 | //invert = !invert; 29 | } 30 | endShape(); 31 | println(frameRate); 32 | } 33 | 34 | float fract(float x) { 35 | return x - floor(x); 36 | } 37 | 38 | void arcConnection(PVector a, PVector b, boolean invert) { 39 | PVector diff = b.copy().sub(a); 40 | PVector t = diff.copy().normalize(); 41 | PVector norm = new PVector(t.y, -t.x); 42 | float m = diff.mag(); 43 | int n = int(m); 44 | for (float i = 0; i <= n; i++) { 45 | float x = 1.0 * i / n; 46 | PVector l = PVector.lerp(a, b, x); 47 | float f = (invert ? -1 : 1) * sqrt(1-(2*x-1)*(2*x-1)) / 2; 48 | l.add(norm.copy().mult(f * m)); 49 | vertex(l.x, l.y); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /CassiniOvalGrid/CassiniOvalGrid.pde: -------------------------------------------------------------------------------- 1 | int margin = 0; 2 | int nBlobs = 8; 3 | 4 | void setup() { 5 | size(900, 900, P3D); 6 | colorMode(HSB, 360, 100, 100, 100); 7 | smooth(8); 8 | ellipseMode(RADIUS); 9 | rectMode(RADIUS); 10 | } 11 | 12 | void draw() { 13 | background(225, 100, 20); 14 | noStroke(); 15 | fill(150, 200, 255); 16 | float t = sin(radians(frameCount * 0.31)); 17 | int n = 80; // circles per row / column 18 | float inc = 1.0 * (width - margin * 2) / n; 19 | float d = 150 + 100 * (0.5 * (1 + t)); // distance threshold 20 | PVector [] blobs = new PVector[nBlobs]; 21 | for (int i = 0; i < nBlobs; i++) { 22 | float n1 = noise(i + 12345 * i); 23 | float n2 = noise(i + 12345 * i, 797 + i); 24 | blobs[i] = new PVector( 25 | margin + (width - margin * 2) * 0.5 * (1 + sin(PI / 3 * n1 + radians(frameCount * n1))), 26 | margin + (height - margin * 2) * 0.5 * (1 + sin(PI / 5 * n2 + radians(frameCount * n2)))); 27 | } 28 | 29 | for (int yi = 0; yi < n; yi++) { 30 | float yBase = margin + yi * inc; 31 | float y = yBase + inc / 2; 32 | float distVal = sin(1.0 * yi / n * PI + radians(frameCount)); 33 | for (int xi = 0; xi < n; xi++) { 34 | float xBase = margin + xi * inc; 35 | float f = 1 - pow(2 * (1.0 * xBase / (width - inc)) - 1, 2); // used to scale sine distortion with distance to center 36 | float x = xBase + inc / 2 + 300.0 * f * distVal; 37 | 38 | PVector p = new PVector(x, y); 39 | float sum = 0.0; 40 | for (int i = 0; i < blobs.length; i++) { 41 | PVector blobI = blobs[i]; 42 | float r = PVector.sub(p, blobI).mag(); 43 | for (int j = i + 1; j < blobs.length; j++) { 44 | PVector blobJ = blobs[j]; 45 | float r2 = PVector.sub(p, blobJ).mag(); 46 | sum += max(0, 1 - r * r2 / (d * d)); 47 | } 48 | } 49 | 50 | fill(200 + x / width * 50 * min(1, sum), 100 * pow(min(1, sum), 5), 100); 51 | if (sum > 0) { 52 | circle(x, y, inc / 2 * min(1, sum)); 53 | } 54 | } 55 | } 56 | println(frameRate); 57 | } 58 | -------------------------------------------------------------------------------- /CassiniShaded/CassiniShaded.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | PShader ovalShader; 4 | float margin; 5 | 6 | void setup() { 7 | size(900, 900, P2D); 8 | pg = createGraphics(1080, 1080, P2D); 9 | margin = pg.width / 15.0; 10 | ovalShader = new PShader(this, "OvalVertShader.vert", "OvalFragShader.frag"); 11 | } 12 | 13 | void draw() { 14 | background(255); 15 | int nPoints = 10; 16 | float [] pointsX = new float[nPoints]; 17 | float [] pointsY = new float[nPoints]; 18 | float speedFactor = 0.45; 19 | 20 | float yInc = (pg.height - margin * 2) / nPoints; 21 | for (int i = 0; i < nPoints; i++) { 22 | pointsX[i] = pg.width / 2 + sin(radians(speedFactor * frameCount * noise(i) + i * 97)) * (pg.width / 2 - margin); 23 | pointsY[i] = margin + i * yInc + yInc / 2; 24 | } 25 | 26 | pg.beginDraw(); 27 | pg.shader(ovalShader); 28 | ovalShader.set("pointsX", pointsX); 29 | ovalShader.set("pointsY", pointsY); 30 | ovalShader.set("d", 1.0 * pg.width / 3 + pg.width / 16 * sin(radians(frameCount * 0.71))); 31 | ovalShader.set("powerAddition", 3.0 * pow(0.5 * (1 + (sin(radians(frameCount * 0.31)))), 2)); 32 | pg.rect(0, 0, pg.width, pg.height); 33 | pg.endDraw(); 34 | image(pg, 0, 0, width, height); 35 | println(frameCount / 60); 36 | } 37 | -------------------------------------------------------------------------------- /CassiniShaded/data/OvalFragShader.frag: -------------------------------------------------------------------------------- 1 | varying vec2 va_pos; 2 | uniform float [10] pointsX; 3 | uniform float [10] pointsY; 4 | uniform float d; 5 | uniform float powerAddition; 6 | 7 | // animated take on the concept of Cassini ovals: https://mathworld.wolfram.com/CassiniOvals.html 8 | 9 | void main() { 10 | float prod = 1.0; 11 | for (int i = 0; i < pointsX.length; i++) { 12 | vec2 pt = vec2(pointsX[i], pointsY[i]); 13 | float r = length(pt - va_pos); 14 | prod *= r; 15 | } 16 | float f = 1.0 - prod / pow(d, pointsX.length); 17 | f = abs(0.5 - f) / 0.5; 18 | f = pow(f, 0.2 + powerAddition); 19 | vec3 col = vec3(0.7 - f * 0.7, 1. - f, max(0., 0.3 + 0.7 - f * 0.7)); 20 | gl_FragColor = vec4(col, 1.0); 21 | } -------------------------------------------------------------------------------- /CassiniShaded/data/OvalVertShader.vert: -------------------------------------------------------------------------------- 1 | uniform mat4 transformMatrix; 2 | attribute vec4 position; 3 | attribute vec4 color; 4 | varying vec4 va_color; 5 | varying vec2 va_pos; 6 | void main() { 7 | gl_Position = transformMatrix * position; 8 | va_color = color; 9 | va_pos = position.xy; 10 | } -------------------------------------------------------------------------------- /CassiniShadedLiquidNeon/CassiniShadedLiquidNeon.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | PShader ovalShader; 4 | float margin; 5 | 6 | void setup() { 7 | size(1600, 900, P2D); 8 | pg = createGraphics(1920, 1080, P2D); 9 | margin = pg.width / 15.0; 10 | ovalShader = new PShader(this, "OvalVertShader.vert", "OvalFragShader.frag"); 11 | } 12 | 13 | void draw() { 14 | background(255); 15 | int nPoints = 10; 16 | float [] pointsX = new float[nPoints]; 17 | float [] pointsY = new float[nPoints]; 18 | float speedFactor = 0.45; 19 | 20 | float yInc = (pg.height - margin * 2) / nPoints; 21 | for (int i = 0; i < nPoints; i++) { 22 | pointsX[i] = pg.width / 2 + sin(radians(speedFactor * frameCount * noise(i) + i * 97)) * (pg.width / 2 - margin); 23 | pointsY[i] = margin + i * yInc + yInc / 2; 24 | } 25 | 26 | pg.beginDraw(); 27 | pg.shader(ovalShader); 28 | ovalShader.set("pointsX", pointsX); 29 | ovalShader.set("pointsY", pointsY); 30 | ovalShader.set("d", 1.0 * pg.width / 3 + pg.width / 16 * sin(radians(frameCount * 0.71))); 31 | ovalShader.set("powerAddition", 3.0 * pow(0.5 * (1 + (sin(radians(frameCount * 0.31)))), 2)); 32 | pg.rect(0, 0, pg.width, pg.height); 33 | pg.endDraw(); 34 | image(pg, 0, 0, width, height); 35 | println(frameCount / 60); 36 | } 37 | -------------------------------------------------------------------------------- /CassiniShadedLiquidNeon/data/OvalFragShader.frag: -------------------------------------------------------------------------------- 1 | varying vec2 va_pos; 2 | uniform float [10] pointsX; 3 | uniform float [10] pointsY; 4 | uniform float d; 5 | uniform float powerAddition; 6 | 7 | // animated take on the concept of Cassini ovals: https://mathworld.wolfram.com/CassiniOvals.html 8 | 9 | void main() { 10 | float prod = 1.0; 11 | for (int i = 0; i < pointsX.length; i++) { 12 | vec2 pt = vec2(pointsX[i], pointsY[i]); 13 | float r = length(pt - va_pos); 14 | prod *= r; 15 | } 16 | float f = 1.0 - prod / pow(d, pointsX.length); 17 | 18 | f = abs(1.5 - f) / 0.5; 19 | f = 2. * abs(0.5 - fract(pow(f, 0.1) * 5.)); 20 | vec3 col = vec3(max(0., pow(f, 0.2 + powerAddition)), 0., max(0., pow(f, 0.2 + powerAddition)) * 0.3); // //, 0., f); 21 | 22 | // f = abs(0.5 - f) / 0.5; 23 | // f = pow(f, 0.2 + powerAddition); 24 | // vec3 col = vec3(0.7 - f * 0.7, 1. - f, max(0., 0.3 + 0.7 - f * 0.7)); 25 | gl_FragColor = vec4(col, 1.0); 26 | } -------------------------------------------------------------------------------- /CassiniShadedLiquidNeon/data/OvalVertShader.vert: -------------------------------------------------------------------------------- 1 | uniform mat4 transformMatrix; 2 | attribute vec4 position; 3 | attribute vec4 color; 4 | varying vec4 va_color; 5 | varying vec2 va_pos; 6 | void main() { 7 | gl_Position = transformMatrix * position; 8 | va_color = color; 9 | va_pos = position.xy; 10 | } -------------------------------------------------------------------------------- /CircleOfCircles/CircleOfCircles.pde: -------------------------------------------------------------------------------- 1 | void setup() { 2 | size(900, 900, P2D); 3 | smooth(8); 4 | ellipseMode(RADIUS); 5 | } 6 | 7 | void draw() { 8 | background(0, 25, 35); 9 | noStroke(); 10 | PVector o = new PVector(width / 2, height / 2); 11 | float t = 0.2 + 0.8 * 0.5 * (1 + sin(radians(frameCount * 0.2))); 12 | float r = t * width / 3; 13 | float maxR = width / 2 - 10; 14 | int n = 1000; 15 | fill(255, 200, 150); 16 | for (int i = 0; i < n; i++) { 17 | float th = i * 2 * PI / n; 18 | float th2 = 2 * PI * mouseY / height + sin(radians(frameCount * 0.2)) * 4 * PI; 19 | float d = pow(PVector.fromAngle(th).sub(PVector.fromAngle(th2)).mag() / 2, 3); 20 | float nz = noise(i * 30000, frameCount * 0.01); 21 | float nzd = nz * (maxR - r) * d; 22 | PVector p = PVector.fromAngle(th + 0.01 * noise(i * 23456, frameCount * 0.023)).mult(r + nzd).add(o); 23 | circle(p.x, p.y, 1 + noise(i) * nzd / 15); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CirclePackingBubbles/CirclePackingBubbles.pde: -------------------------------------------------------------------------------- 1 | // "running" cirle packing for a random starting point, a minimum radius, and a maximum radius 2 | // each EdgeSet has an ArrayList of Circle(s) that must stay within the bounds of the EdgeSet 3 | // could be made more efficient with a quadtree but runs okay 4 | PGraphics pg; 5 | float minR = 4; 6 | float maxR = 200; 7 | int margin = 20; 8 | float spacing = 1; // extra pixels between circles 9 | float alpha = 25; 10 | int maxTries = 2000; // max number of attempts to generate random point not already circumscribed by a circle 11 | int countW = 1; // > 1 if you want a grid pattern 12 | int countH = 1; // > 1 if you want a grid pattern 13 | int circlesPerRound = 5; // number of circles to place and inflate at the same time 14 | ArrayList edgeSets; 15 | float maxDSquared; 16 | 17 | void setup() { 18 | size(900, 900, P2D); 19 | colorMode(HSB); 20 | pg = createGraphics(2160, 2160, P2D); 21 | pg.beginDraw(); 22 | pg.background(0); 23 | pg.stroke(0, 20); 24 | pg.ellipseMode(RADIUS); 25 | pg.strokeWeight(2); 26 | pg.colorMode(HSB); 27 | pg.background(0); 28 | pg.fill(0, 0, 255); 29 | pg.textSize(2000); 30 | pg.background(0); 31 | pg.endDraw(); 32 | maxDSquared = distSquared(new PVector(0, 0), new PVector(pg.width, pg.height)); 33 | edgeSets = new ArrayList(); 34 | float incW = 1.0 * pg.width / countW; 35 | float incH = 1.0 * pg.height / countH; 36 | for (int i = 0; i < countW; i++) { 37 | float left = i * incW; 38 | float right = (i + 1) * incW; 39 | for (int j = 0; j < countH; j++) { 40 | float top = j * incH; 41 | float bottom = (j + 1) * incH; 42 | EdgeSet es = new EdgeSet(left, right, top, bottom, circlesPerRound); 43 | es.baseColor = random(300); 44 | edgeSets.add(es); 45 | } 46 | } 47 | } 48 | 49 | void draw() { 50 | image(pg, 0, 0, 900, 900); 51 | boolean go = false; 52 | pg.beginDraw(); 53 | for (EdgeSet es : edgeSets) { 54 | if (es.live) { 55 | es.update(); 56 | } 57 | go = go || es.live; 58 | } 59 | pg.endDraw(); 60 | 61 | if (!go) { 62 | pg.save("output-1234.png"); 63 | noLoop(); 64 | } 65 | //println(frameCount); 66 | } 67 | 68 | void mouseClicked() { 69 | saveFrame("output-" + int(random(1000000000000.0)) + ".png"); 70 | } 71 | 72 | class Circle { 73 | 74 | PVector center; 75 | float r; 76 | boolean live = true; 77 | float maxRadius; 78 | 79 | Circle(float x, float y) { 80 | this.center = new PVector(x, y); 81 | this.r = minR; 82 | this.live = true; 83 | this.maxRadius = maxR; //minR + maxR * (1 - dSquared / maxDSquared); 84 | } 85 | 86 | boolean intersects(ArrayList circs) { 87 | for (Circle c : circs) { 88 | if (c != this && c.intersects(this)) { 89 | return true; 90 | } 91 | } 92 | return false; 93 | } 94 | 95 | boolean intersects(Circle other) { 96 | return distSquared(this.center, other.center) < (this.r + other.r + spacing) * (this.r + other.r + spacing); 97 | } 98 | 99 | boolean hitsEdges(float left, float right, float top, float bottom) { 100 | return this.center.x - r - spacing < left || this.center.x + r + spacing > right 101 | || this.center.y - r - spacing < top || this.center.y + r + spacing > bottom; 102 | } 103 | 104 | boolean boundsReached(EdgeSet es) { 105 | if (hitsEdges(es.left, es.right, es.top, es.bottom)) { 106 | return true; 107 | } 108 | return r > maxRadius; 109 | } 110 | 111 | Circle copy() { 112 | Circle c = new Circle(center.x, center.y); 113 | c.r = this.r; 114 | return c; 115 | } 116 | 117 | void show(float baseColor) { 118 | color fColor = color(100 + r / maxR * 100, 255, 255, alpha); 119 | pg.fill(fColor); 120 | pg.noStroke(); 121 | pg.ellipse(center.x, center.y, r, r); 122 | } 123 | 124 | } 125 | 126 | class EdgeSet { 127 | 128 | float left, right, top, bottom; 129 | ArrayList circles; 130 | ArrayList candidateList; 131 | boolean live = true; 132 | float baseColor; 133 | int candidateCount; 134 | 135 | EdgeSet(float left, float right, float top, float bottom, int candidateCount) { 136 | this.left = left; 137 | this.right = right; 138 | this.top = top; 139 | this.bottom = bottom; 140 | this.circles = new ArrayList(); 141 | this.candidateCount = candidateCount; 142 | newCandidates(candidateCount); 143 | } 144 | 145 | void newCandidates(int candidateCount) { 146 | this.candidateList = new ArrayList(); 147 | for (int i = 0; i < candidateCount; i++) { 148 | Circle c = newCandidate(this); 149 | if (c != null) { 150 | candidateList.add(c); 151 | } 152 | } 153 | } 154 | 155 | EdgeSet(float left, float right, float top, float bottom) { 156 | this(left, right, top, bottom, 0); 157 | } 158 | 159 | Circle newCandidate(EdgeSet es) { 160 | Circle c = new Circle(random(es.left + minR, es.right-minR), random(es.top + minR, es.bottom-minR)); 161 | for (int i = 0; i < maxTries; i++) { 162 | if (c.boundsReached(es) || c.intersects(circles) || c.intersects(candidateList)) { 163 | c = new Circle(random(es.left + minR, es.right-minR), random(es.top + minR, es.bottom-minR)); 164 | } else { 165 | return c; 166 | } 167 | } 168 | return null; 169 | } 170 | 171 | void update() { 172 | ArrayList toRemove = new ArrayList(); 173 | for (Circle candidate : candidateList) { 174 | if (candidate.boundsReached(this) || candidate.intersects(circles) || candidate.intersects(candidateList)) { 175 | candidate.r -= 1.0; 176 | circles.add(candidate); 177 | toRemove.add(candidate); 178 | } else { 179 | candidate.r++; 180 | } 181 | candidate.show(baseColor); 182 | } 183 | for (Circle c : toRemove) { 184 | candidateList.remove(c); 185 | Circle newCircle = newCandidate(this); 186 | if (newCircle != null) { 187 | candidateList.add(newCircle); 188 | } 189 | } 190 | if (candidateList.isEmpty()) { 191 | println("end"); 192 | noLoop(); 193 | } 194 | } 195 | } 196 | 197 | float distSquared(PVector a, PVector b) { 198 | return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y); 199 | } 200 | -------------------------------------------------------------------------------- /CirclePackingWithGrid2/CirclePackingWithGrid2.pde: -------------------------------------------------------------------------------- 1 | import processing.svg.*; 2 | import java.util.Date; 3 | 4 | PGraphics pg; 5 | boolean svg = false; 6 | int minRadius = 2; 7 | int maxRadius = 40; 8 | float padding = 1; 9 | ArrayList circles = new ArrayList(); 10 | Grid grid; 11 | boolean drawBg = true; 12 | boolean save = false; 13 | 14 | void setup() { 15 | size(900, 900, P2D); 16 | randomSeed(123L); 17 | noiseSeed(123L); 18 | colorMode(HSB, 360, 100, 100, 100); 19 | pg = createGraphics(4320, 4320, P2D); 20 | grid = new Grid(maxRadius * 2, pg.width, pg.height); 21 | smooth(8); 22 | pg.smooth(8); 23 | if (svg) { 24 | pg = createGraphics(900, 900, SVG, getClass().getName() + new Date().getTime() + ".svg"); 25 | } 26 | } 27 | 28 | void draw() { 29 | if (svg) { 30 | drawSVG(); 31 | } else { 32 | drawRaster(); 33 | } 34 | } 35 | 36 | void drawRaster() { 37 | pg.beginDraw(); 38 | if (frameCount < 3) { 39 | pg.ellipseMode(RADIUS); 40 | pg.fill(255, 225, 200); 41 | pg.noStroke(); 42 | //pg.stroke(0); 43 | pg.background(0); 44 | pg.colorMode(HSB, 360, 100, 100, 100); 45 | } else { 46 | int perFrame = 1000; 47 | for (int i = 0; i < perFrame; i++) { 48 | Circle c = placeCircle(); 49 | if (c != null) { 50 | circles.add(c); 51 | c.show(); 52 | } 53 | } 54 | } 55 | //println(circles.size()); 56 | if (save) { 57 | save = false; 58 | pg.save(getClass().getName() + new Date().getTime() + ".png"); 59 | println(circles.size()); 60 | exit(); 61 | } 62 | pg.endDraw(); 63 | println(frameRate); 64 | image(pg, 0, 0, width, height); 65 | } 66 | 67 | void drawSVG() { 68 | pg.beginDraw(); 69 | pg.ellipseMode(RADIUS); 70 | pg.fill(255, 225, 200); 71 | pg.noStroke(); 72 | //pg.stroke(0); 73 | pg.background(0); 74 | while (circles.size() < 35000) { 75 | Circle c = placeCircle(); 76 | if (c != null) { 77 | circles.add(c); 78 | println(circles.size()); 79 | } 80 | } 81 | for (Circle c : circles) { 82 | c.show(); 83 | } 84 | if (svg) { 85 | pg.dispose(); 86 | } 87 | pg.endDraw(); 88 | //image(pg, 0, 0, width, height); 89 | println("Done | " + circles.size()); 90 | noLoop(); 91 | } 92 | 93 | void mouseClicked() { 94 | save = true; 95 | } 96 | 97 | Circle placeCircle() { 98 | int tries = 0; 99 | int regions = 8; 100 | float regionSize = 0.95 * pg.width / 2 / regions; 101 | PVector canvasCenter = new PVector(pg.width / 2, pg.height / 2); 102 | while (tries < 1000) { 103 | float cr = sqrt(random(1)) * pg.width / 2 * 0.95; 104 | PVector p = new PVector(random(minRadius, pg.width - minRadius), random(minRadius, pg.height - minRadius)); 105 | Circle c = new Circle(p, minRadius); 106 | ArrayList close = grid.getCell(p.x, p.y).getOccupantsAndOccupantsOfNeighbors(); 107 | if (c.overlapAny(close, padding)) { 108 | tries++; 109 | continue; 110 | } else { 111 | 112 | PVector diff = p.copy().sub(new PVector(pg.width / 2, pg.height / 2)); 113 | float th = diff.heading(); 114 | color col = color(abs(th / PI) * 60, 80, 100); 115 | c.col = col; 116 | float fdist = diff.mag() / dist(pg.width / 2, pg.height / 2, 0, 0); 117 | float localMax = minRadius + (maxRadius - minRadius) * pow(0.5 * (1 + sin(noise(p.x * 0.003, p.y * 0.003) * TAU * 2)), 4); // minRadius + (maxRadius - minRadius) * pow(0.5 * (1 + sin(th * 5 + fdist * TAU * (0.1 + pow(fdist, 4) * 10))), 2); 118 | while(c.r <= localMax) { 119 | c.r += 0.1; 120 | if (c.overlapAny(close, padding) || c.outOfBounds(padding)) { 121 | c.r -= 0.1; 122 | break; 123 | } 124 | } 125 | grid.add(c, c.p.x, c.p.y); 126 | c.col = color(40 - 40 * c.r / localMax, 85, 100); 127 | return c; 128 | } 129 | } 130 | return null; 131 | } 132 | 133 | class Circle { 134 | 135 | PVector p; 136 | float r; 137 | Circle neighbor; 138 | color col; 139 | 140 | Circle(PVector p, float r) { 141 | this.p = p; 142 | this.r = r; 143 | } 144 | 145 | boolean overlap(Circle o, float pad) { 146 | return this.p.copy().sub(o.p).magSq() <= (this.r + o.r + pad) * (this.r + o.r + pad); 147 | } 148 | 149 | boolean overlapAny(ArrayList others, float pad) { 150 | for (Circle c : others) { 151 | if (this.overlap(c, pad)) { 152 | this.neighbor = c; 153 | return true; 154 | } 155 | } 156 | return false; 157 | } 158 | 159 | boolean outOfBounds(PVector c, float minR, float maxR) { 160 | float mag = p.copy().sub(c).mag(); 161 | return mag - r < minR || mag + r > maxR; 162 | } 163 | 164 | boolean outOfBounds(float padding) { 165 | return p.x - r - padding <= 0 || p.x + r + padding >= pg.width || p.y - r - padding <= 0 || p.y + r + padding >= pg.height; 166 | } 167 | 168 | void show() { 169 | //blob(p.x, p.y, r); 170 | //color colA = color(200, 225, 255); 171 | //color colB = color(0, 0, 255); 172 | //pg.fill(lerpColor(colB, colA, r / maxRadius)); 173 | pg.fill(col); 174 | pg.noStroke(); 175 | pg.circle(p.x, p.y, r); 176 | } 177 | 178 | } 179 | 180 | void blob(float x, float y, float r) { 181 | int n = ceil(r * TAU); 182 | PVector c = new PVector(x, y); 183 | color colA = color(200, 225, 255); 184 | color colB = color(0, 0, 255); 185 | pg.fill(lerpColor(colB, colA, r / maxRadius)); 186 | pg.beginShape(); 187 | for (int i = 0; i <= n; i++) { 188 | float th = i * TAU / n; 189 | float px = cos(th) * r + c.x; 190 | float py = sin(th) * r + c.y; 191 | float noize = noise(px * 0.05, py * 0.05, frameCount); 192 | PVector p = PVector.fromAngle(th).mult(r - r * noize).add(c); 193 | pg.vertex(p.x, p.y); 194 | } 195 | pg.endShape(); 196 | } 197 | -------------------------------------------------------------------------------- /CirclePackingWithGrid2/GridClass.pde: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | 3 | class Grid { 4 | 5 | Cell [][] cells; 6 | ArrayList occupants; 7 | int pixW, pixH; 8 | int w, h; 9 | float cellW, cellH; 10 | 11 | Grid(float maxElementDiameter, int pixW, int pixH) { 12 | this.pixW = pixW; 13 | this.pixH = pixH; 14 | this.w = round(pixW / (maxElementDiameter)); 15 | this.h = round(pixH / (maxElementDiameter)); 16 | cells = new Cell[w][h]; 17 | this.cellW = maxElementDiameter; 18 | this.cellH = maxElementDiameter; 19 | for (int i = 0; i < w; i++) { 20 | for (int j = 0; j < h; j++) { 21 | PVector pos = new PVector(i * cellW, j * cellH); 22 | cells[i][j] = new Cell(pos, cellW, cellH); 23 | } 24 | } 25 | for (int x = 0; x < w; x++) { 26 | for (int y = 0; y < h; y++) { 27 | Cell c = cells[x][y]; 28 | c.neighbors = getNeighbors(x, y); 29 | } 30 | } 31 | occupants = new ArrayList(); 32 | } 33 | 34 | Grid(int w, int h, int pixW, int pixH) { 35 | cells = new Cell[w][h]; 36 | 37 | this.pixW = pixW; 38 | this.pixH = pixH; 39 | this.cellW = 1.0 * pixW / w; 40 | this.cellH = 1.0 * pixH / h; 41 | for (int i = 0; i < w; i++) { 42 | for (int j = 0; j < h; j++) { 43 | PVector pos = new PVector(i * cellW, j * cellH); 44 | cells[i][j] = new Cell(pos, cellW, cellH); 45 | } 46 | } 47 | for (int x = 0; x < w; x++) { 48 | for (int y = 0; y < h; y++) { 49 | Cell c = cells[x][y]; 50 | c.neighbors = getNeighbors(x, y); 51 | } 52 | } 53 | this.w = w; 54 | this.h = h; 55 | occupants = new ArrayList(); 56 | } 57 | 58 | void add(T t, float xPixPos, float yPixPos) { 59 | int x = int(xPixPos / cellW); 60 | int y = int(yPixPos / cellW); 61 | cells[x][y].occupants.add(t); 62 | occupants.add(t); 63 | } 64 | 65 | void add(PVector p) { 66 | int x = int(p.x / cellW); 67 | int y = int(p.y / cellW); 68 | cells[x][y].occupants.add(p); 69 | } 70 | 71 | ArrayList getCellMembers(int x, int y) { 72 | return new ArrayList(cells[x][y].occupants); 73 | } 74 | 75 | Cell getCell(float xPixPos, float yPixPos) { 76 | int x = int(xPixPos / cellW); 77 | int y = int(yPixPos / cellW); 78 | return cells[x][y]; 79 | } 80 | 81 | Cell getCell(int x, int y) { 82 | if (x < 0 || x >= w || y < 0 || y >= h) { 83 | return null; 84 | } else { 85 | return cells[x][y]; 86 | } 87 | } 88 | 89 | ArrayList getNeighbors(int x, int y) { 90 | ArrayList results = new ArrayList(); 91 | for (int i = -1; i <= 1; i++) { 92 | for (int j = -1; j <= 1; j++) { 93 | Cell c = getCell(x + i, y + j); 94 | if (c != null && !(i == 0 && j == 0)) { 95 | results.add(c); 96 | } 97 | } 98 | } 99 | return results; 100 | } 101 | 102 | void show() { 103 | for (Cell [] array : cells) { 104 | for (Cell c : array) { 105 | c.show(); 106 | } 107 | } 108 | } 109 | 110 | void showVectors() { 111 | for (Cell [] array : cells) { 112 | for (Cell c : array) { 113 | c.showVectors(); 114 | } 115 | } 116 | } 117 | 118 | } 119 | 120 | class Cell { 121 | 122 | PVector pos; 123 | int id; 124 | float w, h; 125 | color fillColor; 126 | ArrayList neighbors; 127 | HashSet occupants; 128 | boolean active; 129 | 130 | Cell(PVector pos, float w, float h) { 131 | this.pos = pos; 132 | this.w = w; 133 | this.h = h; 134 | this.occupants = new HashSet(); 135 | this.neighbors = new ArrayList(); 136 | } 137 | 138 | void add(T t) { 139 | occupants.add(t); 140 | } 141 | 142 | void remove(T t) { 143 | occupants.remove(t); 144 | } 145 | 146 | void show() { 147 | noFill(); 148 | stroke(255, 0, 0); 149 | if (active) { 150 | stroke(255, 0, 0); 151 | } 152 | strokeWeight(1); 153 | rect(pos.x, pos.y, w, h); 154 | } 155 | 156 | ArrayList getOccupantsAndOccupantsOfNeighbors() { 157 | ArrayList results = new ArrayList(); 158 | for (Cell c : neighbors) { 159 | results.addAll(c.occupants); 160 | } 161 | results.addAll(occupants); 162 | return results; 163 | } 164 | 165 | ArrayList getOccupantsOfNeighbors() { 166 | ArrayList results = new ArrayList(); 167 | for (Cell c : neighbors) { 168 | results.addAll(c.occupants); 169 | } 170 | return results; 171 | } 172 | 173 | void showVectors() { 174 | strokeWeight(4); 175 | for (T o : occupants) { 176 | PVector p = (PVector) o; 177 | point(p.x, p.y); 178 | } 179 | } 180 | 181 | boolean contains(float x, float y) { 182 | return x >= pos.x && y >= pos.y && x <= pos.x + w && y <= pos.y + h; 183 | } 184 | 185 | } 186 | -------------------------------------------------------------------------------- /ColorStreamsFromImage/ColorStreamsFromImage.pde: -------------------------------------------------------------------------------- 1 | PImage img; 2 | PGraphics pg; 3 | PShader shader; 4 | 5 | void setup() { 6 | size(1600, 900, P3D); 7 | pg = createGraphics(1920, 1080, P3D); 8 | shader = new PShader(this, "VertShader.vert", "PixelWaveFragShader.frag"); 9 | img = loadImage("fruit3.png"); 10 | } 11 | 12 | void draw() { 13 | pg.beginDraw(); 14 | pg.background(0); 15 | pg.image(img, 0, 0, pg.width, pg.height); 16 | if (frameCount == 1) { 17 | pg.loadPixels(); 18 | } 19 | float t = 0.5 * (1 + sin(radians(frameCount * 0.05))); 20 | int y = min(pg.height - 1, int(t * pg.height)); 21 | PImage sampler = img.get(0, y, img.width, 1); 22 | pg.noStroke(); 23 | shader.set("sampler", sampler); 24 | shader.set("resolution", float(img.width), float(img.height)); 25 | shader.set("iTime", radians(frameCount)); 26 | pg.shader(shader); 27 | pg.rect(0, 0, pg.width, pg.height); 28 | pg.endDraw(); 29 | image(pg, 0, 0, width, height); 30 | println(frameCount / 60); 31 | } 32 | -------------------------------------------------------------------------------- /ColorStreamsFromImage/data/PixelWaveFragShader.frag: -------------------------------------------------------------------------------- 1 | varying vec2 va_pos; 2 | uniform vec2 resolution; 3 | uniform sampler2D sampler; 4 | uniform int y; 5 | uniform float iTime; 6 | 7 | void main() 8 | { 9 | vec2 uv = va_pos / resolution.xy; 10 | // float xPivot = 0.5 + 0.2 * sin(iTime * 0.1); 11 | float f = 1. - 4. * uv.x * uv.y; 12 | float freq = 2.5 - 5. * 0.5 * (1. + sin(iTime * 0.2)); 13 | float xpos = mod(uv.x + f * 0.5 * (1. + sin(freq * uv.y + iTime)), 1.); 14 | vec3 col = texture(sampler, vec2(xpos, 0.)).rgb; 15 | 16 | gl_FragColor = vec4(col, 1.0); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /ColorStreamsFromImage/data/VertShader.vert: -------------------------------------------------------------------------------- 1 | uniform mat4 transformMatrix; 2 | attribute vec4 position; 3 | attribute vec4 color; 4 | varying vec4 va_color; 5 | varying vec2 va_pos; 6 | void main() { 7 | gl_Position = transformMatrix * position; 8 | va_color = color; 9 | va_pos = position.xy; 10 | } -------------------------------------------------------------------------------- /ColorStreamsFromImage/data/fruit3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brian-Fearn/Processing/e1058f7c372427491d059a67dd917afc56cec65f/ColorStreamsFromImage/data/fruit3.png -------------------------------------------------------------------------------- /ConcentricParticles/ConcentricParticles.pde: -------------------------------------------------------------------------------- 1 | Attractor att = new Attractor(new PVector(0, 0)); 2 | color bgColor; 3 | color strokeColor; 4 | ArrayList> cPoints = new ArrayList>(); 5 | ArrayList points = new ArrayList(); 6 | int PARTICLE_MODE = 0; 7 | int DEFORM_MODE = 1; 8 | int mode = PARTICLE_MODE; 9 | int dir = 1; 10 | boolean reform = true; 11 | int margin = 25; 12 | float maxD; 13 | PGraphics pg; 14 | 15 | void setup() { 16 | size(900, 900, P3D); 17 | colorMode(HSB, 360, 100, 100, 100); 18 | pg = createGraphics(1080, 1080, P3D); 19 | pg.smooth(8); 20 | pg.beginDraw(); 21 | pg.colorMode(HSB, 360, 100, 100, 100); 22 | pg.strokeWeight(mode == PARTICLE_MODE ? 3 : 2); 23 | bgColor = color(250, 100, 10); 24 | pg.blendMode(ADD); 25 | cursor(ARROW); 26 | pg.background(bgColor); 27 | pg.noFill(); 28 | pg.endDraw(); 29 | int pixPerSegment = 5; 30 | maxD = sqrt(pg.width * pg.width + pg.height * pg.height); 31 | float baseHue = 200; // random(0, 280); 32 | for (int r = 440; r >= 10; r -= 10) { 33 | ArrayList list = circlePoints(pg.width / 2, pg.height / 2, r, pixPerSegment); 34 | for (Particle p : list) { 35 | p.c = color(baseHue + 80.0 * r / 440, 60, 100); //85, 100); 36 | } 37 | cPoints.add(list); 38 | points.addAll(list); 39 | } 40 | } 41 | 42 | void draw() { 43 | PVector mouse = new PVector(map(mouseX, 0, width, 0, pg.width), map(mouseY, 0, height, 0, pg.height)); 44 | att.pos = mouse; 45 | int button = 0; 46 | if (mousePressed) { 47 | button = mouseButton; 48 | } 49 | pg.beginDraw(); 50 | pg.background(bgColor); 51 | 52 | if (mode == PARTICLE_MODE) { 53 | if (mousePressed && mouseButton == LEFT) { 54 | button = 1; 55 | } else if (mousePressed && mouseButton == RIGHT) { 56 | button = -1; 57 | } 58 | for (Particle p : points) { 59 | PVector f = att.calcForce(p, button); 60 | f.mult(10); 61 | p.acc.add(f); 62 | p.update(); 63 | pg.stroke(p.c); 64 | pg.point(p.x, p.y); 65 | } 66 | } else if (mode == DEFORM_MODE) { 67 | switch(button) { 68 | case LEFT: 69 | deform(points, true); 70 | break; 71 | case RIGHT: 72 | deform(points, false); 73 | break; 74 | case CENTER: 75 | deformRadial(points); 76 | break; 77 | default: 78 | break; 79 | } 80 | for (Particle p : points) { 81 | p.update(); 82 | pg.stroke(p.c); 83 | pg.point(p.x, p.y); 84 | } 85 | } 86 | 87 | pg.fill(0, 100, 100, 100); 88 | pg.noStroke(); 89 | pg.circle(mouse.x, mouse.y, 6); 90 | pg.noFill(); 91 | pg.endDraw(); 92 | image(pg, 0, 0, width, height); 93 | //println(frameCount / 60); 94 | println(frameRate); 95 | } 96 | 97 | void keyPressed() { 98 | if (key == CODED) { 99 | if (keyCode == UP) { 100 | dir *= -1; 101 | } 102 | if (keyCode == DOWN) { 103 | mode = 1 - mode; 104 | } 105 | } 106 | } 107 | 108 | void deform(ArrayList set, boolean attract) { 109 | Particle c = new Particle(map(mouseX, 0, width, 0, pg.width), map(mouseY, 0, height, 0, pg.height)); // new Particle(width / 2, height / 2); 110 | float maxDiagonal = getMaxDist(c, set); 111 | for (Particle p : set) { 112 | float d = dist(p.x, p.y, c.x, c.y); 113 | float dFactor = attract ? 1 - 0.25 * pow(1 - d / maxDiagonal, 4) : 1 + 0.25 * pow(1 - d / maxDiagonal, 4); 114 | Particle temp = p.copy(); 115 | temp.sub(c); 116 | temp.mult(dFactor); 117 | temp.add(c); 118 | p.x = temp.x; 119 | p.y = temp.y; 120 | } 121 | } 122 | 123 | void deformRadial(ArrayList set) { 124 | Particle c = new Particle(map(mouseX, 0, width, 0, pg.width), map(mouseY, 0, height, 0, pg.height)); 125 | float maxDiagonal = getMaxDist(c, set); 126 | for (Particle p : set) { 127 | float d = dist(p.x, p.y, c.x, c.y); 128 | float dFactor = pow(1 - d / maxDiagonal, 2.5); 129 | rotateWithRespectTo(p, c, dir * dFactor * PI / 16); 130 | } 131 | } 132 | 133 | float getMaxDist(Particle p, ArrayList set) { 134 | if (set.isEmpty()) { 135 | return 0; 136 | } 137 | float maxDistSq = Float.MIN_VALUE; 138 | for (Particle v : set) { 139 | float dSq = v.copy().sub(p).magSq(); 140 | if (dSq > maxDistSq) { 141 | maxDistSq = dSq; 142 | } 143 | } 144 | return sqrt(maxDistSq); 145 | } 146 | 147 | void rotateWithRespectTo(Particle p, Particle v, float angle) { 148 | p.sub(v); 149 | p.rotate(angle); 150 | p.add(v); 151 | } 152 | 153 | void rotateWithRespectTo(PVector p, PVector v, float angle) { 154 | p.sub(v); 155 | p.rotate(angle); 156 | p.add(v); 157 | } 158 | 159 | ArrayList linePoints(float x1, float y1, float x2, float y2, int pixPerSegment) { 160 | float d = dist(x1, y1, x2, y2); 161 | Particle a = new Particle(x1, y1); 162 | Particle b = new Particle(x2, y2); 163 | Particle diff = (Particle) b.copy().sub(a).normalize().mult(pixPerSegment); 164 | 165 | int n = int(d / pixPerSegment); 166 | ArrayList points = new ArrayList(); 167 | for (int i = 0; i <= n; i++) { 168 | points.add((Particle) a.copy().add(diff.copy().mult(i))); 169 | } 170 | return points; 171 | } 172 | 173 | ArrayList circlePoints(float x, float y, float r, int pixPerSegment) { 174 | float c = 2 * PI * r; 175 | int n = int(c / pixPerSegment); 176 | float inc = 2 * PI / n; 177 | 178 | ArrayList points = new ArrayList(); 179 | for (int i = 0; i < n; i++) { 180 | float angle = i * inc; 181 | points.add(new Particle(x + r * cos(angle), y + r * sin(angle))); 182 | } 183 | return points; 184 | } 185 | 186 | class Particle extends PVector { 187 | 188 | PVector init; 189 | PVector v; 190 | color c; 191 | 192 | PVector pos; 193 | PVector vel; 194 | PVector acc; 195 | 196 | Particle(float x, float y) { 197 | this.pos = new PVector(x, y); 198 | this.vel = new PVector(0, 0); 199 | this.acc = new PVector(0, 0); 200 | this.x = x; 201 | this.y = y; 202 | this.init = new PVector(x, y); 203 | this.v = new PVector(0, 0); 204 | } 205 | 206 | void update() { 207 | if (mode == PARTICLE_MODE) { 208 | vel.add(acc); 209 | vel.limit(5); 210 | checkBounds(); 211 | x += vel.x; 212 | y += vel.y; 213 | this.vel.mult(0.997); 214 | acc.mult(0); 215 | } 216 | if (reform) { 217 | Particle curr = new Particle(x, y); 218 | curr.lerp(init, 0.005); 219 | this.x = curr.x; 220 | this.y = curr.y; 221 | } 222 | } 223 | 224 | void checkBounds() { 225 | if (x < margin || x > pg.width - margin) { 226 | vel.x *= -1; 227 | } 228 | if (y < margin || y > pg.height - margin) { 229 | vel.y *= -1; 230 | } 231 | } 232 | 233 | Particle copy() { 234 | Particle p = new Particle(x, y); 235 | p.init = this.init.copy(); 236 | return p; 237 | } 238 | 239 | } 240 | 241 | class Attractor { 242 | 243 | PVector pos; 244 | boolean active; 245 | 246 | Attractor(PVector pos) { 247 | this.pos = pos; 248 | active = false; 249 | } 250 | 251 | PVector calcForce(PVector otherPos, int charge) { 252 | if (charge == 0) { 253 | return new PVector(0, 0); 254 | } 255 | PVector vec = charge == 1 ? pos.copy().sub(otherPos) : otherPos.copy().sub(pos); 256 | float magSq = vec.mag(); 257 | return vec.mult(500.0 / magSq).limit(5); 258 | } 259 | 260 | void show() { 261 | fill(active ? color(0, 255, 0) : color(255, 0, 0)); 262 | ellipse(pos.x, pos.y, 30, 30); 263 | } 264 | 265 | } 266 | -------------------------------------------------------------------------------- /ConcentricParticles/README.md: -------------------------------------------------------------------------------- 1 | A sketch for playing with particles. There are two "modes" of control, a more "physical" one taking into account velocity, acceleration, and so on, and one that simply deforms the position of each particle directly. Effects include repulsion, attraction, and rotation. 2 | 3 | ![output44](https://user-images.githubusercontent.com/101308215/161361435-b4a86061-b1ea-440f-aed8-844120df0815.png) 4 | ![output29](https://user-images.githubusercontent.com/101308215/161361437-4226a02c-14ad-49a5-8fb8-85d14c6270f9.png) 5 | ![output3](https://user-images.githubusercontent.com/101308215/161361438-2851fb23-7bd0-4ba6-8c52-b00880c5123e.png) 6 | ![output0](https://user-images.githubusercontent.com/101308215/161361439-dcae802a-8783-455a-9b93-a091dadd0ccf.png) 7 | -------------------------------------------------------------------------------- /CosmicEggs/CosmicEggs.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | int margin = 40; 3 | PVector c; 4 | float r; 5 | float fuzz = 0.15; 6 | float _power = 0.25; 7 | 8 | void setup() { 9 | size(900, 900, P2D); 10 | pg = createGraphics(1080, 1080, P2D); 11 | pg.smooth(8); 12 | pg.beginDraw(); 13 | pg.colorMode(HSB, 360, 100, 100, 100); 14 | pg.blendMode(ADD); 15 | pg.background(225, 100, 0); 16 | pg.stroke(225 + random(-25, 25), 70, 100, 15); 17 | pg.ellipseMode(RADIUS); 18 | pg.endDraw(); 19 | r = (pg.width - margin * 2) / 20; 20 | c = new PVector(margin + r, margin + r); 21 | } 22 | 23 | boolean save = false; 24 | 25 | void draw() { 26 | pg.beginDraw(); 27 | if (frameCount == 1) { 28 | pg.background(0); 29 | } 30 | pg.noStroke(); 31 | pg.blendMode(BLEND); 32 | pg.fill(0, 0, 0, 100); 33 | 34 | if (c.x > pg.width - r - margin) { 35 | pg.noFill(); 36 | pg.noStroke(); 37 | noLoop(); 38 | } 39 | if (save) { 40 | save = false; 41 | pg.save("output" + int(random(1000000)) + ".png"); 42 | } 43 | pg.circle(c.x, c.y, r); 44 | pg.blendMode(ADD); 45 | pg.stroke(300 + random(-50, 50), 70, 100, 15); 46 | pg.noFill(); 47 | 48 | int perFrame = 30000; 49 | for (int i = 0; i < perFrame; i++) { 50 | pg.strokeWeight(random(2)); 51 | PVector p = randomInCircle(c, r, _power, fuzz, 0, 2 * PI); 52 | pg.point(p.x, p.y); 53 | } 54 | c.y += r * 1.25; 55 | if (c.y > pg.height - r - margin) { 56 | c.y = r + margin; 57 | c.x += r * 1.25; 58 | } 59 | pg.endDraw(); 60 | image(pg, 0, 0, width, height); 61 | } 62 | 63 | void mouseClicked() { 64 | save = true; 65 | } 66 | 67 | PVector randomInCircle(PVector c, float r, float power, float fuzz, float start, float end) { 68 | float f = pow(random(1), power); 69 | float r2 = f * (r + r * random(fuzz)); 70 | return PVector.fromAngle(random(start, end)).mult(r2).add(c); 71 | } 72 | -------------------------------------------------------------------------------- /DebrisField/DebrisField.pde: -------------------------------------------------------------------------------- 1 | import processing.svg.*; 2 | import java.util.Date; 3 | 4 | PGraphics pg; 5 | boolean svg = false; 6 | int minRadius = 1; 7 | int maxRadius = 20; 8 | float padding = -1; 9 | ArrayList circles = new ArrayList(); 10 | boolean drawBg = true; 11 | boolean save = false; 12 | 13 | void setup() { 14 | size(900, 900, P2D); 15 | randomSeed(123L); 16 | noiseSeed(123L); 17 | pg = createGraphics(900, 900, P2D); 18 | smooth(8); 19 | pg.smooth(8); 20 | if (svg) { 21 | pg = createGraphics(900, 900, SVG, getClass().getName() + new Date().getTime() + ".svg"); 22 | } 23 | } 24 | 25 | void draw() { 26 | if (svg) { 27 | drawSVG(); 28 | } else { 29 | drawRaster(); 30 | } 31 | } 32 | 33 | void drawRaster() { 34 | pg.beginDraw(); 35 | if (frameCount < 3) { 36 | pg.ellipseMode(RADIUS); 37 | pg.fill(255, 225, 200); 38 | pg.noStroke(); 39 | //pg.stroke(0); 40 | pg.background(0); 41 | } else { 42 | int perFrame = 100; 43 | for (int i = 0; i < perFrame; i++) { 44 | Circle c = placeCircle(); 45 | if (c != null) { 46 | circles.add(c); 47 | c.show(); 48 | } 49 | } 50 | } 51 | println(circles.size()); 52 | pg.endDraw(); 53 | image(pg, 0, 0, width, height); 54 | } 55 | 56 | void drawSVG() { 57 | pg.beginDraw(); 58 | pg.ellipseMode(RADIUS); 59 | pg.fill(255, 225, 200); 60 | pg.noStroke(); 61 | //pg.stroke(0); 62 | pg.background(0); 63 | while (circles.size() < 35000) { 64 | Circle c = placeCircle(); 65 | if (c != null) { 66 | circles.add(c); 67 | println(circles.size()); 68 | } 69 | } 70 | for (Circle c : circles) { 71 | c.show(); 72 | } 73 | if (svg) { 74 | pg.dispose(); 75 | } 76 | pg.endDraw(); 77 | //image(pg, 0, 0, width, height); 78 | println("Done | " + circles.size()); 79 | noLoop(); 80 | } 81 | 82 | void mouseClicked() { 83 | save = true; 84 | } 85 | 86 | Circle placeCircle() { 87 | int tries = 0; 88 | while (tries < 1000) { 89 | PVector p = new PVector(random(minRadius, pg.width - minRadius), random(minRadius, pg.height - minRadius)); 90 | Circle c = new Circle(p, minRadius); 91 | if (c.overlapAny(circles, padding)) { 92 | tries++; 93 | continue; 94 | } else { 95 | float y = p.y + pg.height / 13 * sin(p.x / pg.width * TAU * 2); 96 | float localMax = minRadius + (maxRadius - minRadius) * pow(abs(y - pg.height / 2) / (pg.height / 2), 1); 97 | while(c.r <= localMax) { 98 | c.r += 0.1; 99 | if (c.overlapAny(circles, padding) || c.outOfBounds(padding)) { 100 | c.r -= 0.1; 101 | break; 102 | } 103 | } 104 | return c; 105 | } 106 | } 107 | return null; 108 | } 109 | 110 | class Circle { 111 | 112 | PVector p; 113 | float r; 114 | Circle neighbor; 115 | 116 | Circle(PVector p, float r) { 117 | this.p = p; 118 | this.r = r; 119 | } 120 | 121 | boolean overlap(Circle o, float pad) { 122 | return this.p.copy().sub(o.p).magSq() <= (this.r + o.r + pad) * (this.r + o.r + pad); 123 | } 124 | 125 | boolean overlapAny(ArrayList others, float pad) { 126 | for (Circle c : others) { 127 | if (this.overlap(c, pad)) { 128 | this.neighbor = c; 129 | return true; 130 | } 131 | } 132 | return false; 133 | } 134 | 135 | boolean outOfBounds(float padding) { 136 | return p.x - r - padding <= 0 || p.x + r + padding >= pg.width || p.y - r - padding <= 0 || p.y + r + padding >= pg.height; 137 | } 138 | 139 | void show() { 140 | blob(p.x, p.y, r); 141 | //pg.circle(p.x, p.y, r); 142 | } 143 | 144 | } 145 | 146 | void blob(float x, float y, float r) { 147 | int n = ceil(r * TAU); 148 | PVector c = new PVector(x, y); 149 | color colA = color(200, 225, 255); 150 | color colB = color(0, 0, 255); 151 | pg.fill(lerpColor(colB, colA, r / maxRadius)); 152 | pg.beginShape(); 153 | for (int i = 0; i <= n; i++) { 154 | float th = i * TAU / n; 155 | float px = cos(th) * r + c.x; 156 | float py = sin(th) * r + c.y; 157 | float noize = noise(px * 0.05, py * 0.05, frameCount); 158 | PVector p = PVector.fromAngle(th).mult(r - r * noize).add(c); 159 | pg.vertex(p.x, p.y); 160 | } 161 | pg.endShape(); 162 | } 163 | -------------------------------------------------------------------------------- /DeepBlueRadiance/DeepBlueRadiance.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | ArrayList particles = new ArrayList(); 4 | 5 | int nParticles = 6000; 6 | float angleNoise = 0.00; 7 | float noiseScale = 0.01; 8 | boolean randomizeInitAngles = false; 9 | color lightPurple = color(245, 235, 255); 10 | color white = color(255); 11 | color offWhite = color(255, 250, 215); 12 | color bgColor = white; // lightPurple; 13 | color fillColor = color(255, 245, 125); 14 | float shadeFrequency = 1.0; 15 | float shadeMultiplier = 0; // set to 0 for rings rather than spiral 16 | float shadePower = 1; // higher means more contrast between dark and light 17 | float rotationFrequency = 0.4; 18 | float baseNoiseExpansionSpeed = 1.5; 19 | float noiseExpansionMix = 0.6; // 0 to expand in circular rings, 1 to make the expansion "noisy" 20 | float radiusRange = 9; // how big can circles get? 21 | float circleAlpha = 3.5; 22 | long rSeed; 23 | int blendType = SUBTRACT; 24 | 25 | void setup() { 26 | size(900, 900, P2D); 27 | rSeed = (long) random(1000000000); 28 | randomSeed(rSeed); 29 | noiseSeed(rSeed); 30 | pg = createGraphics(1080, 1080, P2D); 31 | pg.smooth(8); 32 | pg.beginDraw(); 33 | pg.blendMode(blendType); 34 | for (int i = 0; i < nParticles; i++) { 35 | float th = randomizeInitAngles ? random(2 * PI) : 2 * PI * i / nParticles; 36 | particles.add(new Mover(new PVector(pg.width / 2, pg.height / 2), th)); 37 | } 38 | pg.fill(255, 225, 105, 10); 39 | pg.noStroke(); 40 | pg.endDraw(); 41 | } 42 | 43 | void draw() { 44 | pg.beginDraw(); 45 | if (frameCount == 1) { 46 | pg.background(bgColor); 47 | } 48 | for (Mover p : particles) { 49 | p.update(); 50 | p.show(); 51 | } 52 | pg.endDraw(); 53 | image(pg, 0, 0, width, height); 54 | println(frameRate); 55 | } 56 | 57 | void mouseClicked() { 58 | pg.save(this.getClass().getName() + rSeed + ".png"); 59 | } 60 | 61 | class Mover { 62 | 63 | PVector pos; 64 | float th; 65 | color c; 66 | 67 | Mover(PVector pos, float th) { 68 | this.pos = pos; 69 | this.th = th; 70 | this.c = color(fillColor); 71 | } 72 | 73 | void update() { 74 | th += 0.01 * cos(radians(frameCount * rotationFrequency)) + random(-angleNoise, angleNoise);; 75 | PVector p = pos.copy(); 76 | float t = pow(0.5 * (1 + sin(radians(frameCount * 0.5) + th)), 1); 77 | float vn = noise(p.x * noiseScale, p.y * noiseScale) * baseNoiseExpansionSpeed; 78 | float v = 0.1 + 0.9 * t; 79 | v = lerp(v, vn, noiseExpansionMix); 80 | pos.add(PVector.fromAngle(th).mult(v)); 81 | } 82 | 83 | void show() { 84 | float ft = random(0.0) + 1.0 * pow(0.5 * (1 + sin(radians(frameCount * shadeFrequency) + th * shadeMultiplier)), shadePower); 85 | pg.fill(c, circleAlpha); 86 | if (pos.x > 0 && pos.x < pg.width && pos.y > 0 && pos.y < pg.height) { 87 | pg.circle(pos.x, pos.y, 1 + radiusRange * ft * pow(dist(pos.x, pos.y, pg.width / 2, pg.height / 2) / pg.width, 1)); 88 | } 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /DemoContainedWaves/DemoContainedWaves.pde: -------------------------------------------------------------------------------- 1 | int margin = 25; 2 | 3 | void setup() { 4 | size(900, 900, P3D); 5 | colorMode(HSB, 360, 100, 100, 100); 6 | smooth(8); 7 | ellipseMode(RADIUS); 8 | frameRate(60); 9 | stroke(40, 50, 100); 10 | strokeWeight(3); 11 | noFill(); 12 | } 13 | 14 | void draw() { 15 | background(225, 100, 20); 16 | PVector origin = new PVector(width / 2, height / 2); 17 | float r = (width - margin * 2) / 2; 18 | circle(origin.x, origin.y, r); 19 | int waveCount = 75; 20 | float angleInc = PI / waveCount; 21 | float timeOffset = radians(frameCount * 3); 22 | float waveAmp = sin(radians(frameCount * 0.5)); 23 | for (int i = 0; i < waveCount; i++) { 24 | float angle = PI / 2 + i * angleInc; 25 | PVector rimPoint = PVector.fromAngle(angle).mult(r).add(origin); 26 | PVector temp = rimPoint.copy().sub(origin); 27 | PVector rimPoint2 = new PVector(-temp.x, temp.y).add(origin); 28 | int pointCount = int(abs(temp.x) / 1); 29 | float waveMag = 300.0 * waveAmp; 30 | stroke(i % 2 == 0 ? 40 : 0, 50, 100); 31 | beginShape(); 32 | for (int j = 0; j <= pointCount; j++) { 33 | PVector p = PVector.lerp(rimPoint, rimPoint2, 1.0 * j / pointCount); 34 | float x = map(p.x, rimPoint.x, rimPoint2.x, 0, 1); 35 | float xFactor = 1 - pow(2 * x - 1, 2); // contain range of waves 36 | float yFactor = 1 - abs(temp.y / r); // contain range of waves 37 | float sineValue = sin(2 * PI * x * 3 + timeOffset); 38 | float yDistortion = yFactor * xFactor * waveMag * sineValue; 39 | vertex(p.x, p.y + yDistortion); 40 | } 41 | endShape(); 42 | } 43 | println(frameRate); 44 | } 45 | -------------------------------------------------------------------------------- /DemoTaperedLines/DemoTaperedLines.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | void setup() { 4 | size(900, 900, P3D); 5 | pg = createGraphics(1080, 1080, P3D); 6 | pg.smooth(8); 7 | pg.beginDraw(); 8 | pg.background(255); 9 | pg.endDraw(); 10 | } 11 | 12 | void draw() { 13 | pg.beginDraw(); 14 | pg.background(255); 15 | pg.stroke(0); 16 | pg.strokeWeight(2); 17 | float xInc = 50 + 200 * (0.5 * (1 + sin(radians(frameCount * 0.5)))); 18 | float yInc = 50 + 200 * (0.5 * (1 + sin(radians(PI / 3 + frameCount * 0.3)))); 19 | for (float y = yInc; y < pg.height + yInc; y += yInc) { 20 | pg.beginShape(); 21 | for (int x = 0; x <= pg.width; x += 5) { 22 | float f = pow(1.0 * abs(x - pg.width / 2) / (pg.width / 2), 2); 23 | pg.strokeWeight(1 + yInc / 2.0 * f); 24 | pg.vertex(x, y); 25 | } 26 | pg.endShape(); 27 | } 28 | pg.strokeWeight(2); 29 | for (float x = xInc; x < pg.width + xInc; x += xInc) { 30 | pg.beginShape(); 31 | for (int y = 0; y <= pg.height; y += 5) { 32 | float f = pow(1.0 * abs(y - pg.height / 2) / (pg.height / 2), 2); 33 | pg.strokeWeight(1 + xInc / 2.0 * f); 34 | pg.vertex(x, y); 35 | } 36 | pg.endShape(); 37 | } 38 | pg.endDraw(); 39 | image(pg, 0, 0, width, height); 40 | if (frameCount % 60 == 0) { 41 | println(frameCount / 60); 42 | } 43 | //println(frameRate); 44 | } 45 | -------------------------------------------------------------------------------- /DifferenceMode3Waves/DifferenceMode3Waves.pde: -------------------------------------------------------------------------------- 1 | ArrayList> curvePair = new ArrayList>(); 2 | PGraphics pg; 3 | int yInc = 70; 4 | int margin = 20; 5 | color bgColor = color(0); 6 | color strokeColor = color(255, 200, 175); 7 | import com.jogamp.opengl.*; 8 | com.jogamp.opengl.GL3 gl; 9 | 10 | void setup() { 11 | size(900, 900, P3D); 12 | colorMode(RGB, 255, 255, 255, 1.0); 13 | blendMode(DIFFERENCE); 14 | pg = createGraphics(1080, 1080, P3D); 15 | pg.smooth(8); 16 | 17 | pg.beginDraw(); 18 | pg.blendMode(DIFFERENCE); 19 | pg.colorMode(RGB, 255, 255, 255, 1.0); 20 | pg.background(bgColor); 21 | pg.endDraw(); 22 | } 23 | 24 | boolean save = false; 25 | int freq = 2; 26 | 27 | void draw() { 28 | background(0); 29 | pg.beginDraw(); 30 | pg.translate(pg.width / 2, pg.height / 2); 31 | 32 | pg.beginPGL().enable(GL3.GL_BLEND); 33 | pg.beginPGL().blendFunc(GL3.GL_ONE_MINUS_DST_COLOR, GL3.GL_ZERO); 34 | pg.fill(255, 0, 170); 35 | pg.background(bgColor); 36 | //pg.stroke(strokeColor); 37 | //pg.strokeWeight(4); 38 | pg.noStroke(); 39 | 40 | int n = 500; 41 | float inc = 2 * PI / n; 42 | float tFactor = sin(radians(frameCount * 0.3)); 43 | float tFactor2 = sin(radians(frameCount * 0.4)); 44 | 45 | curvePair = new ArrayList>(); 46 | 47 | ArrayList points = new ArrayList(); 48 | for (int i = 0; i < n; i++) { 49 | float t = i * inc; 50 | float r = 25 + 15.0 * tFactor * cos(freq * t - radians(frameCount * 0.7)); 51 | float x = r * cos(t); 52 | float y = r * sin(t); 53 | points.add(new PVector(x, y)); 54 | } 55 | curvePair.add(points); 56 | 57 | points = new ArrayList(); 58 | for (int i = 0; i < n; i++) { 59 | float t = i * inc; 60 | float r = 20 + 10.0 * tFactor2 * cos(PI / 2 + freq * t + radians(frameCount * 0.7)); 61 | float x = r * cos(t + PI / 2); 62 | float y = r * sin(t + PI / 2); 63 | points.add(new PVector(x, y)); 64 | } 65 | curvePair.add(points); 66 | 67 | pg.fill(255); 68 | for (int m = 1; m < 62; m += 3) { 69 | 70 | for (ArrayList c : curvePair) { 71 | pg.beginShape(); 72 | for (PVector p : c) { 73 | pg.vertex(p.x * m, p.y * m); 74 | } 75 | pg.endShape(CLOSE); 76 | } 77 | } 78 | if (frameCount % 60 == 0) { 79 | //pg.save("output" + int(random(1000000000)) + ".png"); 80 | save = false; 81 | } 82 | pg.endDraw(); 83 | 84 | image(pg, 0, 0, width, height); 85 | //if (frameCount % 60 == 0) { 86 | // pg.save("output" + int(random(1000000000)) + ".png"); 87 | // save = false; 88 | //} 89 | println(frameCount / 60 + " " + frameRate); 90 | } 91 | 92 | void keyPressed() { 93 | if (keyCode == UP) { 94 | freq++; 95 | } 96 | if (keyCode == DOWN) { 97 | freq--; 98 | } 99 | } 100 | 101 | void mouseClicked() { 102 | save = true; 103 | } 104 | -------------------------------------------------------------------------------- /DottedShadedWaves/DottedShadedWaves.pde: -------------------------------------------------------------------------------- 1 | import java.util.Date; 2 | float [][] curves; 3 | int curveCount = 7; 4 | 5 | PGraphics pg; 6 | color bgColor = color(255, 225, 200); 7 | boolean save = false; 8 | 9 | void setup() { 10 | size(900, 900, P2D); 11 | smooth(8); 12 | pg = createGraphics(2160, 2160, P2D); 13 | pg.smooth(8); 14 | pg.beginDraw(); 15 | pg.background(bgColor); 16 | pg.endDraw(); 17 | 18 | float amp = 300; 19 | float yBase = -350; 20 | curves = new float[curveCount][pg.width]; 21 | for (int i = 0; i < curveCount; i++) { 22 | float coA = random(0.5, 2); 23 | float coB = random(0.5, 2); 24 | yBase = -400 + amp * 1.5 * i; 25 | float offset = random(PI / 16, 15 * PI / 16); 26 | curves[i] = new float[pg.width]; 27 | for (int j = 0; j < pg.width; j++) { 28 | float x = map(j, 0, pg.width, 0, 2 * PI); 29 | float y = 0.5 * (1 + 0.5 * (cos(coA * x + offset) + sin(coB * x))); 30 | curves[i][j] = y * amp + yBase; 31 | } 32 | } 33 | } 34 | 35 | void draw() { 36 | pg.beginDraw(); 37 | if (frameCount == 1) { 38 | pg.background(bgColor); 39 | } 40 | float fuzz = 10; 41 | 42 | for (int i = 0; i < curveCount - 1; i++) { 43 | float [] topCurve = curves[i]; 44 | float [] bottomCurve = curves[i + 1]; 45 | for (int j = 0; j < 3000; j++) { 46 | int choice = int(random(0, pg.width)); 47 | float top = topCurve[choice]; 48 | float bottom = bottomCurve[choice]; 49 | float d = bottom - top; 50 | float yChoice = random(top, bottom); 51 | float distFactor = abs(yChoice - top) / d; 52 | float f = random(fuzz); 53 | float px = choice + random(-fuzz/3, fuzz/3); 54 | if (random(1) < distFactor) { 55 | pg.point(px, yChoice + f); 56 | } 57 | } 58 | } 59 | pg.endDraw(); 60 | if (save) { 61 | pg.save("DottedShadedWaves" + (new Date()).getTime() + ".png"); 62 | save = false; 63 | } 64 | 65 | image(pg, 0, 0, width, height); 66 | println(frameRate); 67 | } 68 | 69 | void mouseClicked() { 70 | save = true; 71 | } 72 | -------------------------------------------------------------------------------- /DottedShadedWaves/README.md: -------------------------------------------------------------------------------- 1 | Very simple sketch that creates some nice shaded wave figures. Based on calculating slightly different trig functions at different y positions and using the distance between successive waves to determine the probability that a black dot will be drawn. 2 | 3 | Some examples of output: 4 | 5 | ![DottedShadedWaves1647613966023small](https://user-images.githubusercontent.com/101308215/161361875-a7ab62ec-2e9b-4675-8374-555dd1f04c70.png) 6 | ![DottedShadedWaves1647612960803small](https://user-images.githubusercontent.com/101308215/161361877-92b43bd3-4c12-4be8-84ce-5dcdd28423f1.png) 7 | 8 | Happy hacking! 9 | -------------------------------------------------------------------------------- /DreamscapesPartOne/DreamscapesPartOne.pde: -------------------------------------------------------------------------------- 1 | import java.util.Date; 2 | 3 | ArrayList> curves = new ArrayList>(); 4 | color bgColor = color(0); 5 | color strokeColor = color(255, 225, 200, 30); 6 | color strokeBase = color(255, 30); 7 | float baseY; 8 | float curvePower = 1.0 / 3; 9 | int minCurves = 2; 10 | int maxCurves = 4; 11 | boolean randomStrokeColor = true; 12 | PGraphics pg; 13 | 14 | void setup() { 15 | size(1600, 900, P2D); 16 | pg = createGraphics(1920, 1080, P2D); 17 | pg.smooth(8); 18 | baseY = pg.height / 20; 19 | colorMode(HSB, 360, 100, 100, 100); 20 | pg.beginDraw(); 21 | pg.background(bgColor); 22 | pg.colorMode(HSB, 360, 100, 100, 100); 23 | pg.endDraw(); 24 | } 25 | 26 | boolean save = false; 27 | void keyPressed() { 28 | if (key == ENTER) { 29 | save = true; 30 | } 31 | } 32 | 33 | void mouseClicked() { 34 | if (mouseButton == RIGHT) { 35 | pg.beginDraw(); 36 | pg.noStroke(); 37 | pg.fill(0, 10); 38 | pg.rect(0, 0, pg.width, pg.height); 39 | baseY += pg.height / 20; 40 | pg.endDraw(); 41 | } 42 | strokeColor = randomStrokeColor ? color(random(360), 60, 100, 30) : strokeColor; 43 | curves = new ArrayList>(); 44 | float mx = map(mouseX, 0, width, 0, pg.width); 45 | int xMin = int(mx - random(pg.width / 12, pg.width / 3)); 46 | int xMax = int(mx + random(pg.width / 12, pg.width / 3)); 47 | int peakX = int(mx); 48 | int n = int(random(minCurves, maxCurves + 1)); 49 | for (int i = xMin; i < xMax; i += int(1.0 * (xMax - xMin) / n)) { 50 | ArrayList c = powerCurve(new PVector(i, pg.height), new PVector(peakX, baseY), int(pg.height - baseY), curvePower); 51 | curves.add(c); 52 | } 53 | 54 | pg.beginDraw(); 55 | pg.noStroke(); 56 | pg.fill(bgColor); 57 | pg.beginShape(); 58 | for (int i = 0; i < curves.get(0).size(); i++) { 59 | PVector p = curves.get(0).get(i); 60 | pg.vertex(p.x, p.y); 61 | } 62 | for (int i = curves.get(curves.size() - 1).size() - 1; i >= 0 ; i--) { 63 | PVector p = curves.get(curves.size() - 1).get(i); 64 | pg.vertex(p.x, p.y); 65 | } 66 | pg.endShape(CLOSE); 67 | pg.endDraw(); 68 | 69 | } 70 | 71 | void draw() { 72 | pg.beginDraw(); 73 | if (frameCount == 1) { 74 | pg.background(bgColor); 75 | } 76 | pg.noFill(); 77 | pg.stroke(strokeColor); 78 | for (int i = 0; i < curves.size() - 1; i++) { 79 | ArrayList thisCurve = curves.get(i); 80 | ArrayList nextCurve = curves.get(i + 1); 81 | for (int j = 0; j < thisCurve.size(); j++) { 82 | PVector left = thisCurve.get(j); 83 | PVector right = nextCurve.get(j); 84 | float span = right.x - left.x; 85 | pg.strokeWeight(random(1.3)); 86 | float rand = sqrt(random(1)); 87 | float x = left.x + span * rand; 88 | float y = left.y + random(-2, 2); 89 | pg.point(x, y); 90 | } 91 | } 92 | if (save) { 93 | println("saving..."); 94 | pg.save("DreamscapesPartOne" + (new Date()).getTime() + ".png"); 95 | save = false; 96 | } 97 | 98 | pg.endDraw(); 99 | 100 | image(pg, 0, 0, width, height); 101 | } 102 | 103 | ArrayList powerCurve(PVector a, PVector b, int n, float power) { 104 | ArrayList result = new ArrayList(); 105 | float magInc = 1.0 / n; 106 | for (int i = 0; i < n; i++) { 107 | float py = lerp(a.y, b.y, magInc * i); 108 | float cy = lerp(0, 1, magInc * i); 109 | float cx = pow(cy, power); 110 | float px = map(cx, 0, 1, a.x, b.x); 111 | result.add(new PVector(px, py)); 112 | } 113 | return result; 114 | } 115 | -------------------------------------------------------------------------------- /DreamscapesPartTwoHills/DreamscapesPartTwoHills.pde: -------------------------------------------------------------------------------- 1 | import java.util.Date; 2 | 3 | ArrayList curve = new ArrayList(); 4 | float yBase, yBaseInit; 5 | int dotCount = 0; 6 | int shadeDirection = -1; // -1 goes toward bottom of screen, 1 goes toward top 7 | int dotsPerFrame = 10000; 8 | int dotsPerCurve = 1000000; 9 | float shadeFuzz = 0.01; 10 | float curveThickness = 300; 11 | float xPadding, topPadding, bottomPadding, yIncrement; 12 | float minCoefficient = 0.5; 13 | float maxCoefficient = 1.5; 14 | float shadeFalloff = 10; 15 | float maxStrokeWeight = 1.5; 16 | float baseHue = 140; // 0 to 360 17 | float baseSaturation = 90; 18 | float saturationRange = 90; 19 | int saturationChangeDirection = -1; 20 | long seed; 21 | boolean noiseCurve = false; 22 | boolean useNormal = false; // shade perpendicular to the curve rather than vertical 23 | boolean save = false; 24 | PGraphics pg; 25 | 26 | void setup() { 27 | randomSeed(seed = (long) random(10000000)); 28 | size(1600, 900, P2D); 29 | pg = createGraphics(1920, 1080, P2D); 30 | pg.smooth(8); 31 | colorMode(HSB, 360, 100, 100, 100); 32 | pg.beginDraw(); 33 | pg.colorMode(HSB, 360, 100, 100, 100); 34 | xPadding = pg.width / 10; 35 | bottomPadding = pg.height / 20; 36 | topPadding = pg.height / 10; 37 | yBaseInit = pg.height / 10; 38 | yIncrement = pg.height / 30; 39 | yBase = yBaseInit; 40 | pg.endDraw(); 41 | } 42 | 43 | void mouseClicked() { 44 | save = true; 45 | } 46 | 47 | void draw() { 48 | pg.beginDraw(); 49 | if (frameCount == 1) { 50 | pg.background(0); 51 | newCurve(); 52 | } 53 | if (!curve.isEmpty()) { 54 | float w = curveThickness; 55 | strip(curve, w, w, dotsPerFrame, shadeFuzz, shadeDirection); 56 | dotCount += dotsPerFrame; 57 | } 58 | if (dotCount > dotsPerCurve) { 59 | dotCount = 0; 60 | newCurve(); 61 | } 62 | //noLoop(); 63 | println(frameRate); 64 | pg.endDraw(); 65 | if (save) { 66 | save = false; 67 | pg.save("DreamscapesPartTwo" + (new Date()).getTime() + "seed" + seed + ".png"); 68 | } 69 | image(pg, 0, 0, width, height); 70 | } 71 | 72 | void newCurve() { 73 | curve = new ArrayList(); 74 | if (yBase > pg.height + bottomPadding) { 75 | return; 76 | } 77 | float initAngle = random(2 * PI); 78 | float co = random(minCoefficient, maxCoefficient); 79 | for (float x = -xPadding; x < pg.width + xPadding; x += 0.5) { 80 | float cx = map(x, -xPadding, pg.width + xPadding, 0, 1); 81 | float cy = 0.0; 82 | if (noiseCurve) { 83 | cy = noise(1000 + frameCount + initAngle + 2 * PI * co * cx); 84 | } else { 85 | cy = 0.5 * (1 + sin(initAngle + 2 * PI * co * cx)); 86 | } 87 | float py = map(cy, 0, 1, yBase, pg.height - bottomPadding); 88 | curve.add(new PVector(x, py)); 89 | } 90 | yBase += yIncrement; 91 | pg.noStroke(); 92 | //pg.fill(0, 5); 93 | //pg.rect(0, 0, pg.width, pg.height); 94 | pg.fill(0); 95 | //pg.stroke(0, 100, 100); 96 | pg.beginShape(); 97 | pg.vertex(0, pg.height); 98 | for (PVector p : curve) { 99 | pg.vertex(p.x, p.y); 100 | } 101 | pg.vertex(pg.width, pg.height); 102 | pg.endShape(); 103 | float yFactor = (yBase - yBaseInit) / (pg.height - yBaseInit); 104 | pg.stroke(baseHue, baseSaturation + saturationChangeDirection * saturationRange * yFactor, 100, 30); 105 | } 106 | 107 | void strip(ArrayList points, float wStart, float wEnd, float n, float fuzz, int dir) { 108 | for (int i = 0; i < n; i++) { 109 | float rand = random(1); //1 - pow(random(1), 0.3); 110 | int choice = int(rand * points.size()); 111 | PVector p = points.get(min(choice, points.size() - 1)); 112 | PVector pos = p.copy(); 113 | if (useNormal) { 114 | PVector normal = getNormal(p, points, choice, dir); 115 | // use normal to pick point somewhere in the "thickness" of the curve 116 | float randW = pow(random(1), 1.0 / shadeFalloff); 117 | float w = lerp(wStart, wEnd, 1.0 * choice / points.size()); 118 | pos.add(normal.mult(w - w * random(fuzz) - w * randW)); 119 | } else { 120 | pos.y = pos.y - dir * (1 - pow(random(1), 1.0 / shadeFalloff)) * (pg.height - p.y); 121 | } 122 | pg.strokeWeight(random(maxStrokeWeight)); 123 | pg.point(pos.x, pos.y); 124 | } 125 | } 126 | 127 | PVector getNormal(PVector p, ArrayList points, int choice, int dir) { 128 | // calculate normal for PVector p based on previous and next points 129 | PVector prev = null; 130 | PVector next = null; 131 | if (choice > 0) { 132 | prev = points.get(choice - 1); 133 | } 134 | if (choice < points.size() - 1) { 135 | next = points.get(choice + 1); 136 | } 137 | PVector diff = new PVector(0, 0); 138 | if (prev != null && next != null) { 139 | diff = prev.copy().sub(next).normalize(); 140 | } else if (prev != null) { 141 | diff = prev.copy().sub(p).normalize(); 142 | } else if (next != null) { 143 | diff = next.copy().sub(p).normalize(); 144 | } 145 | return new PVector(dir * -diff.y, dir * diff.x); 146 | } 147 | -------------------------------------------------------------------------------- /FigureAndGround/GridClass.pde: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | 3 | class Grid { 4 | 5 | Cell [][] cells; 6 | HashSet occupants; 7 | int pixW, pixH; 8 | float cellW, cellH; 9 | 10 | Grid(int w, int h, int pixW, int pixH) { 11 | cells = new Cell[w][h]; 12 | 13 | this.pixW = pixW; 14 | this.pixH = pixH; 15 | this.cellW = 1.0 * pixW / w; 16 | this.cellH = 1.0 * pixH / h; 17 | for (int i = 0; i < w; i++) { 18 | for (int j = 0; j < h; j++) { 19 | PVector pos = new PVector(i * cellW, j * cellH); 20 | cells[i][j] = new Cell(pos, cellW, cellH); 21 | } 22 | } 23 | for (int x = 0; x < w; x++) { 24 | for (int y = 0; y < h; y++) { 25 | 26 | Cell c = cells[x][y]; 27 | c.neighbors = getNeighbors(x, y); 28 | } 29 | } 30 | occupants = new HashSet(); 31 | } 32 | 33 | void add(T t, float xPixPos, float yPixPos) { 34 | int x = int(xPixPos / cellW); 35 | int y = int(yPixPos / cellH); 36 | cells[x][y].occupants.add(t); 37 | occupants.add(t); 38 | } 39 | 40 | void add(PVector p) { 41 | int x = int(p.x / cellW); 42 | int y = int(p.y / cellH); 43 | cells[x][y].occupants.add(p); 44 | occupants.add((T) p); 45 | } 46 | 47 | ArrayList getCellMembers(int x, int y) { 48 | return new ArrayList(cells[x][y].occupants); 49 | } 50 | 51 | Cell getCell(float xPixPos, float yPixPos) { 52 | int x = int(xPixPos / cellW); 53 | int y = int(yPixPos / cellH); 54 | return cells[x][y]; 55 | } 56 | 57 | ArrayList getNeighbors(int x, int y) { 58 | ArrayList results = new ArrayList(); 59 | boolean onLeftBorder = x == 0; 60 | boolean onRightBorder = x == cells.length - 1; 61 | boolean onTopBorder = y == 0; 62 | boolean onBottomBorder = y == cells[0].length - 1; 63 | if (!onLeftBorder) { 64 | if (!onTopBorder) { 65 | results.add(cells[x-1][y-1]); 66 | } 67 | if (!onBottomBorder) { 68 | results.add(cells[x-1][y+1]); 69 | } 70 | results.add(cells[x-1][y]); 71 | } 72 | if (!onRightBorder) { 73 | if (!onTopBorder) { 74 | results.add(cells[x+1][y-1]); 75 | } 76 | if (!onBottomBorder) { 77 | results.add(cells[x+1][y+1]); 78 | } 79 | results.add(cells[x+1][y]); 80 | } 81 | if (!onTopBorder) { 82 | results.add(cells[x][y-1]); 83 | } 84 | if (!onBottomBorder) { 85 | results.add(cells[x][y+1]); 86 | } 87 | return results; 88 | } 89 | 90 | ArrayList getCellAndNeighbors(int x, int y) { 91 | ArrayList results = new ArrayList(); 92 | boolean onLeftBorder = x == 0; 93 | boolean onRightBorder = x == cells[0].length - 1; 94 | boolean onTopBorder = y == 0; 95 | boolean onBottomBorder = y == cells.length - 1; 96 | if (!onLeftBorder) { 97 | if (!onTopBorder) { 98 | results.add(cells[x-1][y-1]); 99 | } 100 | if (!onBottomBorder) { 101 | results.add(cells[x-1][y+1]); 102 | } 103 | results.add(cells[x-1][y]); 104 | } 105 | if (!onRightBorder) { 106 | if (!onTopBorder) { 107 | results.add(cells[x+1][y-1]); 108 | } 109 | if (!onBottomBorder) { 110 | results.add(cells[x+1][y+1]); 111 | } 112 | results.add(cells[x+1][y]); 113 | } 114 | if (!onTopBorder) { 115 | results.add(cells[x+1][y-1]); 116 | } 117 | if (!onBottomBorder) { 118 | results.add(cells[x+1][y+1]); 119 | } 120 | return results; 121 | } 122 | 123 | ArrayList findCloseOccupants(PVector pos) { 124 | Cell c = this.getCell(pos.x, pos.y); 125 | ArrayList close = c.getOccupantsAndOccupantsOfNeighbors(); 126 | return close; 127 | } 128 | 129 | void show() { 130 | for (Cell [] array : cells) { 131 | for (Cell c : array) { 132 | c.show(); 133 | } 134 | } 135 | } 136 | 137 | void showVectors() { 138 | for (Cell [] array : cells) { 139 | for (Cell c : array) { 140 | c.showVectors(); 141 | } 142 | } 143 | } 144 | 145 | } 146 | 147 | class Cell { 148 | 149 | PVector pos; 150 | int id; 151 | float w, h; 152 | color fillColor; 153 | ArrayList neighbors; 154 | HashSet occupants; 155 | boolean active; 156 | 157 | Cell(PVector pos, float w, float h) { 158 | this.pos = pos; 159 | this.w = w; 160 | this.h = h; 161 | this.occupants = new HashSet(); 162 | this.neighbors = new ArrayList(); 163 | } 164 | 165 | void add(T t) { 166 | occupants.add(t); 167 | } 168 | 169 | void remove(T t) { 170 | occupants.remove(t); 171 | } 172 | 173 | void show() { 174 | noFill(); 175 | stroke(255); 176 | if (active) { 177 | stroke(255, 0, 0); 178 | } 179 | strokeWeight(1); 180 | rect(pos.x, pos.y, w, h); 181 | } 182 | 183 | ArrayList getOccupantsAndOccupantsOfNeighbors() { 184 | ArrayList results = new ArrayList(); 185 | for (Cell c : neighbors) { 186 | results.addAll(c.occupants); 187 | } 188 | results.addAll(occupants); 189 | return results; 190 | } 191 | 192 | ArrayList getOccupantsOfNeighbors() { 193 | ArrayList results = new ArrayList(); 194 | for (Cell c : neighbors) { 195 | results.addAll(c.occupants); 196 | } 197 | return results; 198 | } 199 | 200 | void showVectors() { 201 | strokeWeight(4); 202 | for (T o : occupants) { 203 | PVector p = (PVector) o; 204 | point(p.x, p.y); 205 | } 206 | } 207 | 208 | boolean contains(float x, float y) { 209 | return x >= pos.x && y >= pos.y && x <= pos.x + w && y <= pos.y + h; 210 | } 211 | 212 | } 213 | -------------------------------------------------------------------------------- /FilamentSweep/FilamentSweep.pde: -------------------------------------------------------------------------------- 1 | ArrayList points = new ArrayList(); 2 | ArrayList movers = new ArrayList(); 3 | int moverCount = 4; 4 | int margin = 0; 5 | float minReturnRate = 0.02; 6 | float maxReturnRate = 0.1; 7 | float magSqFudge = 10000.0; 8 | float pivotDivisor = 10.0; 9 | float moveMagLimit = 10.0; 10 | float moverMinSpeed = 2.0; 11 | float moverMaxSpeed = 8.0; 12 | float minLerpSpeed = 0.01; 13 | float maxLerpSpeed = 0.2; 14 | boolean randomizeReturnRate = false; 15 | boolean randomizeInitPositions = false; 16 | boolean copperColor = true; 17 | color copper = color(255, 175, 125, 225); 18 | color iceBlue = color(100, 150, 255, 175); 19 | 20 | PGraphics pg; 21 | 22 | void setup() { 23 | size(900, 900, P3D); 24 | pg = createGraphics(1080, 1080, P3D); 25 | pg.smooth(8); 26 | pg.beginDraw(); 27 | pg.ellipseMode(RADIUS); 28 | pg.blendMode(ADD); 29 | pg.stroke(copperColor ? copper : iceBlue); 30 | pg.endDraw(); 31 | initPositions(randomizeInitPositions); 32 | for (int i = 0; i < moverCount; i++) { 33 | Mover m = new Mover(randomPos()); 34 | movers.add(m); 35 | } 36 | 37 | } 38 | 39 | void initPositions(boolean randomize) { 40 | int side = 175; 41 | float inc = (1.0 * pg.width - margin * 2) / side; 42 | float r = inc / 2.0; 43 | points = new ArrayList(); 44 | for (int i = 0; i < side; i++) { 45 | float y = margin + i * inc + r; 46 | for (int j = 0; j < side; j++) { 47 | float x = margin + j * inc + r; 48 | PVector o = randomize 49 | ? new PVector(random(margin, pg.width - margin), random(margin, pg.height - margin)) 50 | : new PVector(x, y); 51 | points.add(new Point(o, margin, pg.width - margin, margin, pg.height - margin)); 52 | } 53 | } 54 | } 55 | boolean save = false; 56 | 57 | void draw() { 58 | pg.beginDraw(); 59 | pg.background(0); 60 | pg.strokeWeight(1); 61 | for (Mover m : movers) { 62 | m.move(); 63 | } 64 | for (Point p : points) { 65 | p.update(); 66 | p.show(); 67 | } 68 | if (save) { 69 | save = false; 70 | pg.save("FilamentSweep" + frameCount + ".png"); 71 | } 72 | pg.endDraw(); 73 | image(pg, 0, 0, width, height); 74 | if (frameCount % 60 == 0) { 75 | println(frameCount / 60 + " --- " + frameRate); 76 | } 77 | } 78 | 79 | void mouseClicked() { 80 | if (mouseButton == LEFT) { 81 | save = true; 82 | } 83 | } 84 | 85 | void keyPressed() { 86 | if (key == CODED && keyCode == UP) { 87 | randomizeReturnRate = !randomizeReturnRate; 88 | randomizeInitPositions = !randomizeInitPositions; 89 | copperColor = !copperColor; 90 | initPositions(randomizeInitPositions); 91 | pg.stroke(copperColor ? copper : iceBlue); 92 | } 93 | } 94 | 95 | PVector randomPos() { 96 | return new PVector(random(pg.width), random(pg.height)); 97 | } 98 | 99 | class Point { 100 | 101 | PVector init, pivot, pos; 102 | float xMin, xMax, yMin, yMax; 103 | float returnRate; 104 | 105 | Point(PVector pos, float xMin, float xMax, float yMin, float yMax) { 106 | this.pos = pos; 107 | this.init = pos.copy(); 108 | this.pivot = pos.copy(); 109 | this.xMin = xMin; 110 | this.xMax = xMax; 111 | this.yMin = yMin; 112 | this.yMax = yMax; 113 | this.returnRate = randomizeReturnRate ? random(minReturnRate, maxReturnRate) : minReturnRate; 114 | } 115 | 116 | void update() { 117 | for (Mover m : movers) { 118 | PVector mover = new PVector(m.pos.x, m.pos.y); 119 | PVector diff = pos.copy().sub(mover); 120 | float magSq = diff.magSq(); 121 | PVector n = diff.copy().normalize(); 122 | n.mult(magSqFudge / magSq).limit(moveMagLimit); 123 | pos.add(n); 124 | pivot.add(n.div(pivotDivisor)); 125 | } 126 | pos = PVector.lerp(pos, init, returnRate); 127 | pivot = PVector.lerp(pivot, init, returnRate); 128 | } 129 | 130 | void checkBounds() { 131 | if (pos.x < xMin) { 132 | pos.x = xMin; 133 | } 134 | if (pos.x > xMax) { 135 | pos.x = xMax; 136 | } 137 | if (pos.y < yMin) { 138 | pos.y = yMin; 139 | } 140 | if (pos.y > yMax) { 141 | pos.y = yMax; 142 | } 143 | } 144 | 145 | void show() { 146 | pg.line(pivot.x, pivot.y, pos.x, pos.y); 147 | } 148 | } 149 | 150 | class Mover { 151 | 152 | PVector pos, dest, vel; 153 | PVector lerpSpeed; 154 | 155 | Mover(PVector pos) { 156 | this.pos = pos; 157 | this.dest = randomPos(); 158 | this.vel = dest.copy().sub(pos).normalize().mult(random(moverMinSpeed, moverMaxSpeed)); 159 | lerpSpeed = new PVector(random(minLerpSpeed, maxLerpSpeed), random(minLerpSpeed, maxLerpSpeed)); 160 | } 161 | 162 | void move() { 163 | pos.add(vel); 164 | if (pos.copy().sub(dest).magSq() < vel.magSq()) { 165 | dest = randomPos(); 166 | vel = dest.copy().sub(pos).normalize().mult(random(moverMinSpeed, moverMaxSpeed)); 167 | lerpSpeed = new PVector(random(minLerpSpeed, maxLerpSpeed), random(minLerpSpeed, maxLerpSpeed)); 168 | } 169 | } 170 | 171 | } 172 | -------------------------------------------------------------------------------- /FilamentSweep/README.md: -------------------------------------------------------------------------------- 1 | Uses a Point class with position history to draw lines whose length is determined by repelling forces of moving objects. Point init positions can be randomized or set to a regular grid for a fuzzy or moiré look. 2 | 3 | Example outputs: 4 | 5 | ![FilamentSweep3659](https://user-images.githubusercontent.com/101308215/165745346-a43e1c5d-64f5-4216-ad1b-24be43537842.png) 6 | 7 | ![FilamentSweep543](https://user-images.githubusercontent.com/101308215/165745352-85933cbc-284f-4412-b738-5e7c2d3ace45.png) 8 | -------------------------------------------------------------------------------- /FlowFieldActivate/FlowFieldActivate.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | ArrayList points; 4 | ArrayList movers = new ArrayList(); 5 | float radius = 300; 6 | float sc = 0.01; 7 | boolean randomPositions = true; 8 | 9 | void setup() { 10 | 11 | size(900, 900, P2D); 12 | pg = createGraphics(1080, 1080, P2D); 13 | pg.smooth(8); 14 | pg.beginDraw(); 15 | colorMode(HSB, 360, 100, 100, 100); 16 | pg.colorMode(HSB, 360, 100, 100, 100); 17 | pg.ellipseMode(RADIUS); 18 | pg.blendMode(ADD); 19 | pg.endDraw(); 20 | setPositions(randomPositions); 21 | for (int i = 0; i < 5; i++) { 22 | movers.add(new Mover(new PVector(random(10, pg.width - 10), -pg.height / 10), new PVector(0, random(2, 5)))); 23 | } 24 | } 25 | 26 | void setPositions(boolean randomize) { 27 | points = new ArrayList(); 28 | int n = 100; 29 | float inc = 1.0 * pg.width / n; 30 | for (int yi = 0; yi < n; yi++) { 31 | float y = inc * yi + inc / 2; 32 | for (int xi = 0; xi < n; xi++) { 33 | float x = inc * xi + inc / 2; 34 | points.add(randomize ? new Point(new PVector(random(pg.width), random(pg.height))) : new Point(new PVector(x, y))); 35 | } 36 | } 37 | } 38 | 39 | void keyPressed() { 40 | if (key == CODED && keyCode == UP) { 41 | randomPositions = !randomPositions; 42 | setPositions(randomPositions); 43 | } 44 | if (keyCode == RIGHT) { 45 | movers.add(new Mover(new PVector(random(10, pg.width - 10), -pg.height / 10), new PVector(0, random(2, 5)))); 46 | } 47 | } 48 | 49 | void draw() { 50 | pg.beginDraw(); 51 | pg.background(0); 52 | pg.strokeWeight(2); 53 | //PVector m = new PVector(mouseX, mouseY); 54 | for (Mover m : movers) { 55 | m.update(); 56 | m.show(); 57 | } 58 | //PVector m = new PVector(mouseX, mouseY); 59 | for (Point p : points) { 60 | for (Mover m : movers) { 61 | p.distort(m.p); 62 | } 63 | p.revert(); 64 | p.show(); 65 | } 66 | pg.endDraw(); 67 | image(pg, 0, 0, width, height); 68 | println(frameRate); 69 | } 70 | 71 | class Point { 72 | 73 | PVector init, p; 74 | float r; 75 | float revertRate; 76 | color initCol, col; 77 | 78 | Point(PVector init) { 79 | this.r = 3; 80 | this.init = init; 81 | this.p = init.copy(); 82 | this.col = color(30, 0, 20); 83 | this.initCol = col; 84 | this.revertRate = random(0.01, 0.04); 85 | } 86 | 87 | void distort(PVector m) { 88 | //PVector diff = p.copy().sub(m); 89 | float dSq = m.copy().sub(p).magSq(); 90 | if (dSq < radius * radius) { 91 | float fd = pow(1 - sqrt(dSq) / radius, 5); 92 | float noize = noise(p.x * sc, p.y * sc, frameCount * sc); 93 | //PVector add = PVector.fromAngle(diff.heading()).mult(fd * 15 * noize); 94 | PVector add = PVector.fromAngle(2 * TAU * noize).mult(fd * 15); 95 | color c = color(180 * noize + 180 * fd, 100, 100); 96 | col = lerpColor(col, c, fd); 97 | p.add(add); 98 | } 99 | } 100 | 101 | void revert() { 102 | p.lerp(init, revertRate); 103 | col = lerpColor(col, initCol, revertRate); 104 | } 105 | 106 | void show() { 107 | pg.stroke(col); 108 | pg.point(p.x, p.y); 109 | } 110 | } 111 | 112 | class Mover { 113 | 114 | PVector p, v; 115 | 116 | Mover(PVector p, PVector v) { 117 | this.p = p; 118 | this.v = v; 119 | } 120 | 121 | void update() { 122 | p.add(v); 123 | if (p.y > pg.height + pg.height / 10) { 124 | p.x = random(10, pg.width - 10); 125 | p.y = -pg.height / 10; 126 | } 127 | } 128 | 129 | void show() { 130 | pg.noStroke(); 131 | pg.fill(0, 0, 100); 132 | pg.circle(p.x, p.y, 5); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /GlowingCircles/GlowingCircles.pde: -------------------------------------------------------------------------------- 1 | int n = 300; 2 | ArrayList movers = new ArrayList(); 3 | PGraphics pg; 4 | 5 | float offset = 0.0; 6 | 7 | void setup() { 8 | size(900, 900, P3D); 9 | pg = createGraphics(1080, 1080, P3D); 10 | pg.smooth(8); 11 | colorMode(HSB, 360, 100, 100, 100); 12 | pg.beginDraw(); 13 | pg.colorMode(HSB, 360, 100, 100, 100); 14 | pg.noStroke(); 15 | for (int i = 0; i < n; i++) { 16 | movers.add(new Mover(random(pg.width), random(pg.height))); 17 | } 18 | } 19 | 20 | void draw() { 21 | pg.beginDraw(); 22 | pg.background(0); 23 | for (Mover m : movers) { 24 | m.move(); 25 | m.checkBounds(); 26 | m.show(); 27 | } 28 | pg.endDraw(); 29 | 30 | image(pg, 0, 0, width, height); 31 | println(frameCount + " ::::: " +frameRate); 32 | } 33 | 34 | class Mover { 35 | 36 | PVector pos; 37 | PVector v; 38 | float r; 39 | float baseHue; 40 | float falloffOscFreq; 41 | 42 | Mover(float x, float y) { 43 | this.pos = new PVector(x, y); 44 | this.v = new PVector((random(2) < 1 ? -1 : 1) * random(0.5, 2), random(0.5, 2)); 45 | this.r = random(10, 25); 46 | this.baseHue = random(360); 47 | this.falloffOscFreq = random(1, 3); 48 | } 49 | 50 | void move() { 51 | this.pos.add(v); 52 | } 53 | 54 | void show() { 55 | int glowRadius = 45; 56 | float glowFalloff = 2 + 4 * abs(sin(radians(0.3 * frameCount * falloffOscFreq))); 57 | pg.fill(baseHue, 0, 100, 100); 58 | pg.circle(pos.x, pos.y, r); 59 | for (int i = 0; i < glowRadius; i += 3) { 60 | float rFactor = pow((1.0 * glowRadius - i) / glowRadius, glowFalloff); 61 | pg.fill(baseHue, 0, 100, 20 * rFactor); 62 | pg.circle(pos.x, pos.y, r + i); 63 | } 64 | } 65 | 66 | void checkBounds() { 67 | if (pos.x + r < 0) { 68 | pos.x = pg.width + r; 69 | } 70 | if (pos.x - r > pg.width) { 71 | pos.x = -r; 72 | } 73 | if (pos.y + r < 0) { 74 | pos.y = pg.height + r; 75 | } 76 | if (pos.y - r > pg.height) { 77 | pos.y = -r; 78 | } 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /GradientArcWaves/GradientArcWaves.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | void setup() { 4 | size(900, 900, P3D); 5 | pg = createGraphics(1080, 1080, P3D); 6 | pg.smooth(8); 7 | pg.beginDraw(); 8 | pg.noStroke(); 9 | pg.endDraw(); 10 | } 11 | 12 | void draw() { 13 | pg.beginDraw(); 14 | pg.background(0); 15 | float n = 300; 16 | float xn = 25, yn = 25; 17 | color colA = color(50, 75, 150); 18 | color colB = color(255, 225, 200); 19 | for (float yi = 0; yi < yn; yi++) { 20 | float y = yi * pg.height / yn + pg.height / yn / 2; 21 | for (float xi = 0; xi < xn; xi++) { 22 | float x = xi * pg.width / yn + pg.width / yn / 2; 23 | PVector c = new PVector(x, y); 24 | float sinf = 0.25 * (2 + sin(map(yi, 0, yn, 0, TAU) + radians(frameCount * 1.3)) + sin(map(xi, 0, xn, 0, TAU) + radians(frameCount))); 25 | float maxAngle = PI / 8 + 15 * PI / 8 * pow(sinf, 3); 26 | float thisN = int(n * maxAngle / TAU); 27 | pg.beginShape(QUAD_STRIP); 28 | for (int i = 0; i <= thisN; i++) { 29 | float th = i * TAU / n; 30 | color col = lerpColor(colA, colB, pow(abs(th - maxAngle / 2) / (maxAngle / 2), 2)); 31 | pg.fill(col); 32 | PVector p = PVector.fromAngle(th + radians(frameCount) + map(xi, 0, xn, 0, TAU)).mult(0.95 * pg.width / xn / 2).add(c); 33 | pg.vertex(c.x, c.y); 34 | pg.vertex(p.x, p.y); 35 | } 36 | pg.endShape(); 37 | } 38 | } 39 | pg.endDraw(); 40 | image(pg, 0, 0, width, height); 41 | println(frameCount / 60); 42 | } 43 | -------------------------------------------------------------------------------- /GradientZoo/GradientZoo.pde: -------------------------------------------------------------------------------- 1 | import java.util.Date; 2 | 3 | void setup() { 4 | size(900, 900, P2D); 5 | background(255, 225, 200); 6 | smooth(8); 7 | stroke(0, 30); 8 | } 9 | 10 | void draw() { 11 | //drawCenteredGradientCircles(); 12 | //drawLinearGradientCircles(); 13 | //drawGradientRings(); 14 | //drawGradientStrips(); 15 | //drawOffsetGradientSquares(); 16 | //drawGradientWaves(); 17 | drawCenteredGradientSquares(); 18 | } 19 | 20 | void mouseClicked() { 21 | saveFrame("GradientZoo" + (new Date()).getTime() + ".png"); 22 | } 23 | 24 | void drawCenteredGradientCircles() { 25 | int perSide = 3; 26 | int inc = width / perSide; 27 | int pointsPerFrame = 500; 28 | float r = inc / 2.1; 29 | stroke(0, 30); 30 | strokeWeight(1); 31 | for (int yi = 0; yi < perSide; yi++) { 32 | for (int xi = 0; xi < perSide; xi++) { 33 | float x = inc * xi + inc / 2; 34 | float y = inc * yi + inc / 2; 35 | int index = xi + yi * perSide; 36 | for (int i = 0; i < pointsPerFrame; i++) { 37 | PVector p = randomInCircle(x, y, r, 0.1 + index / 12.0, 0.02); 38 | point(p.x, p.y); 39 | } 40 | } 41 | } 42 | } 43 | 44 | void drawLinearGradientCircles() { 45 | int perSide = 3; 46 | int inc = width / perSide; 47 | int pointsPerFrame = 500; 48 | float r = inc / 2.1; 49 | stroke(0, 30); 50 | float minWeight = 0.5; 51 | for (int yi = 0; yi < perSide; yi++) { 52 | for (int xi = 0; xi < perSide; xi++) { 53 | float x = inc * xi + inc / 2; 54 | float y = inc * yi + inc / 2; 55 | int index = xi + yi * perSide; 56 | for (int i = 0; i < pointsPerFrame; i++) { 57 | PVector p = randomInCircle(x, y, r, 0.5, 0.00); 58 | float verticalDistanceFactor = pow(abs(y + r - p.y) / (r * 2), 3.0 * (index + 1.0) / (perSide * perSide)); 59 | strokeWeight(minWeight + 2.0 * verticalDistanceFactor); 60 | point(p.x, p.y); 61 | } 62 | } 63 | } 64 | } 65 | 66 | void drawGradientRings() { 67 | int rings = 10; 68 | int margin = 5; 69 | float minRadius = width / 30; 70 | float maxRadius = width / 2 - margin * 2; 71 | float radiusRange = maxRadius - minRadius; 72 | float perRing = radiusRange / rings; 73 | for (int i = 0; i < rings; i++) { 74 | float baseRadius = minRadius + perRing * i; 75 | float thisMaxRadius = baseRadius + perRing; 76 | float ringArea = PI * thisMaxRadius * thisMaxRadius - PI * baseRadius * baseRadius; // scale number of points to ring area (bigger rings need more points) 77 | int perFrame = int(ringArea / 50); 78 | for (int points = 0; points < perFrame; points++) { 79 | float initAngle = 4 * i * 2 * PI / rings; 80 | float rand = random(1); 81 | float r = minRadius + perRing * i + perRing * rand; 82 | float angle = initAngle + 2 * PI * sqrt(random(1)); 83 | PVector p = PVector.fromAngle(angle).mult(r).add(new PVector(width / 2, height / 2)); 84 | point(p.x, p.y); 85 | } 86 | } 87 | } 88 | 89 | void drawGradientStrips() { 90 | int strips = 10; 91 | int margin = 25; 92 | int inc = (width - margin * 2) / strips; 93 | int perFrame = 1000; 94 | for (int xi = 0; xi < strips; xi++) { 95 | float x = margin + xi * inc; 96 | float x2 = x + inc; 97 | boolean upsideDown = xi % 2 == 0; 98 | for (int points = 0; points < perFrame; points++) { 99 | float rand = pow(random(1), 0.1 + xi * 0.5 / strips); // sharper falloff toward the left 100 | float y = upsideDown 101 | ? margin + rand * (height - margin * 2) 102 | : height - margin - rand * (height - margin * 2); 103 | PVector p = new PVector(random(x, x2), y); 104 | strokeWeight(random(2)); 105 | point(p.x, p.y); 106 | } 107 | } 108 | } 109 | 110 | void drawGradientWaves() { 111 | int margin = 10; 112 | int waves = 6; 113 | stroke(0, 30); 114 | noFill(); 115 | float initAngle = 0.0; 116 | float angleInc = 1.3; 117 | float freq = 0.7; 118 | float waveAmp = (height - margin * 2.0) / waves; 119 | // it would be way more efficient to precalculate the sine waves for each x value 120 | // but I wanted to keep everything in one draw method 121 | for (int waveCount = 0; waveCount < waves - 1; waveCount++) { 122 | float yBase = margin + waveCount * waveAmp; 123 | float yBase2 = margin + (waveCount + 1) * waveAmp; 124 | for (int i = 0; i < width; i++) { 125 | float cx = map(i, 0, width, 0, 2 * PI); 126 | float cy = sin(initAngle + cx * freq); 127 | float cy2 = sin(initAngle + angleInc + cx * freq); 128 | PVector p = new PVector(i, map(cy, -1, 1, yBase, yBase + waveAmp)); 129 | PVector p2 = new PVector(i, map(cy2, -1, 1, yBase2, yBase2 + waveAmp)); 130 | PVector plot = PVector.lerp(p, p2, sqrt(random(1))); 131 | strokeWeight(random(2)); 132 | point(plot.x, plot.y); 133 | } 134 | initAngle += angleInc; 135 | } 136 | } 137 | 138 | void drawOffsetGradientSquares() { 139 | int perSide = 5; 140 | int margin = 10; 141 | int inc = (width - margin * 2) / perSide; 142 | int perFrame = 500; 143 | for (int yi = 0; yi < perSide; yi++) { 144 | for (int xi = 0; xi < perSide; xi++) { 145 | float xBase = margin + xi * inc; 146 | float yBase = margin + yi * inc; 147 | for (int points = 0; points < perFrame; points++) { 148 | float x = xBase + inc * pow(random(1), 1.0 / (xi + 2)); 149 | float y = yBase + inc * pow(random(1), 1.0 / (yi + 2)); 150 | strokeWeight(random(2)); 151 | point(x, y); 152 | } 153 | } 154 | } 155 | } 156 | 157 | void drawCenteredGradientSquares() { 158 | int perSide = 5; 159 | int margin = 10; 160 | int inc = (width - margin * 2) / perSide; 161 | int perFrame = 500; 162 | for (int yi = 0; yi < perSide; yi++) { 163 | for (int xi = 0; xi < perSide; xi++) { 164 | float xBase = margin + xi * inc; 165 | float yBase = margin + yi * inc; 166 | int index = xi + yi * perSide; 167 | for (int points = 0; points < perFrame; points++) { 168 | float x = xBase + random(inc); 169 | float y = yBase + random(inc); 170 | float distanceFromSide = min(x - xBase, min(xBase + inc - x, min(y - yBase, yBase + inc - y))); 171 | float distanceF = pow(distanceFromSide / (inc / 2), 0.5 + index * 0.15); 172 | strokeWeight(1.5 - 1.5 * distanceF); 173 | point(x, y); 174 | } 175 | } 176 | } 177 | } 178 | 179 | PVector randomInCircle(float x, float y, float r, float power, float fuzz) { 180 | return PVector.random2D().mult((r + r * random(fuzz)) * pow(random(1), power)).add(new PVector(x, y)); 181 | } 182 | -------------------------------------------------------------------------------- /GroovingSun/GroovingSun.pde: -------------------------------------------------------------------------------- 1 | int margin = 10; 2 | PGraphics back; 3 | PGraphics pg; 4 | 5 | void setup() { 6 | size(900, 900, P3D); 7 | pg = createGraphics(1080, 1080, P3D); 8 | back = createGraphics(1080, 1080, P2D); 9 | pg.smooth(8); 10 | colorMode(HSB, 360, 100, 100, 100); 11 | pg.beginDraw(); 12 | pg.colorMode(HSB, 360, 100, 100, 100); 13 | pg.endDraw(); 14 | setupBackground(); 15 | } 16 | 17 | void setupBackground() { 18 | float baseHue = 225; 19 | back.beginDraw(); 20 | back.loadPixels(); 21 | for (int y = 0; y < back.height; y++) { 22 | for (int x = 0; x < back.width; x++) { 23 | int px = x + y * back.width; 24 | back.pixels[px] = color(baseHue + 55.0 * x / back.height, 100, 100.0 * y / back.height); 25 | } 26 | } 27 | back.updatePixels(); 28 | back.endDraw(); 29 | } 30 | 31 | void draw() { 32 | pg.beginDraw(); 33 | pg.image(back, 0, 0, pg.width, pg.height); 34 | pg.noFill(); 35 | pg.strokeWeight(2); 36 | pg.stroke(25, 69, 100); 37 | PVector origin = new PVector(pg.width / 2, pg.height / 2); 38 | float rOuter = pg.width / 2 - margin; 39 | float rInner = pg.width / 4; 40 | int lerpPointCount = int((rOuter - rInner) / 2); 41 | int spokes = 10; 42 | float spokeInc = 2 * PI / spokes; 43 | float waveMagTimeFactor = pow(abs(sin(radians(frameCount * 0.1))), 0.5); 44 | for (int a = 0; a < spokes; a++) { 45 | float t = a * spokeInc; 46 | float t2 = t + spokeInc; 47 | float mid = (t + t2) / 2; 48 | int n = 20; 49 | PVector meetingPoint = PVector.fromAngle(mid).mult(rOuter).add(origin); 50 | float angleInc = (t2 - t) / n; 51 | float waveMag = 5 + 30.0 * waveMagTimeFactor; 52 | float waveOffset = radians(frameCount * 5); 53 | for (int i = 0; i <= n; i++) { 54 | float angle = t + i * angleInc; 55 | PVector rimPoint = PVector.fromAngle(angle).mult(rInner).add(origin); 56 | PVector dir = PVector.sub(meetingPoint, rimPoint).normalize(); 57 | PVector normal = new PVector(-dir.y, dir.x); 58 | // draw line of "lerpPointCount" points between rimPoint and meetingPoint, with each point deviated a bit by a sine wave 59 | pg.beginShape(); 60 | for (int j = 0; j <= lerpPointCount; j++) { 61 | PVector v = PVector.lerp(rimPoint, meetingPoint, 1.0 * j / lerpPointCount); 62 | float calc = map(j, 0, lerpPointCount, 0, 2 * PI); 63 | calc = waveMag * sin(calc * 2.0 * sin(radians(frameCount * 0.5)) + waveOffset); 64 | float distFactor = 1.0 * j / lerpPointCount; 65 | // y = 1 - (2*x - 1)^2: 66 | // ensure that wave magnitude approaches 0 when close to rimPoint and meetingPoint, so all lines end up where we want them to 67 | distFactor = 1 - (2 * distFactor - 1) * (2 * distFactor - 1); 68 | v.add(PVector.mult(normal, calc * distFactor)); 69 | pg.vertex(v.x, v.y); 70 | } 71 | pg.endShape(); 72 | if (angle % TWO_PI > PI / 2 && angle % TWO_PI < 3 * PI / 2) { 73 | PVector temp = rimPoint.copy().sub(origin); 74 | PVector rimPoint2 = new PVector(-temp.x, temp.y).add(origin); 75 | int lerpPointCount2 = int(abs(temp.x)); 76 | float internalWaveMagTimeFactor = abs(sin(radians(frameCount * 0.25))); 77 | pg.beginShape(); 78 | for (int j = 0; j <= lerpPointCount2; j++) { 79 | PVector v = PVector.lerp(rimPoint, rimPoint2, 1.0 * j / lerpPointCount2); 80 | float calc = map(j, 0, lerpPointCount, 0, 2 * PI); 81 | calc = internalWaveMagTimeFactor * 3 * waveMag * sin(calc * 2.0 + waveOffset); 82 | float distFactor = 1.0 * j / lerpPointCount2; 83 | distFactor = 1 - (2 * distFactor - 1) * (2 * distFactor - 1); 84 | distFactor *= (1 - abs(temp.y) / rInner); // make horizontal waves smaller at top and bottom of circle 85 | v.add(new PVector(0, calc * distFactor)); 86 | pg.vertex(v.x, v.y); 87 | } 88 | pg.endShape(); 89 | } 90 | } 91 | } 92 | pg.endDraw(); 93 | image(pg, 0, 0, width, height); 94 | println(frameCount / 60); 95 | } 96 | -------------------------------------------------------------------------------- /HalftoneSpiral/HalftoneSpiral.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | int arms = 3; 3 | float spiralExp = 3; 4 | 5 | void setup() { 6 | size(1600, 900, P2D); 7 | pg = createGraphics(1920, 1080, P2D); 8 | colorMode(HSB, 360, 100, 100, 100); 9 | pg.smooth(8); 10 | pg.beginDraw(); 11 | pg.ellipseMode(RADIUS); 12 | pg.colorMode(HSB, 360, 100, 100, 100); 13 | pg.endDraw(); 14 | } 15 | 16 | void draw() { 17 | pg.beginDraw(); 18 | pg.background(245, 90, 5); 19 | pg.noStroke(); 20 | int n = 80; 21 | float inc = 1.0 * pg.width / n; 22 | float maxD = dist(0, 0, pg.width / 2, pg.height / 2); 23 | float spiralAdd = 30.0; 24 | float shadeExp = 0.5 + 9 * pow(0.5 * (1 + sin(radians(frameCount * 0.75))), 2); 25 | float speed = 3; 26 | float maxRFrac = 0.9 * min(1, 1.0 * frameCount / 1200); 27 | float minRFrac = 0.05 * min(1, 1.0 * frameCount / 600); 28 | for (int yi = 0; yi < n; yi++) { 29 | float y = inc * yi + inc / 2; 30 | for (int xi = 0; xi < n; xi++) { 31 | float x = inc * xi + inc / 2; 32 | float th = atan2(y - pg.height / 2, x - pg.width / 2); 33 | pg.fill(color(abs(th) / PI * 45, 100, 100)); 34 | float d = dist(x, y, pg.width / 2, pg.height / 2); 35 | float fd = 0.5 * (1 + sin(d / maxD * TAU * (1 + spiralAdd * pow(d / maxD, spiralExp)) + th * arms + radians(-frameCount * speed))); 36 | pg.circle(x, y, inc / 2 * (minRFrac + maxRFrac * pow(fd, shadeExp))); 37 | } 38 | } 39 | pg.endDraw(); 40 | image(pg, 0, 0, width, height); 41 | println(frameCount / 60); 42 | } 43 | 44 | void keyPressed() { 45 | if (key == CODED) { 46 | if (keyCode == UP) { 47 | arms++; 48 | } 49 | if (keyCode == DOWN && arms > 1) { 50 | arms--; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /IllusionOfForm/IllusionOfForm.pde: -------------------------------------------------------------------------------- 1 | import java.util.Date; 2 | 3 | PGraphics pg; 4 | color bgColor = color(40, 0, 0); // color(0); // color(255); // color(255, 225, 200); 5 | color strokeColor = color(255, 125, 125, 40); // color(255, 125, 50, 40); //color(255, 40); // 6 | PVector c; 7 | float r; 8 | float maxDiagonal; 9 | boolean save; 10 | 11 | void setup() { 12 | size(1600, 900, P3D); 13 | pg = createGraphics(1920, 1080, P3D); 14 | maxDiagonal = sqrt(pg.width * pg.width + pg.height * pg.height); 15 | pg.smooth(8); 16 | pg.beginDraw(); 17 | pg.ellipseMode(RADIUS); 18 | pg.stroke(strokeColor); 19 | pg.blendMode(ADD); 20 | pg.endDraw(); 21 | } 22 | 23 | void draw() { 24 | int perFrame = 4; 25 | pg.beginDraw(); 26 | if (frameCount == 1) { 27 | pg.noFill(); 28 | pg.background(bgColor); 29 | } 30 | pg.strokeWeight(1); 31 | for (int j = 0; j < perFrame; j++) { 32 | float t = random(2 * PI); 33 | float t2 = t + PI / 2 * (random(2) < 1 ? -1 : 1); 34 | float x = r * cos(t); 35 | float y = r * sin(t); 36 | PVector v = PVector.fromAngle(t2); 37 | if (c != null) { 38 | PVector p = new PVector(x, y).add(c); 39 | PVector p2 = p.copy().add(v.mult(maxDiagonal)); 40 | pg.line(p.x, p.y, p2.x, p2.y); 41 | } 42 | } 43 | if (save) { 44 | pg.save("TheIllusionOfForm" + (new Date()).getTime() + ".png"); 45 | save = false; 46 | } 47 | pg.endDraw(); 48 | image(pg, 0, 0, width, height); 49 | println(frameRate); 50 | } 51 | 52 | void mouseClicked() { 53 | if (mouseButton == LEFT) { 54 | float x = map(mouseX, 0, width, 0, pg.width); 55 | float y = map(mouseY, 0, height, 0, pg.height); 56 | r = random(100, 200); 57 | c = new PVector(x, y); 58 | } 59 | if (mouseButton == RIGHT) { 60 | save = true; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /IllusionOfForm/README.md: -------------------------------------------------------------------------------- 1 | A very simple sketch based on drawing "circles" by drawing lots of lines tangent to them at different angles. Some example outputs: 2 | 3 | ![TheIllusionOfForm1649540760362](https://user-images.githubusercontent.com/101308215/162653000-6589353c-b823-41d5-9159-5441eb7bea77.png) 4 | 5 | ![TheIllusionOfForm1649529712616](https://user-images.githubusercontent.com/101308215/162653010-381b1f94-fc82-4434-b3d6-b53e526fcf79.png) 6 | 7 | ![TheIllusionOfForm1649541809231](https://user-images.githubusercontent.com/101308215/162652991-1c2864d1-6752-4364-a3c3-eb7162a154b2.png) 8 | 9 | ![TheIllusionOfForm1649541630589](https://user-images.githubusercontent.com/101308215/162652997-a394485a-49d3-49fe-a733-7cf477b7c0af.png) 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Brian Fearn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LazyTrackers/LazyTrackers.pde: -------------------------------------------------------------------------------- 1 | ArrayList watchers = new ArrayList(); 2 | int n = 8; 3 | float turnRate = 0.02; 4 | 5 | void setup() { 6 | size(900, 900, P2D); 7 | smooth(8); 8 | ellipseMode(CENTER); 9 | float inc = 1.0 * width / n; 10 | for (int yi = 0; yi < n; yi++) { 11 | for (int xi = 0; xi < n; xi++) { 12 | float x = xi * inc + inc / 2; 13 | float y = yi * inc + inc / 2; 14 | watchers.add(new Watcher(new PVector(x, y), inc / 5)); 15 | } 16 | } 17 | } 18 | 19 | float currHeading = 0.0; 20 | 21 | void draw() { 22 | background(0, 25, 50); 23 | stroke(255, 225, 200); 24 | fill(25, 75, 100); 25 | strokeWeight(20.0 / n); 26 | for (Watcher w : watchers) { 27 | w.update(); 28 | w.show(); 29 | } 30 | stroke(255, 100, 75); 31 | fill(255, 100, 75); 32 | circle(mouseX, mouseY, 20); 33 | println(frameRate); 34 | } 35 | 36 | class Watcher { 37 | 38 | PVector pos; 39 | float currHeading; 40 | float dim; 41 | 42 | Watcher(PVector pos, float dim) { 43 | this.pos = pos; 44 | this.dim = dim; 45 | } 46 | 47 | void update() { 48 | PVector m = new PVector(mouseX, mouseY); 49 | PVector diff = m.copy().sub(pos); 50 | float h = diff.heading(); 51 | float heading = h > 0 ? h : 2 * PI + h; 52 | // make sure Watcher always turns using the geometrically "shortest" direction (cw or ccw) 53 | if (heading > 3 * PI / 2 && currHeading < PI / 2) { 54 | float goalHeading = heading - 2 * PI; 55 | currHeading = lerp(currHeading, goalHeading, turnRate); 56 | currHeading = currHeading < 0 ? 2 * PI + currHeading : currHeading; 57 | } else if (heading < PI / 2 && currHeading > 3 * PI / 2) { 58 | float goalHeading = 2 * PI + heading; 59 | currHeading = lerp(currHeading, goalHeading, turnRate) % (2 * PI); 60 | } else { 61 | currHeading = lerp(currHeading, heading, turnRate); 62 | } 63 | } 64 | 65 | void show() { 66 | push(); 67 | translate(pos.x, pos.y); 68 | rotate(currHeading); 69 | triangle(-dim, -dim, -dim, dim, dim * 2, 0); 70 | pop(); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /LineWarp/LineWarp.pde: -------------------------------------------------------------------------------- 1 | //MIT License 2 | 3 | //Copyright (c) 2022 Brian Fearn 4 | 5 | //Permission is hereby granted, free of charge, to any person obtaining a copy 6 | //of this software and associated documentation files (the "Software"), to deal 7 | //in the Software without restriction, including without limitation the rights 8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | //copies of the Software, and to permit persons to whom the Software is 10 | //furnished to do so, subject to the following conditions: 11 | 12 | //The above copyright notice and this permission notice shall be included in all 13 | //copies or substantial portions of the Software. 14 | 15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | //SOFTWARE. 22 | 23 | int n = 3; 24 | ArrayList warpers = new ArrayList(); 25 | 26 | void setup() { 27 | size(900, 900, P3D); 28 | smooth(8); 29 | noFill(); 30 | for (int i = 0; i < n; i++) { 31 | warpers.add(new Warper()); 32 | } 33 | } 34 | 35 | void draw() { 36 | background(0, 0, 50); 37 | strokeWeight(2); 38 | int yn = 50; 39 | float yinc = 1.0 * height / yn; 40 | int xn = 300; 41 | float xinc = 1.0 * width / xn; 42 | for (Warper w : warpers) { 43 | w.update(); 44 | } 45 | for (int yi = -10; yi < yn + 10; yi++) { 46 | float y = yi * yinc + yinc / 2; 47 | stroke(yi % 2 == 0 ? color(255, 225, 200) : color(200, 200, 255)); // color(255, 175, 200)); 48 | beginShape(); 49 | for (int xi = -35; xi < xn + 35; xi++) { 50 | float x = xi * xinc + xinc / 2; 51 | PVector p = new PVector(x, y); 52 | for (Warper w : warpers) { 53 | PVector o = w.pos; 54 | float fdist = pow(1 - min(1.0, p.copy().sub(o).mag() / w.warpRadius), 5.0); 55 | if (fdist > 0.0) { 56 | p.sub(o); 57 | p.rotate(fdist * w.warpAngle); 58 | p.add(o); 59 | } 60 | } 61 | vertex(p.x, p.y); 62 | } 63 | endShape(); 64 | } 65 | println(frameRate); 66 | } 67 | 68 | class Warper { 69 | 70 | PVector pos, vel; 71 | float timeOffset, warpAngle, warpRadius; 72 | 73 | Warper() { 74 | this.pos = new PVector(random(width), random(height)); 75 | this.vel = new PVector(random(1, 4) * (random(2) < 1 ? -1 : 1), random(1, 4) * (random(2) < 1 ? -1 : 1)); 76 | this.timeOffset = random(2 * PI); 77 | this.warpAngle = (random(2) < 1 ? -1 : 1) * random(PI, 2 * PI); 78 | this.warpRadius = random(300, 500); 79 | } 80 | 81 | void update() { 82 | if (pos.x < 0 || pos.x > width) { 83 | vel.x *= -1; 84 | } 85 | if (pos.y < 0 || pos.y > height) { 86 | vel.y *= -1; 87 | } 88 | this.pos.add(vel); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /LinksInTheDarkness/LinksInTheDarkness.pde: -------------------------------------------------------------------------------- 1 | ArrayList circles = new ArrayList(); 2 | int n = 35; 3 | int minR = 10; 4 | int maxR = 60; 5 | int connectionsPerCircle = 30; 6 | color COPPER = color(255, 150, 75); 7 | color ELECTRIC_PURPLE = color(125, 100, 225); 8 | color strokeColor = COPPER; 9 | float springFactor = 0.02; 10 | 11 | void setup() { 12 | size(900, 900, P3D); 13 | smooth(8); 14 | blendMode(ADD); 15 | ellipseMode(RADIUS); 16 | noFill(); 17 | for (int i = 0; i < n; i++) { 18 | boolean big = false; // random(n / 2) < 1; 19 | float r = big ? maxR * 2 : random(minR, maxR); 20 | circles.add(new Circle(new PVector(random(r, width - r), random(r, height - r)), r, big ? connectionsPerCircle * 2 : connectionsPerCircle, i)); 21 | } 22 | } 23 | 24 | void draw() { 25 | background(0, 0, 10); 26 | strokeWeight(1); 27 | doCollisions(); 28 | for (Circle c : circles) { 29 | c.update(); 30 | for (Circle o : circles) { 31 | if (o != c) { 32 | c.connect(o); 33 | } 34 | } 35 | } 36 | println(frameCount / 60); 37 | println(frameRate); 38 | } 39 | 40 | void doCollisions() { 41 | for (int i = 0; i < circles.size() - 1; i++) { 42 | for (int j = i + 1; j < circles.size(); j++) { 43 | circles.get(i).collide(circles.get(j)); 44 | } 45 | } 46 | } 47 | 48 | class Circle { 49 | 50 | PVector c, v; 51 | float r; 52 | int id; 53 | ArrayList points; 54 | 55 | Circle(PVector c, float r, int nPoints, int id) { 56 | this.c = c; 57 | this.r = r; 58 | this.v = new PVector(random(1, 2) * (random(2) < 1 ? -1 : 1), 59 | random(1, 2) * (random(2) < 1 ? -1 : 1)); 60 | points = new ArrayList(); 61 | for (int i = 0; i < nPoints; i++) { 62 | points.add(PVector.fromAngle(i * 2 * PI / nPoints).mult(r).add(c)); 63 | } 64 | this.id = id; 65 | } 66 | 67 | void update() { 68 | if (c.x - r < 0 || c.x + r > width) { 69 | v.x *= -1; 70 | } 71 | if (c.y - r < 0 || c.y + r > height) { 72 | v.y *= -1; 73 | } 74 | for (PVector p : points) { 75 | p.sub(c); 76 | p.rotate(PI / 360); 77 | p.add(c); 78 | p.add(v); 79 | } 80 | c.add(v); 81 | } 82 | 83 | void connect(Circle o) { 84 | for (PVector p : points) { 85 | PVector closest = findClosest(p, o.points); 86 | float maxD = (150 + 100.0 * mouseX / width); 87 | float d = PVector.sub(p, closest).mag(); 88 | if (d < maxD) { 89 | float fd = max(pow(1 - d / maxD, 3), 0); 90 | strokeWeight(0.5 + 3 * fd); 91 | stroke(strokeColor, 255 * fd); 92 | line(p.x, p.y, closest.x, closest.y); 93 | } 94 | } 95 | } 96 | 97 | void collide(Circle o) { 98 | PVector diff = o.c.copy().sub(this.c); 99 | float minDist = this.r + o.r; 100 | if (diff.magSq() < (o.r + this.r) * (o.r + this.r)) { 101 | float angle = atan2(o.c.y - this.c.y, o.c.x - this.c.x); 102 | float targetX = this.c.x + cos(angle) * minDist; 103 | float targetY = this.c.y + sin(angle) * minDist; 104 | PVector velDiff = new PVector( 105 | (targetX - o.c.x) * springFactor, 106 | (targetY - o.c.y) * springFactor); 107 | this.v.sub(velDiff); 108 | o.v.add(velDiff); 109 | } 110 | } 111 | 112 | } 113 | 114 | PVector findClosest(PVector p, ArrayList o) { 115 | float dSq = Float.MAX_VALUE; 116 | PVector closest = null; 117 | for (PVector v : o) { 118 | float dSq2 = PVector.sub(p, v).magSq(); 119 | if (dSq2 < dSq) { 120 | closest = v; 121 | dSq = dSq2; 122 | } 123 | } 124 | return closest; 125 | } 126 | -------------------------------------------------------------------------------- /Luminous/Luminous.pde: -------------------------------------------------------------------------------- 1 | import java.util.Date; 2 | 3 | ArrayList movers = new ArrayList(); 4 | PGraphics pg; 5 | color c; 6 | boolean save = false; 7 | 8 | void setup() { 9 | size(900, 900, P2D); 10 | pg = createGraphics(1080, 1080, P2D); 11 | pg.smooth(8); 12 | pg.beginDraw(); 13 | pg.noStroke(); 14 | pg.colorMode(HSB, 360, 100, 100, 100); 15 | pg.background(225, 100, 10); 16 | pg.blendMode(ADD); 17 | pg.ellipseMode(RADIUS); 18 | for (int i = 0; i < 40; i++) { 19 | PVector p = new PVector(random(pg.width), random(pg.height)); 20 | movers.add(new Mover(p.copy())); 21 | } 22 | } 23 | 24 | void draw() { 25 | pg.beginDraw(); 26 | if (frameCount < 3) { 27 | pg.background(225, 100, 10); 28 | } 29 | for (Mover m : movers) { 30 | m.update(); 31 | m.show(); 32 | } 33 | if (save) { 34 | pg.save(getClass().getName() + new Date().getTime() + ".png"); 35 | save = false; 36 | } 37 | pg.endDraw(); 38 | image(pg, 0, 0, width, height); 39 | } 40 | 41 | void mouseClicked() { 42 | save = true; 43 | } 44 | 45 | class Mover { 46 | 47 | PVector pos; 48 | float offset; 49 | int steps = 0; 50 | float speed; 51 | 52 | Mover(PVector pos) { 53 | this.pos = pos.copy(); 54 | this.offset = random(TAU); 55 | this.speed = random(0.05, 0.6); 56 | } 57 | 58 | void update() { 59 | if (steps >= 200) { 60 | steps = 0; 61 | pos = new PVector(random(pg.width), random(pg.height)); 62 | } 63 | float th = offset + sin(radians(frameCount * speed)) * TAU; 64 | pos.add(PVector.fromAngle(th).mult(1)); 65 | steps++; 66 | } 67 | 68 | void show() { 69 | float th = offset + sin(radians(frameCount * 0.2)) * TAU; 70 | float ft = 0.5 * (1 + sin(radians(frameCount * 3))); 71 | pg.fill(160, 60 + 30 * sin(th), 60, 4); 72 | pg.circle(pos.x, pos.y, 2 + 30 * pow(float(steps) / 200, 2)); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /MakingItAllFit/MakingItAllFit.pde: -------------------------------------------------------------------------------- 1 | 2 | int margin = 0; 3 | 4 | void setup() { 5 | size(900, 900, P2D); 6 | smooth(8); 7 | colorMode(HSB, 360, 100, 100, 100); 8 | } 9 | 10 | void draw() { 11 | background(0); 12 | noStroke(); 13 | fill(0); 14 | float rowT = 0.5 * (1 + sin(radians(-frameCount * 0.5))); 15 | float colT = 0.5 * (1 + sin(radians(frameCount * 0.25))); 16 | int perRow = 30; 17 | int perColumn = 60; 18 | 19 | float power = 0.75 + 2.25 * rowT; // mouseX / width; 20 | float powerV = 0.25 + 4.75 * colT; // mouseY / height; 21 | float y = margin; 22 | float _width = width - margin * 2; 23 | float _height = height - margin * 2; 24 | for (int col = 1; col <= perColumn; col++) { 25 | float colOffset = 2 * PI * col / perColumn; 26 | float py = 1.0 * col / perColumn; 27 | py = pow(py, powerV); 28 | float nextY = margin + py * _height; 29 | float x = margin; 30 | for (int i = 1; i <= perRow; i++) { 31 | float rowOffset = 2 * PI * i / perRow; 32 | float t = 0.001 + 0.998 * 0.5 * (1 + sin(rowOffset * 5 + colOffset * 3 + radians(frameCount * 3))); // time factor to vary triangle peak offset 33 | color hFill = color(50.0 * i / perRow, 100, 100); 34 | float p = 1.0 * i / perRow; 35 | p = pow(p, power); 36 | float nextX = margin + p * _width; 37 | float c = lerp(x, nextX, t); // calc offset for triangle peak 38 | fill(hFill); 39 | triangle(x, nextY, nextX, nextY, c, y); 40 | x = nextX; 41 | } 42 | y = nextY; 43 | } 44 | println(frameRate); 45 | } 46 | -------------------------------------------------------------------------------- /MoireDragRectangles/MoireDragRectangles.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg, pg2; 2 | PVector start; 3 | PVector end; 4 | PVector mouseMapped; 5 | 6 | void setup() { 7 | size(900, 900, P2D); 8 | pg = createGraphics(1080, 1080, P2D); 9 | pg2 = createGraphics(1080, 1080, P2D); 10 | 11 | pg.smooth(8); 12 | pg.beginDraw(); 13 | pg.imageMode(CORNERS); 14 | pg.background(255, 225, 200); 15 | pg.endDraw(); 16 | 17 | pg2.smooth(8); 18 | pg2.beginDraw(); 19 | pg2.rectMode(CORNERS); 20 | pg2.endDraw(); 21 | } 22 | 23 | void draw() { 24 | mouseMapped = new PVector(map(mouseX, 0, width, 0, pg2.width), map(mouseY, 0, height, 0, pg2.height)); 25 | pg2.beginDraw(); 26 | pg2.background(255, 225, 200); 27 | pg2.image(pg, 0, 0, pg2.width, pg2.height); 28 | pg2.fill(0); 29 | pg2.circle(mouseMapped.x, mouseMapped.y, 15); 30 | if (mousePressed) { 31 | pg2.noFill(); 32 | pg2.rect(start.x, start.y, mouseMapped.x, mouseMapped.y); 33 | } 34 | pg2.endDraw(); 35 | image(pg2, 0, 0, width, height); 36 | println(frameCount / 60); 37 | } 38 | 39 | void mousePressed() { 40 | start = new PVector(mouseMapped.x, mouseMapped.y); 41 | } 42 | 43 | void mouseReleased() { 44 | if (mouseButton != RIGHT) { 45 | end = new PVector(mouseMapped.x, mouseMapped.y); 46 | ringRect(start.x, start.y, end.x, end.y); 47 | } 48 | } 49 | 50 | void mouseClicked() { 51 | if (mouseButton == RIGHT) { 52 | exit(); 53 | } 54 | } 55 | 56 | void ringRect(float x, float y, float x2, float y2) { 57 | int w = int(abs(x2 - x)); 58 | int h = int(abs(y2 - y)); 59 | PGraphics temp = createGraphics(w, h, P2D); 60 | temp.smooth(8); 61 | temp.beginDraw(); 62 | temp.strokeWeight(2); 63 | temp.noFill(); 64 | temp.ellipseMode(RADIUS); 65 | PVector center = new PVector(random(w), random(h)); 66 | float maxR = max(w * 2, h * 2); 67 | for (float r = 4; r < maxR; r += 4) { 68 | temp.circle(center.x, center.y, r); 69 | } 70 | temp.rect(0, 0, w, h); 71 | temp.endDraw(); 72 | pg.beginDraw(); 73 | pg.image(temp, x, y, x2, y2); 74 | pg.endDraw(); 75 | } 76 | -------------------------------------------------------------------------------- /NoiseShift/NoiseShift.pde: -------------------------------------------------------------------------------- 1 | void setup() { 2 | size(400, 400, P2D); 3 | } 4 | 5 | void draw() { 6 | float ft = sin(PI + radians(frameCount * 0.1)); 7 | float ft2 = sin(PI + radians(frameCount * 0.1)); 8 | float sc = 0.008; 9 | float ysc = 0.008; 10 | float ffc = frameCount * 0.002; 11 | loadPixels(); 12 | for (int y = 0; y < height; y++) { 13 | for (int x = 0; x < width; x++) { 14 | int px = x + y * width; 15 | float noize = noise(x * sc, ffc + y * ysc, ffc); 16 | noize = pow(0.5 * (1 + sin(noize * TAU * 10)), 5); 17 | float noize2 = noise(x * sc, ffc + y * ysc + ft * 10 * sc, ffc); 18 | noize2 = pow(0.5 * (1 + sin(noize2 * TAU * 10)), 5); 19 | float noize3 = noise(x * sc, ffc + y * ysc - ft2 * 10 * sc, ffc); 20 | noize3 = pow(0.5 * (1 + sin(noize3 * TAU * 10)), 5); 21 | pixels[px] = color(noize2 + noize * 255, noize2 * 255, noize3 * 255); 22 | } 23 | } 24 | updatePixels(); 25 | println(frameCount / 60); 26 | } 27 | -------------------------------------------------------------------------------- /PaletteShifter/PaletteShifter.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | Ball ball; 4 | 5 | void setup() { 6 | size(900, 900, P2D); 7 | pg = createGraphics(1080, 1080, P2D); 8 | pg.smooth(8); 9 | colorMode(RGB, 1.0, 1.0, 1.0, 1.0); 10 | pg.beginDraw(); 11 | pg.colorMode(RGB, 1.0, 1.0, 1.0, 1.0); 12 | pg.endDraw(); 13 | ball = new Ball(new PVector(pg.width / 2, pg.height / 2), new PVector(1.5, 1), 20); 14 | } 15 | 16 | void draw() { 17 | pg.beginDraw(); 18 | float rCoefficient = ball.p.x / pg.width; 19 | float gCoefficient = ball.p.y / pg.height; 20 | int nx = 5; 21 | int xInc = pg.width / nx; 22 | for (int y = 0; y < pg.height; y++) { 23 | float d = 1.0 * y / pg.height / 2; 24 | for (int x = 0; x < nx; x++) { 25 | float r = pow(abs(sin(radians(frameCount * 0.01 * (x + 1)) + 2 * PI * rCoefficient + 2 * PI * d)), 2 + x); 26 | float g = pow(abs(sin(2 * PI * gCoefficient + 2 * PI * d)), 3 + x); 27 | float b = pow(abs(sin(2 * PI * d)), 4 + x); 28 | pg.stroke(r, g, b); 29 | pg.line(x * xInc, y, (x + 1) * xInc, y); 30 | } 31 | } 32 | ball.update(); 33 | ball.show(); 34 | pg.endDraw(); 35 | image(pg, 0, 0, width, height); 36 | println(frameCount / 60); 37 | } 38 | 39 | class Ball { 40 | 41 | float r; 42 | PVector p, v; 43 | 44 | Ball(PVector p, PVector v, float r) { 45 | this.p = p; 46 | this.v = v; 47 | this.r = r; 48 | } 49 | 50 | void update() { 51 | p.add(v); 52 | if (p.x - r < 0 || p.x + r > pg.width) { 53 | v.x *= -1; 54 | } 55 | if (p.y - r < 0 || p.y + r > pg.height) { 56 | v.y *= -1; 57 | } 58 | } 59 | 60 | void show() { 61 | pg.noStroke(); 62 | pg.fill(0); 63 | pg.circle(p.x, p.y, r); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /PerlinNoiseBounds/PerlinNoiseBounds.pde: -------------------------------------------------------------------------------- 1 | //MIT License 2 | 3 | //Copyright (c) 2022 Brian Fearn 4 | 5 | //Permission is hereby granted, free of charge, to any person obtaining a copy 6 | //of this software and associated documentation files (the "Software"), to deal 7 | //in the Software without restriction, including without limitation the rights 8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | //copies of the Software, and to permit persons to whom the Software is 10 | //furnished to do so, subject to the following conditions: 11 | 12 | //The above copyright notice and this permission notice shall be included in all 13 | //copies or substantial portions of the Software. 14 | 15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | //SOFTWARE. 22 | 23 | import java.util.Date; 24 | 25 | // USAGE NOTES 26 | // click to save 27 | // change colors by altering the show() method of Particle class 28 | // change sweep direction of particles by altering the getVelocity() and initVelocity() methods of Particle class 29 | 30 | boolean save = false; 31 | int regionCount = 20; 32 | float scaleNoiseX = 0.002; 33 | float scaleNoiseY = 0.002; 34 | int n = 4000; 35 | ArrayList particles = new ArrayList(); 36 | PGraphics pg; 37 | 38 | void setup() { 39 | size(900, 900, P2D); 40 | pg = createGraphics(1080, 1080, P2D); 41 | pg.smooth(8); 42 | colorMode(HSB, 360, 100, 100, 100); 43 | pg.beginDraw(); 44 | pg.colorMode(HSB, 360, 100, 100, 100); 45 | pg.blendMode(ADD); 46 | pg.background(0); 47 | pg.endDraw(); 48 | for (int i = 0; i < n; i++) { 49 | particles.add(new Particle(new PVector(random(pg.width), random(pg.height)))); 50 | } 51 | } 52 | 53 | void draw() { 54 | pg.beginDraw(); 55 | if (frameCount == 1) { 56 | pg.background(0); 57 | } 58 | for (Particle p : particles) { 59 | p.update(); 60 | p.show(); 61 | } 62 | pg.endDraw(); 63 | if (save) { 64 | save = false; 65 | pg.save(getClass().getName() + (new Date()).getTime() + ".png"); 66 | } 67 | image(pg, 0, 0, width, height); 68 | println(frameRate); 69 | } 70 | 71 | void mouseClicked() { 72 | save = true; 73 | } 74 | 75 | int getRegion(float x, float y) { 76 | return int(regionCount * noise(x * scaleNoiseX, y * scaleNoiseY)); 77 | } 78 | 79 | class Particle { 80 | 81 | PVector pos, vel, last; 82 | int region; 83 | 84 | Particle(PVector pos) { 85 | this.pos = pos; 86 | this.last = pos.copy(); 87 | this.region = getRegion(pos.x, pos.y); 88 | initVelocity(); 89 | } 90 | 91 | void update() { 92 | last = pos.copy(); 93 | pos.add(getVelocity()); 94 | if (outOfBounds()) { 95 | this.reset(); 96 | return; 97 | } 98 | } 99 | 100 | PVector getVelocity() { 101 | return vel; 102 | //return PVector.fromAngle(PI / 2 + PI * 0.5 * (1 + sin(map(pos.x, 0, pg.width, 0, 4 * PI)))); 103 | //return PVector.fromAngle(radians(frameCount * 0.3) % (PI / 2)); 104 | //return PVector.fromAngle(PI / 3 + PI / 4 * sin(radians(frameCount * 3))); 105 | //return PVector.fromAngle(4 * PI / 3); 106 | } 107 | 108 | void initVelocity() { 109 | this.vel = PVector.fromAngle(1.0 * region / regionCount * 2 * PI).mult(0.5); 110 | //this.vel = pos.copy().sub(new PVector(pg.width / 2, pg.height / 2)).normalize(); 111 | } 112 | 113 | void reset() { 114 | this.pos = new PVector(random(pg.width), random(pg.height)); 115 | this.last = pos.copy(); 116 | this.region = getRegion(pos.x, pos.y); 117 | initVelocity(); 118 | } 119 | 120 | boolean outOfBounds() { 121 | return this.region != getRegion(pos.x, pos.y) || pos.x < 0 || pos.x > pg.width || pos.y < 0 || pos.y > pg.height; 122 | } 123 | 124 | void show() { 125 | color ca = color(50, 50, 100, 3); 126 | color cb = color(225, 50, 100, 3); 127 | //pg.stroke(lerpColor(ca, cb, 1.0 * region / regionCount)); 128 | //pg.stroke(40, 70, 100, 3); 129 | //pg.stroke(200 + 60.0 * region / regionCount, 85, 100, 4); 130 | pg.stroke((720.0 * region / regionCount) % 360.0, 60, 100, 4); 131 | pg.strokeWeight(random(1, 2.5)); 132 | pg.line(pos.x, pos.y, last.x, last.y); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /PerlinStorm/PerlinStorm.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | void setup() { 4 | size(900, 900, P2D); 5 | pg = createGraphics(1080, 1080, P2D); 6 | pg.smooth(8); 7 | pg.beginDraw(); 8 | pg.blendMode(ADD); 9 | pg.background(0); 10 | pg.endDraw(); 11 | } 12 | 13 | void draw() { 14 | pg.beginDraw(); 15 | pg.background(0); 16 | pg.stroke(125, 125, 200, 50); 17 | float r = 500; 18 | int perFrame = int(r * 1.5); 19 | PVector m = new PVector(pg.width / 2, pg.height / 2); 20 | for (int i = 0; i < perFrame; i++) { 21 | float t = 2 * PI * i / perFrame; 22 | PVector p = PVector.fromAngle(t).mult(r).add(m); 23 | noiseLine(m.x, m.y, p.x, p.y, 5 + r * 1.5 * mouseX / width); 24 | } 25 | pg.endDraw(); 26 | image(pg, 0, 0, width, height); 27 | println(frameRate); 28 | } 29 | 30 | void noiseLine(float x1, float y1, float x2, float y2, float maxNoise) { 31 | PVector a = new PVector(x1, y1); 32 | PVector b = new PVector(x2, y2); 33 | PVector diff = b.copy().sub(a); 34 | PVector dir = diff.copy().normalize(); 35 | PVector n = new PVector(-dir.y, dir.x); 36 | float mag = diff.mag(); 37 | float half = mag / 2; 38 | pg.noFill(); 39 | pg.beginShape(); 40 | //vertex(a.x, a.y); 41 | for (int i = 0; i < mag; i += 4) { 42 | PVector p = dir.copy().mult(i).add(a); 43 | float df = 1 - abs(i - half) / half; 44 | p.add( 45 | n.copy().mult(df * maxNoise * (0.5 - noise(p.x * 0.01 + frameCount * 0.017, p.y * 0.01 + frameCount * 0.009)))); 46 | pg.vertex(p.x, p.y); 47 | } 48 | pg.endShape(); 49 | } 50 | -------------------------------------------------------------------------------- /PoissonTesting/GridClass.pde: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | 3 | class Grid { 4 | 5 | Cell [][] cells; 6 | ArrayList occupants; 7 | int pixW, pixH; 8 | int w, h; 9 | float cellW, cellH; 10 | 11 | Grid(int w, int h, int pixW, int pixH) { 12 | cells = new Cell[w][h]; 13 | 14 | this.pixW = pixW; 15 | this.pixH = pixH; 16 | this.cellW = 1.0 * pixW / w; 17 | this.cellH = 1.0 * pixH / h; 18 | for (int i = 0; i < w; i++) { 19 | for (int j = 0; j < h; j++) { 20 | PVector pos = new PVector(i * cellW, j * cellH); 21 | cells[i][j] = new Cell(pos, cellW, cellH); 22 | } 23 | } 24 | for (int x = 0; x < w; x++) { 25 | for (int y = 0; y < h; y++) { 26 | Cell c = cells[x][y]; 27 | c.neighbors = getNeighbors(x, y); 28 | } 29 | } 30 | this.w = w; 31 | this.h = h; 32 | occupants = new ArrayList(); 33 | } 34 | 35 | void add(T t, float xPixPos, float yPixPos) { 36 | int x = int(xPixPos / cellW); 37 | int y = int(yPixPos / cellW); 38 | cells[x][y].occupants.add(t); 39 | occupants.add(t); 40 | } 41 | 42 | void add(PVector p) { 43 | int x = int(p.x / cellW); 44 | int y = int(p.y / cellW); 45 | cells[x][y].occupants.add(p); 46 | } 47 | 48 | ArrayList getCellMembers(int x, int y) { 49 | return new ArrayList(cells[x][y].occupants); 50 | } 51 | 52 | Cell getCell(float xPixPos, float yPixPos) { 53 | int x = int(xPixPos / cellW); 54 | int y = int(yPixPos / cellW); 55 | return cells[x][y]; 56 | } 57 | 58 | Cell getCell(int x, int y) { 59 | if (x < 0 || x >= w || y < 0 || y >= h) { 60 | return null; 61 | } else { 62 | return cells[x][y]; 63 | } 64 | } 65 | 66 | ArrayList getNeighbors(int x, int y) { 67 | ArrayList results = new ArrayList(); 68 | for (int i = -1; i < 1; i++) { 69 | for (int j = -1; j < 1; j++) { 70 | Cell c = getCell(x + i, y + j); 71 | if (c != null && !(i == 0 && j == 0)) { 72 | results.add(c); 73 | } 74 | } 75 | } 76 | return results; 77 | } 78 | 79 | void show() { 80 | for (Cell [] array : cells) { 81 | for (Cell c : array) { 82 | c.show(); 83 | } 84 | } 85 | } 86 | 87 | void showVectors() { 88 | for (Cell [] array : cells) { 89 | for (Cell c : array) { 90 | c.showVectors(); 91 | } 92 | } 93 | } 94 | 95 | } 96 | 97 | class Cell { 98 | 99 | PVector pos; 100 | int id; 101 | float w, h; 102 | color fillColor; 103 | ArrayList neighbors; 104 | HashSet occupants; 105 | boolean active; 106 | 107 | Cell(PVector pos, float w, float h) { 108 | this.pos = pos; 109 | this.w = w; 110 | this.h = h; 111 | this.occupants = new HashSet(); 112 | this.neighbors = new ArrayList(); 113 | } 114 | 115 | void add(T t) { 116 | occupants.add(t); 117 | } 118 | 119 | void remove(T t) { 120 | occupants.remove(t); 121 | } 122 | 123 | void show() { 124 | noFill(); 125 | stroke(255); 126 | if (active) { 127 | stroke(255, 0, 0); 128 | } 129 | strokeWeight(1); 130 | rect(pos.x, pos.y, w, h); 131 | } 132 | 133 | ArrayList getOccupantsAndOccupantsOfNeighbors() { 134 | ArrayList results = new ArrayList(); 135 | for (Cell c : neighbors) { 136 | results.addAll(c.occupants); 137 | } 138 | results.addAll(occupants); 139 | return results; 140 | } 141 | 142 | ArrayList getOccupantsOfNeighbors() { 143 | ArrayList results = new ArrayList(); 144 | for (Cell c : neighbors) { 145 | results.addAll(c.occupants); 146 | } 147 | return results; 148 | } 149 | 150 | void showVectors() { 151 | strokeWeight(4); 152 | for (T o : occupants) { 153 | PVector p = (PVector) o; 154 | point(p.x, p.y); 155 | } 156 | } 157 | 158 | boolean contains(float x, float y) { 159 | return x >= pos.x && y >= pos.y && x <= pos.x + w && y <= pos.y + h; 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /PoissonTesting/PoissonTesting.pde: -------------------------------------------------------------------------------- 1 | //import com.hamoid.*; 2 | //import java.util.Date; 3 | //VideoExport videoExport; 4 | //final String sketchname = getClass().getName(); 5 | //import java.util.Arrays; 6 | 7 | //void rec() { 8 | // if (frameCount == 1) { 9 | // Date date = new Date(); 10 | // videoExport = new VideoExport(this, sketchname + date.getTime() + ".mp4", pg); 11 | // videoExport.setFrameRate(60); 12 | // videoExport.startMovie(); 13 | // } 14 | // videoExport.saveFrame(); 15 | //} 16 | 17 | PoissonSampler ps = new PoissonSampler(); 18 | ArrayList points = new ArrayList(); 19 | Grid grid; 20 | Grid segs; 21 | int margin = 5; 22 | PGraphics pg; 23 | 24 | void setup() { 25 | size(900, 900, P3D); 26 | pg = createGraphics(1080, 1080, P3D); 27 | pg.smooth(8); 28 | pg.beginDraw(); 29 | pg.background(200, 225, 255); 30 | pg.noStroke(); 31 | ArrayList vecs = ps.getPointsRect(new PVector(margin, margin), pg.width - margin * 2, pg.height - margin * 2, 30, 11); 32 | points.addAll(vecs); 33 | grid = new Grid(pg.width / 11, pg.height / 11, pg.width, pg.height); 34 | segs = new Grid(pg.width / 100, pg.height / 100, pg.width, pg.height); 35 | for (PVector v : vecs) { 36 | grid.add(v); 37 | } 38 | pg.background(0, 0, 50); 39 | pg.endDraw(); 40 | 41 | } 42 | 43 | int index = 0; 44 | boolean drawBg = true; 45 | 46 | void draw() { 47 | pg.beginDraw(); 48 | pg.strokeWeight(2); 49 | //pg.stroke(255); 50 | if (drawBg) { 51 | pg.background(0, 0, 50); 52 | pg.ellipseMode(RADIUS); 53 | //drawBg = false; 54 | } 55 | int perFrame = 100; 56 | //for (int i = 0; i < perFrame && index < points.size(); i++) { 57 | // PVector p = points.get(index); 58 | // pg.point(p.x, p.y); 59 | // index++; 60 | //} 61 | float maxD = dist(0, 0, pg.width / 2, pg.height / 2); 62 | float t = radians(frameCount * 0.2); 63 | for (PVector p : points) { 64 | PVector diff = p.copy().sub(new PVector(pg.width / 2, pg.height / 2)); 65 | float fd = pow(1 - dist(p.x, p.y, pg.width / 2, pg.height / 2) / maxD, 0.5); 66 | float r = 1 + 7 * pow(0.5 * (1 + sin(fd * TAU * 6 + (diff.heading() + t) * 5 + radians(frameCount * 4.5))), 2); 67 | //r = r * 0.5 * (1 + sin(p.x / pg.width * TAU * 3.1 + radians(frameCount * 3))); 68 | pg.square(p.x, p.y, r); 69 | } 70 | 71 | pg.endDraw(); 72 | image(pg, 0, 0, width, height); 73 | //if (index == points.size()) { 74 | // //pg.save("Poisson" + (new Date()).getTime() + ".png"); 75 | // println(index); 76 | // noLoop(); 77 | //} 78 | //rec(); 79 | println(frameCount / 60); 80 | } 81 | -------------------------------------------------------------------------------- /PolygonPacking/GridClass.pde: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | 3 | class Grid { 4 | 5 | Cell [][] cells; 6 | HashSet occupants; 7 | int pixW, pixH; 8 | float cellW, cellH; 9 | 10 | Grid(int w, int h, int pixW, int pixH) { 11 | cells = new Cell[w][h]; 12 | 13 | this.pixW = pixW; 14 | this.pixH = pixH; 15 | this.cellW = 1.0 * pixW / w; 16 | this.cellH = 1.0 * pixH / h; 17 | for (int i = 0; i < w; i++) { 18 | for (int j = 0; j < h; j++) { 19 | PVector pos = new PVector(i * cellW, j * cellH); 20 | cells[i][j] = new Cell(pos, cellW, cellH); 21 | } 22 | } 23 | for (int x = 0; x < w; x++) { 24 | for (int y = 0; y < h; y++) { 25 | 26 | Cell c = cells[x][y]; 27 | c.neighbors = getNeighbors(x, y); 28 | } 29 | } 30 | occupants = new HashSet(); 31 | } 32 | 33 | void add(T t, float xPixPos, float yPixPos) { 34 | int x = int(xPixPos / cellW); 35 | int y = int(yPixPos / cellH); 36 | cells[x][y].occupants.add(t); 37 | occupants.add(t); 38 | } 39 | 40 | void add(PVector p) { 41 | int x = int(p.x / cellW); 42 | int y = int(p.y / cellH); 43 | cells[x][y].occupants.add(p); 44 | occupants.add((T) p); 45 | } 46 | 47 | ArrayList getCellMembers(int x, int y) { 48 | return new ArrayList(cells[x][y].occupants); 49 | } 50 | 51 | Cell getCell(float xPixPos, float yPixPos) { 52 | int x = int(xPixPos / cellW); 53 | int y = int(yPixPos / cellH); 54 | return cells[x][y]; 55 | } 56 | 57 | ArrayList getNeighbors(int x, int y) { 58 | ArrayList results = new ArrayList(); 59 | boolean onLeftBorder = x == 0; 60 | boolean onRightBorder = x == cells.length - 1; 61 | boolean onTopBorder = y == 0; 62 | boolean onBottomBorder = y == cells[0].length - 1; 63 | if (!onLeftBorder) { 64 | if (!onTopBorder) { 65 | results.add(cells[x-1][y-1]); 66 | } 67 | if (!onBottomBorder) { 68 | results.add(cells[x-1][y+1]); 69 | } 70 | results.add(cells[x-1][y]); 71 | } 72 | if (!onRightBorder) { 73 | if (!onTopBorder) { 74 | results.add(cells[x+1][y-1]); 75 | } 76 | if (!onBottomBorder) { 77 | results.add(cells[x+1][y+1]); 78 | } 79 | results.add(cells[x+1][y]); 80 | } 81 | if (!onTopBorder) { 82 | results.add(cells[x][y-1]); 83 | } 84 | if (!onBottomBorder) { 85 | results.add(cells[x][y+1]); 86 | } 87 | return results; 88 | } 89 | 90 | ArrayList getCellAndNeighbors(int x, int y) { 91 | ArrayList results = new ArrayList(); 92 | boolean onLeftBorder = x == 0; 93 | boolean onRightBorder = x == cells[0].length - 1; 94 | boolean onTopBorder = y == 0; 95 | boolean onBottomBorder = y == cells.length - 1; 96 | if (!onLeftBorder) { 97 | if (!onTopBorder) { 98 | results.add(cells[x-1][y-1]); 99 | } 100 | if (!onBottomBorder) { 101 | results.add(cells[x-1][y+1]); 102 | } 103 | results.add(cells[x-1][y]); 104 | } 105 | if (!onRightBorder) { 106 | if (!onTopBorder) { 107 | results.add(cells[x+1][y-1]); 108 | } 109 | if (!onBottomBorder) { 110 | results.add(cells[x+1][y+1]); 111 | } 112 | results.add(cells[x+1][y]); 113 | } 114 | if (!onTopBorder) { 115 | results.add(cells[x+1][y-1]); 116 | } 117 | if (!onBottomBorder) { 118 | results.add(cells[x+1][y+1]); 119 | } 120 | return results; 121 | } 122 | 123 | ArrayList findCloseOccupants(PVector pos) { 124 | Cell c = this.getCell(pos.x, pos.y); 125 | ArrayList close = c.getOccupantsAndOccupantsOfNeighbors(); 126 | return close; 127 | } 128 | 129 | void show() { 130 | for (Cell [] array : cells) { 131 | for (Cell c : array) { 132 | c.show(); 133 | } 134 | } 135 | } 136 | 137 | void showVectors() { 138 | for (Cell [] array : cells) { 139 | for (Cell c : array) { 140 | c.showVectors(); 141 | } 142 | } 143 | } 144 | 145 | } 146 | 147 | class Cell { 148 | 149 | PVector pos; 150 | int id; 151 | float w, h; 152 | color fillColor; 153 | ArrayList neighbors; 154 | HashSet occupants; 155 | boolean active; 156 | 157 | Cell(PVector pos, float w, float h) { 158 | this.pos = pos; 159 | this.w = w; 160 | this.h = h; 161 | this.occupants = new HashSet(); 162 | this.neighbors = new ArrayList(); 163 | } 164 | 165 | void add(T t) { 166 | occupants.add(t); 167 | } 168 | 169 | void remove(T t) { 170 | occupants.remove(t); 171 | } 172 | 173 | void show() { 174 | noFill(); 175 | stroke(255); 176 | if (active) { 177 | stroke(255, 0, 0); 178 | } 179 | strokeWeight(1); 180 | rect(pos.x, pos.y, w, h); 181 | } 182 | 183 | ArrayList getOccupantsAndOccupantsOfNeighbors() { 184 | ArrayList results = new ArrayList(); 185 | for (Cell c : neighbors) { 186 | results.addAll(c.occupants); 187 | } 188 | results.addAll(occupants); 189 | return results; 190 | } 191 | 192 | ArrayList getOccupantsOfNeighbors() { 193 | ArrayList results = new ArrayList(); 194 | for (Cell c : neighbors) { 195 | results.addAll(c.occupants); 196 | } 197 | return results; 198 | } 199 | 200 | void showVectors() { 201 | strokeWeight(4); 202 | for (T o : occupants) { 203 | PVector p = (PVector) o; 204 | point(p.x, p.y); 205 | } 206 | } 207 | 208 | boolean contains(float x, float y) { 209 | return x >= pos.x && y >= pos.y && x <= pos.x + w && y <= pos.y + h; 210 | } 211 | 212 | } 213 | -------------------------------------------------------------------------------- /PolygonPacking/README.md: -------------------------------------------------------------------------------- 1 | A sketch for packing random polygons, with the twist that they are rounded and the rounding is taken into account in the packing, so there is a bit of extra space to use where the "points" of ordinary regular polygons would have been. I use a grid to speed up the bounds-checking process when placing new polygons. 2 | 3 | Example output: 4 | 5 | ![polyssmall](https://user-images.githubusercontent.com/101308215/161362522-0e099f15-68e5-4992-ac2c-1c9c5faf54f4.png) 6 | -------------------------------------------------------------------------------- /Pulses/Pulses.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | color bgColor = color(0, 0, 30); 3 | color strokeColor = color(40, 55, 255); 4 | int margin = 25; 5 | 6 | void setup() { 7 | size(900, 900, P3D); 8 | pg = createGraphics(1080, 1080, P3D); 9 | pg.smooth(8); 10 | pg.beginDraw(); 11 | pg.blendMode(ADD); 12 | pg.strokeWeight(4); 13 | pg.ellipseMode(RADIUS); 14 | pg.endDraw(); 15 | } 16 | 17 | void draw() { 18 | pg.beginDraw(); 19 | pg.noStroke(); 20 | pg.background(bgColor); 21 | float maxR = 100; 22 | int dir = 1; 23 | for (float y = maxR - 10; y < pg.height - maxR / 2; y += maxR) { 24 | float g = 20 + 200 * pow(abs(y - pg.height / 2) / (pg.height / 2), 3); 25 | float b = 255 * pow(abs(y - pg.height / 2) / (pg.height / 2), 2); 26 | float rd = 200 * pow(1 - abs(y - pg.height / 2) / (pg.height / 2), 2); 27 | pg.fill(rd, g, b, 15); 28 | for (int i = margin; i < pg.width - margin; i += 2) { 29 | float px = i; 30 | float xFactor = 1 - pow(abs(px - pg.width / 2) / (pg.width / 2), 1.0 / 3); 31 | float r = xFactor * maxR * 0.5 * (1 + sin(radians(i) + radians(dir * frameCount * 3))); 32 | pg.circle(px, y, r); 33 | } 34 | dir *= -1; 35 | } 36 | pg.endDraw(); 37 | 38 | image(pg, 0, 0, width, height); 39 | println(frameRate); 40 | } 41 | -------------------------------------------------------------------------------- /PushedAside/PushedAside.pde: -------------------------------------------------------------------------------- 1 | ArrayList> lines = new ArrayList>(); 2 | ArrayList points = new ArrayList(); 3 | ArrayList movers = new ArrayList(); 4 | int divs = 60; 5 | int moverCount = 30; 6 | int margin = 80; 7 | color c1, c2; 8 | PGraphics pg; 9 | 10 | void setup() { 11 | size(900, 900, P3D); 12 | c1 = color(255, 225, 200); 13 | c2 = color(175, 25, 100); 14 | pg = createGraphics(1080, 1080, P3D); 15 | pg.smooth(8); 16 | pg.beginDraw(); 17 | pg.ellipseMode(RADIUS); 18 | pg.endDraw(); 19 | int inc = round(1.0 * pg.width / divs); 20 | for (int i = 1; i < divs; i++) { 21 | ArrayList line = new ArrayList(); 22 | for (int j = 0; j <= pg.height; j += 10) { 23 | Point p = new Point(new PVector(i * inc, j)); 24 | line.add(p); 25 | points.add(p); 26 | } 27 | lines.add(line); 28 | } 29 | for (int i = 0; i < moverCount; i++) { 30 | movers.add(new Mover(new PVector(random(pg.width), random(-pg.height, 0)))); 31 | } 32 | } 33 | 34 | float offset = 0; 35 | 36 | void draw() { 37 | pg.beginDraw(); 38 | pg.background(0, 0, 0); //255, 225, 200); 39 | pg.noFill(); 40 | for (Mover m : movers) { 41 | m.move(); 42 | m.show(); 43 | } 44 | offset += 0.01; 45 | pg.stroke(200, 200, 255); 46 | pg.strokeWeight(5); 47 | for (Point p : points) { 48 | for (Mover m : movers) { 49 | PVector diff = p.pos.copy().sub(m.pos); 50 | PVector n = diff.copy().normalize().mult(75.0 * m.repelForce * 1 / diff.mag()); 51 | n.y = 0; 52 | p.pos.add(n); 53 | } 54 | p.update(); 55 | pg.strokeWeight(p.weight); 56 | pg.point(p.pos.x, p.pos.y); 57 | } 58 | 59 | pg.endDraw(); 60 | if (frameCount % 60 == 0) { 61 | println(frameCount / 60 + " --- " + frameRate); 62 | } 63 | image(pg, 0, 0, width, height); 64 | } 65 | 66 | class Point { 67 | 68 | PVector pos; 69 | PVector init; 70 | float weight; 71 | color cl; 72 | 73 | Point(PVector pos) { 74 | this.pos = pos; 75 | this.init = pos.copy(); 76 | this.weight = 3 77 | + 7 * 0.5 * (1 + cos(2 * 2 * PI * map(pos.x, 0, pg.width, 0, 1))); 78 | //+ 2 * sin(2 * PI * 7 * map(pos.y, 0, pg.height, 0, 1)); 79 | this.cl = lerpColor(c1, c2, pos.y / pg.height); 80 | } 81 | 82 | void update() { 83 | pos = PVector.lerp(pos, init, 0.03); 84 | 85 | } 86 | 87 | } 88 | 89 | class Mover { 90 | 91 | PVector pos; 92 | PVector vel; 93 | float r; 94 | float repelForce; 95 | float offset = random(2 * PI); 96 | 97 | Mover(PVector pos) { 98 | this.pos = pos; 99 | this.vel = new PVector(random(0.5, 1) * (random(2) < 1 ? -1 : 1), random(2.5, 4)); 100 | this.r = 5; 101 | this.repelForce = random(1, 4); 102 | } 103 | 104 | void move() { 105 | pos.add(vel); 106 | checkBounds(); 107 | } 108 | 109 | void checkBounds() { 110 | boolean out = pos.x + r < -margin 111 | || pos.x - r > pg.width + margin 112 | || pos.y - r > pg.height + margin; 113 | if (out) { 114 | this.pos = new PVector(random(pg.width), random(-pg.height, -pg.height / 2)); 115 | this.vel = new PVector(random(0.5, 1) * (random(2) < 1 ? -1 : 1), random(1.5, 2.5)); 116 | this.r = 5; 117 | this.repelForce = random(1, 4); 118 | } 119 | } 120 | 121 | void show() { 122 | pg.noStroke(); 123 | pg.fill(100, 150, 255); 124 | pg.circle(pos.x, pos.y, r * repelForce); 125 | float glowRadius = 10; 126 | for (int i = 1; i < glowRadius; i++) { 127 | pg.fill(100, 150, 255, 50 * (1 - 1.0 * i / glowRadius)); 128 | pg.circle(pos.x, pos.y, r * repelForce + i * 2); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Processing 2 | This is a space for Processing sketches whose code I think worth sharing. I'll add updates to this readme as I add new code. 3 | 4 | Some examples of outputs: 5 | 6 | From "FilamentSweep": 7 | 8 | ![FilamentSweep3659](https://user-images.githubusercontent.com/101308215/165743797-1e8c8aac-af56-4d31-a79a-fccd9ee5630a.png) 9 | 10 | From "IllusionOfForm": 11 | 12 | ![TheIllusionOfForm1649540760362](https://user-images.githubusercontent.com/101308215/162593092-c7208d1f-5dc0-4a33-9f98-df6da016a22e.png) 13 | 14 | From "ConcentricParticles": 15 | 16 | ![output44small](https://user-images.githubusercontent.com/101308215/161362280-ac99cf46-4309-460d-a53d-da3dc5cebdcf.png) 17 | -------------------------------------------------------------------------------- /RadialWaves/RadialWaves.pde: -------------------------------------------------------------------------------- 1 | int curveMode = 0; 2 | int squareMode = 1; 3 | int mode = squareMode; 4 | PGraphics pg; 5 | 6 | void setup() { 7 | size(900, 900, P3D); 8 | pg = createGraphics(1080, 1080, P3D); 9 | pg.smooth(8); 10 | pg.beginDraw(); 11 | pg.ellipseMode(RADIUS); 12 | pg.endDraw(); 13 | } 14 | 15 | void draw() { 16 | pg.beginDraw(); 17 | pg.background(255, 225, 200); 18 | pg.noFill(); 19 | int n = mode == curveMode ? 60 : 20; 20 | float r = 500; 21 | float inc = 2 * PI / n; 22 | float radiusInc = 1; 23 | PVector mappedMouse = new PVector(map(mouseX, 0, width, 0, pg.width), map(mouseY, 0, height, 0, pg.height)); 24 | PVector c = new PVector(pg.width / 2, pg.height / 2); 25 | float maxAmp = mode == curveMode ? 125.0 : 50.0; 26 | float speed = mode == curveMode ? 1.3 : 4; 27 | float freq = mode == curveMode ? 1 : 10; 28 | float offset = radians(frameCount * speed); 29 | 30 | float [] sineValues = new float [int(r / radiusInc + 1)]; 31 | float [] squareValues = new float [int(r / radiusInc + 1)]; 32 | for (int j = 0; j <= r / radiusInc; j++) { 33 | sineValues[j] = sin(radians(radiusInc * j * freq) + offset) * maxAmp * mappedMouse.x / pg.width; 34 | } 35 | for (int j = 0; j <= r / radiusInc; j++) { 36 | float s = sin(radians(radiusInc * j * freq) + offset * 2) > 0 ? 1 : -1; 37 | squareValues[j] = s * maxAmp * mappedMouse.x / pg.width; 38 | } 39 | 40 | float maxWeight = 10 + 20.0 * mappedMouse.y / pg.height; 41 | float minWeight = 2.0; 42 | for (int i = 0; i < n; i++) { 43 | float angle = i * inc; 44 | PVector p = PVector.fromAngle(angle); 45 | PVector norm = new PVector(-p.y, p.x); 46 | pg.beginShape(); 47 | for (int j = 0; j <= r / radiusInc; j++) { 48 | float weightFactor = pow(1 - abs(j * radiusInc - r / 2) / (r / 2), 1 + 10.0 * mappedMouse.y / pg.height); 49 | pg.strokeWeight(minWeight + maxWeight * weightFactor); 50 | float val = mode == curveMode ? sineValues[j] : squareValues[j]; 51 | PVector plot = p.copy().mult(j * radiusInc).add(norm.copy().mult(val * (j * radiusInc) / r)).add(c); 52 | pg.vertex(plot.x, plot.y); 53 | } 54 | pg.endShape(); 55 | } 56 | pg.endDraw(); 57 | image(pg, 0, 0, width, height); 58 | println(frameCount / 60); 59 | } 60 | 61 | void keyPressed() { 62 | if (key == CODED) { 63 | if (keyCode == UP) { 64 | mode = 1 - mode; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /ShaderDemos/ShaderDemoGradient/ShaderDemoGradient.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | PShader glowShader; 3 | 4 | void setup() { 5 | size(900, 900, P2D); 6 | pg = createGraphics(1080, 1080, P2D); 7 | pg.smooth(8); 8 | pg.beginDraw(); 9 | pg.ellipseMode(RADIUS); 10 | glowShader = new PShader(this, "GradientShader.vert", "GradientShader.frag"); 11 | pg.blendMode(ADD); 12 | pg.colorMode(RGB, 255, 255, 255, 1.0); 13 | pg.endDraw(); 14 | colorMode(RGB, 255, 255, 255, 1.0); 15 | } 16 | 17 | void draw() { 18 | pg.beginDraw(); 19 | pg.background(0); 20 | int n = 10; 21 | float inc = pg.width / n; 22 | float rBase = inc / 2; 23 | float glowPortion = 0.05; // + 0.7 * mouseX / width; 24 | for (int yi = 0; yi < n; yi++) { 25 | for (int xi = 0; xi < n; xi++) { 26 | float t1 = 0.5 * (1 + sin(radians(frameCount + xi * 17))); 27 | float t2 = 0.5 * (1 + sin(radians(frameCount * 0.7 + yi * 13))); 28 | float yDev = yi % 2 == 0 ? sin(PI + radians(frameCount * 0.5)) : 0; 29 | PVector originDev = new PVector(xi * inc + inc / 2, yDev * inc + yi * inc + inc / 2); 30 | PVector origin = new PVector(xi * inc + inc / 2, yi * inc + inc / 2); 31 | pg.shader(glowShader); 32 | float r = rBase / 4 + 2 * rBase / 3 * pow(t1, 5); 33 | glowShader.set("radius", r * (1 - glowPortion)); 34 | glowShader.set("glowRadius", r * glowPortion); 35 | glowShader.set("glowFalloff", 0.5); 36 | glowShader.set("center", origin.x, origin.y); 37 | glowShader.set("color", new PVector(1.0 * xi / n * t1, 0.0, 0.0)); 38 | glowShader.set("color2", new PVector(0.0, 1.0 * yi / n * t2, 1.0)); 39 | pg.circle(origin.x, origin.y, r); 40 | pg.shader(glowShader); 41 | glowShader.set("center", origin.x, originDev.y); 42 | pg.circle(origin.x, originDev.y, r); 43 | } 44 | } 45 | pg.endDraw(); 46 | image(pg, 0, 0, width, height); 47 | println(frameCount / 60); 48 | } 49 | -------------------------------------------------------------------------------- /ShaderDemos/ShaderDemoGradient/data/GradientShader.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 center; 2 | uniform vec3 centerColor; 3 | uniform float radius; 4 | uniform float glowRadius; 5 | uniform float glowFalloff; 6 | uniform vec3 color; 7 | uniform vec3 color2; 8 | varying vec2 va_pos; 9 | void main() { 10 | 11 | float d = length(va_pos - center); 12 | vec3 colorBlend = mix(color, color2, ((center + radius + glowRadius).x - va_pos.x) / ((radius + glowRadius) * 2.)); 13 | float glow = pow(1. - (d - radius) / glowRadius, glowFalloff); 14 | vec3 col = d < radius 15 | ? vec3(1.) 16 | : d < radius + glowRadius ? vec3(glow) : vec3(0.); 17 | gl_FragColor = vec4(colorBlend, col.x); 18 | } -------------------------------------------------------------------------------- /ShaderDemos/ShaderDemoGradient/data/GradientShader.vert: -------------------------------------------------------------------------------- 1 | uniform mat4 transformMatrix; 2 | attribute vec4 position; 3 | attribute vec4 color; 4 | varying vec4 va_color; 5 | varying vec2 va_pos; 6 | void main() { 7 | gl_Position = transformMatrix * position; 8 | va_color = color; 9 | va_pos = position.xy; 10 | } -------------------------------------------------------------------------------- /ShadowCubes/ShadowCubes.pde: -------------------------------------------------------------------------------- 1 | int margin = 35; 2 | int perSide = 5; 3 | PGraphics pg; 4 | 5 | void setup() { 6 | size(900, 900, P2D); 7 | pg = createGraphics(1080, 1080, P2D); 8 | pg.smooth(8); 9 | } 10 | 11 | void draw() { 12 | pg.beginDraw(); 13 | pg.background(255, 225, 200); 14 | int sidePlusShadow = (pg.width - margin * 2) / perSide; 15 | int hSide = int(sidePlusShadow * 2.0 / 3); 16 | int vSide = int(sidePlusShadow * 2.0 / 3); 17 | float h = 0.1 + 0.9 * 0.5 * (1 + sin(PI + radians(frameCount * 0.7))); 18 | float v = 0.1 + 0.9 * 0.5 * (1 + sin(radians(frameCount))); 19 | int hShadow = int(hSide / 2 * h); 20 | int vShadow = int(vSide / 2 * v); 21 | pg.noStroke(); 22 | for (int x = margin; x < pg.width - margin; x += sidePlusShadow) { 23 | for (int y = margin; y < pg.height - margin; y += sidePlusShadow) { 24 | int px = x; 25 | int py = y; 26 | pg.fill(0); 27 | if (hShadow < 0) { 28 | hSide = -abs(hSide); 29 | px = x + abs(hSide); 30 | } 31 | if (vShadow < 0) { 32 | vSide = -abs(vSide); 33 | py = y + abs(vSide); 34 | } 35 | pg.push(); 36 | pg.translate(px, py); 37 | if (x == margin + sidePlusShadow * 2 && y == margin + sidePlusShadow * 2) { 38 | pg.rotate(pow((radians(frameCount) % (2 * PI)) / (2 * PI), 3) * 2 * PI); 39 | } 40 | pg.beginShape(); 41 | pg.vertex(0, vSide); 42 | pg.vertex(hSide, vSide); 43 | pg.vertex(hSide, 0); // 44 | pg.vertex(hSide + hShadow, vShadow); 45 | pg.vertex(hSide + hShadow, vSide + vShadow); 46 | pg.vertex(hShadow, vSide + vShadow); 47 | pg.endShape(CLOSE); 48 | pg.fill(255, 225, 200); 49 | pg.square(0, 0, hSide); 50 | pg.pop(); 51 | } 52 | } 53 | pg.endDraw(); 54 | image(pg, 0, 0, width, height); 55 | if (frameCount % 60 == 0) { 56 | println(frameCount / 60 + " --- " + frameRate); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ShiftyRadial/ShiftyRadial.pde: -------------------------------------------------------------------------------- 1 | //MIT License 2 | 3 | //Copyright (c) 2022 Brian Fearn 4 | 5 | //Permission is hereby granted, free of charge, to any person obtaining a copy 6 | //of this software and associated documentation files (the "Software"), to deal 7 | //in the Software without restriction, including without limitation the rights 8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | //copies of the Software, and to permit persons to whom the Software is 10 | //furnished to do so, subject to the following conditions: 11 | 12 | //The above copyright notice and this permission notice shall be included in all 13 | //copies or substantial portions of the Software. 14 | 15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | //SOFTWARE. 22 | 23 | PGraphics pg; 24 | 25 | void setup() { 26 | size(900, 900, P2D); 27 | pg = createGraphics(1080, 1080, P2D); 28 | pg.smooth(8); 29 | } 30 | 31 | void draw() { 32 | pg.beginDraw(); 33 | pg.background(0, 20, 30); 34 | pg.fill(255, 215, 160); 35 | pg.noStroke(); 36 | pg.translate(pg.width / 2, pg.height / 2); 37 | int n = 48; 38 | float divs = 1 + 10 * 0.5 * (1 + sin(PI / 2 + radians(frameCount * 0.1))); 39 | float rPadding = pg.width / 30; 40 | float maxR = pg.width / 2 - rPadding; 41 | for (int i = 0; i < n; i++) { 42 | float th = i * TAU / n; 43 | for (float d = 0; d < divs; d++) { 44 | float inc = maxR / divs; 45 | float offset = PI / divs * d; 46 | pg.beginShape(QUAD_STRIP); 47 | float rStart = rPadding + inc * d; 48 | float rEnd = d + 1 > divs ? rPadding + inc * divs : rPadding + inc * (d + 1); 49 | for (float r = rStart; r <= rEnd; r ++) { 50 | float w = map(r, rStart, rEnd, 0, 1); 51 | float fw = 1 - (2 * w - 1) * (2 * w - 1); 52 | float c = map(r, 0, maxR, 0, TAU); 53 | float a = offset + th + 0.5 * sin(offset + radians(frameCount * 0.5) + c); 54 | float m = 6.0; 55 | PVector p = PVector.fromAngle(a - fw * TAU / (n * m)).mult(r); 56 | PVector p2 = PVector.fromAngle(a + fw * TAU / (n * m)).mult(r); 57 | pg.vertex(p.x, p.y); 58 | pg.vertex(p2.x, p2.y); 59 | } 60 | pg.endShape(); 61 | } 62 | } 63 | pg.endDraw(); 64 | image(pg, 0, 0, width, height); 65 | println(frameCount / 60); 66 | } 67 | -------------------------------------------------------------------------------- /SigmoidMotion/SigmoidMotion.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | PShader bloomShader; 3 | 4 | void setup() { 5 | size(900, 900, P2D); 6 | pg = createGraphics(1080, 1080, P2D); 7 | pg.smooth(8); 8 | pg.beginDraw(); 9 | pg.ellipseMode(RADIUS); 10 | bloomShader = new PShader(this, "shader.vert", "shader.frag"); 11 | bloomShader.set("resolution", pg.width, pg.height); 12 | pg.blendMode(ADD); 13 | pg.colorMode(RGB, 255, 255, 255, 1.0); 14 | pg.endDraw(); 15 | colorMode(RGB, 255, 255, 255, 1.0); 16 | } 17 | 18 | void draw() { 19 | pg.beginDraw(); 20 | pg.background(0); 21 | pg.noStroke(); 22 | 23 | float r = 90; 24 | int n = int(pg.height / (r * 2)); 25 | int seconds = 5; 26 | int framesPerLoop = 60 * seconds; 27 | float xMin = r; 28 | float xMax = pg.width - r; 29 | 30 | float glowPortion = 0.5 + 0.5 * (0.5 * (1 + sin(radians(frameCount * 0.75)))); 31 | bloomShader.set("radius", r * (1 - glowPortion)); 32 | bloomShader.set("glowRadius", r * glowPortion); 33 | 34 | int reps = 1; 35 | for (int rep = 0; rep < reps; rep++) { 36 | int frameOffset = rep * framesPerLoop / (reps * 3); 37 | float calcX = 1.0 * ((frameCount + frameOffset) % framesPerLoop) / framesPerLoop; 38 | for (int i = 0; i < n; i++) { 39 | for (int c = 0; c < 3; c++) { 40 | PVector col = new PVector(0, 0, 0); // easy kludge: use PVector to store float RGB values to pass to shader 41 | switch (c % 3) { 42 | case 0: 43 | col = new PVector(1.0, 0, 0); 44 | break; 45 | case 1: 46 | col = new PVector(0, 1.0, 0); 47 | break; 48 | case 2: 49 | col = new PVector(0, 0, 1.0); 50 | break; 51 | } 52 | float yBase = r + 2 * i * r; 53 | float slope = 1 + i * 3.0 * mouseX / pg.width + c * 5.0 * mouseY / pg.height; 54 | 55 | // movement speed determined by sigmoid curve: starts slow, accelerates fast, then decelerates fast 56 | float sig0 = sigmoid(0, slope, 0.5); 57 | float sig1 = sigmoid(1, slope, 0.5); 58 | float sigX = sigmoid(calcX, slope, 0.5); 59 | 60 | // side to side movement 61 | bloomCircle(col, map(sigX, sig0, sig1, xMax, xMin), yBase, r); 62 | bloomCircle(col, map(sigX, sig0, sig1, xMin, xMax), yBase, r); 63 | bloomCircle(col, map(sigX, sig0, sig1, xMax, xMin), pg.height - yBase, r); 64 | bloomCircle(col, map(sigX, sig0, sig1, xMin, xMax), pg.height - yBase, r); 65 | 66 | // up and down movement 67 | bloomCircle(col, yBase, map(sigX, sig0, sig1, xMax, xMin), r); 68 | bloomCircle(col, pg.height - yBase, map(sigX, sig0, sig1, xMax, xMin), r); 69 | bloomCircle(col, yBase, map(sigX, sig0, sig1, xMin, xMax), r); 70 | bloomCircle(col, pg.height - yBase, map(sigX, sig0, sig1, xMin, xMax), r); 71 | } 72 | } 73 | } 74 | pg.endDraw(); 75 | image(pg, 0, 0, width, height); 76 | println(frameCount / 60 + " --- " + frameRate); 77 | } 78 | 79 | void bloomCircle(PVector col, float x, float y, float r) { 80 | pg.shader(bloomShader); 81 | bloomShader.set("color", col); 82 | bloomShader.set("center", x, y); 83 | pg.circle(x, y, r); 84 | } 85 | 86 | float E = exp(1.0); 87 | float sigmoid(float x, float k, float xMidpoint) { 88 | return 1 / (1.0 + pow(E, -k * (x - xMidpoint))); 89 | } 90 | -------------------------------------------------------------------------------- /SigmoidMotion/data/shader.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 center; 2 | uniform vec3 centerColor; 3 | uniform float radius; 4 | uniform float glowRadius; 5 | uniform bool linear; 6 | uniform vec3 color; 7 | varying vec2 va_pos; 8 | void main() { 9 | float d = length(va_pos - center); 10 | float glow = pow(1. - (d - radius) / glowRadius, 2.); 11 | vec3 col = d < radius 12 | ? vec3(1.) 13 | : d < radius + glowRadius ? vec3(glow) : vec3(0.); 14 | gl_FragColor = vec4(color, col.x); 15 | } 16 | -------------------------------------------------------------------------------- /SigmoidMotion/data/shader.vert: -------------------------------------------------------------------------------- 1 | uniform mat4 transformMatrix; 2 | attribute vec4 position; 3 | attribute vec4 color; 4 | varying vec4 va_color; 5 | varying vec2 va_pos; 6 | void main() { 7 | gl_Position = transformMatrix * position; 8 | va_color = color; 9 | va_pos = position.xy; 10 | } 11 | -------------------------------------------------------------------------------- /Skylines/Skylines.pde: -------------------------------------------------------------------------------- 1 | PGraphics bg; 2 | 3 | void setup() { 4 | size(900, 900, P2D); 5 | bg = createGraphics(width, height); 6 | bg.beginDraw(); 7 | colorMode(HSB, 360, 100, 100); 8 | bg.endDraw(); 9 | setupBackground(); 10 | colorMode(RGB, 255, 255, 255); 11 | smooth(8); 12 | } 13 | 14 | void setupBackground() { 15 | float maxD = dist(0, 0, width / 2, height); 16 | bg.beginDraw(); 17 | bg.loadPixels(); 18 | for (int y = 0; y < height; y++) { 19 | for (int x = 0; x < width; x++) { 20 | int px = x + y * width; 21 | float dFactor = dist(x, y, width / 2, height) / maxD; 22 | dFactor = pow(dFactor, 0.7); 23 | bg.pixels[px] = color(60 - 60.0 * dFactor, 90 - 20.0 * dFactor, 90 - 20.0 * dFactor); 24 | //bg.pixels[px] = color(60.0 * y / height, 90 - 20.0 * abs(y - height / 2) / (height / 2), 90 - 20.0 * y / height); 25 | } 26 | } 27 | bg.updatePixels(); 28 | bg.endDraw(); 29 | } 30 | 31 | float [] timeOffsets = new float[10]; 32 | 33 | void draw() { 34 | background(0); 35 | image(bg, 0, 0); 36 | noStroke(); 37 | int n = 10; 38 | float yInc = 1.0 * height / n; 39 | int xn = 900; 40 | float moveY = height * 0.5 * (1 + sin(radians(frameCount * 0.2))); 41 | 42 | for (int i = 1; i <= n; i++) { 43 | float y = yInc * i; 44 | float t = timeOffsets[i - 1]; 45 | float lerpRatio = 0.5 * (1 + sin(radians(frameCount * 0.4))); 46 | timeOffsets[i - 1] = timeOffsets[i - 1] + 0.05 + 0.25 * pow(abs(y - moveY) / height, 2); 47 | fill(0); 48 | beginShape(); 49 | vertex(0, y); 50 | for (int xi = 0; xi <= xn; xi++) { 51 | float cx = map(xi, 0, xn, 0, 2 * PI); 52 | float px = map(xi, 0, xn, 0, width); 53 | float blockValue = pow(0.5 * (1 + sin(i * 10000 + floor(cx * n + t * 2.5) * 4)), 2); 54 | float curveValue = 0.5 * (1 + sin(cx * 5 + t)); 55 | float cy = 0.1 * yInc + 0.85 * yInc * lerp(blockValue, curveValue, lerpRatio); 56 | float py = y - cy; 57 | vertex(px, py); 58 | } 59 | vertex(width, y); 60 | endShape(CLOSE); 61 | } 62 | println(frameRate); 63 | } 64 | -------------------------------------------------------------------------------- /Snakey/Snakey.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | int pixPerInc = 3; 3 | color cl, cl2; 4 | 5 | void setup() { 6 | size(900, 900, P2D); 7 | pg = createGraphics(1080, 1080, P2D); 8 | pg.smooth(8); 9 | pg.beginDraw(); 10 | pg.strokeCap(PROJECT); 11 | cl = color(255, 150, 255); 12 | cl2 = color(100, 50, 255); 13 | pg.stroke(150, 100, 255); 14 | pg.endDraw(); 15 | } 16 | 17 | void draw() { 18 | PVector c = new PVector(pg.width / 2, pg.height / 2); 19 | float timeFactor = 0.05 + 0.95 * 0.5 * (1 + sin(radians(frameCount * 0.5))); 20 | 21 | pg.beginDraw(); 22 | pg.background(0, 0, 50); 23 | pg.strokeWeight(4); 24 | pg.noFill(); 25 | int r = pg.width / 2 - 50; 26 | int count = 0; 27 | while (r >= 60) { 28 | float rOffset = count * PI / 3; 29 | float circ = 2 * PI * r; 30 | int n = int(circ / pixPerInc); 31 | float frac = 1 + n * 1.0 * timeFactor; 32 | float inc = 2 * PI / n; 33 | float offset = radians(frameCount * 0.7); 34 | pg.beginShape(); 35 | for (int i = 1; i < frac; i++) { 36 | float t = rOffset + offset + inc * i; 37 | float t2 = offset + inc * i; 38 | float maxWeight = 25.0 * r / 400 * frac / n; 39 | float thisR = r + 15.0 * sin(t2 * int(1.0 * pow(1.0 * r / 400, 1 / 2.0) * 10)); 40 | float weightFactor = (1 - pow(abs(i - 1.0 * frac / 2) / (frac / 2), 2.0)); 41 | pg.stroke(lerpColor(cl, cl2, 1.0 * i / frac)); 42 | pg.strokeWeight(1 + maxWeight * weightFactor); 43 | PVector p = PVector.fromAngle(t).mult(thisR).add(c); 44 | pg.vertex(p.x, p.y); 45 | } 46 | pg.endShape(); 47 | r -= 60; 48 | count++; 49 | } 50 | pg.endDraw(); 51 | image(pg, 0, 0, width, height); 52 | if (frameCount % 60 == 0) { 53 | println(frameCount / 60 + " --- " + frameRate); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /SoftlySpiraling/SoftlySpiraling.pde: -------------------------------------------------------------------------------- 1 | import java.util.Date; 2 | 3 | PGraphics pg; 4 | 5 | color bgColor = color(0, 10, 30); 6 | color strokeColor = color(255, 225, 200); 7 | 8 | void setup() { 9 | size(900, 900, P2D); 10 | colorMode(HSB, 360, 100, 100, 100); 11 | pg = createGraphics(1080, 1080, P2D); 12 | pg.smooth(8); 13 | } 14 | 15 | boolean drawBg = true; 16 | boolean save = false; 17 | 18 | void mouseClicked() { 19 | save = true; 20 | } 21 | 22 | void draw() { 23 | pg.beginDraw(); 24 | if (drawBg) { 25 | drawBg = false; 26 | pg.colorMode(HSB, 360, 100, 100, 100); 27 | pg.background(220, 90, 10); 28 | } 29 | int perFrame = 15000; 30 | PVector center = new PVector(pg.width / 2, pg.height / 2); 31 | float maxDist = dist(center.x, center.y, center.x, 0); 32 | float sinMag = pg.width / 10; 33 | float sinFreq = 12; 34 | float rotationMag = 2 * TAU; 35 | for (int i = 0; i < perFrame; i++) { 36 | PVector p = new PVector(random(pg.width), random(pg.height)); 37 | float fd = pow(center.copy().sub(p).mag() / maxDist, 0.3); 38 | float th = rotationMag * pow(1 - fd, 1); 39 | PVector p2 = p.copy().sub(center).rotate(th).add(center); 40 | float fy = pg.width / 2 + sinMag * sin(map(p2.y, 0, pg.height, 0, TAU) * sinFreq * (fd)); 41 | float f = abs(p2.x - fy) / (pg.width / 2 + pg.width / 10); 42 | color c = lerpColor(color(220, 90, 10), color(220, 30 * fd, 90), f); 43 | pg.stroke(c); 44 | pg.strokeWeight(random(2)); 45 | pg.point(p.x, p.y); 46 | } 47 | if (save) { 48 | save = false; 49 | pg.save(getClass().getName() + new Date().getTime() + ".png"); 50 | } 51 | pg.endDraw(); 52 | image(pg, 0, 0, width, height); 53 | println(frameRate); 54 | } 55 | -------------------------------------------------------------------------------- /Spinners/Spinners.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | void setup() { 4 | size(900, 900, P3D); 5 | pg = createGraphics(1080, 1080, P3D); 6 | pg.smooth(8); 7 | } 8 | 9 | void draw() { 10 | pg.beginDraw(); 11 | pg.background(255); 12 | pg.noStroke(); 13 | pg.fill(0); 14 | pg.noFill(); 15 | pg.stroke(0); 16 | pg.strokeWeight(3); 17 | int n = 10; 18 | float inc = pg.width / n; 19 | float time = radians(frameCount); 20 | float ft = pow(0.5 * (1 + sin(time * 0.5)), 1.5); 21 | for (int yi = 0; yi < n; yi++) { 22 | for (int xi = 0; xi < n; xi++) { 23 | int m = int(3 + 8 * noise(xi * 1234, yi * 3567)); 24 | float f = 0.75 * pow(0.5 * (1 + sin(time + TAU * xi / n)), 3); 25 | pg.push(); 26 | pg.translate(xi * inc + inc / 2, yi * inc + inc / 2); 27 | pg.beginShape(); 28 | for (int i = 0; i < 200; i++) { 29 | float th = TAU * i / 200; 30 | float r = f * inc * 0.45 + (1 - f ) * inc * 0.45 * pow(0.5 * (1 + sin(th * m)), 1 + 9 * ft); 31 | PVector p = PVector.fromAngle(TAU * i / 200 + time).mult(r); 32 | pg.vertex(p.x, p.y); 33 | } 34 | pg.endShape(CLOSE); 35 | pg.pop(); 36 | } 37 | } 38 | pg.endDraw(); 39 | image(pg, 0, 0, width, height); 40 | println(frameCount / 60); 41 | } 42 | -------------------------------------------------------------------------------- /SpinningSquares/SpinningSquares.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | void setup() { 4 | size(900, 900, P3D); 5 | pg = createGraphics(1080, 1080, P3D); 6 | pg.smooth(8); 7 | pg.beginDraw(); 8 | pg.strokeWeight(2); 9 | pg.rectMode(RADIUS); 10 | pg.ellipseMode(RADIUS); 11 | pg.endDraw(); 12 | } 13 | 14 | int arms = 0; 15 | 16 | void draw() { 17 | pg.beginDraw(); 18 | pg.background(0); 19 | pg.stroke(255); 20 | pg.strokeWeight(1); 21 | pg.fill(0); 22 | int n = 33; 23 | float inc = 1.0 * pg.width / n; 24 | int frames = 4 * 60; 25 | float t = (frameCount % frames) / float(frames); // 0.3 + 0.7 * 0.5 * (1 + sin(radians(frameCount * 1))); 26 | float t2 = (frameCount % (frames * 2)) / float(frames * 2); 27 | float maxD = dist(pg.width / 2, pg.height / 2, 0, 0); 28 | for (int yi = 0; yi < n; yi++) { 29 | for (int xi = 0; xi < n; xi++) { 30 | float y = yi * inc + inc / 2; 31 | float x = xi * inc + inc / 2; 32 | PVector diff = new PVector(x, y).sub(new PVector(pg.width / 2, pg.height / 2)); 33 | pg.push(); 34 | pg.translate(x, y); 35 | float fd = 2 + 10 * pow(0.5 * (1 + sin(dist(pg.width / 2, pg.height / 2, x, y) / maxD * TAU * 2 + diff.heading() * arms)), 2); 36 | float fdd = TAU * 0.5 * (1 + sin(TAU * (t + fd))); 37 | pg.rotateY(x / width * PI + TAU * t2); 38 | //pg.rotateY(pow(sin(PI / 2 * t), fd) * TAU + PI); 39 | pg.rotateX(pow(sin(PI / 2 * t), fd) * TAU + PI); 40 | pg.translate(0, 0, 0.25); 41 | pg.fill(255); 42 | pg.square(0, 0, inc / 2 * 0.65); 43 | pg.translate(0, 0, -0.5); 44 | pg.fill(0); 45 | pg.square(0, 0, inc / 2 * 0.65); 46 | pg.pop(); 47 | } 48 | } 49 | if (frameCount % frames == 0) { 50 | arms = (arms + 3) % 6; 51 | } 52 | pg.endDraw(); 53 | image(pg, 0, 0, width, height); 54 | if (frameCount == 240 * 4 + 1) { 55 | //noLoop(); 56 | } 57 | println(frameCount / 60); 58 | } 59 | -------------------------------------------------------------------------------- /Squircle/Squircle.pde: -------------------------------------------------------------------------------- 1 | //MIT License 2 | 3 | //Copyright (c) 2022 Brian Fearn 4 | 5 | //Permission is hereby granted, free of charge, to any person obtaining a copy 6 | //of this software and associated documentation files (the "Software"), to deal 7 | //in the Software without restriction, including without limitation the rights 8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | //copies of the Software, and to permit persons to whom the Software is 10 | //furnished to do so, subject to the following conditions: 11 | 12 | //The above copyright notice and this permission notice shall be included in all 13 | //copies or substantial portions of the Software. 14 | 15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | //SOFTWARE. 22 | 23 | //Inspired by Inigo Quilez: https://www.shadertoy.com/view/7stcR4 24 | 25 | void setup() { 26 | size(900, 900, P3D); 27 | strokeWeight(3); 28 | smooth(8); 29 | } 30 | 31 | void draw() { 32 | background(0, 50, 75); 33 | stroke(255, 225, 200); 34 | fill(245, 150, 75); 35 | int n = 10; 36 | float r = width / (n * 2); 37 | for (int yi = 0; yi < n; yi++) { 38 | for (int xi = 0; xi < n; xi++) { 39 | float findex = 1 - pow(1.0 * xi / n, 1); 40 | float t = 2 * abs(0.5 - fract(1 - pow(1.0 * yi / n, 1) + frameCount * 0.003)); // vary y-based index for size with time 41 | float findex2 = 6 * pow(t, 5) - 15 * pow(t, 4) + 10 * pow(t, 3); // smoothstep: see https://en.wikipedia.org/wiki/Smoothstep#Generalization_to_higher-order_equations 42 | float y = yi * r * 2 + r; 43 | float x = xi * r * 2 + r; 44 | PVector o = new PVector(x, y); 45 | float offset = findex * PI * 2; 46 | squircle(o, r * (0.1 + 0.85 * findex2), offset, 0); 47 | } 48 | } 49 | println(frameRate); 50 | } 51 | 52 | float fract(float x) { 53 | return x - floor(x); 54 | } 55 | 56 | void squircle(PVector o, float r2, float offset, float rot) { 57 | push(); 58 | translate(o.x, o.y); 59 | rotate(rot); 60 | translate(-r2, -r2); 61 | float t = 0.5 * (1 + sin(radians(frameCount * 1.3) + offset)); 62 | ArrayList points = new ArrayList(); 63 | for (float th = 0; th < PI / 2; th += (PI / 50)) { 64 | float cx = pow(abs(cos(th)), 0.5 + 5 * t); // exponent controls shape 65 | float cy = pow(abs(sin(th)), 0.5 + 5 * t); 66 | float px = map(cx, 0, 1, 0, r2); 67 | float py = map(cy, 0, 1, 0, r2); 68 | points.add(new PVector(px, py)); 69 | } 70 | beginShape(); 71 | for (PVector p : points) { 72 | vertex(p.x, p.y); 73 | } 74 | for (int i = 0; i < points.size(); i++) { 75 | PVector p = points.get(points.size() - 1 - i); 76 | vertex(p.x, 2 * r2 - p.y); 77 | } 78 | for (int i = 0; i < points.size(); i++) { 79 | PVector p = points.get(i); 80 | vertex(2 * r2 - p.x, 2 * r2 - p.y); 81 | } 82 | for (int i = 0; i < points.size(); i++) { 83 | PVector p = points.get(points.size() - 1 - i); 84 | vertex(2 * r2 - p.x, p.y); 85 | } 86 | endShape(); 87 | pop(); 88 | } 89 | -------------------------------------------------------------------------------- /StressDeformation/StressDeformation.pde: -------------------------------------------------------------------------------- 1 | ArrayList points = new ArrayList(); 2 | int dpn = 0; 3 | int n = 80; 4 | float velMultiplier = 1.005; 5 | int margin = 0; 6 | float inc; 7 | ArrayList> grid = new ArrayList>(); 8 | float moverBaseSpeed = 10; 9 | ArrayList movers = new ArrayList(); 10 | int nMovers = 3; 11 | float distortionMagFudge = 0.6; 12 | float distortionMagDivider = 200.0; 13 | float distanceFactorMultiplier = 0.3; 14 | boolean constantReturnRate = true; 15 | float minReturnRate = 0.024; 16 | float maxReturnRate = 0.045; 17 | float moverLimitAdd = 15; 18 | int blendMode = ADD; // SUBTRACT 19 | boolean enlargeOnDeform = true; 20 | boolean circleDraw = true; 21 | PGraphics pg; 22 | 23 | void setup() { 24 | size(900, 900, P2D); 25 | pg = createGraphics(1080, 1080, P2D); 26 | colorMode(HSB, 360, 100, 100, 100); 27 | 28 | pg.smooth(8); 29 | pg.beginDraw(); 30 | pg.colorMode(HSB, 360, 100, 100, 100); 31 | pg.blendMode(blendMode); 32 | pg.endDraw(); 33 | inc = (pg.width - margin * 2.0) / n; 34 | for (int i = -10; i <= n + 10; i++) { 35 | ArrayList list = new ArrayList(); 36 | float y = margin + i * inc; 37 | for (int j = -10; j <= n + 10; j++) { 38 | float x = margin + j * inc; 39 | Point p = new Point(x, y); 40 | list.add(p); 41 | points.add(p); 42 | } 43 | grid.add(list); 44 | } 45 | 46 | for (int i = 0; i < nMovers; i++) { 47 | PVector mPos = PVector.random2D().mult(pg.width * 2).add(new PVector(pg.width / 2, pg.height / 2)); 48 | PVector mDest = new PVector(random(pg.width), random(pg.height)); 49 | PVector mVel = mDest.copy().sub(mPos).normalize().mult(moverBaseSpeed); 50 | Mover mover = new Mover(mPos, mVel); 51 | movers.add(mover); 52 | } 53 | } 54 | 55 | boolean onScreen(PVector p) { 56 | return p.x >= margin && p.x <= pg.width - margin && p.y >= margin && p.y <= pg.height - margin; 57 | } 58 | 59 | void mouseClicked() { 60 | if (mouseButton == LEFT) { 61 | constantReturnRate = !constantReturnRate; 62 | } 63 | if (mouseButton == RIGHT) { 64 | enlargeOnDeform = !enlargeOnDeform; 65 | } 66 | } 67 | 68 | void keyPressed() { 69 | if (key == CODED) { 70 | if (keyCode == UP) { 71 | circleDraw = true; 72 | } 73 | if (keyCode == DOWN) { 74 | circleDraw = false; 75 | } 76 | if (keyCode == LEFT) { 77 | blendMode = SUBTRACT; 78 | pg.blendMode(blendMode); 79 | } 80 | if (keyCode == RIGHT) { 81 | blendMode = ADD; 82 | pg.blendMode(blendMode); 83 | } 84 | } 85 | } 86 | 87 | void draw() { 88 | for (Mover mover : movers) { 89 | mover.update(); 90 | } 91 | deform(points); 92 | 93 | pg.beginDraw(); 94 | color bgColor = blendMode == ADD ? color(225, 90, 20) : color(0, 0, 100); 95 | pg.background(bgColor); 96 | pg.strokeWeight(1.5); 97 | if (circleDraw) { 98 | pg.noStroke(); 99 | } 100 | 101 | for (Point p : points) { 102 | p.update(); 103 | } 104 | 105 | for (int j = 0; j < grid.size() - 1; j++) { 106 | ArrayList row = grid.get(j); 107 | for (int i = 0; i < row.size() - 1; i++) { 108 | Point pt = row.get(i); 109 | Point pt2 = row.get(i + 1); 110 | PVector p = row.get(i).pos; 111 | PVector p2 = row.get(i + 1).pos; 112 | PVector p3 = grid.get(j + 1).get(i).pos; 113 | float bright = (pt.distortionMag + pt2.distortionMag) / 2; 114 | color fillColor = color(pt.hue, 90 - 50 * bright, 40 + 60 * bright, bright * 100); 115 | if (onScreen(p) || onScreen(p2) || onScreen(p3)) { 116 | if (circleDraw) { 117 | pg.fill(fillColor); 118 | float baseR = enlargeOnDeform ? 10 : 15; 119 | float rMult = enlargeOnDeform ? bright : 1 - bright; 120 | float r = blendMode == ADD ? 1 + rMult * baseR : 1 + rMult * baseR; 121 | pg.circle(p.x, p.y, r); 122 | } else { 123 | pg.stroke(fillColor); 124 | pg.line(p.x, p.y, p2.x, p2.y); 125 | pg.stroke(fillColor); 126 | pg.line(p.x, p.y, p3.x, p3.y); 127 | } 128 | } 129 | } 130 | } 131 | pg.endDraw(); 132 | image(pg, 0, 0, width, height); 133 | //println(frameRate); 134 | if (frameCount % 60 == 0) { 135 | println(frameCount / 60); 136 | } 137 | } 138 | 139 | void deform(ArrayList set) { 140 | for (Mover mover : movers) { 141 | Point center = new Point(mover.pos.x, mover.pos.y); 142 | float maxDiagonal = getMaxDist(center, set); 143 | for (Point pt : set) { 144 | PVector p = pt.pos; 145 | PVector c = center.pos; 146 | float d = dist(p.x, p.y, c.x, c.y); 147 | float dFactor = 1 - distanceFactorMultiplier * pow(1 - d / maxDiagonal, 10); 148 | PVector temp = p.copy(); 149 | temp.sub(c); 150 | temp.mult(dFactor); 151 | temp.add(c); 152 | p.x = temp.x; 153 | p.y = temp.y; 154 | } 155 | } 156 | } 157 | 158 | float getMaxDist(Point p, ArrayList set) { 159 | if (set.isEmpty()) { 160 | return 0; 161 | } 162 | float maxDistSq = Float.MIN_VALUE; 163 | for (Point pt : set) { 164 | PVector v = pt.pos; 165 | float dSq = v.copy().sub(p.pos).magSq(); 166 | if (dSq > maxDistSq) { 167 | maxDistSq = dSq; 168 | } 169 | } 170 | return sqrt(maxDistSq); 171 | } 172 | 173 | class Point { 174 | 175 | long id; 176 | PVector pos, init; 177 | float distortionMag; 178 | float hue; 179 | float returnRate; 180 | 181 | Point(float x, float y) { 182 | this.init = new PVector(x, y); 183 | this.pos = init.copy(); 184 | this.returnRate = random(minReturnRate, maxReturnRate); 185 | } 186 | 187 | void update() { 188 | float lerpRate = constantReturnRate ? minReturnRate : this.returnRate; 189 | pos.lerp(init, lerpRate); 190 | PVector diff = pos.copy().sub(init); 191 | distortionMag = min(1.0, diff.mag() / distortionMagDivider); 192 | distortionMag = pow(distortionMag, distortionMagFudge); 193 | hue = 360.0 * abs(diff.heading() / PI); 194 | if (mousePressed) { 195 | pos.x += 0.5 * sin(radians(init.y + 2 * frameCount)); 196 | pos.y += 0.5 * sin(PI / 3 + radians(init.x + 2 * frameCount)); 197 | } 198 | } 199 | 200 | Point copy() { 201 | Point p = new Point(pos.x, pos.y); 202 | p.id = (long) random(Long.MIN_VALUE, Long.MAX_VALUE); 203 | return p; 204 | } 205 | 206 | } 207 | 208 | class Mover { 209 | 210 | PVector pos, vel; 211 | float baseSpeed; 212 | 213 | Mover(PVector pos, PVector vel) { 214 | this.pos = pos; 215 | this.vel = vel; 216 | this.baseSpeed = random(10, 15); 217 | } 218 | 219 | void update() { 220 | pos.add(vel); 221 | PVector origin = new PVector(pg.width / 2, pg.height / 2); 222 | PVector diff = PVector.sub(pos, origin); 223 | vel.mult(velMultiplier).limit(baseSpeed + moverLimitAdd); 224 | if (diff.magSq() > pg.width * 2 * pg.width * 2) { 225 | PVector dest = new PVector(random(pg.width), random(pg.height)); 226 | PVector dir = dest.copy().sub(pos).normalize(); 227 | vel = dir.mult(baseSpeed); 228 | } 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /Suns2304/Suns2304.pde: -------------------------------------------------------------------------------- 1 | void setup() { 2 | size(1600, 900, P2D); 3 | colorMode(HSB, 360, 100, 100, 100); 4 | smooth(8); 5 | ellipseMode(RADIUS); 6 | noStroke(); 7 | } 8 | 9 | void draw() { 10 | background(0); 11 | int ny = 36; 12 | int nx = 64; 13 | float inc = 1.0 * height / ny; 14 | float t = radians(frameCount); 15 | for (int yi = 0; yi < ny; yi++) { 16 | for (int xi = 0; xi < nx; xi++) { 17 | float x = xi * inc; 18 | float y = yi * inc; 19 | float base = 1.0 * 0.5 * (1.0 + sin((1 + sin(t * 0.2) * 0.1 * yi) * map(x, 0, height, 0, 2 * PI) - t)); 20 | float yDisp = pow(base, 1 + 4 * 0.5 * (1 + sin(t * 0.3))); 21 | fill(225, 100, 80 * (1 - base)); 22 | square(x, y, inc); 23 | yDisp *= inc * 1.1; 24 | fill(50 - 50 * yDisp / (inc * 1.1), 65 + 35 * yDisp, 100, 100); 25 | circle(x + inc / 2, y + inc / 2 + yDisp, 0.8 * inc / 2); 26 | } 27 | } 28 | println(frameRate); 29 | } 30 | -------------------------------------------------------------------------------- /Topography/Topography.pde: -------------------------------------------------------------------------------- 1 | import java.util.Date; 2 | 3 | PGraphics pg; 4 | float sc = 0.004; 5 | boolean drawBg = true; 6 | boolean save = false; 7 | 8 | void setup() { 9 | randomSeed(10L); 10 | noiseSeed(10L); 11 | size(900, 900, P2D); 12 | pg = createGraphics(1080, 1080, P2D); 13 | colorMode(HSB, 360, 100, 100, 100); 14 | pg.smooth(8); 15 | pg.beginDraw(); 16 | pg.colorMode(HSB, 360, 100, 100, 100); 17 | pg.endDraw(); 18 | 19 | } 20 | 21 | void draw() { 22 | pg.beginDraw(); 23 | if (drawBg) { 24 | pg.background(0); 25 | drawBg = false; 26 | } 27 | int perFrame = 10000; 28 | for (int i = 0; i < perFrame; i++) { 29 | float x = random(pg.width); 30 | float y = random(pg.height); 31 | float n2 = pow(noise(x * sc + 10000, y * sc + 10000, 100000), 5); 32 | float m = 10 + n2 * 100; 33 | float n = noise(x * sc, y * sc); 34 | float fn = pow(0.5 * (1 + sin(map(n, 0, 1, 0, 2 * PI) * m)), 5); 35 | pg.stroke(40 * fn, 100, 100 * fn); 36 | pg.point(x, y); 37 | } 38 | if (save) { 39 | pg.save(getClass().getName() + new Date().getTime() + ".png"); 40 | save = false; 41 | } 42 | pg.endDraw(); 43 | image(pg, 0, 0, width, height); 44 | println(frameRate); 45 | } 46 | 47 | void mouseClicked() { 48 | save = true; 49 | } 50 | -------------------------------------------------------------------------------- /TriangleDance/TriangleDance.pde: -------------------------------------------------------------------------------- 1 | ArrayList tri = new ArrayList(); 2 | PGraphics pg; 3 | 4 | void setup() { 5 | size(900, 900, P2D); 6 | pg = createGraphics(1080, 1080, P2D); 7 | pg.smooth(8); 8 | int sideLength = pg.width / 10; 9 | tri.add(new PVector(0, 0)); 10 | tri.add(new PVector(0, 1)); 11 | tri.add(new PVector(1, 1)); 12 | tri = fillIn(tri, 2.0 / sideLength); 13 | } 14 | 15 | void draw() { 16 | pg.beginDraw(); 17 | pg.background(0); 18 | pg.noStroke(); 19 | float f = pow(0.5 + 0.5 * mouseX / width, 1); 20 | float speed = 0.8; 21 | 22 | color c1 = color(255, 75, 0); 23 | color c2 = color(255, 225, 200); 24 | color c3 = color(100, 50, 255); 25 | color c4 = color(0, 0, 255); 26 | //color c5 = lerpColor(c2, c4, 0.5 * (1 + sin(radians(frameCount * speed)))); 27 | int n = 10; 28 | int inc = pg.width / n; 29 | for (int cy = 0; cy < n; cy++) { 30 | int yBase = cy * inc; 31 | color c = lerpColor(c1, c3, 1.0 * cy / n); 32 | for (int cx = 0; cx < n; cx++) { 33 | int off = int(frameCount * speed + 50.0 * cx / n); 34 | int endIndex = int(off + f * tri.size()); 35 | int xBase = cx * inc; 36 | pg.fill(c); 37 | pg.beginShape(); 38 | for (int i = off; i < endIndex; i ++) { 39 | PVector p = tri.get(i % tri.size()); 40 | pg.vertex(p.x * inc + xBase, p.y * inc + yBase); 41 | } 42 | pg.endShape(); 43 | pg.fill(c2); 44 | pg.beginShape(); 45 | for (int i = off; i < endIndex; i ++) { 46 | PVector p = tri.get(i % tri.size()); 47 | pg.vertex(inc - p.x * inc + xBase, inc - p.y * inc + yBase); 48 | } 49 | pg.endShape(); 50 | } 51 | } 52 | pg.endDraw(); 53 | if (frameCount % 60 == 0) { 54 | println(frameCount / 60 + " --- " + frameRate); 55 | } 56 | image(pg, 0, 0, width, height); 57 | } 58 | 59 | ArrayList fillIn(ArrayList curve, float pixInc) { 60 | if (curve.isEmpty()) { 61 | return curve; 62 | } 63 | ArrayList newCurve = new ArrayList(); 64 | for (int i = 0; i < curve.size(); i++) { 65 | PVector p = curve.get(i % curve.size()); 66 | PVector next = curve.get((i + 1) % curve.size()); 67 | PVector diff = next.copy().sub(p); 68 | PVector n = diff.copy().normalize(); 69 | float mag = diff.mag(); 70 | int c = round(mag / pixInc); 71 | for (float j = 0; j < c; j++) { 72 | PVector v = p.copy().add(n.copy().mult(j * mag / c)); 73 | newCurve.add(v); 74 | } 75 | } 76 | return newCurve; 77 | } 78 | -------------------------------------------------------------------------------- /TrianglesInConcentricCircles/TrianglesInConcentricCircles.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | color bgColor = color(255, 245, 235); // color(240, 250, 255); 3 | 4 | void setup() { 5 | size(900, 900, P3D); 6 | colorMode(RGB, 255, 255, 255, 1.0); 7 | pg = createGraphics(2160, 2160, P3D); 8 | pg.smooth(8); 9 | pixelDensity(displayDensity()); 10 | pg.beginDraw(); 11 | pg.colorMode(RGB, 255, 255, 255, 1.0); 12 | pg.ellipseMode(RADIUS); 13 | pg.endDraw(); 14 | } 15 | 16 | boolean save = false; 17 | 18 | void draw() { 19 | pg.beginDraw(); 20 | if (frameCount == 1) { 21 | pg.background(bgColor); 22 | } 23 | pg.fill(0); 24 | pg.noFill(); 25 | pg.textSize(30); 26 | float r = pg.width / 2 - 10; 27 | float initR = r; 28 | PVector c = new PVector(pg.width / 2, pg.height / 2); 29 | while (r > initR / 10) { 30 | int n = 40; // triangle "segments" per circle 31 | float angle = 0; 32 | for (int i = 0; i < n; i++) { 33 | angle = i * 2 * PI / n; 34 | PVector p = new PVector(c.x + r * cos(angle), c.y + r * sin(angle)); 35 | float len = 5 + (r - r * 0.63) * (pow(abs(angle - PI) / PI, 1.2)); // height of triangle. no formula for determing these values, just experimentation 36 | PVector diff = new PVector(c.x, c.y).sub(p).normalize().mult(len); // side of triangle pointing in toward center 37 | angle = (i + 1) * 2 * PI / n; 38 | PVector p2 = new PVector(c.x + r * cos(angle), c.y + r * sin(angle)); 39 | float area = triangleArea(p, new PVector(p.x + diff.x, p.y + diff.y), p2); 40 | shadeTriangle(p.x, p.y, p.x + diff.x, p.y + diff.y, p2.x, p2.y, 10 + int(area / 40), 0.2, color(0, 30, 100)); 41 | len = 5 + (r - r * 0.63) * (pow(abs(angle - PI) / PI, 1.2)); 42 | PVector diff2 = new PVector(c.x, c.y).sub(p2).normalize().mult(len); 43 | shadeTriangle(p.x, p.y, p2.x + diff2.x, p2.y + diff2.y, p2.x, p2.y, 10 + int(area / 40), 0.12, color(0, 30, 100)); 44 | } 45 | c.x -= r * 0.18; // move center to left 46 | r *= 0.8; 47 | } 48 | pg.endDraw(); 49 | image(pg, 0, 0, width, height); 50 | if (save) { 51 | pg.save("TrianglesInConcentricCircles" + int(random(100000000)) + ".png"); 52 | save = false; 53 | println("saved"); 54 | } 55 | //println(frameRate); 56 | } 57 | 58 | void mouseClicked() { 59 | save = true; 60 | } 61 | 62 | void shadeTriangle(float x1, float y1, float x2, float y2, float x3, float y3, int nDots, float alpha, color col) { 63 | PVector a = new PVector(x1, y1); 64 | PVector b = new PVector(x2, y2); 65 | PVector c = new PVector(x3, y3); 66 | pg.stroke(col, alpha); 67 | for (int i = 0; i < nDots; i++) { 68 | float r = pow(random(1), 10); 69 | pg.strokeWeight(1 + 2 * r); 70 | PVector p = randomInTriangle(a, b, c); 71 | pg.point(p.x, p.y); 72 | } 73 | } 74 | 75 | // thank you Math Stack Exchange for the formula: https://math.stackexchange.com/questions/18686/uniform-random-point-in-triangle-in-3d 76 | PVector randomInTriangle(PVector a, PVector b, PVector c) { 77 | float r1 = random(1); 78 | float r2 = random(1); 79 | PVector point = new PVector(0, 0); 80 | point.add(PVector.mult(a, 1 - sqrt(r1))); 81 | point.add(PVector.mult(b, sqrt(r1) * (1 - r2))); 82 | point.add(PVector.mult(c, r2 * sqrt(r1))); 83 | return point; 84 | } 85 | 86 | // see: https://mathworld.wolfram.com/TriangleArea.html 87 | float triangleArea(PVector a, PVector b, PVector c) { 88 | PVector u = c.copy().sub(a); 89 | PVector v = c.copy().sub(b); 90 | return 0.5 * u.cross(v).mag(); 91 | } 92 | -------------------------------------------------------------------------------- /TurnTurnTurn/TurnTurnTurn.pde: -------------------------------------------------------------------------------- 1 | void setup() { 2 | size(900, 900, P3D); 3 | smooth(8); 4 | colorMode(HSB, 360, 100, 100, 100); 5 | } 6 | 7 | void draw() { 8 | background(150, 80, 10); 9 | noStroke(); 10 | int pixPerInc = 1; 11 | int petals = 10; 12 | int flowersX = 4; 13 | int flowersY = 4; 14 | float timeFactor = radians(frameCount * 2.5); 15 | float baseR = height / flowersY / 2; 16 | float useR = baseR * 0.95; 17 | int n = int(baseR * 2 * PI / pixPerInc); 18 | float inc = 2 * PI / n; 19 | for (int yi = 0; yi < flowersY; yi++) { 20 | for (int xi = 0; xi < flowersX; xi++) { 21 | float timeOffset = xi * PI / flowersX; 22 | float power = 1 + 10.0 * pow(abs(sin(radians(frameCount * 0.5) - timeOffset)), 4); 23 | fill((175 + xi * 45 + yi * 20) % 360, 75, 90); 24 | PVector origin = new PVector(baseR + baseR * 2 * xi, baseR + baseR * 2 * yi); 25 | beginShape(); 26 | for (int i = 0; i <= n; i++) { 27 | float angle = i * inc; 28 | float r = useR * pow(abs(sin(petals / 2 * angle + timeFactor + timeOffset)), power); 29 | PVector p = PVector.fromAngle(angle).mult(useR - r).add(origin); 30 | vertex(p.x, p.y); 31 | } 32 | endShape(); 33 | 34 | fill((225 + xi * 45 + yi * 20) % 360, 75, 90); 35 | float timeFactor2 = radians(frameCount * 2.3); 36 | beginShape(); 37 | for (int i = 0; i <= n; i++) { 38 | float angle = i * inc; 39 | float r = useR * pow(abs(sin(petals / 2 * angle + timeFactor2)), power); 40 | PVector p = PVector.fromAngle(angle).mult(useR - r).add(origin); 41 | vertex(p.x, p.y); 42 | } 43 | endShape(); 44 | } 45 | } 46 | println(frameCount / 60 + " --- " + frameRate); 47 | } 48 | -------------------------------------------------------------------------------- /WanderingStars/WanderingStars.pde: -------------------------------------------------------------------------------- 1 | 2 | void setup() { 3 | size(900, 900, P3D); 4 | smooth(8); 5 | blendMode(ADD); 6 | } 7 | 8 | void draw() { 9 | background(0); 10 | noStroke(); 11 | fill(255, 150, 100, 100); 12 | int n = 150; 13 | float maxR = 400; 14 | float r = maxR - maxR * abs(sin(radians(frameCount * 0.17))); 15 | float x = r + (width - r * 2) * (0.5 * (1 + sin(radians(frameCount * 0.33)))); 16 | float y = r + (height - r * 2) * (0.5 * (1 + sin(radians(frameCount * 0.23)))); 17 | PVector origin = new PVector(x, y); 18 | float init = radians(frameCount * 0.13); 19 | fill(255, 150, 10, 80); 20 | for (int i = 0; i < n; i++) { 21 | float frac = 1.0 * i / n; 22 | float angle = init + frac * 2 * PI; // 2 * PI * (1 - pow(2 * frac - 1, 2)) + init; 23 | PVector p = PVector.fromAngle(angle).mult(r).add(origin); 24 | float tanAngle = angle + PI / 2; 25 | PVector dir = PVector.fromAngle(tanAngle); 26 | PVector p2 = dir.copy().mult(width * 1.5).add(p); 27 | PVector p3 = dir.copy().mult(-width * 1.5).add(p); 28 | triangle(p2.x, p2.y, p2.x + 10, p2.y, p3.x, p3.y); 29 | } 30 | 31 | r = maxR - maxR * abs(sin(radians(PI / 3 + frameCount * 0.13))); 32 | x = r + (width - r * 2) * (0.5 * (1 + sin(radians(frameCount * 0.29)))); 33 | y = r + (height - r * 2) * (0.5 * (1 + sin(radians(frameCount * 0.19)))); 34 | origin = new PVector(x, y); 35 | init = radians(frameCount * 0.07); 36 | fill(150, 150, 255, 80); 37 | for (int i = 0; i < n; i++) { 38 | float frac = 1.0 * i / n; 39 | float angle = init + frac * 2 * PI; // 2 * PI * (1 - pow(2 * frac - 1, 2)) + init; 40 | PVector p = PVector.fromAngle(angle).mult(r).add(origin); 41 | float tanAngle = angle + PI / 2; 42 | PVector dir = PVector.fromAngle(tanAngle); 43 | PVector p2 = dir.copy().mult(width * 1.5).add(p); 44 | PVector p3 = dir.copy().mult(-width * 1.5).add(p); 45 | triangle(p2.x, p2.y, p2.x, p2.y + 10, p3.x, p3.y); 46 | } 47 | println(frameCount / 60); 48 | } 49 | -------------------------------------------------------------------------------- /WhereDoWeGo/WhereDoWeGo.pde: -------------------------------------------------------------------------------- 1 | PGraphics pg; 2 | 3 | ArrayList pointList = new ArrayList(); 4 | Traveler t; 5 | int n = 20; 6 | float margin; 7 | boolean stop; 8 | boolean drawBg = true; 9 | 10 | void setup() { 11 | size(900, 900, P2D); 12 | pg = createGraphics(1080, 1080, P2D); 13 | pg.smooth(8); 14 | background(255); 15 | frameRate(20); 16 | margin = pg.width / 30; 17 | float inc = (pg.width - margin * 2) / n; 18 | for (int y = 0; y <= n; y++) { 19 | for (int x = 0; x <= n; x++) { 20 | Point p = new Point(x, y); 21 | p.pos = new PVector(margin + x * inc, margin + y * inc); 22 | pointList.add(p); 23 | } 24 | } 25 | setNeighbors(); 26 | t = new Traveler(); 27 | } 28 | 29 | void draw() { 30 | pg.beginDraw(); 31 | if (frameCount < 3) { 32 | pg.background(0); 33 | pg.stroke(255); 34 | pg.strokeWeight(4); 35 | drawBg = false; 36 | } else { 37 | t.show(); 38 | t.travel(); 39 | 40 | if (stop) { 41 | //exit(); 42 | } 43 | } 44 | image(pg, 0, 0, width, height); 45 | pg.endDraw(); 46 | } 47 | 48 | void setNeighbors() { 49 | for (int i = 0; i < pointList.size(); i++) { 50 | Point p = pointList.get(i); 51 | for (int j = i + 1; j < pointList.size(); j++) { 52 | Point p2 = pointList.get(j); 53 | if ((p.x == p2.x && abs(p.y - p2.y) == 1) || (p.y == p2.y && abs(p.x - p2.x) == 1)) { 54 | p.neighbors.add(p2); 55 | p2.neighbors.add(p); 56 | } 57 | } 58 | } 59 | } 60 | 61 | ArrayList getFreePoints() { 62 | ArrayList result = new ArrayList(); 63 | for (Point p : pointList) { 64 | if (p.free) { 65 | result.add(p); 66 | } 67 | } 68 | return result; 69 | } 70 | 71 | class Point { 72 | 73 | ArrayList neighbors = new ArrayList(); 74 | Point next; 75 | boolean free; 76 | int x, y; // grid coordinates 77 | PVector pos; // screen coordinates 78 | 79 | Point(int x, int y) { 80 | this.x = x; 81 | this.y = y; 82 | this.free = true; 83 | } 84 | 85 | ArrayList getFreeNeighbors() { 86 | ArrayList result = new ArrayList(); 87 | for (Point p : neighbors) { 88 | if (p.free) { 89 | result.add(p); 90 | } 91 | } 92 | return result; 93 | } 94 | 95 | String toString() { 96 | String s = ""; 97 | s += String.format("(%d, %d) | ", x, y); 98 | for (Point p : neighbors) { 99 | s += String.format("(%d, %d) ", p.x, p.y); 100 | } 101 | return s; 102 | } 103 | 104 | } 105 | 106 | class Traveler { 107 | 108 | Point p; 109 | Point last; 110 | ArrayList history; 111 | 112 | Traveler() { 113 | reset(); 114 | this.history = new ArrayList(); 115 | } 116 | 117 | void travel() { 118 | p.free = false; 119 | history.add(p); 120 | last = p; 121 | ArrayList choices = p.getFreeNeighbors(); 122 | if (choices.isEmpty()) { 123 | reset(); 124 | } else { 125 | p = choices.get(int(random(choices.size()))); 126 | } 127 | } 128 | 129 | void reset() { 130 | ArrayList choices = getFreePoints(); 131 | if (!choices.isEmpty()) { 132 | p = choices.get(int(random(choices.size()))); 133 | last = null; 134 | } else { 135 | stop = true; 136 | } 137 | } 138 | 139 | void show() { 140 | stroke(255); 141 | fill(255); 142 | if (last != null) { 143 | PVector v = PVector.lerp(last.pos, p.pos, 0.85); 144 | PVector v2 = PVector.lerp(last.pos, p.pos, 0.65); 145 | pg.line(last.pos.x, last.pos.y, v.x, v.y); 146 | 147 | PVector diff = p.pos.copy().sub(last.pos).normalize(); 148 | PVector n = new PVector(-diff.y, diff.x); 149 | PVector p2 = v2.copy().add(n.copy().mult(5)); 150 | PVector p3 = v2.copy().add(n.copy().mult(-5)); 151 | pg.line(p2.x, p2.y, v.x, v.y); 152 | pg.line(p3.x, p3.y, v.x, v.y); 153 | } else { 154 | pg.circle(p.pos.x, p.pos.y, 15); 155 | } 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /WonkyBlob/WonkyBlob.pde: -------------------------------------------------------------------------------- 1 | color bgColor = color(0, 0, 40); 2 | color strokeColor = color(255, 225, 200); // color(200, 240, 255); // 3 | PGraphics pg; 4 | 5 | void setup() { 6 | size(900, 900, P2D); 7 | pg = createGraphics(1080, 1080, P2D); 8 | pg.smooth(8); 9 | 10 | } 11 | 12 | int folds = 5; 13 | int n = 400; 14 | 15 | void keyPressed() { 16 | if (key == CODED) { 17 | if (keyCode == UP) { 18 | n++; 19 | } 20 | if (keyCode == DOWN && n > 3) { 21 | n--; 22 | } 23 | if (keyCode == LEFT) { 24 | n = 6; 25 | } 26 | if (keyCode == RIGHT) { 27 | n = 400; 28 | } 29 | } 30 | if (key == 'i') { 31 | color temp = bgColor; 32 | bgColor = strokeColor; 33 | strokeColor = temp; 34 | } 35 | } 36 | 37 | void draw() { 38 | pg.beginDraw(); 39 | pg.background(bgColor); 40 | //pg.noFill(); 41 | pg.translate(pg.width / 2, pg.height / 2); 42 | pg.stroke(strokeColor); 43 | 44 | float inc = 2 * PI / n; 45 | PVector [] values = new PVector[n]; 46 | PVector [] distValues = new PVector[n]; 47 | float tFactor = sin(radians(frameCount)); 48 | for (int i = 0; i < n; i++) { 49 | float angle = i * inc + radians(frameCount * 0.2); 50 | float r = 15; 51 | float cosAngle = cos(angle); 52 | float sinAngle = sin(angle); 53 | float x = r * cosAngle; 54 | float y = r * sinAngle; 55 | values[i] = new PVector(x, y); 56 | float distR = 50 57 | + 50.0 * tFactor * cos(folds * angle + radians(frameCount * 5)); 58 | distValues[i] = new PVector(distR * cosAngle, distR * sinAngle); 59 | } 60 | 61 | color col1 = color(255, 200, 255); 62 | 63 | int layers = 33; 64 | for (int i = layers - 1; i >= 0; i--) { 65 | PVector c = new PVector(height / 2 * sin(radians(frameCount)) * (1 - 1.0 * i / layers), height / 2 * sin(radians(PI / 3 + frameCount * 1.3)) * (1 - 1.0 * i / layers)); 66 | float indexFactor = 1.0 * i / layers; 67 | pg.fill(lerpColor(col1, bgColor, indexFactor)); 68 | pg.noStroke(); 69 | pg.beginShape(); 70 | for (int j = 0; j < values.length; j++) { 71 | float ratio = abs(1.0 * i - layers) / layers; 72 | ratio = pow(ratio, 3); 73 | PVector val = PVector.lerp(values[j], distValues[j], ratio); 74 | PVector plot = val.copy().mult(1 + i); 75 | pg.vertex(c.x + plot.x, c.y + plot.y); 76 | } 77 | pg.endShape(CLOSE); 78 | } 79 | pg.endDraw(); 80 | image(pg, 0, 0, width, height); 81 | println(frameCount / 60 + " | " + frameRate); 82 | } 83 | -------------------------------------------------------------------------------- /misc/CirclePackingWithGrid21659442631307.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brian-Fearn/Processing/e1058f7c372427491d059a67dd917afc56cec65f/misc/CirclePackingWithGrid21659442631307.png -------------------------------------------------------------------------------- /misc/DreamscapesPartTwo1652972999987seed3767882.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brian-Fearn/Processing/e1058f7c372427491d059a67dd917afc56cec65f/misc/DreamscapesPartTwo1652972999987seed3767882.png -------------------------------------------------------------------------------- /misc/PackedArcs1649820553959.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brian-Fearn/Processing/e1058f7c372427491d059a67dd917afc56cec65f/misc/PackedArcs1649820553959.png -------------------------------------------------------------------------------- /misc/arcsRandom2940173.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brian-Fearn/Processing/e1058f7c372427491d059a67dd917afc56cec65f/misc/arcsRandom2940173.png -------------------------------------------------------------------------------- /misc/github_avi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brian-Fearn/Processing/e1058f7c372427491d059a67dd917afc56cec65f/misc/github_avi.png --------------------------------------------------------------------------------