block by dribnet 1dbdb24efef11d660fd9e98abfa56c61

PS1 MDDN 342 2016

Full Screen

PS1 MDDN 342 2016 - Goblins

The goal of this project was to create a program that generated a series of distinct faces. ‘Goblins’ achieves this by creating sketchy goblin-like faces that have a wide variation in facial expression, giving each face a unique personality. The final arrangement depicts a slumber party of ‘sleeping’ goblins, with some king goblins amongst them. While the majority of the goblins are resting, some are awake and exhibiting a wide variety of emotions.

index.html

<head>
    <script src="//cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.2/p5.js"></script>
    <script src="//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>

focusedRandom.js

function resetFocusedRandom() {
  return Math.seedrandom(arguments);
}

function focusedRandom(min, max, focus, mean) {
  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)();
}

readme.purview_helper.js

// 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 = 1550*3;
  offscreenCanvas.height = 1140*3;
  var context = offscreenCanvas.getContext('2d');
  // background is flat white
  context.fillStyle="#FFFFFF";
  context.fillRect(0, 0, 1550*3, 1140*3);
  context.drawImage(this.canvas, 0, 0, 1550*3, 1140*3);
  // save to browser
  var downloadMime = 'image/octet-stream';
  var imageData = offscreenCanvas.toDataURL('image/png');
  imageData = imageData.replace('image/png', downloadMime);
  p5.prototype.downloadFile(imageData, 'canvas.png', 'png');

/*
  // 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');
  */
}

sketch.js

var main_canvas;
var eyebrow_slider;
var pupil_slider;
var jaw_slider;

var faces = [];
var randVal = 0.18;
var faceScale = 100;

var rows = 8*3;
var cols = 5*3;

function setup () {
  main_canvas = createCanvas(1550*3, 1140*3);
  rectMode(CENTER);

  angleMode(DEGREES);

  for (i = 0; i < rows; i++){
    faces[i] = []
    for (j = 0; j < cols; j++){
      var face = drawHead(int(random(3*faceScale/4.0, faceScale)));
      faces[i].push(face);
    }
  }
}

function draw () {
  background(87, 82, 97);
  fill(255);
  stroke(0);
  strokeWeight(1);

  for (i = 0; i < rows; i++){
    for (j = 0; j < cols; j++){
      push();
      if (i % 2 == 0) {
        translate(25 + faceScale + (2*(faceScale-10)) * i, 45 + faceScale + ((2*faceScale) * j));
      } else {
        translate(25 + faceScale + (2*(faceScale-10)) * i, 45 + (1.5*faceScale) + ((2*faceScale) * j));
      }
      faces[i][j]();
      pop();
    }
  }
  noLoop();  
}

function recreateFaces () {
  faces = [];
  for (i = 0; i < rows; i++){
    faces[i] = []
    for (j = 0; j < cols; j++){
      var face = drawHead(int(random(3*faceScale/4.0, faceScale)));
      faces[i].push(face);
    }
  }
}

function drawHead (scalar) {
  var coords = [(-0.1 + random(-randVal, randVal)) * scalar, 
                (-1.0 + random(-randVal, randVal)) * scalar, 
                (-0.6 + random(-randVal, randVal)) * scalar, 
                (-0.6 + random(-randVal, randVal)) * scalar,
                (-0.8 + random(-randVal, randVal)) * scalar,
                (-0.7 + random(-randVal, randVal)) * scalar,
                (0.5 + random(-randVal, randVal)) * scalar,
                (1.0 + random(-randVal, randVal)) * scalar,
                (0.7 + random(-randVal, randVal)) * scalar,
                (0.5 + random(-randVal, randVal)) * scalar,
                (0.6 + random(-randVal, randVal)) * scalar,
                (0.4 + random(-randVal, randVal)) * scalar,
                (-0.7 + random(-randVal, randVal)) * scalar];

  var eyelid = focusedRandom(-10, 60, 50, -10);
  var mouthval = int(random(3));
  var pupil = focusedRandom(1,6, 5, 2);

  var crownState = random(1);
  var beardState = random(1);
  
  var col = color(random(160, 220), 180, random(210, 245));
  //var col = color(random(210, 235), random(160, 210), 140);

  var pupilOffset = random(-4, 4);
  var eye1 = drawEye(coords[5] + scalar/6.0, coords[6] - 2*scalar/15.0, scalar/3.0, 2*scalar/5.0, pupilOffset, 1);
  var eyelid1 = drawEyelids(coords[5] + scalar/6.0, coords[6] - 2*scalar/15.0, scalar/3.0, 2*scalar/5.0, random(-25, 25), col);

  var eye2 = drawEye(coords[8] - 4*scalar/15.0, coords[9] - 2*scalar/15.0, scalar/2.0, 3*scalar/5.0, pupilOffset, 0); 
  var eyelid2 = drawEyelids(coords[8] - 4*scalar/15.0, coords[9] - 2*scalar/15.0, scalar/2.0, 3*scalar/5.0, random(-25, 25), col);

  var mouth = drawMouth(coords[5] + scalar/6.0 + (coords[8] - coords[5] - 2*scalar/5.0)/2.0, coords[7] - scalar/5.0, 2 * abs(coords[8] - coords[5] - 13*scalar/15.0)/3.0, 2*scalar/15.0);   
  var beard = drawBeard(coords[5] + scalar/6.0 + (coords[8] - coords[5] - 2*scalar/5.0)/2.0, coords[7] - scalar/5.0);
  var nose = drawNose(coords[5] + scalar/12.0 + (coords[8] - coords[5] - 2*scalar/5.0)/2.0, coords[7] - 2*scalar/5.0, abs(coords[8] - coords[5] - 13*scalar/15.0)/2.0, 2*scalar/15.0);

  var ears = drawEars(coords, scalar/5.0, 2*scalar/5.0);  

  var head = drawHeadShape(coords);  
  var crown = drawCrown(coords);

  var rotAngle = random(-18,18);

  return function() {
    push();
    rotate(rotAngle);

    push();
    fill(col);
    sketchyStyle(ears);

    //head
    sketchyStyle(head);
    pop();

    //crown
    if (crownState > 0.95) {
      crown(1);
      push();
      noFill();
      strokeWeight(1);
      translate(0, 1);
      crown(0);
      translate(0, -2);
      crown(0);
      pop();
    }

    eye1(pupil, 1);

    push();
    noFill();
    strokeWeight(1);
    rotate(1);
    eye1(pupil, 0);
    rotate(-2);
    eye1(pupil, 0);
    pop();

    eyelid1(eyelid, 1);

    push();
    noFill();
    strokeWeight(1);
    rotate(1);
    eyelid1(eyelid, 0);
    rotate(-2);
    eyelid1(eyelid, 0);
    pop();

    eye2(pupil, 1);

    push();
    noFill();
    strokeWeight(1);
    rotate(1);
    eye2(pupil, 0);
    rotate(-2);
    eye2(pupil, 0);
    pop();

    eyelid2(eyelid, 1);

    push();
    noFill();
    strokeWeight(1);
    rotate(1);
    eyelid2(eyelid, 0);
    rotate(-2);
    eyelid2(eyelid, 0);
    pop();

    mouth(mouthval, 1);

    push();
    strokeWeight(1);
    translate(0, 2);
    mouth(mouthval, 0);
    translate(0, -4);
    mouth(mouthval, 0);
    pop();

    if (beardState > 0.4) {
      beard();
      push();
      strokeWeight(1);
      translate(0, 2);
      beard();
      translate(0, -4);
      beard();
      pop();
    }

    nose();
    push();
    strokeWeight(1);
    translate(0, 1);
    nose();
    translate(0, -2);
    nose();
    pop();

    pop();
  }
}

function sketchyStyle (object) {
  object();
  push();
  noFill();
  strokeWeight(1);
  rotate(1);
  object();
  rotate(-2);
  object();
  rotate(2)
  translate(0, -3);
  stroke(50);
  object();
  pop();
}

function drawCrown (coords) {
  var ht = random(20, 70);
  var wd = random(20, 60);
  var baseHt = 30;
  return function(fillState) {
    push();
    if (fillState == 1) {
      fill(255,255,100);
    }
    beginShape();
    vertex(coords[0] - wd/2, coords[1] + baseHt);
    vertex(coords[0] - wd/2, coords[1] - (ht-baseHt));
    vertex(coords[0] - wd/4, coords[1] - (ht/2-baseHt));
    vertex(coords[0], coords[1] - (ht-baseHt));
    vertex(coords[0] + wd/4, coords[1] - (ht/2-baseHt));
    vertex(coords[0] + wd/2, coords[1] - (ht-baseHt));
    vertex(coords[0] + wd/2, coords[1] + baseHt);
    vertex(coords[0] - wd/2, coords[1] + baseHt);
    endShape();
    pop();
  }
}

function drawHeadShape (coords) {
  return function() {
    beginShape();
    curveVertex(coords[11], coords[12]);
    curveVertex(coords[0], coords[1]);
    curveVertex(coords[2], coords[3]);
    curveVertex(coords[4], 0);
    curveVertex(coords[5], coords[6]);
    curveVertex(0, coords[7]);
    curveVertex(coords[8], coords[9]);
    curveVertex(coords[10], 0);
    curveVertex(coords[11], coords[12]);
    curveVertex(coords[0], coords[1]);
    curveVertex(coords[2], coords[3]);
    endShape();
  }  
}
function drawEars (coords, wd, ht) {
  return function() {
    ellipse(coords[5], coords[6], wd, ht);
    ellipse(coords[8], coords[9], wd, ht);
  }  
}

function drawNose (x, y, wd, ht) {
  return function() {
    push();
    noFill();
    arc(x, y, wd, ht, 0, 180);
    arc(x - abs(wd/2.0), y + 6, wd/4.0, ht/2.0, 10, 190);
    arc(x + abs(wd/2.0), y + 6, wd/4.0, ht/2.0, -10, 180);
    pop();
  }
}

function drawEye (x, y, wd, ht, offset, lefteye) {
  return function(pupil, fillState) {
    push();
    noFill();
    if (fillState == 1) {
      if (lefteye == 1) {
        arc(x, y, wd, ht*1.5, 0, 68);
        arc(x, y, wd, ht*1.2, 0, 68);
      } else {
        arc(x, y, wd, ht*1.5, 112, 180);
        arc(x, y, wd, ht*1.2, 112, 180);
      }
    }
    if (fillState == 1) {
      fill(255);
    }
  	ellipse(x, y, wd, ht);
    if (fillState == 1) {
      fill(0);
    }
    var mult = offset/(abs(offset));
  	ellipse(x + (wd/10.0*offset) - ((offset/8.0) * pupil * wd/20.0), y, pupil * wd/10.0, pupil * ht/10.0);
    pop();
  }
}

function drawEyelids (x, y, wd, ht, angle, lidCol) {
  return function(eyelid, fillState) {
    push();
    if (fillState == 1) {
      fill(red(lidCol) - 40, green(lidCol) - 40, blue(lidCol) - 40);
    }
    arc(x, y, wd, ht, 190 + eyelid, 350 - eyelid, CHORD);
    arc(x, y, wd, ht, 10 + eyelid, 170 - eyelid, CHORD);

    translate(x, y-(ht/2.0));
    rotate(angle);
    fill(0);
    rect(0, 0, wd, 5);
    pop();
  }
}

function drawMouth (x, y, wd, ht) {
  return function(expression, strokeState) {
  	push();
  	noFill();
  	stroke(0);
    if (strokeState == 1) {
  	 strokeWeight(3);
    }
  	if (expression == 0) {
  		arc(x, y, wd, ht, 0, 180);
  	} else if (expression == 1) {
  		arc(x, y, wd, ht, 180, 360);
    } else {
      push();
      fill(0);
      strokeWeight(1);
      ellipse(x, y, wd, ht)
      pop();
  	}
    pop();
  }
}

function drawBeard (x, y) {
  return function() {
    push();
    fill(0);
    stroke(30);
    rect(x, y + 18, 2, 6);
    rotate(-4);
    rect(x, y + 16, 1, 4);
    rotate(-4);
    rect(x, y + 16, 1, 2);
    rotate(12);
    rect(x, y + 16, 1, 4);
    rotate(4);
    rect(x, y + 16, 1, 2);
    pop();
  }
}

function keyTyped() {
  if (key == '!') {
    saveBlocksImages();
  }
}

function mousePressed() {
  if (mouseButton == LEFT) {
    recreateFaces();
  }
}