Skip to content

Instantly share code, notes, and snippets.

@carlgordon64
Forked from dribnet/.block
Last active August 5, 2022 21:00
Show Gist options
  • Save carlgordon64/260c6dce45cff5230a3230f594bdcd89 to your computer and use it in GitHub Desktop.
Save carlgordon64/260c6dce45cff5230a3230f594bdcd89 to your computer and use it in GitHub Desktop.
Parametric Faces
license: mit

CARL GORDON MEDIA

P1 FINAL

This is my final solution to PS1. I ended up developing my final faces into a similar version to my original avatar. I was really aiming to create a code that would never produce that same face twice, to achieve this I had to add a few more parameters including: Face Position, Eye Size, Brow Size, Ear Size, Lip Size, and Nose Size. I wanted the avatars to look semi realistic / diverse so anyone could use it to produce a cartoon looking vaguely like themselves.

// 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');
}
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.1/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>
<link href='https://fonts.googleapis.com/css?family=Roboto:100,300' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body style="background-color:white">
</body>
<script>
</script>
{
"commits": [
{
"sha": "0000000000000000000000000000000000000012",
"name": "final_version"
},
{
"sha": "0000000000000000000000000000000000000011",
"name": "interaction_2"
},
{
"sha": "0000000000000000000000000000000000000010",
"name": "interaction_1"
},
{
"sha": "0000000000000000000000000000000000000009",
"name": "distribution_2"
},
{
"sha": "0000000000000000000000000000000000000008",
"name": "distribution_1"
},
{
"sha": "0000000000000000000000000000000000000007",
"name": "randomizer_3"
},
{
"sha": "0000000000000000000000000000000000000006",
"name": "randomizer_2"
},
{
"sha": "0000000000000000000000000000000000000005",
"name": "randomizer_1"
},
{
"sha": "0000000000000000000000000000000000000004",
"name": "drawing_styles_3"
},
{
"sha": "0000000000000000000000000000000000000003",
"name": "drawing_styles_2"
},
{
"sha": "0000000000000000000000000000000000000002",
"name": "drawing_styles_1"
},
{
"sha": "0000000000000000000000000000000000000001",
"name": "self_portrait"
}
]
}
///PS1 SELF PORTRAIT CARLGORDON 300308407
var a = 0; //variable to be controlled
var b = 0; //variable to be controlled
var c = 0; //variable to be controlled
var c2 = 0; //variable to be controlled
var d = 0; //variable to be controlled
var e = 0; //variable to be controlled
var f = 0; //variable to be controlled
var g = 0; //variable to be controlled
var h = 0; //variable to be controlled
var i = 0; //variable to be controlled
var demo =0;
var random1 =0;
var random2 =0;
var random3 =0;
var random4 =0;
var random5 =0;
var random6 =0;
var random7 =0;
var random8 =0;
var random9 =0;
var random10 =0;
function setup () {
createCanvas(960, 520);
background(255);
}
function draw(){
background(255);
for($i=0; $i<=width; $i+=width/5){
stroke(200);
strokeWeight(1);
line($i,10,$i,height-10);
}
for($iy=height/3; $iy<=height; $iy+=height/3){
line(10,$iy,width-10,$iy);
}
//text
/*
fill(0);
text(mouseX,100,100, mouseX);
text(mouseY,100,130, mouseY);
text(demo,100,180, mouseY);
text(random1,100,200, mouseY);
*/
//AVATARS
//top row
drawFace(0-width/5,-height/3+10,random2,random5,random9,random10,random4);
drawFace(0-(width/5*2),-height/3+10,random9,random1,random10,random9,random2);
drawFace(0,-height/3+10,random3,random3,random7,random4,random5);
drawFace(0+width/5,-height/3+10,random6,random3,random1,random3,random6);
drawFace(0+(width/5*2),-height/3+10,random7,random5,random3,random2,random10);
//middle row
drawFace(0-width/5,10,random2,random2,random8,random6,random5);
drawFace(0-(width/5*2),10,random6,random9,random3,random2,random9);
drawFace(0,10,random7,random7,random3,random9,random3);
drawFace(0+width/5,10,random3,random10,random1,random6,random5);
drawFace(0+(width/5*2),10,random6,random3,random3,random2,random9);
//bottom row
drawFace(0-width/5,height/3+20,random7,random9,random5,random3,random6);
drawFace(0-(width/5*2),height/3+20,random1,random4,random6,random2,random10);
drawFace(0,height/3+20,random3,random7,random3,random4,random5);
drawFace(0+width/5,height/3+20,random2,random10,random1,random7,random6);
drawFace(0+(width/5*2),height/3+20,random9,random7,random3,random10,random1);
//END AVATARS
}
//////DRAW FACE
function drawFace (x1,y1,Skin,Hair,rand,rand2,rand3) {
$CanvasPosX=x1;
$CanvasPosY=y1;
if(mouseY<=200){
mouseY=200;
}
if(mouseX>=570){
mouseX=570;
}
//shirt color variables
/////////DRAW FACE FUNCTION
if (mouseIsPressed) {
fill(255);
random1=focusedRandom(0,1,2);
random2=focusedRandom(0,1,5);
random3=focusedRandom(0,1,3);
random4=focusedRandom(0,1,0);
random5=focusedRandom(0,1,8);
random6=focusedRandom(0,1,3);
random7=focusedRandom(0,1,2);
random8=focusedRandom(0,1,2);
random9=focusedRandom(0,1,4);
random10=focusedRandom(0,1,7);
}
else {
}
//
//DECLARE SOME GLOBALS
$skincolor="rgb(214,195,168)";
$skincolor2="rgb(200,180,144)";
$shirtcolor="rgb(220,220,220)";
//
///////////////////////
from2 = color(214,195,168, 1 * 255);
to2 = color(80, 66, 54, 1 * 255);
//
fromDark = color(194,175,148, 1 * 255);
toDark = color(70, 56, 44, 1 * 255);
//
newSkin = lerpColor(from2, to2, Skin);
newSkin2 = lerpColor(fromDark, toDark, Skin);
//
blonde = color(246,237,162, 1 * 255);
black = color(47, 41, 32, 1 * 255);
newHair = lerpColor(blonde, black, Hair);
//BODY
stroke(100);
strokeWeight(2);
///////////////////
//HEAD + FACE
strokeWeight(10);
stroke(newSkin2);
fill(newSkin);
///////////////////
//position in square
//translate(x1,y1);
//HEAD
$headwidth=130+lerp(-20,25,rand3);
$headheight=140+lerp(0,12,rand2);
ellipse(width/2+x1,height/2-mouseY/100+y1,$headwidth,$headheight-mouseY/80);
// TOP OF HEAD HAIR
beginShape();
fill(newHair);
noStroke();
vertex(431+x1, 180+y1);
vertex(430+x1, 200+y1);
vertex(525+x1, 200+y1);
vertex(525+x1, 190)+y1;
vertex(525+x1, 170-lerp(-0,20,h/100)+y1);
vertex(width/2+x1, 150+lerp(-0,20,rand)+y1);
vertex(460+x1, 170-lerp(-0,20,rand)+y1);
endShape();
strokeWeight(8);
stroke(newHair);
//
line(530+lerp(0,20,rand3)+x1,228+y1, 520+x1,190+y1);
line(425-lerp(0,20,rand3)+x1,228+y1, 440+x1,190+y1);
//ellipse(mouseX, mouseY, 80, 80);
//EARS
fill(newSkin);
$earPosY=lerp(0,20,rand)+y1;
$earposXL=width/2.3+x1;
$earposXR=width/1.77+x1;
$earwidth=25+lerp(-5,10,rand);
$earheight=35+lerp(-2,5,rand);
noStroke();
strokeWeight(6);
//left
ellipse($earposXL-lerp(0,15,rand3),height/2.3+$earPosY,$earwidth,$earheight);
//right
ellipse($earposXR+lerp(0,15,rand3),height/2.3+$earPosY,$earwidth,$earheight);
//EYE COLOR
from = color(10, 255, 0, 0.5 * 255);
to = color(0, 0, 255, 0.5 * 255);
c1 = lerpColor(from, to, rand3);
//EYES
$lposXL=width/2.1+x1;
$lposXR=width/1.9+x1;
//EYEPOS
$eyePosY=lerp(0,35,rand)+y1;
$eyeposX=lerp(-10,10,rand3);
$eyewidth=lerp(20,35,rand2);
$eyeheight=lerp(6,27,rand2)+(mouseY/80);
stroke(newSkin2);
fill(255);
//EYEBALLS
ellipse($lposXL+($eyeposX),height/2.4+$eyePosY,$eyewidth,$eyeheight);
//r
ellipse($lposXR-($eyeposX),height/2.4+$eyePosY,$eyewidth,$eyeheight);
fill(c1);
noStroke();
//
$iriswidth=lerp(5,20,rand2);
$irisheight=lerp(5,20,rand2);
//left
ellipse($lposXL+($eyeposX)+mouseX/100,height/2.4+$eyePosY,$iriswidth,$irisheight);
//right
ellipse($lposXR-($eyeposX)-mouseX/100,height/2.4+$eyePosY,$iriswidth,$irisheight);
//pupils
fill(60);
noStroke();
//left pupil
$lposY=height/2.4;
$pupilwidth=lerp(5,12,rand2);
$pupilheight=lerp(5,12,rand2);
$glarecolor = color(255, 255, 255, 0.8 * 255);
//left pupil
ellipse($lposXL+($eyeposX)+mouseX/100,$lposY-mouseY/80+$eyePosY,$pupilwidth,$pupilheight);
//right pupil
ellipse($lposXR-($eyeposX)-mouseX/100,height/2.4-mouseY/80+$eyePosY,$pupilwidth,$pupilheight);
//glare
fill($glarecolor);
noStroke();
//glare
strokeWeight(lerp(4,10,rand3));
///////////////////
//BROWS
$browPosY=lerp(0,20,rand)+y1;
stroke(newHair)
//l
line(444+x1,202+mouseY/80+$browPosY,470+x1,208-mouseY/80+$browPosY);
//r
line(488+x1,208-mouseY/80+$browPosY,514+x1,200+mouseY/80+$browPosY);
//line(500,190-mouseY/80,571,185+mouseY/80);
stroke(215,214,179);
strokeWeight(4);
stroke(215,214,179);
///////////////////
//MOUTH
$mouthPosY=lerp(0,20,rand)+y1;
$mouthwidth=45;
$mouthheight=20;
stroke(newSkin2);
fill(100,0,0);
ellipse(width/2+x1,height/1.8-mouseY/80+$mouthPosY,$mouthwidth,$mouthheight);
//MOUTH DETAIL
//teeth
strokeWeight(3);
stroke(255);
line(460+x1,280+mouseY/110+$mouthPosY,500+x1,280+mouseY/110+$mouthPosY);
//
stroke(100,0,0);
strokeWeight(lerp(3,6,rand3));
//top
line(460+x1,280+mouseY/80+$mouthPosY,width/2-4+x1,280-mouseY/100+$mouthPosY);
line(500+x1,280+mouseY/80+$mouthPosY,width/2+4+x1,280-mouseY/100+$mouthPosY);
//l
line(460+x1,280+mouseY/80+$mouthPosY,width/2+x1,296-mouseY/100+$mouthPosY);
//r
line(500+x1,280+mouseY/80+$mouthPosY,width/2+x1,296-mouseY/100+$mouthPosY);
///////
//+RANDOMIZE FEATURE
rmin_L= -20;
rmax_L=0;
//R
rmin_R= 0;
rmax_R=20;
///////////////////
//NOSE
//nose position on face
//
noStroke();
//nose bridge
fill(newSkin2);
beginShape();
//bridge bottom
vertex(width/2+10+x1,height/2+y1+14+lerp(0,20,rand));
vertex(width/2-10+x1,height/2+y1+14+lerp(0,20,rand));
//bridge top
vertex(width/2-5+x1,height/2.7+y1+50+lerp(0,20,rand));
vertex(width/2+5+x1, height/2.7+y1+50+lerp(0,20,rand));
endShape();
ellipse(width/2+x1,height/2.50+y1+30+lerp(0,20,rand),lerp(10,30,rand),lerp(55,70,rand));
//nose tip
//nostrils
$noswidth=16+lerp(0,10,rand);
$nosheight=12-mouseY/80;
//LEFT
ellipse(width/2.02+x1,height/2.2+y1+30+lerp(0,20,rand),$noswidth,$nosheight);
//RIGHT
ellipse(width/1.98+x1,height/2.2+y1+30+lerp(0,20,rand),$noswidth,$nosheight);
//NOSE DETAIL
fill(0);
/* SHOW ME THE RANDOM VALUES GENERATED
text(random1,20,10);
text(random2,20,20);
text(random3,20,30);
text(random4,20,40);
text(random5,20,50);
text(random6,20,60);
text(random7,20,70);
text(random8,20,80);
text(random9,20,90);
*/
noStroke();
}
function myFunction() {
document.getElementById("demo").innerHTML = Math.random();
demo=Math.random();
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
}
///PS1 SELF PORTRAIT CARLGORDON 300308407
function setup () {
createCanvas(960, 520);
background(255);
}
function draw () {
$pupilwidth=20;
$pupilheight=20;
if (mouseIsPressed) {
fill(255);
}
else {
}
background(255);
text(mouseX,100,100, mouseX);
text(mouseY,100,130, mouseY);
//DECLARE SOME GLOBALS
$skincolor="rgb(214,195,168)";
$skincolor2="rgb(200,180,144)";
$shirtcolor="rgb(220,220,220)";
//
//BODY
stroke(100);
strokeWeight(2);
fill($shirtcolor);
ellipse(width/2,height,600,200);
fill($skincolor);
ellipse(width/2,height-200,200,400);
//END BODY
///////////////////
//HEAD + FACE
strokeWeight(10);
stroke($skincolor2);
fill($skincolor);
///////////////////
//HEAD
ellipse(width/2,height/2-mouseY/80,280,height-130-mouseY/80);
strokeWeight(6);
stroke(95,62,34);
strokeWeight(20);
stroke(95,62,34);
line(625,213,578,104);
line(335,213,380,104);
//ellipse(mouseX, mouseY, 80, 80);
///////////////////
//HAIR
strokeWeight(6);
for($i=0; $i<=220; $i+=5){
line(width-350-$i,30,width-370-$i,120);
}
stroke(105,72,34);
strokeWeight(1);
for($i=0; $i<=220; $i+=8){
line(width-350-$i,30,width-370-$i,120);
}
///////////////////
//EARS
//left
$earwidth=60;
$earheight=90;
noStroke();
strokeWeight(6);
ellipse(width/2.9,height/2.3,$earwidth,$earheight);
//right
ellipse(width/1.52,height/2.3,$earwidth,$earheight);
//EAR DETAIL
stroke($skincolor2);
//LEFT
line(334,198,315,243);
line(325,219,337,235);
//RIGHT
line(624,198,652,243);
line(638,219,627,235);
///////////////////////
//EYES
$eyewidth=70;
$eyeheight=40+mouseY/80;
stroke($skincolor2);
fill(255);
ellipse(width/2.3,height/2.4,$eyewidth,$eyeheight);
//r
ellipse(width/1.78,height/2.4,$eyewidth,$eyeheight);
fill(90,183,202);
noStroke();
//
$iriswidth=40;
$irisheight=30;
//left
ellipse(width/2.3+mouseX/50,height/2.4,$iriswidth,$irisheight);
//right
ellipse(width/1.78-mouseX/50,height/2.4,$iriswidth,$irisheight);
//pupils
fill(60);
noStroke();
//left pupil
$lposX=width/2.3;
$lposY=height/2.4;
ellipse($lposX+mouseX/40,$lposY-mouseY/80,$pupilwidth,$pupilheight);
//right pupil
ellipse(width/1.78-mouseX/40,height/2.4-mouseY/80,$pupilwidth,$pupilheight);
strokeWeight(10);
///////////////////
//BROWS
stroke(95,62,34);
line(383,185+mouseY/80,461,189-mouseY/80);
line(500,190-mouseY/80,571,185+mouseY/80);
stroke(215,214,179);
strokeWeight(6);
stroke(215,214,179);
///////////////////
//MOUTH
$mouthwidth=100;
$mouthheight=45;
stroke($skincolor2);
fill(100,0,0);
ellipse(width/2,height/1.4-mouseY/80,$mouthwidth,$mouthheight);
//MOUTH DETAIL
//teeth
strokeWeight(8-mouseY/80);
stroke(255);
line(425,360+mouseY/80,535,360+mouseY/80);
//
stroke(100,0,0);
strokeWeight(9);
//top
line(425,360+mouseY/80,width/2-4,352-mouseY/80);
line(535,360+mouseY/80,width/2+4,352-mouseY/80);
//l
line(425,360+mouseY/80,width/2,380);
line(425,360+mouseY/80,width/2-30,380-mouseY/80);
//r
line(535,360+mouseY/80,width/2,380);
line(535,360+mouseY/80,width/2+30,380-mouseY/80);
///////////////////
//NOSE
//nose position on face
translate(0,50-mouseY/80);
//
noStroke();
//nose bridge
fill($skincolor2);
ellipse(width/2,height/2.5,20,120-mouseY/80);
//nose tip
ellipse(width/2,height/2,20,20-mouseY/80);
//nostrils
$noswidth=40;
$nosheight=30-mouseY/80;
//LEFT
ellipse(width/2.05,height/2,$noswidth,$nosheight);
//RIGHT
ellipse(width/1.95,height/2,$noswidth,$nosheight);
//NOSE DETAIL
stroke(190,170,134);
line(width/2-7,height/3.4,width/2-10,height/2-15);
line(width/2+7,height/3.4,width/2+10,height/2-15);
line(width/2,height/2+15,449,260);
line(width/2,height/2+15,510,260);
noStroke();
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
}
.slider1{
background-color: rgb(255,255,255);
height: auto;
text-align: center;
margin:auto;
font-family: 'Roboto', sans-serif;
font-size: 24px;
padding: 0px;
}
.breaker{
width: 100%;
height: 2px;
background-color: #e0e0e0;
margin-top: 5px;
margin-bottom: 5px;
}
#blu-grn{
background-color: rgb(0,200,200);
}
#blk{
background-color: black;
}
#brwn{
background-color: rgb(87,63,49);
}
#grey{
background-color: gray;
}
#yello{
background-color: rgb(255,227,88);
}
#purpl{
background-color: rgb(131,60,232);
}
#red{
background-color: rgb(255,67,46);
}
#blu{
background-color: rgb(48,103,232);
}
#grn{
background-color: rgb(46,99,57);
}
#pnk{
background-color: rgb(255,192,255);
}
#orange{
background-color: orange;
}
#white{
background-color: white;
}
.big {
display:block;
width:70px;
height:70px;
background-color:red;
cursor:pointer;
border:2px solid #f1f1f1;
}
.big :hover{
transition:0.8s ease all;
border:2px solid #000;
}
input[type=range] {
-webkit-appearance: none;
width: 100%;
margin: 14.8px 0;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 8.4px;
cursor: pointer;
background: #3071a9;
border-radius: 1.3px;
border: 0.2px solid #010101;
}
input[type=range]::-webkit-slider-thumb {
border: 1px solid #fff;
height: 38px;
width: 16px;
border-radius: 3px;
background: #ffe9ff;
cursor: pointer;
-webkit-appearance: none;
margin-top: -15px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #000;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 10px;
cursor: pointer;
background: #e0e0e0;
border-radius: 1.3px;
border: 0.2px solid #e0e0e0;
}
/*buttons*/
input[type=range]::-moz-range-thumb {
border: 2px solid #000000;
height: 10px;
width: 10px;
background: #1b1f20;
cursor: pointer;
}
input[type=range]::-moz-range-thumb :hover {
border: 2px solid #000000;
height: 10px;
width: 10px;
background: #fff;
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 8.4px;
cursor: pointer;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #050c12;
border: 0.2px solid #010101;
border-radius: 2.6px;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
background: #3071a9;
border: 0.2px solid #010101;
border-radius: 2.6px;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-thumb {
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
border: 1px solid #e0e0e0;
height: 38px;
width: 16px;
border-radius: 3px;
background: #ffe9ff;
cursor: pointer;
height: 8.4px;
}
input[type=range]:focus::-ms-fill-lower {
background: #3071a9;
}
input[type=range]:focus::-ms-fill-upper {
background: #b2cfe9;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment