diff --git a/grotto/2025-4-18-14-5-40.png b/grotto/2025-4-18-14-5-40.png new file mode 100644 index 0000000..67b02d5 Binary files /dev/null and b/grotto/2025-4-18-14-5-40.png differ diff --git a/grotto/2025-4-20-21-14-59.png b/grotto/2025-4-20-21-14-59.png new file mode 100644 index 0000000..791fdf2 Binary files /dev/null and b/grotto/2025-4-20-21-14-59.png differ diff --git a/grotto/2025-4-20-21-5-43.png b/grotto/2025-4-20-21-5-43.png new file mode 100644 index 0000000..8918493 Binary files /dev/null and b/grotto/2025-4-20-21-5-43.png differ diff --git a/grotto/2025-4-20-22-20-53.png b/grotto/2025-4-20-22-20-53.png new file mode 100644 index 0000000..10bb450 Binary files /dev/null and b/grotto/2025-4-20-22-20-53.png differ diff --git a/grotto/2025-4-20-22-21-3.png b/grotto/2025-4-20-22-21-3.png new file mode 100644 index 0000000..ecf3ed9 Binary files /dev/null and b/grotto/2025-4-20-22-21-3.png differ diff --git a/grotto/2025-4-20-22-25-54.png b/grotto/2025-4-20-22-25-54.png new file mode 100644 index 0000000..b69a452 Binary files /dev/null and b/grotto/2025-4-20-22-25-54.png differ diff --git a/grotto/2025-4-20-22-34-0.png b/grotto/2025-4-20-22-34-0.png new file mode 100644 index 0000000..a20dcb5 Binary files /dev/null and b/grotto/2025-4-20-22-34-0.png differ diff --git a/grotto/2025-4-20-22-34-6.png b/grotto/2025-4-20-22-34-6.png new file mode 100644 index 0000000..1710e27 Binary files /dev/null and b/grotto/2025-4-20-22-34-6.png differ diff --git a/grotto/2025-4-20-22-38-45.png b/grotto/2025-4-20-22-38-45.png new file mode 100644 index 0000000..06b7192 Binary files /dev/null and b/grotto/2025-4-20-22-38-45.png differ diff --git a/grotto/2025-4-21-20-31-46.png b/grotto/2025-4-21-20-31-46.png new file mode 100644 index 0000000..e2deed1 Binary files /dev/null and b/grotto/2025-4-21-20-31-46.png differ diff --git a/grotto/2025-4-21-20-31-55.png b/grotto/2025-4-21-20-31-55.png new file mode 100644 index 0000000..95fdd89 Binary files /dev/null and b/grotto/2025-4-21-20-31-55.png differ diff --git a/grotto/2025-4-21-20-32-10.png b/grotto/2025-4-21-20-32-10.png new file mode 100644 index 0000000..f12b357 Binary files /dev/null and b/grotto/2025-4-21-20-32-10.png differ diff --git a/grotto/2025-4-22-17-48-58.png b/grotto/2025-4-22-17-48-58.png new file mode 100644 index 0000000..c84582d Binary files /dev/null and b/grotto/2025-4-22-17-48-58.png differ diff --git a/grotto/2025-4-22-17-49-14.png b/grotto/2025-4-22-17-49-14.png new file mode 100644 index 0000000..1f32014 Binary files /dev/null and b/grotto/2025-4-22-17-49-14.png differ diff --git a/grotto/2025-4-22-17-49-7.png b/grotto/2025-4-22-17-49-7.png new file mode 100644 index 0000000..c1c37ac Binary files /dev/null and b/grotto/2025-4-22-17-49-7.png differ diff --git a/grotto/2025-4-22-17-50-15.png b/grotto/2025-4-22-17-50-15.png new file mode 100644 index 0000000..c2c0ede Binary files /dev/null and b/grotto/2025-4-22-17-50-15.png differ diff --git a/grotto/2025-4-22-17-50-26.png b/grotto/2025-4-22-17-50-26.png new file mode 100644 index 0000000..9b1d32c Binary files /dev/null and b/grotto/2025-4-22-17-50-26.png differ diff --git a/grotto/2025-4-22-17-50-57.png b/grotto/2025-4-22-17-50-57.png new file mode 100644 index 0000000..86ae294 Binary files /dev/null and b/grotto/2025-4-22-17-50-57.png differ diff --git a/grotto/grotto.pde b/grotto/grotto.pde new file mode 100644 index 0000000..3f5ddb0 --- /dev/null +++ b/grotto/grotto.pde @@ -0,0 +1,146 @@ +import yash.oklab.*; + +// Configuration parameters +final int WIDTH = 1000; +final int HEIGHT = 1000; +final float NOISE_SCALE = 0.5; +final float NOISE_AMPLITUDE = 100; +final int BASE_RADIUS = 130; +final int PARTICLES_PER_FRAME = 10000; +final float SPRAY_RADIUS = 2; +final int RIDGES = 3; +final int centerX = WIDTH / 2; +final int centerY = HEIGHT / 2; +final int BACKGROUND = 0; + +// Global variables +String finalImagePath = null; +float m_noiseOffset = 0; +float m_hue = 0; +int m_fillColor = 0; + +void settings() { + size(WIDTH, HEIGHT, P2D); + smooth(8); +} + +void setup() { + colorMode(RGB, 255, 255, 255); + noiseDetail(4, 0.5); + Ok.p = this; + resetSketch(); +} + +float noisyRadius(float baseRadius, float angle, float noiseOffset) { + // Convert angle to polar coordinates relative to center + float xoff = cos(angle) + 1; + float yoff = sin(angle) + 1; + + // Calculate the noisy radius at this angle + return baseRadius + map(noise(xoff * NOISE_SCALE, yoff * NOISE_SCALE, noiseOffset), 0, 1, -NOISE_AMPLITUDE, NOISE_AMPLITUDE); +} + +boolean insideRadius(float x, float y, float radius) { + // Check if the point (x, y) is outside the radius + float dist = dist(x, y, centerX, centerY); + return dist < radius; +} + +void drawRidge(float radius, float noiseOffset) { + loadPixels(); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + float dx = x - centerX; + float dy = y - centerY; + + + float angle = atan2(dy, dx); + float dist = sqrt(dx*dx + dy*dy); + + float noisyRadius = noisyRadius(radius, angle, noiseOffset); + float distFromBoundary = abs(dist - noisyRadius); + + if (insideRadius(x, y, noisyRadius)) { + continue; + } + + // Create smooth falloff + float intensity = constrain(map(distFromBoundary, 0, 2*NOISE_AMPLITUDE, 1, 0), 0, 1); + //intensity = intensity * intensity; // Square for smoother falloff + + int loc = x + y * width; + pixels[loc] = lerpColor(BACKGROUND, m_fillColor, intensity * 0.4); + } + } + updatePixels(); + for (int i = 0; i < PARTICLES_PER_FRAME;) { + // Focus particles around the circle boundary for efficiency + float angle = random(TWO_PI); + float noisyRadius = noisyRadius(radius, angle, noiseOffset); + float finalRadius = noisyRadius + randomGaussian() * NOISE_AMPLITUDE * 0.5; + float rx = centerX + cos(angle) * finalRadius; + float ry = centerY + sin(angle) * finalRadius; + if (insideRadius(rx, ry, noisyRadius)) { + continue; + } + circle(rx + randomGaussian() * SPRAY_RADIUS, + ry + randomGaussian() * SPRAY_RADIUS, + random(2, 3)); + i++; + } +} + +void draw() { + // Draw background with low opacity to create a fading effect + fill(BACKGROUND); + rect(0, 0, width, height); + // Draw particles + noStroke(); + + for (int i = 0; i < RIDGES; i++) { + // H = Hue (0-360), S = Saturation (0-100), V = Value (0-100), L = Lightness (0-100) (unused here), A = Alpha (0-100). + // Set the fill color using the Ok.HSV function, which converts HSV values to a color + m_fillColor = Ok.HSV( + m_hue, // Hue: the base hue value, which is randomized in resetSketch() + 80, // ((float)i + 1.0f / (float)RIDGES) * 100.0f, // Saturation: increases with each ridge, creating a gradient effect + ((float)i + 1.0f / (float)RIDGES) * 100.0f, // Brightness: also increases with each ridge for a similar gradient effect + 30 // Alpha: transparency level, set to 30 for a subtle blending effect + ); + fill(m_fillColor); + drawRidge(BASE_RADIUS + 100 * i, m_noiseOffset + 10 * i); + } + + m_noiseOffset += 0.05; +} + +void keyPressed() { + if (key == 's' || key == 'S') { + saveImage(); + } else if (key == ENTER || key == '\n') { + resetSketch(); + } +} + +void saveImage() { + String filename = year() + "-" + month() + "-" + day() + "-" + hour() + "-" + minute() + "-" + second() + ".png"; + if (finalImagePath != null) { + // Copy the temporary file to the new filename + File source = new File(sketchPath(finalImagePath)); + File dest = new File(sketchPath(filename)); + try { + java.nio.file.Files.copy(source.toPath(), dest.toPath()); + } catch (IOException e) { + println("Error saving file: " + e.getMessage()); + } + } else { + save(filename); + } +} + +void resetSketch() { + background(0); + frameCount = 0; + finalImagePath = null; + m_hue = random(360.0f); + loop(); +} diff --git a/grotto/readme.md b/grotto/readme.md new file mode 100644 index 0000000..7de0726 --- /dev/null +++ b/grotto/readme.md @@ -0,0 +1,3 @@ +# Grotto + +Inspired by Jean-Marie Chupin. diff --git a/todo.md b/todo.md index d288c44..ab47ccb 100644 --- a/todo.md +++ b/todo.md @@ -9,10 +9,6 @@ - [x] Use lib in projects - [x] Create git repo - [x] in generative repo, add a 'dependency' section linking back to the PaperAndPencil repo - - [ ] Color - - [ ] Create lib - - [ ] Create example project - - [ ] Use lib in projects - [ ] Utils (saving, etc.) - [ ] Create lib - [ ] Create example project @@ -20,3 +16,4 @@ - [ ] colorGrowth: - [ ] Try it with a more complex color system - [ ] grotto + - [ ] try reversing the drawing process, creating dark shadows instead of light ridges