Created
April 21, 2014 15:17
-
-
Save nossidge/11145652 to your computer and use it in GitHub Desktop.
Naturalistic cross-hatching effect
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Scratchy rectangle shapes. | |
// Lines with origin and destination points that are subtly randomised around a point. | |
// Creates a naturalistic cross-hatching effect. | |
// Save as animated GIF | |
// Requires gifAnimation Processing Library | |
// http://www.extrapixel.ch/processing/gifAnimation/ | |
import gifAnimation.*; | |
GifMaker gifExport; | |
boolean saveToGif = false; | |
int gifFrameCount = 0; | |
int gifFrameDelay = 1000; | |
//////////////////////////////////////////////////////////////////////////////// | |
// GIF stuff. | |
void gifCreateNew() { | |
if (saveToGif) { | |
gifExport = new GifMaker(this, System.currentTimeMillis() + ".gif"); | |
gifExport.setRepeat(0); | |
gifFrameCount = 0; | |
} | |
} | |
void gifAddFrame() { | |
if (saveToGif) { | |
gifExport.setDelay(gifFrameDelay); | |
gifExport.addFrame(); | |
gifFrameCount++; | |
} | |
} | |
void gifSave() { | |
if (saveToGif) { | |
gifExport.setDelay(gifFrameDelay); | |
gifExport.finish(); | |
saveToGif = false; | |
println("Frames saved: " + gifFrameCount ); | |
} | |
} | |
void keyPressed(){ | |
switch( int(key) ) { | |
case 112: save(System.currentTimeMillis() + ".png"); break; // P= save as png | |
case 114: saveToGif=true; gifCreateNew(); break; // R= record new animated gif | |
case 115: gifSave(); break; // S= save the current gif | |
} | |
} | |
void stop() { | |
gifSave(); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
void setup() { | |
frameRate(1); | |
size(900,700); | |
strokeWeight(0); | |
stroke(0); | |
draw(); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
void draw() { | |
background(103); | |
final int shapeType = 5; | |
// 1) Difference between border before fill or border after fill. | |
if ( shapeType == 1 ) { | |
float zoom = 0.6; | |
size(int(900*zoom),int(700*zoom)); | |
ScratchyRect rectLBorderUnder = new ScratchyRect(100*zoom,100*zoom,300*zoom,500*zoom,5,true,30,33,true,235,2,true,true); | |
ScratchyRect rectRBorderOver = new ScratchyRect(500*zoom,100*zoom,300*zoom,500*zoom,5,true,30,33,true,235,2,false,true); | |
rectLBorderUnder.draw(); | |
rectRBorderOver.draw(); | |
} | |
if ( shapeType == 2 ) { | |
float zoom = 0.6; | |
size(int(800*zoom),int(700*zoom)); | |
ScratchyRect bigRectN = new ScratchyRect(100*zoom,100*zoom,600*zoom,250*zoom,5,true,30,33,true,255,2,false,false); | |
bigRectN.drawBorderE = false; | |
bigRectN.drawBorderS = false; | |
bigRectN.draw(); | |
ScratchyRect bigRectE = new ScratchyRect(400*zoom,100*zoom+3,300*zoom,500*zoom,5,true,30,33,true,255,2,false,false); | |
bigRectE.drawBorderW = false; | |
bigRectE.drawBorderN = false; | |
bigRectE.draw(); | |
} | |
if ( shapeType == 3 ) { | |
float zoom = 1.2; | |
size(int(400*zoom),int(350*zoom)); | |
ScratchyRect bigRectN = new ScratchyRect(50*zoom,50*zoom,300*zoom,125*zoom,5,true,30,33,true,235,2,true,false); | |
bigRectN.drawBorderE = false; | |
bigRectN.drawBorderS = false; | |
bigRectN.draw(); | |
ScratchyRect bigRectE = new ScratchyRect(200*zoom,50*zoom+2,150*zoom,250*zoom,5,true,30,33,true,235,2,true,false); | |
bigRectE.drawBorderW = false; | |
bigRectE.drawBorderN = false; | |
bigRectE.draw(); | |
ScratchyRect bigRectSW = new ScratchyRect(30*zoom,195*zoom,150*zoom,125*zoom,5,true,30,33,true,235,2,true,false); | |
bigRectSW.drawBorderE = false; | |
bigRectSW.drawBorderN = false; | |
bigRectSW.draw(); | |
} | |
// Four quadrants, only outer line borders. | |
if ( shapeType == 4 ) { | |
float zoom = 1.1; | |
size(int(400*zoom),int(350*zoom)); | |
ScratchyRect borderRect = new ScratchyRect(50*zoom,50*zoom,300*zoom,250*zoom,7,true,0,22,false,255,2,true,false); | |
borderRect.draw(); | |
ScratchyRect bigRectNW = new ScratchyRect(50*zoom,50*zoom,150*zoom,125*zoom,5,false,30,33,true,235,2,true,false); | |
bigRectNW.drawBorderN = false; | |
bigRectNW.drawBorderE = false; | |
bigRectNW.drawBorderS = false; | |
bigRectNW.drawBorderW = false; | |
bigRectNW.draw(); | |
ScratchyRect bigRectNE = new ScratchyRect(200*zoom,50*zoom,150*zoom,125*zoom,5,false,30,33,true,235,2,true,false); | |
bigRectNE.drawBorderN = false; | |
bigRectNE.drawBorderE = false; | |
bigRectNE.drawBorderS = false; | |
bigRectNE.drawBorderW = false; | |
bigRectNE.draw(); | |
ScratchyRect bigRectSE = new ScratchyRect(200*zoom,175*zoom,150*zoom,125*zoom,5,false,30,33,true,235,2,true,false); | |
bigRectSE.drawBorderN = false; | |
bigRectSE.drawBorderE = false; | |
bigRectSE.drawBorderS = false; | |
bigRectSE.drawBorderW = false; | |
bigRectSE.draw(); | |
ScratchyRect bigRectSW = new ScratchyRect(50*zoom,175*zoom,150*zoom,125*zoom,5,false,30,33,true,235,2,true,false); | |
bigRectSW.drawBorderN = false; | |
bigRectSW.drawBorderE = false; | |
bigRectSW.drawBorderS = false; | |
bigRectSW.drawBorderW = false; | |
bigRectSW.draw(); | |
} | |
// Mondrian | |
if ( shapeType == 5 ) { | |
float zoom = 4; | |
size(int(100*zoom),int(100*zoom)); | |
background(255); | |
float borderRandomVariance = 3.2; | |
// Draw the colour cells first | |
ScratchyRect rectTopRed = new ScratchyRect(0*zoom,0*zoom,45*zoom,40*zoom,borderRandomVariance,true,0,33,true,color(210,0,0),4,false,false); | |
rectTopRed.drawBorderN = false; | |
rectTopRed.drawBorderW = false; | |
rectTopRed.draw(); | |
ScratchyRect rectBotYellow = new ScratchyRect(0*zoom,65*zoom,10*zoom,35*zoom,borderRandomVariance,true,0,33,true,color(253,209,1),4,false,false); | |
rectBotYellow.drawBorderS = false; | |
rectBotYellow.drawBorderW = false; | |
rectBotYellow.draw(); | |
ScratchyRect rectBotBlue = new ScratchyRect(45*zoom,65*zoom,32.5*zoom,30*zoom,borderRandomVariance,true,0,33,true,color(51,35,93),4,false,false); | |
rectBotBlue.draw(); | |
// Then draw the white | |
ScratchyRect rectTopWhite = new ScratchyRect(45*zoom,0*zoom,55*zoom,40*zoom,borderRandomVariance,true,0,33,true,color(252,243,220),4,false,false); | |
rectTopWhite.drawBorderN = false; | |
rectTopWhite.drawBorderE = false; | |
rectTopWhite.draw(); | |
ScratchyRect rectMidLeft = new ScratchyRect(0*zoom,40*zoom,45*zoom,25*zoom,borderRandomVariance,true,0,33,true,color(252,243,220),4,false,false); | |
rectMidLeft.drawBorderW = false; | |
rectMidLeft.draw(); | |
ScratchyRect rectMidRight = new ScratchyRect(45*zoom,40*zoom,55*zoom,25*zoom,borderRandomVariance,true,0,33,true,color(252,243,220),4,false,false); | |
rectMidRight.drawBorderE = false; | |
rectMidRight.draw(); | |
ScratchyRect rectBotLeftWhite = new ScratchyRect(10*zoom,65*zoom,35*zoom,35*zoom,borderRandomVariance,true,0,33,true,color(252,243,220),4,false,false); | |
rectBotLeftWhite.drawBorderS = false; | |
rectBotLeftWhite.draw(); | |
ScratchyRect rectBotBlueUnder = new ScratchyRect(45*zoom,95*zoom,32.5*zoom,30*zoom,borderRandomVariance,true,0,33,true,color(252,243,220),4,false,false); | |
rectBotBlueUnder.draw(); | |
ScratchyRect rectBotRightWhite = new ScratchyRect(77.5*zoom,65*zoom,22.5*zoom,35*zoom,borderRandomVariance,true,0,33,true,color(252,243,220),4,false,false); | |
rectBotRightWhite.drawBorderS = false; | |
rectBotRightWhite.drawBorderE = false; | |
rectBotRightWhite.draw(); | |
} | |
gifAddFrame(); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// A line whose start and end point randomly "huddles" around fixed start & end points. | |
// Remembers the random variance, so subsequent draw()s will display the same line. | |
// No encapsulation. All variables are exposed. | |
class ScratchyLine { | |
// Position of line. | |
float xPos1, yPos1, xPos2, yPos2; | |
// Random variance for the x/y positions of the line. | |
float randomPosRange = 2; | |
// How many times should we draw over the scratchy lines? | |
int lineIterations = 4; | |
// Colour of the line. | |
color lineColour = 0; | |
// Store the varience of the positions. | |
float[] xPos1Rand; | |
float[] yPos1Rand; | |
float[] xPos2Rand; | |
float[] yPos2Rand; | |
// Empty constructor. | |
ScratchyLine() { | |
calculateRandomNos(); | |
} | |
// Everything constructor. | |
ScratchyLine (float xPos1arg, float yPos1arg, float xPos2arg, float yPos2arg, | |
float randomPosRangeArg, int lineIterationsArg, color lineColourArg) { | |
xPos1 = xPos1arg; | |
yPos1 = yPos1arg; | |
xPos2 = xPos2arg; | |
yPos2 = yPos2arg; | |
randomPosRange = randomPosRangeArg; | |
lineIterations = lineIterationsArg; | |
lineColour = lineColourArg; | |
calculateRandomNos(); | |
} | |
// Calculate the random variance of the positions. | |
void calculateRandomNos() { | |
xPos1Rand = new float[lineIterations]; | |
yPos1Rand = new float[lineIterations]; | |
xPos2Rand = new float[lineIterations]; | |
yPos2Rand = new float[lineIterations]; | |
for (int i = 0; i < lineIterations; i++) { | |
xPos1Rand[i] = random(-randomPosRange,randomPosRange); | |
yPos1Rand[i] = random(-randomPosRange,randomPosRange); | |
xPos2Rand[i] = random(-randomPosRange,randomPosRange); | |
yPos2Rand[i] = random(-randomPosRange,randomPosRange); | |
} | |
} | |
// Draw the line. | |
void draw() { | |
stroke(lineColour); | |
for (int i = 0; i < lineIterations; i++) { | |
line(xPos1+xPos1Rand[i], | |
yPos1+yPos1Rand[i], | |
xPos2+xPos2Rand[i], | |
yPos2+yPos2Rand[i] | |
); | |
} | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// A rect made out of ScratchyLines. Rounded corners not supported. | |
// No encapsulation. All variables are exposed. | |
class ScratchyRect { | |
// Position & size of rectangle. | |
float xPos = 0; | |
float yPos = 0; | |
float xWidth = 50; | |
float yHeight = 50; | |
// Random variance for the x/y positions of the borders. | |
float randomPosRange = 2; | |
// Colour of the borders and the fill. | |
// (Borders are all the same colour) | |
color borderColour = 0; | |
color fillColour = 255; | |
// How many times should we draw over the scratchy lines? | |
int borderIterations = 4; | |
int fillIterations = 2; | |
// Should we fill the interior of the rect? | |
Boolean drawFill = true; | |
// Increment of x and y axis when drawing the fill hatching. | |
// Do be sure that this is greater than zero... | |
int fillLineIncrement = 1; | |
// Should we draw the inside fill before the border, | |
// or the border before the inside fill? | |
Boolean fillBeforeBorder = true; | |
// Should we recalculate the random variances each time we draw? | |
Boolean recalculate = false; | |
Boolean alreadyCalculated = false; // Don't alter this. | |
// Arrays of ScratchyLine objects. | |
ScratchyLine[] borderLines; | |
ScratchyLine[] fillLinesX; | |
ScratchyLine[] fillLinesY; | |
// Draw all / individual borders. | |
// ( Should I use both "drawBorders" and "drawBorderS"? | |
// Java is case sensitive, but still... ) | |
Boolean drawBorders = true; | |
Boolean drawBorderN = true; | |
Boolean drawBorderS = true; | |
Boolean drawBorderE = true; | |
Boolean drawBorderW = true; | |
// Empty constructor. | |
ScratchyRect() {} | |
// Everything constructor. | |
ScratchyRect (float xPosArg, float yPosArg, float xWidthArg, float yHeightArg, | |
float randomPosRangeArg, | |
Boolean drawBordersArg, color borderColourArg, int borderIterationsArg, | |
Boolean drawFillArg, color fillColourArg, int fillIterationsArg, | |
Boolean fillBeforeBorderArg, Boolean recalculateArg) { | |
xPos = xPosArg; | |
yPos = yPosArg; | |
xWidth = xWidthArg; | |
yHeight = yHeightArg; | |
randomPosRange = randomPosRangeArg; | |
borderIterations = borderIterationsArg; | |
fillIterations = fillIterationsArg; | |
drawBorders = drawBordersArg; | |
borderColour = borderColourArg; | |
drawFill = drawFillArg; | |
fillColour = fillColourArg; | |
fillBeforeBorder = fillBeforeBorderArg; | |
recalculate = recalculateArg; | |
} | |
void draw() { | |
// Number of borders to draw. | |
int intN = (drawBorderN) ? 1 : 0; | |
int intS = (drawBorderS) ? 1 : 0; | |
int intE = (drawBorderE) ? 1 : 0; | |
int intW = (drawBorderW) ? 1 : 0; | |
int borderCount = intN + intS + intE + intW; | |
if (recalculate || !alreadyCalculated) { | |
borderLines = new ScratchyLine[borderCount]; | |
// Only draw the specified borders. | |
int index = 0; | |
if (drawBorderW) borderLines[index++] = new ScratchyLine(xPos,yPos,xPos,yPos+yHeight,randomPosRange,borderIterations,borderColour); | |
if (drawBorderN) borderLines[index++] = new ScratchyLine(xPos,yPos,xPos+xWidth,yPos,randomPosRange,borderIterations,borderColour); | |
if (drawBorderS) borderLines[index++] = new ScratchyLine(xPos+xWidth,yPos+yHeight,xPos,yPos+yHeight,randomPosRange,borderIterations,borderColour); | |
if (drawBorderE) borderLines[index++] = new ScratchyLine(xPos+xWidth,yPos+yHeight,xPos+xWidth,yPos,randomPosRange,borderIterations,borderColour); | |
} | |
// Draw the borders. | |
if (drawBorders && fillBeforeBorder) { | |
for (int i = 0; i < borderCount; i++) { | |
borderLines[i].draw(); | |
} | |
} | |
// Draw a fill line for each X and Y axis line, plus fillLineIncrement. | |
if (drawFill) { | |
// Make sure it hasn't been set to a foolish value. | |
if (fillLineIncrement <= 0) fillLineIncrement = 1; | |
if (recalculate || !alreadyCalculated) { | |
fillLinesX = new ScratchyLine[int(xWidth)]; | |
for (int x = 0; x < int(xWidth); x=x+fillLineIncrement) { | |
fillLinesX[x] = new ScratchyLine(xPos+x,yPos,xPos+x,yPos+yHeight,2,fillIterations,fillColour); | |
} | |
fillLinesY = new ScratchyLine[int(yHeight)]; | |
for (int y = 0; y < int(yHeight); y=y+fillLineIncrement) { | |
fillLinesY[y] = new ScratchyLine(xPos,yPos+y,xPos+xWidth,yPos+y,2,fillIterations,fillColour); | |
} | |
} | |
// Draw them! | |
for (int x = 0; x < int(xWidth); x=x+fillLineIncrement) { | |
fillLinesX[x].draw(); | |
} | |
for (int y = 0; y < int(yHeight); y=y+fillLineIncrement) { | |
fillLinesY[y].draw(); | |
} | |
alreadyCalculated = true; | |
} | |
// Draw the borders. | |
if (drawBorders && !fillBeforeBorder) { | |
for (int i = 0; i < borderCount; i++) { | |
borderLines[i].draw(); | |
} | |
} | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment