Skip to content

Instantly share code, notes, and snippets.

@jpdenford
Last active October 13, 2016 05:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpdenford/5296444889ce3435a7c4c1280de1d6b4 to your computer and use it in GitHub Desktop.
Save jpdenford/5296444889ce3435a7c4c1280de1d6b4 to your computer and use it in GitHub Desktop.
Feature Drawing
license: mit

PS1 MDDN 342 2016

A clone of an early experiment of PS1.

Generate template faces then draw on top using the mouse.

Middle mouse -> to add a new face at the current mouse position. Left click -> draw lines SPACE -> clear current drawing

// note: this file is poorly named - it can generally be ignored.
// helper functions below for supporting blocks/purview
function saveBlocksImages() {
// generate 960x500 preview.jpg of entire canvas
// TODO: should this be recycled?
var offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = 960;
offscreenCanvas.height = 500;
var context = offscreenCanvas.getContext('2d');
// background is flat white
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 960, 500);
context.drawImage(this.canvas, 0, 0, 960, 500);
// save to browser
var downloadMime = 'image/octet-stream';
var imageData = offscreenCanvas.toDataURL('image/jpeg');
imageData = imageData.replace('image/jpeg', downloadMime);
p5.prototype.downloadFile(imageData, 'preview.jpg', 'jpg');
// generate 230x120 thumbnail.png centered on mouse
offscreenCanvas.width = 230;
offscreenCanvas.height = 120;
// background is flat white
context = offscreenCanvas.getContext('2d');
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 230, 120);
// pixelDensity does the right thing on retina displays
var pd = this._pixelDensity;
var sx = pd * mouseX - pd * 230/2;
var sy = pd * mouseY - pd * 120/2;
var sw = pd * 230;
var sh = pd * 120;
// bounds checking - just displace if necessary
if (sx < 0) {
sx = 0;
}
if (sx > this.canvas.width - sw) {
sx = this.canvas.width - sw;
}
if (sy < 0) {
sy = 0;
}
if (sy > this.canvas.height - sh) {
sy = this.canvas.height - sh;
}
// save to browser
context.drawImage(this.canvas, sx, sy, sw, sh, 0, 0, 230, 120);
imageData = offscreenCanvas.toDataURL('image/png');
imageData = imageData.replace('image/png', downloadMime);
p5.prototype.downloadFile(imageData, 'thumbnail.png', 'png');
}
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.1/p5.js"></script>
<script language="javascript" type="text/javascript" src="readme.purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<style> body {padding: 0; margin: 0;} </style>
</head>
<body style="background-color:white">
</body>
var WIDTH = 960,
HEIGHT = 500;
var colors;
var currentColor;
var faces = [];
//parts
//var myEye;
function setup () {
//initialise global variables
colors = {
green: color(78, 255, 156),
blue: color(65, 253, 255),
black: color(0)
};
currentColor = colors.black;
//myEye = eye("left",1,2);
createCanvas(WIDTH, HEIGHT);
//cover the background
fill(0);
rect(0,0,WIDTH,HEIGHT);
stroke(255);
faces.push(createFace(createVector(WIDTH / 2, HEIGHT / 2), createVector(175, 250), color(255), random(0, 1)));
}
var SIZE = 80;
var time = 0;
var lastMouseX;
var lastMouseY;
var centerPressed = false;
function draw() {
var funkAmt = mouseX / WIDTH;
var pos = createVector(mouseX, mouseY);
//draw things on top
if(mouseIsPressed){
if(mouseButton == LEFT){
if(lastMouseX != 0 || lastMouseY != 0){
line(lastMouseX,lastMouseY,mouseX,mouseY);
}
lastMouseX = mouseX;
lastMouseY = mouseY;
}
if(mouseButton == CENTER){
if(!centerPressed){
var f = createFace(createVector(mouseX, mouseY), createVector(175, 250), color(255), random(0, 1));
faces.push(f);
centerPressed = true;
}
}
} else {
lastMouseX = lastMouseY = 0;
centerPressed = false;
}
//draw faces
faces.forEach(function(elem){
if(!elem.isDrawn){
elem.draw();
elem.isDrawn = true;
}
});
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
} else if (key == '1'){
currentColor = color.black;
} else if (key == '2'){
currentColor = color.blue;
} else if (key == '3'){
currentColor = color.green;
} else if (key == ' '){
rect(0,0,WIDTH,HEIGHT);
faces = [];
}
}
function createFace(position, dimensions, colour, featureOffset){
featureOffset = constrain(featureOffset,0,1.0);
var faceSize = (dimensions.x + dimensions.y) / 2;
//new face object
var f = {
pos: position,
dims: dimensions,
mouthPos: {},
mouthDims: {},
lEyePos: {},
lEyeDims: {},
rEyePos: {},
rEyeDims: {},
nosePos: {},
noseDims: {},
col: colour,
funk: random(),
draw : "drawfunction"
};
//calculate mouth positions
var mX = position.x + (featureOffset * random(-1,1) * (faceSize / 10));
var mY = position.y + (dimensions.y / 3) + (featureOffset * random(-1,1) * (faceSize / 10));
f.mouthPos = createVector(mX, mY);
f.mouthDims = createVector(faceSize/5, faceSize/15);
//calculate eye positions
var lEX = position.x - (dimensions.x / 5) + (featureOffset * random(-1,1) * (faceSize / 10));
var lEY = position.y - (dimensions.y / 7) + (featureOffset * random(-1,1) * (faceSize / 10));
f.lEyePos = createVector(lEX, lEY);
f.lEyeDims = createVector(faceSize/8, faceSize/15);
//r eye
var rEX = position.x + (dimensions.x / 5) + (featureOffset * random(-1,1) * (faceSize / 10));
var rEY = position.y - (dimensions.y / 7) + (featureOffset * random(-1,1) * (faceSize / 10));
f.rEyePos = createVector(rEX, rEY);
f.rEyeDims = createVector(faceSize/8, faceSize/15);
//nose
var nX = position.x + (featureOffset * random(-1,1) * (faceSize / 10));
var nY = position.y + (featureOffset * random(-1,1) * (faceSize / 10));
f.nosePos = createVector(nX, nY);
f.noseDims = createVector(faceSize/8 + random(-1,1) * (faceSize/30), faceSize/8 + random(-1,1) * (faceSize/30));
f.draw = function(){
// head
sketchyEllipse(
this.pos.x,
this.pos.y,
this.dims.x,
this.dims.y,
this.funk
);
// mouth
sketchyEllipse(
this.mouthPos.x,
this.mouthPos.y,
this.mouthDims.x,
this.mouthDims.y,
this.funk
);
// left eye
sketchyEllipse(
this.lEyePos.x,
this.lEyePos.y,
this.lEyeDims.x,
this.lEyeDims.y,
this.funk
);
// right eye
sketchyEllipse(
this.rEyePos.x,
this.rEyePos.y,
this.rEyeDims.x,
this.rEyeDims.y,
this.funk
);
//nose
sketchyEllipse(
this.nosePos.x,
this.nosePos.y,
this.noseDims.x,
this.noseDims.y,
this.funk
);
};
return f;
}
function sketchyEllipse(xOrig, yOrig, wid, hei, funkAmt){
wid = wid * 0.5;
hei = hei * 0.5;
//noise seed based on position
noiseSeed(funkAmt*20);
//set the max funkyness of the ellipse based on size & funk amt
var avgSizeOffset = ((wid + hei) * (constrain(funkAmt, 0, 1.0) * 0.5));
var numPoints = 50;
var x = xOrig + sin(0) * (wid + (noise(0) - 0.5) * avgSizeOffset);
var y = yOrig + cos(0) * (hei + (noise(0) - 0.5) * avgSizeOffset);
var originalX = x,
originalY = y;
for(var i = 0; i < numPoints; i++){
var amt = (i/numPoints) * TWO_PI;
var noiseAmt = noise(amt) - 0.5;
var nextX = xOrig + sin(amt) * (wid + noiseAmt * avgSizeOffset);
var nextY = yOrig + cos(amt) * (hei + noiseAmt * avgSizeOffset);
line(x, y, nextX, nextY);
x = nextX;
y = nextY;
}
//join the start and end
line(x, y, (originalX + x) * 0.5, (originalY + y) * 0.5);
line((originalX + x) * 0.5,(originalY + y) * 0.5, originalX, originalY);
}
/*Maps values 0 -> 1 to 0 -> 1 -> 0 in a zigzag pattern*/
function saw(val){
val = abs(val) % 1.0;
val = val * 2;
if(val > 1.0){
val = 2.0 - val;
}
console.log(val);
return val;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment