Skip to content

Instantly share code, notes, and snippets.

@dribnet
Last active May 7, 2019 07:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 32 You must be signed in to fork a gist
  • Save dribnet/e8f7f19f503af19d7591a9723e67db8a to your computer and use it in GitHub Desktop.
Save dribnet/e8f7f19f503af19d7591a9723e67db8a to your computer and use it in GitHub Desktop.
Parametric Faces
license: mit

PS1 MDDN 342 2016

This is my final solution to PS1. I chose to make faces that reminded me vaguely of my avatar. After some experimenting, I chose to allow only slight variations in tilt. The mouth generally is closed and never opens too far. I decided to allow mutant version of my face with either one or three eyes, but these are very rare.

When viewed as a group, they seem to be a crowd all staring up the sky in disbelief.

// note: this file is poorly named - it can generally be ignored.
// helper functions below for supporting blocks/purview
function saveBlocksImages(doZoom) {
if(doZoom == null) {
doZoom = false;
}
// 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);
if(doZoom) {
// 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);
}
else {
// now scaledown
var full_width = this.canvas.width;
var full_height = this.canvas.height;
context.drawImage(this.canvas, 0, 0, full_width, full_height, 0, 0, 230, 120);
}
imageData = offscreenCanvas.toDataURL('image/png');
imageData = imageData.replace('image/png', downloadMime);
p5.prototype.downloadFile(imageData, 'thumbnail.png', 'png');
}
function resetFocusedRandom() {
return Math.seedrandom(arguments);
}
function focusedRandom(min, max, focus, mean) {
// console.log("hello")
if(max === undefined) {
max = min;
min = 0;
}
if(focus === undefined) {
focus = 1.0;
}
if(mean === undefined) {
mean = (min + max) / 2.0;
}
if(focus == 0) {
return d3.randomUniform(min, max)();
}
else if(focus < 0) {
focus = -1 / focus;
}
sigma = (max - mean) / focus;
val = d3.randomNormal(mean, sigma)();
if (val > min && val < max) {
return val;
}
return d3.randomUniform(min, max)();
}
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.2/p5.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.2/addons/p5.dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.0/seedrandom.min.js"></script>
<script src="https://d3js.org/d3-random.v1.min.js"></script>
<script language="javascript" type="text/javascript" src="focusedRandom.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">
<div id="canvasContainer"></div>
</body>
var main_canvas;
var canvasWidth = 960;
var canvasHeight = 500;
var canvasWidth = 960;
var canvasHeight = 500;
function setup () {
// create the drawing canvas, save the canvas element
main_canvas = createCanvas(canvasWidth, canvasHeight);
// rotation in degrees (more slider friendly)
angleMode(DEGREES);
curRandomSeed = int(focusedRandom(0, 1000));
// position each element on the page
main_canvas.parent('canvasContainer');
}
function changeRandomSeed() {
curRandomSeed = curRandomSeed + 1;
}
var colorFront = [151, 102, 52];
var colorBack = [225, 206, 187];
function drawFace(x, y, w, h, tilt_value, eye_value, mouth_value) {
resetMatrix();
translate(x, y);
rotate(tilt_value);
var extent = 0;
if(h < w) {
extent = h / 2;
}
else {
extent = w / 2;
}
var scale = extent / 220.0;
fill(colorFront);
ellipse(0, 0, 300 * scale, 400 * scale);
// eyes
if (eye_value === 1 || eye_value == 3) {
fill(colorBack);
ellipse( 0, -80 * scale, 50 * scale, 30 * scale);
fill(colorFront);
ellipse(-10 * scale, -80 * scale, 20 * scale, 20 * scale);
}
if (eye_value >= 2) {
fill(colorBack);
ellipse(-50 * scale, -80 * scale, 50 * scale, 30 * scale);
ellipse( 50 * scale, -80 * scale, 50 * scale, 30 * scale);
fill(colorFront);
ellipse(-60 * scale, -80 * scale, 20 * scale, 20 * scale);
ellipse( 40 * scale, -80 * scale, 20 * scale, 20 * scale);
}
// mouth
fill(colorBack);
ellipse(0 * scale, 70 * scale, 150 * scale, mouth_value * scale);
}
function getRandomNumberOfEyes() {
random_result = focusedRandom(0, 100);
if(random_result < 8) {
return 1;
}
else if(random_result > 96) {
return 3;
}
else {
return 2;
}
}
var lastSwapTime = 0;
var millisPerSwap = 2000;
function draw () {
var millisNow = millis();
if(millisNow > lastSwapTime + millisPerSwap) {
changeRandomSeed();
lastSwapTime = millisNow;
}
background(colorBack);
fill(colorFront);
stroke(95, 52, 8)
resetFocusedRandom(curRandomSeed);
var w = canvasWidth / 5;
var h = canvasHeight / 3;
for(var i=0; i<3; i++) {
for(var j=0; j<5; j++) {
var y = h/2 + h*i;
var x = w/2 + w*j;
tilt_value = focusedRandom(-70, 90, 12);
eye_value = getRandomNumberOfEyes();
mouth_value = focusedRandom(0, 50, 4, 1);
drawFace(x, y, w, h, tilt_value, eye_value, mouth_value);
}
}
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
else if (key == '@') {
saveBlocksImages(true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment