(Ey! I love all your post)
//=============================================================================================================
interface Palette {
color nextColor();
void reset();
}
//=============================================================================================================
class RandomPalette implements Palette {
color nextColor() {
return color(random(TWO_PI), random(1), random(1));
}
void reset() {
}
}
//=============================================================================================================
class RandomBrightPalette implements Palette {
color nextColor() {
return color(random(TWO_PI), 1, 1);
}
void reset() {
}
}
//=============================================================================================================
class ColorWheelPalette implements Palette {
static final float BLACK_PROBABILITY = 0.4;
float[] hueOffsets;
float blackProbability;
float whiteProbability;
float saturatedProbability;
float hueValue;
ColorWheelPalette(float[] hueOffsets) {
this.hueOffsets = hueOffsets;
}
color nextColor() {
float h = (hueValue + hueOffsets[(int)random(hueOffsets.length)]) % TWO_PI;
float s;
float b;
float r = random(1);
if (r < blackProbability) {
s = 0;
b = 0;
} else if (r < blackProbability+whiteProbability) {
s = 0;
b = 1;
} else if (r < blackProbability+whiteProbability+saturatedProbability) {
s = 1;
b = 1;
} else {
if (random(1) < 0.5) {
s = random(1);
b = 1;
} else {
s = 1;
b = random(1);
}
}
return color(h, s, b);
}
void reset() {
hueValue = random(TWO_PI);
blackProbability = 0;
whiteProbability = 0;
saturatedProbability = 0;
float r = random(1);
if (random(1) < 0.3) {
// Only saturated
saturatedProbability = 1;
} else if (random(1) < 0.4) {
// saturated + black
blackProbability = 1.0/(1+hueOffsets.length);
saturatedProbability = 1 - blackProbability;
} else if (random(1) < 0.5) {
// saturated + white
whiteProbability = 1.0/(1+hueOffsets.length);
saturatedProbability = 1 - whiteProbability;
} else if (random(1) < 0.6) {
// saturated + black + white
blackProbability = 1.0/(2+hueOffsets.length);
whiteProbability = 1.0/(2+hueOffsets.length);
saturatedProbability = 1 - blackProbability - whiteProbability;
} else {
// Unsaturated
}
}
}
//=============================================================================================================
Palette allPalettes[] = {
new RandomPalette(),
new RandomBrightPalette(), new RandomBrightPalette(), new RandomBrightPalette(), // Extra probability for random bright palette
// Following palettes are based on color scheme described by ColorJack (http://www.colorjack.com/articles/color_formulas.html)
new ColorWheelPalette(new float[]{0}), // Monochrome
new ColorWheelPalette(new float[]{0, PI}), // Complementaty
new ColorWheelPalette(new float[]{0, TWO_PI/12*5, TWO_PI/12*7}), // Split-Complementary
new ColorWheelPalette(new float[]{0, TWO_PI/3, TWO_PI/3*2}), // Triadic
new ColorWheelPalette(new float[]{0, TWO_PI/4, TWO_PI/4*2, TWO_PI/4*3}), // Tetradic
new ColorWheelPalette(new float[]{0, TWO_PI/6, TWO_PI/6*3, TWO_PI/6*4}), // Four-tone
new ColorWheelPalette(new float[]{0, TWO_PI/72*23, TWO_PI/72*31, TWO_PI/72*41, TWO_PI/72*49}), // Five-tone
new ColorWheelPalette(new float[]{0, TWO_PI/12, TWO_PI/12*4, TWO_PI/12*5, TWO_PI/12*8, TWO_PI/12*9}), // Six-tone
new ColorWheelPalette(new float[]{0, TWO_PI/24, TWO_PI/24*2, TWO_PI/24*3, TWO_PI/24*4, TWO_PI/24*5}) // Neutral
};
Palette getRandomPalette() {
Palette palette = allPalettes[(int)random(allPalettes.length)];
palette.reset();
return palette;
}
/*
* Kaleidoscope by Algirdas Rascius (http://mydigiverse.com).
*/
/**
* Mouse-click to change pattern and color.
*/
static final int SCREEN_SIZE = 200;
static final int SIDE = 150;
static final float MAX_TILE_ROTATION_DELTA = 0.02;
static final float MAX_ROTATION_DELTA = 0.008;
static final int AUTO_INITIALIZE_COUNT = 3000;
PGraphics tile;
ArrayList shapes;
Palette palette;
ShapeGenerator shapeGenerator;
float tileRotation;
float rotation;
float tileRotationDelta;
float rotationDelta;
int nextAutoInitialize;
void setup() {
size(750, 500, P3D);
colorMode(HSB, TWO_PI, 1, 1);
noStroke();
textureMode(NORMALIZED);
tile = createGraphics(SCREEN_SIZE, SCREEN_SIZE, JAVA2D);
tile.background(color(0));
shapes = new ArrayList();
frameRate(30);
initialize();
}
void initialize() {
shapes.clear();
palette = getRandomPalette();
shapeGenerator = getRandomShapeGenerator();
tileRotationDelta = random(-MAX_TILE_ROTATION_DELTA, MAX_TILE_ROTATION_DELTA);
rotationDelta = random(-MAX_ROTATION_DELTA, MAX_ROTATION_DELTA);
nextAutoInitialize = AUTO_INITIALIZE_COUNT;
}
void mousePressed() {
initialize();
}
void keyPressed() {
initialize();
}
void draw() {
drawTile();
drawAllTiles();
if (nextAutoInitialize-- < 0) {
initialize();
}
}
void drawTile() {
tile.beginDraw();
tile.filter(BLUR);
shapeGenerator.createShapes(shapes, tile, palette);
for (Iterator i=shapes.iterator(); i.hasNext();) {
Shape s = (Shape)i.next();
if (!s.draw(tile)) {
i.remove();
}
}
tile.endDraw();
}
final static float SIN_30 = sin(TWO_PI/12);
final static float COS_30 = cos(TWO_PI/12);
void drawAllTiles() {
tileRotation = (tileRotation + tileRotationDelta + TWO_PI) % TWO_PI;
rotation = (rotation + rotationDelta + TWO_PI) % TWO_PI;
float tx1 = 0.5+0.49*sin(tileRotation);
float ty1 = 0.5+0.49*cos(tileRotation);
float tx2 = 0.5+0.49*sin(tileRotation+TWO_PI/3);
float ty2 = 0.5+0.49*cos(tileRotation+TWO_PI/3);
float tx3 = 0.5+0.49*sin(tileRotation+TWO_PI/3*2);
float ty3 = 0.5+0.49*cos(tileRotation+TWO_PI/3*2);
translate(width/2, height/2);
scale(SIDE, SIDE);
rotate(rotation);
for (int y=-2; y<=2; y++) {
pushMatrix();
translate(0, y*(1+SIN_30));
for (int x=-2; x<=2; x++) {
pushMatrix();
translate(x*2*COS_30, 0);
if (abs(y)%2==1) {
translate(COS_30, 0);
}
for (int i=0; i<3; i++) {
rotate(TWO_PI/3);
for (int j=0; j<2; j++) {
scale(-1,1);
beginShape();
texture(tile);
vertex(0, 0, tx1, ty1);
vertex(0, 1, tx2, ty2);
vertex(COS_30, SIN_30, tx3, ty3);
endShape();
}
}
popMatrix();
}
popMatrix();
}
}
//=============================================================================================================
interface Shape {
boolean draw(PGraphics g);
}
//=============================================================================================================
class Point implements Shape {
static final float MAX_WEIGHT = 7;
static final float DELTA_WEIGHT = 0.2;
float x;
float y;
color clr;
float w;
Point(PGraphics g, Palette p) {
x = random(0, g.width);
y = random(0, g.height);
clr = p.nextColor();
w = 0;
}
boolean draw(PGraphics g) {
w += DELTA_WEIGHT;
g.strokeWeight(w);
g.stroke(clr);
g.point(x, y);
return w < MAX_WEIGHT;
}
}
//=============================================================================================================
class Spiral implements Shape {
static final float MIN_RADIUS = 0.3;
static final float MAX_RADIUS = 0.6;
static final int WEIGHT = 5;
static final int STEPS = 10;
static final float R_STEP = 0.003;
static final float A_STEP = 0.05;
float radius;
float x;
float y;
color clr;
float r;
float a;
float aDelta;
Spiral(PGraphics g, Palette p) {
radius = random(g.width*MIN_RADIUS, g.width*MAX_RADIUS);
x = random(g.width*MIN_RADIUS, g.width*(1-MIN_RADIUS));
y = random(g.height*MIN_RADIUS, g.height*(1-MIN_RADIUS));
clr = p.nextColor();
r = 0;
a = random(TWO_PI);
aDelta = random(-A_STEP, A_STEP);
}
boolean draw(PGraphics g) {
g.strokeWeight(WEIGHT);
g.stroke(clr);
for (int i=0; i<STEPS; i++) {
float x0 = x + r*radius*sin(a);
float y0 = y + r*radius*cos(a);
r += R_STEP;
a += aDelta;
float x1 = x + r*radius*sin(a);
float y1 = y + r*radius*cos(a);
g.line(x0, y0, x1, y1);
if (r >= 1) {
return false;
}
}
return true;
}
}
//=============================================================================================================
class Circle implements Shape {
static final float MIN_RADIUS = 0.1;
static final float MAX_RADIUS = 0.4;
static final float R_STEP = 0.05;
float radius;
float x;
float y;
color clr;
float r;
Circle(PGraphics g, Palette p) {
radius = random(g.width*MIN_RADIUS, g.width*MAX_RADIUS);
x = random(g.width*MIN_RADIUS, g.width*(1-MIN_RADIUS));
y = random(g.height*MIN_RADIUS, g.height*(1-MIN_RADIUS));
clr = p.nextColor();
r = 0;
}
boolean draw(PGraphics g) {
r += R_STEP;
g.stroke(clr);
g.noFill();
g.strokeWeight(1);
g.ellipseMode(RADIUS);
g.ellipse(x, y, radius*r, radius*r);
return r < 1;
}
}
//=============================================================================================================
class Blot implements Shape {
static final int MIN_SIDES = 6;
static final int MAX_SIDES = 40;
static final float MIN_RADIUS = 0.1;
static final float MAX_RADIUS = 0.4;
static final float R_STEP = 0.05;
int sides;
float radiuses[];
float x;
float y;
color clr;
float r;
Blot(PGraphics g, Palette p) {
sides = (int)random(MIN_SIDES, MAX_SIDES);
radiuses = new float[sides];
for(int i=0; i<sides; i++) {
radiuses[i] = random(g.width*MIN_RADIUS, g.width*MAX_RADIUS);
}
x = random(g.width*MIN_RADIUS, g.width*(1-MIN_RADIUS));
y = random(g.height*MIN_RADIUS, g.height*(1-MIN_RADIUS));
clr = p.nextColor();
r = 0;
}
boolean draw(PGraphics g) {
r += R_STEP;
g.stroke(clr);
g.noFill();
g.strokeWeight(1);
g.beginShape();
for(int i=0; i<sides+3; i++) {
g.curveVertex(x+r*radiuses[i%sides]*sin(TWO_PI/sides*i), y+r*radiuses[i%sides]*cos(TWO_PI/sides*i));
}
g.endShape();
return r < 1;
}
}
//=============================================================================================================
class ShapeGenerator {
float pointProbability;
float spiralProbability;
float circleProbability;
float blotProbability;
ShapeGenerator(float pointProbability, float spiralProbability,
float circleProbability, float blotProbability) {
this.pointProbability = pointProbability;
this.spiralProbability = spiralProbability;
this.circleProbability = circleProbability;
this.blotProbability = blotProbability;
}
void createShapes(ArrayList shapes, PGraphics g, Palette p) {
if (random(1) < pointProbability) {
shapes.add(new Point(g, p));
}
if (random(1) < spiralProbability) {
shapes.add(new Spiral(g, p));
}
if (random(1) < circleProbability) {
shapes.add(new Circle(g, p));
}
if (random(1) < blotProbability) {
shapes.add(new Blot(g, p));
}
}
}
//=============================================================================================================
ShapeGenerator allShapeGenerators[] = {
new ShapeGenerator(0, 0.07, 0, 0), // Spirals only
new ShapeGenerator(0, 0.04, 0, 0), // Spirals only (less frequent)
new ShapeGenerator(0.5, 0.03, 0, 0), // Points ant spirals
new ShapeGenerator(0, 0, 0, 0.07), // Blots only
new ShapeGenerator(0, 0, 0, 0.04), // Blots only (less frequent)
new ShapeGenerator(0, 0, 0.03, 0.04), // Circles and blots
new ShapeGenerator(0, 0.02, 0.02, 0.03), // Spirals, circles and blots
new ShapeGenerator(0, 0.02, 0.01, 0.02), // Spirals, circles and blots (less frequent)
new ShapeGenerator(0.3, 0.02, 0.01, 0.02), // Points, spirals, circles and blots
};
ShapeGenerator getRandomShapeGenerator() {
return allShapeGenerators[(int)random(allShapeGenerators.length)];
}
Kaleidoscope was one of my childhood toys. Here is a Processing version of it.
Mouse-click to change pattern and color.