Cutting Glass Curtain
About this video.
It's a generative art made with Processing programming language and Kdenlive video editor.It creates moving cutting glass animation.
Thanks to nice music:
Warm Breeze by Evan Schaeffer
2015/02/21
http://freemusicarchive.org/music/Evan_Schaeffer/Glow_1216/Evan_Schaeffer_-_06_-_Warm_Breeze
Warm Breeze by Evan Schaeffer is licensed under a Attribution License.
For more permissions:
contact artist
Processing example codes.
I tried to draw these shape with Gaussian distribution and Sigmoid function.Code ver. 180318 Refactoring done.
Why I wrote such complex code like ver 170320?// Cutting Glass Handkerchief 2
// Processing 3.2.1
// 2018.03.18
import java.util.Random;
void setup() {
size(900, 900, P3D);
colorMode(HSB, 360, 100, 100, 100);
blendMode(SCREEN);
hint(DISABLE_DEPTH_TEST);
noFill();
smooth(8);
noLoop();
// frameRate(1);
}
void draw() {
background(0, 0, 0);
ambientLight(0, 0, 100);
camera(0, 0, 900,
0, 0, 0,
0, 1, 0);
int spacing = ceil(random(15, 25));
float sizeRate =random(0.8, 1.0);
float distanceMax = sqrt(width * width / 4 + height * height / 4);
float hueBase = random(360);
float nxStart = random(100);
float nyStart = random(100);
for (float z = 360; z >= 0; z -= 120) {
float nx = nxStart;
for (int x = -width / 2; x < width / 2; x += spacing) {
float ny = nyStart;
for (int y = -height / 2; y < height / 2; y += spacing) {
float distance = sqrt(x*x+y*y) + 1;
float hueDiv = min(45, 6 * distanceMax / distance);
if (hueBase > 50 && hueBase < 160) {
// yellow and green
hueDiv += 15;
}
stroke(
(hueBase + map(random(1), 0, 1, -hueDiv, hueDiv)) % 360,
map(random(1), 0, 1, 10, 80),
(2 + gaussdist(1.5, 1.0, 0.5) * distance / distanceMax) * spacing,
100
);
pushMatrix();
translate(x, y, -z + map(noise(nx, ny), 0, 1, -100 , 100));
strokeWeight(2);
rect(-spacing * sizeRate/2, -spacing * sizeRate/2, spacing * sizeRate, spacing * sizeRate);
strokeWeight(2);
ellipse(0, 0, spacing * sizeRate * 0.7, spacing * sizeRate * 0.7);
popMatrix();
ny += 0.0005 * spacing;
}
nx += 0.0005 * spacing;
}
}
saveFrame("frames/####.png");
exit();
}
float gaussdist(float pmean, float plimit, float pdevi) {
/**
Gaussian distribution
1.parameters.
pmean : mean value
plimit : max value of abs(deviation)
ex. plimit >= 0
pmean = 0.5, plimit = 0.5 -> return value = from 0.0 to 1.0
pdevi : standard deviation value
ex. good value? -> pdevi = plimit / 2
2.return.
gaussian distribution
**/
Random obj_random = new Random();
if (plimit == 0) {
return pmean;
}
float gauss = (float) obj_random.nextGaussian() * pdevi;
// not good idea
if (abs(gauss) > plimit) {
gauss = pow(plimit, 2) / gauss;
}
return pmean + gauss;
}
/*
Copyright (C) 2018 deconbatch
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
*/
Code ver. 170320
// Cutting Glass Curtain
// Processing 3.2.1
// 2017.03.20
import processing.opengl.*;
import java.util.Random;
World wd;
Particle[] pt;
int pline = 35; // line number of particles
int pcolumn = 63; // column number of particles
int divline = 8;
int divcolumn = divline;
int pwidth = divline;
int pnum = pline * pcolumn;
float nl_start, nc_start;
void setup() {
size(1280, 720, OPENGL);
colorMode(HSB, 360, 100, 100, 100);
blendMode(SCREEN);
hint(DISABLE_DEPTH_TEST);
noStroke();
smooth();
// noLoop();
frameRate(20);
// noise for curtain fluttering
nl_start = random(100);
nc_start = random(100);
wd = new World();
pt = new Particle[pnum];
// particle objects
float maxlen = sqrt(pow(pcolumn / 2, 2) + pow(pline / 2, 2));
for (int l = 0; l < pline; l++) {
for (int c = 0; c < pcolumn; c++) {
float x = (c - pcolumn / 2);
float y = (l - pline / 2);
pt[l * pcolumn + c] = new Particle(
x * divcolumn,
y * divline,
pwidth,
sqrt(x*x+y*y) / maxlen
);
}
}
}
void draw() {
wd.redraw();
// curtain depth & center color
float cicle_rotate = (frameCount % 1801) / 10.0 ; cicle_rotate = sin(radians(cicle_rotate));
float cdivz = 2 + cicle_rotate * 2;
float ccolor = map(cicle_rotate, 0, 1, 0, 360);
for (float divz = 0; divz <= pwidth * cdivz * 5; divz += pwidth * cdivz) {
//float divz = 0;
float nl = nl_start;
for (int l = 0; l < pline; l++) {
float nc = nc_start;
for (int c = 0; c < pcolumn; c++) {
int i = l * pcolumn + c;
pt[i].paint(ccolor);
pt[i].fluttering(noise(nc, nl));
pt[i].plotparticle(divz);
nc += 0.007;
}
nl += 0.005;
}
}
nl_start += 0.007;
nc_start += 0.002;
/*
saveFrame("frames/####.png");
if (frameCount >= 1801) {
exit();
}
*/
}
class World {
World() {
}
void redraw() {
background(0, 0, 5);
ambientLight(0, 0, 100);
camera(0, 0, 300,
0, 0, 0,
0, 1, 0);
}
}
class Particle {
Random obj_random;
float pcolor, psatur, pbright;
float sigcenter, sigcurve;
float sx, sy, sz, sweight;
Particle(float x, float y, float w, float s) {
obj_random = new Random();
sx = x;
sy = y;
sz = 0;
sweight = w;
// steep > s > tender
sigcenter = 2;
sigcurve = 1.0 + abs(gaussdist(0, s * s * 20, s * s * 10));
pcolor = 0;
psatur = 0;
pbright = 0;
}
void paint(float center_color) {
pbright = 30 + 30 * sigmoid(gaussdist(0.5, 0.5, 0.25), sigcenter, sigcurve);
psatur = 30 + 40 * sigmoid(gaussdist(0.5, 0.5, 0.25), sigcenter, sigcurve);
pcolor = center_color + 80 - map(sigmoid(gaussdist(0.5, 0.5, 0.1), sigcenter, sigcurve), 0, 1, 0, 160);
if (pcolor > 360) {
pcolor -= 360;
} else if (pcolor < 0) {
pcolor += 360;
}
}
void fluttering(float noise_sz) {
sz = map(noise_sz, 0, 1, -50, 50);
}
void plotparticle(float divz) {
pushMatrix();
translate(sx, sy, sz + divz);
fill(
pcolor,
psatur,
pbright,
100
);
// rect(0, 0, sweight, sweight);
ellipse(0, 0, sweight*0.8, sweight*0.8);
popMatrix();
}
float sigmoid(float x, float pcenter, float pgradient) {
/**
Sigmoid function
1.parameters.
x : x value
pcenter : center of curve. 1 - 1 / pcenter
ex. 10 > pcenter > 1 : 0.9 > center of curve > 0
pgradient : gradient of curve.
ex. 20 > pgradient > 4 : steep > gradient of curve > gentle
2.return.
y value
**/
float modx = pcenter * (x - 1) + 1;
return (float)(1.0 / (1.0 + Math.exp(-modx * pgradient)));
}
float gaussdist(float pmean, float plimit, float pdevi) {
/**
Gaussian distribution
1.parameters.
pmean : mean value
plimit : max value of abs(deviation)
ex. plimit >= 0
pmean = 0.5, plimit = 0.5 -> return value = from 0.0 to 1.0
pdevi : standard deviation value
ex. good value? -> pdevi = plimit / 2
2.return.
gaussian distribution
**/
if (plimit == 0) {
return pmean;
}
float gauss = (float) obj_random.nextGaussian() * pdevi;
// not good idea
if (abs(gauss) > plimit) {
gauss = pow(plimit, 2) / gauss;
}
return pmean + gauss;
}
}
/*
Copyright (C) 2017- deconbatch
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
*/


