Skip to content

Instantly share code, notes, and snippets.

@notmasteryet
Created June 13, 2010 00:53
Show Gist options
  • Save notmasteryet/436232 to your computer and use it in GitHub Desktop.
Save notmasteryet/436232 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<!-- <script src="../../release/processing-0.93.js"></script> -->
<script src="../../processing.js"></script>
<script src="../init.js"></script>
<link rel="stylesheet" href="../style.css"/></head>
<body><h1><a href="http://ejohn.org/blog/processingjs/">Processing.js</a></h1>
<h2>Substrate</h2>
<p>This code was updated from the Java source to work with Processing.js asynchronous image loading. <sup>-F1LT3R</sup></p>
<p>An artistic watercolor visualization by <a href="http://complexification.net/">J. Tarbell</a>.</p>
<p><a href="http://complexification.net/"><b>Original Example:</b> Substrate</a><br>
<script type="application/processing" id="pjs-script">
/* @pjs crisp="true"; */
// Substrate Watercolor
// j.tarbell June, 2004
// Albuquerque, New Mexico
// complexification.net
// Processing 0085 Beta syntax update
// j.tarbell April, 2005
int dimx = 250;
int dimy = 250;
int num = 0;
int maxnum = 100;
// grid of cracks
int[] cgrid;
Crack[] cracks;
// color parameters
int maxpal = 512;
int numpal = 0;
color[] goodcolor = new color[maxpal];
// sand painters
SandPainter[] sands;
// MAIN METHODS ---------------------------------------------
void setup() {
size(250,250);
background(255);
takecolor("data/pollockShimmering.gif");
cgrid = new int[dimx*dimy];
cracks = new Crack[maxnum];
frameRate(100);
}
void draw() {
// crack all cracks
for (int n=0;n<num;n++) {
cracks[n].move();
}
fill(0); rect(5, height - 45, 100, 30);
fill(253); text(nf(frameRate, 0, 1) + " fps", 10, height - 25);
}
void mousePressed() {
begin();
}
// METHODS --------------------------------------------------
void makeCrack() {
if (num<maxnum) {
// make a new crack instance
cracks[num] = new Crack();
num++;
}
}
void begin() {
randomSeed(123);
// erase crack grid
for (int y=0;y<dimy;y++) {
for (int x=0;x<dimx;x++) {
cgrid[y*dimx+x] = 10001;
}
}
// make random crack seeds
for (int k=0;k<16;k++) {
int i = int(random(dimx*dimy-1));
cgrid[i]=int(random(360));
}
// make just three cracks
num=0;
for (int k=0;k<3;k++) {
makeCrack();
}
background(255);
}
// COLOR METHODS ----------------------------------------------------------------
color somecolor() {
// pick some random good color
return goodcolor[int(random(numpal))];
}
void takecolor(String fn) {
PImage b;
b = loadImage(fn, null, function(){
image(b,0,0);
for (int x=0;x<b.width;x++){
for (int y=0;y<1;y++) {
color c = get(x,y);
boolean exists = false;
for (int n=0;n<numpal;n++) {
if (c==goodcolor[n]) {
exists = true;
break;
}
}
if (!exists) {
// add color to pal
if (numpal<maxpal) {
goodcolor[numpal] = c;
numpal++;
}
}
}
}
begin();
});
}
// OBJECTS -------------------------------------------------------
class Crack {
float x, y;
float t; // direction of travel in degrees
// sand painter
SandPainter sp;
Crack() {
// find placement along existing crack
findStart();
sp = new SandPainter();
}
void findStart() {
// pick random point
int px=0;
int py=0;
// shift until crack is found
boolean found=false;
int timeout = 0;
while ((!found) || (timeout++>1000)) {
px = int(random(dimx));
py = int(random(dimy));
if (cgrid[py*dimx+px]<10000) {
found=true;
}
}
if (found) {
// start crack
int a = cgrid[py*dimx+px];
if (random(100)<50) {
a-=90+int(random(-2,2.1));
} else {
a+=90+int(random(-2,2.1));
}
startCrack(px,py,a);
} else {
//println("timeout: "+timeout);
}
}
void startCrack(int X, int Y, int T) {
x=X;
y=Y;
t=T;//%360;
x+=0.61*cos(t*PI/180);
y+=0.61*sin(t*PI/180);
}
void move() {
// continue cracking
x+=0.42*cos(t*PI/180);
y+=0.42*sin(t*PI/180);
// bound check
float z = 0.33;
int cx = int(x+random(-z,z)); // add fuzz
int cy = int(y+random(-z,z));
// draw sand painter
regionColor();
// draw black crack
stroke(0,85);
point(x+random(-z,z),y+random(-z,z));
if ((cx>=0) && (cx<dimx) && (cy>=0) && (cy<dimy)) {
// safe to check
if ((cgrid[cy*dimx+cx]>10000) || (abs(cgrid[cy*dimx+cx]-t)<5)) {
// continue cracking
cgrid[cy*dimx+cx]=int(t);
} else if (abs(cgrid[cy*dimx+cx]-t)>2) {
// crack encountered (not self), stop cracking
findStart();
//makeCrack();
}
} else {
// out of bounds, stop cracking
findStart();
//makeCrack();
}
}
void regionColor() {
// start checking one step away
float rx=x;
float ry=y;
boolean openspace=true;
// find extents of open space
while (openspace) {
// move perpendicular to crack
rx+=0.81*sin(t*PI/180);
ry-=0.81*cos(t*PI/180);
int cx = int(rx);
int cy = int(ry);
if ((cx>=0) && (cx<dimx) && (cy>=0) && (cy<dimy)) {
// safe to check
if (cgrid[cy*dimx+cx]>10000) {
// space is open
} else {
openspace=false;
}
} else {
openspace=false;
}
}
// draw sand painter
sp.render(rx,ry,x,y);
}
}
class SandPainter {
color c;
float g;
SandPainter() {
c = somecolor();
g = random(0.01,0.1);
}
void render(float x, float y, float ox, float oy) {
// modulate gain
g+=random(-0.050,0.050);
float maxg = 1.0;
if (g<0) g=0;
if (g>maxg) g=maxg;
// calculate grains by distance
//int grains = int(sqrt((ox-x)*(ox-x)+(oy-y)*(oy-y)));
int grains = 64;
// lay down grains of sand (transparent pixels)
float w = g/(grains-1);
for (int i=0;i<grains;i++) {
float a = 0.1-i/(grains*10.0);
stroke(red(c),green(c),blue(c),a*256);
point(ox+(x-ox)*sin(sin(i*w)),oy+(y-oy)*sin(sin(i*w)));
}
}
}
// j.tarbell June, 2004
// Albuquerque, New Mexico
// complexification.net
</script><canvas width="250" height="250"></canvas></p>
<div style="height:0px;width:0px;overflow:hidden;"><img src="data/pollockShimmering.gif" id="pollockShimmering.gif"/></div>
<pre id="pjs-code"></pre>
<script>
document.getElementById("pjs-code").innerHTML = document.getElementById("pjs-script").text.replace("<", "&lt;").replace(">", "&gt;");
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment