Skip to content

Instantly share code, notes, and snippets.

@dribnet
Last active October 6, 2021 20:51
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 dribnet/c33d5d9b552222b9adf87327975ddb07 to your computer and use it in GitHub Desktop.
Save dribnet/c33d5d9b552222b9adf87327975ddb07 to your computer and use it in GitHub Desktop.
2021 MDDN 342 Runner
license: mit

2021 MDDN342 Runner

function Boyles_draw_one_frame(cur_frac) {
angleMode(DEGREES);
// Background
noStroke();
fill(45, 93, 94);
rect(0, 0, width, height);
// Moon
fill(226, 252, 249);
noStroke();
ellipse(760, 100, 170);
// Bottom wave
fill(25, 67, 55);
stroke(16, 43, 36);
strokeWeight(3)
beginShape();
vertex(width + 10, height - height / 5);
vertex(width + 10, height + 10);
vertex(-10, height + 10);
vertex(-10, height - height / 5);
for (let i = 0; i < width; i++) {
let phase = cur_frac * 360 + 100;
let y = 5 * sin(i + phase) + 4 * sin(i);
vertex(i, height - height / 5 + y);
}
endShape(CLOSE);
// Trees
let treeKeyFrames = [
-0.45 * width,
0.0 * width,
0.45 * width,
0.9 * width,
1.35 * width
];
for (let i = 0; i < treeKeyFrames.length - 1; i++) {
let curTreeX = map(cur_frac, 0, 1, treeKeyFrames[i + 1], treeKeyFrames[i]);
tree(curTreeX, height - height / 8, height);
}
fill(25, 67, 55);
noStroke();
beginShape();
vertex(width + 10, height - height / 5);
vertex(width + 10, height + 10);
vertex(-10, height + 10);
vertex(-10, height - height / 5);
for (let i = 0; i < width; i++) {
let phase = cur_frac * 360 + 100;
let y = 5 * sin(i + phase) + 4 * sin(i * 1.5);
vertex(i, height - height / 7 + y);
}
endShape(CLOSE);
// Top wave
fill(47, 84, 97, 150);
noStroke();
beginShape();
vertex(width + 10, height / 15);
vertex(width + 10, -10);
vertex(-10, -10);
vertex(-10, height / 15);
for (let i = 0; i < width; i++) {
let phase = cur_frac * 360;
let y = 10 * sin(i + phase) + 4 * sin(i * 2.5 + 70);
vertex(i, height / 2 + y);
}
endShape(CLOSE);
beginShape();
vertex(width + 10, height / 15);
vertex(width + 10, -10);
vertex(-10, -10);
vertex(-10, height / 15);
for (let i = 0; i < width; i++) {
let phase = cur_frac * 360;
let y = 10 * sin(i + phase + 140) + 4 * sin(i * 3.5 + 70);
vertex(i, height / 5 + y);
}
endShape(CLOSE);
// Mist
fill(210, 10);
noStroke();
for (let i = 0; i < 20; i++) {
rect(0, height - 110 - 5 * i, width, 100);
}
}
function tree(x, y, ch) {
let th = ch / 1.3;
push();
translate(x, y);
// Trunk
stroke(12, 30, 40);
strokeWeight(th / 15);
line(0, 0, -th / 7, -th / 4);
strokeWeight(th / 17);
line(-th / 7, -th / 4, -th / 10, -3 * th / 5);
strokeWeight(th / 19);
line(-th / 10, -3 * th / 5, th / 6, -7 * th / 9);
branch(th / 6, -7 * th / 9, 3 * th / 10, -th, th, 21);
// Left branch
strokeWeight(th / 23);
line(-th / 10, -3 * th / 5, -th / 4, -5 * th / 7);
branch(-th / 4, -5 * th / 7, -3 * th / 8, -4.5 * th / 8, th, 25);
strokeWeight(th / 25);
line(-th / 4, -5 * th / 7, -3 * th / 10, -7 * th / 8);
strokeWeight(th / 27);
line(-3 * th / 10, -7 * th / 8, -th / 6, -th);
branch(-3 * th / 10, -7 * th / 8, -4.7 * th / 10, -7.4 * th / 8, th, 27);
branch(-th / 6, -th, -th / 30, -19 * th / 20, th, 29);
strokeWeight(th / 25);
line(th / 6, -7 * th / 9, 3.5 * th / 10, -5.5 * th / 8);
strokeWeight(th / 27);
branch(3.5 * th / 10, -5.5 * th / 8, 4 * th / 10, -th / 2, th, 27);
pop();
}
function branch(x1, y1, x2, y2, th, startW) {
let start = createVector(x1, y1);
let end = createVector(x2, y2);
let p1, p2;
for (let i = 0; i < 10; i++) {
p1 = p5.Vector.lerp(start, end, i * 0.1);
p2 = p5.Vector.lerp(start, end, (i + 1) * 0.1);
strokeWeight(th / (startW + i * 3));
line(p1.x, p1.y, p2.x, p2.y);
}
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
// var DEBUG_MODE = false;
// this can be used to set the number of sliders to show
var NUM_SLIDERS = 3;
// other variables can be in here too
// here's some examples for colors used
// const bg_color_boy = [225, 206, 187];
// const fg_color = [151, 102, 52];
// const stroke_color = [95, 52, 8];
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i = 0; i < s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len, sum_y / s_len];
}
function BoylesFace() {
this.line_color = 0; // can be either 0 (purple = masculine) or 1 (blue = feminine)
this.line_colors_arr = [[146, 9, 173], [64, 245, 233]];
this.face_color = 100; // range is 80 to 230
this.eye_color = 0; // range is 0 to 1 (darkness of hair)
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
// Draw mask backing
fill(this.face_color);
noStroke();
beginShape();
vertex(-2, -1);
bezierVertex(
-2, 1,
-1, 2,
0, 2
);
bezierVertex(
1, 2,
2, 1,
2, -1
);
bezierVertex(
2, -2,
1.7, -3,
0, -3
);
bezierVertex(
-1.7, -3,
-2, -2,
-2, -1
);
endShape(CLOSE);
// Draw eyes
fill(20);
noStroke();
for (let i = -1; i <= 1; i += 2) {
push();
scale(1.15);
beginShape();
vertex(i * 0.35, -0.8);
bezierVertex(
i * 0.32, -0.8,
i * 0.48, -1.08,
i * 0.69, -1.17
);
bezierVertex(
i * 0.9, -1.25,
i * 1.2, -1.19,
i * 1.25, -1.1
);
bezierVertex(
i * 1.27, -1.04,
i * 1.16, -0.92,
i * 1.13, -0.89
);
bezierVertex(
i * 0.86, -0.65,
i * 0.36, -0.78,
i * 0.35, -0.8
);
endShape();
pop();
}
// Pupils
let pupilColor = lerpColor(color(255), color(148, 15, 6), this.eye_color);
fill(pupilColor);
noStroke();
ellipse(0.9, -1.1, 0.3);
ellipse(-0.9, -1.1, 0.3);
// Irises
fill(0);
ellipse(0.9, -1.1, 0.15);
ellipse(-0.9, -1.1, 0.15);
// Draw lines
noFill()
let centre = this.calcBezierPoint([2, -1], [2, 1], [1, 2], [0, 2], 0.9);
let topSide = this.calcBezierPoint([0, -3], [-1.7, -3], [-2, -2], [-2, -1], 0.27);
let bottomSide = this.calcBezierPoint([-2, -1], [-2, 1], [-1, 2], [0, 2], 0.47);
let mouthOpeness = positions.bottom_lip[3][1] - positions.top_lip[3][1];
let lineBrightness = int(map(mouthOpeness, 0.3, 0.7, 2, 5));
let c = this.line_colors_arr[this.line_color];
for (let j = lineBrightness + 1; j > -1; j--) {
if (j == 0) {
stroke(c[0], c[1], c[2]);
strokeWeight(0.03);
} else if (j > lineBrightness) {
stroke(20);
strokeWeight(0.05);
} else {
stroke(c[0], c[1], c[2], 100 - 15 * j);
strokeWeight(0.05 + j * 0.03);
}
line(0, -3, 0, -2.25);
for (let i = -1; i <= 1; i += 2) {
// Centre lines
beginShape();
vertex(0, -2.25);
vertex(i * 0.17, -2);
vertex(i * 0.17, -0.3);
vertex(i * 0.5, -0.4);
vertex(i * 0.5, 0);
vertex(i * 0.17, 0.1);
vertex(i * centre.x, 0.4);
vertex(i * centre.x, centre.y);
endShape();
// Top side lines
beginShape();
vertex(i * topSide.x, topSide.y);
vertex(i * topSide.x, -1.85);
vertex(i * -1.65, -1.55);
vertex(i * -1.65, -1);
endShape();
let p = p5.Vector.lerp(createVector(i * topSide.x, -1.85), createVector(i * -1.65, -1.55), 0.6);
line(p.x, p.y, p.x, -2.2);
// Bottom side lines
beginShape();
vertex(i * bottomSide.x, bottomSide.y);
vertex(i * topSide.x, 1);
vertex(i * topSide.x, 0.3);
vertex(i * -1.65, 0);
endShape();
}
}
}
// This function returns a point along a cubic bezier curve
this.calcBezierPoint = function(p0, p1, p2, p3, t) {
p0 = createVector(p0[0], p0[1]);
p1 = createVector(p1[0], p1[1]);
p2 = createVector(p2[0], p2[1]);
p3 = createVector(p3[0], p3[1]);
p0.mult(-1 * pow(t, 3) + 3 * pow(t, 2) - 3 * t + 1);
p1.mult(3 * pow(t, 3) - 6 * pow(t, 2) + 3 * t);
p2.mult(-3 * pow(t, 3) + 3 * pow(t, 2));
p3.mult(pow(t, 3));
return p0.add(p1.add(p2.add(p3)));
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.line_color = int(map(settings[0], 0, 100, 0, 1));
this.face_color = map(settings[1], 0, 100, 80, 230);
this.eye_color = map(settings[2], 0, 100, 0, 1);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(3);
settings[0] = map(this.line_color, 0, 1, 0, 100);
settings[1] = map(this.face_color, 80, 230, 0, 100);
settings[2] = map(this.eye_color, 0, 1, 0, 100);
return settings;
}
}
{
"000001": [
100,
83,
68
],
"000002": [
100,
95,
54
],
"000005": [
100,
98,
81
],
"000006": [
100,
76,
36
],
"000007": [
0,
95,
0
],
"000009": [
100,
94,
30
],
"000010": [
100,
94,
73
],
"000013": [
0,
100,
100
],
"000014": [
100,
33,
0
],
"000015": [
0,
97,
48
],
"000016": [
0,
95,
21
],
"000018": [
100,
100,
89
],
"000020": [
0,
97,
32
],
"000023": [
0,
94,
30
],
"000025": [
0,
92,
39
],
"000028": [
100,
93,
61
],
"000029": [
100,
99,
100
],
"000030": [
0,
96,
68
],
"000031": [
100,
89,
59
],
"000032": [
0,
96,
46
],
"000035": [
100,
98,
0
],
"000037": [
0,
43,
0
],
"000038": [
0,
91,
23
],
"000040": [
100,
94,
10
],
"000041": [
0,
96,
5
],
"000042": [
100,
90,
25
],
"000043": [
100,
91,
20
],
"000044": [
100,
23,
0
],
"000045": [
100,
91,
26
],
"000047": [
100,
91,
10
],
"000048": [
0,
98,
24
],
"000050": [
0,
95,
7.000000000000001
],
"000051": [
0,
88,
100
],
"000052": [
0,
96,
28.000000000000004
],
"000054": [
100,
93,
100
],
"000055": [
0,
94,
4
],
"000056": [
100,
90,
3
],
"000058": [
100,
96,
0
],
"000060": [
0,
32,
25
],
"000064": [
0,
98,
24
],
"000065": [
0,
69,
0
],
"000068": [
0,
95,
50
],
"000069": [
0,
95,
8
],
"000071": [
100,
92,
87
],
"000073": [
100,
96,
21
],
"000076": [
0,
92,
8
],
"000077": [
100,
91,
0
],
"000078": [
100,
82,
0
],
"000079": [
0,
90,
73
],
"000080": [
0,
94,
0
],
"000081": [
0,
82,
2
],
"000083": [
100,
88,
43
],
"000085": [
100,
82,
32
],
"000086": [
100,
87,
25
],
"000088": [
100,
91,
49
],
"000091": [
0,
94,
8
],
"000092": [
100,
95,
68
],
"000096": [
100,
92,
10
],
"000097": [
100,
90,
32
],
"000099": [
100,
87,
43
],
"000100": [
100,
85,
67
],
"000103": [
100,
93,
18
],
"000104": [
0,
96,
70
],
"000106": [
100,
87,
31
],
"000108": [
100,
94,
78
],
"000109": [
0,
93,
45
],
"000110": [
100,
91,
26
],
"000111": [
100,
77,
79
],
"000114": [
0,
95,
6
],
"000115": [
0,
90,
100
],
"000116": [
0,
96,
21
],
"000117": [
100,
47,
0
],
"000118": [
100,
79,
10
],
"000121": [
100,
80,
6
],
"000122": [
100,
100,
100
],
"000125": [
0,
90,
28.000000000000004
],
"000126": [
100,
81,
100
],
"000129": [
0,
94,
12
],
"000131": [
100,
56.00000000000001,
6
],
"000132": [
100,
71,
13
],
"000133": [
100,
86,
59
],
"000134": [
0,
23,
6
],
"000135": [
0,
68,
11
],
"000137": [
0,
96,
21
],
"000140": [
100,
90,
100
],
"000142": [
100,
93,
25
],
"000143": [
0,
95,
25
],
"000145": [
100,
88,
15
],
"000146": [
100,
88,
31
],
"000147": [
100,
92,
67
],
"000148": [
100,
90,
26
],
"000150": [
0,
94,
63
],
"000151": [
100,
62,
14.000000000000002
],
"000152": [
0,
94,
41
],
"000153": [
0,
95,
24
],
"000155": [
100,
81,
15
],
"000156": [
100,
91,
87
],
"000157": [
100,
92,
85
],
"000160": [
0,
94,
12
],
"000161": [
100,
93,
18
]
}
const ease = new p5.Ease();
function plainBanana(x, y) {
db = color(95, 76, 28); //Dark brown outline
yb = color(249, 227, 98); //Yellow fill
const lineWidth = 1; //stroke strokeWeight
strokeWeight(lineWidth);
stroke(db); //Banana outline
fill(yb); //Drawing the banana shape
beginShape();
curveVertex(x, y);
curveVertex(x - 15, y + 6);
curveVertex(x - 18, y + 12);
curveVertex(x - 5, y + 14);
curveVertex(x + 10, y + 10);
curveVertex(x + 23, y);
curveVertex(x + 27, y - 10);
curveVertex(x + 26, y - 20);
curveVertex(x + 24, y - 27);
curveVertex(x + 24, y - 30);
curveVertex(x + 20, y - 30);
curveVertex(x + 21, y - 25);
curveVertex(x + 20, y - 20);
curveVertex(x + 12, y - 9);
curveVertex(x, y);
curveVertex(x - 15, y + 6);
curveVertex(x - 18, y + 12);
endShape();
noFill(); //Detailed brown Stroke
stroke(db);
strokeWeight(lineWidth);
beginShape();
vertex(x - 17, y + 10);
quadraticVertex(x - 10, y + 10, x, y + 6);
quadraticVertex(x + 10, y + 2, x + 17, y - 5, x + 15, y - 18);
endShape();
noFill(); //Detailed white stroke below the brown stroke
stroke(255);
strokeWeight(0.6);
beginShape();
vertex(x - 10, y + 10);
quadraticVertex(x - 10, y + 10, x, y + 7);
quadraticVertex(x + 10, y + 3, x + 17, y - 4, x + 15, y - 18);
endShape();
noFill(); //Small white stroke
stroke(255);
strokeWeight(0.7);
beginShape();
vertex(x + 20, y - 10);
quadraticVertex(x + 22, y - 12, x + 23, y - 16);
endShape();
noFill(); //Detailed yellow stroke above the brown stroke. Making the brown outline thiner
stroke(yb);
strokeWeight(lineWidth);
beginShape();
vertex(x - 10, y + 5);
quadraticVertex(x - 10, y + 5, x, y + 0.3);
quadraticVertex(x + 9, y - 4, x + 18, y - 14, x + 12, y - 11);
endShape();
stroke(yb); //Bottom yellow line used for making the brown outline thiner
strokeWeight(1.9);
beginShape();
curveVertex(x - 2, y + 5);
curveVertex(x - 3, y + 12);
curveVertex(x + 10, y + 9);
curveVertex(x + 21, y);
curveVertex(x + 15, y - 2);
endShape();
fill(db); //Banana butt
stroke(db);
strokeWeight(lineWidth);
beginShape();
vertex(x - 18, y + 9);
quadraticVertex(x - 17, y + 10, x - 18, y + 12);
endShape();
//
// strokeWeight(lineWidth); //Banana butt detail 1
// fill(db);
// beginShape();
// curveVertex(x - 17, y + 8);
// curveVertex(x - 17, y + 9);
// curveVertex(x - 15, y + 12);
// curveVertex(x - 14, y + 12);
// curveVertex(x - 17, y + 12);
// curveVertex(x - 19, y + 11);
// endShape(CLOSE);
stroke(db); //Banana tip
strokeWeight(lineWidth);
ellipse(x + 22, y - 30, 4, 2);
stroke(yb); //Bottom yellow line used for shading
strokeWeight(lineWidth); //Banana tip detail 1
stroke(db);
fill(db);
beginShape();
curveVertex(x + 20, y - 30);
curveVertex(x + 23, y - 28);
curveVertex(x + 24, y - 30);
curveVertex(x + 22, y - 32);
curveVertex(x + 20, y - 34);
endShape(CLOSE);
fill(db); //Banana tip detail 3
beginShape();
curveVertex(x + 20.9, y - 30);
curveVertex(x + 23, y - 25);
curveVertex(x + 21, y - 27);
curveVertex(x + 21.3, y - 25);
endShape(CLOSE);
fill(db); //Brown banana detail 1
beginShape();
curveVertex(x + 22, y - 6);
curveVertex(x + 23, y - 5);
curveVertex(x + 22, y - 5);
curveVertex(x + 24, y - 8);
curveVertex(x + 21, y - 7);
endShape(CLOSE);
noStroke()
fill(db); //Brown detail 3 on brown stroke
beginShape();
curveVertex(x, y + 6);
curveVertex(x + 2, y + 4);
curveVertex(x + 6, y + 4);
curveVertex(x + 17, y - 6.4);
curveVertex(x + 18, y - 5.5);
curveVertex(x + 12, y);
curveVertex(x + 6, y + 3);
endShape(CLOSE);
noStroke()
fill(255); //White banana detail 4
beginShape();
curveVertex(x - 14, y + 10.4);
curveVertex(x - 12, y + 12);
curveVertex(x - 8, y + 12.5);
curveVertex(x - 5, y + 11);
curveVertex(x - 6, y + 10);
curveVertex(x - 10, y + 9.8);
endShape(CLOSE);
noStroke()
fill(db); //Brown banana detail 5
beginShape();
curveVertex(x - 15, y + 6);
curveVertex(x - 15.3, y + 7);
curveVertex(x - 14, y + 8);
curveVertex(x - 12, y + 7);
curveVertex(x - 10, y + 6);
curveVertex(x - 7, y + 4.8);
curveVertex(x - 7, y + 4);
curveVertex(x - 12, y + 6);
endShape(CLOSE);
}
function RipeBanana(x, y) {
//In this function we draw the light brown banana
db = color(95, 76, 28); //Dark brown
yb = color(198, 178, 79); //Off yellow fill
const lineWidth = 1; //stroke strokeWeight
strokeWeight(lineWidth);
stroke(db); //Banana outline
fill(yb); //Drawing the banana shape
beginShape();
curveVertex(x, y);
curveVertex(x - 15, y + 6);
curveVertex(x - 18, y + 12);
curveVertex(x - 5, y + 14);
curveVertex(x + 10, y + 10);
curveVertex(x + 23, y);
curveVertex(x + 27, y - 10);
curveVertex(x + 26, y - 20);
curveVertex(x + 24, y - 27);
curveVertex(x + 24, y - 30);
curveVertex(x + 20, y - 30);
curveVertex(x + 21, y - 25);
curveVertex(x + 20, y - 20);
curveVertex(x + 12, y - 9);
curveVertex(x, y);
curveVertex(x - 15, y + 6);
curveVertex(x - 18, y + 12);
endShape();
noFill(); //Detailed brown Stroke
stroke(db);
strokeWeight(lineWidth);
beginShape();
vertex(x - 17, y + 10);
quadraticVertex(x - 10, y + 10, x, y + 6);
quadraticVertex(x + 10, y + 2, x + 17, y - 5, x + 15, y - 18);
endShape();
noFill(); //Detailed white stroke below the brown stroke
stroke(255, 255, 255, 150);
strokeWeight(0.6);
beginShape();
vertex(x - 10, y + 10);
quadraticVertex(x - 10, y + 10, x, y + 7);
quadraticVertex(x + 10, y + 3, x + 17, y - 4, x + 15, y - 18);
endShape();
noFill(); //Small white stroke
stroke(255, 255, 255, 150);
strokeWeight(0.7);
beginShape();
vertex(x + 20, y - 10);
quadraticVertex(x + 22, y - 12, x + 23, y - 16);
endShape();
noFill(); //Detailed yellow stroke above the brown stroke. Making the brown outline thiner
stroke(yb);
strokeWeight(lineWidth);
beginShape();
vertex(x - 10, y + 5);
quadraticVertex(x - 10, y + 5, x, y + 0.3);
quadraticVertex(x + 9, y - 4, x + 18, y - 14, x + 12, y - 11);
endShape();
stroke(yb); //Bottom yellow line used for making the brown outline thiner
strokeWeight(1.9);
beginShape();
curveVertex(x - 2, y + 5);
curveVertex(x - 3, y + 12);
curveVertex(x + 10, y + 9);
curveVertex(x + 21, y);
curveVertex(x + 15, y - 2);
endShape();
fill(db); //Banana butt
stroke(db);
strokeWeight(lineWidth);
beginShape();
vertex(x - 18, y + 9);
quadraticVertex(x - 17, y + 10, x - 18, y + 12);
endShape();
strokeWeight(lineWidth); //Banana butt detail 1
fill(db);
beginShape();
curveVertex(x - 17, y + 8);
curveVertex(x - 17, y + 9);
curveVertex(x - 15, y + 12);
curveVertex(x - 14, y + 12);
curveVertex(x - 17, y + 12);
curveVertex(x - 19, y + 11);
endShape(CLOSE);
stroke(db); //Banana tip
strokeWeight(lineWidth);
ellipse(x + 22, y - 30, 4, 2);
stroke(yb); //Bottom yellow line used for shading
strokeWeight(lineWidth); //Banana tip detail 1
stroke(db);
fill(db);
beginShape();
curveVertex(x + 20, y - 30);
curveVertex(x + 23, y - 28);
curveVertex(x + 24, y - 30);
curveVertex(x + 22, y - 32);
curveVertex(x + 20, y - 34);
endShape(CLOSE);
fill(db); //Banana tip detail 2
beginShape();
curveVertex(x + 19, y - 19);
curveVertex(x + 20, y - 20);
curveVertex(x + 22, y - 22);
curveVertex(x + 21, y - 25);
curveVertex(x + 21, y - 25);
curveVertex(x + 20, y - 20);
curveVertex(x + 15, y - 20);
endShape();
fill(db); //Banana tip detail 3
beginShape();
curveVertex(x + 20.9, y - 30);
curveVertex(x + 23, y - 25);
curveVertex(x + 21, y - 27);
curveVertex(x + 21.3, y - 25);
endShape(CLOSE);
fill(db); //Brown banana detail 1
beginShape();
curveVertex(x + 22, y - 6);
curveVertex(x + 23, y - 5);
curveVertex(x + 22, y - 5);
curveVertex(x + 24, y - 8);
curveVertex(x + 21, y - 7);
endShape(CLOSE);
noStroke()
fill(db); //Brown detail 3 on brown stroke
beginShape();
curveVertex(x, y + 6);
curveVertex(x + 2, y + 4);
curveVertex(x + 6, y + 4);
curveVertex(x + 17, y - 6.4);
curveVertex(x + 18, y - 5.5);
curveVertex(x + 12, y);
curveVertex(x + 6, y + 3);
endShape(CLOSE);
noStroke()
fill(255, 255, 255, 150); //White banana detail 4
beginShape();
curveVertex(x - 14, y + 10.4);
curveVertex(x - 12, y + 12);
curveVertex(x - 8, y + 12.5);
curveVertex(x - 5, y + 11);
curveVertex(x - 6, y + 10);
curveVertex(x - 10, y + 9.8);
endShape(CLOSE);
noStroke()
fill(db); //Brown banana detail 5
beginShape();
curveVertex(x - 15, y + 6);
curveVertex(x - 15.3, y + 7);
curveVertex(x - 14, y + 8);
curveVertex(x - 12, y + 7);
curveVertex(x - 10, y + 6);
curveVertex(x - 7, y + 4.8);
curveVertex(x - 7, y + 4);
curveVertex(x - 12, y + 6);
endShape(CLOSE);
}
function offsetAnimation(curFrac, offsetAMT) {
//In this function we create the offset time for the different bananas
let newFrac = curFrac;
for (let i = 0; i <= offsetAMT; i += 0.01) {
newFrac += 0.01;
if (newFrac >= 1) {
newFrac = 0;
}
}
return newFrac;
}
function banana(x, y, curFrac) {
//In this function we draw the banana that chnages colours
//Basic varables
colorMode(RGB);
var strokeColor;
var whiteShine = color(255, 255, 255, 70);
const lineWidth = 1; //stroke strokeWeight
//Variables for lerp colours
let from = color(249, 227, 98); //Light brown
let to = color(124, 92, 41); //Dark Brown
let strokeFrom = color(81, 64, 24); //Light brown
let strokeTo = color(95, 76, 28); //Dark Brown
//Creating the lerp color for the banana peel
if (curFrac < 0.1) {
bananaColor = lerpColor(from, to, curFrac*2);
strokeColor = lerpColor(strokeTo, strokeFrom, curFrac);
} else {
bananaColor = lerpColor(to, from, curFrac);
strokeColor = lerpColor(strokeFrom, strokeTo, curFrac);
}
//Drawing the bananas
strokeWeight(lineWidth);
stroke(strokeColor); //Banana outline
fill(bananaColor); //Drawing the banana shape
beginShape();
curveVertex(x, y);
curveVertex(x - 15, y + 6);
curveVertex(x - 18, y + 12);
curveVertex(x - 5, y + 14);
curveVertex(x + 10, y + 10);
curveVertex(x + 23, y);
curveVertex(x + 27, y - 10);
curveVertex(x + 26, y - 20);
curveVertex(x + 24, y - 27);
curveVertex(x + 24, y - 30);
curveVertex(x + 20, y - 30);
curveVertex(x + 21, y - 25);
curveVertex(x + 20, y - 20);
curveVertex(x + 12, y - 9);
curveVertex(x, y);
curveVertex(x - 15, y + 6);
curveVertex(x - 18, y + 12);
endShape();
noFill(); //Detailed brown Stroke
stroke(strokeColor);
strokeWeight(lineWidth);
beginShape();
vertex(x - 17, y + 10);
quadraticVertex(x - 10, y + 10, x, y + 6);
quadraticVertex(x + 10, y + 2, x + 17, y - 5, x + 15, y - 18);
endShape();
noFill(); //Detailed white stroke below the brown stroke
stroke(whiteShine);
strokeWeight(0.6);
beginShape();
vertex(x - 10, y + 10);
quadraticVertex(x - 10, y + 10, x, y + 7);
quadraticVertex(x + 10, y + 3, x + 17, y - 4, x + 15, y - 18);
endShape();
noFill(); //Small white stroke
stroke(whiteShine);
strokeWeight(0.7);
beginShape();
vertex(x + 20, y - 10);
quadraticVertex(x + 22, y - 12, x + 23, y - 16);
endShape();
noFill(); //Detailed yellow stroke above the brown stroke. Making the brown outline thiner
stroke(bananaColor);
strokeWeight(lineWidth);
beginShape();
vertex(x - 10, y + 5);
quadraticVertex(x - 10, y + 5, x, y + 0.3);
quadraticVertex(x + 9, y - 4, x + 18, y - 14, x + 12, y - 11);
endShape();
stroke(bananaColor); //Bottom yellow line used for making the brown outline thiner
strokeWeight(1.9);
beginShape();
curveVertex(x - 2, y + 5);
curveVertex(x - 3, y + 12);
curveVertex(x + 10, y + 9);
curveVertex(x + 21, y);
curveVertex(x + 15, y - 2);
endShape();
fill(strokeColor); //Banana butt
stroke(strokeColor);
strokeWeight(lineWidth);
beginShape();
vertex(x - 18, y + 9);
quadraticVertex(x - 17, y + 10, x - 18, y + 12);
endShape();
strokeWeight(lineWidth); //Banana butt detail 1
fill(strokeColor);
beginShape();
curveVertex(x - 17, y + 8);
curveVertex(x - 17, y + 9);
curveVertex(x - 15, y + 12);
curveVertex(x - 14, y + 12);
curveVertex(x - 17, y + 12);
curveVertex(x - 19, y + 11);
endShape(CLOSE);
stroke(strokeColor); //Banana tip
strokeWeight(lineWidth);
ellipse(x + 22, y - 30, 4, 2);
stroke(bananaColor); //Bottom yellow line used for shading
strokeWeight(lineWidth); //Banana tip detail 1
stroke(strokeColor);
fill(strokeColor);
beginShape();
curveVertex(x + 20, y - 30);
curveVertex(x + 23, y - 28);
curveVertex(x + 24, y - 30);
curveVertex(x + 22, y - 32);
curveVertex(x + 20, y - 34);
endShape(CLOSE);
fill(strokeColor); //Banana tip detail 2
beginShape();
curveVertex(x + 19, y - 19);
curveVertex(x + 20, y - 20);
curveVertex(x + 22, y - 22);
curveVertex(x + 21, y - 25);
curveVertex(x + 21, y - 25);
curveVertex(x + 20, y - 20);
curveVertex(x + 15, y - 20);
endShape();
fill(strokeColor); //Banana tip detail 3
beginShape();
curveVertex(x + 20.9, y - 30);
curveVertex(x + 23, y - 25);
curveVertex(x + 21, y - 27);
curveVertex(x + 21.3, y - 25);
endShape(CLOSE);
fill(strokeColor); //Brown banana detail 1
beginShape();
curveVertex(x + 22, y - 6);
curveVertex(x + 23, y - 5);
curveVertex(x + 22, y - 5);
curveVertex(x + 24, y - 8);
curveVertex(x + 21, y - 7);
endShape(CLOSE);
fill(strokeColor); //Brown banana detail 2
beginShape();
curveVertex(x + 13, y + 4);
curveVertex(x + 14, y + 3);
curveVertex(x + 14, y + 4);
curveVertex(x + 13, y + 4);
endShape(CLOSE);
noStroke()
fill(strokeColor); //Brown detail 3 on brown stroke
beginShape();
curveVertex(x, y + 6);
curveVertex(x + 2, y + 4);
curveVertex(x + 6, y + 4);
curveVertex(x + 17, y - 6.4);
curveVertex(x + 18, y - 5.5);
curveVertex(x + 12, y);
curveVertex(x + 6, y + 3);
endShape(CLOSE);
noStroke()
fill(whiteShine); //White banana detail 4
beginShape();
curveVertex(x - 14, y + 10.4);
curveVertex(x - 12, y + 12);
curveVertex(x - 8, y + 12.5);
curveVertex(x - 5, y + 11);
curveVertex(x - 6, y + 10);
curveVertex(x - 10, y + 9.8);
endShape(CLOSE);
noStroke()
fill(strokeColor); //Brown banana detail 5
beginShape();
curveVertex(x - 15, y + 6);
curveVertex(x - 15.3, y + 7);
curveVertex(x - 14, y + 8);
curveVertex(x - 12, y + 7); //Play with this one
curveVertex(x - 10, y + 6);
curveVertex(x - 7, y + 4.8);
curveVertex(x - 7, y + 4);
curveVertex(x - 12, y + 6);
endShape(CLOSE);
}
function bananaPeel(x, y, transparency, newFrac) {
//In this function we draw the banana peel.
var bananaColor1 = color(249, 227, 98, transparency); //Light brown outside
var bananaColor2 = color(95, 76, 28, transparency); //Light fill
var bananaColor3 = color(155, 120, 49, transparency); //Dark brown
var bananaInside = color(248, 236, 166, transparency);
const lineWidth2 = 0.3; //stroke strokeWeight
strokeWeight(lineWidth2);
stroke(bananaColor2);
fill(bananaColor3);
//Changing varaibles for the scaling of the banana peels
var scaleStart = 0;
var scalePreMid = 1.5;
var scaleMid = 3;
var scalePreEnd = 2;
var scaleEnd = 0;
let scalePeel;
//Scaling according to the time
if (newFrac <= 0.2) {
scalePeel = map(newFrac, 0, 0.2, scaleStart, scaleMid);
} else if (newFrac <= 0.8) {
scalePeel = map(newFrac, 0.2, 0.8, scaleMid, scalePreEnd);
} else {
scalePeel = map(newFrac, 0.8, 1, scalePreEnd, scaleEnd);
}
scale(scalePeel);
//Left side of banana peel
beginShape();
curveVertex(x - 3, y - 1);
curveVertex(x - 3, y - 1);
curveVertex(x - 5, y);
curveVertex(x - 4, y + 2);
curveVertex(x, y - 1);
endShape(CLOSE);
//Right side of banana peel
beginShape();
curveVertex(x + 2, y - 1);
curveVertex(x + 2, y - 1);
curveVertex(x + 3, y);
curveVertex(x + 4, y + 2);
curveVertex(x + 4, y + 3);
curveVertex(x + 7, y + 2);
curveVertex(x + 6, y);
endShape(CLOSE);
//Inside of the banana peel
push();
//Left side of the inside of banana peel
fill(bananaInside);
stroke(bananaColor2);
strokeWeight(0.3);
beginShape();
curveVertex(x - 3, y - 1);
curveVertex(x - 3, y - 1);
curveVertex(x - 5, y);
curveVertex(x - 4, y + 1);
curveVertex(x, y - 1);
endShape(CLOSE);
//Right side of the inside of banana peel
beginShape();
curveVertex(x + 2, y - 1);
curveVertex(x + 2, y - 1);
curveVertex(x + 3, y);
curveVertex(x + 4.5, y + 1);
curveVertex(x + 5, y + 2.9);
curveVertex(x + 7, y + 2);
curveVertex(x + 6, y);
endShape(CLOSE);
//Middle the inside of banana peel
beginShape();
curveVertex(x, y - 1);
curveVertex(x, y - 1);
curveVertex(x - 2, y);
curveVertex(x - 1, y + 2.5);
curveVertex(x + 2, y + 2);
curveVertex(x + 3, y);
curveVertex(x + 2, y - 1);
endShape(CLOSE);
pop();
}
function bananaAnimation(newFrac, transparency) {
//In the function we animate the banana peel we drew in function bananaPeel().
//Declaring variables for the animation of the peel.
fill(100, 120, 200);
angleMode(DEGREES);
//Adding easy ease
const easeAmount = ease.doubleCircularOgee(newFrac, 0.5);
//The start, mid and end points for the banana peel
let startX = 25;
let startY = -32;
let midX = 6;
let midY = 2;
let endX = -22;
let endY = 11;
//Rotation variables
rot1 = 0;
rot2 = 15;
rot3 = 45;
//Changing varaibles of the peels
let curX;
let curY;
let rotation;
//Creating transparency variables for the banana peel
var transpStart = 70;
var transpMid = 255;
var transpEnd = 150;
var transparency;
//Creating the animationn of the banana peel
if (newFrac < 0.5) {
curX = map(newFrac, 0, 0.5, startX, midX);
curY = map(newFrac, 0, 0.5, startY, midY);
rotation = map(easeAmount, 0, 0.5, rot1, rot2);
transparency = map(easeAmount, 0, 0.5, transpStart, transpMid);
} else {
curX = map(newFrac, 0.5, 1, midX, endX);
curY = map(newFrac, 0.5, 1, midY, endY);
rotation = map(easeAmount, 0.5, 1, rot2, rot3);
transparency = map(easeAmount, 0.5, 1, transpMid, transpEnd);
}
//Calling the bananaPeel function and translating it
push();
translate(curX, curY);
rotate(rotation);
bananaPeel(0, 0, transparency, newFrac);
pop();
}
function bruwer_draw_one_frame(curFrac) {
//In this function we draw everything accroding to the 1 second time frame
noStroke();
//Background
fill(159, 215, 212);
rect(0, 0, width, height);
angleMode(DEGREES);
//Size of the banana in the grid
let bananaScale = height / 320;
//Variables for the grid
let numRows = 5;
let numCols = 8;
let cellWidth = width / (numCols + 1);
let cellHeight = height / (numRows + 1);
//Variables for the noise
let smoothness = 5;
let maxCycleOffset = 0.3;
let scaledOffsety = cellHeight / bananaScale;
let scaledOffsetx = cellWidth / bananaScale;
let b1_y = 0.55 * height;
let b2_y = 0.65 * height;
let b1_size = height / 12;
let b2_size = height / 6;
//Vataibles for the difference in peeling times
let offsetArray = [0, 0.5, 0.3, 0.9, 0.7, 0.6, 0.1, 0.4]
let newFrac;
//The grid of bananas
for (let j = 0; j < numRows; j++) {
let curY = (j + 1.1) * cellHeight;
for (let i = 0; i < numCols; i++) {
let curX = (i + 0.9) * cellWidth;
//Noises
let nudgeLeft = getNoiseValue(curX, curY, curFrac, "nudgeRight", 0, -2, smoothness);
let nudgeDown = getNoiseValue(curX, curY, curFrac, "nudgeDown", 0, 2, smoothness);
let cycle_offset = getNoiseValue(curX, curY, curFrac, "peelOffset", 0, maxCycleOffset, smoothness);
let movement = getNoiseValue(curX, curY, curFrac, "Wiggles", -b1_size * 0.75, b1_size * 0.75, 100);
//The if statement determines the grid layout of the 3 different bananas
if ((i + j) % 3 == 0) {
push();
translate(curX, curY + movement / 9);
scale(bananaScale);
plainBanana(0, 0);
pop();
} else if ((i + j) % 3 == 1) {
push();
translate(curX + nudgeLeft, curY + nudgeDown);
scale(bananaScale);
RipeBanana(0, 0)
pop();
} else {
push();
translate(curX + nudgeLeft, curY + nudgeDown);
scale(bananaScale);
banana(0, 0, curFrac);
// console.log(newFrac);
newFrac = offsetAnimation(curFrac, offsetArray[i]);
cycleFrac = (newFrac + cycle_offset) % 1.0;
bananaAnimation(newFrac, cycleFrac);
pop();
}
}
}
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
// var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
var NUM_SLIDERS = 7;
// other variables can be in here too
// here's some examples for colors used
// This where you define your own face object
function BruwerFace() {
this.thinnessValue = 5;
this.eyeSpaceValue = 2;
this.headHeightValue = 5;
this.eyeSizeValue = 5;
this.mouthHeightValue = 5;
this.mouthScaleValue = 5;
this.draw_segment = function(segment, do_loop) {
for (let i = 0; i < segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
ellipse(px, py, 0.1);
if (i < segment.length - 1) {
let nx = segment[i + 1][0];
let ny = segment[i + 1][1];
line(px, py, nx, ny);
} else if (do_loop) {
let nx = segment[0][0];
let ny = segment[0][1];
line(px, py, nx, ny);
}
}
}
/*
* Draw the face with position lists
*/
this.draw = function(positions) {
// print(positions);
//Basic variable set up
scale(0.3);
angleMode(DEGREES);
const bg_color = [225, 206, 187];
const fg_color = [151, 102, 52];
const strokeColor = [0];
const offWhite = [225, 225, 255, 90];
//For the eyelashes
let symmetry = 12;
let angle = 360 / 12;
//For drawing custom shapes
var x = 0;
var y = 0;
//Face and Hair colors
let hairColor1 = color(229, 182, 90); //Blonde
let hairColor2 = color(218, 53, 50); //Orange
let hairColor3 = color(180, 33, 65); //Red
let hairColor4 = color(107, 66, 39); //Brown
let hairColor5 = color(36, 37, 40); //Black
let noHairColor = color(183, 183, 183); //Grey
let faceColor1 = color(255, 226, 197); //Light skin tone
let faceColor2 = color(255, 221, 170); //Warmer skin tone
let faceColor4 = color(179, 129, 88); //Darker skin tone
let faceColor5 = color(137, 96, 65); //Darkest skin tone
const cheekColour = [255, 108, 126, 60];
const contourColour = [0, 0, 0, 30];
let ethnicity = this.faceColor;
let skinTone;
let hairTone = this.hairColor;
let hairColor;
//Setting up the face color for the slider
if (ethnicity == 1) {
skinTone = faceColor1 //Fare skin tone
} else if (ethnicity == 2) {
skinTone = faceColor2 //Olive skin tone
} else if (ethnicity == 3) {
skinTone = faceColor4 //Warm skin tone
} else {
skinTone = faceColor5 //Dark skin tone
}
//Setting up the hair color for the slider
if (hairTone == 1) {
hairColor = hairColor1 //Blonde
} else if (hairTone == 2) {
hairColor = hairColor2 //orange
} else if (hairTone == 3) {
hairColor = hairColor3 //Red
} else if (hairTone == 4) {
hairColor = hairColor4 //Brown
} else if (hairTone == 5) {
hairColor = hairColor5 //Black
} else {
hairColor = noHairColor;
}
//Face mappings mouth
let mouthPosX = average_point(positions.top_lip);
let mouthPosY = average_point(positions.bottom_lip);
let max = this.mouthHeightValue;
let dMouth = dist(mouthPosX[0], mouthPosX[1], mouthPosY[0], mouthPosY[1]);
let mouthWidth = map(dMouth, 0, max, 0, 10);
let mouthHeight = map(dMouth, 0, max, 0, 25);
let topLipPos = positions.top_lip[9];
let bottomLipPos = positions.bottom_lip[9];
let d = dist(topLipPos[0], topLipPos[1], bottomLipPos[0], bottomLipPos[1]);
//How big the smile is
if (d < 0.1) {
d = 0.02;
}
mouth = map(d, 0, 0.5, 0, 10);
let mouthSize = map(mouth, 0, 10, 0, 2);
//Face mappings nose + eyes + eyebrows
let leftEye1 = positions.left_eye[0];
let leftEye2 = positions.left_eye[5];
let rightEye1 = positions.left_eye[0];
let rightEye2 = positions.left_eye[5];
let noseTop = positions.nose_bridge[0];
let noseBottom = positions.nose_bridge[3];
let leftEyePos = average_point(positions.left_eye);
let rightEyePos = average_point(positions.right_eye);
let leftEyebrow = average_point(positions.left_eyebrow);
let rightEyebrow = average_point(positions.right_eyebrow);
//Position of eyes
leftEyePos[0] *= 3;
leftEyePos[1] *= 0.8;
rightEyePos[0] *= 3;
rightEyePos[1] *= 0.8;
//Positions for the face
let facePosition = average_point(positions.chin);
/////////////////////////////////////////////////////////////////////////////////
if (this.gender > 0 && this.gender <= 1) { //Masculine
fill(skinTone);
//Hair
push();
fill(hairColor);
noStroke();
ellipse(facePosition[0], facePosition[1] - 1.5, this.thinnessValue + 1, this.headHeightValue - 2);
pop();
//Head
push();
noStroke();
ellipse(facePosition[0], facePosition[1], this.thinnessValue, this.headHeightValue);
pop();
//Eyes
fill(0);
ellipse(leftEyePos[0], leftEyePos[1], leftEye2[0], leftEye2[1]);
ellipse(rightEyePos[0], rightEyePos[1], rightEye2[0], leftEye2[1]);
//Eye shine details
push();
noStroke();
fill(255, 255, 255, 50);
ellipse(leftEyePos[0] - 0.2, leftEye1[1], 0.3, 0.3); //Left eye
ellipse(rightEyePos[0] - 0.2, rightEye1[1] + 0.1, 0.3, 0.3); //Right eye
pop();
//Nose
push();
stroke(contourColour);
strokeWeight(0.20);
line(noseTop[0], noseTop[1] + 1.3, noseBottom[0], noseBottom[1] + 1.7);
pop();
//Eyebrows
push();
rotate(-20);
noFill();
stroke(0);
strokeWeight(0.15);
arc(leftEyePos[0] + .5, leftEyePos[1] - 2, 2, 0.2, 180, 0); //Left eyebrow
pop();
push();
rotate(20);
noFill();
stroke(0);
strokeWeight(0.15);
arc(rightEyePos[0] - .5, rightEyePos[1] - 2, 2, 0.2, 180, 0); //Right eyebrow
pop();
//The Moustach
fill(hairColor);
noStroke();
push();
translate(noseBottom[1] + 1, noseBottom[1] + 2.2);
rotate(10);
ellipse(0, 0, 2.5, 1.2);
pop();
push();
translate(-noseBottom[1] - 1, noseBottom[1] + 2.2);
rotate(-10);
ellipse(0, 0, 2.5, 1.2);
pop();
//Mouth
noFill();
stroke(0);
strokeWeight(0.2);
noFill();
arc(0, this.mouthScaleValue, mouthWidth, mouthSize, 0, 180);
//Creates a outline of the shape to give the rough drawn technique
push();
var outline = true;
if (outline) {
noFill();
stroke(strokeColor);
strokeWeight(0.15);
//Head outline
push();
translate(0 - 0.3, 0 + 0.5);
ellipse(facePosition[0], facePosition[1], this.thinnessValue, this.headHeightValue, this.headRoundnessValue);
pop();
}
pop();
//Hair
//Left hair
push();
fill(hairColor);
noStroke();
triangle(-7.5, -3.5, -4.5, -9, 5, -3.5);
pop();
//Hair middle cover up
push();
fill(hairColor);
noStroke();
translate(1.2, -4.8);
rotate(30);
ellipse(0, -1, 6.5, 3.2);
pop();
//Right hair
push();
fill(hairColor);
noStroke();
translate(0.5, -4);
rotate(55);
triangle(-3, -3.5, 1, -5.5, 3, -3.5);
pop();
//middle hair
push();
fill(hairColor);
noStroke();
translate(-2, -4);
rotate(40);
triangle(-3, -3.5, 1, -5.5, 3, -3.5);
pop();
//middle hair
push();
fill(hairColor);
noStroke();
translate(2, -1);
rotate(40);
triangle(-3, -3.5, 1, -5.5, 3, -3.5);
pop();
//Hair detail
push();
fill(hairColor);
noStroke();
translate(0.5, -1.5);
rotate(35);
triangle(-3, -3.5, 1, -5.5, 3, -3.5);
pop();
//Hair detail
push();
fill(hairColor);
noStroke();
translate(-0, -1.5);
rotate(-35);
triangle(-3, -3.5, 1, -5.5, 3, -3.5);
pop();
//Hair detail
push();
fill(hairColor);
noStroke();
translate(-3.2, -4);
rotate(45);
triangle(-3, -3.5, 1, -5.5, 3, -3.5);
pop();
//Hair detail
push();
fill(hairColor);
noStroke();
translate(-1.5, -1);
rotate(-40);
triangle(-3, -3.5, 1, -5.5, 3, -3.5);
pop();
/////////////////////////////////////////////////////////////////////////////////
} else if (this.gender > 1 && this.gender <= 2) { //Gender neuteral
fill(skinTone);
//Hair
push();
fill(hairColor);
noStroke();
ellipse(facePosition[0], facePosition[1] - 1.5, this.thinnessValue + 1, this.headHeightValue - 2);
pop();
//Head
push();
noStroke();
ellipse(facePosition[0], facePosition[1], this.thinnessValue, this.headHeightValue);
pop();
//Eyes
fill(0);
ellipse(leftEyePos[0], leftEyePos[1], leftEye2[0], leftEye2[1]);
ellipse(rightEyePos[0], rightEyePos[1], rightEye2[0], leftEye2[1]);
//Eye shine details
push();
noStroke();
fill(255, 255, 255, 50);
ellipse(leftEyePos[0] - 0.2, leftEye1[1], 0.3, 0.3); //Left eye
ellipse(rightEyePos[0] - 0.2, rightEye1[1] + 0.1, 0.3, 0.3); //Right eye
pop();
//Nose
push();
stroke(contourColour);
strokeWeight(0.20);
line(noseTop[0], noseTop[1] + 1.3, noseBottom[0], noseBottom[1] + 1.7);
pop();
//Eyebrows
push();
rotate(-20);
noFill();
stroke(0);
strokeWeight(0.15);
arc(leftEyePos[0] + .5, leftEyePos[1] - 2, 2, 0.2, 180, 0); //Left eyebrow
pop();
push();
rotate(20);
noFill();
stroke(0);
strokeWeight(0.15);
arc(rightEyePos[0] - .5, rightEyePos[1] - 2, 2, 0.2, 180, 0); //Right eyebrow
pop();
//Mouth
noFill();
stroke(0);
strokeWeight(0.2);
noFill();
arc(0, this.mouthScaleValue, mouthWidth, mouthSize, 0, 180);
//Creates a outline of the shape to give the rough drawn technique
push();
var outline = true;
if (outline) {
noFill();
stroke(strokeColor);
strokeWeight(0.15);
//Head outline
push();
translate(0 - 0.3, 0 + 0.5);
ellipse(facePosition[0], facePosition[1], this.thinnessValue, this.headHeightValue, this.headRoundnessValue);
pop();
}
pop();
//Hair
push();
scale(1);
noStroke();
translate(facePosition[0], facePosition[1] - 1.6);
fill(hairColor);
beginShape();
curveVertex(x, y - 6.2);
curveVertex(x, y - 6.2);
curveVertex(x - 3.2, y - 5);
curveVertex(x - 5, y - 2.5);
curveVertex(x, y - 1.5);
curveVertex(x + 5, y - 2.5);
curveVertex(x + 3.2, y - 5);
curveVertex(x, y - 6.2);
endShape(CLOSE);
pop();
//Hair texture
push();
translate(facePosition[0] + 3.1, facePosition[1] - 12);
rotate(200);
fill(hairColor);
noStroke();
beginShape();
curveVertex(x - 1, y - 8);
curveVertex(x - 1, y - 8);
curveVertex(x + 0.5, y - 6);
curveVertex(x + 2, y - 5);
endShape(CLOSE);
pop();
//Hair texture
push();
translate(facePosition[0] + 4.7, facePosition[1] - 11);
rotate(220);
fill(hairColor);
noStroke();
beginShape();
curveVertex(x - 1, y - 8);
curveVertex(x - 1, y - 8);
curveVertex(x + 0.5, y - 6);
curveVertex(x + 2, y - 5);
endShape(CLOSE);
pop();
//Right Cheek details
push();
strokeWeight(0.1);
translate(6, 0.7);
line(-2.5, 0.5, -2.25, 0.25);
line(-2.9, 0.5, -2.65, 0.25);
pop();
//Left Cheek details
push();
strokeWeight(0.1);
translate(-6, 0.7);
line(2.5, 0.25, 2.25, 0.5);
line(2.9, 0.25, 2.65, 0.5);
pop();
/////////////////////////////////////////////////////////////////////////////////
} else if (this.gender > 2 && this.gender <= 3) { //Plain Jane also gender neuteral
fill(skinTone);
push();
translate(0, 0);
fill(hairColor);
stroke(strokeColor);
strokeWeight(0.15);
rect(-6.95, -9.1, 13.9, 14, 25, 25, 0, 0);
pop();
//Hair
push();
translate(0, 0);
fill(hairColor);
noStroke();
beginShape();
curveVertex(x, y - 8);
curveVertex(x, y - 8);
curveVertex(x - 5, y - 7);
curveVertex(x - 7.8, y);
curveVertex(x - 8, y + 10);
curveVertex(x, y + 9.8);
curveVertex(x + 8, y + 10);
curveVertex(x + 7.8, y);
curveVertex(x + 5, y - 7);
curveVertex(x, y - 8);
endShape(CLOSE);
pop();
//Head
push();
noStroke();
ellipse(0, 0, this.thinnessValue, this.headHeightValue);
pop();
//Mouth
noFill();
stroke(0);
strokeWeight(0.2);
noFill();
arc(0, this.mouthScaleValue, mouthWidth, mouthSize, 0, 180);
//Creates a outline of the shape to give the rough drawn technique
push();
var outline = true;
if (outline) {
noFill();
stroke(strokeColor);
strokeWeight(0.15);
//Head outline
push();
translate(0 - 0.3, 0 + 0.5);
ellipse(0, 0, this.thinnessValue, this.headHeightValue, this.headRoundnessValue);
pop();
//Hair
push();
translate(-0.3, 0.3);
beginShape();
curveVertex(x, y - 8);
curveVertex(x - 5, y - 7);
curveVertex(x - 7.8, y);
curveVertex(x - 8, y + 10);
curveVertex(x, y + 9.8);
curveVertex(x + 8, y + 10);
curveVertex(x + 7.8, y);
curveVertex(x + 5, y - 7);
curveVertex(x, y - 8);
endShape();
pop();
}
pop();
//Hair
push();
translate(0, 0);
fill(hairColor);
noStroke();
rect(-4, -8, 8, 2.4, 25, 25, 0, 0);
pop();
//Part of the hair right
push();
translate(0.7, 4.3);
rotate(50);
fill(hairColor);
noStroke();
ellipse(-4, -8, 7, 2.5);
pop();
//Part of the hair left
push();
translate(4.2, -2.2);
rotate(-55);
fill(hairColor);
noStroke();
ellipse(-4, -8, 7, 2.5);
pop();
//Fringe details
push();
fill(hairColor);
translate(0, 1.8);
noStroke();
//Left fringe
beginShape();
curveVertex(x, y - 8);
curveVertex(x, y - 8);
curveVertex(x - 2, y - 5);
curveVertex(x - 6, y - 2);
curveVertex(x - 7, y - 2);
curveVertex(x - 4, y - 7);
endShape(CLOSE);
//Left fringe individual hair stroke
push();
translate(0.1, 0.6);
rotate(-14);
fill(hairColor);
beginShape();
curveVertex(x + 1, y - 8);
curveVertex(x + 1, y - 8);
curveVertex(x - 0.5, y - 6);
curveVertex(x - 2, y - 5);
endShape(CLOSE);
pop();
//Left fringe individual hair stroke
push();
translate(2, -1);
rotate(-20);
fill(hairColor);
beginShape();
curveVertex(x + 1, y - 8);
curveVertex(x + 1, y - 8);
curveVertex(x - 0.5, y - 6);
curveVertex(x - 2, y - 5);
endShape(CLOSE);
pop();
//Right fringe
push();
beginShape();
curveVertex(x - 0.5, y - 8);
curveVertex(x - 0.5, y - 8);
curveVertex(x + 2, y - 5);
curveVertex(x + 6, y - 2);
curveVertex(x + 6.8, y - 2);
curveVertex(x + 4, y - 7);
endShape(CLOSE);
pop();
//Right fringe individual hair stroke
push();
noStroke();
translate(-1, 0);
rotate(13);
fill(hairColor);
beginShape();
curveVertex(x - 1, y - 8);
curveVertex(x - 1, y - 8);
curveVertex(x + 0.5, y - 6);
curveVertex(x + 2, y - 5);
endShape(CLOSE);
pop();
pop();
//Eyes
fill(0);
ellipse(leftEyePos[0], leftEyePos[1], leftEye2[0], leftEye2[1]);
ellipse(rightEyePos[0], rightEyePos[1], rightEye2[0], leftEye2[1]);
//Eye shine details
push();
noStroke();
fill(offWhite);
ellipse(leftEyePos[0] - 0.2, leftEye1[1], 0.3, 0.3); //Left eye
ellipse(rightEyePos[0] - 0.2, rightEye1[1] + 0.1, 0.3, 0.3); //Right eye
pop();
//Creates a outline of the fringe details shape to give the rough drawn technique
push();
var outline = true;
if (outline) {
noFill();
stroke(strokeColor);
strokeWeight(0.15);
//Fringe details
//Left fringe
push();
translate(-0.5, 1.8);
beginShape();
curveVertex(x - 3, y - 4);
curveVertex(x - 3, y - 4);
curveVertex(x - 6, y - 2);
curveVertex(x - 7, y - 2);
endShape();
pop();
translate(-0.5, 0.1);
//Left strands of hair
push();
translate(0.5, 1.8);
rotate(-6);
beginShape();
curveVertex(x + 0.6, y - 7.8);
curveVertex(x + 0.6, y - 7.8);
curveVertex(x - 0.5, y - 6);
curveVertex(x - 1.5, y - 5.9);
endShape();
pop();
//Right fringe
push();
translate(0.1, 1.1);
beginShape();
curveVertex(x + 2, y - 5);
curveVertex(x + 2, y - 5);
curveVertex(x + 6, y - 2);
curveVertex(x + 6.8, y - 2);
endShape();
pop();
//Right strands of hair
push();
translate(0.6, 2.5);
rotate(10);
beginShape();
curveVertex(x - 1.5, y - 8.5);
curveVertex(x - 1.5, y - 8.5);
curveVertex(x - 1.2, y - 8);
curveVertex(x + 0.5, y - 6);
curveVertex(x + 2.2, y - 5);
endShape();
pop();
pop();
}
/////////////////////////////////////////////////////////////////////////////////
} else if (this.gender > 3 && this.gender <= 4) { //Fem
fill(skinTone);
//Hair
push();
translate(facePosition[0], facePosition[1]);
fill(hairColor);
noStroke();
beginShape();
curveVertex(x, y - 8.3);
curveVertex(x, y - 8.3);
curveVertex(x - 3, y - 8.7);
curveVertex(x - 7, y - 5);
curveVertex(x - 8, y);
curveVertex(x - 9, y + 9);
curveVertex(x, y + 8.5);
curveVertex(x + 9, y + 9);
curveVertex(x + 8, y);
curveVertex(x + 7, y - 5);
curveVertex(x + 3, y - 8.9);
curveVertex(x, y - 8.3);
endShape(CLOSE);
pop();
//Head
push();
noStroke();
ellipse(facePosition[0], facePosition[1], this.thinnessValue, this.headHeightValue);
pop();
//Mouth
noFill();
stroke(0);
strokeWeight(0.2);
noFill();
arc(0, this.mouthScaleValue, mouthWidth, mouthSize, 0, 180);
//Creates a outline of the shape to give the rough drawn technique
push();
var outline = true;
if (outline) {
noFill();
stroke(strokeColor);
strokeWeight(0.15);
//Head outline
push();
translate(0 - 0.3, 0 + 0.5);
ellipse(facePosition[0], facePosition[1], this.thinnessValue, this.headHeightValue, this.headRoundnessValue);
pop();
//Hair outline
push();
translate(facePosition[0] - 0.3, facePosition[1] + 0.3);
beginShape();
curveVertex(x, y - 8.3);
curveVertex(x, y - 8.3);
curveVertex(x - 3, y - 8.7);
curveVertex(x - 7, y - 5);
curveVertex(x - 8, y);
curveVertex(x - 9, y + 9);
curveVertex(x, y + 8.5);
curveVertex(x + 9, y + 9);
curveVertex(x + 8, y);
curveVertex(x + 7, y - 5);
curveVertex(x + 3, y - 8.9);
curveVertex(x, y - 8.3);
endShape(CLOSE);
pop();
}
pop();
//Fringe
push();
noStroke();
translate(facePosition[0], facePosition[1] - 0.5);
fill(hairColor);
beginShape();
curveVertex(x, y - 7.5);
curveVertex(x, y - 7.5);
curveVertex(x - 5, y - 6.5);
curveVertex(x - 5.5, y - 1);
curveVertex(x, y - 2);
curveVertex(x + 5.5, y - 1);
curveVertex(x + 4.5, y - 6.5);
curveVertex(x, y - 7.5);
endShape(CLOSE);
pop();
//Fringe details
//Right texture
push();
translate(facePosition[0] + 7, facePosition[1] + 2.8);
rotate(-45);
fill(skinTone);
noStroke();
beginShape();
curveVertex(x + 1, y - 8);
curveVertex(x + 1, y - 8);
curveVertex(x - 0.5, y - 6);
curveVertex(x - 2, y - 5);
endShape(CLOSE);
pop();
//Right texture
push();
translate(facePosition[0] + 9, facePosition[1] + 2);
rotate(-50);
fill(skinTone);
noStroke();
beginShape();
curveVertex(x + 1, y - 8);
curveVertex(x + 1, y - 8);
curveVertex(x - 0.5, y - 6);
curveVertex(x - 2, y - 5);
endShape(CLOSE);
pop();
//Left texture
push();
translate(facePosition[0] - 6.5, facePosition[1] + 2.8);
rotate(45);
fill(skinTone);
noStroke();
beginShape();
curveVertex(x - 1, y - 8);
curveVertex(x - 1, y - 8);
curveVertex(x + 0.5, y - 6);
curveVertex(x + 2, y - 5);
endShape(CLOSE);
pop();
//Left texture
push();
translate(facePosition[0] - 9, facePosition[1] + 2);
rotate(50);
fill(skinTone);
noStroke();
beginShape();
curveVertex(x - 1, y - 8);
curveVertex(x - 1, y - 8);
curveVertex(x + 0.5, y - 6);
curveVertex(x + 2, y - 5);
endShape(CLOSE);
pop();
//Eyes
fill(0);
ellipse(leftEyePos[0], leftEyePos[1], leftEye2[0], leftEye2[1]);
ellipse(rightEyePos[0], rightEyePos[1], rightEye2[0], leftEye2[1]);
//Eye shine details
push();
noStroke();
fill(offWhite);
ellipse(leftEyePos[0] - 0.2, leftEye1[1], 0.3, 0.3); //Left eye
ellipse(rightEyePos[0] - 0.2, rightEye1[1] + 0.1, 0.3, 0.3); //Right eye
pop();
//Cheeks
push();
fill(cheekColour);
noStroke();
ellipse(-3, 1.1, 1.5, 0.8);
ellipse(3, 1.1, 1.5, 0.8);
pop();
//Right Cheek details
push();
strokeWeight(0.1);
translate(5.6, 0.7);
line(-2.5, 0.5, -2.25, 0.25);
line(-2.9, 0.5, -2.65, 0.25);
pop();
//Left Cheek details
push();
strokeWeight(0.1);
translate(-5.6, 0.7);
line(2.5, 0.25, 2.25, 0.5);
line(2.9, 0.25, 2.65, 0.5);
pop();
/////////////////////////////////////////////////////////////////////////////////
} else if (this.gender > 4 && this.gender <= 5) { //Most Fem
fill(skinTone);
//Hair
push();
translate(facePosition[0], facePosition[1]);
fill(hairColor);
noStroke();
beginShape();
curveVertex(x + 2.5, y - 8);
curveVertex(x + 2.5, y - 8);
curveVertex(x + 0.5, y - 9.4);
curveVertex(x - 4, y - 9.4);
curveVertex(x - 6, y - 7);
curveVertex(x - 8, y - 1);
curveVertex(x - 9.7, y + 2);
curveVertex(x - 9, y + 4);
curveVertex(x - 10, y + 7);
curveVertex(x - 9, y + 9);
curveVertex(x - 5.7, y + 8.5);
curveVertex(x - 1, y + 9.5);
curveVertex(x + 4, y + 8.5);
curveVertex(x + 8, y + 9);
curveVertex(x + 10, y + 6);
curveVertex(x + 8.5, y + 4);
curveVertex(x + 9, y + 2);
curveVertex(x + 7, y - 1);
curveVertex(x + 6, y - 7.5);
curveVertex(x + 2.5, y - 8);
endShape(CLOSE);
pop();
//Head
push();
noStroke();
ellipse(facePosition[0], facePosition[1], this.thinnessValue, this.headHeightValue);
pop();
//Mouth
noFill();
stroke(0);
strokeWeight(0.2);
noFill();
arc(0, this.mouthScaleValue, mouthWidth, mouthSize, 0, 180);
//Creates a outline of the shape to give the rough drawn technique
push();
var outline = true;
if (outline) {
noFill();
stroke(strokeColor);
strokeWeight(0.15);
//Head outline
push();
translate(0 - 0.3, 0 + 0.5);
ellipse(facePosition[0], facePosition[1], this.thinnessValue, this.headHeightValue, this.headRoundnessValue);
pop();
//Hair outline
push();
translate(facePosition[0] - 0.3, facePosition[1] + 0.3);
beginShape();
curveVertex(x + 2.5, y - 8);
curveVertex(x + 2.5, y - 8);
curveVertex(x + 0.5, y - 9.4);
curveVertex(x - 4, y - 9.4);
curveVertex(x - 6, y - 7);
curveVertex(x - 8, y - 1);
curveVertex(x - 9.7, y + 2);
curveVertex(x - 9, y + 4);
curveVertex(x - 10, y + 7);
curveVertex(x - 9, y + 9);
curveVertex(x - 5.7, y + 8.5);
curveVertex(x - 1, y + 9.5);
curveVertex(x + 4, y + 8.5);
curveVertex(x + 8, y + 9);
curveVertex(x + 10, y + 6);
curveVertex(x + 8.5, y + 4);
curveVertex(x + 9, y + 2);
curveVertex(x + 7, y - 1);
curveVertex(x + 6, y - 7.5);
endShape(CLOSE);
pop();
}
pop();
//Fringe
//Left fringe
push();
fill(hairColor);
noStroke();
translate(facePosition[0], facePosition[1] + 2);
beginShape();
curveVertex(x + 1.8, y - 8);
curveVertex(x + 1.8, y - 8);
curveVertex(x + 0.5, y - 4.8);
curveVertex(x - 4, y - 4);
curveVertex(x - 7, y - 1);
curveVertex(x - 7, y - 4);
curveVertex(x - 6, y - 8.1);
curveVertex(x - 9, y - 6);
endShape();
pop();
//Right fridge
push();
fill(hairColor);
noStroke();
translate(facePosition[0], facePosition[1] + 2);
beginShape();
curveVertex(x + 1.5, y - 8.5);
curveVertex(x + 1.5, y - 8.5);
curveVertex(x + 2, y - 5);
curveVertex(x + 6, y - 3);
curveVertex(x + 5.7, y - 6.9);
endShape(CLOSE);
pop();
push();
fill(hairColor);
translate(facePosition[0], facePosition[1]);
noStroke();
rect(-5, -7.5, 10, 3);
pop();
//Creates a outline of the shape to give the rough drawn technique
push();
var outline = true;
if (outline) {
noFill();
stroke(strokeColor);
strokeWeight(0.15);
//fringe details
push();
translate(facePosition[0] - 0.4, facePosition[1] + 1.8);
//Left frindge
beginShape();
curveVertex(x + 1.35, y - 6);
curveVertex(x + 1.35, y - 6);
curveVertex(x + 0.4, y - 4.8);
curveVertex(x - 4, y - 4);
curveVertex(x - 6, y - 2);
curveVertex(x - 6, y - 3);
endShape();
pop();
//Right fringe
push();
translate(facePosition[0] + 0.2, facePosition[1] + 1.8);
beginShape();
curveVertex(x + 1.5, y - 7);
curveVertex(x + 1.5, y - 7);
curveVertex(x + 2, y - 5);
curveVertex(x + 6, y - 3);
curveVertex(x + 5, y - 6);
endShape();
pop();
}
pop();
//Left eyelashes
push();
translate(leftEyePos[0], leftEyePos[1] - 0.2);
for (i = 0; i < 12; i++) {
noFill();
stroke(strokeColor);
strokeWeight(0.1);
rotate(angle);
line(0, 0, 0.6, 0);
}
pop();
//Right eyelashes
push();
translate(rightEyePos[0], rightEyePos[1] - 0.2);
for (i = 0; i < 12; i++) {
noFill();
stroke(strokeColor);
strokeWeight(0.1);
rotate(angle);
line(0, 0, 0.6, 0);
}
pop();
//Eyes
fill(0);
ellipse(leftEyePos[0], leftEyePos[1], leftEye2[0], leftEye2[1]);
ellipse(rightEyePos[0], rightEyePos[1], rightEye2[0], leftEye2[1]);
//Eye shine details
push();
noStroke();
fill(offWhite);
ellipse(leftEyePos[0] - 0.2, leftEye1[1], 0.3, 0.3); //Left eye
ellipse(rightEyePos[0] - 0.2, rightEye1[1] + 0.1, 0.3, 0.3); //Right eye
pop();
//Cheeks
push();
fill(cheekColour);
noStroke();
ellipse(-3, 1.1, 1.5, 0.8);
ellipse(3, 1.1, 1.5, 0.8);
pop();
//Right Cheek details
push();
strokeWeight(0.1);
translate(5.6, 0.7);
line(-2.5, 0.5, -2.25, 0.25);
line(-2.9, 0.5, -2.65, 0.25);
pop();
//Left Cheek details
push();
strokeWeight(0.1);
translate(-5.6, 0.7);
line(2.5, 0.25, 2.25, 0.5);
line(2.9, 0.25, 2.65, 0.5);
pop();
}
}
//Sliders
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.thinnessValue = map(settings[0], 0, 100, 10.5, 12.5);
this.headHeightValue = map(settings[1], 0, 100, 13, 15);
this.mouthHeightValue = map(settings[2], 0, 100, 1, 4);
this.mouthScaleValue = map(settings[3], 0, 100, 2.5, 4);
this.faceColor = int(map(settings[4], 0, 100, 1, 4));
this.hairColor = int(map(settings[5], 0, 100, 1, 6));
this.gender = map(settings[6], 0, 100, 1, 5);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(1);
settings[0] = map(this.thinnessValue, 10.5, 12.5, 0, 100);
settings[1] = map(this.headHeightValue, 13, 15, 0, 100);
settings[2] = map(this.mouthHeightValue, 1, 4, 0, 100);
settings[3] = map(this.mouthScaleValue, 2.5, 4, 0, 100);
settings[4] = map(this.faceColor, 1, 4, 0, 100);
settings[5] = map(this.hairColor, 1, 6, 0, 100);
settings[6] = map(this.gender, 1, 5, 0, 100);
return settings;
}
}
// given an array of [x,y] points, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for (var i = 0; i < list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
{
"000001": [
7.000000000000028,
74.00000000000003,
0,
100,
0,
60,
100
],
"000002": [
0,
71,
0,
80.00000000000001,
0,
40,
40
],
"000005": [
0,
0,
0,
100,
0,
0,
23
],
"000006": [
0,
47.000000000000064,
20,
100,
100,
60,
100
],
"000007": [
0,
100,
0,
100,
0,
80,
0
],
"000009": [
46,
71,
0,
88.00000000000003,
0,
60,
100
],
"000010": [
0,
0,
0,
100,
0,
0,
100
],
"000013": [
11.000000000000032,
79,
0,
100,
0,
0,
0
],
"000014": [
0,
98.00000000000004,
0,
100,
75,
80,
46
],
"000015": [
16.999999999999993,
79.99999999999999,
0,
100,
0,
60,
0
],
"000016": [
11.000000000000032,
30.99999999999996,
0,
76.00000000000001,
0,
60,
0
],
"000018": [
0,
24.00000000000002,
11.999999999999995,
100,
0,
0,
100
],
"000020": [
40.000000000000036,
0,
0,
100,
0,
60,
12
],
"000023": [
0,
24.00000000000002,
0,
100,
0,
60,
19
],
"000025": [
58.00000000000001,
79.99999999999999,
0,
100,
0,
60,
0
],
"000028": [
8.999999999999986,
100,
0,
100,
100,
60,
100
],
"000029": [
0,
0,
0,
100,
0,
0,
100
],
"000030": [
20.999999999999996,
41.99999999999999,
0,
100,
0,
0,
0
],
"000031": [
23.000000000000043,
79,
0,
71,
0,
0,
18
],
"000032": [
40.000000000000036,
33.00000000000001,
18.000000000000004,
63.00000000000002,
0,
60,
12
],
"000035": [
0,
67,
0,
100,
0,
80,
38
],
"000037": [
29.000000000000004,
67,
0,
100,
100,
80,
0
],
"000038": [
8.999999999999986,
40.000000000000036,
9.000000000000004,
100,
0,
60,
0
],
"000040": [
0,
25,
0,
100,
66.66666666666666,
80,
21.999999999999996
],
"000041": [
0,
100,
0,
100,
33.33333333333333,
80,
18
],
"000042": [
0,
68.99999999999994,
0,
88.00000000000003,
0,
80,
89.00000000000001
],
"000043": [
0,
32.00000000000003,
13.000000000000004,
69,
0,
60,
100
],
"000044": [
0,
100,
0,
100,
100,
80,
72
],
"000045": [
0,
79.99999999999999,
15,
86,
0,
60,
100
],
"000047": [
50,
29.000000000000004,
15,
25,
66.66666666666666,
80,
48
],
"000048": [
0,
0,
41.99999999999999,
100,
0,
80,
14.000000000000002
],
"000050": [
11.000000000000032,
82.00000000000003,
4.0000000000000036,
83.99999999999999,
0,
80,
0
],
"000051": [
59.999999999999964,
36.00000000000003,
20.000000000000004,
100,
66.66666666666666,
100,
14.000000000000002
],
"000052": [
0,
100,
0,
83,
0,
60,
0
],
"000054": [
0,
0,
0,
64,
0,
0,
100
],
"000055": [
0,
62.000000000000014,
10.000000000000002,
86,
0,
80,
0
],
"000056": [
0,
0,
5,
100,
0,
80,
17.000000000000004
],
"000058": [
12.00000000000001,
0,
0,
100,
0,
80,
100
],
"000060": [
71.99999999999997,
0,
0,
100,
100,
80,
9.999999999999998
],
"000064": [
9.999999999999964,
8.000000000000007,
0,
72.00000000000001,
0,
60,
0
],
"000065": [
37.999999999999986,
71.99999999999997,
0,
86,
0,
60,
0
],
"000068": [
0,
58.999999999999986,
5.999999999999997,
61,
0,
100,
15.000000000000002
],
"000069": [
8.999999999999986,
0,
0,
67,
0,
80,
0
],
"000071": [
0,
50.99999999999998,
8,
72.00000000000001,
0,
0,
68
],
"000073": [
0,
44.00000000000004,
0,
100,
0,
60,
100
],
"000076": [
0,
0,
0,
61.99999999999998,
0,
80,
13
],
"000077": [
0,
0,
0,
58.00000000000001,
0,
80,
100
],
"000078": [
8.999999999999986,
25,
0,
94,
0,
80,
61
],
"000079": [
0,
82.00000000000003,
0,
61.99999999999998,
0,
80,
10.999999999999998
],
"000080": [
0,
100,
0,
100,
0,
80,
0
],
"000081": [
0,
82.00000000000003,
6.999999999999999,
76.00000000000001,
0,
80,
0
],
"000083": [
0,
65.00000000000003,
0,
80.00000000000001,
0,
20,
100
],
"000085": [
45.000000000000014,
0,
0,
81,
0,
60,
100
],
"000086": [
0,
0,
0,
100,
0,
60,
15.000000000000002
],
"000088": [
0,
15.000000000000036,
0,
89,
0,
20,
64
],
"000091": [
0,
0,
0,
77.99999999999999,
0,
80,
0
],
"000092": [
0,
0,
0,
85,
0,
0,
67
],
"000096": [
0,
0,
0,
89,
0,
60,
67
],
"000097": [
0,
20.999999999999996,
0,
52.99999999999999,
0,
60,
47
],
"000099": [
0,
84.99999999999997,
5.999999999999997,
83,
0,
60,
95
],
"000100": [
0,
50,
0,
79,
0,
0,
24
],
"000103": [
0,
16.999999999999993,
0,
82,
0,
80,
80
],
"000104": [
0,
65.00000000000003,
0,
100,
0,
0,
0
],
"000106": [
0,
87.00000000000001,
0,
77.00000000000001,
0,
60,
95
],
"000108": [
11.000000000000032,
28.999999999999915,
0,
100,
0,
0,
95
],
"000109": [
0,
100,
0,
81,
0,
60,
0
],
"000110": [
12.99999999999999,
0,
0,
100,
0,
60,
20.999999999999996
],
"000111": [
12.99999999999999,
33.999999999999986,
0,
100,
100,
60,
12
],
"000114": [
0,
47.000000000000064,
0,
100,
33.33333333333333,
80,
0
],
"000115": [
0,
100,
0,
69,
0,
80,
17.000000000000004
],
"000116": [
12.00000000000001,
67,
0,
77.00000000000001,
0,
60,
0
],
"000117": [
0,
67,
5.999999999999997,
77.00000000000001,
100,
80,
100
],
"000118": [
0,
45.000000000000014,
0,
86.99999999999997,
66.66666666666666,
80,
100
],
"000121": [
0,
0,
0,
79,
66.66666666666666,
80,
72
],
"000122": [
0,
51.99999999999996,
0,
80.00000000000001,
0,
100,
7.000000000000001
],
"000125": [
16.999999999999993,
0,
0,
91.00000000000001,
0,
100,
13
],
"000126": [
0,
23.000000000000043,
0,
77.00000000000001,
66.66666666666666,
0,
100
],
"000129": [
0,
100,
0,
77.00000000000001,
0,
80,
0
],
"000131": [
0,
0,
0,
67,
66.66666666666666,
80,
60
],
"000132": [
24.00000000000002,
53.00000000000003,
0,
91.00000000000001,
100,
80,
100
],
"000133": [
0,
46.99999999999997,
0,
73.99999999999999,
0,
0,
21.999999999999996
],
"000134": [
0,
70.00000000000001,
0,
77.99999999999999,
100,
80,
6
],
"000135": [
0,
25.99999999999998,
1.0000000000000009,
92,
100,
80,
6
],
"000137": [
49.00000000000002,
46.99999999999997,
10.000000000000002,
83.99999999999999,
0,
60,
0
],
"000140": [
0,
0,
13.000000000000004,
75,
0,
0,
85.00000000000001
],
"000142": [
0,
42.99999999999997,
12.999999999999998,
100,
0,
80,
80
],
"000143": [
0,
50,
0,
77.00000000000001,
0,
0,
18
],
"000145": [
0,
50,
0,
82,
0,
80,
96
],
"000146": [
0,
50,
0,
86,
66.66666666666666,
60,
96
],
"000147": [
29.000000000000004,
0,
0,
82,
66.66666666666666,
0,
80
],
"000148": [
0,
45.000000000000014,
19.000000000000004,
77.99999999999999,
0,
80,
23
],
"000150": [
0,
29.000000000000004,
11.999999999999995,
67,
0,
40,
16.000000000000004
],
"000151": [
0,
100,
16,
92,
66.66666666666666,
80,
81.99999999999999
],
"000152": [
45.000000000000014,
48.00000000000004,
0,
67,
0,
60,
15.000000000000002
],
"000153": [
0,
50.99999999999998,
0,
69.99999999999999,
0,
60,
15.000000000000002
],
"000155": [
0,
100,
0,
86,
33.33333333333333,
40,
100
],
"000156": [
0,
0,
0,
79,
0,
0,
20.999999999999996
],
"000157": [
25,
7.000000000000028,
0,
79,
0,
0,
60
],
"000160": [
0,
100,
0,
83.99999999999999,
0,
80,
0
],
"000161": [
0,
74.00000000000003,
0,
72.99999999999999,
0,
80,
42.99999999999999
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// these control the colors used
ch3_bodyPrimary = [204, 204, 204];
ch3_bodySecondary = [128, 128, 128];
ch3_detailPrimary = [0, 0, 0];
ch3_detailSecondary = [0, 0, 255];
function CampbellFace() {
// draw strokes with rounded joints
// strokeJoin(ROUND);
// set colour mode to HSB
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
colorMode(HSB);
strokeJoin(ROUND);
// variables of facial structure
var nose_pos = average_point(positions.nose_bridge);
var eye1_pos = average_point(positions.left_eye);
var eye2_pos = average_point(positions.right_eye);
var upperLip = average_point(positions.top_lip);
var bottomLip = average_point(positions.bottom_lip);
var face_pos = average_point(positions.chin);
var half_height = positions.chin[7][1] - nose_pos[1];
var face_width = positions.chin[positions.chin.length-1][0] - positions.chin[0][0];
var x = nose_pos[0];
var y = nose_pos[1];
var w = 2 * face_width;
var h = 2.5 * half_height;
// bolleans for whether face is looking left or right
var lookingLeft = false;
var lookingRight = false;
// compare nose landmarks to check if looking left or right
if(Math.abs(positions.nose_bridge[3][0] - positions.nose_bridge[0][0]) > 0.03){
if(positions.nose_bridge[3][0] < positions.nose_bridge[0][0])
lookingLeft = true;
if(positions.nose_bridge[3][0] > positions.nose_bridge[0][0])
lookingRight = true;
}
else {
lookingLeft = true;
}
// adjustable variables of character identity
var gender = map(this.genderValue, 0, 100, 0, 1);
var hair = map(this.hairValue, 0, 100, 80, 200);
var curlookDirection = map(this.lookDirection, 0, 100, -15, 15);
var curEyelidTop_height = map(this.eyelidTop_height, 0, 100, 0, 70);
var curEyelidBottom_height = map(this.eyelidBottom_height, 0, 100, 0, 70);
var curHue = map(this.hue, 0, 100, 0, 360);
var curSaturation = map(this.saturation, 0, 100, 0, 100);
var curBrightnessPrimary = map(this.brightness, 0, 100, 50, 100);
var curBrightnessSecondary = map(this.brightness, 0, 100, 20, 70);
// sets object scale
var extent = 0;
if(h < w) {
extent = h / 2;
}
else {
extent = w / 2;
}
var scale = extent / 220.0;
// draw left ear if male
// draw rectangle from a centre point
rectMode(CENTER)
// if male face and is looking left
if(gender == 1 & lookingLeft == true) {
// draw ear
stroke(ch3_detailPrimary)
strokeWeight(10 * scale);
fill(curHue, curSaturation, curBrightnessPrimary);
rect(face_pos[0] - (10 * scale), eye2_pos[1] - (100 * scale), 50 * scale, hair * scale, 100 * scale, 100 * scale, 0, 0);
}
// if male and is looking right
if(gender == 1 & lookingRight == true) {
// draw ear
stroke(ch3_detailPrimary)
strokeWeight(10 * scale);
fill(curHue, curSaturation, curBrightnessPrimary);
rect(face_pos[0] + (10 * scale), eye1_pos[1] - (100 * scale), 50 * scale, hair * scale, 100 * scale, 100 * scale, 0, 0);
}
// head
// draw rectangle from a centre point
rectMode(CENTER);
// draw face
stroke(ch3_detailPrimary)
strokeWeight(10 * scale);
fill(curHue, curSaturation, curBrightnessPrimary);
rect(face_pos[0], face_pos[1] - (70 * scale), 300 * scale, 320 * scale, 200 * scale, 200 * scale, 0, 0);
// draw dissection
fill(curHue, curSaturation, curBrightnessSecondary);
ellipse(face_pos[0], face_pos[1] + (90 * scale), 300 * scale, 80 * scale);
// draw bone
strokeWeight(7 * scale);
fill(ch3_detailSecondary);
ellipse(face_pos[0], face_pos[1] + (90 * scale), 150 * scale, 30 * scale);
// draw right ear if male
rectMode(CENTER);
// if male and looking left
if(gender == 1 & lookingLeft == true) {
// draw ear
stroke(ch3_detailPrimary)
strokeWeight(10 * scale);
fill(curHue, curSaturation, curBrightnessPrimary);
rect(face_pos[0] + (30 * scale), eye2_pos[1] - (100 * scale), 50 * scale, hair * scale, 100 * scale, 100 * scale, 0, 0);
//cover
noStroke();
fill(curHue, curSaturation, curBrightnessPrimary);
rectMode(CENTER);
rect(face_pos[0] + (30 * scale), eye2_pos[1] - (5 * scale), 70 * scale, 150 * scale);
}
// if male and looking right
if(gender == 1 & lookingRight == true) {
// draw ear
stroke(ch3_detailPrimary)
strokeWeight(10 * scale);
fill(curHue, curSaturation, curBrightnessPrimary);
rect(face_pos[0] - (30 * scale), eye1_pos[1] - (100 * scale), 50 * scale, hair * scale, 100 * scale, 100 * scale, 0, 0);
//cover
noStroke();
fill(curHue, curSaturation, curBrightnessPrimary);
rectMode(CENTER);
rect(face_pos[0] - (30 * scale), eye1_pos[1] - (5 * scale), 70 * scale, 150 * scale);
}
// features for when looking left
if(lookingLeft == true) {
// left eye
stroke(ch3_detailPrimary);
strokeWeight(7 * scale);
fill(ch3_detailSecondary);
ellipse(eye1_pos[0], eye1_pos[1], 80 * scale, 80 * scale);
// pupil
noStroke();
fill(ch3_detailPrimary);
arc(eye1_pos[0] + curlookDirection * scale, eye1_pos[1], (30) * scale, (50) * scale, 20, 340, PIE);
// eyelid
strokeWeight(7 * scale);
stroke(ch3_detailPrimary);
fill(curHue, curSaturation, curBrightnessSecondary);
// top eyelid
arc(eye1_pos[0], eye1_pos[1], 80 * scale, 80 * scale, 265 - curEyelidTop_height, 275 + curEyelidTop_height, CHORD);
// bottom eyelid
arc(eye1_pos[0], eye1_pos[1], 80 * scale, 80 * scale, 85 - curEyelidBottom_height, 95 + curEyelidBottom_height, CHORD);
// eyebrow
stroke(ch3_detailPrimary)
noFill();
arc(eye1_pos[0], (eye1_pos[1]), 130 * scale, 110 * scale, 240, 300);
// nose
// if female draw bird style
if(gender < 1) {
// translate to an offset of the centre of the face
push();
translate(face_pos[0] - (100 * scale), face_pos[1] - (70 * scale));
// draw beak
stroke(ch3_detailPrimary)
strokeWeight(7 * scale);
fill(curHue, curSaturation, curBrightnessSecondary);
arc(0, 0, 250 * scale, 150 * scale, 335, 385, PIE);
// draw mouth
stroke(ch3_detailPrimary);
strokeWeight(7 * scale);
line(5 * scale, 0 * scale, 80 * scale, 0 * scale);
stroke(ch3_detailPrimary)
strokeWeight(7 * scale);
noFill();
arc(110 * scale, 0 * scale, 50 * scale, 50 * scale, 140, 210);
// teeth
stroke(ch3_detailPrimary)
strokeWeight(7 * scale);
fill(ch3_detailSecondary);
// check teeth value
if(Math.abs(upperLip[1] - bottomLip[1]) > 0.28) {
arc(40 * scale, 0 * scale, 20 * scale, 40 * scale, 0, 180, CHORD);
} if(Math.abs(upperLip[1] - bottomLip[1]) > 0.2) {
arc(60 * scale, 0 * scale, 20 * scale, 40 * scale, 0, 180, CHORD);
} if(Math.abs(upperLip[1] - bottomLip[1]) < 0.2) {
}
pop();
}
// if male draw dog style
if(gender == 1) {
// translate to an offset of centre of the face
push();
translate(face_pos[0] - (130 * scale), face_pos[1] - (100 * scale));
// draw snout
stroke(ch3_detailPrimary)
strokeWeight(10 * scale);
fill(curHue, curSaturation, curBrightnessPrimary);
// top snout
rectMode(CORNER);
rect(0, 0, 140 * scale, 45 * scale, 18 * scale, 0, 0, 18 * scale);
stroke(ch3_detailPrimary)
strokeWeight(10 * scale);
fill(curHue, curSaturation, curBrightnessPrimary);
// bottom snout
rect(30 * scale, 45 * scale, 110 * scale, 35 * scale, 14 * scale, 0, 0, 14 * scale);
noStroke();
fill(curHue, curSaturation, curBrightnessPrimary);
// re-fill / cover
rect(130 * scale, -7 * scale, 60 * scale, 100 * scale);
// draw nose
noStroke();
fill(ch3_detailPrimary);
push();
rotate(10);
ellipse(0 * scale, 0 * scale, 40 * scale, 28 * scale);
pop();
// mouth
stroke(ch3_detailPrimary)
strokeWeight(7 * scale);
noFill();
arc(155 * scale, 40 * scale, 50 * scale, 50 * scale, 140, 210);
// teeth
stroke(ch3_detailPrimary)
strokeWeight(7 * scale);
fill(ch3_detailSecondary);
// check teeth value
if(Math.abs(upperLip[1] - bottomLip[1]) > 0.28) {
arc(70 * scale, 45 * scale, 20 * scale, 40 * scale, 0, 180, CHORD);
} if(Math.abs(upperLip[1] - bottomLip[1]) > 0.2) {
arc(90 * scale, 45 * scale, 20 * scale, 40 * scale, 0, 180, CHORD);
} if(Math.abs(upperLip[1] - bottomLip[1]) < 0.2) {
}
pop();
}
// right eye
// eye
stroke(ch3_detailPrimary);
strokeWeight(7 * scale);
fill(ch3_detailSecondary);
ellipse(eye2_pos[0], eye2_pos[1], 80 * scale, 80 * scale);
// pupil
noStroke();
fill(ch3_detailPrimary);
arc(eye2_pos[0] + curlookDirection * scale, eye2_pos[1], (30) * scale, (50) * scale, 20, 340, PIE);
// eyelid
strokeWeight(7 * scale);
stroke(ch3_detailPrimary);
fill(curHue, curSaturation, curBrightnessSecondary);
// top eyelid
arc(eye2_pos[0], eye2_pos[1], 80 * scale, 80 * scale, 265 - curEyelidTop_height, 275 + curEyelidTop_height, CHORD);
// bottom eyelid
arc(eye2_pos[0], eye2_pos[1], 80 * scale, 80 * scale, 85 - curEyelidBottom_height, 95 + curEyelidBottom_height, CHORD);
// eyebrow
stroke(ch3_detailPrimary)
noFill();
arc(eye2_pos[0], (eye2_pos[1]), 130 * scale, 110 * scale, 240, 300);
}
// facial feature if looking right
if(lookingRight == true) {
// right eye
stroke(ch3_detailPrimary);
strokeWeight(7 * scale);
fill(ch3_detailSecondary);
ellipse(eye2_pos[0], eye2_pos[1], 80 * scale, 80 * scale);
// pupil
noStroke();
fill(ch3_detailPrimary);
arc(eye2_pos[0] + curlookDirection * scale, eye2_pos[1], (30) * scale, (50) * scale, 20, 340, PIE);
// eyelid
strokeWeight(7 * scale);
stroke(ch3_detailPrimary);
fill(curHue, curSaturation, curBrightnessSecondary);
// top eyelid
arc(eye2_pos[0], eye2_pos[1], 80 * scale, 80 * scale, 265 - curEyelidTop_height, 275 + curEyelidTop_height, CHORD);
// bottom eyelid
arc(eye2_pos[0], eye2_pos[1], 80 * scale, 80 * scale, 85 - curEyelidBottom_height, 95 + curEyelidBottom_height, CHORD);
// eyebrow
stroke(ch3_detailPrimary)
noFill();
arc(eye2_pos[0], (eye2_pos[1]), 130 * scale, 110 * scale, 240, 300);
// nose
// if female draw bird style
if(gender < 1) {
// translate to an offset of the centre of the face
push();
translate(face_pos[0] + (120 * scale), face_pos[1] - (70 * scale));
// draw beak
stroke(ch3_detailPrimary)
strokeWeight(7 * scale);
fill(curHue, curSaturation, curBrightnessSecondary);
arc(0, 0, 250 * scale, 150 * scale, 155, 205, PIE);
// draw mouth
stroke(ch3_detailPrimary);
strokeWeight(7 * scale);
line(-5 * scale, 0 * scale, -80 * scale, 0 * scale);
stroke(ch3_detailPrimary)
strokeWeight(7 * scale);
noFill();
arc(-110 * scale, 0 * scale, 50 * scale, 50 * scale, 320, 390);
// teeth
stroke(ch3_detailPrimary)
strokeWeight(7 * scale);
fill(ch3_detailSecondary);
// check teeth value
if(Math.abs(upperLip[1] - bottomLip[1]) > 0.28) {
arc(-40 * scale, 0 * scale, 20 * scale, 40 * scale, 0, 180, CHORD);
} if(Math.abs(upperLip[1] - bottomLip[1]) > 0.2) {
arc(-60 * scale, 0 * scale, 20 * scale, 40 * scale, 0, 180, CHORD);
} if(Math.abs(upperLip[1] - bottomLip[1]) < 0.2) {
}
pop();
}
// if male draw dog style
if(gender == 1) {
// translate to an offset of the centre of the face
push();
translate(face_pos[0], face_pos[1] - (100 * scale));
// draw snout
stroke(ch3_detailPrimary)
strokeWeight(10 * scale);
fill(curHue, curSaturation, curBrightnessPrimary);
// top snout
rectMode(CORNER);
rect(0, 0, 140 * scale, 45 * scale, 0, 18 * scale, 18 * scale, 0);
stroke(ch3_detailPrimary)
strokeWeight(10 * scale);
fill(curHue, curSaturation, curBrightnessPrimary);
// bottom snout
rect(0 * scale, 45 * scale, 110 * scale, 35 * scale, 0, 14 * scale, 14 * scale, 0);
noStroke();
fill(curHue, curSaturation, curBrightnessPrimary);
// re-fill / cover
rect(-50 * scale, -7 * scale, 60 * scale, 100 * scale);
// draw nose
noStroke();
fill(ch3_detailPrimary);
push();
rotate(-10);
ellipse(140 * scale, 30 * scale, 40 * scale, 28 * scale);
pop();
// mouth
stroke(ch3_detailPrimary)
strokeWeight(7 * scale);
noFill();
arc(-15 * scale, 50 * scale, 50 * scale, 50 * scale, 320, 390);
// teeth
stroke(ch3_detailPrimary)
strokeWeight(7 * scale);
fill(ch3_detailSecondary);
// check teeth value
if(Math.abs(upperLip[1] - bottomLip[1]) > 0.28) {
arc(40 * scale, 45 * scale, 20 * scale, 40 * scale, 0, 180, CHORD);
} if(Math.abs(upperLip[1] - bottomLip[1]) > 0.2) {
arc(60 * scale, 45 * scale, 20 * scale, 40 * scale, 0, 180, CHORD);
} if(Math.abs(upperLip[1] - bottomLip[1]) < 0.2) {
}
pop();
}
// left eye
stroke(ch3_detailPrimary);
strokeWeight(7 * scale);
fill(ch3_detailSecondary);
ellipse(eye1_pos[0], eye1_pos[1], 80 * scale, 80 * scale);
// pupil
noStroke();
fill(ch3_detailPrimary);
arc(eye1_pos[0] + curlookDirection * scale, eye1_pos[1], (30) * scale, (50) * scale, 20, 340, PIE);
// eyelid
strokeWeight(7 * scale);
stroke(ch3_detailPrimary);
fill(curHue, curSaturation, curBrightnessSecondary);
// top eyelid
arc(eye1_pos[0], eye1_pos[1], 80 * scale, 80 * scale, 265 - curEyelidTop_height, 275 + curEyelidTop_height, CHORD);
// bottom eyelid
arc(eye1_pos[0], eye1_pos[1], 80 * scale, 80 * scale, 85 - curEyelidBottom_height, 95 + curEyelidBottom_height, CHORD);
// eyebrow
stroke(ch3_detailPrimary)
noFill();
arc(eye1_pos[0], (eye1_pos[1]), 130 * scale, 110 * scale, 240, 300);
}
// colorMode(RGB);
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.genderValue = settings[0];
this.hairValue = settings[1];
this.lookDirection = settings[2];
this.eyelidTop_height = settings[3];
this.eyelidBottom_height = settings[4];
this.hue = settings[5];
this.saturation = settings[6];
this.brightness = settings[7];
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
properties = new Array(8);
properties[0] = this.genderValue;
properties[1] = this.hairValue;
properties[2] = this.lookDirection;
properties[3] = this.eyelidTop_height;
properties[4] = this.eyelidBottom_height;
properties[5] = this.hue;
properties[6] = this.saturation;
properties[7] = this.brightness;
return properties;
}
}
// given a point, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for(var i=0; i<list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
{
"000001": [
65,
57,
51,
68,
87,
5,
29,
42
],
"000002": [
50,
50,
36,
50,
87,
0,
50,
50
],
"000058": [
50,
50,
76,
71,
78,
4,
0,
0
],
"000005": [
50,
50,
50,
85,
62,
10,
45,
77
],
"000006": [
50,
50,
93,
59,
55,
8,
41,
22
],
"000007": [
100,
49,
50,
71,
38,
50,
0,
0
],
"000009": [
50,
50,
31,
50,
100,
5,
41,
29
],
"000010": [
50,
50,
50,
87,
70,
10,
31,
74
],
"000013": [
100,
33,
76,
47,
89,
13,
33,
78
],
"000014": [
50,
50,
50,
73,
85,
50,
0,
0
],
"000015": [
100,
65,
62,
89,
100,
7,
33,
13
],
"000016": [
100,
27,
99,
50,
100,
5,
37,
16
],
"000018": [
50,
50,
50,
70,
93,
11,
32,
65
],
"000020": [
100,
100,
77,
71,
100,
6,
33,
3
],
"000023": [
100,
17,
100,
51,
100,
5,
23,
0
],
"000025": [
100,
0,
48,
66,
66,
6,
32,
15
],
"000028": [
50,
50,
50,
56,
100,
4,
44,
36
],
"000029": [
50,
50,
50,
87,
70,
10,
31,
74
],
"000030": [
100,
79,
76,
59,
94,
9,
33,
40
],
"000031": [
50,
50,
50,
85,
62,
10,
45,
77
],
"000032": [
100,
50,
77,
71,
100,
6,
33,
3
],
"000035": [
50,
50,
50,
50,
50,
50,
0,
0
],
"000037": [
100,
0,
83,
50,
71,
50,
0,
0
],
"000038": [
100,
49,
50,
71,
91,
50,
0,
0
],
"000041": [
100,
100,
0,
45,
100,
50,
0,
0
],
"000042": [
50,
50,
50,
66,
67,
10,
43,
74
],
"000043": [
50,
50,
38,
43,
62,
4,
26,
2
],
"000044": [
50,
50,
50,
73,
85,
50,
0,
0
],
"000045": [
50,
50,
50,
56,
100,
4,
47,
52
],
"000050": [
100,
49,
50,
57,
100,
50,
0,
0
],
"000051": [
100,
0,
59,
60,
85,
0,
0,
49
],
"000048": [
100,
82,
50,
88,
77,
50,
0,
0
],
"000047": [
50,
50,
50,
77,
50,
6,
18,
0
],
"000040": [
50,
50,
50,
65,
70,
4,
19,
6
],
"000052": [
100,
65,
70,
57,
84,
2,
20,
0
],
"000054": [
50,
50,
44,
50,
100,
9,
27,
57
],
"000055": [
100,
53,
42,
61,
78,
38,
0,
0
],
"000056": [
50,
50,
41,
81,
66,
5,
0,
0
],
"000060": [
100,
0,
0,
50,
90,
4,
28,
0
],
"000064": [
100,
59,
52,
75,
89,
6,
28,
8
],
"000065": [
100,
76,
41,
81,
78,
5,
0,
0
],
"000068": [
100,
82,
72,
63,
65,
15,
0,
50
],
"000069": [
100,
41,
63,
0,
90,
31,
0,
0
],
"000071": [
50,
50,
50,
85,
62,
10,
45,
77
],
"000073": [
50,
50,
27,
85,
62,
2,
45,
21
],
"000076": [
100,
94,
25,
75,
89,
6,
16,
0
],
"000077": [
50,
50,
76,
71,
78,
4,
0,
0
],
"000078": [
50,
50,
50,
73,
85,
50,
0,
0
],
"000079": [
100,
0,
63,
66,
66,
5,
37,
48
],
"000080": [
100,
59,
18,
53,
79,
34,
0,
0
],
"000081": [
100,
34,
58,
60,
94,
46,
0,
0
],
"000083": [
50,
50,
39,
55,
81,
4,
46,
30
],
"000085": [
50,
50,
62,
53,
42,
3,
34,
19
],
"000086": [
50,
50,
50,
64,
92,
6,
33,
18
],
"000088": [
50,
50,
64,
61,
90,
5,
53,
61
],
"000091": [
100,
45,
45,
95,
100,
33,
0,
0
],
"000092": [
50,
50,
45,
65,
58,
11,
38,
67
],
"000096": [
50,
50,
50,
40,
71,
0,
38,
0
],
"000097": [
50,
50,
52,
44,
40,
6,
37,
43
],
"000099": [
50,
50,
50,
53,
100,
3,
30,
10
],
"000100": [
50,
50,
74,
48,
41,
7,
35,
31
],
"000103": [
50,
50,
27,
51,
85,
5,
30,
5
],
"000104": [
100,
18,
50,
44,
83,
8,
44,
54
],
"000108": [
50,
50,
37,
59,
76,
10,
38,
75
],
"000106": [
50,
50,
27,
50,
100,
5,
40,
0
],
"000109": [
100,
50,
57,
50,
70,
5,
31,
21
],
"000110": [
50,
50,
50,
50,
88,
5,
37,
23
],
"000111": [
50,
50,
74,
50,
94,
11,
27,
68
],
"000114": [
100,
29,
49,
51,
63,
5,
19,
0
],
"000115": [
100,
0,
50,
67,
79,
7,
18,
71
],
"000116": [
100,
59,
58,
52,
91,
3,
26,
28
],
"000117": [
50,
50,
66,
85,
78,
23,
0,
0
],
"000118": [
50,
50,
23,
61,
90,
0,
18,
0
],
"000121": [
50,
50,
63,
49,
81,
4,
30,
0
],
"000122": [
50,
50,
52,
57,
85,
8,
22,
56
],
"000125": [
100,
0,
48,
53,
76,
20,
0,
26
],
"000126": [
50,
50,
54,
62,
54,
11,
16,
70
],
"000129": [
100,
53,
72,
53,
81,
20,
0,
0
],
"000131": [
50,
50,
100,
63,
89,
4,
4,
0
],
"000132": [
50,
50,
64,
66,
89,
18,
0,
0
],
"000133": [
50,
50,
66,
49,
73,
8,
28,
42
],
"000134": [
100,
0,
0,
55,
80,
51,
0,
0
],
"000135": [
100,
28,
100,
52,
96,
19,
0,
0
],
"000137": [
100,
62,
91,
65,
86,
6,
23,
15
],
"000140": [
50,
50,
38,
55,
82,
10,
33,
61
],
"000142": [
50,
50,
44,
60,
83,
6,
39,
0
],
"000143": [
100,
39,
64,
63,
80,
7,
22,
28
],
"000145": [
50,
50,
46,
58,
100,
5,
26,
0
],
"000146": [
50,
50,
100,
43,
89,
0,
37,
0
],
"000147": [
50,
50,
72,
53,
53,
8,
37,
64
],
"000148": [
50,
50,
100,
59,
74,
0,
13,
0
],
"000150": [
100,
74,
49,
100,
52,
0,
50,
52
],
"000151": [
62,
53,
51,
66,
89,
6,
21,
0
],
"000152": [
100,
39,
44,
64,
100,
5,
23,
33
],
"000153": [
100,
23,
54,
60,
85,
4,
26,
0
],
"000155": [
50,
50,
49,
51,
75,
0,
49,
50
],
"000156": [
50,
50,
52,
58,
62,
8,
30,
45
],
"000157": [
50,
50,
43,
62,
77,
8,
22,
63
],
"000160": [
100,
44,
50,
56,
75,
38,
0,
0
],
"000161": [
50,
50,
31,
62,
73,
5,
0,
0
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
//var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
var NUM_SLIDERS = 6;
// other variables can be in here too
//helmet colors
const chen_red = [197, 17, 18];
const lime = [100, 255, 51];
const cyan = [0, 255, 232];
const yellow = [255, 243, 0];
const brown = [95, 60, 12];
const chen_black = [50];
const white = [210];
//eye colors
const eye_blue = [0, 182, 255, 75];
const eye_black = [4, 27, 30, 30];
const eye_green = [20, 135, 49, 75];
const eye_brown = [74, 35, 6, 50];
//mask colors
const mask = [157, 200, 217];
const mask_shade = [76, 95, 109];
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i=0; i<s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len , sum_y / s_len ];
}
// This where you define your own face object
function ChenFace() {
// these are state variables for a face
// (your variables should be different!)
this.helmet_color = 2; // variations of hair colors
this.eye_color = 4; // variations of eye colors
this.gender = 1;
this.ref_shift = 1.5; //location of reflection
this.ref_shift_2 = 1;
// example of a function *inside* the face object.
// this draws a segment, and do_loop will connect the ends if true
this.draw_segment = function(segment, do_loop) {
for(let i=0; i<segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
ellipse(px, py, 0.1);
if(i < segment.length - 1) {
let nx = segment[i+1][0];
let ny = segment[i+1][1];
line(px, py, nx, ny);
}
else if(do_loop) {
let nx = segment[0][0];
let ny = segment[0][1];
line(px, py, nx, ny);
}
}
};
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
//helmet
stroke(0, 150);
strokeWeight(0.2);
if (this.helmet_color >= 0 && this.helmet_color <= 1){
fill(chen_black);
} else if (this.helmet_color > 1 && this.helmet_color <= 2){
fill(brown);
} else if (this.helmet_color > 2 && this.helmet_color <= 3){
fill(chen_red);
} else if (this.helmet_color > 3 && this.helmet_color <= 4){
fill(yellow);
} else if (this.helmet_color > 4 && this.helmet_color <= 5){
fill(white);
}
beginShape();
curveVertex(positions.chin[0][0]-0.2, positions.chin[0][1]-0.5);
curveVertex(positions.chin[0][0]-0.2, positions.chin[0][1]-0.5);
curveVertex(positions.chin[0][0]-0.2, positions.chin[0][1]+2.5);
curveVertex(positions.chin[16][0]+0.2, positions.chin[16][1]+2.5);
curveVertex(positions.chin[16][0]+0.2, positions.chin[16][1]-0.5);
curveVertex(positions.chin[16][0]+0.2, positions.chin[16][1]-0.5);
endShape();
beginShape();
vertex(positions.chin[0][0]-0.2, positions.chin[0][1]-0.45);
quadraticVertex(0, positions.nose_bridge[0][1]-4, positions.chin[16][0]+0.2, positions.chin[16][1]-0.45)
endShape();
//mask
noStroke();
fill(mask);
beginShape();
curveVertex(positions.chin[0][0], positions.chin[0][1]);
curveVertex(positions.chin[2][0], positions.chin[2][1]);
curveVertex(positions.chin[3][0]-0.1, positions.chin[3][1]);
curveVertex(positions.nose_tip[2][0], positions.nose_tip[2][1]+0.6);
curveVertex(positions.chin[13][0]-0.1, positions.chin[13][1]);
curveVertex(positions.chin[14][0], positions.chin[14][1]);
curveVertex(positions.chin[16][0], positions.chin[16][1]);
curveVertex(positions.right_eyebrow[4][0]-0.2, positions.right_eyebrow[4][1]);
curveVertex(positions.nose_bridge[0][0], positions.nose_bridge[0][1]-1);
curveVertex(positions.left_eyebrow[0][0]+0.2, positions.left_eyebrow[0][1]);
curveVertex(positions.chin[0][0], positions.chin[0][1]);
curveVertex(positions.chin[2][0], positions.chin[2][1]);
curveVertex(positions.chin[3][0], positions.chin[3][1]);
endShape();
//eyes
noStroke();
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye);
if (this.eye_color > 0 && this.eye_color <= 1){
fill(eye_black);
} else if (this.eye_color >1 && this.eye_color <= 2){
fill(eye_brown);
} else if (this.eye_color >2 && this.eye_color <= 3){
fill(eye_green);
} else if (this.eye_color >3 && this.eye_color <= 4) {
fill(eye_blue);
}
if (this.gender >= 0 && this.gender <= 0.5){ //softer edges for female
ellipse(left_eye_pos[0], left_eye_pos[1]+0.25, 0.38, 0.28);
ellipse(right_eye_pos[0], right_eye_pos[1]+0.25, 0.38, 0.28);
fill(255, 50); // eye reflection
ellipse(left_eye_pos[0]+0.1, left_eye_pos[1]+0.2, 0.1);
ellipse(right_eye_pos[0]+0.1, right_eye_pos[1]+0.2, 0.1);
} else{ //harder edges for male
beginShape(); //left eye
vertex(positions.left_eye[0][0], positions.left_eye[0][1]+0.25);
vertex(positions.left_eye[1][0],positions.left_eye[1][1]+0.25);
vertex(positions.left_eye[2][0], positions.left_eye[2][1]+0.25);
vertex(positions.left_eye[3][0], positions.left_eye[3][1]+0.25);
vertex(positions.left_eye[4][0], positions.left_eye[4][1]+0.25);
vertex(positions.left_eye[5][0], positions.left_eye[5][1]+0.25);
endShape();
beginShape(); //right eye
vertex(positions.right_eye[0][0], positions.right_eye[0][1]+0.25);
vertex(positions.right_eye[1][0],positions.right_eye[1][1]+0.25);
vertex(positions.right_eye[2][0], positions.right_eye[2][1]+0.25);
vertex(positions.right_eye[3][0], positions.right_eye[3][1]+0.25);
vertex(positions.right_eye[4][0], positions.right_eye[4][1]+0.25);
vertex(positions.right_eye[5][0], positions.right_eye[5][1]+0.25);
endShape();
// eye reflection
fill(255, 25);
ellipse(left_eye_pos[0]-0.08, left_eye_pos[1]+0.21, 0.15, 0.11);
ellipse(right_eye_pos[0]-0.08, right_eye_pos[1]+0.21, 0.15, 0.11);
}
//blush
if (this.gender >= 0 && this.gender <= 0.5){
fill(255, 222, 254);
ellipse(positions.left_eye[0][0], positions.left_eye[0][1]+0.6, 0.5, 0.1);
ellipse(positions.right_eye[3][0], positions.right_eye[3][1]+0.6, 0.5, 0.1);
} else {
fill(255, 222, 254, 150);
ellipse(positions.left_eye[0][0], positions.left_eye[0][1]+0.6, 0.4, 0.08);
ellipse(positions.right_eye[3][0], positions.right_eye[3][1]+0.6, 0.4, 0.08);
}
//nose
let nose_top = positions.nose_bridge[1];
let nose_bottom = positions.nose_bridge[3];
let nose_end = null;
stroke(76, 95, 109, 25);
strokeWeight(0.08);
line(nose_top[0], nose_top[1], nose_bottom[0], nose_bottom[1]-0.15);
//mouth
noStroke();
fill(255, 25);
beginShape();
vertex(positions.top_lip[1][0],positions.top_lip[1][1]-0.2);
vertex(positions.top_lip[2][0], positions.top_lip[2][1]-0.2);
vertex(positions.top_lip[3][0], positions.top_lip[3][1]-0.2);
vertex(positions.top_lip[4][0], positions.top_lip[4][1]-0.2);
vertex(positions.top_lip[5][0], positions.top_lip[5][1]-0.2);
vertex(positions.bottom_lip[10][0], positions.bottom_lip[10][1]-0.3);
vertex(positions.bottom_lip[9][0], positions.bottom_lip[9][1]-0.3);
vertex(positions.bottom_lip[8][0], positions.bottom_lip[8][1]-0.3);
endShape();
//reflection
let curRefShift = this.ref_shift;
let curRefShift_2 = this.ref_shift_2;
fill(254, 252, 255, 220);
if(nose_top[0] > nose_bottom[0]){
ellipse(positions.nose_bridge[3][0] + curRefShift, right_eye_pos[1]+0.22, 1, 0.5);
ellipse(positions.top_lip[3][0] - curRefShift_2 , positions.top_lip[1][1]-0.2, 0.2, 0.1);
} else{
ellipse(positions.nose_bridge[3][0] - curRefShift, right_eye_pos[1]+0.22, 1, 0.5);
ellipse(positions.top_lip[3][0] + curRefShift_2 , positions.top_lip[1][1]-0.2, 0.2, 0.1);
}
//mask outline
noFill();
stroke(0, 200);
strokeWeight(0.2);
beginShape();
curveVertex(positions.chin[0][0], positions.chin[0][1]);
curveVertex(positions.chin[2][0], positions.chin[2][1]);
curveVertex(positions.chin[3][0]-0.1, positions.chin[3][1]);
curveVertex(positions.nose_tip[2][0], positions.nose_tip[2][1]+0.6);
curveVertex(positions.chin[13][0]-0.1, positions.chin[13][1]);
curveVertex(positions.chin[14][0], positions.chin[14][1]);
curveVertex(positions.chin[16][0], positions.chin[16][1]);
curveVertex(positions.right_eyebrow[4][0]-0.2, positions.right_eyebrow[4][1]);
curveVertex(positions.nose_bridge[0][0], positions.nose_bridge[0][1]-1);
curveVertex(positions.left_eyebrow[0][0]+0.2, positions.left_eyebrow[0][1]);
curveVertex(positions.chin[0][0], positions.chin[0][1]);
curveVertex(positions.chin[2][0], positions.chin[2][1]);
curveVertex(positions.chin[3][0], positions.chin[3][1]);
endShape();
//decorations
if (this.gender >= 0 && this.gender <= 0.5){ //flower hat for female
stroke(0, 200);
strokeWeight(0.1);
fill(255, 192, 183);
push();
angleMode(DEGREES);
if (nose_top[0] > nose_bottom[0]){
translate(positions.chin[16][0]-0.1, positions.chin[16][1]-0.5);
} else {
translate(positions.chin[0][0]+0.1, positions.chin[0][1]-0.5);
}
for (let i = 0; i < 5; i++){
ellipse(0, 0.35, 0.37, 0.75);
rotate(360/5);
}
noStroke();
fill(236, 180, 172, 200);
ellipse(0, 0, 0.3);
pop();
} else { //plant hat for male
stroke(0, 200);
strokeWeight(0.1);
push();
translate(positions.nose_bridge[0][0], positions.nose_bridge[0][1]-1.3);
fill(3, 77, 13);
if (nose_top[0] > nose_bottom[0]){
beginShape();
vertex(-0.2, -0.4);
vertex(-0.2, -0.7);
quadraticVertex(-1.1, -0.85, -1.5, -1.4);
quadraticVertex(-0.6, -1.9, -0.1, -1.05);
quadraticVertex(0.55, -2.4, 1.4, -1.8);
quadraticVertex(0.9, -0.7, 0.2, -0.7);
vertex(0.2, -0.4);
vertex(-0.2, -0.4);
endShape();
} else {
beginShape();
vertex(0.2, -0.4);
vertex(0.2, -0.7);
quadraticVertex(1.1, -0.85, 1.5, -1.4);
quadraticVertex(0.6, -1.9, 0.1, -1.05);
quadraticVertex(-0.55, -2.4, -1.4, -1.8);
quadraticVertex(-0.9, -0.7, -0.2, -0.7);
vertex(-0.2, -0.4);
vertex(0.2, -0.4);
endShape();
}
pop();
}
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.helmet_color = map(settings[0], 0, 100, 0, 5);
this.eye_color = map(settings[1], 0, 100, 1, 4);
this.gender = map(settings[2], 0, 100, 0, 1);
this.ref_shift = map(settings[3], 0, 100, 1, 1.8);
this.ref_shift_2 = map(settings[4], 0, 100, 0.3, 1.2);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(6);
settings[0] = map(this.helmet_color, 0, 5, 0, 100);
settings[1] = map(this.eye_color, 1, 4, 0, 100);
settings[2] = map(this.gender, 0, 1, 0, 100);
settings[3] = map(this.ref_shift, 1, 1.8, 0, 100);
settings[4] = map(this.ref_shift_2, 0.3, 1.2, 0, 100);
return settings;
}
}
{
"000001": [
63,
26,
0,
100,
33,
null
],
"000002": [
46,
11.000000000000004,
0,
68,
21.000000000000004,
null
],
"000005": [
68,
16,
0,
68,
85.99999999999999,
null
],
"000006": [
21.000000000000004,
11.000000000000004,
0,
68,
21.000000000000004,
null
],
"000007": [
0,
15,
100,
69,
30,
null
],
"000009": [
23,
13.000000000000004,
0,
100,
30,
null
],
"000010": [
65,
81,
0,
56.99999999999999,
48.00000000000001,
null
],
"000013": [
69,
98,
100,
81.00000000000001,
52.99999999999999,
null
],
"000014": [
0,
0,
0,
81.00000000000001,
26.999999999999996,
null
],
"000015": [
27,
0,
100,
59,
67,
null
],
"000016": [
14.000000000000002,
15,
100,
80.00000000000001,
61.999999999999986,
null
],
"000018": [
71,
33,
0,
46.999999999999986,
61.999999999999986,
null
],
"000020": [
16.000000000000004,
0,
100,
50.99999999999999,
61.999999999999986,
null
],
"000023": [
11.000000000000002,
2.0000000000000018,
100,
56.99999999999999,
59.999999999999986,
null
],
"000025": [
28.000000000000004,
0,
100,
84.00000000000001,
61.999999999999986,
null
],
"000028": [
21.999999999999996,
0,
0,
48.999999999999986,
61.999999999999986,
null
],
"000029": [
64,
75,
0,
55.99999999999999,
57.999999999999986,
null
],
"000030": [
64,
17,
100,
94,
23.000000000000004,
null
],
"000031": [
63,
83,
0,
30,
74.99999999999999,
null
],
"000032": [
72,
0,
100,
34,
42,
null
],
"000035": [
0,
24,
0,
30,
40,
null
],
"000037": [
0,
16,
100,
100,
1.000000000000001,
null
],
"000038": [
19,
80.00000000000001,
100,
55.99999999999999,
30,
null
],
"000040": [
0,
18.000000000000004,
0,
73.00000000000001,
30,
null
],
"000041": [
0,
17,
100,
100,
0,
null
],
"000042": [
75,
69.99999999999999,
0,
68,
9.000000000000002,
null
],
"000043": [
40,
13.999999999999998,
0,
40.00000000000001,
46,
null
],
"000044": [
0,
0,
0,
40.00000000000001,
46,
null
],
"000045": [
43,
20.000000000000004,
0,
40.00000000000001,
46,
null
],
"000047": [
0,
0,
0,
53.99999999999999,
52.99999999999999,
null
],
"000048": [
0,
0,
100,
53.99999999999999,
52.99999999999999,
null
],
"000050": [
0,
13.000000000000004,
100,
86.00000000000001,
52.99999999999999,
null
],
"000051": [
100,
11.000000000000004,
100,
53.99999999999999,
52.99999999999999,
null
],
"000052": [
32,
80.00000000000001,
100,
53.99999999999999,
52.99999999999999,
null
],
"000054": [
67,
79,
0,
53.99999999999999,
52.99999999999999,
null
],
"000055": [
0,
17,
100,
68,
61.999999999999986,
null
],
"000056": [
0,
24,
0,
68,
46.99999999999999,
null
],
"000058": [
0,
77.99999999999999,
0,
56.99999999999999,
67,
null
],
"000060": [
32,
20.000000000000004,
100,
100,
67,
null
],
"000064": [
25,
8,
100,
56.99999999999999,
67,
null
],
"000065": [
0,
13.000000000000004,
100,
56.99999999999999,
67,
null
],
"000068": [
100,
11.000000000000004,
100,
71.00000000000001,
40,
null
],
"000069": [
0,
24,
100,
28.999999999999996,
94,
null
],
"000071": [
62,
45,
0,
84.00000000000001,
50.000000000000014,
null
],
"000073": [
32,
24,
0,
100,
28.000000000000007,
null
],
"000076": [
0,
8,
100,
57.99999999999999,
46.99999999999999,
null
],
"000077": [
31,
0,
0,
89.00000000000003,
46,
null
],
"000078": [
9.999999999999998,
4.0000000000000036,
0,
56.99999999999999,
70,
null
],
"000079": [
100,
24,
100,
87.00000000000003,
34,
null
],
"000080": [
0,
82,
100,
70,
17,
null
],
"000081": [
0,
20.000000000000004,
100,
78.00000000000001,
50.000000000000014,
null
],
"000083": [
25,
23,
0,
72.00000000000001,
50.000000000000014,
null
],
"000085": [
26,
10.000000000000002,
0,
72.00000000000001,
50.000000000000014,
null
],
"000086": [
35,
11.999999999999995,
0,
100,
18,
null
],
"000088": [
36,
23,
0,
79.00000000000001,
18,
null
],
"000091": [
0,
0,
100,
61,
18,
null
],
"000092": [
66,
67,
0,
84.00000000000001,
43,
null
],
"000096": [
27,
9.000000000000002,
0,
61,
48.00000000000001,
null
],
"000097": [
25,
90,
0,
61,
48.00000000000001,
null
],
"000099": [
25,
100,
0,
61,
48.00000000000001,
null
],
"000100": [
70,
1.0000000000000009,
0,
89.00000000000003,
30,
null
],
"000103": [
25,
41,
0,
62,
30,
null
],
"000104": [
62,
23,
100,
51.99999999999999,
39.00000000000001,
null
],
"000106": [
25,
17,
0,
82.00000000000001,
28.000000000000007,
null
],
"000108": [
69,
8,
0,
82.00000000000001,
28.000000000000007,
null
],
"000109": [
68,
50,
100,
67,
28.000000000000007,
null
],
"000110": [
21.999999999999996,
48,
0,
67,
28.000000000000007,
null
],
"000111": [
69,
8,
0,
100,
28.000000000000007,
null
],
"000114": [
0,
20.999999999999996,
100,
52.99999999999999,
39.00000000000001,
null
],
"000115": [
100,
45,
100,
52.99999999999999,
39.00000000000001,
null
],
"000116": [
27,
19.000000000000004,
100,
52.99999999999999,
39.00000000000001,
null
],
"000117": [
0,
27,
0,
87.00000000000003,
28.000000000000007,
null
],
"000118": [
19,
6.999999999999999,
0,
100,
15.999999999999998,
null
],
"000121": [
0,
15,
0,
45.000000000000014,
46.99999999999999,
null
],
"000122": [
66,
13.999999999999998,
0,
42.00000000000001,
65,
null
],
"000125": [
100,
72.00000000000001,
100,
84.00000000000001,
52.99999999999999,
null
],
"000126": [
61,
83,
0,
68,
43,
null
],
"000129": [
0,
4.9999999999999964,
100,
56.99999999999999,
43,
null
],
"000131": [
0,
0,
0,
90.00000000000003,
43,
null
],
"000132": [
0,
11.000000000000004,
0,
90.00000000000003,
43,
null
],
"000133": [
61,
69.99999999999999,
0,
51.99999999999999,
35,
null
],
"000134": [
0,
0,
100,
100,
23.000000000000004,
null
],
"000135": [
0,
0,
100,
85.00000000000001,
23.000000000000004,
null
],
"000137": [
100,
0,
100,
100,
3.9999999999999982,
null
],
"000140": [
70,
75,
0,
68,
24.999999999999993,
null
],
"000142": [
20.999999999999996,
24,
0,
51.99999999999999,
8.000000000000002,
null
],
"000143": [
24,
77.99999999999999,
100,
75.00000000000001,
26.000000000000007,
null
],
"000145": [
0,
10.000000000000002,
0,
82.00000000000001,
26.000000000000007,
null
],
"000146": [
49.00000000000001,
4.0000000000000036,
0,
100,
0,
null
],
"000147": [
64,
71,
0,
55.99999999999999,
0,
null
],
"000148": [
0,
48.99999999999999,
0,
100,
0,
null
],
"000150": [
51,
0,
100,
86.00000000000001,
12,
null
],
"000151": [
28.000000000000004,
0,
0,
36.00000000000001,
54.99999999999999,
null
],
"000152": [
22.000000000000004,
57.99999999999999,
100,
45.000000000000014,
72.99999999999999,
null
],
"000153": [
0,
18.000000000000004,
100,
45.000000000000014,
72.99999999999999,
null
],
"000155": [
54,
13.000000000000004,
0,
77.00000000000001,
61,
null
],
"000156": [
72,
0,
0,
98,
61,
null
],
"000157": [
69,
69,
0,
51.99999999999999,
61,
null
],
"000160": [
0,
6.999999999999999,
100,
51.99999999999999,
31,
null
],
"000161": [
0,
77.99999999999999,
0,
51.99999999999999,
54.000000000000014,
null
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
//var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
// var NUM_SLIDERS = 7;
// other variables can be in here too
// here's some examples for colors used
// const bg_color = [225, 206, 187];
// const fg_color = [151, 102, 52];
// const stroke_color = [95, 52, 8];
const cooper_brown =[250, 155, 117];
const brown1 =[209, 131, 100];
const brown2 =[135, 85, 65];
const brown3 = [79, 50, 38];
const brown4 = [43, 29, 21];
const lip = [247, 134, 89];
const lip1 = [204, 108, 69];
const lip2 = [107, 67, 51];
const lip3 = [79, 40, 25];
const lip4 = [33, 19, 10];
this.show_points = function (segment){
for(let i=0; i<segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
var number = i.toString();
textAlign(CENTER, CENTER);
textSize(0.2);
fill(0);
text(number, px, py, 0.1);
}
}
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i=0; i<s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len , sum_y / s_len ];
}
// This where you define your own face object
function CooperFace() {
// these are state variables for a face
// (your variables should be different!)
this.faceSize = 3;
this.eye = 0.5;
this.lip = 1 ;
this.tooth = 2;
this.mouth = 1;
this.num_eyes = 2;
this.eye_shift = -1;
this.face_colour = 1;
// example of a function *inside* the face object.
// this draws a segment, and do_loop will connect the ends if true
this.draw_segment = function(segment, do_loop) {
for(let i=0; i<segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
ellipse(px, py, 0.1);
if(i < segment.length - 1) {
let nx = segment[i+1][0];
let ny = segment[i+1][1];
line(px, py, nx, ny);
}
else if(do_loop) {
let nx = segment[0][0];
let ny = segment[0][1];
line(px, py, nx, ny);
}
}
};
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
let left_eye = segment_average(positions.left_eye);
let right_eye = segment_average(positions.right_eye);
let nose_tip = positions.nose_tip[2];
let top_lip = positions.top_lip[3];
let bottom_lip = positions.bottom_lip[0];
let whiskers = positions.nose_bridge[2];
let nostrils = positions.nose_bridge[2];
let tooth = positions.nose_bridge[3];
noStroke();
//head
if(this.face_colour == 0){
fill(cooper_brown);
}else
if(this.face_colour == 1){
fill(brown1);
}else
if(this.face_colour == 2){
fill(brown2);
}else
if(this.face_colour == 3){
fill(brown3);
}else
if(this.face_colour == 4){
fill(brown4);
}
ellipse(0, -0.3,this.faceSize,4);
// eyes
fill(255);
ellipse(left_eye[0], left_eye[1], 1,this.eye);
ellipse(right_eye[0], right_eye[1],1, this.eye);
let curEyeShift = 0.04 * this.eye_shift;
if(this.num_eyes == 2) {
fill(0);
ellipse(left_eye[0] + curEyeShift, left_eye[1], 0.5);
ellipse(right_eye[0] + curEyeShift, right_eye[1], 0.5);
}
else {
let eyePosX = (left_eye[0] + right_eye[0]) / 2;
let eyePosY = (left_eye[1] + right_eye[1]) / 2;
fill(0);
ellipse(eyePosX, eyePosY, 0.45, 0.27);
fill(0);
ellipse(eyePosX - 0.1 + curEyeShift, eyePosY, 0.18);
}
//mouth
fill(255, 201, 251);
ellipse(top_lip[0],top_lip[1],bottom_lip[0],this.mouth);
//teeth
if(this.tooth == 2){
noStroke();
push();
translate(tooth[0],tooth[1]);
fill(255);
triangle(0.25, 0.5, 0.5, 2, 0.75, 0.5);
triangle(-0.75, 0.5, -0.5, 2, -0.25, 0.5);
pop();
}else
if(this.tooth == 0){
noStroke();
push();
translate(tooth[0],tooth[1]);
fill(255);
triangle(0.25, 0.5, 0.5, 0, 0.75, 0.5);
triangle(-0.75, 0.5, -0.5, 0, -0.25, 0.5);
pop();
}
//lip
if(this.face_colour == 0){
fill(lip);
}else
if(this.face_colour == 1){
fill(lip1);
}else
if(this.face_colour == 2){
fill(lip2);
}else
if(this.face_colour == 3){
fill(lip3);
}else
if(this.face_colour == 4){
fill(lip4);
}
ellipse(nose_tip[0],nose_tip[1], 4, 1);
//nostrils
fill(0);
ellipse(nostrils[0],nostrils[1],this.lip, 0.5);
//whiskers
noFill();
stroke(255, 194, 115);
push();
translate(whiskers[0],whiskers[1]);
angleMode(DEGREES);
strokeWeight(0.05);
arc(0.4, 1, 1.6, 1.2, 290, 50);
arc(0.6, 1, 1.6, 1.2, 290, 50);
arc(0.8, 1, 1.6, 1.2, 290, 50);
arc(0, 1, 1.6, 1.2, 320, 50);
arc(0, 0.52, 0.8, 1.2, 360, 50);
arc(0, 0.6, 0.4, 1.2, 340, 50);
arc(-0.2, 0.6, 0.4, 1.2, 340, 50);
arc(-0.4, 0.6, 0.4, 1.2, 340, 50);
arc(-0.4, 1, 1.6, 1.2, 135, 250);
arc(-0.6, 1, 1.6, 1.2, 135, 250);
arc(-0.8, 1, 1.6, 1.2, 135, 250);
arc(-0.32, 0.96,1, 1.08, 120, 250);
arc(-0.2, 0.88, 0.4, 1.2, 180, 250);
pop();
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.faceSize = map(settings[0], 0, 100, 2.8, 4);
this.eye = map(settings[1], 0, 100, 0.5, 0.8);
this.lip = map(settings[2], 0, 100, 0.5, 2);
this.tooth = int(map(settings[3], 0, 100, 0, 2));
this.mouth = map(settings[4], 0, 100, 0.5, 1.5);
this.eye_shift = map(settings[5], 0, 100, -2, 2);
this.face_colour = int(map(settings[6], 0, 100, 0, 4));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(3);
settings[0] = map(this.faceSize, 2.8, 4, 0, 100);
settings[1] = map(this.eye, 0.5, 0.8, 0, 100);
settings[2] = map(this.lip, 0.5, 2, 0, 100);
settings[3] = int(map(this.tooth, 0, 2, 0, 100));
settings[4] = map(this.mouth,0.5,1.5,0,100);
settings[5] = map(this.eye_shift, -2, 2, 0, 100);
settings[6] = int(map(this.face_colour, 0, 4, 0, 100));
return settings;
}
}
{
"000001": [
63.000000000000014,
18.000000000000014,
17,
0,
5.000000000000004,
60,
0
],
"000002": [
77.99999999999999,
24.999999999999982,
4.0000000000000036,
0,
49,
38,
0
],
"000005": [
100,
13.000000000000009,
10.000000000000002,
0,
39,
46,
0
],
"000006": [
52,
16.00000000000001,
0,
0,
33.00000000000001,
95,
50
],
"000007": [
54,
22.000000000000018,
11.000000000000004,
100,
0,
60,
0
],
"000009": [
75.00000000000003,
20.99999999999998,
1.0000000000000009,
0,
37,
42,
0
],
"000010": [
100,
0,
16,
0,
0,
41,
0
],
"000013": [
100,
0,
0,
100,
14.000000000000002,
75,
0
],
"000014": [
100,
14.000000000000009,
9.000000000000002,
0,
0,
37,
75
],
"000015": [
54,
0,
20.999999999999996,
100,
7.000000000000006,
57.99999999999999,
0
],
"000016": [
50,
13.000000000000009,
8,
100,
0,
100,
25
],
"000018": [
81.00000000000003,
14.000000000000009,
19.000000000000004,
0,
30.000000000000004,
45,
0
],
"000020": [
60.00000000000001,
0,
17,
100,
19.999999999999996,
77,
0
],
"000023": [
58.00000000000001,
20.000000000000014,
20.999999999999996,
100,
6.000000000000005,
100,
0
],
"000025": [
66.00000000000001,
6.000000000000004,
4.9999999999999964,
100,
0,
44,
0
],
"000028": [
63.000000000000014,
11.000000000000009,
44.000000000000014,
0,
87.99999999999999,
54,
25
],
"000029": [
81.99999999999999,
17.00000000000001,
0,
0,
55.00000000000001,
45,
0
],
"000030": [
95,
14.000000000000009,
0,
100,
0,
43,
0
],
"000031": [
66.00000000000001,
5.0000000000000036,
22.000000000000007,
0,
25,
43,
0
],
"000032": [
61.00000000000001,
28.999999999999986,
4.0000000000000036,
100,
44.99999999999999,
54,
0
],
"000035": [
65.00000000000001,
39.99999999999999,
0,
0,
7.000000000000006,
53,
0
],
"000037": [
73.00000000000001,
51,
60,
100,
0,
94,
50
],
"000038": [
62.000000000000014,
3.000000000000002,
32,
100,
20.999999999999996,
71,
0
],
"000040": [
73.99999999999997,
33.999999999999986,
0,
0,
0,
66,
25
],
"000041": [
54,
26.000000000000018,
56.99999999999999,
100,
83,
0,
25
],
"000042": [
67.00000000000001,
13.000000000000009,
0,
0,
0,
34,
0
],
"000043": [
49,
23.000000000000018,
4.0000000000000036,
0,
56.999999999999986,
30,
0
],
"000044": [
34.999999999999986,
22.000000000000018,
23,
0,
0,
48,
100
],
"000045": [
56.00000000000001,
7.000000000000004,
6.999999999999999,
0,
66.00000000000001,
70,
25
],
"000047": [
66.00000000000001,
0,
5.999999999999997,
0,
23,
74,
25
],
"000048": [
83.99999999999999,
0,
11.000000000000004,
100,
0,
50,
0
],
"000050": [
75.00000000000003,
0,
28.000000000000004,
100,
79,
62,
25
],
"000051": [
92,
18.000000000000014,
38.99999999999999,
100,
0,
62,
25
],
"000052": [
64.00000000000001,
14.000000000000009,
31,
100,
0,
69,
25
],
"000054": [
71.00000000000001,
14.000000000000009,
6.999999999999999,
0,
55.00000000000001,
71,
0
],
"000055": [
71.00000000000001,
31.999999999999986,
16,
100,
0,
56.99999999999999,
25
],
"000056": [
77.00000000000003,
30.99999999999999,
11.000000000000004,
100,
0,
50,
0
],
"000058": [
77.00000000000003,
24.999999999999982,
5.999999999999997,
0,
0,
71,
0
],
"000060": [
100,
26.000000000000018,
20.000000000000004,
100,
20.999999999999996,
0,
100
],
"000064": [
100,
6.000000000000004,
18.000000000000004,
100,
0,
57.99999999999999,
0
],
"000065": [
75.99999999999997,
6.000000000000004,
40.00000000000001,
100,
23,
57.99999999999999,
25
],
"000068": [
61.00000000000001,
14.000000000000009,
13.000000000000004,
100,
20.999999999999996,
44,
0
],
"000069": [
61.00000000000001,
14.000000000000009,
13.000000000000004,
100,
20.999999999999996,
44,
0
],
"000071": [
81.00000000000003,
24.000000000000018,
1.0000000000000009,
0,
17.999999999999993,
62,
0
],
"000073": [
84.99999999999999,
26.999999999999986,
11.000000000000004,
0,
12,
20.999999999999996,
25
],
"000076": [
100,
26.999999999999986,
18.000000000000004,
100,
0,
15.000000000000002,
25
],
"000077": [
96,
18.000000000000014,
6.999999999999999,
0,
0,
79,
25
],
"000078": [
96,
0,
5.999999999999997,
0,
0,
39,
0
],
"000079": [
53,
13.000000000000009,
24,
100,
0,
80,
25
],
"000080": [
65.00000000000001,
16.00000000000001,
11.000000000000004,
100,
0,
54,
0
],
"000081": [
59.00000000000001,
17.00000000000001,
32,
100,
37,
100,
25
],
"000083": [
38.99999999999999,
18.000000000000014,
4.9999999999999964,
0,
0,
52,
0
],
"000085": [
95,
47,
5.999999999999997,
0,
0,
63,
0
],
"000086": [
100,
31.999999999999986,
5.999999999999997,
0,
27,
27,
0
],
"000088": [
87.99999999999999,
24.999999999999982,
10.000000000000002,
0,
18.999999999999993,
78,
25
],
"000091": [
79.00000000000003,
0,
13.000000000000004,
100,
0,
17.000000000000004,
0
],
"000092": [
73.00000000000001,
10.000000000000007,
5.999999999999997,
0,
0,
46,
0
],
"000096": [
100,
28.999999999999986,
23,
0,
0,
46,
0
],
"000097": [
100,
31.999999999999986,
17,
0,
19.999999999999996,
56.99999999999999,
0
],
"000099": [
52,
0,
23,
0,
47,
50,
0
],
"000100": [
79.99999999999999,
26.999999999999986,
23,
0,
0,
91,
0
],
"000103": [
75.99999999999997,
30.99999999999999,
1.0000000000000009,
0,
0,
43,
0
],
"000104": [
54,
0,
38.00000000000001,
100,
36,
61,
0
],
"000106": [
43.99999999999999,
20.99999999999998,
18.000000000000004,
0,
49,
46,
0
],
"000108": [
58.00000000000001,
22.000000000000018,
0,
0,
40.99999999999999,
51,
0
],
"000109": [
28.000000000000018,
13.000000000000009,
0,
100,
21.999999999999996,
60,
0
],
"000110": [
100,
19.000000000000014,
52,
0,
50,
50,
0
],
"000111": [
100,
19.000000000000014,
38.00000000000001,
0,
47,
100,
100
],
"000114": [
56.00000000000001,
31.999999999999986,
20.000000000000004,
100,
44.99999999999999,
60,
0
],
"000115": [
29.99999999999999,
10.000000000000007,
6.999999999999999,
100,
0,
68,
0
],
"000116": [
39.99999999999999,
0,
6.999999999999999,
100,
37,
76,
0
],
"000117": [
32.999999999999986,
0,
34.99999999999999,
0,
27,
68,
100
],
"000118": [
64.00000000000001,
19.000000000000014,
8,
0,
0,
34,
25
],
"000121": [
51,
23.000000000000018,
15,
0,
0,
56.99999999999999,
25
],
"000122": [
69.99999999999997,
36.999999999999986,
22.000000000000007,
0,
29.000000000000004,
66,
0
],
"000125": [
69.99999999999997,
24.999999999999982,
22.000000000000007,
100,
0,
50,
0
],
"000126": [
60.00000000000001,
24.999999999999982,
6.999999999999999,
0,
29.000000000000004,
80,
0
],
"000129": [
30.99999999999999,
17.00000000000001,
0,
100,
31.000000000000007,
80,
0
],
"000131": [
63.000000000000014,
0,
6.999999999999999,
0,
25,
100,
50
],
"000132": [
84.99999999999999,
24.000000000000018,
23,
0,
49,
82,
50
],
"000133": [
84.99999999999999,
24.000000000000018,
13.999999999999998,
0,
33.00000000000001,
53,
0
],
"000134": [
51,
20.000000000000014,
41.99999999999999,
100,
36,
0,
100
],
"000135": [
37.999999999999986,
22.000000000000018,
17,
100,
0,
100,
50
],
"000137": [
66.00000000000001,
3.000000000000002,
16,
100,
30.000000000000004,
100,
0
],
"000140": [
61.00000000000001,
22.000000000000018,
0,
0,
0,
38,
0
],
"000142": [
42.99999999999999,
20.000000000000014,
8,
0,
10.999999999999998,
38,
0
],
"000143": [
81.99999999999999,
19.000000000000014,
11.999999999999995,
100,
7.9999999999999964,
54,
0
],
"000145": [
67.00000000000001,
0,
8,
0,
76,
57.99999999999999,
0
],
"000146": [
79.00000000000003,
17.00000000000001,
8,
0,
56.999999999999986,
88,
25
],
"000147": [
81.99999999999999,
23.000000000000018,
5.999999999999997,
0,
8.999999999999996,
92,
0
],
"000148": [
47,
32.999999999999986,
2.0000000000000018,
0,
24,
100,
0
],
"000150": [
58.00000000000001,
13.000000000000009,
0,
100,
0,
55.00000000000001,
0
],
"000151": [
61.00000000000001,
13.000000000000009,
27,
0,
53,
59,
25
],
"000152": [
68.00000000000001,
0,
20.999999999999996,
100,
39,
41,
0
],
"000153": [
38.99999999999999,
14.000000000000009,
11.999999999999995,
100,
40.99999999999999,
50,
0
],
"000155": [
71.99999999999997,
20.99999999999998,
13.999999999999998,
0,
40,
59,
25
],
"000156": [
66.00000000000001,
20.99999999999998,
6.999999999999999,
0,
24,
69,
0
],
"000157": [
100,
20.99999999999998,
16,
0,
0,
52,
0
],
"000160": [
62.000000000000014,
13.000000000000009,
11.999999999999995,
100,
0,
63,
0
],
"000161": [
75.99999999999997,
15.00000000000001,
11.000000000000004,
0,
40,
39,
0
]
}
// https://d3js.org/d3-random/ v1.1.2 Copyright 2018 Mike Bostock
!function(n,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r(n.d3=n.d3||{})}(this,function(n){"use strict";function r(){return Math.random()}var t=function n(r){function t(n,t){return n=null==n?0:+n,t=null==t?1:+t,1===arguments.length?(t=n,n=0):t-=n,function(){return r()*t+n}}return t.source=n,t}(r),u=function n(r){function t(n,t){var u,e;return n=null==n?0:+n,t=null==t?1:+t,function(){var o;if(null!=u)o=u,u=null;else do{u=2*r()-1,o=2*r()-1,e=u*u+o*o}while(!e||e>1);return n+t*o*Math.sqrt(-2*Math.log(e)/e)}}return t.source=n,t}(r),e=function n(r){function t(){var n=u.source(r).apply(this,arguments);return function(){return Math.exp(n())}}return t.source=n,t}(r),o=function n(r){function t(n){return function(){for(var t=0,u=0;u<n;++u)t+=r();return t}}return t.source=n,t}(r),i=function n(r){function t(n){var t=o.source(r)(n);return function(){return t()/n}}return t.source=n,t}(r),c=function n(r){function t(n){return function(){return-Math.log(1-r())/n}}return t.source=n,t}(r);n.randomUniform=t,n.randomNormal=u,n.randomLogNormal=e,n.randomBates=i,n.randomIrwinHall=o,n.randomExponential=c,Object.defineProperty(n,"__esModule",{value:!0})});
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
//color variables
skinMidtone_color = ["#ffd5be","#ebcebb", "#ffd5be", "#CAA288", "#8c6652"];
skinLowlight_color = ["#f4c4b0", "#e5bbac","#e5b6a2", "#b78c79", "#775041"]
n1= [244, 200, 176, 50];
n2= [229, 187, 172, 50];
n3 = [232, 188, 169, 40];
n4 = [188, 149, 126, 50];
n5 = [124, 84, 68, 50];
noseColor = [n1, n2,n3, n4, n5];
h1= [255, 255, 255, 10];
h2= [249, 245, 239, 10];
h3 = [249, 245, 239, 10];
h4 = [255, 231, 216, 10];
h5 = [255, 231, 216, 10];
noseHighlight = [h1, h2, h3, h4, h5];
skinShadow_color = ["#d6a995", "#d6a995","#ba9584", "#9b7768", "#725241"]
// stroke_color = [skinLowlight_color[1]];
upperLip_color = ["#ba8080", "#d1a3a1", "#dba69b", "#a5776b","#6d453d", "#54322b"]; // 1 longer than the rest for stroke
lowerLip_color = ["#db9d9d", "#ebbdbb", "#ffc9be", "#ca9588", "#8c5c52"];
teeth_color = ["#fcfaf4", "#fff", "#f2ece3", "#f7f2ea", "#efe6da"];
eye_color = ["#3e7191", "#22323d", "#3d4722", "#543f14", "#493127", "#000"];
pupil_color = "#000";
function DockertyFace() {
this.lookPos = 50;
this.eyeAngle = 100;
this.skinColor = 50;
this.eyeColor = 50;
this.eyeSize = 50;
this.draw = function(positions) {
var nose_pos = average_point(positions.nose_bridge);
var eye1_pos = average_point(positions.left_eye);
var eye2_pos = average_point(positions.right_eye);
var half_height = positions.chin[7][1] - nose_pos[1];
var face_width = positions.chin[positions.chin.length-1][0] - positions.chin[0][0];
var eye_squish = map(this.eyeAngle, 0, 100, 50, 100);
var skin_color_value = int(map(this.skinColor, 0, 100, 2, 4.9));
var eye_color_value = int(map(this.eyeColor, 0, 100, 0, 5.9));
var eye_size = map(this.eyeSize, 0, 100, 0.7, 1.5);
var x = nose_pos[0];
var y = nose_pos[1];
var w = 2 * face_width;
var h = 2.5 * half_height;
var extent = 0;
if(h < w) {
extent = h / 2;
}
else {
extent = w / 2;
}
var size = extent / 220.0;
// head
stroke(0, 0, 0, 100);
fill(skinMidtone_color[skin_color_value]);
beginShape();
curveVertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1]);
for(var i=0; i<positions.chin.length;i++) {
curveVertex(positions.chin[i][0], positions.chin[i][1]);
}
for(var i=positions.right_eyebrow.length-1; i>=0;i--) {
curveVertex(positions.right_eyebrow[i][0], positions.right_eyebrow[i][1]);
}
for(var i=positions.left_eyebrow.length-1; i>=0;i--) {
curveVertex(positions.left_eyebrow[i][0], positions.left_eyebrow[i][1]);
}
curveVertex(positions.chin[0][0], positions.chin[0][1]);
endShape(CLOSE);
/////////////////////////////////////////// mouth
//inner mouth
stroke(upperLip_color[skin_color_value+1]);
strokeWeight(0.005);
fill(teeth_color[skin_color_value]);
beginShape();
for(var i=0; i<positions.top_lip.length/2;i++) {
vertex(positions.top_lip[i][0], positions.top_lip[i][1]);
}
for(var i=0; i<6;i++) {
if (i!=3 && i!=9){
vertex(positions.bottom_lip[i][0], positions.bottom_lip[i][1]);
}
}
endShape(CLOSE);
//lips
fill(upperLip_color[skin_color_value]);
beginShape();
for(var i=0; i<positions.top_lip.length;i++) {
curveVertex(positions.top_lip[i][0], positions.top_lip[i][1]);
}
endShape(CLOSE);
fill(lowerLip_color[skin_color_value]);
beginShape();
for(var i=0; i<positions.bottom_lip.length;i++) {
if (i!=3 && i!=9){
curveVertex(positions.bottom_lip[i][0], positions.bottom_lip[i][1]);
}
}
endShape(CLOSE);
noStroke();
///////////////////////////////////////////left eye
eyeball_color = teeth_color[skin_color_value];
iris_color = eye_color[eye_color_value];
push();
scale(1.4);
translate(0.2, 0.4);
//eyeball
beginShape();
fill(eyeball_color)
for(var i=0; i<positions.left_eye.length;i++) {
curveVertex(positions.left_eye[i][0], positions.left_eye[i][1]);
}
endShape(CLOSE);
//eye center
push();
translate((eye1_pos[0]-0.1)+(this.lookPos/500), eye1_pos[1]-0.03);
scale(eye_squish/100, 1);
fill(iris_color);
ellipse(0, 0, 20 * size *eye_size, 20 * size*eye_size);
if (eye_color_value == 5){
fill(255, 144, 96, 20);
} else if (eye_color_value == 4){
fill(255, 183, 96, 20);
}else {
fill(230, 250, 200, 20);
}
for(var i=0; i<8;i++) {
ellipse(0, 0, (12+i) * size*eye_size, (12+i) * size*eye_size);
}
fill(pupil_color);
ellipse(0, 0, 8 * size*eye_size, 8 * size*eye_size);
pop();
//eye highlights
fill(255, 255, 255, 5);
for (var i=4; i>0;i-=0.02) {
ellipse((eye1_pos[0]-0.03), eye1_pos[1]-0.07, i * size, i* size)
}
push();
translate(eye1_pos[0], eye1_pos[1]);
rotate(-30);
for (var i=6; i>0;i-=0.02) {
ellipse(0, 0, i * (size/2), i*size);
}
pop();
//lower lid shadow
for(var j=0.04; j>0; j-= 0.02){
push();
translate(-0.02, -j);
scale(0.98, 1)
fill(0, 0, 0, (20/(j*30)));
beginShape();
curveVertex(positions.left_eye[0][0], positions.left_eye[0][1]);
for(var i=5; i>=3;i--) {
curveVertex(positions.left_eye[i][0], positions.left_eye[i][1]);
}
for(var i=3; i<=5;i++) {
curveVertex(positions.left_eye[i][0], (positions.left_eye[i][1])+0.1);
}
endShape(CLOSE);
pop();
}
//lower lid shape
beginShape();
fill(skinMidtone_color[skin_color_value]);
curveVertex(positions.left_eye[0][0], positions.left_eye[0][1]);
for(var i=5; i>=3;i--) {
curveVertex(positions.left_eye[i][0], positions.left_eye[i][1]);
}
for(var i=3; i<=5;i++) {
curveVertex(positions.left_eye[i][0], (positions.left_eye[i][1])+0.15);
}
endShape(CLOSE);
//eyelid shadow
for(var j=0.01; j<0.1; j+= 0.01){
push();
translate(-0.02, j);
scale(0.98, 1)
beginShape();
fill(0, 0, 0, (20/(j*20)));
curveVertex((positions.left_eye[0][0]), (positions.left_eye[0][1]));
for(var i=0; i<4;i++) {
var eyelid_value_y = ((positions.left_eye[i][1] + positions.left_eyebrow[i+1][1])/2.2);
var eyelid_value_x = ((positions.left_eye[i][0] + positions.left_eyebrow[i][0])/2.3);
curveVertex((eyelid_value_x), (eyelid_value_y));
}
for(var i=3; i>=0;i--) {
curveVertex((positions.left_eye[i][0]), (positions.left_eye[i][1]));
}
endShape(CLOSE);
pop();
}
//eyelid shape
beginShape();
fill(skinLowlight_color[skin_color_value]);
curveVertex((positions.left_eye[0][0]), (positions.left_eye[0][1]));
for(var i=0; i<4;i++) {
var eyelid_value_y = ((positions.left_eye[i][1] + positions.left_eyebrow[i+1][1])/2.2);
var eyelid_value_x = ((positions.left_eye[i][0] + positions.left_eyebrow[i][0])/2.3);
curveVertex((eyelid_value_x), (eyelid_value_y));
}
for(var i=3; i>=0;i--) {
curveVertex((positions.left_eye[i][0]), (positions.left_eye[i][1]));
}
endShape(CLOSE);
//browbone shape
beginShape();
fill(skinMidtone_color[skin_color_value]);
vertex((positions.left_eye[0][0]), (positions.left_eye[0][1]));
for(var i=0; i<4;i++) {
var eyelid_value_y = ((positions.left_eye[i][1] + positions.left_eyebrow[i+1][1])/2.2);
var eyelid_value_x = ((positions.left_eye[i][0] + positions.left_eyebrow[i][0])/2.3);
curveVertex((eyelid_value_x), (eyelid_value_y));
}
curveVertex((positions.left_eyebrow[4][0]+positions.left_eyebrow[3][0])/2.5, (positions.left_eyebrow[3][1]+0.2));
curveVertex((positions.left_eyebrow[1][0]+0.2), (positions.left_eyebrow[1][1])+0.1);
endShape(CLOSE);
pop();
//////////////////////////////////////////////////right eye
push();
scale(1.4);
translate(-0.2, 0.4);
//eyeball
beginShape();
fill(eyeball_color)
for(var i=0; i<positions.right_eye.length;i++) {
curveVertex(positions.right_eye[i][0], positions.right_eye[i][1]);
}
endShape(CLOSE);
push();
translate((eye2_pos[0]-0.1)+(this.lookPos/500), eye2_pos[1]-0.03);
scale(eye_squish/100, 1);
//iris
fill(iris_color);
ellipse(0, 0, 20 * size*eye_size, 20 * size*eye_size);
if (eye_color_value == 5){
fill(255, 144, 96, 20);
} else if (eye_color_value == 4){
fill(255, 183, 96, 20);
}else {
fill(230, 250, 200, 20);
}
for(var i=0; i<8;i++) {
ellipse(0, 0, (12+i) * size*eye_size, (12+i) * size*eye_size);
}
//pupil
fill(pupil_color);
ellipse(0, 0, 8 * size*eye_size, 8 * size*eye_size);
pop();
//eye highlights
fill(255, 255, 255, 5);
for (var i=4; i>0;i-=0.02) {
ellipse((eye2_pos[0]-0.1)+0.07, eye2_pos[1]-0.07, i * size, i* size)
}
push();
translate(eye2_pos[0], eye2_pos[1]);
rotate(-30);
for (var i=6; i>0;i-=0.01) {
ellipse(0, 0, i * (size/2), i*size);
}
pop();
//lower lid shadow
for(var j=0.04; j>0; j-= 0.02){
push();
translate(0.02, -j);
scale(0.98, 1)
fill(0, 0, 0, (20/(j*30)));
beginShape();
curveVertex(positions.right_eye[0][0], positions.right_eye[0][1]);
for(var i=5; i>=3;i--) {
curveVertex(positions.right_eye[i][0], positions.right_eye[i][1]);
}
for(var i=3; i<=5;i++) {
curveVertex(positions.right_eye[i][0], (positions.right_eye[i][1])+0.1);
}
endShape(CLOSE);
pop();
}
//lower lid shape
beginShape();
fill(skinMidtone_color[skin_color_value]);
curveVertex(positions.right_eye[0][0], positions.right_eye[0][1]);
for(var i=5; i>=3;i--) {
curveVertex(positions.right_eye[i][0], positions.right_eye[i][1]);
}
for(var i=3; i<=5;i++) {
curveVertex(positions.right_eye[i][0], (positions.right_eye[i][1])+0.15);
}
endShape(CLOSE);
//eyelid shadow
for(var j=0.01; j<0.1; j+= 0.02){
push();
translate(0.02, j);
scale(0.98, 1)
beginShape();
fill(0, 0, 0, (20/(j*20)));
curveVertex((positions.right_eye[0][0]), (positions.right_eye[0][1]));
for(var i=0; i<4;i++) {
var eyelid_value_y = ((positions.right_eye[i][1] + positions.right_eyebrow[i][1])/2.2);
var eyelid_value_x = ((positions.right_eye[i][0] + positions.right_eyebrow[i+1][0])/2.3);
curveVertex((eyelid_value_x), (eyelid_value_y));
}
for(var i=3; i>=0;i--) {
curveVertex((positions.right_eye[i][0]), (positions.right_eye[i][1]));
}
endShape(CLOSE);
endShape(CLOSE);
pop();
}
//eyelid shape
beginShape();
fill(skinLowlight_color[skin_color_value]);
curveVertex((positions.right_eye[0][0]), (positions.right_eye[0][1]));
for(var i=0; i<4;i++) {
var eyelid_value_y = ((positions.right_eye[i][1] + positions.right_eyebrow[i][1])/2.2);
var eyelid_value_x = ((positions.right_eye[i][0] + positions.right_eyebrow[i+1][0])/2.3);
curveVertex((eyelid_value_x), (eyelid_value_y));
}
for(var i=3; i>=0;i--) {
curveVertex((positions.right_eye[i][0]), (positions.right_eye[i][1]));
}
endShape(CLOSE);
//browbone shape
beginShape();
fill(skinMidtone_color[skin_color_value]);
for(var i=3; i>=0;i--) {
var eyelid_value_y = ((positions.right_eye[i][1] + positions.right_eyebrow[i][1])/2.2);
var eyelid_value_x = ((positions.right_eye[i][0] + positions.right_eyebrow[i+1][0])/2.3);
curveVertex((eyelid_value_x), (eyelid_value_y));
}
curveVertex((positions.right_eyebrow[0][0]+0.15), (positions.right_eyebrow[0][1])+0.1);
curveVertex((positions.right_eyebrow[1][0]+0.15), (positions.right_eyebrow[1][1])+0.1);
curveVertex((positions.right_eyebrow[2][0]+positions.right_eyebrow[3][0])/2.5, (positions.right_eyebrow[2][1]+0.15));
endShape(CLOSE);
pop();
////////////////////////////////////////eyebrows
//left eyebrow
var browScale = 0.2
for (var j=0; j<10; j++){
browScale-=0.02;
beginShape();
fill(0, 0, 0, 30);
for(var i=1; i<3;i++) {
vertex((positions.left_eyebrow[i+1][0]), (positions.left_eyebrow[i+1][1]+0.2));
}
vertex((positions.left_eyebrow[4][0]-browScale), (positions.left_eyebrow[4][1]+0.2)-(browScale/2));
vertex((positions.left_eyebrow[4][0]-browScale), (positions.left_eyebrow[4][1])-(browScale/2));
for(var i=3; i>=0;i--) {
if (i!=1){
vertex((positions.left_eyebrow[i][0]), (positions.left_eyebrow[i][1]));
}
}
endShape(CLOSE);
}
//right eyebrow
var browScale = 0
for (var j=0; j<10; j++){
browScale-=0.02;
beginShape();
vertex((positions.right_eyebrow[0][0]-browScale), (positions.right_eyebrow[0][1]+0.2)+(browScale/2));
for(var i=1; i<4;i++) {
vertex((positions.right_eyebrow[i-1][0]), (positions.right_eyebrow[i-1][1]+0.2));
}
for(var i=4; i>=0;i--) {
if (i!= 3){
vertex((positions.right_eyebrow[i][0]), (positions.right_eyebrow[i][1]));
}
}
vertex((positions.right_eyebrow[0][0]-browScale), (positions.right_eyebrow[0][1])+(browScale/2));
endShape(CLOSE);
}
////////////////////////////////////////////// nose
//bottom of nose
beginShape();
fill(skinShadow_color[skin_color_value]);
stroke(0, 0, 0, 80)
strokeWeight(0.02);
vertex(positions.nose_tip[positions.nose_tip.length-1][0], positions.nose_tip[positions.nose_tip.length-1][1]);
vertex(positions.nose_bridge[positions.nose_bridge.length-1][0], positions.nose_bridge[positions.nose_bridge.length-1][1]);
for(var i=0; i<positions.nose_tip.length;i++) {
vertex(positions.nose_tip[i][0], positions.nose_tip[i][1]);
}
vertex(positions.nose_bridge[positions.nose_bridge.length-1][0], positions.nose_bridge[positions.nose_bridge.length-1][1]);
endShape(CLOSE);
//nose bridge
noStroke();
fill(skinMidtone_color[skin_color_value]);
beginShape();
vertex(((positions.nose_bridge[0][0]+positions.right_eye[4][0])/2)-0.3, positions.nose_bridge[0][1]);
vertex(((positions.nose_bridge[0][0]+positions.left_eye[4][0])/2)+0.3, positions.nose_bridge[0][1]);
vertex(positions.nose_tip[0][0], positions.nose_tip[0][1]);
vertex(positions.nose_tip[2][0], positions.nose_bridge[positions.nose_bridge.length-1][1]+0.3);
vertex(positions.nose_tip[4][0], positions.nose_tip[4][1]);
endShape(CLOSE);
fill(noseColor[skin_color_value]);
var noseWidth = 0;
for (var j=0; j<20; j++){
noseWidth+=0.02
beginShape();
vertex(((positions.nose_bridge[0][0]+positions.right_eye[4][0])/2)-0.3, positions.nose_bridge[0][1]+noseWidth);
vertex(((positions.nose_bridge[0][0]+positions.left_eye[4][0])/2)+0.3, positions.nose_bridge[0][1]+noseWidth);
vertex(positions.nose_tip[0][0]+noseWidth, positions.nose_tip[0][1]);
vertex(positions.nose_tip[2][0], positions.nose_bridge[positions.nose_bridge.length-1][1]+0.3);
vertex(positions.nose_tip[4][0]-noseWidth, positions.nose_tip[4][1]);
endShape(CLOSE);
}
//nose highlight
fill(noseHighlight[skin_color_value]);
var highlightWidth = 0.2;
for (var j=0; j<20; j++){
highlightWidth -= 0.01;
beginShape();
vertex(((positions.nose_bridge[1][0]+positions.right_eye[4][0])/2)-0.4, positions.nose_bridge[1][1]+highlightWidth);
vertex(((positions.nose_bridge[1][0]+positions.left_eye[4][0])/2)+0.4, positions.nose_bridge[1][1]+highlightWidth);
vertex(positions.nose_tip[1][0]+highlightWidth, positions.nose_bridge[positions.nose_bridge.length-1][1]+0.2);
vertex(positions.nose_tip[2][0], positions.nose_bridge[positions.nose_bridge.length-1][1]+0.3);
vertex(positions.nose_tip[3][0]-highlightWidth, positions.nose_bridge[positions.nose_bridge.length-1][1]+0.2);
endShape(CLOSE);
}
}
/*// set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.lookPos = settings[0];
this.eyeAngle = settings[1];
this.skinColor = settings[2];
this.eyeColor = settings[3];
this.eyeSize = settings[4];
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
properties = new Array(4);
properties[0] = this.lookPos;
properties[1] = this.eyeAngle;
properties[2] = this.skinColor;
properties[3] = this.eyeColor;
properties[4] = this.eyeSize;
return properties;
}
}
// given a point, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for(var i=0; i<list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
{
"000001": [
100,
90,
14,
100,
47
],
"000002": [
44,
72,
0,
66,
42
],
"000058": [
75,
100,
0,
0,
31
],
"000005": [
50,
100,
23,
61,
30
],
"000006": [
64,
84,
51,
100,
36
],
"000007": [
50,
100,
39,
72,
23
],
"000009": [
8,
100,
24,
64,
34
],
"000010": [
50,
100,
19,
0,
73
],
"000013": [
76,
82,
11,
0,
28
],
"000014": [
21,
100,
69,
100,
42
],
"000015": [
36,
84,
20,
23,
0
],
"000016": [
100,
100,
23,
76,
30
],
"000018": [
17,
100,
0,
26,
20
],
"000020": [
73,
100,
21,
15,
9
],
"000023": [
100,
72,
28,
0,
33
],
"000025": [
58,
100,
50,
54,
23
],
"000028": [
50,
100,
32,
86,
71
],
"000029": [
36,
100,
19,
0,
31
],
"000030": [
9,
100,
50,
80,
50
],
"000031": [
50,
100,
23,
0,
6
],
"000032": [
58,
92,
9,
59,
23
],
"000035": [
44,
100,
0,
58,
31
],
"000037": [
65,
62,
50,
100,
50
],
"000038": [
50,
100,
0,
0,
12
],
"000040": [
50,
100,
26,
71,
47
],
"000041": [
28,
38,
50,
75,
64
],
"000042": [
31,
100,
0,
0,
43
],
"000043": [
37,
100,
0,
57,
44
],
"000044": [
45,
100,
69,
100,
65
],
"000045": [
59,
100,
32,
75,
57
],
"000047": [
90,
100,
38,
80,
74
],
"000048": [
82,
100,
0,
80,
38
],
"000050": [
39,
69,
25,
75,
38
],
"000051": [
73,
100,
23,
100,
32
],
"000052": [
62,
100,
0,
0,
37
],
"000054": [
23,
100,
24,
0,
64
],
"000055": [
37,
84,
22,
60,
31
],
"000056": [
29,
90,
20,
0,
38
],
"000060": [
65,
62,
50,
100,
43
],
"000064": [
48,
96,
21,
22,
29
],
"000065": [
49,
100,
38,
70,
50
],
"000068": [
25,
100,
14,
76,
21
],
"000069": [
45,
100,
25,
65,
22
],
"000071": [
50,
100,
23,
61,
45
],
"000073": [
29,
61,
23,
29,
61
],
"000076": [
4,
100,
21,
78,
26
],
"000077": [
100,
79,
0,
0,
74
],
"000078": [
7,
100,
31,
100,
60
],
"000079": [
85,
100,
40,
82,
40
],
"000080": [
26,
100,
21,
24,
36
],
"000081": [
51,
82,
37,
77,
23
],
"000083": [
43,
100,
27,
55,
20
],
"000085": [
52,
100,
24,
32,
88
],
"000086": [
8,
100,
31,
63,
59
],
"000088": [
90,
94,
23,
89,
63
],
"000091": [
54,
88,
11,
20,
44
],
"000092": [
17,
100,
10,
25,
45
],
"000096": [
33,
100,
16,
15,
53
],
"000097": [
57,
100,
30,
0,
62
],
"000099": [
27,
100,
0,
26,
50
],
"000100": [
58,
77,
27,
72,
58
],
"000103": [
27,
100,
18,
30,
49
],
"000104": [
36,
100,
32,
19,
37
],
"000106": [
9,
100,
50,
63,
80
],
"000108": [
43,
100,
21,
0,
45
],
"000109": [
66,
100,
29,
24,
33
],
"000110": [
27,
87,
27,
54,
100
],
"000111": [
83,
100,
35,
22,
70
],
"000114": [
44,
100,
30,
80,
46
],
"000115": [
60,
82,
30,
56,
22
],
"000116": [
45,
100,
26,
80,
31
],
"000117": [
64,
89,
71,
94,
71
],
"000118": [
17,
100,
37,
98,
79
],
"000121": [
48,
100,
16,
100,
55
],
"000122": [
43,
91,
27,
57,
55
],
"000125": [
50,
100,
30,
20,
36
],
"000126": [
79,
100,
14,
0,
86
],
"000129": [
72,
97,
34,
27,
31
],
"000131": [
100,
100,
16,
100,
66
],
"000132": [
52,
100,
48,
87,
67
],
"000133": [
48,
100,
19,
26,
57
],
"000134": [
21,
69,
79,
85,
48
],
"000135": [
96,
79,
38,
100,
70
],
"000137": [
80,
93,
19,
66,
17
],
"000140": [
29,
100,
30,
0,
59
],
"000142": [
38,
96,
25,
27,
41
],
"000143": [
66,
100,
24,
2,
43
],
"000145": [
46,
100,
7,
72,
68
],
"000146": [
45,
56,
37,
100,
34
],
"000147": [
67,
100,
10,
0,
66
],
"000148": [
75,
47,
10,
28,
37
],
"000150": [
40,
100,
19,
11,
39
],
"000151": [
34,
100,
38,
100,
48
],
"000152": [
41,
94,
25,
57,
23
],
"000153": [
44,
98,
17,
68,
33
],
"000155": [
50,
100,
29,
100,
88
],
"000156": [
50,
75,
24,
49,
74
],
"000160": [
40,
100,
26,
70,
36
],
"000161": [
45,
100,
14,
23,
34
],
"000157": [
50,
100,
50,
50,
71
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// other variables can be in here too
// these control the colors used
function FelizardoFace() {
const bg_color = [225, 206, 187];
const fg_color = [151, 102, 52];
const stroke_color = [95, 52, 8];
// these are state variables for a face
// (your variables may be different)
this.tilt_value = 0;
this.mouth_value = 1;
this.eye_size = 0;
this.eyelid = 0;
this.mouth_open = 1;
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
colorMode(HSL, 360, 100, 100, 1);
//head
let head_location = average_point(positions.chin)
//eyes
let eye_L = average_point(positions.left_eye)
let eye_R = average_point(positions.right_eye)
//mouth points
//*top
let m_left = positions.top_lip[0];
let m_m_left = positions.top_lip[1];
let m_top = positions.top_lip[3];
let m_m_right = positions.top_lip[5]
let m_right = positions.top_lip[6];
let m_bot = positions.bottom_lip[9];
//bottom
let m_b1 = positions.bottom_lip[0];
let m_b2 = positions.bottom_lip[1];
let m_b3 = positions.bottom_lip[4];
let m_b4 = positions.bottom_lip[6];
//mouth pts for teeth
let m_teeth = positions.top_lip[10];
let m_teeth2 = positions.top_lip[8];
let m_teeth3 = positions.top_lip[7];
let m_teeth4 = positions.top_lip[11];
//brow points
let b_r1 = positions.right_eyebrow[0];
let b_r2 = positions.right_eyebrow[4];
let b_l1 = positions.left_eyebrow[0];
let b_l2 = positions.left_eyebrow[4];
//cheek pts
let ch_1 = positions.chin[2];
let ch_2 = positions.chin[14];
//CHIN PTS
let b_ch_1 = positions.chin[5];
let b_ch_2 = positions.chin[7];
let b_ch_3 = positions.chin[8];
let b_ch_4 = positions.chin[9];
let b_ch_5 = positions.chin[11];
//*******************************************************************************
//********************** E Y E S ************************************
//*******************************************************************************
//**************** e y e s h a p e **************************
noStroke();
fill(255);
ellipse(eye_L[0], eye_L[1], .9 * this.eye_size, .9 * this.eye_size);
ellipse(eye_R[0], eye_R[1], .9 * this.eye_size, .9 * this.eye_size);
//**************** e y e c o l o u r **************************
//******cornea
fill(1 * this.eye_colour, 75, 50, 1); // eye colour
ellipse(eye_L[0], eye_L[1], .6 * this.eye_size, .6 * this.eye_size);
ellipse(eye_R[0], eye_R[1], .6 * this.eye_size, .6 * this.eye_size);
//********* iris
fill(0);
ellipse(eye_L[0], eye_L[1], .2 * this.eye_size, .2 * this.eye_size);
ellipse(eye_R[0], eye_R[1], .2 * this.eye_size, .2 * this.eye_size);
//************* e y e l i d s *******************
//********** SURPRISED
if (this.eyelid == 0) {
fill(0);
arc(eye_L[0], eye_L[1], 1 * this.eye_size, 1 * this.eye_size, 15, 165, CHORD);
arc(eye_R[0], eye_R[1], 1 * this.eye_size, 1 * this.eye_size, 15, 165, CHORD);
}
//*********** MELLOW
if (this.eyelid == 1) {
fill(0);
arc(eye_L[0], eye_L[1], 1 * this.eye_size, 1 * this.eye_size, -180, 0, CHORD);
arc(eye_R[0], eye_R[1], 1 * this.eye_size, 1 * this.eye_size, -180, 0, CHORD);
}
//*********** ANGRY
if (this.eyelid == 2) {
fill(0);
arc(eye_L[0], eye_L[1], 1 * this.eye_size, 1 * this.eye_size, -150, 20, CHORD);
arc(eye_R[0], eye_R[1], 1 * this.eye_size, 1 * this.eye_size, 160, -30, CHORD);
//lower lids
arc(eye_L[0], eye_L[1], 1 * this.eye_size, 1 * this.eye_size, -150, 20, CHORD);
arc(eye_R[0], eye_R[1], 1 * this.eye_size, 1 * this.eye_size, 160, -30, CHORD);
}
//*********** SCHLEEP
if (this.eyelid == 3) {
fill(0);
arc(eye_L[0], eye_L[1], 1 * this.eye_size, 1 * this.eye_size, -180, 0, CHORD);
arc(eye_R[0], eye_R[1], 1 * this.eye_size, 1 * this.eye_size, -180, 0, CHORD);
//lower lids
arc(eye_L[0], eye_L[1], 1 * this.eye_size, 1 * this.eye_size, 20, 160, CHORD);
arc(eye_R[0], eye_R[1], 1 * this.eye_size, 1 * this.eye_size, 20, 160, CHORD);
}
//*******************************************************************************
//********************** C H I N ******************************
//*******************************************************************************
stroke(0);
strokeWeight(.02);
line(b_ch_2[0], b_ch_2[1], ch_1[0], ch_1[1]); //cheek to jaw connector
line(b_ch_4[0], b_ch_4[1], ch_2[0], ch_2[1]);
fill(20, 0, this.skin);
noStroke();
beginShape();
vertex(b_ch_1[0], b_ch_1[1]);
vertex(b_ch_2[0], b_ch_2[1] + 1 * this.chin);
vertex(b_ch_3[0], b_ch_3[1] + 1 * this.chin);
vertex(b_ch_4[0], b_ch_4[1] + 1 * this.chin);
vertex(b_ch_5[0], b_ch_5[1]);
endShape();
fill(0);
ellipse(b_ch_2[0], b_ch_2[1] - .08, .07, .07); //peg
ellipse(b_ch_4[0], b_ch_4[1] - .08, .07, .07);
//*******************************************************************************
//********************** M O U T H **************************
//*******************************************************************************
//********** bottom lip *check if working properly.
//cheek pivot
fill(0);
ellipse(ch_2[0], ch_2[1], .2, .2);
ellipse(ch_1[0], ch_1[1], .2, .2);
//cheek wires
strokeWeight(.02);
stroke(0);
noFill();
line(ch_2[0], ch_2[1], m_b1[0], m_b1[1]);
line(ch_2[0], ch_2[1], m_b1[0], (m_b1[1] * this.mouth_open) + .05);
line(ch_1[0], ch_1[1], m_b4[0], m_b4[1]);
line(ch_1[0], ch_1[1], m_b4[0], (m_b4[1] * this.mouth_open) + .05);
stroke(360, 70, 60, 1); //bottom lip colour
strokeWeight(.4);
noFill();
bezier(m_b1[0], m_b1[1], m_b2[0], m_b2[1] * this.mouth_open, m_b3[0], m_b3[1] * this.mouth_open, m_b4[0], m_b4[1]);
//********** top_lip
noFill();
strokeWeight(.5);
stroke(360, 100, 60, 1); //thick top lip colour
bezier(m_left[0], m_left[1], m_m_left[0], m_m_left[1] - .2, m_m_right[0], m_m_right[1] - .2, m_right[0], m_right[1]);
strokeWeight(.3);
stroke(360, 100, 40, 1); //top lip shade
bezier(m_left[0], m_left[1] + .1, m_m_left[0], m_m_left[1], m_m_right[0], m_m_right[1], m_right[0], m_right[1] + .1);
//************* top teeth
fill(225);
noStroke();
arc(m_teeth3[0], m_teeth3[1], .45 * .5, .7 * .5, 15 + 20, 165, CHORD); //right back
arc(m_teeth3[0] - .2, m_teeth3[1], .45 * .5, .7 * .5, 15, 165, CHORD); //right back 2
arc(m_teeth4[0], m_teeth4[1], .45 * .5, .7 * .5, 15 - 20, 165 - 10, CHORD); //left back
arc(m_teeth4[0] + .2, m_teeth4[1], .45 * .5, .7 * .5, 15, 165, CHORD); //left back 2
fill(255);
arc(m_teeth[0], m_teeth[1] - .15, .45, .7, 15, 165, CHORD);
arc(m_teeth2[0], m_teeth2[1] - .15, .45, .7, 15, 165, CHORD);
//*******************************************************************************
//********************** M or F **************************************
//*******************************************************************************
if (this.horn == 0) {
fill(100, 0, 50);
ellipse(head_location[0], head_location[1] - 3.29, .5, .25);
fill(20, 0, this.skin);
ellipse(head_location[0], head_location[1] - 3.31, .5, .2);
stroke(200, 0, this.skin - 10);
strokeWeight(.1);
line(head_location[0], head_location[1] - 3.4, head_location[0], head_location[1] - 4.5)
noStroke(0);
fill(20, 0, this.skin + 10);
ellipse(head_location[0], head_location[1] - 4.5, .3, .3);
}
//*******************************************************************************
//********************** B R O W S **************************
//*******************************************************************************
//eyebrow background mechanics
fill(0);
strokeWeight(.02);
stroke(0);
ellipse(head_location[0], head_location[1] - 3, .2, .2);
line(head_location[0], head_location[1] - 3, b_l1[0] * .8, b_l1[1] * 1.4 * this.eyebrows);
line(head_location[0], head_location[1] - 3, b_l2[0] * .8, b_l2[1] * 1.1 * this.eyebrows);
line(head_location[0], head_location[1] - 3, b_r1[0] * .8, b_r1[1] * 1.1 * this.eyebrows);
line(head_location[0], head_location[1] - 3, b_r2[0] * .8, b_r2[1] * 1.4 * this.eyebrows);
strokeWeight(.55);
stroke(20, 0, this.skin);
line(b_l1[0] * .8, b_l1[1] * 1.4 * this.eyebrows, b_l2[0] * .8, b_l2[1] * 1.1 * this.eyebrows); // left eyebrow
line(b_r1[0] * .8, b_r1[1] * 1.1 * this.eyebrows, b_r2[0] * .8, b_r2[1] * 1.4 * this.eyebrows); // right eyebrow
fill(0)
noStroke();
ellipse(b_l1[0] * .8, b_l1[1] * 1.4 * this.eyebrows, .06, .06);
ellipse(b_l2[0] * .8, b_l2[1] * 1.1 * this.eyebrows, .06, .06);
ellipse(b_r1[0] * .8, b_r1[1] * 1.1 * this.eyebrows, .06, .06);
ellipse(b_r2[0] * .8, b_r2[1] * 1.4 * this.eyebrows, .06, .06);
//*******************************************************************************
//*******************************************************************************
//*******************************************************************************
}
/* set internal properties based on list numbers 0-100 */
//put all slider elements here first
this.setProperties = function(settings) {
this.eye_size = map(settings[0], 0, 100, .9, 1.1);
this.eyelid = int(map(settings[1], 0, 100, 0, 4));
this.eyebrows = map(settings[2], 0, 100, .9, 1.1);
this.mouth_open = map(settings[4], 0, 100, 1, 1.5);
this.eye_colour = map(settings[3], 0, 100, 1, 359);
this.horn = int(map(settings[5], 0, 100, 0, 1));
this.skin = map(settings[6], 0, 100, 100, 50);
this.chin = map(settings[7], 0, 100, 0, 1);
}
/* get internal properties as list of numbers 0-100 */
//then wire them up here in this order (flip it round)
this.getProperties = function() {
let settings = new Array(8);
settings[0] = map(this.eye_size, .9, 1.1, 0, 100);
settings[1] = map(this.eyelid, 0, 4, 0, 100);
settings[2] = map(this.eyebrows, 1, 1.5, 0, 100);
settings[4] = map(this.mouth_open, 1, 1.5, 0, 100);
settings[3] = map(this.eye_colour, 1, 359, 0, 100);
settings[5] = map(this.horn, 0, 1, 0, 100);
settings[6] = map(this.skin, 100, 50, 0, 100);
settings[7] = map(this.chin, 0, 1, 0, 100);
return settings;
}
}
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for (var i = 0; i < list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
{
"000001": [
24,
56,
-12,
27,
42,
100,
69,
1
],
"000002": [
50.999999999999964,
0,
-19.999999999999996,
0,
33.00000000000001,
100,
100,
12
],
"000058": [
51.99999999999997,
75,
-14.79999999999999,
56.00000000000001,
29.000000000000004,
100,
81,
2
],
"000005": [
49.99999999999997,
50,
-19.999999999999996,
28.000000000000004,
10.999999999999988,
100,
76,
32
],
"000006": [
48.99999999999997,
50,
-19.999999999999996,
91,
50,
100,
50,
26
],
"000007": [
49.99999999999997,
25,
-19.999999999999996,
70,
22.00000000000002,
0,
73,
50
],
"000009": [
49.99999999999997,
50,
-19.999999999999996,
0,
78.00000000000003,
100,
63,
0
],
"000010": [
49.99999999999997,
50,
-19.999999999999996,
16,
50,
100,
62,
24
],
"000013": [
49.99999999999997,
0,
-14.399999999999991,
18,
50,
0,
50,
50
],
"000014": [
49.99999999999997,
50,
-19.999999999999996,
65,
50,
100,
32,
50
],
"000015": [
0,
75,
-19.999999999999996,
97,
100,
0,
82,
38
],
"000016": [
49.99999999999997,
50,
-19.999999999999996,
96,
50,
0,
56.00000000000001,
22
],
"000018": [
0,
75,
-19.999999999999996,
17,
18.000000000000014,
100,
77,
2
],
"000020": [
8.000000000000004,
75,
-19.999999999999996,
92,
100,
0,
67,
34
],
"000028": [
0,
50,
-19.999999999999996,
22,
50,
100,
50,
3
],
"000023": [
0,
50,
-15.199999999999992,
90,
50,
0,
87,
20
],
"000025": [
0,
50,
-19.999999999999996,
89,
50,
0,
42,
0
],
"000029": [
0,
75,
-11.99999999999999,
20,
29.000000000000004,
100,
86,
26
],
"000030": [
100,
100,
11.20000000000001,
51,
8.000000000000007,
0,
70,
19
],
"000031": [
15.000000000000007,
75,
-15.999999999999993,
30,
50,
100,
32,
64
],
"000032": [
0,
25,
20.000000000000018,
98,
89.00000000000001,
0,
63,
48
],
"000035": [
100,
100,
-19.999999999999996,
69,
45.000000000000014,
100,
100,
13
],
"000037": [
61.99999999999998,
50,
-19.999999999999996,
75,
41.99999999999999,
0,
31,
60
],
"000038": [
100,
0,
20.000000000000018,
86,
37.999999999999986,
0,
75,
31
],
"000040": [
49.99999999999997,
50,
10.000000000000009,
67,
54,
100,
82,
0
],
"000041": [
70.99999999999999,
0,
20.000000000000018,
69,
50.99999999999998,
0,
59,
45
],
"000042": [
100,
100,
8.000000000000007,
8,
50,
100,
62,
0
],
"000043": [
48.99999999999997,
100,
15.600000000000014,
56.00000000000001,
23,
100,
69,
0
],
"000044": [
100,
25,
0,
66,
14.000000000000012,
100,
20,
18
],
"000045": [
22.00000000000001,
0,
4.400000000000004,
11,
46,
100,
66,
9
],
"000047": [
49.99999999999997,
50,
0,
68,
50,
100,
28.999999999999996,
0
],
"000048": [
100,
75,
1.200000000000001,
61,
43.000000000000014,
0,
100,
57.99999999999999
],
"000050": [
100,
100,
20.000000000000018,
70,
98,
0,
73,
83
],
"000051": [
49.99999999999997,
0,
-16.39999999999999,
46,
50,
0,
57.99999999999999,
0
],
"000052": [
55.99999999999997,
25,
12.800000000000011,
71,
58.999999999999986,
0,
56.00000000000001,
46
],
"000054": [
100,
75,
20.000000000000018,
25,
66.00000000000001,
100,
61,
0
],
"000055": [
100,
25,
2.400000000000002,
72,
39.000000000000014,
0,
70,
44
],
"000056": [
100,
25,
4.800000000000004,
65,
62.000000000000014,
0,
80,
0
],
"000060": [
19.00000000000001,
100,
-19.999999999999996,
67,
100,
0,
11,
36
],
"000064": [
0,
0,
4.800000000000004,
88,
69,
0,
63,
32
],
"000065": [
0,
25,
-5.999999999999983,
64,
41.99999999999999,
0,
28.000000000000004,
23
],
"000068": [
97,
25,
18.000000000000014,
40,
79.99999999999999,
0,
22,
37
],
"000069": [
100,
100,
20.000000000000018,
69,
100,
0,
67,
44
],
"000071": [
62.99999999999998,
0,
-19.199999999999996,
23,
50,
100,
72,
0
],
"000073": [
100,
75,
-6.799999999999984,
67,
66.00000000000001,
100,
70,
0
],
"000076": [
100,
75,
20.000000000000018,
74,
81.99999999999999,
0,
65,
55.00000000000001
],
"000077": [
49.99999999999997,
75,
-7.999999999999985,
60,
25.99999999999998,
100,
71,
0
],
"000078": [
100,
75,
5.200000000000005,
74,
64.99999999999999,
100,
77,
18
],
"000079": [
15.000000000000007,
100,
10.000000000000009,
46,
50,
0,
33,
30
],
"000080": [
100,
25,
6.000000000000005,
72,
23,
0,
57.99999999999999,
26
],
"000081": [
100,
0,
12.400000000000011,
65,
50.99999999999998,
0,
77,
50
],
"000083": [
100,
75,
10.80000000000001,
0,
50,
100,
91,
0
],
"000085": [
93,
100,
12.00000000000001,
0,
22.00000000000002,
100,
74,
0
],
"000086": [
100,
75,
18.400000000000016,
0,
62.000000000000014,
100,
88,
0
],
"000088": [
0,
100,
3.600000000000003,
79,
20.999999999999996,
100,
100,
0
],
"000091": [
49.99999999999997,
50,
14.400000000000013,
70,
25.99999999999998,
0,
64,
23
],
"000092": [
12.000000000000007,
0,
15.200000000000014,
23,
50,
100,
50,
0
],
"000096": [
57.99999999999997,
25,
10.40000000000001,
91,
69,
100,
26,
0
],
"000097": [
69.99999999999999,
75,
8.800000000000008,
40,
14.999999999999991,
100,
50,
0
],
"000099": [
100,
75,
20.000000000000018,
87,
52,
100,
60,
23
],
"000100": [
100,
100,
5.600000000000005,
28.000000000000004,
37.000000000000014,
100,
81,
0
],
"000103": [
51.99999999999997,
50,
0,
66,
50,
100,
50,
0
],
"000104": [
100,
75,
2.8000000000000025,
85,
33.00000000000001,
0,
50,
50
],
"000106": [
93,
0,
20.000000000000018,
90,
66.00000000000001,
100,
30,
0
],
"000108": [
49.99999999999997,
50,
-8.399999999999984,
20,
50,
100,
73,
0
],
"000109": [
49.99999999999997,
100,
8.400000000000007,
74,
49.00000000000002,
0,
54,
27
],
"000110": [
100,
75,
1.200000000000001,
91,
58.00000000000001,
100,
76,
0
],
"000111": [
100,
75,
20.000000000000018,
33,
69,
100,
0,
0
],
"000114": [
49.99999999999997,
50,
0,
71,
50,
0,
50,
50
],
"000115": [
49.99999999999997,
50,
0,
46,
0,
0,
50,
50
],
"000116": [
100,
100,
0,
68,
50,
0,
79,
36
],
"000117": [
100,
25,
-15.59999999999999,
73,
35.00000000000001,
100,
0,
0
],
"000118": [
49.99999999999997,
50,
9.200000000000008,
69,
50,
100,
33,
2
],
"000121": [
49.99999999999997,
0,
0,
62,
50,
100,
50,
0
],
"000122": [
100,
25,
2.0000000000000018,
42,
75,
100,
100,
0
],
"000125": [
96,
0,
20.000000000000018,
53,
60.999999999999986,
0,
43,
27
],
"000126": [
49.99999999999997,
50,
0,
50,
50,
100,
76,
0
],
"000129": [
49.99999999999997,
50,
0.40000000000000036,
62,
24.00000000000002,
0,
73,
43
],
"000131": [
100,
75,
6.000000000000005,
72,
54,
100,
26,
0
],
"000132": [
100,
75,
7.600000000000007,
71,
41.99999999999999,
100,
0,
0
],
"000133": [
92,
75,
17.200000000000017,
22,
28.000000000000025,
100,
33,
0
],
"000134": [
49.99999999999997,
50,
7.200000000000006,
65,
41.000000000000014,
0,
0,
50
],
"000135": [
100,
0,
0,
63,
10.999999999999988,
0,
24,
37
],
"000137": [
0,
75,
-7.5999999999999845,
46,
29.000000000000004,
0,
85,
17
],
"000140": [
100,
100,
-2.39999999999998,
22,
20.999999999999996,
100,
100,
0
],
"000142": [
88.99999999999999,
75,
4.400000000000004,
90,
56.999999999999986,
100,
100,
0
],
"000143": [
100,
25,
20.000000000000018,
86,
69,
0,
50,
35
],
"000145": [
100,
75,
20.000000000000018,
76,
50,
100,
75,
0
],
"000146": [
93,
100,
20.000000000000018,
89,
37.000000000000014,
100,
67,
0
],
"000147": [
94,
100,
20.000000000000018,
50,
50,
100,
67,
0
],
"000148": [
100,
75,
5.200000000000005,
76,
62.999999999999986,
100,
67,
2
],
"000150": [
49.99999999999997,
50,
0,
100,
28.000000000000025,
0,
100,
14.000000000000002
],
"000151": [
0,
100,
14.000000000000012,
68,
50,
100,
79,
0
],
"000152": [
100,
75,
7.200000000000006,
71,
50,
0,
92,
40
],
"000153": [
49.99999999999997,
50,
0,
85,
50,
0,
83,
36
],
"000155": [
93,
100,
12.800000000000011,
0,
49.00000000000002,
100,
65,
0
],
"000156": [
100,
100,
20.000000000000018,
26,
33.00000000000001,
100,
74,
0
],
"000157": [
49.99999999999997,
75,
6.000000000000005,
16,
23,
100,
81,
0
],
"000160": [
49.99999999999997,
50,
0,
69,
25.99999999999998,
0,
79,
83
],
"000161": [
100,
75,
8.000000000000007,
70,
33.999999999999986,
100,
93,
0
]
}
function gambles_draw_one_frame(cur_frac) {
// note: to clear the screen draw a rectangle
// that is width x height - like this
noStroke();
fill(10);
rect(0, 0, width, height);
// note: all shape sizes, line widths, etc. should be a
// function of width and height
let rect_width = height / 10.0;
let half_width = rect_width / 2;
// note: animation should progress depending on the
// value of cur_frac which goes from 0 to 1, and it
// should loop seamlessly
let cur_x = map(cur_frac, 0, 1, 0, width) - half_width;
fill(200);
// draw the rect moving across the screen
rect(cur_x, 0, rect_width, height);
// a second version (offscreen) for when it loops back around
rect(cur_x+width, 0, rect_width, height);
rect(cur_x-width, 0, rect_width, height);
// note: you can draw optional things depending on "debugView"
if (debugView) {
// we'll draw our "keyframes"
noFill();
stroke(255, 0, 0);
strokeWeight(height/100);
// here we "plug in" the values when cur_frac is 0
rect(-half_width, 0, rect_width, height);
rect( width - half_width, 0, rect_width, height);
rect(-width - half_width, 0, rect_width, height);
}
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
var DEBUG_MODE = false;
// this can be used to set the number of sliders to show
var NUM_SLIDERS = 8;
// other variables can be in here too
// const fg_color = [255];
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i = 0; i < s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len, sum_y / s_len];
}
// This where you define your own face object
function GamblesFace() {
// these are state variables for a face
// (your variables should be different!)
this.eye_type = .2; // changes between different styles range is 0 to 1 with 3 different styles of eye
this.right_eyeBrow_height = .5; // Low, Middle, or High range is 0 to 1 with 3 different positions
this.left_eyeBrow_height = .5; // Low, Middle, or High range is 0 to 1 with 3 different positions
this.mouth_type = .2; // changes between different styles range is 0 to 1 with 5 different positions
this.bridge_direction = .2; // left or right range is 0 to 1 with 2 different positions
// example of a function *inside* the face object.
// this draws a segment, and do_loop will connect the ends if true
this.draw_segment = function (segment, do_loop) {
for (let i = 0; i < segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
if (i < segment.length - 1) {
let nx = segment[i + 1][0];
let ny = segment[i + 1][1];
ellipse(px, py, .1)
line(px, py, nx, ny);
} else if (do_loop) {
let nx = segment[0][0];
let ny = segment[0][1];
line(px, py, nx, ny);
}
}
};
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function (positions) {
rectMode(CENTER);
noStroke()
// average the location of some of the facepart to be used to determine if they are in one or another
let nose_tip_pos = segment_average(positions.nose_tip);
let top_lip_pos = segment_average(positions.top_lip);
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye);
// size and number of cells in the grid
var gridSize = 3;
var cellSize = .75;
/*** TOM ADDED THIS LOOP #1 to "color in" the face ***/
// this is a lookup table that keeps track of previous cells
for (let y = -gridSize; y < gridSize; y += cellSize) {
// each row we'll draw one line from left_x to right_x
let left_x = null;
let right_x = null;
for (let x = -gridSize; x < gridSize; x += cellSize) {
let lastX = null;
let lastY = null;
for (let i = 0; i < positions.chin.length; i++) {
if (positions.chin[i][0] > (x - cellSize / 2) && positions.chin[i][0] < (x + cellSize / 2) && positions.chin[i][1] > (y - cellSize / 2) && positions.chin[i][1] < (y + cellSize / 2)) {
if (x != lastX && y != lastY) {
lastX = x;
lastY = y;
// first check if this is the first one
if (left_x == null) {
// just record this for both left and right
left_x = x;
right_x = x;
} else if (x < left_x) {
// new left_x
left_x = x;
} else if (x > right_x) {
right_x = x;
}
}
}
}
}
if (left_x != null) {
// now draw the line (series of cells)
for (let j = left_x; j <= right_x; j += cellSize) {
let selectFill = random(0, 1)
if (selectFill >= 0 && selectFill < .33) {
gridGradient(j, y);
} else if (selectFill >= .33 && selectFill < .66) {
circles(j, y)
} else if (selectFill >= .66 && selectFill < 1) {
triangles(j, y);
}
}
}
}
/*** END OF TOM'S ADDITONS ***/
// Main loop, logic gates that check if the given point of the facial feature is within the bounds of a cell, if it is then go through another set of logic gates to determine which 'style' of that facepart to draw
for (let x = -gridSize; x < gridSize; x += cellSize) {
for (let y = -gridSize; y < gridSize; y += cellSize) {
if (left_eye_pos[0] > (x - cellSize / 2) && left_eye_pos[0] < (x + cellSize / 2) && left_eye_pos[1] > (y - cellSize / 2) && left_eye_pos[1] < (y + cellSize / 2)) {
if (this.eye_type >= 0 && this.eye_type <= .33) {
eye1(x, y);
} else if (this.eye_type > .33 && this.eye_type <= .66) {
eye2(x, y);
} else if (this.eye_type > .66 && this.eye_type <= 1) {
eye3(x, y);
}
} else if (right_eye_pos[0] > (x - cellSize / 2) && right_eye_pos[0] < (x + cellSize / 2) && right_eye_pos[1] > (y - cellSize / 2) && right_eye_pos[1] < (y + cellSize / 2)) {
if (this.eye_type >= 0 && this.eye_type <= .33) {
eye1(x, y);
} else if (this.eye_type > .33 && this.eye_type <= .66) {
eye2(x, y);
} else if (this.eye_type > .66 && this.eye_type <= 1) {
eye3(x, y);
}
} else if (positions.nose_bridge[3][0] > (x - cellSize / 2) && positions.nose_bridge[3][0] < (x + cellSize / 2) && positions.nose_bridge[3][1] > (y - cellSize / 2) && positions.nose_bridge[3][1] < (y + cellSize / 2)) {
noseTip(x, y)
} else if (positions.nose_bridge[0][0] > (x - cellSize / 2) && positions.nose_bridge[0][0] < (x + cellSize / 2) && positions.nose_bridge[0][1] > (y - cellSize / 2) && positions.nose_bridge[0][1] < (y + cellSize / 2)) {
if (this.bridge_direction >= 0 && this.bridge_direction <= .5) {
noseBridge1(x,y);
} else if (this.bridge_direction > .5 && this.bridge_direction <= 1) {
noseBridge2(x,y);
}
} else if (top_lip_pos[0] > (x - cellSize / 2) && top_lip_pos[0] < (x + cellSize / 2) && top_lip_pos[1] > (y - cellSize / 2) && top_lip_pos[1] < (y + cellSize / 2)) {
if (this.mouth_type >= 0 && this.mouth_type <=.2) {
mouth1(x, y);
} else if (this.mouth_type > .2 && this.mouth_type <=.4) {
mouth2(x, y);
} else if (this.mouth_type > .4 && this.mouth_type <=.6) {
mouth3(x, y);
} else if (this.mouth_type > .6 && this.mouth_type <=.8) {
mouth4(x, y);
} else if (this.mouth_type > .8 && this.mouth_type <=1) {
mouth5(x, y);
}
} else if (positions.left_eyebrow[3][0] > (x - cellSize / 2) && positions.left_eyebrow[3][0] < (x + cellSize / 2) && positions.left_eyebrow[3][1] > (y - cellSize / 2) && positions.left_eyebrow[3][1] < (y + cellSize / 2)) {
if (this.left_eyeBrow_height >= 0 && this.left_eyeBrow_height <= .33) {
eyebrowLow(x, y);
} else if (this.left_eyeBrow_height > .33 && this.left_eyeBrow_height <= .66) {
eyebrowMiddle(x, y);
} else if (this.left_eyeBrow_height > .66 && this.left_eyeBrow_height <= 1) {
eyebrowHigh(x, y);
}
} else if (positions.left_eyebrow[1][0] > (x - cellSize / 2) && positions.left_eyebrow[1][0] < (x + cellSize / 2) && positions.left_eyebrow[1][1] > (y - cellSize / 2) && positions.left_eyebrow[1][1] < (y + cellSize / 2)) {
if (this.left_eyeBrow_height >= 0 && this.left_eyeBrow_height <= .33) {
eyebrowLow(x, y);
} else if (this.left_eyeBrow_height > .33 && this.left_eyeBrow_height <= .66) {
eyebrowMiddle(x, y);
} else if (this.left_eyeBrow_height > .66 && this.left_eyeBrow_height <= 1) {
eyebrowHigh(x, y);
}
} else if (positions.right_eyebrow[1][0] > (x - cellSize / 2) && positions.right_eyebrow[1][0] < (x + cellSize / 2) && positions.right_eyebrow[1][1] > (y - cellSize / 2) && positions.right_eyebrow[1][1] < (y + cellSize / 2)) {
if (this.right_eyeBrow_height >= 0 && this.right_eyeBrow_height <= .33) {
eyebrowLow(x, y);
} else if (this.right_eyeBrow_height > .33 && this.right_eyeBrow_height <= .66) {
eyebrowMiddle(x, y);
} else if (this.right_eyeBrow_height > .66 && this.right_eyeBrow_height <= 1) {
eyebrowHigh(x, y);
}
} else if (positions.right_eyebrow[3][0] > (x - cellSize / 2) && positions.right_eyebrow[3][0] < (x + cellSize / 2) && positions.right_eyebrow[3][1] > (y - cellSize / 2) && positions.right_eyebrow[3][1] < (y + cellSize / 2)) {
if (this.right_eyeBrow_height >= 0 && this.right_eyeBrow_height <= .33) {
eyebrowLow(x, y);
} else if (this.right_eyeBrow_height > .33 && this.right_eyeBrow_height <= .66) {
eyebrowMiddle(x, y);
} else if (this.right_eyeBrow_height > .66 && this.right_eyeBrow_height <= 1) {
eyebrowHigh(x, y);
}
}
}
}
// eye type 1
function eye1(x, y) {
fill(128, 155, 194);
rect(x, y, cellSize, cellSize);
fill(255);
beginShape();
vertex(x - cellSize / 2, y);
bezierVertex(x - cellSize / 4, y, x - cellSize / 4, y + cellSize / 4, x, y + cellSize / 4);
bezierVertex(x + cellSize / 4, y + cellSize / 4, x + cellSize / 4, y, x + cellSize / 2, y);
bezierVertex(x + cellSize / 4, y, x + cellSize / 4, y - cellSize / 4, x, y - cellSize / 4);
bezierVertex(x - cellSize / 4, y - cellSize / 4, x - cellSize / 4, y, x - cellSize / 2, y);
endShape();
fill(0)
ellipse(x, y, cellSize / 4)
}
// eye type 2
function eye2(x, y) {
fill(128, 155, 194);
rect(x, y, cellSize, cellSize);
fill(255);
ellipse(x, y, cellSize / 2);
fill(0);
ellipse(x, y, cellSize / 4);
}
// eye type 3
function eye3(x, y) {
fill(128, 155, 194);
rect(x, y, cellSize, cellSize);
fill(108, 135, 174);
arc(x, y, cellSize / 2, cellSize / 2, 180, 360, PIE);
fill(255);
arc(x, y, cellSize / 2, cellSize / 2, 0, 180, PIE);
fill(0)
arc(x, y, cellSize / 4, cellSize / 4, 0, 180, PIE);
}
// nose bridge with shadow to the left
function noseBridge1(x, y) {
fill(128, 155, 194)
rect(x - cellSize / 4, y, cellSize / 2, cellSize);
fill(108, 135, 174);
rect(x + cellSize / 4, y, cellSize / 2, cellSize);
}
// nose bridge with shadow to the right
function noseBridge2(x, y) {
fill(108, 135, 174);
rect(x - cellSize / 4, y, cellSize / 2, cellSize);
fill(128, 155, 194);
rect(x + cellSize / 4, y, cellSize / 2, cellSize);
}
// nose tile, only one style
function noseTip(x, y) {
fill(128, 155, 194);
rect(x, y, cellSize, cellSize);
fill(108, 135, 174);
ellipse(x - cellSize / 6, y + cellSize/6, cellSize / 4, cellSize / 4);
ellipse(x + cellSize / 6, y + cellSize/6, cellSize / 4, cellSize / 4);
}
// mouth style 1
function mouth1(x, y) {
fill(0);
rect(x,y,cellSize,cellSize)
fill(255)
rect(x, y - cellSize / 2 + cellSize/8, cellSize, cellSize / 4);
}
// mouth style 2
function mouth2(x, y) {
fill(0);
rect(x, y, cellSize, cellSize);
fill(255)
rect(x, y - cellSize / 2 + cellSize / 8, cellSize, cellSize / 4);
rect(x, y + cellSize / 2 - cellSize / 8, cellSize, cellSize / 4);
}
// mouth style 3
function mouth3(x, y) {
fill(0);
rect(x, y + cellSize/8, cellSize, cellSize/4);
fill(108, 135, 174);
rect(x, y - cellSize/2 + cellSize / 8, cellSize, cellSize / 4);
fill(255);
rect(x, y - cellSize / 8, cellSize, cellSize / 4);
fill(128, 155, 194);
rect(x, y + cellSize / 2 - cellSize / 8, cellSize, cellSize / 4);
}
// mouth style 4
function mouth4(x, y) {
fill(0);
rect(x, y + cellSize/8, cellSize, cellSize/4);
fill(108, 135, 174);
rect(x, y - cellSize / 2 + cellSize / 4, cellSize, cellSize / 2);
fill(128, 155, 194);
rect(x, y + cellSize / 2 - cellSize / 8, cellSize, cellSize / 4);
}
// mouth style 5
function mouth5(x, y) {
fill(108, 135, 174);
rect(x, y - cellSize / 2 + cellSize / 4, cellSize, cellSize / 2);
fill(128, 155, 194);
rect(x, y + cellSize / 2 - cellSize / 4, cellSize, cellSize / 2);
fill(108, 135, 174);
rect(x, y + cellSize / 2 - cellSize / 8, cellSize, cellSize / 4);
}
// eyebrow middle
function eyebrowMiddle(x, y) {
fill(128, 155, 194);
rect(x, y, cellSize, cellSize);
fill(108, 135, 174)
rect(x, y, cellSize, cellSize / 4);
}
// eyebrow high
function eyebrowHigh(x, y) {
fill(128, 155, 194);
rect(x, y, cellSize, cellSize);
fill(108, 135, 174)
rect(x, y - cellSize / 2 + cellSize / 8, cellSize, cellSize / 4);
}
// eyebrow low
function eyebrowLow(x, y) {
fill(128, 155, 194);
rect(x, y, cellSize, cellSize);
fill(108, 135, 174)
rect(x, y + cellSize / 2 - cellSize / 8, cellSize, cellSize / 4);
}
// grid gradient tile, includes the various different directions that can be drawn
function gridGradient(x, y) {
fill(128, 155, 194);
rect(x, y, cellSize, cellSize)
// size and number of cells within each gradient cell. (gradient is made of a grid of squares)
var gradientGridSize = gridSize / 8;
var gradientCellSize = gradientGridSize / 15;
// variable to pick a random direction for the gradient to be drawn in (left, right, up, or down)
let directionSwitch = random(0, 1);
// draws the grid
for (let cellX = -gradientGridSize; cellX < gradientGridSize; cellX += gradientCellSize) {
for (let cellY = -gradientGridSize; cellY < gradientGridSize; cellY += gradientCellSize) {
// logic gates for the direction
if (directionSwitch >= 0 && directionSwitch < .25) {
// as Y or X value changes increase or decrease the chance for the cell to change colour
if (cellY + random(-.4, .4) < 0) {
fill(108, 135, 174)
} else {
fill(128, 155, 194)
}
} else if (directionSwitch >= .25 && directionSwitch < .5) {
if (cellY + random(-.4, .4) > 0) {
fill(108, 135, 174)
} else {
fill(128, 155, 194)
}
} else if (directionSwitch >= .5 && directionSwitch < .75) {
if (cellX + random(-.4, .4) > 0) {
fill(108, 135, 174)
} else {
fill(128, 155, 194)
}
} else if (directionSwitch >= .75 && directionSwitch < 1) {
if (cellX + random(-.4, .4) < 0) {
fill(108, 135, 174)
} else {
fill(128, 155, 194)
}
}
// draws the cell
beginShape()
vertex(x + cellX, y + cellY);
vertex(x + cellX + gradientCellSize, y + cellY);
vertex(x + cellX + gradientCellSize, y + cellY + gradientCellSize);
vertex(x + cellX, y + cellY + gradientCellSize);
endShape(CLOSE);
}
}
}
// circles cell style, includes the two versions with inverted colours
function circles(x, y) {
// size of circle
let circleSize = 4;
// variable to randomise the colours
let circleColourSwitch = random(0, 1);
// logic gate for the fill
if (circleColourSwitch < .5) {
fill(128, 155, 194);
} else {
fill(108, 135, 174);
}
rect(x, y, cellSize, cellSize);
if (circleColourSwitch < .5) {
fill(108, 135, 174);
} else {
fill(128, 155, 194);
}
// arcs are drawn in the corner and on the sides of the cell so that they don't overlap with the edges
arc(x - cellSize / 2, y - cellSize / 2, cellSize / circleSize, cellSize / circleSize, 0, 90, PIE);
arc(x - cellSize / 6, y - cellSize / 2, cellSize / circleSize, cellSize / circleSize, 0, 180, PIE);
arc(x + cellSize / 6, y - cellSize / 2, cellSize / circleSize, cellSize / circleSize, 0, 180, PIE);
arc(x + cellSize / 2, y - cellSize / 2, cellSize / circleSize, cellSize / circleSize, 90, 180, PIE);
arc(x + cellSize / 2, y - cellSize / 6, cellSize / circleSize, cellSize / circleSize, 90, 270, PIE);
arc(x + cellSize / 2, y + cellSize / 6, cellSize / circleSize, cellSize / circleSize, 90, 270, PIE);
arc(x + cellSize / 2, y + cellSize / 2, cellSize / circleSize, cellSize / circleSize, 180, 270, PIE);
arc(x - cellSize / 6, y + cellSize / 2, cellSize / circleSize, cellSize / circleSize, 180, 360, PIE);
arc(x + cellSize / 6, y + cellSize / 2, cellSize / circleSize, cellSize / circleSize, 180, 360, PIE);
arc(x - cellSize / 2, y + cellSize / 2, cellSize / circleSize, cellSize / circleSize, 270, 360, PIE);
arc(x - cellSize / 2, y - cellSize / 6, cellSize / circleSize, cellSize / circleSize, 270, 450, PIE);
arc(x - cellSize / 2, y + cellSize / 6, cellSize / circleSize, cellSize / circleSize, 270, 450, PIE);
// ellipses in the centre
ellipse(x - cellSize / 6, y - cellSize / 6, cellSize / circleSize, cellSize / circleSize);
ellipse(x + cellSize / 6, y - cellSize / 6, cellSize / circleSize, cellSize / circleSize);
ellipse(x + cellSize / 6, y + cellSize / 6, cellSize / circleSize, cellSize / circleSize);
ellipse(x - cellSize / 6, y + cellSize / 6, cellSize / circleSize, cellSize / circleSize);
}
// draws the triangular styled cell in its two inverted variants
function triangles(x, y) {
// same as the other functions, randomises the two variants
let triangleColourSwitch = random(0, 1);
// logic gates for fill
if (triangleColourSwitch < .5) {
fill(128, 155, 194);
} else {
fill(108, 135, 174);
}
rect(x, y, cellSize, cellSize);
if (triangleColourSwitch < .5) {
fill(108, 135, 174);
} else {
fill(128, 155, 194);
}
// draw the triangles using a custom shape
beginShape();
vertex(x - cellSize / 2, y + cellSize / 2);
vertex(x - cellSize / 2, y - cellSize / 2);
vertex(x, y + cellSize / 2);
vertex(x, y - cellSize / 2);
vertex(x + cellSize / 2, y + cellSize / 2);
endShape(CLOSE)
}
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function (settings) {
this.eye_type = map(settings[0], 0, 100, 0, 1);
this.right_eyeBrow_height = map(settings[1], 0, 100, 0, 1);
this.left_eyeBrow_height = map(settings[2], 0, 100, 0, 1);
this.mouth_type = map(settings[3], 0, 100, 0, 1);
this.bridge_direction = map(settings[4], 0, 100, 0, 1);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function () {
let settings = new Array(3);
settings[0] = map(this.eye_type, 0, 1, 0, 100);
settings[1] = map(this.right_eyeBrow_height, 0, 1, 0, 100);
settings[2] = map(this.left_eyeBrow_height, 0, 1, 0, 100);
settings[3] = map(this.mouth_type, 0, 1, 0, 100);
settings[4] = map(this.bridge_direction, 0, 1, 0, 100);
return settings;
}
}
{
"000001": [
20,
50,
50,
20,
20
],
"000002": [
43,
84,
72,
11,
20
],
"000005": [
17,
84,
72,
71,
20
],
"000006": [
17,
84,
72,
56.00000000000001,
20
],
"000007": [
100,
0,
0,
100,
53
],
"000009": [
2,
47,
86,
48,
53
],
"000010": [
20,
0,
0,
92,
53
],
"000013": [
60,
0,
0,
45,
0
],
"000014": [
22,
100,
100,
100,
53
],
"000015": [
100,
0,
0,
50,
50
],
"000016": [
54,
44,
38,
100,
50
],
"000018": [
0,
100,
100,
7.000000000000001,
50
],
"000020": [
97,
42,
38,
25,
50
],
"000023": [
56.99999999999999,
42,
38,
57.99999999999999,
100
],
"000025": [
93,
0,
0,
100,
100
],
"000028": [
0,
100,
100,
13,
0
],
"000029": [
0,
43,
46,
48,
0
],
"000030": [
60,
0,
0,
100,
0
],
"000031": [
0,
46,
51,
41,
0
],
"000032": [
75,
46,
51,
72,
0
],
"000035": [
0,
100,
100,
67,
0
],
"000037": [
100,
0,
60,
97,
0
],
"000038": [
47,
54,
60,
46,
0
],
"000040": [
17,
84,
72,
71,
20
],
"000041": [
47,
5,
46,
46,
0
],
"000042": [
0,
43,
46,
100,
0
],
"000043": [
17,
84,
72,
0,
56.99999999999999
],
"000044": [
0,
50,
50,
76,
50
],
"000045": [
0,
100,
100,
13,
0
],
"000047": [
92,
65,
79,
59,
36
],
"000048": [
38,
95,
100,
85,
10
],
"000050": [
76,
0,
0,
46,
0
],
"000051": [
54,
42,
38,
99,
50
],
"000052": [
42,
74,
80,
65,
5
],
"000054": [
0,
50,
50,
0,
50
],
"000055": [
53,
33,
46,
100,
1
],
"000056": [
30,
84,
72,
41,
20
],
"000058": [
0,
0,
50,
100,
50
],
"000060": [
77,
21,
49,
98,
25
],
"000064": [
100,
48,
50,
73,
87
],
"000065": [
65,
42,
66,
42,
10
],
"000068": [
100,
30,
50,
31,
100
],
"000069": [
48,
0,
0,
72,
26
],
"000071": [
17,
84,
72,
45,
20
],
"000073": [
15,
89,
81,
59,
13
],
"000076": [
74,
24,
25,
100,
56.00000000000001
],
"000077": [
0,
0,
50,
100,
50
],
"000078": [
22,
100,
100,
100,
53
],
"000079": [
52,
23,
42,
96,
50
],
"000080": [
73,
24,
24,
81,
32
],
"000081": [
98,
12,
50,
14.000000000000002,
100
],
"000083": [
0,
73,
75,
89,
0
],
"000085": [
1,
48,
68,
82,
51
],
"000086": [
0,
100,
100,
76,
100
],
"000088": [
0,
61,
84,
59,
50
],
"000091": [
100,
0,
0,
100,
0
],
"000092": [
0,
50,
75,
83,
25
],
"000096": [
13,
43,
52,
70,
42
],
"000097": [
15,
92,
86,
57.99999999999999,
60
],
"000099": [
10,
75,
75,
17,
60
],
"000100": [
7.000000000000001,
96,
93,
67,
80
],
"000103": [
6,
61,
80,
100,
56.00000000000001
],
"000104": [
0,
100,
100,
13,
0
],
"000106": [
20,
50,
50,
20,
20
],
"000108": [
0,
43,
46,
0,
0
],
"000109": [
49,
14.000000000000002,
44,
71,
25
],
"000110": [
13,
94,
90,
0,
56.99999999999999
],
"000111": [
100,
72,
64,
0,
30
],
"000114": [
50,
11,
21,
84,
38
],
"000115": [
60,
0,
0,
100,
0
],
"000116": [
68,
39,
54,
0,
24
],
"000117": [
0,
68,
62,
44,
33
],
"000118": [
10,
75,
75,
84,
60
],
"000121": [
0,
100,
100,
72,
96
],
"000122": [
10,
75,
74,
44,
37
],
"000125": [
55.00000000000001,
18,
20,
63,
0
],
"000126": [
19,
44,
40,
57.99999999999999,
31
],
"000129": [
52,
9,
27,
56.00000000000001,
6
],
"000131": [
6,
48,
63,
56.99999999999999,
59
],
"000132": [
14.000000000000002,
83,
83,
0,
56.99999999999999
],
"000133": [
9,
66,
67,
36,
40
],
"000134": [
91,
11,
53,
53,
100
],
"000135": [
66,
0,
0,
82,
48
],
"000137": [
64,
59,
57.99999999999999,
56.00000000000001,
80
],
"000140": [
0,
0,
2,
100,
80
],
"000142": [
9,
84,
85,
69,
2
],
"000143": [
82,
36,
40,
76,
73
],
"000145": [
12,
78,
74,
34,
13
],
"000146": [
9,
69,
71,
31,
23
],
"000147": [
10,
73,
68,
67,
26
],
"000148": [
4,
56.99999999999999,
73,
51,
42
],
"000150": [
67,
3,
11,
100,
100
],
"000151": [
22,
62,
68,
33,
44
],
"000152": [
67,
28.000000000000004,
35,
56.99999999999999,
8
],
"000153": [
61,
28.000000000000004,
35,
50,
51
],
"000155": [
9,
68,
73,
43,
49
],
"000156": [
19,
53,
51,
57.99999999999999,
26
],
"000157": [
15,
62,
56.00000000000001,
65,
39
],
"000160": [
79,
1,
11,
73,
38
],
"000161": [
11,
86,
79,
6,
13
]
}
const ease_gar = new p5.Ease();
//Leafs variables
let leafCount = 8; // number of leafs to draw
let LEAFS = []; // leaf array
let first_draw = true;
function garcia_draw_one_frame(cur_frac) {
if(first_draw) {
first_draw = false;
for (let leafFall = 0; leafFall < leafCount; leafFall++) {
LEAFS.push({
x1: random(-1, width / 3),
x2: random(width / 1.5, width + width / 50),
y: 0,
variation: random(-width / 50, +width / 20),
rotation: random(-20, 20),
size: random(.15, .4)
});
}
}
angleMode(DEGREES);
let sun_size = canvasHeight / 3.5;
let halfWidth = width / 2;
let thirdWidth = width / 3
let quarterWidth = width / 4;
let fifthWidth = width / 5;
let halftHeight = height / 2;
let thirdHeight = height / 3;
let quarterHeight = height / 4;
let fifthHeight = height / 5;
let customStrokeWeight = width / 550;
//set up colours
let orange = '#E6703D';
let darkOrange = '#ae473f';
let brown = '#A87338';
let yellow = '#ffc039';
let darkYellow = '#f7a61e';
let beige = '#faf8e6';
let white = '#ffffff';
let green = '#4c806c';
let skyColor = '#F0B79E';
let waterColor = '#ffedd9';
let lightPink = '#FE95A1';
let middlePink = '#FF8795';
let darkPink = '#FF7181';
let darkerPink = '#80163C';
let magenta = '#dd455a';
let purple = '#9e2754';
let middlePurple = '#7b3759';
let darkPurple = '#400522';
/*********STAR FUNCTION************/
// function to draw a star reference : https://p5js.org/examples/form-star.html
function star(x, y, min, max, end) {
const angle = 360 / 4;
const halfAngle = angle / 2;
const radius1 = width / 350;
const radius2 = width / 90;
let starSize;
push();
translate(x, y);
//animate star in
if (cur_frac < max && cur_frac >= min) {
starSize = map(cur_frac, 0, max, 0, 1);
scale(starSize);
beginShape();
for (let a = 0; a < 360; a += angle) {
let sx = cos(a) * radius1;
let sy = sin(a) * radius1;
vertex(sx, sy);
sx = cos(a + halfAngle) * radius2;
sy = sin(a + halfAngle) * radius2;
vertex(sx, sy);
}
endShape(CLOSE);
}
// animate star out
else if (cur_frac < end && cur_frac >= max) {
starSize = map(cur_frac, max, end, 1, 0);
scale(starSize);
beginShape();
for (let a = 0; a < 360; a += angle) {
let sx = cos(a) * radius1;
let sy = sin(a) * radius1;
vertex(sx, sy);
sx = cos(a + halfAngle) * radius2;
sy = sin(a + halfAngle) * radius2;
vertex(sx, sy);
}
endShape(CLOSE);
}
pop();
}
/********FUNCTION TO ADD AN OFFSET TO ANIMATIONS*********/
//function created by Hazel and modified by me
function offsetAnimation(cur_frac, offsetAMT, number) {
let newFrac;
if (number == 1) {
newFrac = ease_gar.maclaurinCosine(cur_frac); // bird animation
} else if (number == 2) {
newFrac = ease_gar.gompertz(cur_frac); // ripples animation
} else if (number == 3) {
newFrac = ease_gar.linear(cur_frac); // leafs animation
}
for (let i = 0; i <= offsetAMT; i += 0.01) {
newFrac += 0.01;
if (newFrac >= 1) {
newFrac = 0;
}
}
return newFrac;
}
/*****************SKY***************/
noStroke();
fill(skyColor);
push();
rectMode(CORNER);
rect(0, 0, width, height);
pop();
/**********BIRDS FUNCTION*********/
function bird(birdX, birdY, birdSize, animationOffset) {
let birdWingY;
let newFrac = offsetAnimation(cur_frac, animationOffset, 1); // add an offset
stroke(white);
noFill();
strokeWeight(customStrokeWeight);
//draw the bird
push();
translate(birdX, birdY);
scale(birdSize); // add scale to change the bird size
// animate the wings Y position
if (newFrac < .5) {
birdWingY = map(newFrac, 0, 0.5, height / 100, -height / 60);
} else {
birdWingY = map(newFrac, 0.5, 1, -height / 60, height / 100);
}
//draw birds
beginShape();
vertex(-width / 100, birdWingY);
vertex(0, 0);
vertex(width / 100, birdWingY);
endShape();
pop();
}
bird(width / 2.3, height / 4.5, 1.7, 0.5);
bird(width / 2.5, height / 6, 1.3, 0.3);
bird(width / 2.1, height / 5.5, 1.3, 0.4)
bird(width / 1.95, height / 7, 1, 0.2);
/*******************SUN********************/
noStroke();
fill(lightPink);
ellipse(halfWidth, halftHeight - width / 35, sun_size + width / 15);
fill(middlePink);
ellipse(halfWidth, halftHeight - width / 35, sun_size + width / 30);
fill(darkPink);
ellipse(halfWidth, halftHeight - width / 35, sun_size);
/*****************MOUNTAINS*************/
//mountain back
fill('#caa291');
beginShape();
curveVertex(-quarterWidth, height / 1.5); //left
curveVertex(width / 1.5, height / 1.5); //right
curveVertex(thirdWidth, height / 2.5); //top
endShape(CLOSE);
//shadow
fill('#D4B0A0')
beginShape();
curveVertex(width / 1.5, height / 1.8); //right
curveVertex(width / 2.5, height / 2.25); //top
curveVertex(width / 3.5, height / 1.9); // middle
curveVertex(width / 5, height / 1.8); // left
curveVertex(width / 6, height / 1.5); // bottom
endShape(CLOSE);
// mountain front
fill("#bd9384");
beginShape();
curveVertex(width * 1.25, height / 1.25); //right
curveVertex(width / 6, height / 1.45); //left
curveVertex(thirdWidth, height / 1.75) //top right
curveVertex(width / 1.25, height / 2.75); //top
endShape(CLOSE);
//shadow
fill('#B08778');
beginShape();
curveVertex(width / 6, height / 1.5); //left
curveVertex(width / 3.5, height / 1.6) //top right
curveVertex(width / 1.4, height / 2.45); //top
curveVertex(width / 1.5, height / 1.5);
endShape(CLOSE);
/***************WATER**********************/
fill(waterColor);
noStroke();
push();
rectMode(CORNER);
rect(0, height / 1.5, width, thirdHeight);
pop();
//sun reflection / ripples
function ripples(x1, Y, x2, offset) {
let waterChange;
let newFrac = offsetAnimation(cur_frac, offset, 2);
if (newFrac < 0.5) {
waterChange = map(newFrac, 0, .5, 0, width / 150);
} else {
waterChange = map(newFrac, 0.5, 1, width / 150, 0);
}
stroke(lightPink);
strokeWeight(width / 200);
line(x1 - waterChange, Y, x2 - waterChange, Y);
}
//draw ripples
ripples(width / 2 - width / 12, height / 1.45, width / 2 + width / 25, 0.5);
ripples(width / 2 + width / 14, height / 1.45, width / 2 + width / 10, .2);
ripples(width / 2 - width / 14, height / 1.4, width / 2 + width / 15, .5);
ripples(width / 2 + width / 11, height / 1.4, width / 2 + width / 10, 0);
ripples(width / 2 - width / 20, height / 1.35, width / 2 - width / 50, 0.8);
ripples(width / 2, height / 1.35, width / 2 + width / 13, .9);
ripples(width / 2 - width / 50, height / 1.3, width / 2 + width / 20.1, .4);
//sparkles
fill(white);
noStroke();
star(width / 2 + width / 50, height / 1.45, 0, .25, .5);
star(width / 2 - width / 25, height / 1.4, .28, .6, .8);
star(width / 2 + width / 20, height / 1.35, .15, .35, .7);
/*********************BOAT***************/
function boat() {
// sails
noStroke();
fill(purple);
triangle(width / 200, 0, 0, -height / 5, -width / 12, -height / 90);
triangle(width / 100, 0, width / 300, -height / 5, width / 20, -height / 70);
//boat base
fill(magenta);
push();
rectMode(CORNER);
rect(-width / 10.1, 0, width / 10, height / 20);
arc(0, 0, width / 7, height / 10, 0, 90);
rect(width / 15, -height / 90, width / 200, height / 80);
pop();
//boat wood detail
noFill();
stroke(middlePink);
strokeWeight(customStrokeWeight);
line(width / 14.5, height / 120, -width / 10.2, height / 120);
line(width / 15, height / 120 + height / 120, -width / 10.2, height / 120 + height / 120);
line(width / 16.5, height / 120 + (2 * height / 120), -width / 10.2, height / 120 + (2 * height / 120));
line(width / 19.5, height / 120 + (3 * height / 120), -width / 10.2, height / 120 + (3 * height / 120));
line(width / 22, height / 120 + (4 * height / 120), -width / 10.2, height / 120 + (4 * height / 120));
// small windows
strokeWeight(height / 300);
fill(purple);
circle(width / 50, height / 60, height / 80);
circle(width / 50 + width / 80, height / 60, height / 80);
circle(width / 50 + (2 * width / 80), height / 60, height / 80);
}
//draw boat
push();
translate(width / 3.25, height / 1.45);
//animate the boat angle
let boatAngle;
let boatFAngleMovement = ease_gar.backInOut(cur_frac);
if (cur_frac < .5) {
boatAngle = map(boatFAngleMovement, 0, 0.5, 0, 2);
} else {
boatAngle = map(boatFAngleMovement, 0.5, 1, 2, 0);
}
rotate(boatAngle);
//draw the boat
boat();
pop();
//water in front of the boat to hide the bottom of the hull
fill("#ffedd9");
push();
rectMode(CORNER);
rect(width / 5, height / 1.37, width / 6, height / 20);
pop();
/***************LEFT FLOOR***********/
noStroke();
fill(middlePurple);
beginShape();
curveVertex(width - width / 10, height + height / 10); // right
curveVertex(0, height); //left bottom
curveVertex(-quarterWidth, height / 1.3); // left
curveVertex(width / 10, height / 1.4); // top middle
curveVertex(halfWidth, height / 1.1); //bottom middle
endShape(CLOSE);
/**************TREE FUNCTION*************/
function tree(x, y) {
fill(beige);
rectMode(CENTER);
//draw the base of the tree trunc
rect(x, y, width / 20, halftHeight);
arc(x, y + height / 4.015, width / 20, height / 40, 0, 180);
// draw the circles
stroke(green);
strokeWeight(customStrokeWeight);
ellipse(x, y + width / 150, width / 50, height / 20);
ellipse(x, y + width / 150, width / 150, height / 45);
// draw the stripes
for (let i = 1; i < 5; i++) {
noFill();
arc(x, y + (height / 18) * i, width / 20.25, height / 40, 0, 180);
arc(x, y - (height / 18) * i, width / 20.25, height / 40, 0, 180);
}
}
/*********SMALL LEAF FUNCTION*********/
function leaf(x, y, s, angle) {
push();
translate(x, y);
scale(s);
rotate(angle);
bezier(0, 0, -width / 20, -height / 6, -width / 40, -height / 6, 0, -height / 4);
bezier(0, 0, width / 20, -height / 6, width / 40, -height / 6, 0, -height / 4);
pop();
}
/***********MOVING LEAF FUNCTION*******/
function movingLeaf(Num) {
let jvalue;
let Value;
let min = 0.1;
// start the for loop at different values depending on the Num value to split the leafs from the left and the right of the screen
if (Num == 1) {
jvalue = 0;
Value = LEAFS.length / 2; // half array
} else {
jvalue = 3;
Value = LEAFS.length; // full array
}
for (let j = jvalue; j < Value; j++) {
const leafs = LEAFS[j]; // assign the each value of the LEAFS array to a variable
let leafX;
let newFrac = offsetAnimation(cur_frac, min, 3); //offset the animation of the leafs
let XValue;
// assign different X value to the different side
if (Num == 1) {
XValue = leafs.x1
} else {
XValue = leafs.x2
}
// wiggle the leafs from left to right
if (cur_frac < .25) {
leafX = map(cur_frac, 0, .25, XValue, XValue + leafs.variation);
} else if (cur_frac >= .25 && cur_frac <= .5) {
leafX = map(cur_frac, .25, .5, XValue + leafs.variation, XValue);
} else if (cur_frac > .5 && cur_frac < .75) {
leafX = map(cur_frac, .5, .75, XValue, XValue - leafs.variation);
} else {
leafX = map(cur_frac, .75, 1, XValue - leafs.variation, XValue);
}
// animate the leafs from top to bottom
let leafY = map(newFrac, 0, 1, height / 4, height + height / 10);
// animate the rotation of the leafs
let leafRotation = ease_gar.linear(cur_frac);
let leafAngle;
if (cur_frac < 0.25) {
leafAngle = map(leafRotation, 0, .25, 0, 15);
} else if (cur_frac >= 0.25 && leafRotation <= 0.5) {
leafAngle = map(leafRotation, .25, .5, 15, 0);
} else if (cur_frac > 0.5 && leafRotation < 0.75) {
leafAngle = map(leafRotation, .5, .75, 0, -15);
} else {
leafAngle = map(leafRotation, .75, 1, -15, 0);
}
// draw the leafs
push();
translate(leafX, leafY);
rotate(leafAngle);
scale(leafs.size);
fill(yellow);
noStroke();
bezier(0, 0, -width / 20, -height / 6, -width / 40, -height / 6, 0, -height / 4);
bezier(0, 0, width / 20, -height / 6, width / 40, -height / 6, 0, -height / 4);
pop();
min += 0.3; // add more offset to each leaf
}
}
/*************LEFT TREE************/
//back leafs
fill(darkYellow)
push();
ellipseMode(CORNER)
ellipse(0 - width / 15, height / 3.25, width / 6, quarterHeight);
ellipse(width / 6, height / 15, fifthWidth, thirdHeight);
ellipse(width / 15, height / 4, width / 5.5, quarterHeight);
pop();
//tree base
tree(width / 10, halftHeight);
// moving leafs
movingLeaf(1);
//front leafs
fill(yellow);
noStroke();
push();
ellipseMode(CORNER);
ellipse(0 - width / 12, 0 - height / 50, width / 5, height / 2.5);
ellipse(width / 5, 0 - height / 20, width / 5, height / 5);
ellipse(width / 30, 0 - height / 15, width / 5, height / 3);
ellipse(width / 6, 0, width / 5, height / 3);
pop();
// small leaf detail
fill(darkYellow);
leaf(width / 4, height / 4, .25, 25);
leaf(width / 8, height / 8, .2, -45);
leaf(width / 3.5, height / 10, .15, 70);
leaf(width / 15, height / 4.5, .35, -30);
leaf(width / 5, height / 8, .4, 20);
leaf(width / 18, height / 15, .2, 18);
//floor front
noStroke();
fill(darkPurple);
beginShape();
curveVertex(0, height); // left
curveVertex(width + width / 20, height); // right
curveVertex(width / 1.005, height / 1.35); // right top
curveVertex(width / 1.3, height / 1.4) // right middle
curveVertex(width / 2.5, height / 1.1);
endShape(CLOSE);
/************TREE FOREGROUND********/
//back leafs
fill(darkYellow)
push();
ellipseMode(CORNER);
ellipse(width - width / 9, thirdHeight, width / 6, height / 3.5); //bottom right
ellipse(width / 1.5, height / 15, fifthWidth, thirdHeight);
ellipse(width / 1.3, height / 3.5, width / 6, height / 3.5);
pop();
//tree base
tree(width - width / 8, height / 2.05);
//moving leafs
movingLeaf(2);
//front leafs
fill(yellow);
noStroke();
push();
ellipseMode(CORNER);
ellipse(width / 1.18, 0 - height / 50, fifthWidth, height / 2.5);
ellipse(width / 1.5, 0 - height / 20, fifthWidth, fifthHeight);
ellipse(width / 1.4, 0 - height / 15, fifthWidth, thirdHeight);
ellipse(width / 1.4, 0, fifthWidth, thirdHeight);
pop();
// small leaf detail
fill(darkYellow);
leaf(width - width / 5, height / 8, .25, 20);
leaf(width - width / 4.5, height / 4, .2, -45);
leaf(width - width / 8, height / 15, .15, -40);
leaf(width - width / 15, height / 3, .35, 30);
leaf(width - width / 3.5, height / 10, .38, -10);
leaf(width - width / 18, height / 15, .2, 18);
leaf(width - width / 9, height / 4.5, .4, 15);
/********FOREGROUND BERRY BUSH*********/
//berry function
function berry(x, y, color, side) {
if (color == 1) {
fill(orange)
} else if (color == 2) {
fill(brown)
} else {
fill(darkOrange)
}
let w = width / 50;
circle(x, y, w);
//shine
fill(lightPink);
if (side == 1) {
circle(x - width / 300, y - height / 300, w - width / 70);
} else {
circle(x + width / 300, y - height / 300, w - width / 70);
}
}
//right leafs
fill(darkerPink);
leaf(width, height, 1, -10);
leaf(width, height, 1, -80);
leaf(width - width / 200, height, 1, -35);
//right side berries
berry(width - width / 25, height - height / 18, 1, 1);
berry(width - width / 9.5, height - height / 9, 1, 1);
berry(width - width / 8, height - height / 40, 1, 1);
berry(width - width / 50, height - height / 20, 2, 1);
berry(width - width / 30, height - height / 8, 2, 1);
berry(width - width / 12, height - height / 10, 2, 1);
berry(width - width / 11, height - height / 35, 2, 1);
berry(width - width / 18, height - height / 10, 3, 1);
berry(width - width / 12, height - height / 7, 3, 1);
berry(width - width / 9, height - height / 15, 3, 1);
berry(width - width / 23, height - height / 40, 3, 1);
berry(width - width / 15, height - height / 20, 3, 1);
berry(width - width / 70, height - height / 11, 3, 1);
//left leafs
fill(purple);
leaf(width / 400, height, 1, 5);
leaf(0, height, 1, 90);
leaf(0, height, 1, 45);
//left side
berry(width / 9, height - height / 9, 1, 2);
berry(width / 40, height - height / 14, 1, 2);
berry(width / 8, height - height / 40, 1, 2);
berry(width / 50, height - height / 20, 2, 2);
berry(width / 25, height - height / 9, 2, 2);
berry(width / 12, height - height / 10, 2, 2);
berry(width / 11, height - height / 35, 2, 2);
berry(width / 18, height - height / 10, 3, 2);
berry(width / 12, height - height / 7, 3, 2);
berry(width / 9, height - height / 15, 3, 2);
berry(width / 25, height - height / 40, 3, 2);
berry(width / 15, height - height / 20, 3, 2);
}
/*
* FaceMap class - holds all information about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program
// var DEBUG_MODE = false;
// this can be used to set the number of sliders to show
var NUM_SLIDERS = 8;
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i = 0; i < s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len, sum_y / s_len];
}
// This where you define your own face object
function GarciaFace() {
// these are state variables for a face
this.gender = 1; // 1 or 2
this.skin = 2; // 1, 2, 3
this.hair = 1; // 1, 2, 3 or 4
this.eyes = 3; // 1 or 2
this.fringeType = 2; // 1, 2, 3 or 4
this.earType = 1; // 1, 2, 3 or 4
this.hairType = 1; // 1, 2 or 3
this.features = 1; // 1 or 2
/*Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function (positions) {
angleMode(DEGREES);
// get the width of the face from the chin positions
let jaw_dist = positions.chin[16][0] - positions.chin[0][0];
let faceWidth = map(jaw_dist, 3.2, 4.2, 3.5, 4.6, true);
/**********MOUTH FUNCTION*********/
function MOUTH(gender) {
/***VARIABLES MAPPED TO POSITIONS***/
// get the mouth opening from the bottom and top lip positions
let mouth_height = positions.bottom_lip[8][1] - positions.top_lip[8][1];
let mouthType;
// draw closed mouth
if (mouth_height < .1) {
mouthType = 1
}
//draw open mouth and map the mouth opening
else {
mouthType = 2
}
// get the mouth position
let mouth_pos = segment_average(positions.bottom_lip);
// get the mouth width
let mouth_width = positions.top_lip[6][0] - positions.top_lip[0][0];
//mouth colours
const mouthStokeColor = '#76051B';
const mouthColor1 = '#EF9A9A';
const mouthColor2 = '#EC8383';
strokeWeight(.08);
push();
translate(mouth_pos[0], mouth_pos[1]);
/*****CLOSED MOUTH*****/
if (mouthType < 2) {
// get the height of the bottom lip
let bottom_lip_height = positions.bottom_lip[2][1] - positions.bottom_lip[7][1];
//get the height of the top lip
let top_lip_height = positions.top_lip[7][1] - positions.top_lip[2][1];
// map top and bottom lip heights
let bottomLip = map(bottom_lip_height, 0.07, 0.5, .5, 1, true);
let topLip = map(top_lip_height, 0.18, 0.4, .6, 1, true);
//lips for women
if (gender < 2) {
//bottom lip
stroke(mouthStokeColor);
fill(mouthColor1);
arc(0, 0, mouth_width, bottomLip, 0, 180, OPEN);
// top lip
fill(mouthColor2);
arc(0, 0, mouth_width, topLip, 180, 0, OPEN);
// lip shine detail
noStroke();
fill(255);
ellipse(-.38, .15, .25, .1);
circle(-.1, .15, .1);
}
// lip middle line
stroke(mouthStokeColor);
line(positions.top_lip[6][0] + .15, 0, positions.top_lip[0][0] - .15, 0);
}
/*****OPEN MOUTH*****/
else {
let mouthHeight = map(mouth_height, .01, .3, .7, 1.7, true);
let tongueHeight = map(mouthHeight, 1, 2, .25, .5);
// mouth base
stroke(mouthStokeColor);
fill(mouthColor2);
arc(0, -0.5, mouth_width, mouthHeight, 0, 180, CHORD);
// tongue
noStroke();
fill(mouthStokeColor);
ellipse(0, mouthHeight / 2 - tongueHeight - .4, mouth_width - .5, tongueHeight);
}
pop();
};
/**********HAIR FUNCTION*********/
function HAIR(hairType, gender, faceWidth) {
let hairStroke = .7;
/******WOMEN HAIR*******/
if (gender < 2) {
/*****SPACE BUNS HAIR*****/
if (hairType < 2) {
// shadow
push();
noFill();
stroke(0, 50);
strokeWeight(hairStroke);
circle(-2.25, -3, 2);
circle(2.75, -3, 2);
ellipse(.25, -.75, 6, 6);
pop();
// white outline
push();
noFill();
stroke(255);
strokeWeight(hairStroke);
circle(-2.5, -3, 2); // left spacebun
circle(2.5, -3, 2); //right spacebun
ellipse(0, -.75, 6, 6); // hair base
pop();
// hair
push();
fill(hairColor);
circle(-2.5, -3, 2); // left spacebun
circle(2.5, -3, 2); //right spacebun
circle(0, -.75, 6); // hair base
pop();
}
/*****STRAIGHT HAIR*****/
else {
// shadow
push();
fill(0, 50);
rectMode(CENTER);
rect(.4, 1.6, 6.7, 3.8);
arc(.4, -.3, 6.7, 6.7, 180, 0);
pop();
// White Outline
push();
fill(255);
rectMode(CENTER);
rect(0, 1.2, 6.7, 3.9);
arc(0, -.7, 6.7, 6.7, 180, 0);
pop();
// hair shape
push();
fill(hairColor);
rectMode(CENTER);
rect(0, 1, 6, 3.6);
arc(0, -.75, 6, 6, 180, 0);
pop();
}
}
/********MEN HAIR STYLE******/
else {
/*******ROUND HAIR*******/
if (hairType < 2) {
//shadow
push();
rectMode(CENTER);
noFill();
stroke(0, 50);
strokeWeight(hairStroke);
strokeCap(SQUARE);
rect(.25, -1.5, faceWidth, 3);
arc(.25, 0.1, faceWidth, 4.5, 0, 180, OPEN);
pop();
//white outline
push();
rectMode(CENTER);
noFill();
stroke(255);
strokeWeight(hairStroke);
rect(0, -1.75, faceWidth, 3);
ellipse(0, -.25, faceWidth, 4.5);
pop();
//hair
push();
rectMode(CENTER);
fill(hairColor);
rect(0, -1.75, faceWidth, 3);
pop();
}
/*********FLAT TOP*******/
else {
// shadow
push();
noFill();
stroke(0, 50);
strokeWeight(hairStroke);
ellipse(0.25, 0, faceWidth, 4.5);
ellipse(0.25, -0.75, 4.5, 4.25); // hair base
pop();
// white outline
push();
noFill();
stroke(255);
strokeWeight(hairStroke);
ellipse(0, -.25, faceWidth, 4.5);
ellipse(0, -1, 4.5, 4.25); // hair base
pop();
// hair
fill(hairColor);
ellipse(0, -1, 4.5, 4.25); // hair base
}
}
};
/**********FRINGE FUNCTION*********/
function FRINGE(fringeType, faceWidth, gender, hair) {
noStroke();
fill(hairColor);
/*****SIDE FRINGE*****/
if (fringeType == 1) {
push();
translate(-1.25, -2.4);
rotate(-25);
arc(0, -.10, 4, 3, 20, 144);
pop();
/*******HAIR PINS*****/
if (gender < 2) {
let hairPin = random(1, 10); // randomise when there is an hair pin
// draw a star hair pin if the earrings are not the star ones
if (hairPin < 5) {
// function to draw a star reference : https://p5js.org/examples/form-star.html
function star(x, y) {
const angle = 360 / 5;
const halfAngle = angle / 2;
beginShape();
for (let a = 0; a < 360; a += angle) {
let sx = x + cos(a) * .4;
let sy = y + sin(a) * .4;
vertex(sx, sy);
sx = x + cos(a + halfAngle) * .18;
sy = y + sin(a + halfAngle) * .18;
vertex(sx, sy);
}
endShape(CLOSE);
}
noStroke();
fill('#F4D525');
star(-2.15, -1);
}
// draw a heart hair pin if the earrings are not the heart ones
else if (hairPin > 8 && hair >= 2) {
// function to draw a heart reference: https://editor.p5js.org/Mithru/sketches/Hk1N1mMQg
function heart(x, y) {
beginShape();
vertex(x, y);
bezierVertex(x - 1.5 / 2, y - 1.5 / 2, x - 1.5, y + 1.5 / 3, x, y + 1.5);
bezierVertex(x + 1.5, y + 1.5 / 3, x + 1.5 / 2, y - 1.5 / 2, x, y);
endShape(CLOSE);
}
push();
translate(-2.15, -1.25);
scale(.5);
noStroke;
fill('#D90368');
heart(0, 0);
pop();
}
}
}
/*****STRAIGHT FRINGE*****/
else if (fringeType == 2) {
arc(0, -1.25, faceWidth, 3.5, 180, 0);
}
/******CENTER HAIRLINE******/
else {
arc(0, -3, 3, 2.5, 30, 150);
}
};
/**********EYES FUNCTION*********/
function EYES(gender, eyes) {
//Eyes colours
const eyeColor1 = '#6BABEC';
const eyeColor2 = '#BB85C9';
let eyeColor;
let pupil = random(.4, .9);
// map colours to slider
if (eyes < 2) {
eyeColor = eyeColor1
} else {
eyeColor = eyeColor2
}
/*****EYES VARIABLES*****/
const lashSize = .2;
const lashGap = -.05;
let lashNum = int(random(5, 12));
const eyeHeight = .9;
const eyeWidth = 1.2;
const eyeStrokeWeight = .1;
/*******EYES VARIABLES FROM POSITION*****/
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye);
// get the right eye opening from the eye positions
let right_eye_opening = positions.right_eye[5][1] - positions.right_eye[1][1];
let rightEyeType;
// closed eye
if (right_eye_opening < 0.167) {
rightEyeType = 1;
}
// half open eye
else if (right_eye_opening >= 0.167 && right_eye_opening <= 0.18) {
rightEyeType = 2;
}
// wide open eye
else {
rightEyeType = 3;
}
// get the left eye opening from the eye positions
let left_eye_opening = positions.left_eye[4][1] - positions.left_eye[2][1];
let leftEyeType;
// closed eye
if (left_eye_opening <= 0.18) {
leftEyeType = 1;
}
// half open eye
else if (left_eye_opening > 0.18 && left_eye_opening < 0.19) {
leftEyeType = 2;
}
//wide open eye
else {
leftEyeType = 3;
}
/*****EYELASHES FUNCTION*****/
function eyeLashes(num, radius, length, start, span) {
stroke(0);
strokeWeight(eyeStrokeWeight);
push();
rotate(start);
for (i = 0; i <= num; i++) {
push();
rotate(span / num * i)
line(0, -radius, 0, -(radius + length))
pop();
};
pop();
}
push();
/*****LEFT EYE*****/
// closed eye
if (leftEyeType == 1) {
//draw the left eye
push();
translate(left_eye_pos[0] - .25, left_eye_pos[1]); // translate to the center of the left eye
stroke(0);
strokeWeight(eyeStrokeWeight);
line(-.6, 0, .75, 0); // closed eye line
//lashes
if (gender < 2) {
line(-.6, 0, -.9, .25);
line(-.25, 0, -.5, .25);
}
pop();
}
// half open eye
else if (leftEyeType == 2) {
//draw the left eye
push();
translate(left_eye_pos[0] - .25, left_eye_pos[1]);
// draw the eye base
stroke(0);
strokeWeight(eyeStrokeWeight);
fill(255);
arc(0, 0, eyeWidth, eyeHeight, 0, 180, CHORD);
// coloured pupil
noStroke();
fill(eyeColor);
arc(0, 0, pupil * .75, pupil, 0, 180);
// iris
fill(0);
arc(0, 0, pupil * .75 - .2, pupil - .2, 0, 180);
// light detail
fill(255);
circle(-.25, .25, .2);
if (gender < 2) {
//lashes
eyeLashes(lashNum / 2, eyeWidth / 2 + lashGap, lashSize, -90, -180);
}
pop();
}
// wide open eye
else {
//draw the left eye
push();
translate(left_eye_pos[0] - .25, left_eye_pos[1]); // translate to the center of the left eye
//left eye base
fill(255);
stroke(0);
strokeWeight(eyeStrokeWeight);
ellipse(0, 0, eyeWidth, eyeHeight);
// coloured pupil
noStroke();
fill(eyeColor);
ellipse(0, 0, pupil * .75, pupil);
// iris
fill(0);
ellipse(0, 0, pupil * .75 - .2, pupil - .2);
// light detail
fill(255);
circle(-.25, .2, .3);
if (gender < 2) {
//lashes
eyeLashes(lashNum, eyeWidth / 2 + lashGap, lashSize, -90, 360);
}
pop();
}
/*****RIGHT EYE*****/
// closed eye
if (rightEyeType == 1) {
push();
translate(right_eye_pos[0] + .25, right_eye_pos[1]); // translate to the center of the right eye
scale(-1, 1); // mirror the eye
stroke(0);
strokeWeight(eyeStrokeWeight);
// closed eye line
line(-.6, 0, .75, 0);
//lashes
if (gender < 2) {
line(-.6, 0, -.9, .25);
line(-.25, 0, -.5, .25);
}
pop();
}
// half open eye
else if (rightEyeType == 2) {
push();
translate(right_eye_pos[0] + .25, right_eye_pos[1]); // translate to the center of the right eye
scale(-1, 1); // mirror the eye
// draw the eye base
stroke(0);
strokeWeight(eyeStrokeWeight);
fill(255);
arc(0, 0, eyeWidth, eyeHeight, 0, 180, CHORD);
// coloured pupil
noStroke();
fill(eyeColor);
arc(0, 0, pupil * .75, pupil, 0, 180);
// iris
fill(0);
arc(0, 0, pupil * .75 - .2, pupil - .2, 0, 180);
// light detail
fill(255);
circle(-.25, .25, .2);
if (gender < 2) {
//lashes
eyeLashes(lashNum / 2, eyeWidth / 2 + lashGap, lashSize, -90, -180);
}
pop();
}
// wide open eye
else {
push();
translate(right_eye_pos[0] + .25, right_eye_pos[1]); // translate to the center of the right eye
scale(-1, 1); // mirror the eye
//right eye base
fill(255);
stroke(0);
strokeWeight(eyeStrokeWeight);
ellipse(0, 0, eyeWidth, eyeHeight);
// coloured pupil
noStroke();
fill(eyeColor);
ellipse(0, 0, pupil * .75, pupil);
// iris
fill(0);
ellipse(0, 0, pupil * .75 - .2, pupil - .2);
// light detail
fill(255);
circle(.25, .2, .3);
if (gender < 2) {
//lashes
eyeLashes(lashNum, eyeWidth / 2 + lashGap, lashSize, -90, 360);
}
pop();
}
pop();
}
/**********EAR FUNCTION*********/
function EAR(earType, gender) {
//ear variables
const earWidth = .75;
let nose_pos = segment_average(positions.nose_tip);
let earX = (faceWidth / 2) + (earWidth / 3);
let earY = nose_pos[1];
// draw ear bases
fill(skinColor);
circle(earX, earY, earWidth); // right ear
circle(-earX, earY, earWidth); // left ear
/*********RIGHT EAR CROSS*********/
push();
stroke(0);
strokeWeight(.07);
translate(earX, earY);
rotate(45);
line(0, -.2, 0, .2);
rotate(90);
line(0, -.2, 0, .2);
pop();
/*********LEFT EAR CROSS*********/
push();
stroke(0);
strokeWeight(.07);
translate(-earX, earY);
rotate(45);
line(0, -.2, 0, .2);
rotate(90);
line(0, -.2, 0, .2);
pop();
/*********EARRINGS*********/
if (gender < 2) { //if it is a woman
/*****EAR LOOPs*****/
if (earType < 2) {
// right earring
push();
translate(earX, earY);
noFill();
stroke('#F4D525');
strokeWeight(0.1);
ellipse(0, 1.35, .5, 2);
pop();
// left earring
push();
translate(-earX, earY);
noFill();
stroke('#F4D525');
strokeWeight(0.1);
ellipse(0, 1.35, .5, 2);
pop();
}
/*****PEARL EARRINGS*****/
else if (earType >= 2 && earType < 3) {
// right earring
push();
translate(earX, earY);
noStroke();
fill(255);
circle(0, .55, .5);
pop();
// left earring
push();
translate(-earX, earY);
noStroke();
fill(255);
circle(0, .55, .5);
pop();
}
/*****STAR EARRINGS*****/
else {
// function to draw a star reference : https://p5js.org/examples/form-star.html
function star(x, y) {
const angle = 360 / 5;
const halfAngle = angle / 2;
beginShape();
for (let a = 0; a < 360; a += angle) {
let sx = x + cos(a) * .4;
let sy = y + sin(a) * .4;
vertex(sx, sy);
sx = x + cos(a + halfAngle) * .18;
sy = y + sin(a + halfAngle) * .18;
vertex(sx, sy);
}
endShape(CLOSE);
}
// right earring
push();
translate(earX, earY);
fill('#F4D525');
star(0, .6);
pop();
// left earring
push();
translate(-earX, earY);
scale(-1, 1);
fill('#F4D525');
star(0, .6);
pop();
}
}
};
/**********FACE FEATURES FUNCTION*********/
function FEATURES(features, gender, skin) {
//Cheek colours
const cheekColor1 = '#ffb4a2';
const cheekColor2 = '#D36F83';
let cheekColor;
// map cheek colour to skin slider
if (skin < 2) {
cheekColor = cheekColor1
} else {
cheekColor = cheekColor2
}
// map the moustache to the top lip position
let moustache_pos = segment_average(positions.top_lip);
if (features < 2) {
// cheeks for female
if (gender < 2) {
noStroke();
fill(cheekColor);
circle(-1.4, 0, .75);
circle(1.4, 0, .75)
}
//moustache for male
else {
noStroke();
fill(hairColor);
push();
rotate(20);
ellipse(moustache_pos[0] + .7, moustache_pos[1] - .7, 1, .5);
pop();
push();
scale(-1, 1);
rotate(20);
ellipse(moustache_pos[0] + .7, moustache_pos[1] - .7, 1, .5);
pop();
}
}
}
noStroke();
push();
/************HAIR*****************/
//hair colours
const hairColor1 = '#D72483';
const hairColor2 = '#7400b8';
const hairColor3 = '#b7094c';
let hairColor;
if (this.hair < 2) {
hairColor = hairColor1
} else if (this.hair >= 2 && this.hair < 3) {
hairColor = hairColor2
} else {
hairColor = hairColor3
}
HAIR(this.hairType, this.gender, faceWidth); // draw the hair
/********HEAD*************/
//skin colours
const skinColor1 = '#FFDCC8';
const skinColor2 = '#f2bda5';
const skinColor3 = '#9a583c';
let skinColor;
if (this.skin < 2) {
skinColor = skinColor1
} else if (this.skin >= 2 && this.skin < 3) {
skinColor = skinColor2
} else {
skinColor = skinColor3
}
//draw Head
fill(skinColor);
ellipse(0, -.25, faceWidth, 4.5); // head
/*********EARS************/
EAR(this.earType, this.gender);
/************MOUTH***************/
MOUTH(this.gender); //draw the mouth
/******FACE FEATURES***********/
FEATURES(this.features, this.gender, this.skin);
/***********EYES************/
EYES(this.gender, this.eyes); //draw the eyes
/**************FRINGE***************/
FRINGE(this.fringeType, faceWidth, this.gender, this.hair);
pop();
};
/* set internal properties based on list numbers 0-100 */
this.setProperties = function (settings) {
this.gender = map(settings[0], 0, 100, 1, 2);
this.skin = map(settings[1], 0, 100, 1, 3);
this.hair = map(settings[2], 0, 100, 1, 3);
this.eyes = map(settings[3], 0, 100, 1, 2);
this.fringeType = int(map(settings[4], 0, 100, 1, 3));
this.earType = map(settings[5], 0, 100, 1, 3);
this.hairType = map(settings[6], 0, 100, 1, 2);
this.features = map(settings[7], 0, 100, 1, 2);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function () {
let settings = new Array(8);
settings[0] = map(this.gender, 1, 2, 0, 100);
settings[1] = map(this.skin, 1, 3, 0, 100);
settings[2] = map(this.hair, 1, 3, 0, 100);
settings[3] = map(this.eyes, 1, 2, 0, 100);
settings[4] = map(this.fringeType, 1, 3, 0, 100);
settings[5] = map(this.earType, 1, 3, 0, 100);
settings[6] = map(this.hairType, 1, 2, 0, 100);
settings[7] = map(this.features, 1, 2, 0, 100);
return settings;
}
}
{
"000001": [
0,
40,
100,
100,
0,
50,
75,
25
],
"000002": [
0,
0,
100,
100,
0,
100,
0,
0
],
"000005": [
0,
0,
0,
0,
100,
67,
0,
100
],
"000006": [
0,
100,
66.00000000000001,
100,
0,
0,
100,
0
],
"000007": [
100,
0,
55.49999999999999,
100,
100,
0,
100,
0
],
"000009": [
0,
0,
62.999999999999986,
100,
0,
100,
100,
0
],
"000010": [
0,
0,
0,
0,
0,
67,
100,
0
],
"000013": [
100,
0,
0,
0,
100,
66.66666666666666,
100,
100
],
"000014": [
0,
100,
66.00000000000001,
100,
100,
0,
100,
100
],
"000015": [
100,
0,
62.999999999999986,
100,
100,
0,
0,
100
],
"000016": [
100,
0,
57.00000000000001,
100,
100,
0,
100,
100
],
"000018": [
0,
0,
0,
0,
0,
55.00000000000001,
100,
100
],
"000020": [
100,
0,
58.999999999999986,
100,
100,
0,
100,
0
],
"000023": [
100,
0,
66.00000000000001,
100,
100,
0,
100,
100
],
"000025": [
100,
0,
62.999999999999986,
100,
100,
0,
100,
100
],
"000028": [
0,
50,
58.999999999999986,
100,
100,
100,
100,
100
],
"000029": [
0,
0,
0,
0,
0,
50,
100,
100
],
"000030": [
100,
50,
100,
100,
100,
0,
0,
100
],
"000031": [
0,
0,
62.999999999999986,
0,
100,
100,
0,
100
],
"000032": [
100,
0,
54,
100,
100,
0,
100,
100
],
"000035": [
0,
0,
56.999999999999986,
100,
0,
54,
100,
0
],
"000037": [
100,
100,
62.000000000000014,
100,
100,
0,
100,
100
],
"000038": [
100,
0,
60.00000000000001,
0,
100,
0,
100,
100
],
"000040": [
0,
0,
54,
100,
100,
66.66666666666666,
0,
0
],
"000041": [
100,
56.999999999999986,
58.999999999999986,
100,
100,
0,
100,
0
],
"000042": [
0,
0,
55.00000000000001,
0,
0,
100,
100,
0
],
"000043": [
0,
54,
95,
100,
0,
0,
100,
0
],
"000044": [
0,
100,
81,
100,
100,
67,
0,
0
],
"000045": [
0,
53,
100,
100,
0,
0,
100,
0
],
"000047": [
0,
56.00000000000001,
58.999999999999986,
100,
0,
0,
100,
0
],
"000048": [
100,
0,
58.5,
100,
0,
66.66666666666666,
100,
100
],
"000050": [
100,
0,
52.49999999999999,
100,
0,
66.66666666666666,
100,
100
],
"000051": [
100,
56.00000000000001,
100,
100,
100,
67,
100,
100
],
"000052": [
100,
62.000000000000014,
62.000000000000014,
100,
100,
67,
0,
100
],
"000054": [
0,
0,
0,
0,
0,
0,
100,
100
],
"000055": [
100,
0,
54,
100,
100,
0,
0,
100
],
"000056": [
0,
0,
58.5,
100,
0,
66.66666666666666,
100,
100
],
"000058": [
0,
0,
55.00000000000001,
0,
0,
100,
100,
100
],
"000060": [
100,
100,
64.99999999999999,
0,
100,
67,
100,
100
],
"000064": [
100,
0,
54,
0,
0,
67,
100,
0
],
"000065": [
100,
0,
83,
100,
100,
67,
100,
100
],
"000068": [
100,
51,
100,
100,
0,
67,
100,
100
],
"000069": [
100,
0,
64.5,
100,
0,
66.66666666666666,
100,
100
],
"000071": [
0,
0,
0,
0,
0,
66.66666666666666,
100,
100
],
"000073": [
0,
60.00000000000001,
83,
100,
0,
0,
100,
0
],
"000076": [
100,
58.00000000000001,
54,
100,
0,
0,
100,
0
],
"000077": [
0,
0,
60.00000000000001,
100,
0,
51,
100,
100
],
"000078": [
0,
0,
60.00000000000001,
100,
0,
0,
100,
100
],
"000079": [
100,
54,
60.00000000000001,
100,
100,
0,
100,
100
],
"000080": [
100,
0,
54,
100,
100,
0,
100,
100
],
"000081": [
100,
0,
55.00000000000001,
100,
100,
0,
100,
100
],
"000083": [
0,
0,
100,
0,
0,
52,
100,
100
],
"000085": [
0,
0,
100,
100,
0,
0,
100,
100
],
"000086": [
0,
0,
56.999999999999986,
100,
100,
56.00000000000001,
100,
100
],
"000088": [
0,
0,
100,
100,
100,
0,
100,
100
],
"000091": [
100,
0,
64.99999999999999,
0,
100,
0,
100,
100
],
"000092": [
0,
0,
0,
0,
0,
100,
0,
100
],
"000096": [
0,
0,
55.00000000000001,
100,
0,
0,
0,
0
],
"000097": [
0,
0,
56.999999999999986,
0,
0,
67,
100,
0
],
"000099": [
0,
0,
60.00000000000001,
0,
0,
66.66666666666666,
100,
0
],
"000100": [
0,
0,
66.00000000000001,
100,
100,
67,
0,
100
],
"000103": [
0,
10.999999999999998,
51,
50,
0,
33.00000000000001,
100,
100
],
"000104": [
100,
0,
0,
0,
100,
100,
0,
0
],
"000106": [
0,
0,
64.99999999999999,
100,
0,
100,
0,
100
],
"000108": [
0,
54,
0,
0,
0,
0,
0,
100
],
"000109": [
100,
53,
58.999999999999986,
100,
100,
0,
0,
100
],
"000110": [
0,
0,
62.000000000000014,
50,
50,
55.00000000000001,
0,
0
],
"000111": [
0,
100,
0,
100,
0,
0,
100,
0
],
"000114": [
100,
0,
60.00000000000001,
100,
50,
0,
0,
100
],
"000115": [
100,
0,
89.99999999999999,
0,
100,
0,
100,
100
],
"000116": [
100,
0,
52,
0,
50,
0,
100,
100
],
"000117": [
0,
100,
56.999999999999986,
100,
50,
100,
100,
0
],
"000118": [
0,
51,
61.5,
100,
0,
100,
100,
0
],
"000121": [
0,
0,
55.00000000000001,
100,
50,
1.0000000000000009,
100,
0
],
"000122": [
0,
0,
0,
100,
50,
50,
100,
100
],
"000125": [
100,
0,
0,
0,
100,
0,
100,
100
],
"000126": [
0,
52,
0,
0,
0,
0,
100,
100
],
"000129": [
100,
0,
58.999999999999986,
0,
100,
0,
0,
0
],
"000131": [
0,
100,
62.000000000000014,
100,
0,
100,
100,
100
],
"000132": [
0,
53,
60.00000000000001,
100,
0,
0,
100,
100
],
"000133": [
0,
53,
0,
0,
0,
68.00000000000001,
0,
100
],
"000134": [
100,
100,
51,
100,
100,
0,
100,
100
],
"000135": [
100,
53,
64.99999999999999,
100,
100,
0,
100,
100
],
"000137": [
100,
0,
51,
100,
100,
0,
100,
0
],
"000140": [
0,
58.999999999999986,
0,
50,
0,
0,
100,
0
],
"000142": [
0,
0,
60.00000000000001,
0,
0,
62.999999999999986,
100,
100
],
"000143": [
100,
0,
60.00000000000001,
0,
100,
0,
100,
0
],
"000145": [
0,
56.999999999999986,
51,
100,
0,
100,
100,
0
],
"000146": [
0,
58.999999999999986,
150,
100,
50,
0,
100,
0
],
"000147": [
0,
46,
15.000000000000002,
0,
0,
64.00000000000001,
100,
0
],
"000148": [
0,
46,
66.00000000000001,
100,
0,
33.00000000000001,
100,
100
],
"000150": [
100,
46,
100,
100,
100,
0,
0,
100
],
"000151": [
0,
46,
55.00000000000001,
100,
0,
100,
100,
100
],
"000152": [
100,
60.00000000000001,
83,
100,
100,
0,
100,
100
],
"000153": [
100,
46,
52,
100,
100,
0,
100,
100
],
"000155": [
0,
46,
150,
100,
0,
0,
100,
100
],
"000156": [
0,
46,
0,
0,
0,
69,
100,
100
],
"000157": [
0,
46,
0,
0,
0,
0,
100,
100
],
"000160": [
100,
0,
62.000000000000014,
100,
100,
0,
0,
0
],
"000161": [
0,
0,
51,
0,
0,
0,
100,
0
]
}
let noise_01 = 1;
let noise_02 = 1;
let noise_03 = 1;
let opacity = 1;
let smoothVal = 100;
const ease_ge = new p5.Ease();
function ge_draw_one_frame(cur_frac) {
// draw the background every time
drawBG();
// initialize the values
let blue = color(99, 176, 242);
let purple = color('#D02E9D');
let frame = floor(map(cur_frac, 0, 1, 0, 24)); // get an integer from 0 to 23 as integers (current frame)
// set an array of 24 values going up and down
let arr1 = linspace(0, 1, 12);
let arr2 = (linspace(1, 0, 12));
let arr = concat(arr1, arr2);
// if not the debug view, draw the wallpaper
if(!debugView) {
strokeWeight(width*0.001);
// initialize the values, and make sure they all fit in different size of canvas
let die_size = width * 0.06; gap_y = height/4-die_size*2, gap_x = die_size*0.2;
let set_width = die_size * 2 * 6 + gap_x * 6;
let row = 0;
// draw dice to fill the screen
for (var y = die_size+gap_y*2; y <= height-die_size; y += die_size*2+gap_y) { // y position of the dice
for (var i = 0; i < width/set_width; i++) { // how many sets will be drawn
let gap = set_width / 6 + gap_x, x = die_size + i * (set_width+die_size+gap_x); // set the gap between die and x position
if (row % 2 == 0) { x = die_size*2 + i * (set_width+die_size+gap_x);} // every line with even numbers will have an x offset
drawD4(x+gap_x, y+getEaseValue(arr, 0+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
drawD6(x+gap, y+getEaseValue(arr, 1+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
drawD8(x+gap*2, y+getEaseValue(arr, 2+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
drawD10(x+gap*3, y+getEaseValue(arr, 3+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
drawD12(x+gap*4, y+getEaseValue(arr, 4+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
drawD20(x+gap*5, y+getEaseValue(arr, 5+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
}
row++;
}
}
// if debug view, draw only two set
if (debugView) {
strokeWeight(height*0.01);
// here we draw three set of dice
let die_size = width*0.07, gap_y = height*0.015, gap_x = width*0.005;
let set_width = die_size * 2 * 6 + gap_x * 6;
let row = 0;
for (var y = die_size*1.5; y <= height-die_size; y += die_size*2+gap_y) {
for (var i = 0; i < width/set_width; i++) {
let gap = set_width / 6 + gap_x, x = die_size + i * (set_width+die_size+gap_x);
if (row % 2 == 0) { x = die_size*2 + i * (set_width+die_size+gap_x);}
drawD4(x+gap_x, y+getEaseValue(arr, 0+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
drawD6(x+gap, y+getEaseValue(arr, 1+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
drawD8(x+gap*2, y+getEaseValue(arr, 2+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
drawD10(x+gap*3, y+getEaseValue(arr, 3+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
drawD12(x+gap*4, y+getEaseValue(arr, 4+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
drawD20(x+gap*5, y+getEaseValue(arr, 5+i*6, frame, die_size), die_size, cur_frac, blue, purple, i*row, true);
}
row++;
}
}
}
/* draw a die with 4 faces */
function drawD4(x, y, size, step, c1, c2, str, isGrad) {
if(!checkWidBounds(x, size) || !checkHeightBounds(y, size)) return;
arr = setNoise(x, y, c1, c2, step, "d4_0", str, isGrad);
c1 = arr[0]; c2 = arr[1];
let br = p5.Vector.fromAngle(radians(30), size*noise_01); // bottom right
let bl = p5.Vector.fromAngle(radians(150), size*noise_02); // bottom left
let t = p5.Vector.fromAngle(radians(270), size*noise_03); // top
let cols = [color('#9C4F96'), color('#FF6355'), color('#FBA949'), color('#FAE442'), color('#8BD448'), color('#2AA8F2')];
push();
translate(x, y);
gradientLine(0, 0, br.x, br.y, c1, c2, step);
gradientLine(0, 0, bl.x, bl.y, c1, c2, step);
gradientLine(0, 0, t.x, t.y, c1, c2, step);
gradientLine(bl.x, bl.y, br.x, br.y, c1, c2, step);
gradientLine(t.x, t.y, bl.x, bl.y, c1, c2, step);
gradientLine(br.x, br.y, t.x, t.y, c1, c2, step);
pop();
}
/* draw a die with 6 faces */
function drawD6(x, y, size, step, c1, c2, str, isGrad) {
if(!checkWidBounds(x, size) || !checkHeightBounds(y, size)) return;
setNoise(x, y, c1, c2, step, "d6_0", str, isGrad);
let len = size * 0.92;
let b = p5.Vector.fromAngle(radians(90), len*noise_01); // bottom
let tl = p5.Vector.fromAngle(radians(210), len*noise_02); // top left
let tr = p5.Vector.fromAngle(radians(-30), len*noise_03); // top right
let t = p5.Vector.fromAngle(radians(-90), len*noise_02); // top
let br = p5.Vector.fromAngle(radians(30), len*noise_01); // bottom right
let bl = p5.Vector.fromAngle(radians(150), len*noise_03); // bottom left
push();
translate(x, y);
// top face
gradientLine(0, 0, tl.x, tl.y, c1, c2, step);
gradientLine(0, 0, tr.x, tr.y, c1, c2, step);
gradientLine(tl.x, tl.y, t.x, t.y, c1, c2, step);
gradientLine(t.x, t.y, tr.x, tr.y, c1, c2, step);
// right face
gradientLine(0, 0, b.x, b.y, c1, c2, step);
gradientLine(br.x, br.y, b.x, b.y, c1, c2, step);
gradientLine(br.x, br.y, tr.x, tr.y, c1, c2, step);
// left face
gradientLine(tl.x, tl.y, bl.x, bl.y, c1, c2, step);
gradientLine(b.x, b.y, bl.x, bl.y, c1, c2, step);
pop();
}
/* draw a die with 8 faces */
function drawD8(x, y, size, step, c1, c2, str, isGrad) {
if(!checkWidBounds(x, size) || !checkHeightBounds(y, size)) return;
setNoise(x, y, c1, c2, step, "d8_0", str, isGrad);
let wid = size / tan(radians(60));
let len = wid / cos(radians(30));
let r = p5.Vector.fromAngle(radians(0), wid*noise_01); // right
let tr = p5.Vector.fromAngle(radians(-30), len*noise_02); // top right
let t = p5.Vector.fromAngle(radians(-90), size*noise_03); // top
let tl = p5.Vector.fromAngle(radians(-150), len*noise_03); // top left
let l = p5.Vector.fromAngle(radians(180), wid*noise_02); // left
let b = p5.Vector.fromAngle(radians(90), size*0.6*noise_01); // bottom
push();
translate(x, y);
// front face
gradientLine(t.x, t.y, r.x, r.y, c1, c2, step);
gradientLine(t.x, t.y, l.x, l.y, c1, c2, step);
gradientLine(l.x, l.y, r.x, r.y, c1, c2, step);
// left face
gradientLine(l.x, l.y, tl.x, tl.y, c1, c2, step);
gradientLine(tl.x, tl.y, t.x, t.y, c1, c2, step);
// right face
gradientLine(tr.x, tr.y, r.x, r.y, c1, c2, step);
gradientLine(tr.x, tr.y, t.x, t.y, c1, c2, step);
// bottom face
gradientLine(b.x, b.y, r.x, r.y, c1, c2, step);
gradientLine(b.x, b.y, l.x, l.y, c1, c2, step);
pop();
}
/* draw a die with 10 faces */
function drawD10(x, y, size, step, c1, c2, str, isGrad) {
if(!checkWidBounds(x, size) || !checkHeightBounds(y, size)) return;
setNoise(x, y, c1, c2, step, "d10_0", str, isGrad);
let len = size * 0.92;
let w = (len/2) / cos(radians(20));
let mr = p5.Vector.fromAngle(radians(-20), w*noise_01); // middle right
let r = p5.Vector.fromAngle(radians(0), len*noise_02); // right
let t = p5.Vector.fromAngle(radians(-90), len*noise_03); // top
let ml = p5.Vector.fromAngle(radians(-160), w*noise_03); // middle left
let l = p5.Vector.fromAngle(radians(180), len*noise_02); // left
let b = p5.Vector.fromAngle(radians(90), len*noise_01); // bottom
push();
translate(x, y);
// front face
gradientLine(t.x, t.y, ml.x, ml.y, c1, c2, step);
gradientLine(ml.x, ml.y, 0, 0, c1, c2, step);
gradientLine(mr.x, mr.y, 0, 0, c1, c2, step);
gradientLine(mr.x, mr.y, t.x, t.y, c1, c2, step);
// left face
gradientLine(ml.x, ml.y, l.x, l.y, c1, c2, step);
gradientLine(l.x, l.y, t.x, t.y, c1, c2, step);
// right face
gradientLine(mr.x, mr.y, r.x, r.y, c1, c2, step);
gradientLine(r.x, r.y, t.x, t.y, c1, c2, step);
// bottom faces
gradientLine(b.x, b.y, l.x, l.y, c1, c2, step);
gradientLine(b.x, b.y, r.x, r.y, c1, c2, step);
gradientLine(b.x, b.y, 0, 0, c1, c2, step);
pop();
}
/* draw a die with 12 faces */
function drawD12(x, y, size, step, c1, c2, str, isGrad) {
if(!checkWidBounds(x, size) || !checkHeightBounds(y, size)) return;
setNoise(x, y, c1, c2, step, "d12_0", str, isGrad);
let middle_w = (size) / cos(radians(15));
let inner_w = (size/2) / cos(radians(30));
let ir = p5.Vector.fromAngle(radians(30), inner_w * noise_01); // inner right
let r = p5.Vector.fromAngle(radians(-5), size * noise_03); // right
let mr = p5.Vector.fromAngle(radians(15),middle_w * noise_02); // middle right
let tr = p5.Vector.fromAngle(radians(-70), size * noise_01); // top right
let ur = p5.Vector.fromAngle(radians(-45), size * noise_03); // upper right
let br = p5.Vector.fromAngle(radians(75), size * noise_02); // bottom right
let lr = p5.Vector.fromAngle(radians(45), size * noise_01); // lower right
let mlr = p5.Vector.fromAngle(radians(15), size * noise_03); // middle lower left
let mt = p5.Vector.fromAngle(radians(-90),inner_w * noise_02); // middle top
let il = p5.Vector.fromAngle(radians(150), inner_w * noise_01); // inner left
let l = p5.Vector.fromAngle(radians(185), size * noise_03); // left
let ml = p5.Vector.fromAngle(radians(175),middle_w * noise_02); // middle left
let tl = p5.Vector.fromAngle(radians(-110), size * noise_01); // top left
let ul = p5.Vector.fromAngle(radians(-135), size * noise_03); // upper left
let bl = p5.Vector.fromAngle(radians(105), size * noise_02); // bottom left
let ll = p5.Vector.fromAngle(radians(135), size * noise_01); // lower left
let mll = p5.Vector.fromAngle(radians(165), size * noise_03); // middle lower left
push();
translate(x, y);
// front face
gradientLine(0, 0, il.x, il.y, c1, c2, step);
gradientLine(il.x, il.y, bl.x, bl.y, c1, c2, step);
gradientLine(bl.x, bl.y, br.x, br.y, c1, c2, step);
gradientLine(br.x, br.y, ir.x, ir.y, c1, c2, step);
gradientLine(0, 0, ir.x, ir.y, c1, c2, step);
// left face
gradientLine(0, 0, mt.x, mt.y, c1, c2, step);
gradientLine(mt.x, mt.y, ul.x, ul.y, c1, c2, step);
gradientLine(l.x, l.y, ul.x, ul.y, c1, c2, step);
gradientLine(l.x, l.y, il.x, il.y, c1, c2, step);
// right face
gradientLine(0, 0, ir.x, ir.y, c1, c2, step);
gradientLine(ir.x, ir.y, r.x, r.y, c1, c2, step);
gradientLine(r.x, r.y, ur.x, ur.y, c1, c2, step);
gradientLine(mt.x, mt.y, ur.x, ur.y, c1, c2, step);
// bottom faces
gradientLine(bl.x, bl.y, ll.x, ll.y, c1, c2, step);
gradientLine(ll.x, ll.y, mll.x, mll.y, c1, c2, step);
gradientLine(l.x, l.y, mll.x, mll.y, c1, c2, step);
gradientLine(br.x, br.y, lr.x, lr.y, c1, c2, step);
gradientLine(lr.x, lr.y, mlr.x, mlr.y, c1, c2, step);
gradientLine(r.x, r.y, mlr.x, mlr.y, c1, c2, step);
// top face
gradientLine(tr.x, tr.y, ur.x, ur.y, c1, c2, step);
gradientLine(tl.x, tl.y, ul.x, ul.y, c1, c2, step);
gradientLine(tl.x, tl.y, tr.x, tr.y, c1, c2, step);
pop();
}
/* draw a die with 20 faces */
function drawD20(x, y, size, step, c1, c2, str, isGrad) {
if(!checkWidBounds(x, size) || !checkHeightBounds(y, size)) return;
setNoise(x, y, c1, c2, step, "d20_0", str, isGrad);
let len = size * cos(radians(30)) * 1.1;
let wid = size/2 * 1.1;
let t = p5.Vector.fromAngle(radians(-90), len * noise_02); // top
let tr = p5.Vector.fromAngle(radians(-30), len * noise_02); // top right
let mr = p5.Vector.fromAngle(radians(-35), wid * noise_01); // middle right
let lr = p5.Vector.fromAngle(radians(25), len * noise_03); // lower right
let tl = p5.Vector.fromAngle(radians(-150), len * noise_01); // top left
let ml = p5.Vector.fromAngle(radians(-145), wid * noise_03); // middle left
let ll = p5.Vector.fromAngle(radians(155), len * noise_01); // lower left
let lm = p5.Vector.fromAngle(radians(90), wid * noise_02); // lower middle
let b = p5.Vector.fromAngle(radians(90), len * noise_03); // bottom
push();
translate(x, y);
// middle face
gradientLine(mr.x, mr.y, ml.x, ml.y, c1, c2, step);
gradientLine(mr.x, mr.y, lm.x, lm.y, c1, c2, step);
gradientLine(lm.x, lm.y, ml.x, ml.y, c1, c2, step);
// left faces
gradientLine(lm.x, lm.y, ll.x, ll.y, c1, c2, step);
gradientLine(ll.x, ll.y, ml.x, ml.y, c1, c2, step);
gradientLine(tl.x, tl.y, ll.x, ll.y, c1, c2, step);
gradientLine(tl.x, tl.y, ml.x, ml.y, c1, c2, step);
// right faces
gradientLine(lm.x, lm.y, lr.x, lr.y, c1, c2, step);
gradientLine(lr.x, lr.y, mr.x, mr.y, c1, c2, step);
gradientLine(tr.x, tr.y, lr.x, lr.y, c1, c2, step);
gradientLine(tr.x, tr.y, mr.x, mr.y, c1, c2, step);
// top faces
gradientLine(tr.x, tr.y, t.x, t.y, c1, c2, step);
gradientLine(mr.x, mr.y, t.x, t.y, c1, c2, step);
gradientLine(tl.x, tl.y, t.x, t.y, c1, c2, step);
gradientLine(ml.x, ml.y, t.x, t.y, c1, c2, step);
// bottom faces
gradientLine(lm.x, lm.y, b.x, b.y, c1, c2, step);
gradientLine(ll.x, ll.y, b.x, b.y, c1, c2, step);
gradientLine(lr.x, lr.y, b.x, b.y, c1, c2, step);
pop();
}
/* draw a gradient line with colors flows */
function gradientLine(x0, y0, x1, y1, c1, c2, s) {
let d = dist(x0, y0, x1, y1); // the length of the line
let prevX = x0, prevY = y0;
for (var i = 1; i < d; i++) {
let step = map(i, 0, d, 0, 1);
let c, col_step;
// getting the x1, y1 for the line fragment
let x = lerp(x0, x1, step);
let y = lerp(y0, y1, step);
// getting the color from the current frame and the lerp color
if (step <= s) {
col_step = map(step, 0, s, 0, 1);
c = lerpColor(c1, c2, col_step);
} else {
col_step = map(step, s, 1, 0, 1);
c = lerpColor(c1, c2, col_step);
}
stroke(c);
line(prevX, prevY, x, y);
prevX = x;
prevY = y;
}
}
/* check the width boundaries for die's x position */
function checkWidBounds(x, size) {
if (x > width-size) { return false; }
else { return true; }
}
/* check the height boundaries for die's y position */
function checkHeightBounds(y, size) {
if (y > height) { return false; }
else { return true; }
}
/* get average noise value for the global opacity */
function getOpacity(x, y, step){
let opacity2 = getNoiseValue(x, y, step, "opacity", 50, 255, smoothVal);
let opacity1 = getNoiseValue(x, y, 0, "opacity", 50, 255, smoothVal);
return map(0.5, 0, 1, opacity2, opacity1);
}
/* get average noise value for dice's line's length size */
function getNoise(x, y, step, str){
let noise2 = getNoiseValue(x, y, step, str, 0.9, 1.1, 300);
let noise1 = getNoiseValue(x, y, 0, str, 0.9, 1.1, 300);
return map(0.5, 0, 1, noise2, noise1);
}
/* set the noice and color value from the given conditions */
function setNoise(x, y, c1, c2, step, prefix, str, isGrad) {
let arr = []; // array to store output colors
if (isGrad) {
opacity = getOpacity(x, y, step);
c1.setAlpha(opacity); c2.setAlpha(opacity);
noise_01 = getNoise(x, y, step, prefix+"1"+str);
noise_02 = getNoise(x, y, step, prefix+"2"+str);
noise_03 = getNoise(x, y, step, prefix+"3"+str);
} else {
noise_01 = 1; noise_02 = 1; noise_03 = 1; // is not gradient, don't change sizes
}
arr.push(c1);
arr.push(c2);
return arr;
}
/** return an array with size of the given number,
* with maximum(not included) and minimin provided, and evenly spaced
* @param x --- minimum
* @param y --- maximum
* @num --- the size of the array
*/
function linspace(x, y, num) {
let result = [];
let step = (y-x)/num;
for (let i = 0; i < num; i++) {
result[i] = x + i * step;
}
return result;
}
/** get a value out of array,
* if the index is exceeding the array size,
* loop it from the start
*/
function arrayAt(arr, index) {
let len = arr.length;
return arr[index % len];
}
/** get a easing value from the given number, and map it from 0 to maximum
* @param arr --- the array that contains all the step values
* @param index --- the starting position in the array
* @param frame --- the current position in the array
* @param max --- the maximum number of the output value
*/
function getEaseValue(arr, index, frame, max) {
return map(ease_ge.quadraticInOut(arrayAt(arr, index+frame)), 0, 1, 0, max);
}
/* draw a background with a subtle brown color at the middle */
function drawBG() {
let dark = color(97, 66, 47);
let light = color(158, 108, 77);
let gap = width * 0.03;
fill(10);
rect(0, 0, width, height);
noStroke();
for (let i = 1; i <= 15; i++) {
let step = map(i, 1, 15, 0, 1);
let col = lerpColor(dark, light, step);
col.setAlpha(7);
fill(col);
ellipse(width/2, height/2, width-i*gap, height-i*gap);
}
}
/*
* FaceMap class - holds all information about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
var DEBUG_MODE = false;
// this can be used to set the number of sliders to show
var NUM_SLIDERS = 8;
// other variables can be in here too
const noiseVal = 0.03; // constant for the hand-drawn looking algorithm
// skin colors
const skin_col_1 = [240, 215, 214];
const skin_col_2 = [245, 201, 168];
const skin_col_3 = [227, 170, 135];
const skin_col_4 = [208, 169, 120];
const skin_col_5 = [194, 137, 99];
const skin_col_6 = [131, 85, 48];
const skin_cols = [skin_col_1, skin_col_2, skin_col_3, skin_col_4, skin_col_5, skin_col_6];
// hair colors
const hair_col_1 = [242,217,111];
const hair_col_2 = [130,78,43];
const hair_col_3 = [168,60,21];
const hair_col_4 = [94,48,48];
const hair_col_5 = [34,33,40];
const hair_cols = [hair_col_1, hair_col_2, hair_col_3, hair_col_4, hair_col_5];
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i=0; i<s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len , sum_y / s_len ];
}
// This where you define your own face object
function GeFace() {
// these are state variables for a face
this.skin_value = 1; // 0 - 5
this.facing = 0; // 0: facing right/front, 1: facing left
this.eye_shift = -1; // range is -10 to 10
this.mouth_value = 1; // range is 0.5 to 8
this.eye_lash = 0; // 0: no eye lashes, 1: has eye lashes
this.eye_height = 1.3; // how big the eyes are opened
this.eye_gap = 0.3; // range is 0 - 0.5
this.hair_value = 0; // 0 - 4
this.hair_length = 0; // 0: short hair, 1: long hair
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
// head
fill(skin_cols[this.skin_value]);
stroke(25);
strokeWeight(0.1);
this.drawFace(positions.chin);
// mouth
noFill();
stroke(25);
strokeWeight(0.03);
this.drawMouth(positions);
// nose
this.drawShape(positions.nose_tip);
// eyes
this.drawEyes(positions);
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.skin_value = int(map(settings[0], 0, 100, 0, 5.99));
this.eye_shift = map(settings[1], 0, 100, -0.6, 0.6);
this.hair_value = int(map(settings[2], 0, 100, 0, 4.99));
this.facing = int(map(settings[3], 0, 100, 0, 2));
this.eye_height = map(settings[4], 0, 100, 0.2, 1.3);
this.eye_lash = int(map(settings[5], 0, 100, 0, 2));
this.eye_gap = map(settings[6], 0, 100, 0, 0.5);
this.hair_length = int(map(settings[7], 0, 100, 0, 2));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(8);
settings[0] = map(this.skin_value, 0, 5.99, 0, 100);
settings[1] = map(this.eye_shift, -0.6, 0.6, 0, 100);
settings[2] = map(this.hair_value, 0, 4.99, 0, 100);
settings[3] = map(this.facing, 0, 2, 0, 100);
settings[4] = map(this.eye_height, 0.2, 1.3, 0, 100);
settings[5] = map(this.eye_lash, 0, 2, 0, 100);
settings[6] = map(this.eye_gap, 0, 0.5, 0, 100);
settings[7] = map(this.hair_length, 0, 2, 0, 100);
return settings;
}
/* draw the face with the provided face value and slider values */
this.drawFace = function(segment) {
let facePos = this.analyzeFace(segment);
let front = facePos[0];
let back = facePos[1];
let chin = facePos[2];
let pos = [];
facePos[0] = front[0] * 0.2 + back[0] * 0.8;
facePos[1] = (front[1] + back[1])/2;
let faceWidth = abs(front[0]-back[0])/12.0
push();
if(this.facing >= 1) { // facing left
scale(-faceWidth, abs(front[1]-chin[1])/8.0);
} else {
scale(faceWidth, abs(front[1]-chin[1])/8.0);
}
translate(facePos[0], facePos[1]);
this.drawBackHair();
fill(skin_cols[this.skin_value]);
let face = this.computeBezier(-6.2, -7, -3, -8, -1, -8, 2, -7);
face.push(...this.computeBezier(2, -7, 5, -6, 3, -4, 4, -2));
face.push(...this.computeBezier(4, -2, 6, 1, 6, 4, 4, 5.5));
face.push(...this.computeBezier(4, 5.5, 2, 7, -1, 8, -6, 5));
face.push(...this.computeBezier(-6, 5, -8, 4, -8, 3, -8, 1));
face.push(...this.computeBezier(-8, 1.5, -10, 2, -11, -2, -8, 0));
face.push(...this.computeBezier(-8, -1, -8, -3, -8, -5, -6, -7));
this.drawShape(face);
this.drawFrontHair();
pop();
}
/* draw the eyes, which can open and close */
this.drawEyes = function(positions) {
let eyeLPos = segment_average(positions.left_eye);
let eyeRPos = segment_average(positions.right_eye);
let yPos = positions.nose_bridge[1];
let eyeWidth = 1.3;
let eyeMPos = [];
eyeMPos[0] = (eyeLPos[0] + eyeRPos[0])/2;
let curEyeShift = this.eye_shift;
lerpVal = this.eye_gap;
eyeLPos[0] = lerp(eyeLPos[0], eyeMPos[0], lerpVal);
eyeRPos[0] = lerp(eyeRPos[0], eyeMPos[0], lerpVal);
eyeLPos[1] = yPos[1];
eyeRPos[1] = yPos[1];
// left eye
stroke(25);
fill(220);
this.drawOval(eyeLPos[0], eyeLPos[1], eyeWidth, this.eye_height);
fill(25);
noStroke();
this.drawOval(eyeLPos[0]+this.eye_shift, eyeLPos[1], 0.15, 0.15);
// right eye
stroke(25);
fill(220);
this.drawOval(eyeRPos[0], eyeRPos[1], eyeWidth, this.eye_height);
fill(25);
noStroke();
this.drawOval(eyeRPos[0]+this.eye_shift, eyeRPos[1], 0.15, 0.15);
// eyebrows, it follows the eyes without intersecting with one another
stroke(25);
noFill();
this.drawShape(this.computeBezier(eyeLPos[0]-eyeWidth*0.4, eyeLPos[1]-this.eye_height*0.6,
eyeLPos[0]-eyeWidth*0.2, eyeLPos[1]-this.eye_height*0.85,
eyeLPos[0]+eyeWidth*(0.5-lerpVal), eyeLPos[1]-this.eye_height*0.85,
eyeLPos[0]+eyeWidth*(0.6-lerpVal), eyeLPos[1]-this.eye_height*0.6));
this.drawShape(this.computeBezier(eyeRPos[0]-eyeWidth*0.4, eyeRPos[1]-this.eye_height*0.6,
eyeRPos[0]-eyeWidth*0.2, eyeRPos[1]-this.eye_height*0.85,
eyeRPos[0]+eyeWidth*(0.5-lerpVal), eyeRPos[1]-this.eye_height*0.85,
eyeRPos[0]+eyeWidth*(0.6-lerpVal), eyeRPos[1]-this.eye_height*0.6));
// eyelash
if (this.eye_lash >= 1) {
this.drawLine(eyeLPos[0]-eyeWidth*0.4, eyeLPos[1]-this.eye_height*0.3, eyeLPos[0]-eyeWidth*0.6, eyeLPos[1]-this.eye_height*0.4);
this.drawLine(eyeRPos[0]+eyeWidth*0.4, eyeRPos[1]-this.eye_height*0.3, eyeRPos[0]+eyeWidth*0.6, eyeRPos[1]-this.eye_height*0.4);
}
}
/* draw the mouth, either closed or open */
this.drawMouth = function(positions) {
let mouth = subset(positions.top_lip, 6); // get the lower half of the top lip
let length = mouth.length; // get the initial top lip length
mouth.push(...reverse(subset(positions.bottom_lip, 0, 7))); // get the lower half of the bottom lip
let pos = segment_average(positions.top_lip); // find the position of the mouth
push();
scale(1, 1.3); // scale up the y axis to exaggerate the expression
if (this.facing >= 1){
translate(-0.2, -0.1);
} else {
translate(0.2, -0.1);
}
let mouthHeight = this.findHeight(mouth);
// if the mouth is opened, draw a mouth, teeth and tongue
if (mouthHeight > 0.4) {
fill(103,38,54);
this.drawShape(mouth);
fill(255);
// teeth
let top = this.combineCurve(subset(mouth, 0, length+1)); // get a more detailed array with points
top = subset(top, top.length*0.2, top.length-(top.length*0.3));
// draw the lower points of the teeth, use the mouth height as the guidance
loop = top[0];
let tmp = [];
tmp[0] = top[top.length-3][0];
tmp[1] = top[top.length-3][1]+ mouthHeight*0.2;
append(top, tmp)
tmp = [];
tmp[0] = top[2][0];
tmp[1] = top[2][1]+ mouthHeight*0.2;
append(top, tmp)
append(top, loop);
this.drawShape(top);
// tongue
let bottom = this.combineCurve(subset(mouth, length));
tongue = subset(bottom, bottom.length*0.3, bottom.length-(bottom.length*0.5));
let x = lerp(tongue[0][0], tongue[tongue.length-1][0], 0.45);
let y = lerp(tongue[0][1], tongue[tongue.length-1][1], 0.45);
stroke(255, 0, 0);
fill(180,85,118);
noStroke();
this.drawShape(tongue);
this.drawOval(x, y, dist(tongue[0][0], tongue[tongue.length-1][0], tongue[0][1], tongue[tongue.length-1][1])*0.45, mouthHeight*0.3);
// redraw the outline
stroke(25);
noFill();
this.drawShape(mouth);
} else {
// if the mouth is not opened
noFill();
this.drawShape(subset(positions.bottom_lip, 6));
}
noFill();
pop();
}
/**
* helper method to draw the front hair
*/
this.drawFrontHair = function() {
fill(hair_cols[this.hair_value]);
let hair = this.computeBezier(4, -3, 1, -4, -1, -5, -1, -7.5);
hair.push(...this.computeBezier(-1, -7.5, -2, -2, -4, -4, -8, -1));
hair.push(...this.computeBezier(-8, -1, -8, -3, -8, -5, -6, -7));
hair.push(...this.computeBezier(-6.2, -7, -3, -8, -1, -8, 2, -7));
hair.push(...this.computeBezier(2, -7, 5, -6, 3, -4, 4, -3));
this.drawShape(hair);
}
/**
* helper method to draw the back hair
*/
this.drawBackHair = function(){
fill(hair_cols[this.hair_value]);
if (this.hair_length >= 1) { // long hair
let hair = this.computeBezier(-6, -7, -9, -5, -10, -2, -9, 2);
hair.push(...this.computeBezier(-9, 2, -8, 4, -12, 6, -10, 7));
hair.push(...this.computeBezier(-10, 7, -7, 9, -5, 7, -2, 8.5));
hair.push(...this.computeBezier(-1.7, 8.5, 0, 9, 4, 10, 7, 6));
hair.push(...this.computeBezier(7, 6, 5, 5, 5, 3, 5, 1));
hair.push(...this.computeBezier(5, 1, 8, -2, 4, -5, 3, -6.5));
this.drawShape(hair);
} else { // short hair
let hair = this.computeBezier(-6, -7, -9, -5, -10, -2, -9, 2);
hair.push(...this.computeBezier(-9, 2, -8, 4, -8, 4, -9, 5));
hair.push(...this.computeBezier(-9, 5, -8.5, 5, -8, 6, -5, 5));
hair.push(...this.computeBezier(-5, 5, -2, 6, -2, 5, 6, 6));
hair.push(...this.computeBezier(6, 6, 5, 3, 7, 0, 3, -6.6));
this.drawShape(hair);
}
}
/**
* helper method to draw an array of points with curveVertex and noise
*/
this.drawShape = function(segment) {
beginShape();
curveVertex(segment[0][0], segment[0][1]);
for(let i=0; i<segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
curveVertex(px, py);
}
curveVertex(segment[segment.length-1][0], segment[segment.length-1][1]);
endShape();
}
/**
* helper method to draw a line with noise
*/
this.drawLine = function(x1, y1, x2, y2){
var dis = dist(x1, y1, x2, y2);
beginShape();
curveVertex(x1, y1);
for (var i = 0; i < dis; i+=0.1) {
var p = i / dis;
var x = lerp(x1, x2, p);
var y = lerp(y1, y2, p);
var offset = getNoiseValue(x, y, 1, "face", -noiseVal, noiseVal, 10);
curveVertex(x+offset, y+offset);
}
curveVertex(x2, y2);
endShape();
}
/**
* helper method to draw an arc with start to end in degree
* x, y - the middle of the arc
*/
this.drawOval = function(x, y, width, height){
var a = width/2, b = height/2;
var dis = 2 * PI * b + 4 * (a - b);
beginShape();
curveVertex(x+a, y);
for (var i = 0; i <= dis; i+=0.1) {
var t = map(i, 0, dis, 0, 360);
var offset = getNoiseValue(0, 0, map(i, 0, dis, 0, 1), "face", -noiseVal, noiseVal, 10);
var newX = (a + offset) * cos(t) + x;
var newY = (b + offset) * sin(t) + y;
curveVertex(newX, newY);
}
curveVertex(x+a, y);
endShape(CLOSE);
}
/**
* helper method to draw a bezier curve with noise
*/
this.computeBezier = function(x1, y1, x2, y2, x3, y3, x4, y4) {
let vertices = [];
let j = 2;
vertices[0] = []; vertices[1] = [];
vertices[0][0] = x1; vertices[0][1] = y1;
vertices[1][0] = x1; vertices[1][1] = y1;
// estimate how long the curve is from point to point dist
let estimateDist = dist(x1, y1, x2, y2) + dist(x2, y2, x3, y3) + dist(x3, y3, x4, y4);
// loop through the bezier and add them into the array with noise offset
for (let i = 0; i <= estimateDist; i += 0.3) {
let t = i / estimateDist; // t is [0,1], the ratio in the curve that we can get the vector point
let x = bezierPoint(x1, x2, x3, x4, t);
let y = bezierPoint(y1, y2, y3, y4, t);
let offset = getNoiseValue(0, 0, t, "face", -noiseVal, noiseVal, 10);
vertices[j] = [];
vertices[j][0] = x + offset;
vertices[j][1] = y + offset;
j++;
}
vertices[j] = []; vertices[j+1] = [];
vertices[j][0] = x4; vertices[j][1] = y4;
vertices[j+1][0] = x4; vertices[j+1][1] = y4;
return vertices;
}
/**
* analyze the face center position, its width and height
* and return an array of the leftest, rightest and lowest point
*/
this.analyzeFace = function(segment){
let result = [];
result[0] = segment[0];
result[1] = segment[segment.length-1];
result[2] = segment[0];
for(let i = 0; i < segment.length; i++) {
if (result[2][1] < segment[i][1]) result[2] = segment[i];
}
return result;
}
/**
* find the height of the given point array
* used for calculating if the mouth is opened
*/
this.findHeight = function(segment) {
let minY = segment[0][1];
let maxY = segment[0][1];
for (let i = 0; i < segment.length; i++) {
if(minY > segment[i][1]) minY = segment[i][1];
if(maxY < segment[i][1]) maxY = segment[i][1];
}
return abs(maxY - minY);
}
/**
* helper method to calculate a more detailed points array for a given array
* which is a continuous curve
*/
this.combineCurve = function(segment){
let result = [];
for (let i = 0; i < segment.length-1; i++) {
let dis = dist(segment[i][0], segment[i][1], segment[i+1][0], segment[i+1][1]);
for (let j = 0; j < dis; j+=0.05) {
let t = j/dis;
let point = [];
point[0] = lerp(segment[i][0], segment[i+1][0], t);
point[1] = lerp(segment[i][1], segment[i+1][1], t);
append(result, point);
}
}
return result;
}
}
{
"000001": [
20,
47,
81,
25,
40,
0,
26,
0
],
"000002": [
20,
51,
50,
100,
81.00000000000001,
100,
17,
100
],
"000005": [
20,
50,
0,
0,
43,
100,
47,
0
],
"000006": [
80,
61,
25,
0,
43,
100,
0,
100
],
"000007": [
20,
54,
100,
100,
52,
0,
18,
0
],
"000009": [
20,
45.00000000000001,
25,
0,
59,
100,
19,
100
],
"000010": [
20,
57.99999999999999,
0,
0,
55.000000000000014,
100,
18,
100
],
"000013": [
20,
57.99999999999999,
0,
0,
53.000000000000014,
0,
18,
0
],
"000014": [
80,
45.00000000000001,
100,
0,
53.000000000000014,
100,
18,
0
],
"000015": [
20,
39,
100,
0,
14.999999999999996,
0,
18,
0
],
"000016": [
20,
76,
100,
100,
40.00000000000001,
0,
18,
0
],
"000018": [
0,
47,
0,
0,
44,
100,
18,
100
],
"000020": [
20,
59,
75,
0,
40.00000000000001,
0,
18,
100
],
"000023": [
20,
75,
100,
0,
42,
0,
18,
0
],
"000025": [
20,
55.00000000000001,
75,
100,
43,
0,
15,
0
],
"000028": [
20,
55.00000000000001,
25,
0,
72,
100,
15,
100
],
"000029": [
20,
47,
0,
0,
72,
100,
15,
100
],
"000030": [
20,
49,
0,
0,
82,
0,
15,
0
],
"000031": [
20,
56.99999999999999,
25,
0,
82,
100,
28.000000000000004,
0
],
"000032": [
20,
45.00000000000001,
25,
0,
63,
0,
13,
0
],
"000035": [
20,
56.00000000000001,
100,
0,
76,
100,
13,
100
],
"000037": [
80,
56.00000000000001,
100,
0,
51.000000000000014,
0,
13,
0
],
"000038": [
0,
44.00000000000001,
100,
0,
38.00000000000001,
0,
13,
0
],
"000040": [
40,
55.00000000000001,
100,
0,
86.00000000000001,
100,
53,
100
],
"000041": [
20,
19,
100,
100,
87,
0,
53,
0
],
"000042": [
20,
42.00000000000001,
25,
0,
53.000000000000014,
100,
53,
100
],
"000043": [
20,
50,
25,
0,
63,
100,
53,
100
],
"000044": [
100,
50,
100,
0,
64.00000000000001,
100,
43,
100
],
"000045": [
20,
43.00000000000001,
75,
100,
58.00000000000001,
100,
44,
100
],
"000047": [
40,
67,
100,
0,
33,
100,
33,
100
],
"000048": [
0,
67,
100,
100,
20,
0,
33,
0
],
"000050": [
20,
49,
100,
0,
45,
0,
24,
0
],
"000051": [
20,
46.00000000000001,
100,
100,
45,
0,
25,
0
],
"000052": [
20,
48,
75,
100,
42,
0,
44,
0
],
"000054": [
20,
47,
0,
100,
42,
100,
45,
100
],
"000055": [
20,
51,
100,
100,
42,
0,
45,
0
],
"000056": [
20,
42.00000000000001,
100,
0,
34.99999999999999,
0,
45,
0
],
"000058": [
20,
52,
100,
0,
58.00000000000001,
100,
45,
100
],
"000060": [
80,
34,
100,
100,
51.000000000000014,
0,
17,
0
],
"000064": [
20,
51,
100,
0,
46.00000000000002,
0,
36,
0
],
"000065": [
40,
52,
100,
0,
51.000000000000014,
0,
39,
0
],
"000068": [
20,
51,
100,
0,
44,
0,
14.000000000000002,
0
],
"000069": [
20,
52,
100,
0,
30,
0,
45,
0
],
"000071": [
20,
51,
0,
100,
75.00000000000001,
100,
30,
0
],
"000073": [
20,
36,
100,
100,
42,
100,
22,
100
],
"000076": [
40,
40,
100,
100,
41,
0,
39,
0
],
"000077": [
20,
57.99999999999999,
100,
100,
51.000000000000014,
100,
45,
100
],
"000078": [
20,
51,
100,
0,
46.00000000000002,
100,
45,
100
],
"000079": [
20,
60,
100,
100,
49.00000000000001,
0,
45,
0
],
"000080": [
20,
39,
100,
0,
33,
0,
21,
0
],
"000081": [
20,
66,
100,
0,
31,
0,
13,
0
],
"000083": [
16.69449081803005,
51,
60.12024048096192,
0,
56.99999999999999,
100,
30,
100
],
"000085": [
20,
51,
50,
100,
83,
100,
45,
100
],
"000086": [
20,
43.00000000000001,
75,
0,
48,
100,
22,
100
],
"000088": [
20,
51,
75,
100,
48,
100,
28.000000000000004,
100
],
"000091": [
20,
51,
100,
100,
20,
0,
27,
0
],
"000092": [
20,
40,
0,
0,
51.000000000000014,
100,
36,
100
],
"000096": [
20,
51,
100,
0,
65,
100,
45,
100
],
"000097": [
20,
56.99999999999999,
25,
100,
63,
100,
31,
100
],
"000099": [
16.69449081803005,
51,
20.040080160320638,
0,
22.000000000000004,
100,
11,
100
],
"000100": [
20,
51,
0,
0,
75.00000000000001,
100,
45,
0
],
"000103": [
20,
47,
25,
0,
68.00000000000001,
100,
24,
100
],
"000104": [
20,
51,
25,
100,
42,
0,
21,
0
],
"000106": [
20,
43.00000000000001,
25,
0,
45,
100,
11,
100
],
"000108": [
20,
51,
0,
0,
59,
100,
28.000000000000004,
100
],
"000109": [
20,
51,
100,
100,
42,
0,
23,
0
],
"000110": [
20,
51,
75,
0,
65,
100,
45,
100
],
"000111": [
60,
51,
0,
100,
32,
100,
24,
0
],
"000114": [
20,
51,
100,
0,
81.00000000000001,
0,
45,
0
],
"000115": [
20,
51,
100,
100,
42,
0,
45,
0
],
"000116": [
20,
51,
25,
0,
53.000000000000014,
0,
39,
0
],
"000117": [
100,
51,
100,
100,
63,
100,
45,
100
],
"000118": [
20,
43.00000000000001,
100,
0,
63,
100,
34,
100
],
"000121": [
20,
59,
100,
0,
62.000000000000014,
100,
32,
100
],
"000122": [
0,
44.00000000000001,
0,
0,
79.00000000000001,
100,
45,
0
],
"000125": [
20,
56.99999999999999,
100,
100,
50,
0,
45,
0
],
"000126": [
40,
59,
0,
100,
67,
0,
44,
100
],
"000129": [
20,
51,
100,
100,
36.00000000000001,
0,
24,
0
],
"000131": [
20,
68,
100,
100,
38.00000000000001,
100,
18,
100
],
"000132": [
60,
56.00000000000001,
100,
100,
63,
100,
34,
100
],
"000133": [
20,
51,
0,
100,
63,
100,
45,
100
],
"000134": [
100,
25,
100,
100,
58.00000000000001,
0,
22,
0
],
"000135": [
60,
76,
100,
0,
52,
0,
36,
0
],
"000137": [
20,
69,
100,
0,
28.999999999999996,
0,
0,
0
],
"000140": [
20,
49,
0,
0,
56.99999999999999,
100,
24,
100
],
"000142": [
20,
51,
75,
0,
59,
100,
26,
100
],
"000143": [
20,
59,
25,
100,
55.000000000000014,
0,
35,
0
],
"000145": [
20,
49,
100,
0,
32,
100,
28.999999999999996,
100
],
"000146": [
20,
37,
50,
0,
43,
100,
12,
100
],
"000147": [
20,
59,
0,
0,
66.00000000000001,
100,
31,
100
],
"000148": [
20,
69,
100,
0,
41,
100,
19,
0
],
"000150": [
20,
51,
50,
0,
61,
0,
28.000000000000004,
0
],
"000151": [
60,
53,
100,
0,
66.00000000000001,
100,
33,
100
],
"000152": [
20,
51,
75,
0,
38.99999999999999,
0,
24,
0
],
"000153": [
20,
51,
100,
0,
51.000000000000014,
0,
25,
0
],
"000155": [
20,
51,
50,
100,
74,
100,
34,
100
],
"000156": [
20,
51,
0,
100,
63,
100,
34,
0
],
"000157": [
20,
51,
0,
0,
51.000000000000014,
100,
31,
100
],
"000160": [
20,
51,
100,
100,
47.00000000000001,
0,
27,
0
],
"000161": [
20,
48,
100,
100,
36.00000000000001,
100,
28.999999999999996,
100
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
//var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
// var NUM_SLIDERS = 8;
// other variables can be in here too
// here's some examples for colors used
// const bg_color = [225, 206, 187];
// const fg_color = [151, 102, 52];
// const stroke_color = [95, 52, 8];
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i=0; i<s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len , sum_y / s_len ];
}
// This where you define your own face object
function HillFace() {
const eye_position = 0.85;
const eye_size1 = 0.6;
const eye_size2 = 0.8;
const pupil_size1 = 0.25;
const pupil_size2 = 0.25;
const rect_height = 4;
const rect_width = 3.5;
const mouth_wide = 1.25;
//BAG COLOURS//
const bag_light = [209, 182, 150];
const bag_mid = [187, 145, 100];
const bag_dark = [144, 102, 73];
const side_shadow_light = [163, 138, 107];
const side_shadow_mid = [140, 109, 75];
const side_shadow_dark = [108, 77, 55];
const top_shadow_light = [182, 158, 129];
const top_shadow_mid = [164, 127, 88];
const top_shadow_dark = [126, 89, 64];
this.eye_value = 2; //1-2
this.eye_brow = 2; //1-2
this.nose_value = 1; //1-2
this.bag_colour = 1; //1-3
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
rectMode(CENTER);
scale(1.5);
noStroke();
///HEAD//////
//front
let face_pos = segment_average(positions.chin);
if (this.bag_colour == 1) {
fill(bag_light);
}
else if (this.bag_colour == 2) {
fill(bag_mid);
}
else if (this.bag_colour == 3) {
fill(bag_dark);
}
rect(0, -0.25, rect_width, rect_height);
//pointy detail
triangle(-1.75, 1.74, -1.75, 2.25, -1.25, 1.74);
push();
triangle(-0.6, 1.74, -0.95, 2.25, -1.3, 1.74);
translate(0.5, 0);
triangle(-0.4, 1.74, -0.75, 2.25, -1.1, 1.74);
translate(0.7, 0);
triangle(-0.4, 1.74, -0.75, 2.25, -1.1, 1.74);
translate(0.6, 0);
triangle(-0.4, 1.74, -0.75, 2.25, -1.1, 1.74);
pop();
triangle(1.25, 1.74, 1.75, 2.25, 1.75, 1.74);
//top
if (this.bag_colour == 1) {
fill(top_shadow_light);
}
else if (this.bag_colour == 2) {
fill(top_shadow_mid);
}
else if (this.bag_colour == 3) {
fill(top_shadow_dark);
}
quad(-2.5, -2.5, -1.75, -2.25, 1.75, -2.25, 1, -2.5);
//side
if (this.bag_colour == 1) {
fill(side_shadow_light);
}
else if (this.bag_colour == 2) {
fill(side_shadow_mid);
}
else if (this.bag_colour == 3) {
fill(side_shadow_dark);
}
quad(-2.5, 1.25, -2.5, -2.5, -1.75, -2.25, -1.75, 1.75);
triangle(-1.75, 1.7, -1.75, 2.25, -2.25, 1.4);
triangle(-2.5, 1.9, -2.5, 1.25, -2, 1.4);
noFill();
stroke(0);
strokeWeight(0.06);
///NOSE//////
let nose_top = positions.nose_bridge[1];
let nose_bottom = positions.nose_bridge[3];
let nose_center = positions.nose_tip[2];
if (this.nose_value == 1) {
line(nose_top[0], nose_top[1], nose_bottom[0], nose_bottom[1]);
line(nose_top[0] - 0.02, nose_top[1], nose_bottom[0], nose_bottom[1]);
arc(nose_center[0], nose_center[1], 0.5, 0.5, 0, 180);
arc(nose_center[0], nose_center[1], 0.5, 0.55, 0, 180);
}
else if (this.nose_value == 2) {
arc(nose_center[0], nose_center[1], 0.5, 0.5, 0, 180);
arc(nose_center[0], nose_center[1], 0.5, 0.55, 0, 180);
}
///MOUTH/////
let mouth_pos = segment_average(positions.bottom_lip);
let lip_top = positions. top_lip[9];
let lip_bottom = positions. bottom_lip[9];
let d = dist(lip_top[0], lip_top[1], lip_bottom[0], lip_bottom[1]);
let mouth = map(d, 0, 1, 0, 10);
let mouth_open = map(mouth, 0, 10, 0, 1);
if (d < 0.2) {
d = 0;
}
ellipse(mouth_pos[0], mouth_pos[1] + 0.1, mouth_wide, mouth_open);
ellipse(mouth_pos[0], mouth_pos[1] + 0.1, mouth_wide, mouth_open + 0.05);
///EYEBROWS/////
let left_eyebrow_pos = segment_average(positions.left_eyebrow);
let right_eyebrow_pos = segment_average(positions.right_eyebrow);
if (this.eye_brow == 1) {
rect(left_eyebrow_pos[0], left_eyebrow_pos[1], 0.7, 0.01);
rect(right_eyebrow_pos[0], right_eyebrow_pos[1], 0.7, 0.01);
}
else if (this.eye_brow == 2) {
fill(0);
rect(left_eyebrow_pos[0], left_eyebrow_pos[1], 0.5, 0.06);
rect(right_eyebrow_pos[0], right_eyebrow_pos[1], 0.5, 0.06);
}
///EYES//////
noFill();
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye);
if (this.eye_value == 1) {
ellipse(left_eye_pos[0], left_eye_pos[1], eye_size1 - 0.1, eye_size1);
ellipse(right_eye_pos[0], right_eye_pos[1], eye_size1 - 0.1, eye_size1);
ellipse(left_eye_pos[0], left_eye_pos[1], eye_size1 - 0.1, eye_size1 + 0.05);
ellipse(right_eye_pos[0], right_eye_pos[1], eye_size1 - 0.1, eye_size1 + 0.05);
fill(0);
ellipse(left_eye_pos[0], left_eye_pos[1], pupil_size1);
ellipse(right_eye_pos[0], right_eye_pos[1], pupil_size1);
}
else if (this.eye_value == 2) {
arc(left_eye_pos[0], left_eye_pos[1], eye_size2 - 0.2, eye_size2, 0, 180, CHORD);
arc(right_eye_pos[0], right_eye_pos[1], eye_size2 - 0.2, eye_size2, 0, 180, CHORD);
arc(left_eye_pos[0], left_eye_pos[1], eye_size2 - 0.2, eye_size2 + 0.05, 0, 180, CHORD);
arc(right_eye_pos[0], right_eye_pos[1], eye_size2 - 0.2, eye_size2 + 0.05, 0, 180, CHORD);
fill(0);
ellipse(left_eye_pos[0], left_eye_pos[1] + 0.15, pupil_size2);
ellipse(right_eye_pos[0], right_eye_pos[1] + 0.15, pupil_size2);
}
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.eye_value = int(map(settings[0], 0, 100, 1, 2));
this.eye_brow = int(map(settings[1], 0, 100, 1, 2));
this.nose_value = int(map(settings[2], 0, 100, 1, 2));
this.bag_colour = int(map(settings[3], 0, 100, 1, 3));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(4);
settings[0] = map(this.eye_value, 1, 2, 0, 100);
settings[1] = map(this.eye_brow, 1, 2 , 0, 100);
settings[2] = map(this.nose_value, 1, 2, 0, 100);
settings[3] = map(this.bag_colour, 1, 3, 0, 100);
return settings;
}
}
{
"000018": [
100,
100,
100,
0
],
"000020": [
100,
100,
0,
0
],
"000023": [
0,
100,
0,
0
],
"000025": [
100,
100,
0,
0
],
"000028": [
100,
100,
100,
50
],
"000029": [
0,
0,
100,
0
],
"000030": [
100,
0,
0,
0
],
"000031": [
0,
100,
100,
0
],
"000032": [
100,
0,
0,
0
],
"000035": [
100,
100,
100,
0
],
"000037": [
100,
100,
0,
100
],
"000038": [
0,
100,
0,
0
],
"000040": [
100,
100,
100,
0
],
"000041": [
100,
100,
0,
50
],
"000042": [
0,
0,
100,
0
],
"000043": [
100,
100,
100,
0
],
"000044": [
100,
100,
100,
100
],
"000045": [
100,
100,
100,
0
],
"000047": [
100,
100,
100,
50
],
"000048": [
100,
100,
0,
0
],
"000050": [
100,
100,
0,
0
],
"000051": [
100,
0,
0,
0
],
"000052": [
0,
100,
0,
50
],
"000054": [
0,
0,
100,
0
],
"000055": [
100,
100,
0,
0
],
"000056": [
0,
100,
0,
0
],
"000058": [
0,
100,
100,
0
],
"000060": [
100,
100,
0,
100
],
"000064": [
0,
100,
0,
0
],
"000065": [
100,
100,
0,
50
],
"000068": [
100,
0,
0,
0
],
"000069": [
100,
100,
0,
0
],
"000071": [
0,
0,
100,
0
],
"000073": [
100,
100,
100,
0
],
"000076": [
100,
100,
0,
0
],
"000077": [
100,
100,
100,
0
],
"000078": [
100,
100,
100,
0
],
"000079": [
100,
0,
0,
50
],
"000080": [
0,
100,
0,
0
],
"000081": [
100,
100,
0,
50
],
"000083": [
100,
100,
100,
0
],
"000085": [
0,
100,
100,
0
],
"000086": [
100,
100,
100,
0
],
"000088": [
100,
100,
100,
0
],
"000091": [
100,
100,
0,
0
],
"000092": [
0,
0,
100,
0
],
"000096": [
100,
100,
100,
0
],
"000097": [
0,
0,
100,
0
],
"000099": [
0,
0,
100,
0
],
"000100": [
100,
0,
100,
0
],
"000103": [
0,
100,
100,
0
],
"000001": [
100,
0,
100,
0
],
"000002": [
100,
100,
100,
0
],
"000005": [
0,
0,
100,
0
],
"000006": [
100,
0,
100,
50
],
"000007": [
100,
100,
0,
0
],
"000009": [
100,
100,
100,
0
],
"000010": [
0,
0,
100,
0
],
"000013": [
0,
0,
0,
0
],
"000014": [
100,
100,
100,
100
],
"000015": [
100,
100,
0,
0
],
"000016": [
100,
100,
0,
0
],
"000161": [
0,
100,
100,
0
],
"000160": [
100,
100,
0,
0
],
"000157": [
0,
0,
100,
0
],
"000156": [
0,
0,
100,
0
],
"000155": [
100,
100,
100,
0
],
"000153": [
100,
100,
0,
0
],
"000152": [
0,
100,
0,
0
],
"000151": [
100,
100,
100,
50
],
"000150": [
0,
100,
0,
0
],
"000148": [
0,
100,
100,
0
],
"000147": [
0,
0,
100,
0
],
"000146": [
100,
100,
100,
50
],
"000145": [
100,
100,
100,
0
],
"000143": [
0,
0,
0,
0
],
"000142": [
0,
100,
100,
0
],
"000140": [
0,
0,
100,
50
],
"000137": [
100,
100,
0,
0
],
"000135": [
100,
100,
0,
50
],
"000134": [
100,
100,
0,
100
],
"000133": [
0,
0,
100,
0
],
"000132": [
100,
100,
100,
50
],
"000131": [
100,
100,
100,
0
],
"000129": [
0,
100,
0,
0
],
"000126": [
0,
0,
100,
0
],
"000125": [
0,
100,
0,
0
],
"000122": [
100,
0,
100,
0
],
"000121": [
100,
100,
100,
0
],
"000118": [
100,
100,
100,
50
],
"000117": [
100,
100,
100,
100
],
"000116": [
100,
100,
0,
0
],
"000115": [
0,
0,
0,
0
],
"000114": [
100,
100,
0,
0
],
"000111": [
100,
0,
100,
50
],
"000110": [
0,
100,
100,
0
],
"000109": [
0,
0,
0,
0
],
"000108": [
0,
0,
100,
0
],
"000106": [
100,
100,
100,
0
],
"000104": [
0,
0,
0,
0
]
}
// var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
// var NUM_SLIDERS = 8;
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i=0; i<s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len , sum_y / s_len ];
}
// This where you define your own face object
function HoFace() {
// these are state variables for a face
// (your variables should be different!)
//pumpkin colour (Hair)
const yellow = color(255, 255, 0);
const mid_yellow = color(255, 117, 24);
const dark_yellow = color(127, 51, 0);
const error_green = color(0, 255, 0);
//eye colour
const brown = color(69,24,0);
const blue = color(135,206,250);
const grey = color(128,128,128);
const pink = color(255,182,193);
/*
* earSize can vary from 0 to 4
* earDist is the distance between ears and varies from 0 to 4
* faceColor is 1,2,3,4 for yellow,blue,red, or violet respectively
*/
this.leafSize = 5;
this.leafDist = 5;
this.hairColor = 1;
this.eyeColor = 1;
this.blushColor = 1;
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
noStroke();
push();
if(this.hairColor == 0) {
fill(yellow);
}
else if (this.hairColor==1) {
fill(mid_yellow);
}
else if (this.hairColor==2) {
fill(dark_yellow);
}
else {
fill(error_green);
}
// head
push();
scale(1/3);
translate(-4,0);
noStroke();
ellipse(0, 0, 7,10);
ellipse(2, 0, 5,10);
ellipse(4, 0, 8,10);
ellipse(6, 0, 5,10);
ellipse(8, 0, 7,10);
pop();
pop();
//leaf//
push();
scale(1/3);
let leafRadius = map(this.leafSize, 0, 10, 0.3, 2);
let leafXPos = map(this.leafDist, 0, 10, 0.5, 2);
fill(58,23,11);
noStroke();
rect(-2+leafXPos,-8.5,leafRadius+1.5,4,0.2,1,1,1);
pop();
//leaf//
push();
//nose//
let nose_top = positions.nose_bridge[0];
let nose_bottom = positions.nose_bridge[3];
stroke(0);
strokeWeight(0.15);
// line(nose_top[0], nose_top[1], nose_bottom[0], nose_bottom[1]); //top
fill(0);
triangle(nose_bottom[0], nose_bottom[1], nose_top[0], nose_top[0],nose_bottom[1], nose_bottom[1]);
let nose_end = null;
if(nose_top[0] < nose_bottom[0]) {
nose_end = positions.nose_tip[0];
}
else {
nose_end = positions.nose_tip[4];
}
// let nose_end = positions.nose_tip[4];
let nose_center = positions.nose_tip[2];
pop();
// line(nose_end[0], nose_end[1], nose_center[0], nose_center[1]); //bottom
//nose//
//mouth//
// let top_lip = positions.top_lip[0];
// let bottom_lip = positions.bottom_lip[]
push();
push();
fill(0);
noStroke();
ellipse(positions.bottom_lip[7][0], positions.bottom_lip[6][1],0.2);
ellipse(positions.bottom_lip[8][0], positions.bottom_lip[8][1],0.2);
ellipse(positions.bottom_lip[9][0], positions.bottom_lip[9][1],0.2);
ellipse(positions.bottom_lip[10][0], positions.bottom_lip[10][1],0.2);
ellipse(positions.bottom_lip[0][0], positions.bottom_lip[0][1],0.2);
pop();
pop();
push();
if(this.eyeColor == 0) {
fill(brown);
}
else if (this.eyeColor==1) {
fill(blue);
}
else if (this.eyeColor==2) {
fill(grey);
}
else {
fill(error_green);
}
//eyes//
noStroke();
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye);
push();
translate(0,0.5);
push();
fill(255);
ellipse(left_eye_pos[0], left_eye_pos[1], 0.5);
ellipse(right_eye_pos[0], right_eye_pos[1], 0.5);
pop();
push();
translate(0,0);
ellipse(left_eye_pos[0], left_eye_pos[1], 0.3);
ellipse(right_eye_pos[0], right_eye_pos[1], 0.3);
pop();
pop();
pop();
//eyes//
if(this.blushColor == 0) {
fill(pink);
}
else if (this.eyeColor==1) {
noFill();
}
else if (this.eyeColor==2) {
noFill();
}
else {
noFill();
}
//blush
ellipse(1.5,0,0.5,0.25);
ellipse(-1.5,0,0.5,0.25);
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.leafSize = map(settings[0], 0, 100, 0, 10);
this.leafDist = map(settings[1], 0, 100, 0, 10);
this.hairColor = int(map(settings[2], 0, 100, 0, 3));
this.eyeColor = int(map(settings[3], 0, 100, 0, 3));
this.blushColor = int(map(settings[4], 0, 100, 0, 3));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(5);
settings[0] = map(this.leafSize, 0, 10, 0, 100);
settings[1] = map(this.leafDist, 0, 10, 0, 100);
settings[2] = map(this.hairColor, 0, 4, 0, 100);
settings[3] = map(this.eyeColor, 0, 4, 0, 100);
settings[4] = map(this.blushColor, 0, 4, 0, 100);
return settings;
}
}
{
"000001": [
50,
50,
0,
0,
50
],
"000002": [
50,
50,
50,
0
],
"000005": [
50,
50,
0,
75
],
"000006": [
50,
50,
0,
0
],
"000007": [
50,
50,
75,
0,
50
],
"000009": [
50,
50,
75,
0,
0
],
"000010": [
50,
50,
0,
50,
0
],
"000013": [
50,
50,
0,
0,
75
],
"000014": [
50,
50,
75,
0,
0
],
"000015": [
50,
50,
50,
0,
75
],
"000016": [
50,
50,
75,
0,
50
],
"000018": [
50,
50,
0,
0,
0
],
"000020": [
50,
50,
75,
0,
50
],
"000023": [
50,
50,
75,
0,
50
],
"000025": [
50,
50,
75,
0,
50
],
"000028": [
50,
50,
0,
0,
0
],
"000029": [
50,
50,
0,
25,
0
],
"000030": [
50,
50,
0,
0,
75
],
"000031": [
50,
50,
0,
50,
0
],
"000032": [
50,
50,
0,
0,
75
],
"000035": [
50,
50,
50,
0,
0
],
"000037": [
50,
50,
50,
0,
75
],
"000038": [
50,
50,
50,
50,
50
],
"000040": [
50,
50,
50,
0,
0
],
"000041": [
50,
50,
50,
0,
75
],
"000042": [
50,
50,
0,
50,
0
],
"000043": [
50,
50,
75,
25,
0
],
"000044": [
50,
50,
75,
0,
0
],
"000045": [
50,
50,
50,
0,
0
],
"000047": [
50,
50,
75,
0,
0
],
"000048": [
50,
50,
75,
0,
50
],
"000050": [
50,
50,
75,
0,
25
],
"000051": [
50,
50,
0,
0,
75
],
"000052": [
50,
50,
50,
50,
75
],
"000054": [
50,
50,
0,
0,
0
],
"000055": [
50,
50,
75,
0,
25
],
"000056": [
50,
50,
75,
0,
25
],
"000058": [
50,
50,
75,
25,
0
],
"000060": [
50,
50,
75,
0,
50
],
"000064": [
50,
50,
50,
0,
0
],
"000065": [
50,
50,
75,
0,
50
],
"000068": [
50,
50,
0,
0,
75
],
"000069": [
50,
50,
75,
0,
25
],
"000071": [
50,
50,
0,
0,
0
],
"000073": [
50,
50,
75,
0,
0
],
"000076": [
50,
50,
75,
0,
50
],
"000077": [
50,
50,
75,
0,
0
],
"000078": [
50,
50,
75,
0,
0
],
"000079": [
50,
50,
0,
0,
75
],
"000080": [
50,
50,
75,
0,
50
],
"000081": [
50,
50,
75,
0,
50
],
"000083": [
50,
50,
50,
25,
0
],
"000085": [
50,
50,
50,
0,
0
],
"000086": [
50,
50,
0,
0,
0
],
"000088": [
50,
50,
50,
0,
0
],
"000091": [
50,
50,
75,
0,
50
],
"000092": [
50,
50,
0,
50,
0
],
"000096": [
50,
50,
75,
0,
0
],
"000097": [
50,
50,
50,
0,
0
],
"000099": [
50,
50,
50,
0,
0
],
"000100": [
50,
50,
0,
0,
0
],
"000103": [
50,
50,
75,
25,
0
],
"000104": [
50,
50,
0,
0,
75
],
"000106": [
50,
50,
0,
0,
0
],
"000108": [
50,
50,
0,
50,
0
],
"000109": [
50,
50,
0,
0,
75
],
"000110": [
50,
50,
0,
0,
0
],
"000111": [
50,
50,
0,
0,
0
],
"000114": [
50,
50,
75,
0,
50
],
"000115": [
50,
50,
0,
0,
75
],
"000116": [
50,
50,
50,
0,
50
],
"000117": [
50,
50,
75,
0,
0
],
"000118": [
50,
50,
75,
0,
0
],
"000121": [
50,
50,
75,
0,
0
],
"000122": [
50,
50,
0,
0,
0
],
"000125": [
50,
50,
0,
50,
75
],
"000126": [
50,
50,
0,
0,
0
],
"000129": [
50,
50,
75,
0,
50
],
"000131": [
50,
50,
75,
0,
0
],
"000132": [
50,
50,
75,
0,
0
],
"000133": [
50,
50,
0,
50,
0
],
"000134": [
50,
50,
75,
0,
50
],
"000135": [
50,
50,
75,
0,
50
],
"000137": [
50,
50,
75,
0,
25
],
"000140": [
50,
50,
0,
25,
0
],
"000142": [
50,
50,
75,
25,
0
],
"000143": [
50,
50,
50,
0,
50
],
"000145": [
50,
50,
75,
0,
0
],
"000146": [
50,
50,
50,
0,
0
],
"000147": [
50,
50,
0,
25,
0
],
"000148": [
50,
50,
75,
25,
0
],
"000150": [
50,
50,
75,
0,
50
],
"000151": [
50,
50,
75,
0,
0
],
"000152": [
50,
50,
0,
0,
75
],
"000153": [
50,
50,
75,
0,
50
],
"000155": [
50,
50,
75,
0,
0
],
"000156": [
50,
50,
0,
25,
0
],
"000157": [
50,
50,
0,
25,
0
],
"000160": [
50,
50,
75,
0,
50
],
"000161": [
50,
50,
75,
0,
0
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
//var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
// var NUM_SLIDERS = 3;
// This where you define your own face object
function HowardFace() {
const light = color(250, 200, 140);
const middle = color(230, 155, 75);
const dark = color(170, 125, 70);
const tan = color(250, 235, 200);
//this.mouth_value
this.fur_colour = 1;
this.ear_length = -1;
this.blush = 0;
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
let left_eye = average_point(positions.left_eye);
let right_eye = average_point(positions.right_eye);
let left_eyebrow = average_point(positions.left_eyebrow);
let right_eyebrow = average_point(positions.right_eyebrow);
let left_d = dist(left_eye[0], left_eye[1], left_eyebrow[0], left_eyebrow[1]);
let right_d = dist(right_eye[0], right_eye[1], right_eyebrow[0], right_eyebrow[1]);
let left_eb_move = map(left_d, 0.4, 0.7, 0.6, 1.5, true);
let right_eb_move = map(right_d, 0.4, 0.7, 0.6, 1.5, true);
left_eye[0] *= 3;
left_eye[1] *= 3;
right_eye[0] *= 3;
right_eye[1] *= 3;
if (this.fur_colour == 1) {
fill(light);
} else if (this.fur_colour == 2) {
fill(middle);
} else {
fill(dark);
}
noStroke();
ellipse(0, 0.15, 5, 5.5);
stroke(tan);
noFill();
strokeWeight(0.3);
fill(tan);
ellipse(0, 1.5, 3, 2.2);
// head outline
noFill();
strokeWeight(0.25);
stroke(60, 50, 50);
beginShape();
vertex(0, -2.625);
//bezierVertex(3, -7.5, 7, -5, 8, 1);
//bezierVertex(8, 1, 10, 8, 0, 9);
bezierVertex(1.05, -2.625, 2.45, -1.75, 2.45, 0.35);
bezierVertex(2.45, 0.35, 2.625, 2.8, 0, 2.8);
bezierVertex(-2.625, 2.8, -2.625, 0.25, -2.55, 0.35);
bezierVertex(-2.45, -1.75, -1.05, -2.625, 0, -2.625);
endShape();
//ears
//Ear colour
if (this.fur_colour == 1) {
fill(light);
} else if (this.fur_colour == 2) {
fill(middle);
} else {
fill(dark);
}
//left ear
beginShape();
curveVertex(-2.4, -0.7);
curveVertex(-2.4, -0.7);
curveVertex(-2.8, -1.4 + this.ear_length);
curveVertex(-2.45, -2.45 + this.ear_length);
curveVertex(-1.05, -2.38);
curveVertex(-1.05, -2.38);
endShape();
//right ear
beginShape();
curveVertex(2.345, -0.7);
curveVertex(2.345, -0.7);
curveVertex(2.8, -1.4 + this.ear_length);
curveVertex(2.45, -2.45 + this.ear_length);
curveVertex(1.05, -2.38);
curveVertex(1.05, -2.38);
endShape();
fill(tan);
stroke(tan);
//left ear inside
beginShape();
curveVertex(-2.1, -1.4);
curveVertex(-2.1, -1.4);
curveVertex(-2.24, -1.225 + this.ear_length);
curveVertex(-2.24, -1.75 + this.ear_length);
curveVertex(-1.575, -2);
curveVertex(-1.575, -2);
endShape();
//left ear inside line
beginShape();
curveVertex(-2.1, -1.4);
curveVertex(-2.1, -1.4);
curveVertex(-1.925, -1.645);
curveVertex(-1.6625, -1.925);
curveVertex(-1.575, -2);
curveVertex(-1.575, -2);
endShape();
//right ear inside
beginShape();
curveVertex(2.1, -1.4);
curveVertex(2.1, -1.4);
curveVertex(2.24, -1.225 + this.ear_length);
curveVertex(2.24, -1.75 + this.ear_length);
curveVertex(1.575, -2);
curveVertex(1.575, -2);
endShape();
//right ear inside line
beginShape();
curveVertex(2.1, -1.4);
curveVertex(2.1, -1.4);
curveVertex(1.925, -1.645);
curveVertex(1.6625, -1.925);
curveVertex(1.575, -2);
curveVertex(1.575, -2);
endShape();
//left brow
push();
strokeWeight(0.375)
translate(0, 1 - left_eb_move);
beginShape();
curveVertex(-1.225, -1.12);
curveVertex(-1.225, -1.12);
curveVertex(-1.05, -1.19);
curveVertex(-0.91, -1.19);
curveVertex(-0.805, -1.12);
curveVertex(-0.805, -1.12);
endShape();
beginShape();
curveVertex(-1.225, -1.12);
curveVertex(-1.225, -1.12);
curveVertex(-1.05, -1.085);
curveVertex(-0.91, -1.085);
curveVertex(-0.805, -1.12);
curveVertex(-0.805, -1.12);
endShape();
//right brow
beginShape();
curveVertex(1.225, -1.12);
curveVertex(1.225, -1.12);
curveVertex(1.05, -1.19);
curveVertex(0.91, -1.19);
curveVertex(0.805, -1.12);
curveVertex(0.805, -1.12);
endShape();
beginShape();
curveVertex(1.225, -1.12);
curveVertex(1.225, -1.12);
curveVertex(1.05, -1.085);
curveVertex(0.91, -1.085);
curveVertex(0.805, -1.12);
curveVertex(0.805, -1.12);
endShape();
pop();
// eyes
const green = color('#3bb44a');
const darkGreen = color('#046538');
const lightBlue = color('#9bcde1');
const darkBlue = color('#0c76c1');
const lightBrown = color('#8b5f3c');
const pink = color('#ff9292');
//outline
noStroke();
fill(40);
ellipse(-1.05, -0.175, 0.735);
ellipse(1.05, -0.175, 0.735);
//iris
if (this.blush < 5) {
fill(lightBlue);
} else {
fill(pink);
}
ellipse(-1.05, -0.175, 0.7);
ellipse(1.05, -0.175, 0.7);
//
fill(40);
ellipse(-1.05, -0.175, 0.455);
ellipse(1.05, -0.175, 0.455);
//white reflection
fill(255);
ellipse(-1.225, -0.35, 0.175, 0.14);
ellipse(0.875, -0.35, 0.175, 0.14);
//mouth open
let top_lip_point = positions.top_lip[9];
let bottom_lip_point = positions.bottom_lip[9];
// fill(255, 0, 0);
let d = dist(top_lip_point[0], top_lip_point[1], bottom_lip_point[0], bottom_lip_point[1])
let mouth = map(d, 0, 0.5, 0, 10);
let mouth_size = map(mouth, 0, 10, 0, 1.5);
fill(250, 100, 100);
stroke(40);
strokeWeight(0.15)
ellipse(0, 1.2, 1.5, mouth_size);
//tongue cover
noStroke();
fill(tan);
ellipse(0.525, 1.12, 1.05, 0.77)
ellipse(-0.525, 1.12, 1.05, 0.77)
if (this.fur_colour == 1) {
fill(light);
} else if (this.fur_colour == 2) {
fill(middle);
} else {
fill(dark);
}
ellipse(0, 0.2, 1.4, 1.5);
fill(tan);
ellipse(0, 0.7, 2.1, 0.9);
//nose
fill(40);
ellipse(0, 0.875, 0.7, 0.525);
//mouth
stroke(40)
noFill();
strokeWeight(0.1575);
beginShape();
curveVertex(-0.07, 1.05);
curveVertex(-0.07, 1.05);
curveVertex(0.35, 1.505);
curveVertex(0.77, 1.54);
curveVertex(1.05, 1.33);
curveVertex(1.05, 1.33);
endShape();
beginShape();
curveVertex(0.07, 1.05);
curveVertex(0.07, 1.05);
curveVertex(-0.35, 1.505);
curveVertex(-0.77, 1.54);
curveVertex(-1.05, 1.33);
curveVertex(-1.05, 1.33);
endShape();
//blush
if (this.blush < 5) {
} else {
noStroke()
fill(200, 50, 50, 180);
ellipse(-1.4, 0.7, 0.8, 0.5);
ellipse(1.4, 0.7, 0.8, 0.5);
}
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.fur_colour = int(map(settings[0], 0, 100, 1, 4));
this.ear_length = map(settings[1], 0, 100, 0, -1);
this.blush = map(settings[2], 0, 100, 0, 10);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(4);
settings[0] = map(this.fur_colour, 1, 4, 0, 100);
settings[1] = map(this.ear_length, 0, -1, 0, 100);
settings[2] = map(this.blush, 0, 10, 0, 100);
return settings;
}
}
// given an array of [x,y] points, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for (var i = 0; i < list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
{
"000001": [
0,
0,
100
],
"000002": [
0,
28.999999999999996,
100
],
"000005": [
0,
0,
100
],
"000006": [
50,
49,
100
],
"000007": [
0,
100,
0
],
"000009": [
0,
56.99999999999999,
100
],
"000010": [
0,
0,
100
],
"000013": [
0,
0,
0
],
"000014": [
50,
100,
100
],
"000015": [
0,
77,
0
],
"000016": [
0,
86,
0
],
"000018": [
0,
0,
100
],
"000020": [
0,
65,
0
],
"000023": [
0,
76,
0
],
"000025": [
0,
62,
0
],
"000028": [
0,
68,
100
],
"000029": [
0,
0,
100
],
"000030": [
0,
0,
0
],
"000031": [
0,
77,
100
],
"000032": [
0,
50,
0
],
"000035": [
0,
100,
100
],
"000037": [
100,
100,
0
],
"000038": [
0,
83,
0
],
"000040": [
0,
83,
100
],
"000041": [
0,
92,
0
],
"000042": [
0,
30,
100
],
"000043": [
0,
75,
100
],
"000044": [
100,
100,
100
],
"000045": [
0,
65,
100
],
"000047": [
50,
100,
100
],
"000048": [
0,
88,
0
],
"000050": [
0,
88,
0
],
"000051": [
0,
0,
0
],
"000052": [
0,
84,
0
],
"000054": [
0,
0,
100
],
"000055": [
0,
100,
0
],
"000056": [
0,
100,
0
],
"000058": [
0,
100,
100
],
"000060": [
100,
0,
0
],
"000064": [
0,
71,
0
],
"000065": [
0,
100,
0
],
"000068": [
0,
0,
0
],
"000069": [
0,
100,
0
],
"000071": [
0,
0,
100
],
"000073": [
0,
62,
100
],
"000076": [
0,
100,
0
],
"000077": [
0,
71,
100
],
"000078": [
0,
71,
100
],
"000079": [
0,
0,
0
],
"000080": [
0,
100,
0
],
"000081": [
0,
100,
0
],
"000083": [
0,
41,
100
],
"000085": [
0,
53,
100
],
"000086": [
0,
37,
100
],
"000088": [
0,
49,
100
],
"000091": [
0,
93,
0
],
"000092": [
0,
0,
100
],
"000096": [
0,
84,
100
],
"000097": [
0,
62,
100
],
"000099": [
0,
53,
100
],
"000100": [
0,
30,
100
],
"000103": [
0,
76,
100
],
"000104": [
0,
33,
0
],
"000106": [
0,
70,
100
],
"000108": [
0,
0,
100
],
"000109": [
0,
46,
0
],
"000110": [
0,
54,
100
],
"000111": [
100,
19,
100
],
"000114": [
0,
100,
0
],
"000115": [
0,
0,
0
],
"000116": [
0,
59,
0
],
"000117": [
100,
100,
100
],
"000118": [
0,
100,
100
],
"000121": [
0,
100,
100
],
"000122": [
0,
0,
100
],
"000125": [
0,
35,
0
],
"000126": [
50,
0,
100
],
"000129": [
0,
90,
0
],
"000131": [
50,
100,
100
],
"000132": [
50,
100,
100
],
"000133": [
0,
51,
100
],
"000134": [
100,
100,
0
],
"000135": [
50,
100,
0
],
"000137": [
0,
17,
0
],
"000140": [
50,
0,
100
],
"000142": [
0,
66,
100
],
"000143": [
0,
54,
0
],
"000145": [
0,
84,
100
],
"000146": [
0,
63,
100
],
"000147": [
0,
0,
100
],
"000148": [
0,
86,
100
],
"000150": [
0,
24,
0
],
"000151": [
0,
84,
100
],
"000152": [
0,
61,
0
],
"000153": [
0,
61,
0
],
"000155": [
0,
34,
100
],
"000156": [
0,
0,
100
],
"000157": [
0,
0,
100
],
"000160": [
0,
100,
0
],
"000161": [
0,
100,
100
]
}
//var DEBUG_MODE = true;
// var NUM_SLIDERS = 8;
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i=0; i<s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len , sum_y / s_len ];
}
function HuFace() {
const face = [134, 89, 54];
const brown = [96, 60, 16];
const orange = [181, 135, 78];
const yellow = [164, 116, 10];
const grey = [129, 120, 101];
const pink = [217, 194, 182];
const horns_color = [254, 233, 217];
const nose_color = [53, 37, 18];
const ear_color = [234, 192, 158];
this.earringc = 1;
this.earDist = 0.3;
this.eyeDist = 0;
this.mouthDist = -0.1;
this.faceColor = 1;
this.fur = 1;
this.furColor = 3;
this.horns = -0.1;
this.draw = function(positions) {
noStroke();
//horns
fill(horns_color);
beginShape();
vertex(positions.chin[0][0]+0.5, positions.left_eyebrow[2][1]-0.3);
vertex(positions.chin[0][0]-0.1,positions.left_eyebrow[2][1]+0.3);
vertex(positions.chin[0][0]-0.5,positions.left_eyebrow[2][1]-1.3);
vertex(positions.left_eyebrow[0][0], positions.left_eyebrow[2][1]-3-this.horns);
vertex(positions.chin[0][0], positions.left_eyebrow[2][1]-1.5);
endShape();
beginShape();
vertex(positions.chin[16][0]-0.4, positions.right_eyebrow[2][1]-0.3);
vertex(positions.chin[16][0]-1.4,positions.right_eyebrow[2][1]+1.3);
vertex(positions.chin[16][0]-0.5,positions.right_eyebrow[2][1]-1.5);
vertex(positions.right_eyebrow[4][0], positions.right_eyebrow[2][1]-3-this.horns);
vertex(positions.chin[16][0], positions.right_eyebrow[2][1]-1.3);
endShape();
//earring
if(this.earringc == 1) {
fill(255, 255, 255);
}
else if (this.earringc == 2) {
fill(pink);
}
else if (this.earringc == 3) {
fill(ear_color);
}
else if (this.earringc == 4) {
fill(yellow);
}
else {
fill(horns_color);
}
ellipse(positions.chin[0][0]-0.3, positions.chin[0][1]-0.1, this.earDist, 0.6);
//fur
if(this.furColor == 1) {
fill(brown);
}
else if (this.furColor == 2) {
fill(pink);
}
else if (this.furColor == 3) {
fill(grey);
}
else if (this.furColor == 4) {
fill(face);
}
else {
fill(horns_color);
}
bezier(positions.chin[0][0]-1.1, positions.chin[0][1]-0.7,positions.chin[0][0]-2, positions.chin[0][1]-this.fur, positions.chin[0][0], positions.chin[0][1], positions.chin[0][0]+1.5, positions.left_eyebrow[2][1]-0.1);
bezier(positions.chin[16][0]+0.9, positions.chin[16][1]-0.7,positions.chin[16][0]+2, positions.chin[16][1]-this.fur, positions.chin[16][0], positions.chin[16][1], positions.chin[16][0]-1.5, positions.right_eyebrow[2][1]-0.1);
//ear
push();
fill(ear_color);
bezier(positions.chin[0][0]-1, positions.chin[0][1]-1,positions.chin[0][0]-2, positions.chin[0][1], positions.chin[0][0], positions.chin[0][1], positions.chin[0][0]+1.5, positions.left_eyebrow[2][1]-0.5);
bezier(positions.chin[16][0]+0.8, positions.chin[16][1]-1,positions.chin[16][0]+2, positions.chin[16][1], positions.chin[16][0], positions.chin[16][1], positions.chin[16][0]-1.5, positions.right_eyebrow[2][1]-0.5);
pop();
// face
if(this.faceColor == 1) {
fill(face);
}
else if (this.faceColor== 2) {
fill(orange);
}
else if (this.faceColor== 3) {
fill(yellow);
}
else if (this.faceColor== 4) {
fill(grey);
}
else {
fill(brown);
}
noStroke();
beginShape();
vertex(positions.chin[0][0]-0.3, positions.chin[0][1]-0.8);
vertex(positions.chin[16][0]-0.3, positions.chin[16][1]-0.8);
vertex(positions.chin[8][0], positions.chin[8][1]);
endShape();
bezier(positions.chin[0][0]-0.3, positions.chin[0][1]-0.79,positions.left_eyebrow[0][0], positions.left_eyebrow[2][1]-1.2, positions.right_eyebrow[4][0], positions.right_eyebrow[2][1]-1.2,positions.chin[16][0]-0.3, positions.chin[16][1]-0.79);
bezier(positions.chin[0][0]-0.29, positions.chin[0][1]-0.8, positions.chin[0][0]-0.4,positions.chin[1][1], positions.chin[7][0], positions.chin[8][1], positions.chin[8][0]+0.01, positions.chin[8][1]);
bezier(positions.chin[16][0]-0.31, positions.chin[16][1]-0.8, positions.chin[16][0]+0.4, positions.chin[15][1], positions.chin[9][0], positions.chin[8][1], positions.chin[8][0]-0.01, positions.chin[8][1]);
//nose bridge
stroke(0);
noFill();
bezier(positions.right_eyebrow[0][0], positions.right_eyebrow[0][1]+0.2, positions.nose_bridge[0][0], positions.nose_bridge[0][1],positions.nose_bridge[2][0]+0.3, positions.nose_bridge[2][1], positions.nose_tip[4][0], positions.nose_tip[4][1]);
bezier(positions.left_eyebrow[4][0], positions.left_eyebrow[4][1]+0.2, positions.nose_bridge[0][0], positions.nose_bridge[0][1],positions.nose_bridge[2][0]+0.3, positions.nose_bridge[2][1], positions.nose_tip[0][0], positions.nose_tip[0][1]);
//up nose
fill(nose_color);
noStroke();
let nose_up = positions.nose_tip[0];
let nose_upr = positions.nose_tip[4];
ellipse(nose_up[0], nose_up[1]+0.3,0.5, 0.3);
ellipse(nose_upr[0], nose_up[1]+0.3,0.5, 0.3);
stroke(2);
noFill();
bezier(positions.nose_tip[0][0]-0.1,positions.nose_tip[0][1]+0.1,positions.nose_tip[2][0],positions.nose_tip[2][1]+0.1,positions.nose_tip[2][0]+0.3,positions.nose_tip[2][1],positions.nose_tip[4][0]+0.1,positions.nose_tip[4][1]+0.1);
//eyebows
let left_eyebrow1 = positions.left_eyebrow[4];
let left_eyebrow2 = positions.left_eyebrow[2];
let left_eyebrow3 = positions.left_eyebrow[0];
let right_eyebrow1 = positions.right_eyebrow[4];
let right_eyebrow2 = positions.right_eyebrow[2];
let right_eyebrow3 = positions.right_eyebrow[0];
noFill();
bezier(left_eyebrow1[0], left_eyebrow1[1], left_eyebrow2[0], left_eyebrow2[1], left_eyebrow2[0], left_eyebrow2[1], left_eyebrow3[0], left_eyebrow3[1]);
bezier(right_eyebrow1[0], right_eyebrow1[1], right_eyebrow2[0], right_eyebrow2[1], right_eyebrow2[0], right_eyebrow2[1], right_eyebrow3[0], right_eyebrow3[1]);
//eyes
stroke(0);
fill(255);
ellipse(positions.left_eye[1][0], positions.left_eye[5][1], 0.8, 0.5);
ellipse(positions.right_eye[2][0], positions.right_eye[4][1], 0.8, 0.5);
noStroke();
fill(0);
ellipse(positions.left_eye[1][0]-this.eyeDist, positions.left_eye[5][1], 0.7, 0.48);
ellipse(positions.right_eye[2][0]-this.eyeDist,positions.right_eye[4][1], 0.7, 0.48);
//mouth
let up_mouth = positions.top_lip[0];
stroke(0);
noFill();
bezier(positions.top_lip[0][0]-this.mouthDist,positions.bottom_lip[5][1],positions.bottom_lip[4][0],positions.bottom_lip[4][1]+0.1, positions.bottom_lip[2][0],positions.bottom_lip[2][1]+0.1, positions.bottom_lip[0][0]+this.mouthDist,positions.bottom_lip[1][1]);
}
this.setProperties = function(settings) {
this.earDist = map(settings[0], 0, 100, 0.1, 0.3);
this.eyeDist = map(settings[1], 0, 100, -0.07, 0.08);
this.faceColor = int(map(settings[2], 0, 100, 0, 4));
this.earringc = int(map(settings[3], 0, 100, 0, 4));
this.mouthDist = map(settings[4], 0, 100, -0.2, 0);
this.fur = map(settings[5], 0, 100, 0, -0.6);
this.furColor = int(map(settings[6], 0, 100, 0, 4));
this.horns = map(settings[7], 0, 100, -0.5, 0.3);
}
this.getProperties = function() {
let settings = new Array(7);
settings[0] = map(this.earDist, 0.1, 0.3, 0, 100);
settings[1] = map(this.eyeDist, -0.05, 0.06, 0, 100);
settings[2] = map(this.faceColor, 0, 4, 0, 100);
settings[3] = map(this.earringc, 0, 4, 0, 100);
settings[4] = map(this.mouthDist, -0.2, -0.1, 0, 100);
settings[5] = map(this.fur, 0, -0.6, 0, 100);
settings[6] = map(this.furColor, 0, 4, 0, 100);
settings[7] = map(this.horns, -0.5, 0.3,0, 100);
return settings;
}
}
{
"000001": [
100,
40.45454545454545,
25,
100,
0,
0,
75,
50
],
"000002": [
34.99999999999999,
50.000000000000014,
50,
25,
88,
34,
75,
35.99999999999999
],
"000005": [
100,
30.909090909090914,
25,
25,
0,
0,
75,
50
],
"000006": [
100,
30.909090909090914,
25,
50,
49,
19,
25,
28.000000000000004
],
"000007": [
56.999999999999986,
45.909090909090914,
0,
50,
49,
100,
25,
15
],
"000009": [
56.999999999999986,
103.18181818181822,
75,
25,
50,
72,
50,
54
],
"000010": [
25.999999999999996,
41.818181818181834,
100,
50,
36.99999999999999,
21.000000000000004,
75,
95
],
"000013": [
25.999999999999996,
35,
100,
50,
147.99999999999997,
21.000000000000004,
75,
95
],
"000014": [
25.999999999999996,
58.18181818181819,
100,
50,
200,
21.000000000000004,
75,
95
],
"000015": [
25.999999999999996,
60.909090909090914,
25,
50,
0,
21.000000000000004,
75,
95
],
"000016": [
25.999999999999996,
-18.181818181818183,
25,
50,
0,
21.000000000000004,
75,
95
],
"000018": [
25.999999999999996,
40.45454545454545,
100,
50,
0,
26,
25,
95
],
"000020": [
25.999999999999996,
36.36363636363637,
100,
0,
0,
100,
0,
0
],
"000023": [
25.999999999999996,
-18.181818181818183,
25,
0,
102,
17,
0,
73.99999999999999
],
"000025": [
25.999999999999996,
58.18181818181819,
25,
0,
200,
38,
25,
65
],
"000028": [
25.999999999999996,
48.63636363636365,
75,
0,
200,
13,
0,
100
],
"000029": [
0,
48.63636363636365,
100,
0,
200,
13,
0,
100
],
"000030": [
17.000000000000004,
48.63636363636365,
50,
0,
200,
13,
0,
100
],
"000031": [
17.000000000000004,
48.63636363636365,
0,
0,
200,
13,
25,
100
],
"000032": [
17.000000000000004,
43.181818181818194,
25,
0,
200,
13,
25,
100
],
"000035": [
17.000000000000004,
40.45454545454545,
50,
0,
200,
13,
100,
100
],
"000037": [
17.000000000000004,
36.36363636363637,
100,
0,
200,
16,
0,
100
],
"000038": [
17.000000000000004,
47.27272727272728,
75,
0,
200,
16,
25,
100
],
"000040": [
37.99999999999999,
47.27272727272728,
25,
100,
104,
0,
25,
94
],
"000041": [
37.99999999999999,
45.909090909090914,
0,
100,
200,
45.00000000000001,
50,
75.00000000000001
],
"000042": [
37.99999999999999,
44.54545454545456,
25,
100,
200,
45.00000000000001,
50,
75.00000000000001
],
"000043": [
37.99999999999999,
43.181818181818194,
25,
100,
200,
45.00000000000001,
50,
75.00000000000001
],
"000044": [
37.99999999999999,
40.45454545454545,
25,
100,
200,
45.00000000000001,
0,
75.00000000000001
],
"000045": [
37.99999999999999,
36.36363636363637,
25,
100,
200,
45.00000000000001,
75,
75.00000000000001
],
"000047": [
37.99999999999999,
30.909090909090914,
0,
0,
200,
45.00000000000001,
75,
75.00000000000001
],
"000048": [
37.99999999999999,
14.545454545454545,
25,
0,
200,
100,
75,
0
],
"000050": [
37.99999999999999,
70.45454545454547,
75,
100,
200,
19,
25,
0
],
"000051": [
37.99999999999999,
48.63636363636365,
25,
100,
200,
19,
25,
85
],
"000052": [
37.99999999999999,
29.545454545454547,
50,
75,
200,
35,
0,
85
],
"000054": [
37.99999999999999,
43.181818181818194,
25,
50,
128,
33,
75,
85
],
"000055": [
37.99999999999999,
45.909090909090914,
25,
50,
0,
33,
75,
85
],
"000056": [
37.99999999999999,
56.818181818181834,
100,
50,
200,
42.00000000000001,
0,
85
],
"000058": [
37.99999999999999,
39.090909090909086,
100,
50,
200,
42.00000000000001,
0,
85
],
"000060": [
37.99999999999999,
62.27272727272728,
0,
50,
40.00000000000001,
19,
25,
56.00000000000001
],
"000064": [
100,
48.63636363636365,
25,
50,
80.00000000000001,
19,
25,
56.00000000000001
],
"000065": [
100,
48.63636363636365,
25,
50,
160.00000000000003,
19,
25,
56.00000000000001
],
"000068": [
100,
50.000000000000014,
0,
0,
49.999999999999986,
19,
75,
56.00000000000001
],
"000069": [
100,
50.000000000000014,
0,
0,
100,
19,
75,
56.00000000000001
],
"000071": [
100,
40.45454545454545,
100,
0,
200,
30,
25,
100
],
"000073": [
100,
51.36363636363637,
100,
50,
200,
30,
25,
100
],
"000076": [
100,
51.36363636363637,
100,
50,
200,
30,
0,
100
],
"000077": [
100,
28.181818181818187,
75,
50,
200,
30,
25,
100
],
"000078": [
100,
45.909090909090914,
75,
50,
200,
30,
25,
100
],
"000079": [
100,
40.45454545454545,
75,
50,
200,
30,
25,
100
],
"000080": [
100,
85.45454545454547,
75,
50,
200,
30,
25,
100
],
"000081": [
100,
54.0909090909091,
25,
50,
200,
6,
50,
72.99999999999999
],
"000083": [
100,
55.45454545454547,
50,
25,
0,
35,
0,
100
],
"000085": [
100,
56.818181818181834,
50,
25,
0,
35,
0,
100
],
"000086": [
100,
107.2727272727273,
0,
25,
0,
35,
0,
100
],
"000088": [
100,
28.181818181818187,
0,
25,
0,
35,
0,
100
],
"000091": [
100,
20.000000000000004,
0,
75,
200,
69,
100,
100
],
"000092": [
100,
63.63636363636365,
50,
75,
200,
69,
100,
100
],
"000096": [
100,
69.09090909090911,
75,
75,
0,
69,
100,
100
],
"000097": [
100,
36.36363636363637,
75,
75,
0,
69,
100,
100
],
"000099": [
100,
33.63636363636364,
25,
0,
0,
17,
0,
100
],
"000100": [
100,
51.36363636363637,
25,
0,
0,
59,
50,
39.00000000000001
],
"000103": [
100,
60.909090909090914,
50,
50,
76.00000000000001,
49,
75,
87
],
"000104": [
100,
47.27272727272728,
100,
50,
152.00000000000003,
49,
75,
87
],
"000106": [
56.999999999999986,
45.909090909090914,
0,
50,
16.000000000000014,
47,
0,
56.99999999999999
],
"000108": [
56.999999999999986,
44.54545454545456,
0,
50,
32,
47,
75,
56.99999999999999
],
"000109": [
56.999999999999986,
43.181818181818194,
0,
50,
64,
47,
100,
56.99999999999999
],
"000110": [
35.99999999999999,
60.909090909090914,
50,
50,
128,
81,
25,
56.99999999999999
],
"000111": [
35.99999999999999,
-18.181818181818183,
50,
50,
23.999999999999993,
30,
0,
56.99999999999999
],
"000114": [
35.99999999999999,
50.000000000000014,
50,
50,
47.999999999999986,
54,
25,
56.99999999999999
],
"000115": [
35.99999999999999,
44.54545454545456,
25,
50,
96,
33,
50,
56.99999999999999
],
"000116": [
35.99999999999999,
45.909090909090914,
25,
25,
47.999999999999986,
54,
50,
56.99999999999999
],
"000117": [
35.99999999999999,
44.54545454545456,
50,
25,
96,
54,
0,
56.99999999999999
],
"000118": [
35.99999999999999,
95,
50,
25,
192,
54,
0,
56.99999999999999
],
"000121": [
35.99999999999999,
36.36363636363637,
50,
25,
200,
54,
0,
56.99999999999999
],
"000122": [
35.99999999999999,
30.909090909090914,
100,
25,
200,
54,
25,
56.99999999999999
],
"000125": [
35.99999999999999,
55.45454545454547,
75,
25,
200,
54,
75,
56.99999999999999
],
"000126": [
35.99999999999999,
56.818181818181834,
25,
25,
0,
36,
0,
56.99999999999999
],
"000129": [
35.99999999999999,
-18.181818181818183,
25,
50,
113.99999999999999,
56.99999999999999,
0,
56.99999999999999
],
"000131": [
35.99999999999999,
-18.181818181818183,
25,
50,
200,
56.99999999999999,
0,
56.99999999999999
],
"000132": [
35.99999999999999,
-18.181818181818183,
50,
50,
38.00000000000001,
56.99999999999999,
0,
56.99999999999999
],
"000133": [
100,
-18.181818181818183,
0,
50,
139.99999999999997,
34,
0,
56.99999999999999
],
"000134": [
100,
118.18181818181819,
0,
50,
200,
34,
0,
56.99999999999999
],
"000135": [
100,
-18.181818181818183,
100,
50,
46.000000000000014,
34,
75,
56.99999999999999
],
"000137": [
100,
-18.181818181818183,
25,
50,
92,
34,
75,
56.99999999999999
],
"000140": [
100,
66.36363636363637,
50,
50,
145.99999999999997,
34,
50,
56.99999999999999
],
"000142": [
100,
71.81818181818184,
0,
50,
0,
0,
25,
89
],
"000143": [
53.000000000000014,
44.54545454545456,
50,
50,
0,
0,
25,
89
],
"000145": [
53.000000000000014,
43.181818181818194,
75,
75,
94,
48,
75,
89
],
"000146": [
100,
40.45454545454545,
50,
25,
188,
48,
75,
100
],
"000147": [
100,
59.54545454545455,
25,
25,
86,
48,
75,
100
],
"000148": [
100,
63.63636363636365,
100,
25,
100,
64,
100,
100
],
"000150": [
100,
69.09090909090911,
0,
25,
200,
64,
100,
100
],
"000151": [
70,
50.000000000000014,
50,
25,
0,
51,
50,
100
],
"000152": [
70,
50.000000000000014,
50,
25,
0,
51,
50,
100
],
"000153": [
70,
50.000000000000014,
100,
25,
0,
51,
50,
100
],
"000155": [
70,
50.000000000000014,
100,
25,
0,
73,
75,
100
],
"000156": [
24.999999999999996,
37.727272727272734,
0,
25,
0,
49,
100,
100
],
"000157": [
24.999999999999996,
33.63636363636364,
0,
25,
0,
49,
100,
100
],
"000160": [
24.999999999999996,
28.181818181818187,
75,
25,
36.00000000000001,
80,
50,
100
],
"000161": [
24.999999999999996,
48.63636363636365,
25,
25,
72.00000000000001,
80,
75,
100
]
}
function drawCrown() { //function to draw a crown
var pineappleShade = color(237, 159, 0);
var crownColor = color(230, 175, 11);
fill(pineappleShade);
triangle(width/2.05, height/5.5, width/1.98, height/7.3, width/1.93, height/5.5); //crown
fill(crownColor);
triangle(width/2.1, height/5.5, width/2.04, height/6.9, width/1.99, height/5.5);
triangle(width/1.98, height/5.5, width/1.93, height/6.9, width/1.88, height/5.5);
}
function drawLine() { //function draws one rectangle for the fence
fill(70);
rect(width/100, height/2.02, width/120, height/8);
}
function drawClouds() { //draws clouds in the background
var cloudColor = color(242, 242, 242);
fill(cloudColor);
ellipse(width/18, height/5.8, width/14, height/14);
ellipse(width/10, height/6, width/12, height/9);
ellipse(width/7, height/5.6, width/14, height/16);
ellipse(width/5.8, height/5.3, width/18, height/30);
}
function drawpineLines() { //function draws pineapple lines
var pineappleLines = color(227, 155, 0);
push();
stroke(pineappleLines);
noFill();
strokeWeight(width/100);
line(width/5.4, height/4.6, width/3.99, height/3.1);
line(width/7, height/3.97, width/4.19, height/2.45);
line(width/7.62, height/3.03, width/5.09, height/2.25);
line(width/5.1, height/4.6, width/7.62, height/3.05);
line(width/4.23, height/4.03, width/6.87, height/2.4);
line(width/3.99, height/3.05, width/5.4, height/2.25);
pop();
}
function drawLeaf() { //draws pineapple leaves
var leafColor = color(73, 135, 37);
var leafShade = color(63, 107, 21);
push();
stroke(leafColor);
strokeWeight(width/30);
line(width/5.2, height/6.8, width/5.25, height/3);
strokeWeight(width/60);
line(width/5.2, height/8.5, width/5.25, height/3);
stroke(leafShade);
strokeWeight(width/30);
line(width/6, height/5.3, width/5.25, height/3);
strokeWeight(width/65);
line(width/6.2, height/6.4, width/5.25, height/3);
strokeWeight(width/30);
line(width/4.6, height/5.3, width/5.25, height/3);
strokeWeight(width/65);
line(width/4.45, height/6.4, width/5.25, height/3);
pop();
}
function huang_draw_one_frame(cur_frac) {
// note: to clear the screen draw a rectangle
// that is width x height - like this
noStroke();
fill(156, 200, 255); //background colour
rect(0, 0, width, height);
// note: all shape sizes, line widths, etc. should be a
// function of width and height
let rect_width = height / 10.0;
let half_width = rect_width / 2;
// note: animation should progress depending on the
// value of cur_frac which goes from 0 to 1, and it
// should loop seamlessly
let cur_x = map(cur_frac, 0, 1, 0, width) - half_width;
//colour variables
var grassColor = color(69, 153, 74);
var bushColor = color(21, 130, 27);
var pillarColor = color(235, 231, 223);
var pathColor = color(247, 201, 94);
var castleColor = color(222, 212, 189);
var castleShade = color(194, 187, 172);
var castleShadeDark = color(156, 151, 142);
var castleDoor = color(77, 64, 53);
var pineappleColor = color(255, 174, 0);
var pineappleLines = color(227, 155, 0);
var pineappleShade = color(237, 159, 0);
var leafColor = color(73, 135, 37);
var leafShade = color(63, 107, 21);
var crownColor = color(230, 175, 11);
//mapping the clouds
let cloudsMove;
if (cur_frac > 0.5) {
cloudsMove = map(cur_frac, 0, 0.5, width/-16, width/-14);
} else {
cloudsMove = map(cur_frac, 0.5, 1, width/-14, width/-16);
}
let cloudsMoveLeft;
if (cur_frac > 0.5) {
cloudsMoveLeft = map(cur_frac, 0, 0.5, width/2.4, width/2.3);
} else {
cloudsMoveLeft = map(cur_frac, 0.5, 1, width/2.3, width/2.4);
}
let cloudsMoveRight;
if (cur_frac > 0.5) {
cloudsMoveRight = map(cur_frac, 0, 0.5, width/0.72, width/0.715);
} else {
cloudsMoveRight = map(cur_frac, 0.5, 1, width/0.715, width/0.72);
}
let cloudsRightSmall;
if (cur_frac > 0.5) {
cloudsRightSmall = map(cur_frac, 0, 0.5, width/0.535, width/0.54);
} else {
cloudsRightSmall = map(cur_frac, 0.5, 1, width/0.54, width/0.535);
}
//draws clouds
push();
scale(0.6);
translate(cloudsMove, height/5);
drawClouds();
pop();
push();
scale(0.4);
translate(cloudsMoveLeft, height/8);
drawClouds();
pop();
push();
scale(0.65);
translate(cloudsMoveRight, height/5);
drawClouds();
pop();
push();
scale(0.4);
translate(cloudsRightSmall, height/8);
drawClouds();
pop();
//draws castle
fill(castleShade);
rect(width/2.5, height/30, height/12, height/12); //castle's top bricks
rect(width/2.09, height/30, height/12, height/12);
rect(width/1.8, height/30, height/12, height/12);
fill(pillarColor);
rect(width/2.5, height/30, height/12, height/100); //castle's top bricks (darker)
rect(width/2.09, height/30, height/12, height/100);
rect(width/1.8, height/30, height/12, height/100);
fill(castleShadeDark);
stroke(0, 100);
strokeWeight(height/300);
rect(width/3.23, height/6, width/18, height/3);
rect(width/1.57, height/6, width/18, height/3);
noStroke();
fill(pathColor);
triangle(width/3.23, height/6, width/2.95, height/12, width/2.74, height/6);
triangle(width/1.57, height/6, width/1.5, height/12, width/1.444, height/6);
fill(castleShade);
rect(width/4.05, height/3, width/1.98, height/4.5); //back wall
fill(pillarColor);
rect(width/4.05, height/3, width/1.98, height/100);
fill(castleShade);
rect(width/2.44, height/12, width/5.5, height/2.8);
fill(castleColor);
rect(width/2.32, height/2.8, width/7, height/4); //front door wall
fill(castleShade);
rect(width/2.32, height/2.8, width/7, height/100);
stroke(0, 100);
strokeWeight(height/300);
rect(width/2.74, height/3.2, width/15, height/3);
rect(width/1.75, height/3.2, width/15, height/3);
noStroke();
fill(pathColor);
triangle(width/2.74, height/3.2, width/2.52, height/4.5, width/2.312, height/3.2);
triangle(width/1.75, height/3.2, width/1.65, height/4.5, width/1.565, height/3.2);
fill(castleDoor);
stroke(30, 90);
strokeWeight(height/140);
ellipse(width/1.998, height/2, width/16, height/5); //castle door
noStroke();
fill(80);
rect(width/2.157, height/12, width/280, height/8); //castle flag straps
rect(width/1.87, height/12, width/280, height/8);
fill(pathColor);
rect(width/2.245, height/8.6, width/8.8, height/4.6); //castle flag
fill(pillarColor);
rect(width/2.2, height/8.6, width/65, height/4.6); //flag stripes
rect(width/1.874, height/8.6, width/65, height/4.6);
fill(castleShadeDark);
rect(width/2.82, height/2.7, width/45, height/50); //castle brick
rect(width/2.82, height/2.4, width/45, height/50);
rect(width/2.82, height/2.17, width/45, height/50);
rect(width/1.596, height/2.7, width/45, height/50); //castle brick
rect(width/1.596, height/2.4, width/45, height/50);
rect(width/1.596, height/2.17, width/45, height/50);
fill(castleShadeDark);
rect(width/2.45, height/7, width/55, height/60);
rect(width/1.74, height/4.6, width/55, height/60);
//draws pineapple on flag
stroke(pineappleShade);
strokeWeight(width/52);
line(width/2.05, height/3.43, width/2.05, height/3.5); //leg
line(width/1.935, height/3.43, width/1.935, height/3.5);
line(width/2.15, height/4.6, width/1.94, height/4); //hand
line(width/1.9, height/4.35, width/1.85, height/4.6);
fill(pineappleColor);
noStroke();
rect(width/2.13, height/6, width/15, height/8, width/35); //head
push();
scale(0.5);
translate(width/1.228, height/7.7);
drawpineLines();
pop();
fill(30);
ellipse(width/2.028, height/4.5, height/48); //eyes
ellipse(width/1.95, height/4.5, height/48);
arc(width/1.988, height/4.2, width/60, width/60, 0, PI, CHORD); //mouth
push();
translate(-1.5, -1);
drawCrown(); //crown
pop();
stroke(30);
strokeWeight(width/150);
line(width/2.15, height/5.6, width/2.17, height/3.8); //staff stick
line(width/1.855, height/5.6, width/1.833, height/3.8);
noStroke();
fill(leafShade);
ellipse(width/2.15, height/5.6, height/30); //staff orb
ellipse(width/1.855, height/5.6, height/30);
fill(leafColor)
ellipse(width/2.15, height/5.6, height/80);
ellipse(width/1.855, height/5.6, height/80);
//draws fence lines
for (let i=0; i<7; i++) { //for loop to add more fence lines
push();
translate(width/8*(i-1.03)/1.5, 0);
drawLine();
pop();
}
for (let i=0; i<7; i++) {
push();
translate(width/8*(i-1.03)/1.5, 0);
translate(width/1.545, 0);
drawLine();
pop();
}
//draws fence
fill(60);
rect(width/-50, height/2.05, width/2.21, height/100);
rect(width/1.75, height/2.05, width/2.21, height/100);
let lightOn; //mapping light size
if (cur_frac < 0.5) {
lightOn = map(cur_frac, 0, 0.5, height/35, height/18);
} else {
lightOn = map(cur_frac, 0.5, 1, height/18, height/35);
}
//draw glowing staff orb
fill(63, 107, 21, 100);
ellipse(width/1.855, height/5.6, lightOn);
fill(73, 135, 37, 240);
stroke(63, 107, 21, 150);
strokeWeight(height/100);
ellipse(width/1.855, height/5.6, height/35);
noStroke();
fill(63, 107, 21, 100);
ellipse(width/2.15, height/5.6, lightOn);
fill(73, 135, 37, 240);
stroke(63, 107, 21, 150);
strokeWeight(height/100);
ellipse(width/2.15, height/5.6, height/35);
noStroke();
//draws grass
fill(grassColor);
stroke(leafShade);
strokeWeight(1);
rect(0, height/1.8, width, height/2);
noStroke();
//draws perspective path
fill(pathColor);
stroke(pineappleShade);
strokeWeight(1);
beginShape();
vertex(width/2.1, height/1.798);
vertex(width/1.905, height/1.798);
vertex(width/1.5, height);
vertex(width/2.77, height);
endShape(CLOSE);
noStroke();
//draws pillars
fill(pillarColor);
stroke(170);
strokeWeight(2);
rect(width/7.2, height/1.8, width/10, height/2); //left side pillars
noStroke();
rect(width/7.2, height/2.02, width/10, height/50);
fill(pathColor); //flag on pillar
stroke(pineappleColor);
strokeWeight(width/120);
rect(width/6.45, height/1.8, width/15, height/3.5);
noStroke();
fill(220);
rect(width/7.9, height/1.97, width/8, height/12);
fill(pillarColor);
stroke(170);
strokeWeight(2);
rect(width/1.312, height/1.8, width/10, height/2); //right side pillars
noStroke();
rect(width/1.312, height/2.02, width/10, height/50);
fill(pathColor);
stroke(pineappleColor);
strokeWeight(width/120);
rect(width/1.284, height/1.8, width/15, height/3.5);
noStroke();
fill(220);
rect(width/1.335, height/1.97, width/8, height/12);
push();
scale(0.8);
translate(width/-3.725, height/1.3); //draws crown on flag
drawCrown();
pop();
push();
scale(0.8);
translate(width/1.953, height/1.3);
drawCrown();
pop();
//draws bushes in the corners
fill(bushColor);
ellipse(width/30, height/1.2, width/6); //left side bushes
ellipse(width/10, height/1.1, width/5);
ellipse(width/4.5, height/1, width/8);
ellipse(width/30, height/1, width/8);
ellipse(width, height/1.08, width/4); //right side bushes
ellipse(width/1.15, height/1.07, width/7);
ellipse(width/1.25, height, width/8);
//maps for the pineapple
let leftLeg;
if(cur_frac < 0.5) {
leftLeg = map(cur_frac, 0, 0.5, height/3, height/2.73);
} else {
leftLeg = map(cur_frac, 0.5, 1, height/2.73, height/3);
}
let rightLeg;
if(cur_frac > 0.5) {
rightLeg = map(cur_frac, 0, 0.5, height/3.1, height/2.89);
} else {
rightLeg = map(cur_frac, 0.5, 1, height/2.89, height/3.1);
}
let eyesClose;
if (cur_frac > 0.85) {
eyesClose = map(cur_frac, 0, 1, width/45, width/500);
}
let headShake;
if (cur_frac > 0.5) {
headShake = map(cur_frac, 0, 0.5, height/4.3, height/4.6);
} else {
headShake = map(cur_frac, 0.5, 1, height/4.6, height/4.3);
}
let eyeShake;
if (cur_frac > 0.5) {
eyeShake = map(cur_frac, 0, 0.5, height/2.9, height/3.1);
} else {
eyeShake = map(cur_frac, 0.5, 1, height/3.1, height/2.9);
}
let mouthShake;
if (cur_frac > 0.5) {
mouthShake = map(cur_frac, 0, 0.5, height/2.7, height/2.85);
} else {
mouthShake = map(cur_frac, 0.5, 1, height/2.85, height/2.7);
}
let longHand;
if (cur_frac > 0.5) {
longHand = map(cur_frac, 0, 0.5, height/2.8, height/3.1);
} else {
longHand = map(cur_frac, 0.5, 1, height/3.1, height/2.8);
}
let pineLines;
if(cur_frac < 0.5) {
pineLines = map(cur_frac, 0, 0.5, width/-250, width/200);
} else {
pineLines = map(cur_frac, 0.5, 1, width/200, width/-250);
}
let pineLeaf;
if (cur_frac < 0.5) {
pineLeaf = map(cur_frac, 0, 0.5, 0, 10);
} else {
pineLeaf = map(cur_frac, 0.5, 1, 10, 0);
}
//draws pineapples
push();
translate(0, pineLeaf) //moves leaves with head
drawLeaf(); //calls draw leaf function
pop();
push();
translate(width/1.613, pineLeaf)
drawLeaf();
pop();
fill(pineappleShade);
rect(width/6.7, leftLeg, width/29, height/7.5, width/8); //draws legs on left
rect(width/5.1, rightLeg, width/29, height/7.5, width/8);
rect(width/1.298, leftLeg, width/29, height/7.5, width/8); //draws legs on right
rect(width/1.224, rightLeg, width/29, height/7.5, width/8);
push();
stroke(pineappleShade)
strokeWeight(width/35);
line(width/9.2, longHand, width/7, height/3.05); //draws hands on left
line(width/4.2, height/3.05, width/3.66, longHand);
pop();
push();
stroke(pineappleShade)
strokeWeight(width/35);
line(width/1.38, longHand, width/1.3, height/3.05); //draws hands on right
line(width/1.19, height/3.05, width/1.119, longHand);
pop();
fill(pineappleColor);
rect(width/7.9, headShake, width/7.8, height/4.1, width/18); //draws head on left
rect(width/1.34, headShake, width/7.8, height/4.1, width/18); //draws head on right
push();
translate(0, pineLines); //moves lines with head
drawpineLines(); //calls draw pineapple line function
pop();
push();
translate(width/1.615, pineLines);
drawpineLines();
pop();
fill(40);
ellipse(width/1.268, eyeShake, width/45, eyesClose); //draws eyes on left
ellipse(width/1.203, eyeShake, width/45, eyesClose);
ellipse(width/5.9, eyeShake, width/45, eyesClose); //draws eyes on right
ellipse(width/4.7, eyeShake, width/45, eyesClose);
angleMode(RADIANS);
arc(width/5.23, mouthShake, width/35, width/35, 0, PI, CHORD); //draws mouth on left
arc(width/1.233, mouthShake, width/35, width/35, 0, PI, CHORD); //draws mouth on right
// note: you can draw optional things depending on "debugView"
if (debugView) {
}
}
// remove this or set to false to enable full program (load will be slower)
// var DEBUG_MODE = true;
// tto set the number of sliders to show
var NUM_SLIDERS = 7;
//given a segment, this returns the average point of [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i=0; i<s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len, sum_y / s_len];
}
function drawSpots() { // draws the spots for the males
noStroke();
ellipse(0, -2.1, 0.22);
ellipse(-0.2, -1.8, 0.22);
ellipse(0.2, -1.8, 0.22);
}
function drawBlush() { //draws the blush for females
noFill();
strokeWeight(0.1);
ellipse(-1, 0, 0.3);
ellipse(1, 0, 0.3);
strokeWeight(0.05);
line(-1.2, 0, -0.8, 0);
line(0.8, 0, 1.2, 0);
}
// colour variables
// const bg_color = [225, 206, 187];
// const fg_color = [151, 102, 52];
// const stroke_color = [95, 52, 8];
// defines face object
function HuangFace() {
// face variables
this.faceColor = 0; //range is 0 to 1
this.blackEye = 0.5; //Black eyeSize range is 0.05 to 0.9
this.eyeSize = 0.5 //White eyeSuze range is 0.2 to 0.5
this.earShape = 1; //range is 0.6 to 1.5
this.antennaColor = 0; //range is 0 to 1
this.showBlush = 0; //range is 0 to 1
this.showSpots = 0; //range is 0 to 1
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
//positions for the face
let face_left = positions.chin[4];
let face_chin = positions.chin[8];
let face_right = positions.chin[16];
let right_cheek = positions.chin[2];
let left_cheek = positions.chin[4];
//determines face colour by sliders
if(this.faceColor == 0) {
strokeWeight(0.2);
stroke(255);
fill(0);
} else if (this.faceColor == 1) {
strokeWeight(0.2);
stroke(0);
fill(255);
}
//custom head shape based on chin positions
beginShape();
vertex(face_left[0]-0.4, -0.7)
bezierVertex(-2.5, -4, 2, -4.5, face_right[0], -1);
bezierVertex(face_right[0], face_chin[0], 0, 5, face_left[0]-0.4, -0.7);
endShape();
//shows blush for females
//if statement determines if blush is black or white depending on face colour
if (this.faceColor == 0 && this.showBlush == 1) {
push();
fill(50);
drawSpots();
pop();
} else if (this.faceColor == 1 && this.showBlush == 1) {
push();
fill(0);
drawSpots();
pop();
}
//gets average of the eyes
fill(150);
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye);
ellipse(left_eye_pos[0], left_eye_pos[1], 0.1);
ellipse(right_eye_pos[0], right_eye_pos[1], 0.1);
//draws eyes
let blackEye = map(this.eyeSize, 5, 100, 2, 4); //mapping eye boundary
noStroke();
fill(0);
ellipse(left_eye_pos[0], left_eye_pos[1], this.blackEye); //size of eye is random
ellipse(right_eye_pos[0], right_eye_pos[1], this.blackEye);
fill(255);
ellipse(left_eye_pos[0], left_eye_pos[1], this.eyeSize);
ellipse(right_eye_pos[0], right_eye_pos[1], this.eyeSize);
//positions for the nose
let nose_top = positions.nose_bridge[0];
let nose_bottom = positions.nose_bridge[3];
let nose_middle = positions.nose_tip[0];
//draws nose
noFill();
stroke(0);
strokeWeight(0.2);
curve(nose_top[0], nose_top[1], nose_top[0]-0.3, nose_top[1]+0.5, nose_bottom[0]+0.3, nose_bottom[1], nose_middle[0]+3, nose_middle[1]-5);
//shows spots for males
//if statement determines if spots are black or white depending on face colour
if (this.faceColor == 0 && this.showSpots == 1) {
push();
stroke(255);
drawBlush();
pop();
} else if (this.faceColor == 1 && this.showSpots == 1) {
push();
stroke(0);
drawBlush();
pop();
}
//positions for the mouth
let mouth_left = positions.top_lip[0];
let mouth_right = positions.bottom_lip[0];
let mouth_middle = positions.bottom_lip[3];
//draws mouth
if(this.faceColor == 0) {
stroke(255);
} else {
stroke(0);
}
strokeWeight(0.2);
curve(0, 0, mouth_left[0], mouth_left[1], mouth_right[0], mouth_right[1], mouth_middle[0]+2, mouth_middle[1]-2);
//if statement determines if antennas are black or white
if(this.antennaColor == 0) {
stroke(255);
fill(0);
} else if (this.antennaColor == 1) {
stroke(0);
fill(255);
}
//draws ears
rotate(-20, 0);
ellipse(0, -2.8, 0.5, this.earShape); //changes the height of the ears
ellipse(0, -3.8, 1, 0.4);
rotate(45, 0);
ellipse(0.1, -2.8, 0.5, this.earShape);
ellipse(0.1, -3.8, 1, 0.4);
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.faceColor = int(map(settings[0], 0, 100, 0, 1));
this.blackEye = (map(settings[1], 0, 100, 0.05, 0.9));
this.eyeSize = map(settings[2], 0, 100, 0.2, 0.5);
this.earShape = map(settings[3], 0, 100, 0.6, 1.5);
this.antennaColor = int(map(settings[4], 0, 100, 0, 1));
this.showBlush = int(map(settings[5], 0, 100, 0, 1));
this.showSpots = int(map(settings[6], 0, 100, 0, 1));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(7);
settings[0] = map(this.faceColor, 0, 1, 0, 100);
settings[1] = map(this.blackEye, 0.05, 0.9, 0, 100);
settings[2] = map(this.eyeSize, 0.2, 0.5, 0, 100);
settings[3] = map(this.earShape, 0.6, 1.5, 0, 100);
settings[4] = map(this.antennaColor, 0, 1, 0, 100);
settings[5] = map(this.showBlush, 0, 1, 0, 100);
settings[6] = map(this.showSpots, 0, 1, 0, 100);
return settings;
}
}
{
"000001": [
100,
51,
13.000000000000004,
100,
100,
0,
100
],
"000002": [
100,
73,
13.000000000000004,
100,
100,
0,
100
],
"000005": [
100,
75,
32.000000000000014,
60.00000000000002,
100,
0,
100
],
"000006": [
100,
51,
5.000000000000004,
100,
100,
0,
100
],
"000007": [
100,
66,
0,
40,
0,
100,
0
],
"000009": [
100,
64,
0,
100,
0,
0,
100
],
"000010": [
100,
75,
60,
43,
100,
0,
100
],
"000013": [
100,
47,
21.000000000000004,
11.999999999999998,
100,
100,
0
],
"000014": [
0,
64,
49.999999999999986,
16,
0,
0,
100
],
"000015": [
100,
48,
0,
25.999999999999996,
0,
100,
0
],
"000016": [
100,
48,
0,
25.999999999999996,
0,
100,
0
],
"000018": [
100,
56.99999999999999,
6.999999999999998,
65.99999999999999,
100,
0,
100
],
"000020": [
100,
47,
0,
65.99999999999999,
0,
100,
0
],
"000023": [
100,
47,
28.000000000000007,
24.999999999999996,
0,
100,
0
],
"000025": [
100,
47,
4.0000000000000036,
18.000000000000004,
0,
100,
0
],
"000028": [
100,
56.00000000000001,
5.000000000000004,
100,
100,
0,
100
],
"000029": [
100,
70,
40,
100,
100,
0,
100
],
"000030": [
100,
67,
0,
43,
100,
100,
0
],
"000031": [
100,
67,
37,
54.99999999999999,
0,
0,
100
],
"000032": [
100,
53.000000000000014,
7.999999999999999,
30,
100,
100,
0
],
"000035": [
100,
67,
0,
100,
0,
0,
100
],
"000037": [
0,
38,
22.000000000000004,
0,
0,
100,
0
],
"000038": [
100,
51,
29.00000000000001,
22.000000000000007,
0,
100,
0
],
"000040": [
100,
54,
0,
44.99999999999999,
0,
0,
100
],
"000041": [
100,
54,
0,
35,
0,
100,
0
],
"000042": [
100,
70,
51.99999999999999,
48.99999999999999,
100,
0,
100
],
"000043": [
100,
70,
31.00000000000001,
100,
0,
0,
100
],
"000044": [
0,
70,
39,
100,
0,
0,
100
],
"000045": [
100,
57.99999999999999,
13.000000000000004,
100,
100,
0,
100
],
"000047": [
100,
47,
0,
100,
0,
0,
100
],
"000048": [
100,
47,
0,
37.00000000000001,
0,
100,
0
],
"000051": [
100,
55.000000000000014,
0,
0,
100,
100,
0
],
"000050": [
100,
55.000000000000014,
0,
15,
0,
100,
0
],
"000052": [
100,
55.000000000000014,
23.000000000000004,
18.000000000000004,
0,
100,
0
],
"000054": [
100,
55.000000000000014,
23.000000000000004,
100,
100,
0,
100
],
"000055": [
100,
54,
5.9999999999999964,
28.000000000000014,
0,
100,
0
],
"000056": [
100,
56.00000000000001,
0,
44,
0,
100,
0
],
"000058": [
100,
61,
25.000000000000007,
100,
0,
0,
100
],
"000060": [
0,
61,
25.000000000000007,
0,
0,
100,
0
],
"000064": [
100,
45,
0,
19.000000000000004,
0,
100,
0
],
"000065": [
100,
56.99999999999999,
6.999999999999998,
31,
0,
100,
0
],
"000068": [
100,
55.000000000000014,
13.000000000000004,
31,
100,
100,
0
],
"000069": [
100,
55.000000000000014,
26.000000000000007,
18.000000000000004,
0,
100,
0
],
"000071": [
100,
61,
26.000000000000007,
40,
100,
0,
100
],
"000073": [
100,
61,
26.000000000000007,
100,
0,
0,
100
],
"000076": [
100,
56.99999999999999,
14.000000000000004,
44,
0,
100,
0
],
"000077": [
100,
59,
14.000000000000004,
100,
0,
0,
100
],
"000078": [
100,
74,
38,
100,
0,
0,
100
],
"000079": [
100,
54,
14.999999999999996,
0,
100,
100,
0
],
"000080": [
100,
54,
14.000000000000004,
23.999999999999996,
0,
100,
0
],
"000081": [
100,
54,
14.000000000000004,
23.999999999999996,
0,
100,
0
],
"000083": [
100,
54,
14.000000000000004,
100,
100,
0,
100
],
"000085": [
100,
56.00000000000001,
19,
100,
100,
0,
100
],
"000086": [
100,
56.00000000000001,
19,
2.0000000000000018,
100,
0,
100
],
"000088": [
100,
56.00000000000001,
0,
100,
100,
0,
100
],
"000091": [
100,
43,
0,
35.99999999999999,
0,
100,
0
],
"000092": [
100,
51,
18,
50.000000000000014,
100,
0,
100
],
"000096": [
100,
50,
18,
100,
0,
0,
100
],
"000097": [
100,
62,
60,
100,
100,
0,
100
],
"000099": [
100,
52,
37,
100,
100,
0,
100
],
"000100": [
100,
52,
37,
46.99999999999999,
100,
0,
100
],
"000103": [
100,
66,
52.99999999999999,
100,
0,
0,
100
],
"000104": [
100,
51,
38,
28.000000000000014,
100,
100,
0
],
"000106": [
100,
51,
9,
28.000000000000014,
100,
0,
100
],
"000108": [
100,
51,
45.00000000000001,
57.999999999999986,
100,
0,
100
],
"000109": [
100,
51,
45.00000000000001,
30,
100,
100,
0
],
"000110": [
100,
51,
45.00000000000001,
50.99999999999999,
100,
0,
100
],
"000111": [
100,
50,
20,
50.99999999999999,
100,
0,
100
],
"000114": [
100,
63,
7.999999999999999,
33,
0,
100,
0
],
"000115": [
100,
55.000000000000014,
7.999999999999999,
0,
100,
100,
0
],
"000116": [
100,
55.000000000000014,
7.999999999999999,
17,
0,
100,
0
],
"000117": [
0,
55.000000000000014,
47.999999999999986,
100,
0,
0,
100
],
"000118": [
100,
60,
19,
50.99999999999999,
0,
0,
100
],
"000121": [
100,
55.000000000000014,
15.999999999999998,
100,
0,
0,
100
],
"000122": [
100,
52,
5.000000000000004,
25.999999999999996,
100,
0,
100
],
"000125": [
100,
52,
31.00000000000001,
0,
100,
100,
0
],
"000126": [
100,
60,
51.99999999999999,
100,
100,
0,
100
],
"000129": [
100,
54,
41,
37.99999999999999,
0,
100,
0
],
"000131": [
0,
52,
0,
74,
0,
0,
100
],
"000132": [
0,
52,
26.000000000000007,
100,
0,
0,
100
],
"000133": [
100,
68,
74.00000000000001,
41,
100,
0,
100
],
"000134": [
0,
68,
14.999999999999996,
0,
0,
100,
0
],
"000135": [
0,
68,
28.000000000000007,
44,
0,
100,
0
],
"000137": [
100,
51,
15.999999999999998,
15,
0,
100,
0
],
"000140": [
100,
59,
40,
100,
100,
0,
100
],
"000142": [
100,
59,
40,
100,
0,
0,
100
],
"000143": [
100,
59,
46.00000000000001,
32,
0,
100,
0
],
"000145": [
100,
44,
1.0000000000000009,
100,
0,
0,
100
],
"000146": [
100,
44,
1.0000000000000009,
100,
100,
0,
100
],
"000147": [
100,
55.000000000000014,
42.00000000000001,
100,
100,
0,
100
],
"000148": [
100,
49,
30.00000000000001,
41,
0,
0,
100
],
"000150": [
100,
49,
19,
41,
100,
100,
0
],
"000151": [
100,
49,
0,
100,
0,
0,
100
],
"000152": [
100,
49,
30.00000000000001,
18.000000000000004,
0,
100,
0
],
"000153": [
100,
49,
0,
17,
0,
100,
0
],
"000155": [
100,
66,
0,
100,
100,
0,
100
],
"000156": [
100,
66,
37,
48.99999999999999,
100,
0,
100
],
"000157": [
100,
50,
46.999999999999986,
100,
100,
0,
100
],
"000160": [
100,
50,
0,
28.999999999999996,
0,
100,
0
],
"000161": [
100,
50,
45.00000000000001,
100,
0,
0,
100
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
//var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
// var NUM_SLIDERS = 4;
// other variables can be in here too
// here's some examples for colors used
// const bg_color = [225, 206, 187];
// const fg_color = [151, 102, 52];
// const stroke_color = [95, 52, 8];
//skin colour
//brown
const brownS = [74, 52, 33];
//white
const whiteS = [232, 223, 218];
//tan
const tanS = [191, 148, 107];
//hair colour
//red
const redH = [181, 63, 16];
//blonde
const blondeH = [214, 171, 77];
//brown
const brownH = [51, 29, 0];
//black
const blackH = [28, 27, 26];
this.show_points = function(segment) {
for (let i = 0; i < segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
var number = i.toString();
textAlign(CENTER, CENTER);
textSize(0.2);
fill(0);
text(number, px, py, 0.1);
}
}
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i = 0; i < s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len, sum_y / s_len];
}
// This where you define your own face object
function IdrisFace() {
// these are state variables for a face
// (your variables should be different!)
//all to max, chnage later
this.green = 3;
this.flower = 1.8;
this.facex = 3;
this.bflower = 1.4;
this.skin = 2;
this.hair = 4;
// example of a function *inside* the face object.
// this draws a segment, and do_loop will connect the ends if true
this.draw_segment = function(segment, do_loop) {
for (let i = 0; i < segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
ellipse(px, py, 0.1);
if (i < segment.length - 1) {
let nx = segment[i + 1][0];
let ny = segment[i + 1][1];
line(px, py, nx, ny);
} else if (do_loop) {
let nx = segment[0][0];
let ny = segment[0][1];
line(px, py, nx, ny);
}
}
};
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
// outer fuzz for female hair
//red
if (this.hair == 1) {
if (this.green == 3 || this.green === 2) {
fill(redH);
push();
angleMode(DEGREES);
translate(0, -1.4);
noStroke();
for (let i = 0; i < 20; i++) {
ellipse(0, 1.8, 1.44);
rotate(20);
}
pop();
}
}
//blonde
if (this.hair == 2) {
if (this.green == 3 || this.green === 2) {
fill(blondeH);
push();
angleMode(DEGREES);
translate(0, -1.4);
noStroke();
for (let i = 0; i < 20; i++) {
ellipse(0, 1.8, 1.44);
rotate(20);
}
pop();
}
}
//brown
if (this.hair == 3) {
if (this.green == 3 || this.green === 2) {
fill(brownH);
push();
angleMode(DEGREES);
translate(0, -1.4);
noStroke();
for (let i = 0; i < 20; i++) {
ellipse(0, 1.8, 1.44);
rotate(20);
}
pop();
}
}
//black
if (this.hair == 4) {
if (this.green == 3 || this.green === 2) {
fill(blackH);
push();
angleMode(DEGREES);
translate(0, -1.4);
noStroke();
for (let i = 0; i < 20; i++) {
ellipse(0, 1.8, 1.44);
rotate(20);
}
pop();
}
}
//female hair
//red
if (this.hair == 1) {
if (this.green == 3 || this.green === 2) {
noStroke();
fill(redH);
ellipse(0, -1.4, 4.68);
fill(50, 168, 82);
push();
angleMode(DEGREES);
translate(-0.72, -2.7);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(1.8, -2);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(0.72, -3);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
}
}
//blonde
if (this.hair == 2) {
if (this.green == 3 || this.green === 2) {
noStroke();
fill(blondeH);
ellipse(0, -1.4, 4.68);
fill(23, 158, 191);
push();
angleMode(DEGREES);
translate(-0.72, -2.7);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(1.8, -2);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(0.72, -3);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
}
}
//brown
if (this.hair == 3) {
if (this.green == 3 || this.green === 2) {
noStroke();
fill(brownH);
ellipse(0, -1.4, 4.68);
fill(204, 8, 96);
push();
angleMode(DEGREES);
translate(-0.72, -2.7);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(1.8, -2);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(0.72, -3);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
}
}
//black
if (this.hair == 4) {
if (this.green == 3 || this.green === 2) {
noStroke();
fill(blackH);
ellipse(0, -1.4, 4.68);
fill(255);
push();
angleMode(DEGREES);
translate(-0.72, -2.7);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(1.8, -2);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(0.72, -3);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.4);
rotate(180 / 5);
}
pop();
}
}
// head code
if (this.skin == 1) {
fill(brownS);
noStroke();
ellipse(0, -0.4, this.facex, 3.6);
}
if (this.skin == 2) {
fill(tanS);
noStroke();
ellipse(0, -0.4, this.facex, 3.6);
}
if (this.skin == 3) {
fill(whiteS);
noStroke();
ellipse(0, -0.4, this.facex, 3.6);
}
//beard
//red
if (this.hair == 1) {
fill(redH);
if (this.green < 2) {
ellipse(0, 1.75, 2.5, 2.5);
push();
angleMode(DEGREES);
translate(0, 1.75);
noStroke();
for (let i = 0; i < 20; i++) {
ellipse(0, 1, 1);
rotate(20);
}
//flowers for beard
pop();
fill(50, 168, 82);
push();
angleMode(DEGREES);
translate(-0.9, 2);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(1.2, 1.5);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(0.3, 2.5);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
}
}
//blonde
if (this.hair == 2) {
fill(blondeH);
if (this.green < 2) {
ellipse(0, 1.75, 2.5, 2.5);
push();
angleMode(DEGREES);
translate(0, 1.75);
noStroke();
for (let i = 0; i < 20; i++) {
ellipse(0, 1, 1);
rotate(20);
}
//flowers for beard
pop();
fill(23, 158, 191);
push();
angleMode(DEGREES);
translate(-0.9, 2);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(1.2, 1.5);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(0.3, 2.5);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
}
}
//brown
if (this.hair == 3) {
fill(brownH);
if (this.green < 2) {
ellipse(0, 1.75, 2.5, 2.5);
push();
angleMode(DEGREES);
translate(0, 1.75);
noStroke();
for (let i = 0; i < 20; i++) {
ellipse(0, 1, 1);
rotate(20);
}
//flowers for beard
pop();
fill(204, 8, 96);
push();
angleMode(DEGREES);
translate(-0.9, 2);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(1.2, 1.5);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(0.3, 2.5);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
}
}
//black
if (this.hair == 4) {
fill(blackH);
if (this.green < 2) {
ellipse(0, 1.75, 2.5, 2.5);
push();
angleMode(DEGREES);
translate(0, 1.75);
noStroke();
for (let i = 0; i < 20; i++) {
ellipse(0, 1, 1);
rotate(20);
}
//flowers for beard
pop();
fill(255);
push();
angleMode(DEGREES);
translate(-0.9, 2);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(1.2, 1.5);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
push();
angleMode(DEGREES);
translate(0.3, 2.5);
noStroke();
for (let i = 0; i < 10; i++) {
ellipse(0, 0, 0.36, 1.2);
rotate(180 / 5);
}
pop();
}
}
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye);
//blush
if (this.green == 3 || this.green === 2) {
fill(196, 118, 118, 60);
noStroke();
ellipse(left_eye_pos[0], left_eye_pos[1] + 1, 0.7, 0.5);
ellipse(right_eye_pos[0], right_eye_pos[1] + 1, 0.7, 0.5);
}
//nose
let nose_top = positions.nose_bridge[0];
let nose_bottom = positions.nose_bridge[2];
let nose_bottom2 = positions.nose_bridge[3];
// print(nose_top, nose_bottom);
stroke(59, 41, 26);
strokeWeight(0.1);
line(nose_top[0], nose_top[1], nose_bottom[0], nose_bottom[1]);
fill(255);
stroke(59, 41, 26);
let nose_end = null;
if (nose_top[0] < nose_bottom[0]) {
nose_end = positions.nose_tip[0];
} else {
nose_end = positions.nose_tip[4];
}
let nose_center = positions.nose_tip[2];
push();
noFill()
strokeWeight(0.1);
angleMode(DEGREES);
arc(nose_bottom2[0], nose_bottom2[1], 0.5, 0.5, 180, 0, OPEN);
pop();
noStroke();
fill(59, 41, 26);
ellipse(nose_bottom2[0] - 0.07, nose_bottom2[1], 0.07, 0.1);
ellipse(nose_bottom2[0] + 0.07, nose_bottom2[1], 0.07, 0.1);
//glasses code
fill(40, 43, 43);
stroke(122, 122, 122);
strokeWeight(0.072);
ellipse(left_eye_pos[0], left_eye_pos[1], 1.2);
ellipse(right_eye_pos[0], right_eye_pos[1], 1.2);
//middlerim
fill(0);
push();
stroke(122, 122, 122);
rectMode(CENTER);
rect(nose_top[0], nose_top[1], 0.72, 0.108);
pop();
//mouth code
let mouthstart = positions.top_lip[0];
let mouthstart2 = positions.top_lip[7];
let mouthbot = positions.bottom_lip[0];
let mouthbot2 = positions.bottom_lip[7];
let mouth = segment_average(positions.top_lip);
let mouth2 = segment_average(positions.bottom_lip);
fill(92, 40, 19);
noStroke();
stroke(64, 27, 27);
strokeWeight(0.07);
push();
//bottom lip
translate(mouth2[0], mouth2[1]);
angleMode(DEGREES)
arc(0, mouth[0], mouthbot[0], 0.5, 0, 180, OPEN);
//top lip
strokeWeight(0.2);
arc(0, mouth[0], mouthbot[0], 0.2, 180, 0, OPEN);
pop();
noStroke();
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.facex = map(settings[1], 0, 100, 2.52, 3);
this.green = int(map(settings[0], 0, 100, 1, 3));
this.flower = map(settings[0], 0, 100, 0.36, 1.8);
this.earingsy = map(settings[3], 0, 100, 0.72, 2);
this.bflower = map(settings[0], 0, 100, 0.36, 1.4);
this.skin = int(map(settings[2], 0, 100, 1, 3));
this.hair = int(map(settings[3], 0, 100, 1, 4));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(4);
settings[1] = map(this.facex, 2.52, 3, 0, 100);
settings[0] = map(this.green, 1, 3, 0, 100);
settings[0] = map(this.flower, 0.36, 1.8, 0, 100);
settings[3] = map(this.earingsy, 0.72, 2, 0, 100);
settings[0] = map(this.bflower, 0.36, 1.4, 0, 100);
settings[2] = map(this.skin, 1, 3, 0, 100);
settings[3] = map(this.hair, 1, 4, 0, 100);
return settings;
}
}
{
"000001": [
0,
93,
100,
100
],
"000002": [
100,
46.00000000000002,
100,
0
],
"000005": [
67,
57.000000000000014,
50,
33.33333333333333
],
"000006": [
98.00000000000001,
53.99999999999998,
0,
33.33333333333333
],
"000007": [
0,
100,
100,
100
],
"000009": [
100,
100,
100,
66.66666666666666
],
"000010": [
86,
78.00000000000001,
100,
33.33333333333333
],
"000013": [
0,
100,
100,
33.33333333333333
],
"000014": [
100,
31.00000000000001,
0,
100
],
"000015": [
0,
100,
100,
66.66666666666666
],
"000016": [
0,
100,
50,
66.66666666666666
],
"000018": [
96.00000000000001,
78.00000000000001,
100,
33.33333333333333
],
"000020": [
0,
100,
100,
66.66666666666666
],
"000023": [
0,
100,
100,
100
],
"000025": [
0,
100,
50,
66.66666666666666
],
"000028": [
100,
51.000000000000036,
50,
66.66666666666666
],
"000029": [
92.00000000000001,
67.00000000000003,
50,
33.33333333333333
],
"000030": [
0,
100,
50,
33.33333333333333
],
"000031": [
100,
100,
100,
66.66666666666666
],
"000032": [
0,
100,
100,
33.33333333333333
],
"000035": [
100,
47.999999999999986,
100,
100
],
"000037": [
0,
100,
0,
100
],
"000038": [
0,
100,
100,
100
],
"000040": [
100,
100,
50,
100
],
"000041": [
0,
100,
50,
100
],
"000042": [
94,
66.00000000000004,
100,
33.33333333333333
],
"000043": [
100,
57.000000000000014,
50,
66.66666666666666
],
"000044": [
100,
10.999999999999991,
0,
100
],
"000045": [
100,
35.00000000000003,
50,
0
],
"000047": [
100,
47.00000000000001,
50,
100
],
"000048": [
0,
100,
100,
100
],
"000050": [
0,
74,
100,
100
],
"000051": [
0,
100,
100,
33.33333333333333
],
"000052": [
0,
19.000000000000036,
100,
66.66666666666666
],
"000054": [
100,
88.00000000000003,
100,
33.33333333333333
],
"000055": [
0,
100,
100,
100
],
"000056": [
0,
72.00000000000003,
100,
100
],
"000058": [
100,
81.99999999999996,
100,
100
],
"000060": [
0,
100,
0,
100
],
"000064": [
0,
100,
100,
66.66666666666666
],
"000065": [
0,
100,
50,
100
],
"000068": [
0,
100,
100,
100
],
"000069": [
0,
100,
100,
100
],
"000071": [
82,
63.99999999999999,
100,
33.33333333333333
],
"000073": [
68.00000000000001,
59.999999999999964,
50,
0
],
"000076": [
0,
100,
100,
100
],
"000077": [
100,
100,
100,
66.66666666666666
],
"000078": [
100,
100,
50,
66.66666666666666
],
"000079": [
0,
100,
100,
66.66666666666666
],
"000080": [
0,
100,
100,
100
],
"000081": [
0,
100,
0,
100
],
"000083": [
100,
34.00000000000005,
100,
0
],
"000085": [
100,
100,
100,
0
],
"000086": [
100,
100,
100,
66.66666666666666
],
"000088": [
100,
42.00000000000001,
100,
0
],
"000091": [
0,
100,
100,
100
],
"000092": [
87.99999999999999,
69.99999999999997,
50,
33.33333333333333
],
"000096": [
100,
100,
100,
0
],
"000097": [
70,
84.99999999999999,
50,
0
],
"000099": [
100,
25.00000000000002,
100,
0
],
"000100": [
87.99999999999999,
81.99999999999996,
100,
33.33333333333333
],
"000103": [
100,
54.99999999999996,
100,
66.66666666666666
],
"000104": [
25,
86.99999999999996,
100,
33.33333333333333
],
"000106": [
100,
27.999999999999968,
100,
66.66666666666666
],
"000108": [
87.99999999999999,
78.00000000000001,
100,
33.33333333333333
],
"000109": [
0,
84.99999999999999,
50,
0
],
"000110": [
100,
100,
100,
66.66666666666666
],
"000111": [
94.99999999999999,
32.99999999999997,
0,
33.33333333333333
],
"000114": [
0,
100,
100,
100
],
"000115": [
0,
100,
100,
66.66666666666666
],
"000116": [
0,
100,
100,
66.66666666666666
],
"000117": [
100,
0,
0,
100
],
"000118": [
100,
71.00000000000006,
50,
66.66666666666666
],
"000121": [
100,
100,
50,
100
],
"000122": [
98.00000000000001,
83.00000000000001,
100,
33.33333333333333
],
"000125": [
0,
100,
100,
66.66666666666666
],
"000126": [
84,
71.00000000000006,
50,
33.33333333333333
],
"000129": [
0,
42.00000000000001,
100,
100
],
"000131": [
100,
83.00000000000001,
0,
100
],
"000132": [
100,
100,
0,
100
],
"000133": [
84,
57.000000000000014,
50,
33.33333333333333
],
"000134": [
0,
100,
0,
100
],
"000135": [
0,
100,
0,
100
],
"000137": [
0,
100,
100,
66.66666666666666
],
"000140": [
96.00000000000001,
71.00000000000006,
50,
33.33333333333333
],
"000142": [
100,
41.00000000000002,
100,
66.66666666666666
],
"000143": [
0,
100,
100,
66.66666666666666
],
"000145": [
100,
100,
100,
100
],
"000146": [
100,
100,
50,
0
],
"000147": [
82,
74.99999999999997,
50,
33.33333333333333
],
"000148": [
100,
54.99999999999996,
100,
100
],
"000150": [
0,
100,
100,
0
],
"000151": [
100,
74.99999999999997,
50,
100
],
"000152": [
0,
100,
100,
0
],
"000153": [
0,
100,
100,
66.66666666666666
],
"000155": [
100,
100,
100,
0
],
"000156": [
64,
83.00000000000001,
100,
33.33333333333333
],
"000157": [
82,
85.99999999999997,
100,
33.33333333333333
],
"000160": [
0,
100,
100,
100
],
"000161": [
100,
100,
100,
100
]
}
<head>
<script language="javascript" type="text/javascript" src="p5.js"></script>
<script language="javascript" type="text/javascript" src="seedrandom.min.js"></script>
<script language="javascript" type="text/javascript" src="d3-random.v1.min.js"></script>
<script language="javascript" type="text/javascript" src="z_clmtrackr.js"></script>
<script language="javascript" type="text/javascript" src="z_model_pca_20_svm.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="z_focused_random.js"></script>
<script language="javascript" type="text/javascript" src="z_face_system.js"></script>
<script language="javascript" type="text/javascript" src="z_kdTree.js"></script>
<script language="javascript" type="text/javascript" src="z_face-api.js"></script>
<script language="javascript" type="text/javascript" src="z_training_images.js"></script>
<script language="javascript" type="text/javascript" src="z_testing_images.js"></script>
<script language="javascript" type="text/javascript" src="p5.func.js"></script>
<script language="javascript" type="text/javascript" src="simplex-noise.js"></script>
<script language="javascript" type="text/javascript" src="z_focused_random.js"></script>
<!-- 2021 -->
<script language="javascript" type="text/javascript" src="boylesz_face.js"></script>
<script language="javascript" type="text/javascript" src="boylesz_anim.js"></script>
<script language="javascript" type="text/javascript" src="bruwer_face.js"></script>
<script language="javascript" type="text/javascript" src="bruwer_anim.js"></script>
<script language="javascript" type="text/javascript" src="gambles_face.js"></script>
<script language="javascript" type="text/javascript" src="gambles_anim.js"></script>
<script language="javascript" type="text/javascript" src="garcia_face.js"></script>
<script language="javascript" type="text/javascript" src="garcia_anim.js"></script>
<script language="javascript" type="text/javascript" src="ge_face.js"></script>
<script language="javascript" type="text/javascript" src="ge_anim.js"></script>
<script language="javascript" type="text/javascript" src="huang_face.js"></script>
<script language="javascript" type="text/javascript" src="huang_anim.js"></script>
<script language="javascript" type="text/javascript" src="obrien_face.js"></script>
<script language="javascript" type="text/javascript" src="obrien_anim.js"></script>
<script language="javascript" type="text/javascript" src="palmer_face.js"></script>
<script language="javascript" type="text/javascript" src="palmer_anim.js"></script>
<script language="javascript" type="text/javascript" src="sapsford_face.js"></script>
<script language="javascript" type="text/javascript" src="sapsford_anim.js"></script>
<script language="javascript" type="text/javascript" src="wei_face.js"></script>
<script language="javascript" type="text/javascript" src="wei_anim.js"></script>
<!-- 2020 -->
<script language="javascript" type="text/javascript" src="chen_face.js"></script>
<script language="javascript" type="text/javascript" src="cooper_face.js"></script>
<script language="javascript" type="text/javascript" src="hill_face.js"></script>
<script language="javascript" type="text/javascript" src="ho_face.js"></script>
<script language="javascript" type="text/javascript" src="howard_face.js"></script>
<script language="javascript" type="text/javascript" src="hu_face.js"></script>
<script language="javascript" type="text/javascript" src="idris_face.js"></script>
<script language="javascript" type="text/javascript" src="lee_face.js"></script>
<script language="javascript" type="text/javascript" src="luo_face.js"></script>
<script language="javascript" type="text/javascript" src="mckendry_face.js"></script>
<script language="javascript" type="text/javascript" src="mcsweeney_face.js"></script>
<script language="javascript" type="text/javascript" src="ng_face.js"></script>
<script language="javascript" type="text/javascript" src="nuesca_face.js"></script>
<script language="javascript" type="text/javascript" src="park_face.js"></script>
<script language="javascript" type="text/javascript" src="ruan_face.js"></script>
<script language="javascript" type="text/javascript" src="to_face.js"></script>
<script language="javascript" type="text/javascript" src="truong_face.js"></script>
<script language="javascript" type="text/javascript" src="tuala_face.js"></script>
<script language="javascript" type="text/javascript" src="wang_face.js"></script>
<script language="javascript" type="text/javascript" src="yee_face.js"></script>
<script language="javascript" type="text/javascript" src="zhang_face.js"></script>
<script language="javascript" type="text/javascript" src="zhao_face.js"></script>
<!-- 2019 -->
<script language="javascript" type="text/javascript" src="jaegers_face.js"></script>
<script language="javascript" type="text/javascript" src="kelly19_face.js"></script>
<script language="javascript" type="text/javascript" src="trewavas_face.js"></script>
<!-- 2018 -->
<script language="javascript" type="text/javascript" src="felizardo_face.js"></script>
<script language="javascript" type="text/javascript" src="jordan_face.js"></script>
<script language="javascript" type="text/javascript" src="joy_face.js"></script>
<script language="javascript" type="text/javascript" src="salazar_face.js"></script>
<!-- 2017 -->
<script language="javascript" type="text/javascript" src="campbell_face.js"></script>
<script language="javascript" type="text/javascript" src="dockerty_face.js"></script>
<script language="javascript" type="text/javascript" src="kelly_face.js"></script>
<script language="javascript" type="text/javascript" src="petris_face.js"></script>
<script language="javascript" type="text/javascript" src="prezo_runner.js"></script>
<style>
body { padding: 0; margin: 0; }
.inner { position: absolute; }
#controls {
font: 300 12px "Helvetica Neue";
padding: 5;
margin: 5;
background: #f0f0f0;
opacity: 0.0;
-webkit-transition: opacity 0.2s ease;
-moz-transition: opacity 0.2s ease;
-o-transition: opacity 0.2s ease;
-ms-transition: opacity 0.2s ease;
}
#controls:hover { opacity: 0.9; }
</style>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner" id="controls" height="500">
<table>
<tr>
<td>Lash Thickness</td>
<td id="slider1Container"></td>
</tr>
<tr>
<td>Eye Shade</td>
<td id="slider2Container"></td>
</tr>
<tr>
<td>Lip Style</td>
<td id="slider3Container"></td>
</tr>
<tr>
<td>Face Shade</td>
<td id="slider4Container"></td>
</tr>
<tr>
<td>Face Hue</td>
<td id="slider5Container"></td>
</tr>
<tr>
<td>setting 6</td>
<td id="slider6Container"></td>
</tr>
<tr>
<td>setting 7</td>
<td id="slider7Container"></td>
</tr>
<tr>
<td>setting 8</td>
<td id="slider8Container"></td>
</tr>
<tr>
<td>setting 9</td>
<td id="slider9Container"></td>
</tr>
<tr>
<td>setting 10</td>
<td id="slider10Container"></td>
</tr>
<tr>
<td>setting 11</td>
<td id="slider11Container"></td>
</tr>
<tr>
<td>setting 12</td>
<td id="slider12Container"></td>
</tr>
<tr>
</tr>
<tr>
<td>show target</td>
<td id="sliderTintContainer"></td>
</tr>
<tr>
<td>Draw function</td>
<td id="selector1Container"></td>
</tr>
<tr>
<td>Face Draw</td>
<td id="checkbox1Container"></td>
</tr>
<tr>
<td>Face Targets</td>
<td id="checkbox2Container"></td>
</tr>
<tr>
<td>Face Points</td>
<td id="checkbox3Container"></td>
</tr>
<tr>
<td></td>
<td id="button1Container"></td>
</tr>
<tr>
<td></td>
<td id="button2Container"></td>
</tr>
<tr>
<td></td>
<td id="button3Container"></td>
</tr>
<tr>
<td></td>
<td id="button4Container"></td>
</tr>
</table>
</div>
<div>
<div id="canvasContainer"></div>
<a href="face.js">face code</a><br>
<a href="sketch.html">sketches</a>
</div>
</div>
<pre>
<p id="output">
</p>
</pre>
</body>
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// other variables can be in here too
// these control the colors used
// const bg_color = [225, 206, 187];
// const fg_color = [151, 102, 52];
// const stroke_color = [95, 52, 8];
function JaegersFace() {
// these are state variables for a face
// (your variables may be different)
// this.eye_value = 2; // can be either 2 (eyes) or 3 (no eyes)
// this.mouth_value = 1; // range is 0.5 to 8
// this.tilt_value = 0; // range is -30 to 30
this.length = 340;
this.curly = 100;
this.e = 100;
this.eyeColour = 200;
this.acc = 6;
this.hair = 50;
this.makeupStrength = 100;
this.eyeBrowSize = 0.15;
this.skin = 50;
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
translate(0, -0.2);
scale(1.3);
scale(0.4, 0.4);
let skew = this.turn;
let superWhiteSkin = color(255, 230, 209);
let whiteSkin = color(237, 203, 175);
let tanSkin = color(217, 180, 141);
let darkSkin = color(179, 146, 116);
let skinColour;
let whiteHair = color(232, 237, 237);
let blondeHair = color(255, 218, 115);
let gingerHair = color(230, 150, 90);
let brownHair = color(181, 91, 58);
let blackHair = color(100, 100, 100);
let hairColour = color(100, 100, 100);
//skin colour
if(this.skin < 33){
skinColour = lerpColor(superWhiteSkin, whiteSkin, this.skin/33);
} else if(this.skin < 66){
skinColour = lerpColor(whiteSkin, tanSkin, (this.skin-33)/33);
} else {
skinColour = lerpColor(tanSkin, darkSkin, (this.skin-66)/33);
}
angleMode(DEGREES);
let L = this.length;
let eyeSize = this.e;
fill(255, 218, 115);
//hair colour
if(this.hair < 25){
hairColour = lerpColor(whiteHair, blondeHair, this.hair/25);
} else if(this.hair < 50){
hairColour = lerpColor(blondeHair, gingerHair, (this.hair-25)/25);
} else if(this.hair < 75){
hairColour = lerpColor(gingerHair, brownHair, (this.hair-50)/25);
} else{
hairColour = lerpColor(brownHair, blackHair, (this.hair-75)/25);
}
fill(hairColour);
stroke(hairColour.red -50, green(hairColour) - 50, blue(hairColour) - 50);
//strokeWeight(width/960/10);
strokeWeight(0.04);
randomSeed(23);
let cheekboneLeftX = positions.chin[4][0];
let cheekboneLeftY = positions.chin[4][1];
let cheekboneRightX = positions.chin[12][0];
let cheekboneRightY = positions.chin[12][1];
let eliSize = (positions.chin[16][0] - positions.chin[0][0])/2;
let eliX = positions.chin[0][0] + eliSize;
let eliY = positions.chin[0][1]+(positions.chin[16][1] - positions.chin[0][1])/2;
push();
translate(eliX*2.5, ((eliY-((eliSize*1.5)))*2.5)+9);
this.drawHair(L, this.curly, hairColour);
pop();
//ears
push();
scale(2.5, 2.5);
fill(skinColour);
stroke(red(skinColour)-20, green(skinColour)-42, blue(skinColour)-58);
let headTurn = (eliX - positions.nose_bridge[0][0])*0.3;
push();
translate(positions.chin[1][0]+0.3+headTurn, positions.chin[1][1]);
ellipse(0, 0, 1,1.5 );
pop();
push();
translate(positions.chin[15][0]-0.3+headTurn, positions.chin[15][1]);
ellipse(0, 0, 1,1.5 );
pop();
pop();
//head
fill(skinColour);
stroke(red(skinColour)-20, green(skinColour)-42, blue(skinColour)-58);
push();
scale(2.5, 2.5);
ellipse(eliX, eliY, eliSize*2);
beginShape();
vertex(positions.chin[0][0], positions.chin[0][1]);
bezierVertex(positions.chin[0][0], positions.chin[0][1],
cheekboneLeftX+(positions.chin[0][0] - cheekboneLeftX)/2, positions.chin[3][1] , cheekboneLeftX, cheekboneLeftY); // cheekboneLeftX+(positions.chin[0][0] - cheekboneLeftX)/2.5, cheekboneLeftY
vertex(cheekboneLeftX, cheekboneLeftY);
bezierVertex(cheekboneLeftX, cheekboneLeftY, cheekboneLeftX + 0, cheekboneLeftY*1.25 , positions.chin[7][0], positions.chin[7][1]); // cheekboneLeftX + 0.1, cheekboneLeftY*1.15
vertex(positions.chin[7][0], positions.chin[7][1]); //CHIN
bezierVertex(positions.chin[7][0], positions.chin[7][1], positions.chin[8][0], positions.chin[8][1] + 0.15, positions.chin[9][0], positions.chin[9][1]);
vertex(positions.chin[9][0], positions.chin[9][1]); //CHIN
bezierVertex(positions.chin[9][0], positions.chin[9][1], cheekboneRightX - 0, cheekboneRightY*1.25 , cheekboneRightX, cheekboneRightY); // cheekboneRightX - 0.1, cheekboneRightY*1.15
vertex(cheekboneRightX, cheekboneRightY);
bezierVertex(cheekboneRightX, cheekboneRightY, cheekboneRightX+(positions.chin[16][0] - cheekboneRightX)/2, positions.chin[13][1] , positions.chin[16][0], positions.chin[16][1]); // cheekboneRightX+(positions.chin[16][0] - cheekboneRightX)/2.5, cheekboneRightY
vertex(positions.chin[16][0], positions.chin[16][1]);
endShape();
pop();
//FACIAL FEATURES
push();
// eyes
fill(255);
push();
push();
this.makeup(this.makeupStrength, eyeSize, skew, positions);
pop();
push();
scale(2.5, 2.5);
let buffer = 0.5;
let eyeShearLeft = (positions.left_eye[0][1] - positions.left_eye[3][1])*-100;
let eyeShearRight = (positions.right_eye[0][1] - positions.right_eye[3][1])*-100;
let scaleOffset = (eliX - positions.nose_bridge[0][0]);
push(); //left eye
stroke(255);
translate(average_point(positions.left_eye)[0], average_point(positions.left_eye)[1] + buffer);
//translate(average_point(positions.left_eye)[0], average_point(positions.left_eye)[1] + 0);
this.eyeBrow(hairColour, positions, -0.1, this.eyeBrowSize);
if(scaleOffset > 0){
scale((eliSize*0.6)-(scaleOffset*0.5), eliSize*0.6);
} else {
scale(eliSize*0.6, eliSize*0.6);
}
rotate(eyeShearLeft);
this.eye(-0.1, eyeSize, hairColour, this.eyeColour); //left eye
pop();
push(); //right eye
stroke(255);
translate(average_point(positions.right_eye)[0], average_point(positions.right_eye)[1] + buffer);
this.eyeBrow(hairColour, positions, 0.1, this.eyeBrowSize);
if(scaleOffset < 0){
scale((eliSize*0.6)+(scaleOffset*0.5), eliSize*0.6);
} else {
scale(eliSize*0.6, eliSize*0.6);
}
rotate(eyeShearRight);
this.eye(0.1, eyeSize, hairColour, this.eyeColour); //right eye
pop();
pop();
pop();
//nose
noFill();
strokeWeight(0.05);
stroke(75);
push();
scale(2.5, 2.5);
strokeWeight(0.05);
stroke(204, 60, 35, 40);
line(positions.nose_bridge[0][0],positions.nose_bridge[3][1], positions.nose_bridge[3][0], average_point(positions.nose_tip)[1]);
push();
noFill();
strokeWeight(0.05);
stroke(75);
translate(0, -0.4);
translate(positions.nose_tip[2][0], positions.nose_tip[2][1]+(buffer/2));
scale(0.4, 0.4);
bezier(-0.45, 1.05, -0.4, 1, -0.35, 1 ,-0.2, 1.15);
bezier(0.45, 1.05, 0.4, 1, 0.35, 1 ,0.2, 1.15);
noStroke();
fill(204, 60, 35, 40);
push();
translate(0, 0.5);
scale(0.6, 0.8);
beginShape(); //nose shadow
vertex(0.5, 0.4);
bezierVertex(0.5, 0.4, 1.75, 0.75 ,0, 1.4); //bottomright
vertex(0, 1.4);
bezierVertex(0, 1.4, -1.75, 0.75 , -0.5, 0.4); //bottomleft
vertex(-0.5, 0.4);
bezierVertex(-0.5, 0.4, -0.4, 0.35,0, 0.5); //top left
vertex(0, 0.5);
bezierVertex(0, 0.5, 0.4, 0.35 ,0.5, 0.4); //top right
endShape(CLOSE);
pop();
pop();
pop();
//mouth
let lipsDiff=
(positions.bottom_lip[10][1] - positions.top_lip[8][1]) + (positions.bottom_lip[8][1] - positions.top_lip[10][1]);
stroke(0);
push();
scale(2.5,2.5);
translate(0, buffer/1.5 );
stroke(0);
strokeWeight(0.015);
let b1x = positions.top_lip[7][0]+(positions.top_lip[8][0]-positions.top_lip[7][0])/2;
let b1y = positions.top_lip[7][1];
let b4x = positions.top_lip[10][0]+(positions.top_lip[11][0]-positions.top_lip[10][0])/2;
let b4y = positions.top_lip[11][1];
fill(red(skinColour)-15, green(skinColour)-35, blue(skinColour)-35);
//fill(222, 218, 213);
beginShape();
vertex(b1x, b1y);
bezierVertex(b1x, b1y,positions.top_lip[9][0] , positions.top_lip[9][1] ,b4x, b4y);
vertex(b4x, b4y);
if(lipsDiff < 0.1) {
bezierVertex(b4x, b4y,positions.top_lip[9][0] , positions.top_lip[9][1] ,b1x, b1y);
} else {
bezierVertex(b4x, b4y,positions.bottom_lip[9][0] , positions.bottom_lip[9][1] + buffer/2 ,b1x, b1y);
}
vertex(b1x, b1y);
endShape();
//teeth
if(lipsDiff > 0.1) {
fill(242, 228, 225);
beginShape();
vertex(b1x, b1y);
bezierVertex(b1x, b1y,positions.top_lip[9][0] , positions.top_lip[9][1] ,b4x, b4y);
vertex(b4x, b4y);
bezierVertex(b4x, b4y,positions.bottom_lip[9][0] ,
positions.top_lip[9][1]+((positions.bottom_lip[9][1] + buffer/2)-positions.top_lip[9][1])/3
,b1x, b1y);
vertex(b1x, b1y);
endShape();
}
pop();
//mouth shadow
fill(204, 60, 35, 30);
noStroke();
translate(0, buffer/2);
beginShape();
vertex(0, 3.25);
bezierVertex(0, 3.25, 0.6, 3.25, 0.3, 3.5);
vertex(0.3, 3.5);
bezierVertex(0.3, 3.5, 0, 3.75, -0.3, 3.5);
vertex(-0.3, 3.5);
bezierVertex(-0.3, 3.5, -0.6, 3.25, 0, 3.25);
endShape(CLOSE);
pop();
//hair
noStroke();
fill(255, 50);
fill(255, 218, 115);
stroke(230, 188, 73);
fill(hairColour);
stroke(red(hairColour) -50, green(hairColour) - 50, blue(hairColour) - 50);
push();
this.Fringe(L, this.curly, positions);
pop();
//accessories
push(); //right accessories
translate(eliX*2.5, ((eliY-((eliSize*1.5)))*2.5)+9);
if(skew > 0){ //right getting shrunk
scale(1-(skew*0.1), 1-(skew*0.1));
translate(skew*0.8, -skew*0.25);
} else {
scale(1+(-skew*0.1), 1+(-skew*0.1));
translate(skew*0.8, -skew*0.25);
}
if(this.acc > 2){ //2 flower RIGHT
push();
this.flower1(L, 1);
pop();
}
if(this.acc > 3){ //3 flower RIGHT
push();
this.flower1(L, 0.8);
pop();
}
if(this.acc > 0){ //0 bow RIGHT
push();
this.bow(L, this.curly, 1);
pop();
}
pop();
push(); //left accessories
translate(0, 0);
translate(eliX*2.5, ((eliY-((eliSize*1.5)))*2.5)+9);
if(skew < 0){ //right getting shrunk
scale(1-(-skew*0.1), 1-(-skew*0.1));
translate(skew*0.8, skew*0.25);
} else {
scale(1+(skew*0.1), 1+(skew*0.1));
translate(skew*0.8, skew*0.25);
}
if(this.acc > 4){ //4 flower LEFT
push();
this.flower2(L, this.curly);
pop();
}
if(this.acc > 1){ //1 bow LEFT
push();
this.bow(L, this.curly, -1);
pop();
}
pop();
}
this.eyeBrow = function(col, positions, pos, size){
push();
let hairColour = col;
colorMode(HSB, 360, 100, 100, 100);
fill(hairColour);
stroke(hue(hairColour), saturation(hairColour), brightness(hairColour)-20);
strokeWeight(0.03);
let browSize = size; //0 -> 0.25
if(pos < 0){ //left eye
translate(-average_point(positions.left_eye)[0], -average_point(positions.left_eye)[1]);
beginShape();
vertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]); //start
bezierVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1],
positions.left_eyebrow[0][0],positions.left_eyebrow[1][1]+(positions.left_eyebrow[0][1]-positions.left_eyebrow[1][1])/2,
positions.left_eyebrow[1][0],positions.left_eyebrow[1][1]);
vertex(positions.left_eyebrow[1][0],positions.left_eyebrow[1][1]);
bezierVertex(positions.left_eyebrow[1][0],positions.left_eyebrow[1][1],
positions.left_eyebrow[2][0],positions.left_eyebrow[3][1]*1.05,
positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]);
vertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]); //end
vertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]-browSize);
bezierVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]-browSize,
positions.left_eyebrow[2][0],positions.left_eyebrow[3][1]*1.05-(browSize*1),
positions.left_eyebrow[1][0]-(browSize*0.3),positions.left_eyebrow[1][1]-(browSize*0.4));
vertex(positions.left_eyebrow[1][0]-(browSize*0.3),positions.left_eyebrow[1][1]-(browSize*0.4));
bezierVertex(positions.left_eyebrow[1][0]-(browSize*0.3),positions.left_eyebrow[1][1]-(browSize*0.4),
positions.left_eyebrow[0][0],
(positions.left_eyebrow[1][1]-(browSize*0.4))+(positions.left_eyebrow[0][1]-(positions.left_eyebrow[1][1]-(browSize*0.4)))/2,
positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
vertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]); //start
endShape();
} else { //right eye
translate(-average_point(positions.right_eye)[0], -average_point(positions.right_eye)[1]);
beginShape();
vertex(positions.right_eyebrow[4][0],positions.right_eyebrow[4][1]); //start
bezierVertex(positions.right_eyebrow[4][0],positions.right_eyebrow[4][1],
positions.right_eyebrow[4][0],positions.right_eyebrow[3][1]+(positions.right_eyebrow[4][1]-positions.right_eyebrow[3][1])/2, //average
positions.right_eyebrow[3][0],positions.right_eyebrow[3][1]);
vertex(positions.right_eyebrow[3][0],positions.right_eyebrow[3][1]);
bezierVertex(positions.right_eyebrow[3][0],positions.right_eyebrow[3][1],
positions.right_eyebrow[2][0],positions.right_eyebrow[1][1]*1.05,
positions.right_eyebrow[0][0],positions.right_eyebrow[0][1]);
vertex(positions.right_eyebrow[0][0],positions.right_eyebrow[0][1]); //end
vertex(positions.right_eyebrow[0][0],positions.right_eyebrow[0][1]-browSize);
bezierVertex(positions.right_eyebrow[0][0],positions.right_eyebrow[0][1]-browSize,
positions.right_eyebrow[2][0],positions.right_eyebrow[1][1]*1.05-(browSize*1),
positions.right_eyebrow[3][0]+(browSize*0.3),positions.right_eyebrow[3][1]-(browSize*0.4));
vertex(positions.right_eyebrow[3][0]+(browSize*0.3),positions.right_eyebrow[3][1]-(browSize*0.4));
bezierVertex(positions.right_eyebrow[3][0]+(browSize*0.3),positions.right_eyebrow[3][1]-(browSize*0.4),
positions.right_eyebrow[4][0],
(positions.right_eyebrow[3][1]-(browSize*0.4))+(positions.right_eyebrow[4][1]-(positions.right_eyebrow[3][1]-(browSize*0.4)))/2, //average
positions.right_eyebrow[4][0],positions.right_eyebrow[4][1]);
vertex(positions.right_eyebrow[4][0],positions.right_eyebrow[4][1]); //start
endShape();
}
colorMode(RGB, 255);
pop();
}
this.makeup = function(strength, eyeSize ,skew, positions){
let buffer = 0.5;
//blush
let eliSize = (positions.chin[16][0] - positions.chin[0][0])/2;
let scaleOffset = ((positions.chin[0][0] + eliSize) - positions.nose_bridge[0][0]);
for(let i = 0; i < 10; i++){
noStroke();
fill(255, 64, 118, 0.05*strength); //0.05
push();
if(scaleOffset > 0){
scale((eliSize*0.6)-(scaleOffset*0.5), (eliSize*0.6)-(scaleOffset*0.3));
translate(scaleOffset*-1, 0);
} else {
scale(eliSize*0.6, eliSize*0.6);
}
translate(0, buffer/2);
ellipse(-2.75, 0, i*0.3, i*0.3); //left blush
pop();
push();
if(scaleOffset < 0){
scale((eliSize*0.6)-(scaleOffset*-0.5), (eliSize*0.6)-(scaleOffset*-0.3));
translate(scaleOffset*-1, 0);
} else {
scale(eliSize*0.6, eliSize*0.6);
}
translate(0, buffer/2);
ellipse(2.75, 0, i*0.3, i*0.3); //right blush
pop();
}
//cheek lines
strokeWeight(0.05);
stroke(199, 143, 107, strength*2.55);
push();
if(scaleOffset > 0){
scale((eliSize*0.6)-(scaleOffset*0.5), (eliSize*0.6)-(scaleOffset*0.3));
translate(scaleOffset*-1,0);
} else {
scale(eliSize*0.6, eliSize*0.6);
}
//left lines
line(-3, 0, -3.2, 0.5);
line(-2.75, 0.05, -2.95, 0.55);
line(-2.5, 0.1, -2.7, 0.6);
line(-2.25, 0.15, -2.45, 0.65);
pop();
push();
if(scaleOffset < 0){
scale((eliSize*0.6)-(scaleOffset*-0.5), (eliSize*0.6)-(scaleOffset*-0.3));
translate(scaleOffset*-1, 0);
} else {
scale(eliSize*0.6, eliSize*0.6);
}
//right lines
line(3.2, 0, 3, 0.5);
line(2.95, 0.05, 2.75, 0.55);
line(2.7, 0.1, 2.5, 0.6);
line(2.45, 0.15, 2.25, 0.65);
pop();
//lipstick
push();
let lipsDiff= (positions.bottom_lip[10][1] - positions.top_lip[8][1]) + (positions.bottom_lip[8][1] - positions.top_lip[10][1]);
scale(2.5,2.5);
translate(0, buffer/1.5 );
stroke(0);
strokeWeight(0.02);
let b4x = positions.top_lip[7][0]+(positions.top_lip[8][0]-positions.top_lip[7][0])/2;
let b4y = positions.top_lip[7][1];
let b1x = positions.top_lip[10][0]+(positions.top_lip[11][0]-positions.top_lip[10][0])/2;
let b1y = positions.top_lip[11][1];
let topMid;
if(b4y - b1y < 0){
topMid = b4y+(b1y - b4y)/2;
} else {
topMid = b1y+(b4y - b1y)/2;
}
fill(255, 64, 118, 1.5*strength); //0.75
stroke(255, 64, 118, 3*strength);
beginShape();
vertex(b1x, b1y);
bezierVertex(b1x, b1y, positions.top_lip[2][0],positions.top_lip[2][1]-(0.15*buffer) ,positions.top_lip[3][0], topMid);
vertex(positions.top_lip[3][0], topMid);
bezierVertex(positions.top_lip[3][0], topMid, positions.top_lip[4][0],positions.top_lip[4][1]-(0.15*buffer), b4x, b4y);
vertex(b4x, b4y);
if(lipsDiff < 0.1) {
bezierVertex(b4x, b4y, average_point(positions.bottom_lip)[0], positions.bottom_lip[3][1]+ buffer*0.25, b1x, b1y);
} else {
bezierVertex(b4x, b4y, average_point(positions.bottom_lip)[0], positions.bottom_lip[3][1] + buffer*0.75,b1x, b1y);
}
vertex(b1x, b1y);
endShape();
pop();
}
this.flower2 = function(len, curl){
if(len > 190){
translate(map(len, 190, 340, -5.5,-6.5+curl/200), map(len, 190, 340, -1, 5+curl/50));
}else {
translate(map(len, 0, 190, -5, -5.5),
map(len, 0, 190, -3.5, -1));
}
stroke(163, 120, 57);
for(let i = 0; i < 5; i++){
rotate(72);
push();
translate(0, -1);
fill(250, 236, 192);
bezier(-0.25, 0.5, -1.5, -1.25, 1.5, -1.25 ,0.25, 0.5);
fill(237, 196, 135);
noStroke();
bezier(-0.15, 0.5, -1, -0.75, 1, -0.75 ,0.15, 0.5);
pop();
}
fill(222, 178, 113);
ellipse(0, 0, 1, 1);
}
this.flower1 = function(len, sc){
scale(sc, sc);
if(sc < 1){
translate(2, -1);
}
if(len > 190){
translate(6, map(len, 190, 340, -2, 3));
} else {
translate(map(len, 0, 190, 4, 6),
map(len, 0, 190, -6.5, -2));
}
if(sc < 1){
stroke(131, 87, 173);
} else {
stroke(78, 127, 207);
}
for(let i = 0; i < 5; i++){
rotate(72);
if(sc < 1){
fill(180-i*10, 140-i*10, 219);
} else {
fill(166-i*10, 200-i*10, 255);
}
push();
translate(0, -0.75);
ellipse(0, 0, 1.5, 1.5);
pop();
}
if(sc < 1){
fill(230, 172, 110);
} else {
fill(245, 208, 115);
}
ellipse(0, 0, 1, 1);
}
this.bow = function(len,curl, pos){
c = curl/100;
let scale1 = map(len, 0, 340, 0.7, 1);
if(pos < 0){
translate(-6*(1-scale1), -3*(1-scale1));
} else {
translate(6*(1-scale1), -3*(1-scale1));
}
scale(scale1, scale1);
scale(pos, 1);
scale(0.8, 0.8);
if(len > 190){
translate(7.25+map(len, 190, 340, 0, c),
-4+map(len, 190, 340, 0, c));
} else {
translate(7.25-map(len, 0, 190, 2, 0), -4-map(len, 0, 190, 3, 0)); //short
scale(map(len, 0, 190, 0.75, 1), map(len, 0, 190, 0.75, 1));
}
rotate(0);
fill(255, 204, 225);
stroke(171, 65, 108);
strokeWeight(0.05);
beginShape();
vertex(0, 1);
bezierVertex(0, 1, 0.25, 3, 1.5, 5);
vertex(3, 5);
bezierVertex(3, 5, 1, 3.5, 0.5, 1);
endShape();
beginShape();
vertex(0.25, 1);
bezierVertex(0.25, 1, 0.75, 3, 4, 5);
vertex(5, 4);
bezierVertex(5, 4, 1.5, 3.5, 0.75, 1);
endShape();
//big left
beginShape();
vertex(0, 0);
bezierVertex(0, 0,-3, -3, -3, -2);
vertex(-2, 0);
bezierVertex(-2, 0, -3, 1, -2, 1.5);
vertex(0, 1);
endShape();
//big right
beginShape();
vertex(1, 0);
bezierVertex(1, 0,3, -3, 3, -2);
vertex(3, -2);
vertex(2.25, 0);
bezierVertex(2, 0, 3, 1, 2, 1.5);
vertex(2, 1.5);
vertex(1, 1);
endShape();
//outline
fill(255, 150, 193);
noStroke();
bezier(2, 1.5, 2.5, 0.75, 1, 0.5 ,1, 1);
//outline2
bezier(-2, 1.5, -2, 0.5, 0, 0.3 ,0, 1);
//upper outline
beginShape();
vertex(1, 0);
bezierVertex(1, 0 ,3, -3, 3, -2);
vertex(1, 0.25);
endShape();
beginShape();
vertex(0, 0);
bezierVertex(0, 0,-3, -3, -3, -2);
vertex(0, 0.25);
endShape();
//shadow
fill(171, 65, 108);
stroke(171, 65, 108);
bezier(2, 1.5, 2, 1, 1.5, 1 ,1, 1);
line(2, 1.5, 1, 1);
//shadow2
bezier(-2, 1.5, -1.5, 0.75, -0.5, 0.75 ,0, 1);
line(-2, 1.5, 0, 1);
fill(255, 204, 225);
rect(-0.1, -0.1, 1.1,1.1, 0.3);
}
this.eye = function(pos, size, col, eyeCol){
colorMode(HSB, 360, 100, 100, 100);
let coll = eyeCol;
let bright;
if(size > 25){
bright = map(size, 25, 100, 1, 0);
} else {
bright = 1;
}
let Med = color(coll, 83 - (59*bright), 79 - (30*bright)); //59
let Dark = color(coll, 53- (29*bright), 52 - (30*bright)); //29
let Light = color(coll, 68 - (44*bright), 92 - (30*bright)); //44
let hairColour = col;
push();
scale(0.24, 0.24);
translate(pos, 0);
let sc = 0.57;
stroke(0);
strokeWeight(0.2*sc);
strokeCap(SQUARE);
push();
if(pos < 0){
scale(-1, 1);
translate(-0.15, 0);
}
//eyebrow
strokeWeight(0.2*sc);
//outter white eye //3
if(size > 50 && size < 75){
sc = map(size, 50, 75, 0, 0.57);
} else if(size >= 75){
sc = 0.57;
} else {
sc = 0;
}
noStroke();
beginShape();
fill(255);
vertex(-3.5*sc, -0.5*sc);
bezierVertex(-3.5*sc, -1*sc, 1.5*sc, -5.5*sc , 4.5*sc , 0);
vertex(4.5*sc, 0);
bezierVertex(5*sc, 0, 1.5*sc, 5*sc, -2.5*sc, 2*sc);
endShape();
//outline
stroke(0);
noFill();
beginShape();
vertex(-3.5*sc, -0.5*sc);
bezierVertex(-3.5*sc, -1*sc, 1.5*sc, -5.5*sc , 4.5*sc , 0);
vertex(4.5*sc, 0);
endShape();
pop();
strokeWeight(0.3*sc);
//bulk blue //2
if(size > 25 && size < 50){
sc = map(size, 25, 50, 0, 0.57);
} else if(size >= 50){
sc = 0.57;
} else {
sc = 0;
}
stroke(Dark);
fill(Dark);
ellipse(0.1*sc, 0, 5*sc, 5*sc);
noStroke();
//blue shading //2
fill(Med);
ellipse(0, 0.5*sc, 4.5*sc, 3*sc);
fill(Light);
ellipse(0, 1*sc, 4*sc, 2.5*sc);
//noisey dots //4
if(size > 75){
sc = map(size, 75, 100, 0, 0.57);
} else {
sc = 0;
}
//lines from center //4
stroke(0);
strokeWeight(0.1*sc);
rotate(30);
let cent;
for(let i = 0; i < 16; i++){
cent = map(i, 0, 15, -1, 1);
if(cent < 0){cent = cent*-1;}
if(i % 2 == 0){
stroke(0);
line(-1*sc, 1*sc, (-1.75+cent/3)*sc, (1.75-cent/3)*sc);
} else {
stroke(100);
line(-1.4*sc, 1.4*sc, (-1.25+cent/3)*sc, (1.25-cent/3)*sc);
}
rotate(-10);
}
//lower white cirles //4
fill(255, 50);
noStroke();
rotate(-160);
for(let j = 0; j < 6; j++){
ellipse(1.25*sc, 1.5*sc, 0.6*sc, 0.6*sc);
rotate(-12);
}
//black center //1
sc = 0.57;
fill(0);
push();
translate(0, -0.25);
ellipse(0, 0, 1.5*sc, 2.25*sc);
if(size > 75){
sc = map(size, 75, 100, 0, 0.57);
} else {
sc = 0;
}
pop();
//white circles highlight //2
if(size > 25 && size < 50){
sc = map(size, 25, 50, 0, 0.57);
} else if(size >= 50){
sc = 0.57;
} else {
sc = 0;
}
fill(255);
ellipse(0.75*sc, -0.75*sc, 0.75*sc, 0.75*sc);
ellipse(1.75*sc, -1.5*sc, 1.25*sc, 1*sc);
ellipse(-2*sc, 1*sc, 1*sc, 1*sc);
pop();
colorMode(RGB, 255);
}
this.Fringe = function(Len, cur, positions){
rectMode(CORNERS);
let L;
if(Len > 140){
L = 340;
} else if(Len > 106){
L = map(Len, 105, 140, 0, 340);
} else {
L = 0;
}
let skew = positions.nose_bridge[0][0]*3.5;
push();
let eliSize = (positions.chin[16][0] - positions.chin[0][0])/2;
let eliX = positions.chin[0][0] + eliSize;
let eliY = positions.chin[0][1]+(positions.chin[16][1] - positions.chin[0][1])/2;
fill(255);
pop();
let tr = -positions.right_eyebrow[2][0];
let trMultiplier = map(L, 0, 340, -1, 1);
translate(0, 7);
translate(0, eliY*2.5-(eliSize*2.5));
if(L > 0){
let xSc = map(L, 0, 340, 0.4-(cur/250), map(cur, 0, 100, 1.5, 1.25));
let ySc = map(L, 0, 340, 0, map(cur, 0, 100, 2, 1.4));
let c = map(cur, 0, 100, 0.8*ySc, 0);
let c2 = cur/100;
translate(0, map(L, 0, 340, -6.5, map(cur, 0, 100, -4.5, -4)));
for(let i = 0; i <5; i++){
push();
if((i+1) % 2 == 0){ //even, left
translate((map(i-1, 0, 4, 4, 0)), ((-0.55-cur/400)+(i-1)*0.09)*(i-1)); //2, 4
} else { //odd, right
translate((map(i, 0, 4, -4, 0)), ((-0.55-cur/400)+i*0.09)*i); //1, 3, 5
}
if(i == 0){ //left 1
if(skew > 0){
scale(1+(skew*0.5), 1+(skew*0.3));
translate(skew*0, 0);
} else {
scale(1-(0.2*-skew), 1);
translate(-0.5*skew, 0.15*-skew);
}
} else if(i ==1){ //right 1
if(skew > 0){
scale(1-(0.2*skew), 1);
translate(-0.5*skew, 0.15*skew);
} else {
scale(1+(-skew*0.5), 1+(-skew*0.3));
translate(skew*0, 0);
}
} else if(i ==2){ //left 2
if(skew > 0){
scale(1+(skew*0.25), 1+(skew*0.1));
translate((skew*0.1), 0);
} else {
scale(1-(-skew*0.15), 1);
translate(0.5*skew , 0.3*-skew);
}
}else if(i ==3){ //right 2
if(skew > 0){
scale(1-(skew*0.1), 1);
translate(0.5*skew , 0.3*skew);
} else {
scale(1+(-skew*0.25), 1+(-skew*0.1));
translate((skew*0.1), 0);
}
}else if(i ==4){ //middle
if(skew > 0){
scale(1, 1);
translate(1*skew, 0);
} else {
scale(1, 1);
translate(1*skew, 0);
}
}
beginShape();
let test = 1;
vertex(-xSc, -ySc);
bezierVertex(-xSc, -ySc, 0, -2*(ySc)+c, xSc, -ySc); //top curve
vertex(xSc, -ySc);
bezierVertex(xSc, -ySc, 2*xSc-c, 0, xSc, ySc); //east curve
vertex(xSc, ySc);
bezierVertex(xSc, ySc, 0, 2*(ySc)-c, -xSc, ySc); //bottom curve
vertex(-xSc, ySc);
bezierVertex(-xSc, ySc, -2*xSc+c, 0, -xSc, -ySc); //west curve
endShape(CLOSE);
pop();
}
}
}
this.drawHair = function(Len, cur, col){
let hairColour = col;
let L = Len
//let curl = map(cur, 0, 100, 180, -90);
let curl;
if(L > 240){
curl = map(cur, 0, 100, 180, map(L, 240, 340, 180, -90));
} else {
curl = 180;
}
let curly = cur;
let curlScale;
if (L < 139){
curlScale = map(
curly, 0, 100, 0,
map(L, 0, 139, 0.1, 2));
} else {
curlScale = map(curly, 0, 100, 0, map(L, 139, 340, 2, 3));
}
push();
translate(0, -3);
rotate(10);
for(let i = 0; i < 5; i++){
rotate(28);
if(L < 139){
if(L > 90){
ellipse(-4, 0, 4, map(curly, 0, 100, map(L, 90, 139, 0.01, 8), map(L, 90, 139, 2.5, 4)));
} else {
ellipse(map(L, 0, 90, -2.9, -4), 0, 4, map(curly, 0, 100, 0.01, 2.5));
}
}
else {
ellipse(-4, 0, 4, map(curly, 0, 100, 8, 4));
}
}
pop();
if(L < 139){ //shorter hair
translate(0, map(L, 0, 139, 7, 0));
scale(map(L, 0, 139, 0.2, 1), map(L, 0, 139, 0.5, 1));
arc(3+0, -5, 6, 6, 170, 221+L, CHORD); //ARAAC
arc(-3-0, -5, 6, 6, 320-L, 371, CHORD); //mirror
let HairLength = -5+map(L, 0, 139, -130, 0);
push(); //right curl
translate(3 + ((3+curlScale) * cos(221+L)) +0 , -5 + ((3+curlScale) * sin(221+L)));
rotate(HairLength);
beginShape();
let cX = map(HairLength, -135, -5, -0.2, -0.9);
let cY = map(HairLength, -135, -5, -0.0, -0.8);
let radiuss = map(HairLength, -135, -5, 0.1, curlScale*1.5)/2;
let anglee = -20;
endShape();
fill(225, 206, 187);
fill(hairColour);
pop();
HairLength = -5+map(L, 0, 139, 160, 30);
push(); //left curl
translate(-3 - ((3+curlScale) * cos(221+L)) -0 , -5 + ((3+curlScale) * sin(221+L)));
rotate(HairLength);
beginShape();
cX = map(HairLength, 155, 25, 0.2, 0.4);
cY = map(HairLength, 155, 25, -0.0, -1.1 );
radiuss = map(HairLength, 155, 25, 0.1, curlScale*1.4)/2;
anglee = 170;
endShape();
fill(225, 206, 187);
fill(hairColour);
pop();
} else { //longer hair
fill(255, 218, 115);
fill(hairColour);
arc(3, -5, 6, 6, 170, 360, CHORD); //top hair ARAAC
arc(-3-0, -5, 6, 6, 180, 370, CHORD);
let HairLength = -5+map(L, 139, 360, 0, 14*1);
//big curls
let x1 = (6+0 + 2+0)/2;
let y1 = (-5-6.5)/2;
let x2 = (6+map(L, 139, 360,0, 1)+0-map(HairLength, -5, 9, 0, curlScale) + (6+0)-map(HairLength, -5, 9, 0, curlScale))/2;
let y2 = (-5+map(L, 139, 360, 0, 14*1)+-5+map(L, 139, 360, 0, 14*1))/2;
for(let i = 0; i < 3; i++){
ellipse(lerp(x1, x2, 0.2 + (0.3*i)), lerp(y1, y2, 0.2 + (0.3*i)),
map(curly, 0, 100, 0, map(L, 139, 360, 0.5, 9-i)),
map(L, 139, 360, 0, 8-i));
}
beginShape(); //long strands
vertex(6+0, -5); //1
vertex(6+map(L, 139, 360,0, 1)+0-map(HairLength, -5, 9, 0, curlScale), //2
-5+map(L, 139, 360, 0, 14*1));
vertex((6+0)-map(HairLength, -5, 9, 0, curlScale), //3
-5+map(L, 139, 360, 0, 14*1));
vertex(2+0, -6.5); //4
endShape();
//big curls Mirror
x1 = (-6-0 + -2-0)/2;
y1 = (-5 + -6.5)/2;
x2 = (-6-map(L, 139, 360,0, 1)-0+map(HairLength, -5, 9, 0, curlScale) + -6-0+map(HairLength, -5, 9, 0, curlScale))/2;
y2 = (-5+map(L, 139, 360, 0, 14*1) + -5+map(L, 139, 360, 0, 14*1))/2;
for(let i = 0; i < 3; i++){
ellipse(lerp(x1, x2, 0.2 + (0.3*i)), lerp(y1, y2, 0.2 + (0.3*i)),
map(curly, 0, 100, 0, map(L, 139, 360, 0.5, 9-i)),
map(L, 139, 360, 0, 8-i));
}
beginShape(); //long strands mirror
vertex(-6-0, -5);
vertex(-6-map(L, 139, 360,0, 1)-0+map(HairLength, -5, 9, 0, curlScale),
-5+map(L, 139, 360, 0, 14*1));
vertex(-6-0+map(HairLength, -5, 9, 0, curlScale),
-5+map(L, 139, 360, 0, 14*1));
vertex(-2-0, -6.5);
endShape();
beginShape();
for(let i = 0; i < 50; i++){ //outer curl
vertex((5.95+0)-map(HairLength, -5, 9+0, 0, curlScale)+curlScale+
curlScale*cos(map(curl, 180, -90, 180, 180-(4.5*i))),
HairLength-map(L, 139, 340, 0, 0.75)+
curlScale*sin(map(curl, 180, -90, 180, 180-(4.5*i))));
}
for(let i = 15; i > 0; i--){ //inner curl
let shrink = 1;
shrink = map(i, 15, 0, 1.2, 5);
vertex(
(6+map(L, 139, 360,0, 1)+0)-map(HairLength, -5, 9+0, 0, curlScale)+curlScale/shrink+
curlScale/shrink*cos(map(curl, 180, -90, 180, 180-(17*i))),
HairLength-map(L, 139, 340, 0, 0.75)+
curlScale/shrink*sin(map(curl, 180, -90, 180, 180-(15 *i)))
);
}
endShape();
beginShape();
for(let i = 0; i < 50; i++){ //outer curl mirror
vertex((-5.95-0)+map(HairLength, -5, 9+0, 0, curlScale)-curlScale+
curlScale*cos(map(curl, 180, -90, 0, (4.5*i))),
HairLength-map(L, 139, 340, 0, 0.75)+
curlScale*sin(map(curl, 180, -90, 0, (4.5 *i))));
}
for(let i = 15; i > 0; i--){ //inner curl mirror
let shrink = 1;
shrink = map(i, 15, 0, 1.2, 5);
vertex(
(-6-map(L, 139, 360,0, 1)-0)+map(HairLength, -5, 9+0, 0, curlScale)-curlScale/shrink+
curlScale/shrink*cos(map(curl, 180, -90, -10, (17*i))),
HairLength-map(L, 139, 340, 0, 0.75)+curlScale/shrink*sin(map(curl, 180, -90, -10, (15 *i)))
);
}
endShape();
}
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
// this.eye_value = int(map(settings[0], 0, 100, 2, 3));
// this.mouth_value = map(settings[1], 0, 100, 0.5, 8);
// this.tilt_value = map(settings[2], 0, 100, -30, 30);
this.length = map(settings[0], 0, 100, 0, 340);
this.curly = settings[1];
this.e = settings[2];
this.eyeColour = map(settings[3], 0, 100, 0, 360);
this.acc = int(map(settings[4], 0, 100, 0, 8))
this.hair = settings[5];
this.makeupStrength = settings[6];
this.eyeBrowSize = map(settings[7], 0, 100, 0, 0.4);
this.skin = settings[8];
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(8);
settings[0] = map(this.length, 0, 340, 0, 100);
settings[1] = this.curly;
settings[2] = this.e;
settings[3] = map(this.eyeColour, 0, 360, 0, 100);
settings[4] = map(this.acc, 0, 8, 0, 100);
settings[5] = this.hair;
settings[6] = this.makeupStrength;
settings[7] = map(this.eyeBrowSize, 0, 0.4, 0, 100);
settings[8] = this.skin;
return settings;
}
}
// given an array of [x,y] points, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for(var i=0; i<list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
{
"000001": [
100,
74,
100,
56.00000000000001,
12.5,
61,
100,
31,
30
],
"000002": [
100,
0,
100,
0,
0,
52,
52,
20.000000000000004,
0
],
"000005": [
100,
0,
100,
56.00000000000001,
0,
6,
100,
55.00000000000001,
24
],
"000007": [
0,
100,
0,
100,
0,
95,
0,
75.00000000000001,
27
],
"000009": [
100,
100,
100,
54,
50,
92,
100,
28.000000000000004,
21
],
"000010": [
100,
100,
100,
53,
25,
3,
50,
31,
18
],
"000013": [
0,
100,
0,
56.00000000000001,
0,
6,
0,
61,
14
],
"000014": [
100,
100,
100,
95.99999999999999,
25,
100,
100,
56.00000000000001,
100
],
"000015": [
34,
0,
0,
50,
0,
14,
0,
55.00000000000001,
21
],
"000016": [
0,
61,
0,
56.00000000000001,
0,
89,
0,
61,
24
],
"000018": [
100,
100,
100,
56.00000000000001,
25,
0,
100,
42,
15
],
"000020": [
49,
100,
0,
51,
0,
100,
0,
62,
23
],
"000023": [
28.000000000000004,
48,
0,
49,
0,
91,
0,
61,
15
],
"000025": [
1,
0,
0,
53,
0,
85,
0,
62,
52
],
"000028": [
100,
100,
100,
90,
25,
100,
100,
39.00000000000001,
67
],
"000029": [
100,
100,
100,
53,
25,
8,
100,
28.000000000000004,
18
],
"000030": [
37,
53,
0,
56.00000000000001,
0,
0,
0,
71.99999999999999,
33
],
"000031": [
100,
100,
100,
56.00000000000001,
0,
19,
100,
31,
21
],
"000032": [
22,
54,
0,
51,
0,
10,
0,
43,
21
],
"000035": [
100,
48,
100,
11.999999999999998,
0,
100,
100,
25,
13
],
"000037": [
0,
0,
0,
50,
0,
100,
0,
72.99999999999999,
100
],
"000038": [
27,
0,
0,
51,
0,
88,
0,
79.00000000000001,
22
],
"000006": [
100,
100,
100,
99,
0,
100,
100,
34,
100
],
"000040": [
100,
0,
100,
93,
100,
100,
100,
44,
28
],
"000041": [
54,
100,
0,
51,
12.5,
100,
0,
67,
100
],
"000042": [
100,
100,
100,
53,
25,
11,
100,
27,
18
],
"000043": [
100,
100,
100,
23,
25,
100,
100,
49,
20
],
"000044": [
100,
100,
100,
78,
100,
100,
100,
50,
92
],
"000045": [
100,
100,
100,
90,
0,
91,
100,
24,
35
],
"000047": [
100,
100,
100,
100,
25,
100,
100,
16,
45
],
"000048": [
48,
100,
0,
56.00000000000001,
0,
100,
0,
71.99999999999999,
0
],
"000050": [
30,
100,
0,
51,
0,
100,
0,
89,
39
],
"000051": [
0,
0,
0,
50,
0,
100,
0,
83,
56
],
"000052": [
34,
42,
0,
53,
0,
90,
0,
84,
17
],
"000054": [
100,
100,
100,
56.99999999999999,
25,
7,
100,
28.000000000000004,
33
],
"000055": [
20.999999999999996,
100,
0,
51,
0,
100,
0,
76.00000000000001,
22
],
"000056": [
56.00000000000001,
100,
51,
94,
0,
100,
100,
38.00000000000001,
0
],
"000058": [
100,
100,
100,
56.00000000000001,
25,
100,
100,
7.000000000000001,
7
],
"000060": [
0,
0,
0,
50,
0,
100,
0,
0,
100
],
"000064": [
14.000000000000002,
57,
0,
50,
0,
100,
0,
80.00000000000001,
17
],
"000065": [
30,
0,
0,
100,
0,
100,
0,
91,
56
],
"000068": [
45,
100,
2,
0,
87.5,
100,
0,
0,
34
],
"000069": [
27,
100,
0,
53,
0,
100,
0,
67,
16
],
"000071": [
100,
100,
100,
56.00000000000001,
50,
4,
100,
33,
24
],
"000073": [
100,
100,
100,
100,
25,
91,
100,
41,
18
],
"000076": [
75.99999999999999,
10,
0,
50,
12.5,
100,
0,
100,
100
],
"000077": [
100,
100,
100,
56.00000000000001,
25,
100,
100,
33,
48
],
"000078": [
100,
100,
100,
38,
0,
100,
100,
83,
37
],
"000079": [
1,
0,
0,
53,
0,
97,
0,
53,
42
],
"000160": [
30,
100,
0,
51,
0,
100,
0,
77.00000000000001,
32
],
"000157": [
100,
47,
100,
55.00000000000001,
0,
17,
75,
43,
35
],
"000156": [
52,
100,
100,
56.00000000000001,
0,
11,
100,
31,
35
],
"000153": [
0,
52,
0,
52,
0,
100,
0,
54,
34
],
"000152": [
0,
57,
0,
51,
37.5,
76,
0,
45,
34
],
"000151": [
100,
51,
100,
94,
0,
100,
35,
47,
78
],
"000150": [
30,
0,
0,
52,
62.5,
100,
0,
61,
12
],
"000148": [
96,
0,
100,
45,
25,
99,
100,
28.000000000000004,
28
],
"000147": [
100,
35,
100,
62,
0,
13,
91,
31,
46
],
"000146": [
100,
100,
100,
0,
0,
94,
100,
40.00000000000001,
74
],
"000145": [
100,
100,
100,
38,
0,
100,
100,
32,
75
],
"000143": [
14.000000000000002,
0,
0,
52,
0,
42,
0,
65,
24
],
"000142": [
100,
100,
100,
73,
0,
100,
100,
44,
24
],
"000140": [
100,
45,
100,
51,
0,
12,
100,
34,
51
],
"000137": [
0,
0,
0,
52,
100,
94,
0,
65,
23
],
"000135": [
28.000000000000004,
63,
0,
0,
0,
100,
0,
100,
85
],
"000134": [
0,
0,
0,
0,
0,
100,
0,
76.00000000000001,
100
],
"000133": [
100,
0,
100,
47.99999999999999,
25,
17,
100,
40.00000000000001,
48
],
"000132": [
100,
51,
100,
0,
0,
100,
100,
55.00000000000001,
100
],
"000131": [
100,
100,
100,
0,
12.5,
100,
100,
38.00000000000001,
70
],
"000129": [
37,
0,
0,
51,
0,
100,
0,
67,
27
],
"000126": [
100,
100,
100,
50,
12.5,
0,
100,
50,
39
],
"000125": [
0,
0,
0,
52,
0,
100,
0,
71.99999999999999,
57
],
"000122": [
100,
100,
100,
69,
25,
0,
100,
34,
0
],
"000121": [
100,
100,
100,
8,
0,
100,
100,
36.99999999999999,
100
],
"000080": [
1,
100,
0,
51,
0,
100,
0,
69.99999999999999,
39
],
"000081": [
14.000000000000002,
100,
0,
0,
0,
100,
0,
71.99999999999999,
69
],
"000083": [
100,
100,
100,
54,
12.5,
50,
100,
28.999999999999996,
23
],
"000085": [
100,
100,
100,
37,
25,
89,
100,
31,
33
],
"000086": [
100,
0,
100,
42,
0,
81,
79,
50,
24
],
"000088": [
100,
100,
100,
95.99999999999999,
12.5,
53,
93,
26,
13
],
"000091": [
13,
100,
0,
56.99999999999999,
0,
100,
0,
68.99999999999999,
26
],
"000092": [
100,
100,
100,
56.00000000000001,
0,
8,
97,
31,
38
],
"000096": [
100,
100,
100,
0,
0,
100,
100,
39.00000000000001,
31
],
"000097": [
100,
0,
100,
70,
0,
44,
88,
36.99999999999999,
42
],
"000099": [
100,
45,
100,
31,
12.5,
91,
100,
36.99999999999999,
36
],
"000100": [
43,
0,
100,
100,
0,
17,
100,
35.99999999999999,
27
],
"000103": [
100,
48,
100,
44,
25,
100,
100,
31,
33
],
"000104": [
0,
0,
0,
64,
0,
14,
0,
55.00000000000001,
22
],
"000106": [
100,
48,
100,
34,
12.5,
50,
100,
35.99999999999999,
28
],
"000108": [
100,
100,
100,
54,
0,
7,
100,
31,
42
],
"000109": [
28.999999999999996,
46,
0,
51,
0,
21,
0,
61,
24
],
"000110": [
100,
100,
100,
56.00000000000001,
0,
50,
94,
42,
26
],
"000111": [
100,
100,
100,
63,
0,
100,
100,
39.00000000000001,
84
],
"000114": [
51,
100,
0,
95,
0,
100,
0,
65,
71
],
"000115": [
0,
0,
0,
51,
0,
16,
0,
39.00000000000001,
24
],
"000116": [
20.999999999999996,
100,
0,
64,
0,
92,
0,
70.99999999999999,
28
],
"000117": [
100,
100,
100,
0,
25,
100,
100,
39.00000000000001,
64
],
"000118": [
100,
100,
100,
90,
0,
100,
97,
40.00000000000001,
100
],
"000155": [
100,
0,
99,
0,
0,
100,
99,
43,
27
],
"000161": [
100,
40,
100,
54,
0,
100,
100,
45,
0
]
}
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for(var i=0; i<list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
function JordanFace() {
const bg_color = [0, 0, 0];
const fg_color = [255, 255, 255];
const stroke_color = [95, 52, 8];
this.eyepaint_value = 2;
this.mouth_value = 1;
this.tilt_value = 0;
this.colour2_value = 0;
this.draw = function(positions) {
rotate(this.tilt_value);
var eye1_pos = positions.left_eye;
var eye2_pos = positions.right_eye;
var toplip_pos = positions.top_lip;
var bottomlip_pos = positions.bottom_lip;
// Here I set my colour variables for the face and eye paint colour
if (this.colour_value === 1) {
var colour1 = color(240,10,10,120);
}
if (this.colour_value === 2) {
var colour1 = color(0,0,255,150);
}
if (this.colour_value === 3) {
var colour1 = color(255,255,255,120);
}
if (this.colour2_value === 1) {
var colour2 = color(240,10,10,80);
}
if (this.colour2_value === 2) {
var colour2 = color(0,0,255,80);
}
if (this.colour2_value === 3) {
var colour2 = color(255,255,255,80);
}
if (this.colour2_value === 4) {
var colour2 = color(255,255,255,0);
}
//face
// Here I use the points around the jaw and eyebrows to make a face shape that is filled
// to provide a base for the face paint
fill(colour2);
noStroke();
beginShape();
for(var i=0; i<positions.chin.length;i++) {
vertex(positions.chin[i][0], positions.chin[i][1]);
}
for(var i=positions.right_eyebrow.length-1; i>=0;i--) {
vertex(positions.right_eyebrow[i][0], positions.right_eyebrow[i][1]);
}
for(var i=positions.left_eyebrow.length-1; i>=0;i--) {
vertex(positions.left_eyebrow[i][0], positions.left_eyebrow[i][1]);
}
endShape(CLOSE);
// eyes
if (this.eyepaint_value === 1) {
;
// This is my first variant of the eye make up that makes a curved triangle going down from the eye.
fill(colour1);
beginShape();
vertex(eye1_pos[4][0]+.2 , eye1_pos[3][1]+.21);
quadraticVertex(-1.5, -.2, eye1_pos[1][0] -.4 , 1.2);
quadraticVertex(-1.5, -.2, eye1_pos[0][0] , eye1_pos[3][1]+.25);
endShape();
beginShape();
vertex(eye2_pos[4][0]-.2 , eye2_pos[3][1]+.21);
quadraticVertex(1.5, -.2, eye2_pos[1][0] +.4 , 1.2);
quadraticVertex(1.5, -.2, eye2_pos[3][0], eye2_pos[0][1]+.25);
endShape();
noStroke();
}
if (this.eyepaint_value === 2) {
;
// For my second eye make-up variant I've made a diamond shape mapped to the eye corners.
fill(colour1);
triangle(eye1_pos[3][0] +.2,eye1_pos[3][1],eye1_pos[0][0]-.25,eye1_pos[0][1],eye1_pos[2][0],-2.5);
triangle(eye1_pos[3][0]+.2,eye1_pos[3][1],eye1_pos[0][0]-.25,eye1_pos[0][1],eye1_pos[1][0],.5);
triangle(eye2_pos[3][0]+.25,eye2_pos[3][1],eye2_pos[0][0]-.2,eye2_pos[0][1],eye2_pos[1][0],-2.5);
triangle(eye2_pos[3][0]+.25,eye2_pos[3][1],eye2_pos[0][0]-.2,eye2_pos[0][1],eye2_pos[2][0],.5);
}
if (this.eyepaint_value === 3) {
;
// I've made a variant of the eye make up that is a stripe across the face
// I didn't end up using this variant as it does not work well visually
// However I've kept the code in place to show my process and so that it can be seen when changing the settings
fill(colour1);
rect(eye1_pos[0][0] -.25 ,eye1_pos[2][1] -.2,3,.6,.2);
}
// I've seperated the dark makeup around the eye from the other parts so I can turn it on and off independently.
// However I've left it on for all variants as it works best visually.
if (this.eyeshadow_value === 1) {
fill(0,0,0,120)
bezier(eye1_pos[3][0]+.2 , eye1_pos[3][1], -1.6 , -1.9 , -1.8 , -.3, eye1_pos[3][0]+.2 , eye1_pos[3][1] );
bezier(eye2_pos[0][0] -.2, eye2_pos[0][1], 1.6 , -1.9 , 1.8 , -.3, eye2_pos[0][0]-.2 , eye2_pos[0][1]);
fill(255,0,0);
fill(fg_color);
}
// mouth
if (this.mouth_value === 1) {
// My first mouth variant is a quad below the lip
fill(0,0,0,120);
quad(bottomlip_pos[2][0],bottomlip_pos[2][1],bottomlip_pos[4][0],bottomlip_pos[4][1],
bottomlip_pos[4][0] +.1,bottomlip_pos[4][1]+.6,bottomlip_pos[2][0] -.1,bottomlip_pos[2][1]+.6,2);
}
if (this.mouth_value === 2) {
// The second mouth variant is a kind of exaggerated lipstick that makes the mouth appear much larger.
fill(0,0,0,120);
bezier(toplip_pos[0][0]-.2, toplip_pos[0][1],0,toplip_pos[4][1]-.2,0,toplip_pos[4][1]-.2,toplip_pos[6][0]+.2,toplip_pos[6][1]);
bezier(toplip_pos[0][0]-.2, toplip_pos[0][1],-.4,bottomlip_pos[3][1]+.3,.4,bottomlip_pos[3][1]+.3,toplip_pos[6][0]+.2,toplip_pos[6][1]);
}
}
this.setProperties = function(settings) {
this.eyepaint_value = int(map(settings[0], 0, 100, 1, 3));
this.mouth_value = int(map(settings[1], 0, 100, 1, 2));
this.colour_value = int(map(settings[3], 0, 100 ,1, 3));
this.eyeshadow_value = int(map(settings[4], 0, 100 ,1, 2));
this.colour2_value = int(map(settings[5], 0, 100 ,1, 3));
}
this.getProperties = function() {
let settings = new Array(5);
settings[0] = map(this.eyepaint_value, 1, 3, 0, 100);
settings[1] = map(this.mouth_value, 1, 2, 0, 100);
settings[3] = map(this.colour_value, 1, 3, 0, 100);
settings[4] = map(this.eyeshadow_value, 1, 2, 0, 100);
settings[5] = map(this.colour2_value, 1, 3, 0, 100);
console.log(settings[5]);
return settings;
}
}
{
"000001": [
0,
75,
0,
0,
0,
100
],
"000002": [
50,
50,
null,
0,
0,
100
],
"000005": [
0,
0,
null,
0,
0,
100
],
"000006": [
50,
50,
null,
50,
0,
0
],
"000007": [
0,
100,
null,
0,
0,
100
],
"000009": [
50,
50,
null,
0,
0,
100
],
"000010": [
50,
50,
null,
0,
0,
100
],
"000013": [
0,
100,
null,
0,
0,
100
],
"000014": [
0,
0,
null,
50,
0,
0
],
"000015": [
0,
100,
null,
0,
0,
100
],
"000016": [
0,
100,
null,
0,
0,
100
],
"000018": [
50,
50,
null,
0,
0,
100
],
"000020": [
50,
100,
null,
0,
0,
100
],
"000023": [
0,
100,
null,
0,
0,
100
],
"000025": [
0,
100,
null,
0,
0,
100
],
"000028": [
50,
0,
null,
0,
0,
100
],
"000029": [
50,
50,
null,
0,
0,
100
],
"000030": [
0,
100,
null,
0,
0,
100
],
"000031": [
0,
0,
null,
0,
0,
100
],
"000032": [
0,
100,
null,
0,
0,
100
],
"000035": [
50,
50,
null,
0,
0,
100
],
"000037": [
0,
100,
null,
50,
0,
0
],
"000038": [
0,
100,
null,
0,
0,
100
],
"000040": [
0,
0,
null,
0,
0,
100
],
"000041": [
50,
100,
null,
100,
0,
50
],
"000042": [
50,
50,
null,
0,
0,
100
],
"000043": [
50,
50,
null,
0,
0,
100
],
"000044": [
50,
50,
null,
50,
0,
0
],
"000045": [
50,
0,
null,
0,
0,
100
],
"000047": [
50,
50,
null,
50,
0,
0
],
"000048": [
0,
100,
null,
0,
0,
100
],
"000050": [
0,
100,
null,
0,
0,
100
],
"000051": [
0,
100,
null,
0,
0,
100
],
"000052": [
0,
100,
null,
100,
0,
50
],
"000054": [
50,
50,
null,
0,
0,
100
],
"000055": [
0,
100,
null,
0,
0,
100
],
"000056": [
50,
0,
null,
0,
0,
100
],
"000058": [
50,
50,
null,
0,
0,
100
],
"000060": [
0,
100,
null,
50,
0,
0
],
"000064": [
0,
100,
null,
0,
0,
100
],
"000065": [
0,
100,
null,
100,
0,
50
],
"000068": [
0,
100,
null,
100,
0,
50
],
"000069": [
0,
100,
null,
0,
0,
100
],
"000071": [
50,
50,
null,
0,
0,
100
],
"000073": [
50,
50,
null,
0,
0,
100
],
"000076": [
0,
100,
null,
0,
0,
100
],
"000077": [
50,
50,
null,
0,
0,
100
],
"000078": [
50,
50,
null,
0,
0,
100
],
"000079": [
0,
100,
null,
0,
0,
100
],
"000080": [
0,
100,
null,
0,
0,
100
],
"000081": [
0,
100,
null,
0,
0,
100
],
"000083": [
50,
50,
null,
0,
0,
100
],
"000085": [
50,
50,
null,
0,
0,
100
],
"000086": [
0,
0,
null,
0,
0,
100
],
"000088": [
50,
50,
null,
0,
0,
100
],
"000091": [
0,
100,
null,
0,
0,
100
],
"000092": [
50,
50,
null,
0,
0,
100
],
"000096": [
50,
50,
null,
100,
0,
50
],
"000097": [
50,
50,
null,
0,
0,
100
],
"000099": [
50,
50,
null,
0,
0,
100
],
"000100": [
0,
0,
null,
0,
0,
100
],
"000103": [
50,
0,
null,
0,
0,
100
],
"000104": [
0,
100,
null,
0,
0,
100
],
"000106": [
50,
0,
null,
0,
0,
100
],
"000108": [
50,
50,
null,
0,
0,
100
],
"000109": [
0,
100,
null,
100,
0,
50
],
"000110": [
50,
50,
null,
0,
0,
100
],
"000111": [
0,
0,
null,
50,
0,
0
],
"000114": [
0,
100,
null,
0,
0,
100
],
"000115": [
0,
100,
null,
0,
0,
100
],
"000116": [
0,
100,
null,
0,
0,
100
],
"000117": [
50,
50,
null,
50,
0,
0
],
"000118": [
0,
0,
null,
50,
0,
0
],
"000121": [
50,
0,
null,
0,
0,
100
],
"000122": [
0,
0,
null,
0,
0,
100
],
"000125": [
0,
100,
null,
100,
0,
50
],
"000126": [
50,
50,
null,
100,
0,
50
],
"000129": [
0,
100,
null,
0,
0,
100
],
"000131": [
50,
50,
null,
100,
0,
50
],
"000132": [
50,
50,
null,
50,
0,
0
],
"000133": [
50,
0,
null,
0,
0,
100
],
"000134": [
0,
100,
null,
50,
0,
0
],
"000135": [
0,
100,
null,
50,
0,
0
],
"000137": [
0,
100,
null,
0,
0,
100
],
"000140": [
50,
0,
null,
0,
0,
100
],
"000142": [
50,
50,
null,
0,
0,
100
],
"000143": [
0,
100,
null,
0,
0,
100
],
"000145": [
50,
50,
null,
0,
0,
100
],
"000146": [
50,
50,
null,
100,
0,
50
],
"000147": [
50,
0,
null,
0,
0,
100
],
"000148": [
0,
0,
null,
0,
0,
100
],
"000150": [
0,
100,
null,
0,
0,
100
],
"000151": [
50,
50,
null,
50,
0,
0
],
"000152": [
0,
100,
null,
0,
0,
100
],
"000153": [
0,
100,
null,
0,
0,
100
],
"000155": [
50,
50,
null,
0,
0,
100
],
"000156": [
0,
0,
null,
0,
0,
100
],
"000157": [
50,
50,
null,
0,
0,
100
],
"000160": [
0,
100,
null,
0,
0,
100
],
"000161": [
50,
50,
null,
0,
0,
100
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// other variables can be in here too
// these control the colors used
const truLip = "#E37D55";
const truWhite = "#E3CFB9";
const truShadow = "#A06644";
const truMouth = "#2B1C17";
function JoyFace() {
// these are state variables for a face
// (your variables may be different)
this.wink_value = 1;//keep
this.colour_value = 0.5;//keep
this.hair_colour_value = 0.5;
this.eye_colour_value = 0.5;
this.brow_value = 0.5;
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
//Variables for face size and mouth status
var faceWidth = positions.chin[16][0] - positions.chin[0][0];//right of face - left of face = face width
var faceHeight = positions.chin[16][1] - positions.chin[0][1];//bottom of face - top of face = face height
//variables to indicate which side the face tends toward
var faceCenter = positions.chin[16][0] - faceWidth/2;//right of face - (face width/2) = center face position
var faceAngle = map(positions.nose_tip[2][0], positions.chin[0][0], positions.chin[16][0], -1, 1);//map middle of nose value to face width from left face-right face to -1 - +1
// print(faceAngle);
//if above val is >0, nose is on right. if val < 0, nose is on left
if((positions.top_lip[9][1] - positions.top_lip[0][1])>0){
var smile_Value = positions.top_lip[9][1] - positions.top_lip[0][1]
}
else{
var smile_Value = positions.top_lip[9][1] - positions.top_lip[6][1]; //corners of mouth are above/below mid top lip
}
var smile_Value = 2*positions.top_lip[9][1] - positions.top_lip[6][1]- positions.top_lip[0][1];
var mouthOpen_Value = positions.bottom_lip[9][1] - positions.top_lip[9][1]/*bottom of top lip*/; // distance between bottom middle of top lip and top middle of bottom lip
if(smile_Value > 0){//if smile_value is positive, smiling, else not smiling
var smile = true;
}
else{
var smile = false;
}
if (mouthOpen_Value > 0.1){// if mouthOpen_value is small (close to 0), the mouth is closed, else it is open
var mouthOpen = true;
}
else{
var mouthOpen = false;
}
if(faceAngle < 0.05){
var centerFaceDraw = positions.nose_tip[2][0] - faceCenter;
}
else if(faceAngle > 0.05){
var centerFaceDraw = positions.nose_tip[2][0] - faceCenter*-1;
}
else{
var centerFaceDraw = 0;
}
//face
var truBase = color(241, 141, 83);
var truBase2 = color(255, 199, 113);
var curBaseColour = lerpColor(truBase2, truBase, this.colour_value);
fill(curBaseColour);
noStroke();
beginShape();
for(var i=0; i<positions.chin.length;i++) {
vertex(positions.chin[i][0], positions.chin[i][1]);
}
for(var i=positions.right_eyebrow.length-1; i>=2;i--) {
vertex(positions.right_eyebrow[i][0], positions.right_eyebrow[i][1] - 1);
}
for(var i=positions.left_eyebrow.length-3; i>=0;i--) {
vertex(positions.left_eyebrow[i][0], positions.left_eyebrow[i][1] - 1);
}
endShape();
//eye fake tan rims
push();
scale(0.03);
noFill();
var l = 0.5*509.0/255;
strokeWeight(1.5);
push();
translate(-28, -32.5);
for (var i = 1; i<225*4; i+=32) {
stroke ( 255, 255, 240, 255-(i+200)/(l));
ellipse(positions.left_eye[0][0], positions.left_eye[0][1], i, i);
}
pop();
push();
translate(28, -32.5);
for (var i = 1; i<225*4; i+=32) {
stroke ( 255, 255, 210, 255-(i+200)/(l));
ellipse(positions.right_eye[0][0], positions.right_eye[0][1], i, i);
}
pop();
noStroke()
pop();
//eyes
//eye rim
//R
push();
scale(1.2);
translate(-0.1, 0.17);
fill(truShadow);
if (this.wink_value >= 0.5 ){
beginShape();
for(var i=0; i<positions.right_eye.length;i++) {
vertex(positions.right_eye[i][0], positions.right_eye[i][1]);
}
endShape();
}
else{
beginShape();
for(var i=0; i<positions.right_eye.length - 2;i++) {
vertex(positions.right_eye[i][0], positions.right_eye[i][1]);
}
vertex(positions.right_eye[1][0] + (positions.right_eye[2][0] - positions.right_eye[1][0])/2 - 0.04, positions.right_eye[1][1] +0.03 );
vertex(positions.right_eye[1][0] + (positions.right_eye[2][0] - positions.right_eye[1][0])/2 + 0.05, positions.right_eye[1][1] +0.02 );
endShape();
}
pop();
push()
scale(1.2);
translate(0.1, 0.17);
//L
fill(truShadow);
beginShape();
for(var i=0; i<positions.left_eye.length;i++) {
vertex(positions.left_eye[i][0], positions.left_eye[i][1]);
}
endShape();
pop();
//eye whites
//R
fill(truWhite);
if (this.wink_value >= 0.5 ){
beginShape();
for(var i=0; i<positions.right_eye.length;i++) {
vertex(positions.right_eye[i][0], positions.right_eye[i][1]);
}
endShape();
}
//L
fill(truWhite);
beginShape();
for(var i=0; i<positions.left_eye.length;i++) {
vertex(positions.left_eye[i][0], positions.left_eye[i][1]);
}
endShape();
noStroke();
//irises
var truIris1 = color(136, 173, 150);
var truIris2 =color(0, 47, 54);
var truIris3 = color(163, 97, 10);
var truIris4 =color(61, 33, 0);
//setting eye colour
if(this.eye_colour_value < 0.4){
var truIris = lerpColor(truIris1, truIris2, this.eye_colour_value);
}
else if(this.eye_colour_value >= 0.4 && this.eye_colour_value < 0.6){
var truIris = lerpColor(truIris2, truIris3, this.eye_colour_value);
}
else{
var truIris = lerpColor(truIris3, truIris4, this.eye_colour_value);
}
fill(truIris);
//R
if (this.wink_value >= 0.5 ){
beginShape();
vertex(positions.right_eye[1][0], positions.right_eye[1][1]);
vertex(positions.right_eye[2][0], positions.right_eye[2][1]);
vertex(positions.right_eye[4][0], positions.right_eye[4][1]-0.03);
vertex(positions.right_eye[5][0]+(positions.right_eye[4][0]-positions.right_eye[5][0])/2, positions.right_eye[4][1])
vertex(positions.right_eye[5][0], positions.right_eye[5][1]-0.03);
endShape();
}
//L
beginShape();
vertex(positions.left_eye[1][0], positions.left_eye[1][1]);
vertex(positions.left_eye[2][0], positions.left_eye[2][1]);
vertex(positions.left_eye[4][0], positions.left_eye[4][1]-0.03);
vertex(positions.left_eye[5][0]+(positions.left_eye[4][0]-positions.left_eye[5][0])/2, positions.left_eye[4][1])
vertex(positions.left_eye[5][0], positions.left_eye[5][1]-0.03);
endShape();
let bottomLip5 = positions.bottom_lip[3];
let topLip1 = positions.top_lip[0];
let topLip4 = positions.top_lip[3];
let topLip7 = positions.top_lip[6];
//lips
if (!smile && !mouthOpen){ //draw pucker
push();
translate (positions.nose_tip[2][0] - 3.1, positions.nose_tip[2][1] - 4.8);
scale(0.008, 0.0089);
fill(truLip);
beginShape();
vertex(390,571);
vertex(375,565);
vertex(367,570);
vertex(351,595);
vertex(334,623);
vertex(327,629);
vertex(331,634);
vertex(344,675);
vertex(366,703);
vertex(396,707);
vertex(417,698);
vertex(433,677);
vertex(442,644);
vertex(439,630);
vertex(445,627);
vertex(435,618);
vertex(427,594);
vertex(416,573);
vertex(405,565);
endShape();
//inside
fill(truMouth);
push();
scale(0.5);
translate(390, 650);
beginShape();
vertex(387,591);
vertex(369,597);
vertex(362,613);
vertex(356,625);
vertex(363,649);
vertex(387,653);
vertex(413,644);
vertex(418,623);
vertex(412,610);
vertex(404,589);
endShape();
pop();
pop();
}
else if (!smile && mouthOpen){ //draw shouting mouth
push();
translate (positions.nose_tip[2][0] - 3.1, positions.nose_tip[2][1] - 4.8);
scale(0.008, 0.0089);
fill(truLip);
beginShape();
vertex(390,571);
vertex(375,565);
vertex(367,570);
vertex(351,595);
vertex(334,623);
vertex(327,629);
vertex(331,634);
vertex(344,675);
vertex(366,703);
vertex(396,707);
vertex(417,698);
vertex(433,677);
vertex(442,644);
vertex(439,630);
vertex(445,627);
vertex(435,618);
vertex(427,594);
vertex(416,573);
vertex(405,565);
endShape();
//inside
fill(truMouth);
beginShape();
vertex(387,591);
vertex(369,597);
vertex(362,613);
vertex(356,625);
vertex(363,649);
vertex(387,653);
vertex(413,644);
vertex(418,623);
vertex(412,610);
vertex(404,589);
endShape();
//teeth1
fill(truWhite);
beginShape();
vertex(418,619);
vertex(386,618);
vertex(356,620);
vertex(363,649);
vertex(387,644);
vertex(413,644);
endShape();
//teeth2
beginShape();
vertex(409,599);
vertex(405,589);
vertex(369,596);
vertex(369,601);
vertex(369,596);
endShape();
pop();
}
else if (smile && !mouthOpen){ //grumpy face
push();
translate (positions.nose_tip[2][0] - 3.1, positions.nose_tip[2][1] - 4.9);
scale(0.008, 0.0089);
fill(truLip);
beginShape();
vertex(390,617);//cupids bow
vertex(375,617);//highest
vertex(367,617);
vertex(327,639);//left
vertex(366,650);
vertex(396,660);//lowest
vertex(417,650);
vertex(445,637);//right
vertex(416,627);
vertex(405,620);//highest2
endShape();
//inside
fill(truShadow);
beginShape();
vertex(387,630);//highest
vertex(362,635);
vertex(295,665);//left
vertex(363,649);
vertex(387,642);//lowest
vertex(413,645);
vertex(465,660);//right
vertex(412,630);
endShape();
pop();
}
else if (smile && mouthOpen){ //normal smile
//teeth
noStroke();
fill(truWhite);
beginShape();
vertex(topLip1[0], topLip1[1]);
vertex(topLip4[0], topLip4[1]);
vertex(topLip7[0], topLip7[1]);
vertex(bottomLip5[0], bottomLip5[1]);
vertex(topLip1[0], topLip1[1]);
endShape();
//lips
noStroke();
fill(truLip);
beginShape();
for(var i=0; i<positions.top_lip.length;i++) {
vertex(positions.top_lip[i][0], positions.top_lip[i][1]);
}
endShape();
beginShape();
for(var i=0; i<positions.bottom_lip.length;i++) {
vertex(positions.bottom_lip[i][0], positions.bottom_lip[i][1]);
}
endShape();
//under-mouth shadow
fill(truShadow);
beginShape();
if(faceAngle > -0.5){ //if not facing left
vertex(positions.bottom_lip[3][0] - 0.4,positions.bottom_lip[3][1] + 0.1);
vertex(positions.bottom_lip[3][0] - 0.3,positions.bottom_lip[3][1] + 0.08);
vertex(positions.bottom_lip[3][0] - 0.3,positions.bottom_lip[3][1] + 0.07);
}
else{
vertex(positions.bottom_lip[3][0] - 0,positions.bottom_lip[3][1] + 0.1);
vertex(positions.bottom_lip[3][0] - 0.1,positions.bottom_lip[3][1] + 0.08);
vertex(positions.bottom_lip[3][0] - 0.15,positions.bottom_lip[3][1] + 0.07);
}
vertex(positions.bottom_lip[3][0] - 0.03,positions.bottom_lip[3][1]);//bottom-most lip point
if(faceAngle < 0.5){ // if not facing right
vertex(positions.bottom_lip[3][0] + 0.2,positions.bottom_lip[3][1] + 0.03);
vertex(positions.bottom_lip[3][0] + 0.3,positions.bottom_lip[3][1] + 0.07);
vertex(positions.bottom_lip[3][0] + 0.3,positions.bottom_lip[3][1] + 0.08);
vertex(positions.bottom_lip[3][0] + 0.4,positions.bottom_lip[3][1] + 0.1);
}
else{
vertex(positions.bottom_lip[3][0] + 0.15,positions.bottom_lip[3][1] + 0.03);
vertex(positions.bottom_lip[3][0] + 0.2,positions.bottom_lip[3][1] + 0.07);
vertex(positions.bottom_lip[3][0] + 0.25,positions.bottom_lip[3][1] + 0.08);
vertex(positions.bottom_lip[3][0] + 0.15,positions.bottom_lip[3][1] + 0.1);
}
vertex(positions.bottom_lip[3][0],positions.bottom_lip[3][1] + 0.09);//mid bottom
endShape();
}
//Nose
let noseMidX = positions.nose_tip[2][0];
let noseMidY = positions.nose_tip[2][1];
let noseMLeftX = positions.nose_tip[1][0];
let noseMLeftY = positions.nose_tip[1][1];
let noseLeftX = positions.nose_tip[0][0];
let noseLeftY = positions.nose_tip[0][1];
let noseRightX = positions.nose_tip[4][0];
let noseRightY = positions.nose_tip[4][1];
let noseMRightX = positions.nose_tip[3][0];
let noseMRightY = positions.nose_tip[3][1];
fill(curBaseColour);
beginShape();
if(faceAngle <=-0.1){ // if face is pointed more toward the right
vertex(noseLeftX + 0.2, noseLeftY - 0.5);//left high
vertex(noseLeftX - 0.02, noseLeftY - 0.1);//left
vertex(noseLeftX + 0.08, noseLeftY + 0.08);
}
vertex(noseMLeftX - 0.02 , noseMLeftY - 0.05);
vertex(noseMLeftX + 0.05, noseMLeftY - 0.2);//left nostril
vertex(noseMLeftX + 0.1, noseMLeftY + 0.05);//left tip
vertex(noseMidX + 0.08, noseMidY - 0.08);//right tip
vertex(noseMRightX, noseMRightY - 0.1);//right nostril
vertex(noseMRightX + 0.05, noseMRightY + 0.05);
vertex(noseRightX, noseRightY);
if(faceAngle > 0.1){ //if face is pointed toward the left more
vertex(noseRightX - 0.2, noseRightY-0.5);//right high
}
endShape();
fill(truShadow);
beginShape();
if(faceAngle <=-0.1){ // if face is pointed more toward the right
vertex(noseLeftX + 0.2, noseLeftY - 0.8);//left high
vertex(noseLeftX - 0.02, noseLeftY - 0.1);//left
vertex(noseLeftX + 0.08, noseLeftY + 0.08);
}
vertex(noseMLeftX - 0.02 , noseMLeftY - 0.05);
vertex(noseMLeftX + 0.05, noseMLeftY - 0.2);//left nostril
vertex(noseMLeftX + 0.1, noseMLeftY + 0.05);//left tip
vertex(noseMidX + 0.08, noseMidY - 0.08);//right tip
vertex(noseMRightX, noseMRightY - 0.1);//right nostril
vertex(noseMRightX + 0.05, noseMRightY + 0.05);
vertex(noseRightX, noseRightY);
if(faceAngle > 0.1){ //if face is pointed toward the left more
vertex(noseRightX - 0.2, noseRightY-0.8);//right high
}
vertex(noseMRightX + 0.25, noseMRightY - 0.05);
vertex(noseMRightX + 0.03, noseMRightY + 0.1);
vertex(noseMRightX - 0.05, noseMRightY + 0.1);
vertex(noseMidX + 0.1, noseMidY + 0.04);
vertex(noseMidX - 0.13, noseMidY + 0.05);
vertex(noseMLeftX, noseMLeftY + 0.07);
vertex(noseMLeftX - 0.09 , noseMLeftY + 0.08);
vertex(noseLeftX - 0.02, noseLeftY + 0.1);
vertex(noseLeftX - 0.1, noseLeftY + 0.0);
endShape();
//shadows
//eyelids
//R
beginShape();
vertex(positions.right_eye[0][0], positions.right_eye[0][1] - 0.12);
vertex(positions.right_eye[1][0], positions.right_eye[1][1] - 0.1);
vertex(positions.right_eye[2][0], positions.right_eye[2][1] - 0.1);
vertex(positions.right_eye[3][0], positions.right_eye[3][1] - 0.12);
vertex(positions.right_eye[2][0], positions.right_eye[2][1] - 0.15);
vertex(positions.right_eye[1][0], positions.right_eye[1][1] - 0.15);
endShape();
beginShape();
vertex(positions.left_eye[0][0], positions.left_eye[0][1] - 0.1);
vertex(positions.left_eye[1][0], positions.left_eye[1][1] - 0.1);
vertex(positions.left_eye[2][0], positions.left_eye[2][1] - 0.1);
vertex(positions.left_eye[3][0], positions.left_eye[3][1] - 0.1);
vertex(positions.left_eye[2][0], positions.left_eye[2][1] - 0.15);
vertex(positions.left_eye[1][0], positions.left_eye[1][1] - 0.15);
endShape();
//Brows
var truhair = color(255, 206, 10);
var truhair2 = color(255, 246, 140);
var curHairColour = lerpColor(truhair2, truhair, this.hair_colour_value);
fill(curHairColour);
var browArch = map(this.brow_value, 0, 1, -0.23, 0.17);
//R
push();
beginShape();
vertex(positions.right_eyebrow[0][0], positions.right_eyebrow[0][1]);//left top
vertex(positions.right_eyebrow[2][0], positions.right_eyebrow[2][1] + browArch);//middle top
vertex(positions.right_eyebrow[4][0], positions.right_eyebrow[4][1]);//right top
vertex(positions.right_eyebrow[2][0], positions.right_eyebrow[2][1]+0.2 + browArch);//middle bottom
vertex(positions.right_eyebrow[0][0], positions.right_eyebrow[0][1]+0.2);//left bottom
endShape();
pop();
//L
beginShape();
vertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1]);//left top
vertex(positions.left_eyebrow[2][0], positions.left_eyebrow[2][1]);//middle top
vertex(positions.left_eyebrow[4][0], positions.left_eyebrow[4][1]);//right top
vertex(positions.left_eyebrow[4][0], positions.left_eyebrow[4][1]+0.2);
vertex(positions.left_eyebrow[2][0], positions.left_eyebrow[2][1]+0.2);//middle bottom
endShape();
//Hair
fill(curHairColour);
if(faceAngle <= -0.6){ //looking to the left the most (extreme)
push();
translate (-2.8, -4.8);
scale(0.008, 0.0089);
beginShape();
vertex(225,340);//corner
vertex(250,305);
vertex(333,276);
vertex(408,302);
vertex(534,329);
vertex(549,462);
vertex(561,482);
vertex(578,493);
vertex(600,454);
vertex(587,420);
vertex(591,382);
vertex(596,343);
vertex(588,322);
vertex(582,278);
vertex(607,252);
vertex(586,202);
vertex(536,190);
vertex(485,167);
vertex(419,157);//R
vertex(347,154);//highest
vertex(266,174);//L
vertex(198,199);
vertex(142,230);
vertex(142,261);
vertex(163,286);
endShape();
pop();
beginShape();
//hairline
vertex(positions.chin[15][0], positions.chin[15][1]);//face R
vertex(positions.chin[16][0] - 0.5, positions.chin[16][1]); // Face R
vertex(positions.right_eyebrow[3][0], positions.right_eyebrow[3][1] - 0.4);
vertex(positions.right_eyebrow[0][0], positions.right_eyebrow[2][1] - 0.45);
vertex(positions.right_eyebrow[0][0] - 0.7, positions.right_eyebrow[0][1] - 0.8);//mid forehead hair
vertex(positions.left_eyebrow[3][0] - 0.4, positions.right_eyebrow[2][1] - 0.4);
vertex(positions.left_eyebrow[0][0]+0.05, positions.left_eyebrow[0][1] - 0.5);
vertex(positions.chin[0][0], positions.chin[0][1]); //face L
vertex(positions.chin[1][0], positions.chin[1][1]);//face L
vertex(positions.chin[1][0]-0.1, positions.chin[1][1]);
//non-hairline
vertex(positions.chin[1][0] - 0.05, positions.chin[1][1] - 0.2);
vertex(positions.chin[0][0] - 0.15, positions.chin[0][1] - 0.35);
vertex(positions.chin[0][0] - 0.2, positions.chin[0][1] - 0.7);
vertex(positions.chin[0][0] - 0.1, positions.chin[0][1] - 1.4);
vertex(positions.right_eyebrow[2][0]- 1.7, positions.right_eyebrow[2][1] - 1);
vertex(positions.right_eyebrow[2][0]- 1.5, positions.right_eyebrow[2][1] - 1);
vertex(positions.right_eyebrow[2][0]- 1, positions.right_eyebrow[2][1] - 1.5);
vertex(positions.right_eyebrow[2][0] + 1, positions.right_eyebrow[2][1] - 1.3);
vertex(positions.right_eyebrow[2][0] + 1.9, positions.right_eyebrow[2][1] - 0.7);
vertex(positions.right_eyebrow[2][0] + 2, positions.right_eyebrow[2][1] - 0.4);
endShape();
}
else if(faceAngle < -0.5 && faceAngle > -0.6){ //looking to the left the most
push();
translate (-2.8, -4.8);
scale(0.008, 0.0089);
beginShape();
vertex(160,500);
pop();
push();
vertex(positions.chin[1][0] + 180,positions.chin[1][1] + 490);//lowest left
//scale(125, 112.35);
vertex(positions.chin[0][0] + 180,positions.chin[0][1]+490);
pop();
push();
translate (-2.8, -4.8);
scale(0.008, 0.0089);
vertex(210,335);//corner
vertex(250,305);
vertex(333,276);
vertex(408,302);
vertex(534,329);
vertex(549,462);
vertex(561,482);
vertex(578,493);
vertex(600,454);
vertex(587,420);
vertex(591,382);
vertex(596,343);
vertex(588,322);
vertex(582,278);
vertex(607,252);
vertex(586,202);
vertex(536,190);
vertex(485,167);
vertex(419,157);//R
vertex(347,154);//highest
vertex(266,174);//L
vertex(198,199);
vertex(132,230);
vertex(132,261);
vertex(153,286);
vertex(141,308);
vertex(150,337);
vertex(145,378);
vertex(135,427);
endShape();
pop();
beginShape();
//hairline
vertex(positions.chin[15][0], positions.chin[15][1]);//face R
vertex(positions.chin[16][0] - 0.5, positions.chin[16][1]); // Face R
vertex(positions.right_eyebrow[3][0], positions.right_eyebrow[3][1] - 0.4);
vertex(positions.right_eyebrow[0][0], positions.right_eyebrow[2][1] - 0.45);
vertex(positions.right_eyebrow[0][0] - 0.7, positions.right_eyebrow[0][1] - 0.8);//mid forehead hair
vertex(positions.left_eyebrow[3][0] - 0.4, positions.right_eyebrow[2][1] - 0.4);
vertex(positions.left_eyebrow[0][0]+0.05, positions.left_eyebrow[0][1] - 0.5);
vertex(positions.chin[0][0], positions.chin[0][1]); //face L
vertex(positions.chin[1][0], positions.chin[1][1]);//face L
vertex(positions.chin[1][0]-0.1, positions.chin[1][1]);
//non-hairline
vertex(positions.chin[1][0] - 0.05, positions.chin[1][1] - 0.2);
vertex(positions.chin[0][0] - 0.15, positions.chin[0][1] - 0.35);
vertex(positions.chin[0][0] - 0.2, positions.chin[0][1] - 0.7);
vertex(positions.chin[0][0] - 0.1, positions.chin[0][1] - 1.4);
vertex(positions.right_eyebrow[2][0]- 2.35, positions.right_eyebrow[2][1] - 1);
vertex(positions.right_eyebrow[2][0]- 1.5, positions.right_eyebrow[2][1] - 1.6);
vertex(positions.right_eyebrow[2][0]- 1, positions.right_eyebrow[2][1] - 1.5);
vertex(positions.right_eyebrow[2][0] + 1, positions.right_eyebrow[2][1] - 1.3);
vertex(positions.right_eyebrow[2][0] + 1.9, positions.right_eyebrow[2][1] - 0.7);
vertex(positions.right_eyebrow[2][0] + 2, positions.right_eyebrow[2][1] - 0.4);
endShape();
}
else if(faceAngle < -0.14 && faceAngle > -0.35){ //looking to the left smaller amount
push();
translate (-2.9, -4.8);
scale(0.008, 0.0089);
beginShape();
vertex(160,500);
pop();
push();
vertex(positions.chin[1][0] + 180,positions.chin[1][1] + 490);//lowest left
//scale(125, 112.35);
vertex(positions.chin[0][0] + 180,positions.chin[0][1]+490);
pop();
push();
translate (-2.9, -4.8);
scale(0.008, 0.0089);
vertex(210,335);//corner
vertex(250,305);
vertex(333,276);
vertex(408,302);
vertex(534,329);
vertex(549,462);
vertex(561,482);
vertex(578,493);
vertex(600,454);
vertex(587,420);
vertex(591,382);
vertex(596,343);
vertex(588,322);
vertex(582,278);
vertex(607,252);
vertex(586,202);
vertex(536,190);
vertex(485,167);
vertex(419,157);//R
vertex(347,154);//highest
vertex(266,174);//L
vertex(198,199);
vertex(132,230);
vertex(132,261);
vertex(153,286);
vertex(141,308);
vertex(150,337);
vertex(145,378);
vertex(135,427);
endShape();
pop();
beginShape();
//hairline
//vertex(positions.chin[15][0], positions.chin[15][1]);//face R
vertex(positions.chin[16][0], positions.chin[16][1]); // Face R
vertex(positions.right_eyebrow[3][0], positions.right_eyebrow[3][1] - 0.4);
vertex(positions.right_eyebrow[0][0], positions.right_eyebrow[2][1] - 0.45);
vertex(positions.right_eyebrow[0][0] - 0.7, positions.right_eyebrow[0][1] - 0.8);//mid forehead hair
vertex(positions.left_eyebrow[3][0] - 0.4, positions.right_eyebrow[2][1] - 0.4);
vertex(positions.left_eyebrow[0][0]+0.05, positions.left_eyebrow[0][1] - 0.5);
vertex(positions.chin[0][0], positions.chin[0][1]); //face L
vertex(positions.chin[1][0], positions.chin[1][1]);//face L
vertex(positions.chin[1][0]-0.1, positions.chin[1][1]);
//non-hairline
vertex(positions.chin[1][0] - 0.05, positions.chin[1][1] - 0.2);
vertex(positions.chin[0][0] - 0.15, positions.chin[0][1] - 0.35);
vertex(positions.chin[0][0] - 0.2, positions.chin[0][1] - 0.7);
vertex(positions.chin[0][0] - 0.1, positions.chin[0][1] - 1.4);
vertex(positions.right_eyebrow[2][0]- 2.35, positions.right_eyebrow[2][1] - 1);
vertex(positions.right_eyebrow[2][0]- 1.5, positions.right_eyebrow[2][1] - 1.6);
vertex(positions.right_eyebrow[2][0]- 1, positions.right_eyebrow[2][1] - 1.5);
vertex(positions.right_eyebrow[2][0]+ 1, positions.right_eyebrow[2][1]-1);
vertex(positions.right_eyebrow[2][0]+ 1.2, positions.right_eyebrow[2][1]- 0.5);
endShape();
}
else if(faceAngle <= -0.35){ //looking to the left more
push();
translate (-2.6, -4.8);
scale(0.008, 0.0089);
beginShape();
vertex(160,500);
pop();
push();
vertex(positions.chin[1][0] + 180,positions.chin[1][1] + 490);//lowest left
//scale(125, 112.35);
vertex(positions.chin[0][0] + 180,positions.chin[0][1]+490);
pop();
push();
translate (-2.7, -4.8);
scale(0.008, 0.0089);
vertex(210,335);//corner
vertex(250,305);
vertex(333,276);
vertex(408,302);
vertex(534,329);
vertex(549,462);
vertex(561,482);
vertex(578,493);
vertex(600,454);
vertex(587,420);
vertex(591,382);
vertex(596,343);
vertex(588,322);
vertex(582,278);
vertex(607,252);
vertex(586,202);
vertex(536,190);
vertex(485,167);
vertex(419,157);//R
vertex(347,154);//highest
vertex(266,174);//L
vertex(198,199);
vertex(132,230);
vertex(132,261);
vertex(153,286);
vertex(141,308);
vertex(150,337);
vertex(145,378);
vertex(135,427);
endShape();
pop();
beginShape();
//hairline
//vertex(positions.chin[15][0], positions.chin[15][1]);//face R
vertex(positions.chin[16][0], positions.chin[16][1]); // Face R
vertex(positions.right_eyebrow[3][0], positions.right_eyebrow[3][1] - 0.4);
vertex(positions.right_eyebrow[0][0], positions.right_eyebrow[2][1] - 0.45);
vertex(positions.right_eyebrow[0][0] - 0.7, positions.right_eyebrow[0][1] - 0.8);//mid forehead hair
vertex(positions.left_eyebrow[3][0] - 0.4, positions.right_eyebrow[2][1] - 0.4);
vertex(positions.left_eyebrow[0][0]+0.05, positions.left_eyebrow[0][1] - 0.5);
vertex(positions.chin[0][0], positions.chin[0][1]); //face L
vertex(positions.chin[1][0], positions.chin[1][1]);//face L
vertex(positions.chin[1][0]-0.1, positions.chin[1][1]);
//non-hairline
vertex(positions.chin[1][0] - 0.05, positions.chin[1][1] - 0.2);
vertex(positions.chin[0][0] - 0.15, positions.chin[0][1] - 0.35);
vertex(positions.chin[0][0] - 0.2, positions.chin[0][1] - 0.7);
vertex(positions.chin[0][0] - 0.1, positions.chin[0][1] - 1.4);
vertex(positions.right_eyebrow[2][0]- 2.35, positions.right_eyebrow[2][1] - 1);
vertex(positions.right_eyebrow[2][0]- 1.5, positions.right_eyebrow[2][1] - 1.6);
vertex(positions.right_eyebrow[2][0]- 1, positions.right_eyebrow[2][1] - 1.5);
vertex(positions.right_eyebrow[2][0]+ 1.55, positions.right_eyebrow[2][1]-1);
vertex(positions.right_eyebrow[2][0]+ 1.7, positions.right_eyebrow[2][1]- 0.5);
endShape();
}
else if(faceAngle >= -0.14 && faceAngle <= 0.14){ //looking straight on
push();
translate (-3.25, -4.8);
scale(0.0089);
beginShape();
vertex(160,500);
vertex(188,507);
vertex(190,407);
vertex(210,335);
vertex(250,305);
vertex(333,276);
vertex(408,302);
vertex(534,329);
vertex(549,462);
vertex(561,482);
vertex(578,493);
vertex(600,454);
vertex(587,420);
vertex(591,382);
vertex(596,343);
vertex(588,322);
vertex(582,278);
vertex(607,252);
vertex(586,202);
vertex(536,190);
vertex(485,167);
vertex(419,157);//R
vertex(347,154);//highest
vertex(266,174);//L
vertex(198,199);
vertex(132,230);
vertex(132,261);
vertex(153,286);
vertex(141,308);
vertex(138,337);
vertex(138,378);
vertex(135,427);
endShape();
pop();
beginShape();
//hairline
vertex(positions.chin[15][0], positions.chin[15][1]);//face R
vertex(positions.chin[16][0], positions.chin[16][1]); // Face R
vertex(positions.right_eyebrow[3][0], positions.right_eyebrow[3][1] - 0.4);
vertex(positions.right_eyebrow[0][0], positions.right_eyebrow[2][1] - 0.45);
vertex(positions.right_eyebrow[0][0] - 0.7, positions.right_eyebrow[0][1] - 0.8);//mid forehead hair
vertex(positions.left_eyebrow[3][0] - 0.4, positions.right_eyebrow[2][1] - 0.35);
vertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1] - 0.5);
vertex(positions.chin[0][0], positions.chin[0][1]); //face L
vertex(positions.chin[1][0], positions.chin[1][1]);//face L
//non-hairline
vertex(positions.chin[1][0] - 0.15, positions.chin[1][1] - 0.2);
vertex(positions.chin[0][0] - 0.25, positions.chin[0][1] - 0.35);
vertex(positions.chin[0][0] - 0.15, positions.chin[0][1] - 0.7);
vertex(positions.chin[0][0] + 0.2, positions.chin[0][1] - 1.3);
vertex(positions.right_eyebrow[2][0]- 2.5, positions.right_eyebrow[2][1] - 1);
vertex(positions.right_eyebrow[2][0]+ 0.6, positions.right_eyebrow[2][1] - 0.9);
endShape();
}
else if (faceAngle > 0.12 && faceAngle <=0.35){ // looking to the right a small amount
push();
translate (-3.35, -4.8);
scale(0.0087, 0.0089);
beginShape();
vertex(160,500);
vertex(188,507);
vertex(190,407);
vertex(210,335);
vertex(250,305);
vertex(333,276);
vertex(408,302);
vertex(534,329);
vertex(549,462);
vertex(561,482);
vertex(578,493);
vertex(600,454);
vertex(587,420);
vertex(591,382);
vertex(596,343);
vertex(588,322);
vertex(582,278);
vertex(607,252);
vertex(586,202);
vertex(536,190);
vertex(485,167);
vertex(419,157);//R
vertex(347,154);//highest
vertex(266,174);//L
vertex(198,199);
vertex(132,230);
vertex(132,261);
vertex(153,286);
vertex(141,308);
vertex(138,337);
vertex(138,378);
vertex(135,427);
endShape();
pop();
beginShape();
//hairline
vertex(positions.chin[15][0], positions.chin[15][1]);//face R
vertex(positions.chin[16][0], positions.chin[16][1]); // Face R
vertex(positions.right_eyebrow[3][0], positions.right_eyebrow[3][1] - 0.4);
vertex(positions.right_eyebrow[0][0], positions.right_eyebrow[2][1] - 0.45);
vertex(positions.right_eyebrow[0][0] - 0.7, positions.right_eyebrow[0][1] - 0.8);//mid forehead hair
vertex(positions.left_eyebrow[3][0] - 0.4, positions.right_eyebrow[2][1] - 0.35);
vertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1] - 0.5);
vertex(positions.chin[0][0], positions.chin[0][1]); //face L
vertex(positions.chin[1][0], positions.chin[1][1]);//face L
//non-hairline
vertex(positions.chin[1][0] - 0.15, positions.chin[1][1] - 0.2);
vertex(positions.chin[0][0] - 0.25, positions.chin[0][1] - 0.35);
vertex(positions.chin[0][0] - 0.15, positions.chin[0][1] - 0.7);
vertex(positions.chin[0][0] + 0.2, positions.chin[0][1] - 1.9);
vertex(positions.right_eyebrow[2][0]- 2.5, positions.right_eyebrow[2][1] - 1.4);
vertex(positions.right_eyebrow[2][0]+ 0.6, positions.right_eyebrow[2][1] - 0.9);
endShape();
}
else if(faceAngle >= 0.35 && faceAngle < 0.5){ //looking to right more
push();
translate (-3.6, -4.8);
scale(0.0087, 0.0089);
beginShape();
vertex(160,500);
vertex(188,507);
vertex(190,407);
vertex(210,335);
vertex(250,305);
vertex(333,276);
vertex(408,302);
vertex(534,329);
vertex(549,462);
vertex(561,482);
vertex(578,493);
vertex(600,454);
vertex(587,420);
vertex(591,382);
vertex(596,343);
vertex(588,322);
vertex(582,278);
vertex(607,252);
vertex(586,202);
vertex(536,190);
vertex(485,167);
vertex(419,157);//R
vertex(347,154);//highest
vertex(266,174);//L
vertex(198,199);
vertex(132,230);
vertex(132,261);
vertex(153,286);
vertex(141,308);
vertex(138,337);
vertex(138,378);
vertex(135,427);
endShape();
pop();
beginShape();
//hairline
vertex(positions.chin[15][0], positions.chin[15][1]);//face R
vertex(positions.chin[16][0], positions.chin[16][1]); // Face R
vertex(positions.right_eyebrow[3][0], positions.right_eyebrow[3][1] - 0.4);
vertex(positions.right_eyebrow[0][0], positions.right_eyebrow[2][1] - 0.45);
vertex(positions.right_eyebrow[0][0] - 0.7, positions.right_eyebrow[0][1] - 0.8);//mid forehead hair
vertex(positions.left_eyebrow[3][0] - 0.4, positions.right_eyebrow[2][1] - 0.35);
vertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1] - 0.5);
vertex(positions.chin[0][0], positions.chin[0][1]); //face L
vertex(positions.chin[1][0], positions.chin[1][1]);//face L
//non-hairline
vertex(positions.chin[1][0] - 0.15, positions.chin[1][1] - 0.2);
vertex(positions.chin[0][0] - 0.25, positions.chin[0][1] - 0.35);
vertex(positions.chin[0][0] - 0.15, positions.chin[0][1] - 0.7);
vertex(positions.chin[0][0] + 0.2, positions.chin[0][1] - 1.9);
vertex(positions.right_eyebrow[2][0]- 2.5, positions.right_eyebrow[2][1] - 1.4);
vertex(positions.right_eyebrow[2][0]+ 0.2, positions.right_eyebrow[2][1] - 0.5);
endShape();
}
else if(faceAngle>0.5 && faceAngle<0.6){ // looking to the right most
push();
translate (-3.6, -4.8);
scale(0.0087, 0.0089);
beginShape();
vertex(160,500);
vertex(188,507);
vertex(190,407);
vertex(210,335);
vertex(250,305);
vertex(333,276);
vertex(408,302);
vertex(534,329);
vertex(549,462);
vertex(561,482);
vertex(578,493);
vertex(600,454);
vertex(587,420);
vertex(591,382);
vertex(596,343);
vertex(588,322);
vertex(582,278);
vertex(607,252);
vertex(586,202);
vertex(536,190);
vertex(485,167);
vertex(419,157);//R
vertex(347,154);//highest
vertex(266,174);//L
vertex(198,199);
vertex(132,230);
vertex(132,261);
vertex(153,286);
vertex(141,308);
vertex(138,337);
vertex(138,378);
vertex(135,427);
endShape();
pop();
beginShape();
//hairline
vertex(positions.chin[15][0], positions.chin[15][1]);//face R
vertex(positions.chin[16][0], positions.chin[16][1]); // Face R
vertex(positions.right_eyebrow[3][0], positions.right_eyebrow[3][1] - 0.4);
vertex(positions.right_eyebrow[0][0], positions.right_eyebrow[2][1] - 0.45);
vertex(positions.right_eyebrow[0][0] - 0.7, positions.right_eyebrow[0][1] - 0.8);//mid forehead hair
vertex(positions.left_eyebrow[3][0] - 0.4, positions.right_eyebrow[2][1] - 0.35);
vertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1] - 0.5);
vertex(positions.chin[0][0], positions.chin[0][1]); //face L
vertex(positions.chin[1][0], positions.chin[1][1]);//face L
//non-hairline
vertex(positions.chin[1][0] - 0.15, positions.chin[1][1] - 0.2);
vertex(positions.chin[0][0] - 0.25, positions.chin[0][1] - 0.35);
vertex(positions.chin[0][0] - 0.15, positions.chin[0][1] - 0.7);
vertex(positions.chin[0][0] + 0.2, positions.chin[0][1] - 1.5);
vertex(positions.right_eyebrow[2][0]- 2.5, positions.right_eyebrow[2][1] - 1.2);
vertex(positions.right_eyebrow[2][0]+ 0.2, positions.right_eyebrow[2][1] - 0.5);
endShape();
}
else { // looking to the right most (extreme)
push();
translate (-3.6, -4.8);
scale(0.0087, 0.0089);
beginShape();
vertex(160,500);
vertex(188,507);
vertex(190,407);
vertex(210,335);
vertex(250,305);
vertex(333,276);
vertex(408,302);
vertex(534,329);
vertex(560,343);
vertex(588,322);
vertex(582,278);
vertex(607,252);
vertex(586,202);
vertex(536,190);
vertex(485,167);
vertex(419,157);//R
vertex(347,154);//highest
vertex(266,174);//L
vertex(198,199);
vertex(132,230);
vertex(132,261);
vertex(153,286);
vertex(141,308);
vertex(138,337);
vertex(138,378);
vertex(135,427);
endShape();
pop();
beginShape();
//hairline
vertex(positions.chin[15][0], positions.chin[15][1]);//face R
vertex(positions.chin[16][0], positions.chin[16][1]); // Face R
vertex(positions.right_eyebrow[3][0], positions.right_eyebrow[3][1] - 0.4);
vertex(positions.right_eyebrow[0][0], positions.right_eyebrow[2][1] - 0.45);
vertex(positions.right_eyebrow[0][0] - 0.7, positions.right_eyebrow[0][1] - 0.8);//mid forehead hair
vertex(positions.left_eyebrow[3][0] - 0.4, positions.right_eyebrow[2][1] - 0.35);
vertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1] - 0.5);
vertex(positions.chin[0][0], positions.chin[0][1]); //face L
vertex(positions.chin[1][0], positions.chin[1][1]);//face L
//non-hairline
vertex(positions.chin[1][0] - 0.15, positions.chin[1][1] - 0.2);
vertex(positions.chin[0][0] - 0.25, positions.chin[0][1] - 0.35);
vertex(positions.chin[0][0] - 0.15, positions.chin[0][1] - 0.7);
vertex(positions.chin[0][0] + 0.2, positions.chin[0][1] - 1.5);
vertex(positions.right_eyebrow[2][0]- 2.5, positions.right_eyebrow[2][1] - 1.2);
vertex(positions.right_eyebrow[2][0]+ 0.2, positions.right_eyebrow[2][1] - 0.5);
endShape();
}
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.wink_value = map(settings[0], 0, 100, 0, 1);
this.colour_value = map(settings[1], 0, 100, 0, 1);
this.hair_colour_value = map(settings[2], 0, 100, 0, 1);
this.eye_colour_value = map(settings[3], 0, 100, 0, 1);
this.brow_value = map(settings[4], 0, 100, 0, 1);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(5);
settings[0] = map(this.wink_value, 0, 1, 0, 100);
settings[1] = map(this.colour_value, 0, 1, 0, 100);
settings[2] = map(this.hair_colour_value, 0, 1, 0, 100);
settings[3] = map(this.eye_colour_value, 0, 1, 0, 100);
settings[4] = map(this.brow_value, 0, 1, 0, 100);
return settings;
}
}
// given an array of [x,y] points, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for(var i=0; i<list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
{
"000001": [
0,
17,
56.99999999999999,
98,
0,
null,
null
],
"000002": [
0,
0,
51,
100,
0,
null,
null
],
"000005": [
0,
11,
11,
0,
100,
null,
null
],
"000006": [
0,
100,
80,
100,
62,
null,
null
],
"000007": [
100,
11,
100,
100,
100,
null,
null
],
"000009": [
0,
0,
87,
53,
1,
null,
null
],
"000010": [
0,
0,
0,
0,
69,
null,
null
],
"000013": [
100,
13,
0,
1,
0,
null,
null
],
"000014": [
0,
100,
100,
100,
50,
null,
null
],
"000015": [
100,
0,
100,
22,
90,
null,
null
],
"000016": [
100,
25,
100,
100,
31,
null,
null
],
"000018": [
0,
0,
0,
10,
0,
null,
null
],
"000020": [
100,
17,
100,
39,
89,
null,
null
],
"000023": [
100,
0,
100,
0,
18,
null,
null
],
"000025": [
100,
16,
89,
100,
89,
null,
null
],
"000028": [
0,
39,
62,
100,
1,
null,
null
],
"000029": [
0,
0,
0,
0,
0,
null,
null
],
"000030": [
100,
41,
42,
100,
100,
null,
null
],
"000031": [
0,
0,
70,
0,
0,
null,
null
],
"000032": [
100,
8,
43,
100,
100,
null,
null
],
"000035": [
0,
0,
100,
52,
81,
null,
null
],
"000037": [
100,
100,
100,
100,
100,
null,
null
],
"000038": [
100,
21,
100,
0,
0,
null,
null
],
"000040": [
0,
0,
100,
52,
30,
null,
null
],
"000041": [
100,
32,
100,
100,
0,
null,
null
],
"000042": [
0,
1,
64,
0,
21,
null,
null
],
"000043": [
0,
6,
93,
48,
0,
null,
null
],
"000044": [
0,
100,
100,
100,
51,
null,
null
],
"000045": [
0,
8,
55.00000000000001,
100,
0,
null,
null
],
"000047": [
0,
100,
100,
100,
0,
null,
null
],
"000048": [
100,
0,
100,
22,
100,
null,
null
],
"000050": [
100,
14.000000000000002,
100,
88,
0,
null,
null
],
"000051": [
100,
34,
50,
100,
28.999999999999996,
null,
null
],
"000052": [
100,
39,
91,
0,
39,
null,
null
],
"000054": [
0,
0,
0,
13,
0,
null,
null
],
"000055": [
100,
10,
100,
100,
100,
null,
null
],
"000056": [
100,
0,
100,
26,
52,
null,
null
],
"000058": [
0,
0,
100,
0,
100,
null,
null
],
"000060": [
100,
99,
69,
100,
0,
null,
null
],
"000064": [
100,
0,
100,
0,
51,
null,
null
],
"000065": [
100,
55.00000000000001,
100,
100,
0,
null,
null
],
"000068": [
100,
35,
91,
78,
0,
null,
null
],
"000069": [
100,
9,
100,
87,
100,
null,
null
],
"000071": [
0,
3,
0,
0,
15,
null,
null
],
"000073": [
0,
14.000000000000002,
100,
70,
41,
null,
null
],
"000076": [
100,
10,
100,
100,
78,
null,
null
],
"000077": [
0,
0,
100,
49,
28.000000000000004,
null,
null
],
"000078": [
0,
0,
98,
17,
24,
null,
null
],
"000079": [
100,
22,
56.00000000000001,
100,
31,
null,
null
],
"000080": [
100,
0,
100,
0,
32,
null,
null
],
"000081": [
100,
52,
100,
100,
0,
null,
null
],
"000083": [
0,
1,
66,
16,
31,
null,
null
],
"000085": [
0,
0,
60,
12,
25,
null,
null
],
"000086": [
0,
0,
68,
57.99999999999999,
100,
null,
null
],
"000088": [
0,
0,
49,
100,
100,
null,
null
],
"000091": [
100,
0,
100,
32,
100,
null,
null
],
"000092": [
0,
7.000000000000001,
0,
0,
18,
null,
null
],
"000096": [
0,
18,
100,
100,
100,
null,
null
],
"000097": [
0,
1,
35,
0,
75,
null,
null
],
"000099": [
0,
21,
30,
9,
0,
null,
null
],
"000100": [
0,
1,
26,
100,
51,
null,
null
],
"000103": [
0,
0,
92,
4,
100,
null,
null
],
"000104": [
100,
0,
31,
0,
0,
null,
null
],
"000106": [
0,
39,
77,
100,
0,
null,
null
],
"000108": [
0,
0,
1,
0,
0,
null,
null
],
"000109": [
100,
25,
65,
0,
21,
null,
null
],
"000110": [
0,
0,
62,
0,
0,
null,
null
],
"000111": [
0,
100,
32,
95,
0,
null,
null
],
"000114": [
100,
0,
100,
100,
0,
null,
null
],
"000115": [
100,
0,
41,
2,
50,
null,
null
],
"000116": [
100,
0,
91,
99,
0,
null,
null
],
"000117": [
0,
100,
100,
97,
24,
null,
null
],
"000118": [
0,
85,
100,
85,
28.999999999999996,
null,
null
],
"000121": [
0,
50,
100,
87,
21,
null,
null
],
"000122": [
0,
0,
0,
85,
0,
null,
null
],
"000125": [
100,
36,
52,
1,
73,
null,
null
],
"000126": [
0,
53,
0,
0,
0,
null,
null
],
"000129": [
100,
0,
100,
0,
0,
null,
null
],
"000131": [
0,
86,
100,
100,
0,
null,
null
],
"000132": [
0,
99,
100,
100,
0,
null,
null
],
"000133": [
0,
9,
35,
0,
0,
null,
null
],
"000134": [
100,
100,
100,
100,
0,
null,
null
],
"000135": [
100,
89,
100,
100,
28.999999999999996,
null,
null
],
"000137": [
100,
4,
0,
18,
0,
null,
null
],
"000140": [
0,
50,
1,
0,
100,
null,
null
],
"000142": [
0,
0,
100,
0,
100,
null,
null
],
"000143": [
100,
0,
82,
0,
0,
null,
null
],
"000145": [
0,
5,
100,
87,
0,
null,
null
],
"000146": [
0,
39,
83,
100,
0,
null,
null
],
"000147": [
0,
40,
21,
49,
80,
null,
null
],
"000148": [
0,
0,
100,
2,
89,
null,
null
],
"000150": [
100,
1,
52,
11,
51,
null,
null
],
"000151": [
0,
77,
100,
100,
0,
null,
null
],
"000152": [
100,
11,
49,
9,
0,
null,
null
],
"000153": [
100,
13,
100,
55.00000000000001,
0,
null,
null
],
"000155": [
0,
30,
49,
88,
0,
null,
null
],
"000156": [
0,
0,
0,
0,
0,
null,
null
],
"000157": [
0,
0,
0,
0,
79,
null,
null
],
"000160": [
100,
0,
100,
100,
80,
null,
null
],
"000161": [
0,
0,
100,
0,
0,
null,
null
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// other variables can be in here too
// these control the colors used
const core_colour = [240, 200, 10];
const light_colour = [240, 215, 24];
const shadow_colour = [165, 42, 42, 15];
const hair_light = [255, 204, 0];
function Kelly19Face() {
// these are state variables for a face
// (your variables may be different)
this.eye_type = 1; // defines eye type
this.hair_colour = color(255, 200, 100); // eyebrow colour
this.eyebrow_width = 0.1;
this.eyelid_type = 1;
this.teeth = 50;
this.lip_colour = 0;
this.facial_hair = 0;
this.eye_colour = 255;
this.makeup = 1;
//size variables
this.x_percentage = 1;
this.y_percentage = 1;
let hair_light = color("#fabc37");
let hair_dark = color("#302E23");
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
//shifts face to the left/right to approximate rotation
let face_rotate = map(positions.nose_bridge[3][0], -1, 1, 1.5, -1.5);
//eye values -------------------------------------------------------------------------------------------------------------- //
//eye centers
let left_eye = average_point(positions.left_eye);
let right_eye = average_point(positions.right_eye);
//eye size
let left_eye_size = abs(positions.left_eye[0][0] - positions.left_eye[3][0]);
let right_eye_size = abs(positions.right_eye[0][0] - positions.right_eye[3][0]);
// calculate average eye angle
let left_eye_angle = average_angle(positions.left_eye);
let right_eye_angle = average_angle(positions.right_eye);
//eye squint
let left_eye_squint = constrain(average_distance(positions.left_eye) * 6, 1, 8);
let right_eye_squint = constrain(average_distance(positions.right_eye) * 6, 1, 8);
let hair_colour = lerpColor(hair_light, hair_dark, this.hair_colour);
head(face_rotate, -0.5);
if (this.eye_type <= 1) {
open_eye(left_eye, left_eye_size, left_eye_angle, left_eye_squint, this.eyelid_type, this.eye_colour, this.makeup);
open_eye(right_eye, right_eye_size, right_eye_angle, right_eye_squint, this.eyelid_type, this.eye_colour, this.makeup);
// eye_detail(left_eye, left_eye_size, left_eye_angle, -1);
// eye_detail(right_eye, right_eye_size, right_eye_angle, 1);
eyebrows_flow(positions.left_eyebrow, this.eyebrow_width, hair_colour);
eyebrows_flow(positions.right_eyebrow.reverse(), this.eyebrow_width, hair_colour);
} else if (this.eye_type <= 2) {
classic_eye(left_eye, left_eye_size);
classic_eye(right_eye, right_eye_size);
eyebrows_flow(positions.left_eyebrow, this.eyebrow_width, hair_colour);
eyebrows_flow(positions.right_eyebrow.reverse(), this.eyebrow_width, hair_colour);
} else if (this.eye_type <= 3) {
cross_eye(left_eye, left_eye_size, left_eye_angle);
cross_eye(right_eye, right_eye_size, right_eye_angle);
eyebrows_flow(positions.left_eyebrow, this.eyebrow_width, hair_colour);
eyebrows_flow(positions.right_eyebrow.reverse(), this.eyebrow_width, hair_colour);
} else if (this.eye_type <= 4) {
eyebrows_flow(positions.left_eyebrow, this.eyebrow_width, hair_colour);
eyebrows_flow(positions.right_eyebrow.reverse(), this.eyebrow_width, hair_colour);
heart_eye(left_eye, left_eye_size, left_eye_angle);
heart_eye(right_eye, right_eye_size, right_eye_angle);
}
open_mouth(positions.top_lip, positions.bottom_lip, this.teeth, this.lip_colour);
let left_backup = positions.left_eye;
let eyelid_left = positions.left_eye.slice();
let eyelid_right = positions.right_eye.slice();
let left_removed = eyelid_left.splice(1, 2);
let left_1 = eyelid_left[1];
let left_2 = eyelid_left[3];
let left_3 = eyelid_left[2];
let left_4 = eyelid_left[0];
eyelid_left = [left_1, left_2, left_3, left_4];
eye_shadow(positions.left_eyebrow, eyelid_left);
let right_removed = eyelid_right.splice(1, 2);
let right_1 = eyelid_right[0];
let right_2 = eyelid_right[2];
let right_3 = eyelid_right[3];
let right_4 = eyelid_right[1];
eyelid_right = [right_1, right_2, right_3, right_4];
eye_shadow(positions.right_eyebrow.reverse(), eyelid_right.reverse());
//glasses(left_eye, right_eye, left_eye_angle,right_eye_angle,left_eye_size,right_eye_size);
nose(positions.nose_bridge, positions.nose_tip);
//glasses_bridge(left_eye, right_eye, left_eye_angle,right_eye_angle,left_eye_size,right_eye_size,face_rotate);
//light reflection
push();
noFill();
scale(0.9);
translate(face_rotate, -0.5);
rectMode(CENTER);
scale(0.3);
strokeWeight(0.5);
stroke(255, 70);
arc(-4.5, -4.5, 3, 3, 180, 270);
pop();
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.hair_colour = map(settings[0], 0, 100, 0, 1);
this.eyebrow_width = map(settings[1], 0, 100, 0.05, 0.25);
this.eyelid_type = map(settings[2], 0, 100, 0, 4);
this.eye_colour = map(settings[3], 0, 100, 0, 360);
this.lip_colour = map(settings[4], 0, 100, 0, 1);
this.teeth = map(settings[5], 0, 100, 0, 100);
this.makeup = map(settings[6], 0, 100, 0, 5);
this.eye_type = map(settings[7], 0, 100, 0, 4);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(8);
settings[0] = map(this.hair_colour, 0, 1, 0, 100);
settings[1] = map(this.eyebrow_width, 0.05, 0.25, 0, 100);
settings[2] = map(this.eyelid_type, 0, 4, 0, 100);
settings[3] = map(this.eye_colour, 0, 360, 0, 100);
settings[4] = map(this.lip_colour, 0, 1, 0, 100);
settings[5] = map(this.teeth, 0, 100, 0, 100);
settings[6] = map(this.makeup, 0, 5, 0, 100);
settings[7] = map(this.eye_type, 0, 4, 0, 100);
return settings;
}
// given an array of [x,y] points, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for (var i = 0; i < list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
}
function head(center_x, center_y) {
push();
noStroke();
scale(0.9);
translate(center_x, center_y);
this.x_percentage = 1;
this.y_percentage = 1;
rectMode(CENTER);
scale(0.3);
push();
fill(0, 10);
rect(0, 0, 17 * this.x_percentage, 14 * this.y_percentage, 2.5); //core
rect(0, 8, 10 * this.x_percentage, 2 * this.y_percentage); // bottom
rect(0, -8.5, 7 * this.x_percentage, 3 * this.y_percentage, 0.5, 0.5, 0, 0); // top
pop();
//fill core colour
fill(core_colour);
rect(0, 0, 17 * this.x_percentage, 14 * this.y_percentage, 2.5); //core
rect(0, 8, 10 * this.x_percentage, 2 * this.y_percentage); // bottom
rect(0, -8.5, 7 * this.x_percentage, 3 * this.y_percentage, 0.5, 0.5, 0, 0); // top
//fill highlight
fill(light_colour);
rect(0, 0, 17 * 0.8 * this.x_percentage, 14 * this.y_percentage, 2.5); //core
rect(0, 8, 10 * 0.8 * this.x_percentage, 2 * this.y_percentage); // bottom
rect(0, -8.5, 7 * 0.64 * this.x_percentage, 3 * this.y_percentage, 0.5, 0.5, 0, 0); // top
//fill shadow
fill(shadow_colour);
rect(0, 7.5 * this.x_percentage, 10 * this.y_percentage, 1);
pop();
}
function angle(cx, cy, ex, ey) {
var dy = ey - cy;
var dx = ex - cx;
var theta = Math.atan2(dy, dx); // range (-PI, PI]
theta *= 180 / Math.PI; // rads to degs, range (-180, 180]
//if (theta < 0) theta = 360 + theta; // range [0, 360)
theta = theta - 90;
return theta;
}
function average_angle(eye) {
let a1 = angle(eye[1][0], eye[1][1], eye[5][0], eye[5][1]);
let a2 = angle(eye[2][0], eye[2][1], eye[4][0], eye[4][1]);
let average = (a1 + a2) / 2;
return average;
}
function distance(x1, y1, x2, y2) {
var dy = abs(y2 - y1);
var dx = abs(x2 - x1);
var dist = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
return dist;
}
function average_distance(eye) {
let d1 = distance(eye[1][0], eye[1][1], eye[5][0], eye[5][1]);
let d2 = distance(eye[2][0], eye[2][1], eye[4][0], eye[4][1]);
let average = (d1 + d2) / 2;
return average;
}
function eye_shadow(eyebrow, eye) {
push();
fill(0, 10);
noStroke();
beginShape();
curveVertex(eyebrow[0][0], eyebrow[0][1]);
curveVertex(eyebrow[1][0], eyebrow[1][1]);
curveVertex(eyebrow[2][0], eyebrow[2][1]);
curveVertex(eyebrow[3][0], eyebrow[3][1]);
curveVertex(eyebrow[4][0], eyebrow[4][1]);
curveVertex(eye[0][0], eye[0][1]);
curveVertex(eye[1][0], eye[1][1]);
curveVertex(eye[2][0], eye[2][1]);
curveVertex(eye[3][0], eye[3][1]);
curveVertex(eyebrow[0][0], eyebrow[0][1]);
curveVertex(eyebrow[1][0], eyebrow[1][1]);
endShape(CLOSE);
pop();
}
function nose(nose_bridge, nose_tip) {
let nose_offset = 0.5;
//backing
fill(light_colour);
noStroke();
beginShape()
vertex(nose_bridge[0][0], nose_bridge[0][1] - nose_offset);
vertex(nose_tip[0][0], nose_tip[0][1] - nose_offset);
vertex(nose_tip[nose_tip.length - 1][0], nose_tip[nose_tip.length - 1][1] - nose_offset);
endShape(CLOSE);
//bridge
strokeWeight(0.07);
noFill();
stroke(core_colour);
beginShape();
curveVertex(nose_bridge[0][0], nose_bridge[0][1] - nose_offset);
for (var i = 0; i < nose_bridge.length; i++) {
curveVertex(nose_bridge[i][0], nose_bridge[i][1] - nose_offset);
}
curveVertex(nose_bridge[nose_bridge.length - 1][0], nose_bridge[nose_bridge.length - 1][1] - nose_offset);
endShape();
stroke(core_colour);
beginShape();
curveVertex(nose_bridge[2][0], nose_bridge[2][1] - nose_offset);
for (var i = 2; i < nose_bridge.length; i++) {
curveVertex(nose_bridge[i][0], nose_bridge[i][1] - nose_offset);
}
curveVertex(nose_bridge[nose_bridge.length - 1][0], nose_bridge[nose_bridge.length - 1][1] - nose_offset);
endShape();
//tip
stroke(core_colour);
strokeWeight(0.1);
noFill();
beginShape();
curveVertex(nose_tip[0][0], nose_tip[0][1] - nose_offset);
for (var i = 1; i < nose_tip.length - 1; i++) {
curveVertex(nose_tip[i][0], nose_tip[i][1] - nose_offset);
}
curveVertex(nose_tip[nose_tip.length - 1][0], nose_tip[nose_tip.length - 1][1] - nose_offset);
endShape();
push();
fill(0,20);
noStroke();
ellipse(nose_tip[1][0], nose_tip[1][1] - nose_offset,0.1,0.05);
ellipse(nose_tip[nose_tip.length-2][0], nose_tip[nose_tip.length-2][1] - nose_offset,0.1,0.05);
pop();
push();
ellipseMode(CENTER);
noFill();
stroke(core_colour);
strokeWeight(0.05);
translate(nose_tip[nose_tip.length-2][0], nose_tip[nose_tip.length-2][1] - nose_offset);
//rotate(45);
arc(0, 0, 0.3, 0.3, 315, 0);
pop();
push();
ellipseMode(CENTER);
noFill();
stroke(core_colour);
strokeWeight(0.05);
translate(nose_tip[1][0], nose_tip[1][1] - nose_offset);
//rotate(-45);
arc(0, 0, 0.3, 0.3, 180, 235);
pop();
}
function open_eye(pos, eye_size, eye_angle, eye_squint, eyelid_type, eye_colour, makeup) {
push();
translate(pos[0], pos[1]);
noStroke();
//eye background/tiredness - could be randomised
fill(core_colour);
ellipse(0, 0, eye_size * 1.2, eye_size * 1.2);
push();
fill(255, 100, 20, makeup);
for (let i = 0; i < 20; i++) {
ellipse(0, 0, eye_size * 1 + (0.025 * i), eye_size + 1 * (0.025 * i));
}
pop();
//eye fill - solid black
fill(0);
ellipse(0, 0, eye_size, eye_size);
push();
colorMode(HSL);
if(eye_colour > 0 && eye_colour< 360){
fill(eye_colour, 100, 20);
ellipse(0, 0, eye_size * 0.7, eye_size * 0.7);
}
pop();
//white eye detail
fill(255);
ellipse(-eye_size / 7, -eye_size / 7, eye_size / 2.5, eye_size / 2.5);
rotate(eye_angle);
if (eyelid_type <= 1) {
//none
} else if (eyelid_type > 1 && eyelid_type <= 2) {
//bttm rd
eyelid_bottom_rd(eye_size, eye_squint);
} else if (eyelid_type > 2 && eyelid_type <= 3) {
//top rd
eyelid_top_rd(eye_size, eye_squint);
} else if (eyelid_type > 3 && eyelid_type <= 4) {
//both rd
eyelid_top_rd(eye_size, eye_squint);
eyelid_bottom_rd(eye_size, eye_squint);
}
pop();
}
function closed_eye(pos, eye_size, eye_angle) {
push();
translate(pos[0], pos[1]);
rotate(eye_angle);
stroke(0);
strokeWeight(0.15);
line(-eye_size / 2, 0, eye_size / 2, 0);
pop();
}
function eyelid_top_rd(size, squint) {
push();
noStroke();
fill(light_colour);
translate(0, -size * squint / 2);
scale(1.5);
ellipse(0, 0, size, size / 2);
pop();
}
function eyelid_bottom_rd(size, squint) {
push();
noStroke();
fill(light_colour);
translate(0, size * squint / 2);
scale(1.5);
ellipse(0, 0, size, size / 2);
//highlight_colour.setAlpha(map(squint, 1.3, 1.9, 70, 0));
stroke(255, 20);
strokeWeight(0.05);
noFill();
arc(0, 0, size / 1, size / 2.5, 215, 325);
//highlight_colour.setAlpha(70);
pop();
}
function eyelid_top_sq(size, squint) {
push();
rectMode(CENTER);
noStroke();
fill(light_colour);
translate(0, -size * squint / 2);
scale(1.5);
rect(0, 0, size, size / 2);
pop();
}
function eyelid_bottom_sq(size, squint) {
push();
rectMode(CENTER);
noStroke();
fill(light_colour);
translate(0, size * squint / 2);
scale(1.5);
rect(0, 0, size, size / 2);
//highlight_colour.setAlpha(map(squint, 1.3, 1.9, 70, 0));
stroke(255, 20);
strokeWeight(0.05);
noFill();
//arc(0, 0, size / 1, size / 2.5, 215, 325);
//highlight_colour.setAlpha(70);
pop();
}
function eyebrows(eyebrow, width) {
//eyebrow
push();
curveTightness(0);
strokeJoin(ROUND);
noFill();
stroke(light_colour);
strokeWeight(width * 1.7);
beginShape();
curveVertex(eyebrow[0][0], eyebrow[0][1]);
for (var i = 1; i < eyebrow.length; i++) {
curveVertex(eyebrow[i][0], eyebrow[i][1]);
}
curveVertex(eyebrow[eyebrow.length - 1][0], eyebrow[eyebrow.length - 1][1]);
endShape();
stroke(0, 200);
strokeWeight(width);
beginShape();
curveVertex(eyebrow[0][0], eyebrow[0][1]);
for (var i = 1; i < eyebrow.length; i++) {
curveVertex(eyebrow[i][0], eyebrow[i][1]);
}
curveVertex(eyebrow[eyebrow.length - 1][0], eyebrow[eyebrow.length - 1][1]);
endShape();
pop();
}
function eyebrows_flow(eyebrow, width, colour) {
//eyebrow
push();
fill(light_colour);
stroke(light_colour);
strokeWeight(width);
beginShape();
curveVertex(eyebrow[0][0], eyebrow[0][1]);
curveVertex(eyebrow[0][0], eyebrow[0][1]);
curveVertex(eyebrow[1][0], eyebrow[1][1] - width / 2);
curveVertex(eyebrow[2][0], eyebrow[2][1] - width / 2);
curveVertex(eyebrow[3][0], eyebrow[3][1] - width / 2);
curveVertex(eyebrow[4][0], eyebrow[4][1]);
curveVertex(eyebrow[3][0], eyebrow[3][1] + width / 2)
curveVertex(eyebrow[2][0], eyebrow[2][1] + width / 2);
curveVertex(eyebrow[1][0], eyebrow[1][1] + width / 2);
curveVertex(eyebrow[0][0], eyebrow[0][1]);
curveVertex(eyebrow[0][0], eyebrow[0][1]);
endShape();
pop();
push();
noStroke();
fill(colour);
beginShape();
curveVertex(eyebrow[0][0], eyebrow[0][1]);
curveVertex(eyebrow[0][0], eyebrow[0][1]);
curveVertex(eyebrow[1][0], eyebrow[1][1] - width / 2);
curveVertex(eyebrow[2][0], eyebrow[2][1] - width / 2);
curveVertex(eyebrow[3][0], eyebrow[3][1] - width / 2);
curveVertex(eyebrow[4][0], eyebrow[4][1]);
curveVertex(eyebrow[3][0], eyebrow[3][1] + width / 2)
curveVertex(eyebrow[2][0], eyebrow[2][1] + width / 2);
curveVertex(eyebrow[1][0], eyebrow[1][1] + width / 2);
curveVertex(eyebrow[0][0], eyebrow[0][1]);
curveVertex(eyebrow[0][0], eyebrow[0][1]);
endShape();
pop();
push();
noStroke();
fill(0, 20);
beginShape();
curveVertex(eyebrow[0][0], eyebrow[0][1]);
curveVertex(eyebrow[0][0], eyebrow[0][1]);
curveVertex(eyebrow[1][0], eyebrow[1][1]);
curveVertex(eyebrow[2][0], eyebrow[2][1]);
curveVertex(eyebrow[3][0], eyebrow[3][1]);
curveVertex(eyebrow[4][0], eyebrow[4][1]);
curveVertex(eyebrow[3][0], eyebrow[3][1] + width / 2)
curveVertex(eyebrow[2][0], eyebrow[2][1] + width / 2);
curveVertex(eyebrow[1][0], eyebrow[1][1] + width / 2);
curveVertex(eyebrow[0][0], eyebrow[0][1]);
curveVertex(eyebrow[0][0], eyebrow[0][1]);
endShape();
pop();
}
function cross_eye(pos, eye_size, eye_angle) {
push();
translate(pos[0], pos[1]);
rotate(eye_angle);
stroke(0);
strokeWeight(0.15);
eye_size = eye_size * 0.5;
line(-eye_size / 2, eye_size / 2, eye_size / 2, -eye_size / 2);
line(-eye_size / 2, -eye_size / 2, eye_size / 2, eye_size / 2);
pop();
}
function classic_eye(pos, eye_size) {
push();
translate(pos[0], pos[1]);
noStroke();
fill(core_colour);
eye_size = eye_size / 1.5;
ellipse(0, 0, eye_size * 1.5, eye_size * 1.5);
fill(0);
ellipse(0, 0, eye_size, eye_size);
pop();
}
function heart_eye(pos, eye_size, angle) {
push();
translate(pos[0], pos[1] - 0.2);
rotate(angle)
scale(0.9);
noStroke();
push();
fill(139, 0, 0, 200);
scale(1.2);
beginShape();
vertex(0, 0);
bezierVertex(-eye_size / 2, -eye_size / 2, -eye_size, eye_size / 3, 0, eye_size);
bezierVertex(eye_size, eye_size / 3, eye_size / 2, -eye_size / 2, 0, 0);
endShape(CLOSE);
pop();
fill('#C91A09');
beginShape();
vertex(0, 0);
bezierVertex(-eye_size / 2, -eye_size / 2, -eye_size, eye_size / 3, 0, eye_size);
bezierVertex(eye_size, eye_size / 3, eye_size / 2, -eye_size / 2, 0, 0);
endShape(CLOSE);
push();
noFill();
strokeWeight(0.1);
stroke(255, 150);
arc(0, eye_size / 4, eye_size, eye_size / 2, 190, 210);
pop();
pop();
}
function eye_detail(pos, eye_size, angle, dir) {
push();
let detail_angle = 30;
let line_num = 3;
translate(pos[0], pos[1]);
rotate(angle);
stroke(core_colour);
strokeWeight(0.07);
//translate(eye_size / 2 * dir, 0);
rotate(-detail_angle / 2);
for (let i = 0; i < line_num; i++) {
line(eye_size / 1.2 * dir, 0, eye_size * 1.2 * dir, 0);
rotate(detail_angle / line_num);
}
pop();
}
function glasses(left_eye, right_eye, left_angle,right_angle,left_size,right_size) {
push();
stroke(0);
strokeCap(SQUARE);
rectMode(CENTER);
noFill();
strokeWeight(0.7);
//line(0, 0, dir * eye_spacing / 2 - dir * eye_size * 1.7 / 2, 0);
strokeWeight(0.12);
push();
translate(left_eye[0],left_eye[1]);
rect(0, 0, left_size * 1.8, left_size * 1.3, 0.2, 0.2, 0.2, 0.2);
pop();
push();
translate(right_eye[0],right_eye[1]);
rect(0, 0, right_size * 1.8, right_size * 1.3, 0.2, 0.2, 0.2, 0.2);
pop();
pop();
}
function glasses_bridge(left_eye, right_eye, left_angle,right_angle,left_size,right_size,face_rotate) {
push();
stroke(0);
strokeCap(SQUARE);
rectMode(CENTER);
noFill();
translate(face_rotate, -0.5);
strokeWeight(0.17);
let y = (left_eye[1] + right_eye[1])/2 - 0.2;
line(left_eye[0]+left_size*0.85 - face_rotate,y+0.5, right_eye[0]-right_size*0.85 - face_rotate,y+0.5);
line(left_eye[0]-left_size*0.85 - face_rotate,y+0.5, -17*0.27/2,y+0.5);
line(right_eye[0]+right_size*0.85 - face_rotate,y+0.5, 17*0.27/2,y+0.5);
pop();
}
function classic_mouth(mouth_width, mouth_height, mouth_emotion) {
push();
noFill();
strokeWeight(0.4);
translate(0, mouth_height);
stroke(0);
arc(0, 0, mouth_width, 1, 0, 180);
pop();
}
function open_mouth(top_lip, bottom_lip, teeth, lip_colour) {
let offset = 0.5;
push();
noStroke();
fill(0);
scale(1.1);
beginShape();
vertex(bottom_lip[11][0], bottom_lip[11][1] - offset);
vertex(bottom_lip[10][0], bottom_lip[10][1] - offset);
vertex(bottom_lip[9][0], bottom_lip[9][1] - offset);
vertex(bottom_lip[8][0], bottom_lip[8][1] - offset);
vertex(top_lip[11][0], top_lip[11][1] - offset);
vertex(top_lip[10][0], top_lip[10][1] - offset);
vertex(top_lip[9][0], top_lip[9][1] - offset);
vertex(top_lip[8][0], top_lip[8][1] - offset);
vertex(top_lip[7][0], top_lip[7][1] - offset);
endShape();
pop();
//let teeth_top = 0.15;
let teeth_top = map(teeth, 0, 100, 0, 0.15);
push();
fill(255);
noStroke();
beginShape();
curveVertex(top_lip[11][0], top_lip[11][1] - offset);
curveVertex(top_lip[11][0], top_lip[11][1] - offset);
curveVertex(top_lip[10][0], top_lip[10][1] - offset);
curveVertex(top_lip[9][0], top_lip[9][1] - offset);
curveVertex(top_lip[8][0], top_lip[8][1] - offset);
curveVertex(top_lip[7][0], top_lip[7][1] - offset);
curveVertex(top_lip[8][0], top_lip[8][1] - offset + teeth_top);
curveVertex(top_lip[9][0], top_lip[9][1] - offset + teeth_top);
curveVertex(top_lip[10][0], top_lip[10][1] - offset + teeth_top);
endShape(CLOSE);
pop();
//let teeth_bottom = 0.1;
if (teeth >= 80) {
let teeth_bottom = map(teeth, 80, 100, 0, 0.1);
push();
fill(255);
noStroke();
beginShape();
curveVertex(bottom_lip[11][0], bottom_lip[11][1] - offset);
curveVertex(bottom_lip[11][0], bottom_lip[11][1] - offset);
curveVertex(bottom_lip[10][0], bottom_lip[10][1] - offset);
curveVertex(bottom_lip[9][0], bottom_lip[9][1] - offset);
curveVertex(bottom_lip[8][0], bottom_lip[8][1] - offset);
curveVertex(bottom_lip[7][0], bottom_lip[7][1] - offset);
curveVertex(bottom_lip[8][0], bottom_lip[8][1] - offset - teeth_bottom);
curveVertex(bottom_lip[9][0], bottom_lip[9][1] - offset - teeth_bottom);
curveVertex(bottom_lip[10][0], bottom_lip[10][1] - offset - teeth_bottom);
endShape(CLOSE);
pop();
}
push();
noStroke();
let c1 = color('#f0c80a');
let c2 = color('#ffc694');
let c3 = color('#ff9494');
let c4 = color('#ff0000');
let c5 = color('#690000');
let lip_fill = color('#f0c80a')
if (lip_colour <= 0.25) {
lip_fill = lerpColor(c1, c2, map(lip_colour, 0, 0.25, 0, 1));
fill(lip_fill);
} else if (lip_colour <= 0.5) {
lip_fill = lerpColor(c2, c3, map(lip_colour, 0.25, 0.5, 0, 1));
fill(lip_fill);
} else if (lip_colour <= 0.75) {
lip_fill = lerpColor(c3, c4, map(lip_colour, 0.5, 0.75, 0, 1));
fill(lip_fill);
} else {
lip_fill = lerpColor(c4, c5, map(lip_colour, 0.75, 1, 0, 1));
fill(lip_fill);
}
beginShape();
curveVertex(top_lip[0][0], top_lip[0][1] - offset);
for (var i = 0; i < top_lip.length; i++) {
curveVertex(top_lip[i][0], top_lip[i][1] - offset);
}
curveVertex(top_lip[top_lip.length - 1][0], top_lip[top_lip.length - 1][1] - offset);
endShape(CLOSE);
beginShape();
curveVertex(bottom_lip[0][0], bottom_lip[0][1] - offset);
for (var i = 0; i < bottom_lip.length; i++) {
curveVertex(bottom_lip[i][0], bottom_lip[i][1] - offset);
}
curveVertex(bottom_lip[bottom_lip.length - 1][0], bottom_lip[bottom_lip.length - 1][1] - offset);
endShape(CLOSE);
pop();
push();
if (lip_colour <= 0.25) {
fill(0, 15);
} else {
fill(0, 50);
}
noStroke();
beginShape();
vertex(bottom_lip[0][0], bottom_lip[0][1] - offset);
vertex(bottom_lip[1][0], bottom_lip[1][1] - offset);
vertex(bottom_lip[2][0], bottom_lip[2][1] - offset);
vertex(bottom_lip[3][0], bottom_lip[3][1] - offset);
vertex(bottom_lip[4][0], bottom_lip[4][1] - offset);
vertex(bottom_lip[5][0], bottom_lip[5][1] - offset);
vertex(bottom_lip[6][0], bottom_lip[6][1] - offset);
vertex(bottom_lip[7][0], bottom_lip[7][1] - offset);
vertex(bottom_lip[8][0], bottom_lip[8][1] - offset + 0.1);
vertex(bottom_lip[9][0], bottom_lip[9][1] - offset + 0.1);
vertex(bottom_lip[10][0], bottom_lip[10][1] - offset + 0.1);
vertex(bottom_lip[11][0], bottom_lip[11][1] - offset + 0.1);
endShape(CLOSE);
beginShape();
vertex(top_lip[0][0], top_lip[0][1] - offset);
vertex(top_lip[1][0], top_lip[1][1] - offset + 0.1);
vertex(top_lip[2][0], top_lip[2][1] - offset + 0.1);
vertex(top_lip[3][0], top_lip[3][1] - offset + 0.1);
vertex(top_lip[4][0], top_lip[4][1] - offset + 0.1);
vertex(top_lip[5][0], top_lip[5][1] - offset + 0.1);
vertex(top_lip[6][0], top_lip[6][1] - offset);
vertex(top_lip[7][0], top_lip[7][1] - offset);
vertex(top_lip[8][0], top_lip[8][1] - offset);
vertex(top_lip[9][0], top_lip[9][1] - offset);
vertex(top_lip[10][0], top_lip[10][1] - offset);
vertex(top_lip[11][0], top_lip[11][1] - offset);
endShape(CLOSE);
pop();
push();
ellipseMode(CENTER);
noFill();
stroke(core_colour);
strokeWeight(0.05);
translate(top_lip[6][0], top_lip[6][1] - offset);
arc(0, 0, 0.3, 0.3, 315, 45);
pop();
push();
ellipseMode(CENTER);
noFill();
stroke(core_colour);
strokeWeight(0.05);
translate(top_lip[0][0], top_lip[0][1] - offset);
arc(0, 0, 0.3, 0.3, 135, 235);
pop();
}
function tongue_out(mouth_width, mouth_height, mouth_emotion) {
push();
noFill();
strokeWeight(0.5);
translate(0, mouth_height);
stroke(0);
arc(0, 0, mouth_width, 1, 0, 180);
pop();
}
function line_mouth(mouth_width, mouth_height, mouth_emotion, dir) {
push();
noFill();
strokeWeight(0.4);
translate(dir * 0.5, mouth_height);
stroke(0);
//line(-mouth_width, 0, mouth_width, 0);
curveTightness(0);
beginShape();
curveVertex(dir * -mouth_width / 1.5, -mouth_emotion / 4);
curveVertex(dir * -mouth_width / 1.5, -mouth_emotion / 4);
curveVertex(dir * mouth_width / 3 / 1.5, -mouth_emotion / 4);
//curveVertex(mouth_width / 2, 0);
curveVertex(dir * mouth_width / 1.5, mouth_emotion / 3);
curveVertex(dir * mouth_width / 1.5, mouth_emotion / 3);
endShape();
strokeWeight(0.2);
stroke('#B58800');
if (dir > 0) {
if (mouth_emotion > 0) {
push();
translate(dir * mouth_width / 1.5, mouth_emotion / 3);
arc(0, 0, 1, 1, 0, 90);
pop();
} else {
push();
translate(dir * mouth_width / 1.5, mouth_emotion / 3);
arc(0, 0, 1.2, 1.2, 270, 0);
pop();
}
} else {
if (mouth_emotion > 0) {
push();
translate(dir * mouth_width / 1.5, mouth_emotion / 3);
arc(0, 0, 1, 1, 90, 180);
pop();
} else {
push();
translate(dir * mouth_width / 1.5, mouth_emotion / 3);
arc(0, 0, 1.2, 1.2, 180, 270);
pop();
}
}
pop();
}
function butt_chin(mouth_width, mouth_height, mouth_emotion) {
push();
noFill();
strokeWeight(0.4);
translate(0, mouth_height);
stroke(0);
arc(0, 0, mouth_width * 2, mouth_emotion * 4, 0, 180);
pop();
}
{
"000001": [
61,
30,
63,
5.999999999999999,
76,
73,
100,
0
],
"000002": [
0,
30,
32,
14.000000000000002,
69,
100,
100,
0
],
"000005": [
2,
98,
37,
50,
63,
19,
100,
0
],
"000006": [
47,
28.000000000000004,
92,
13,
63,
97,
100,
0
],
"000007": [
92,
89.00000000000003,
43,
7.000000000000001,
0,
0,
0,
0
],
"000009": [
77,
65,
39,
16,
63,
100,
100,
0
],
"000010": [
27,
26,
82,
54,
52,
32,
100,
0
],
"000013": [
0,
82.00000000000001,
48,
51,
0,
100,
0,
0
],
"000014": [
75,
32,
31,
0,
69,
100,
100,
0
],
"000015": [
61,
91.00000000000003,
41,
57.99999999999999,
0,
21,
0,
0
],
"000016": [
39,
77.00000000000001,
41,
11.999999999999998,
0,
0,
0,
0
],
"000018": [
33,
26,
36,
18,
49,
100,
100,
35
],
"000020": [
70,
97,
84,
50,
0,
21,
0,
33
],
"000023": [
74,
94,
45,
53,
0,
16,
0,
0
],
"000025": [
78,
100,
69,
5.999999999999999,
0,
17,
0,
0
],
"000028": [
0,
20.999999999999996,
32,
9,
62,
73,
100,
0
],
"000029": [
25,
35.99999999999999,
66,
50,
52,
100,
100,
0
],
"000030": [
36,
100,
50,
28.000000000000004,
0,
0,
0,
32
],
"000031": [
12,
31,
41,
51,
44,
100,
100,
0
],
"000032": [
61,
100,
93,
74,
2,
28.000000000000004,
0,
0
],
"000035": [
100,
17.999999999999993,
42,
15,
62,
18,
100,
0
],
"000037": [
100,
100,
28.000000000000004,
100,
0,
0,
0,
0
],
"000038": [
83,
100,
41,
53,
0,
100,
0,
8
],
"000040": [
100,
17.999999999999993,
71,
9,
70,
0,
100,
0
],
"000041": [
100,
100,
37,
50,
0,
100,
0,
0
],
"000042": [
69,
27,
76,
54,
68,
13,
100,
0
],
"000043": [
68,
28.999999999999996,
80,
14.000000000000002,
60,
100,
100,
0
],
"000044": [
89,
20.999999999999996,
86,
0,
88,
14.000000000000002,
100,
2
],
"000045": [
49,
23,
96,
9,
53,
100,
100,
0
],
"000047": [
100,
15,
91,
0,
53,
100,
100,
0
],
"000048": [
97,
83.00000000000001,
78,
0,
0,
0,
0,
0
],
"000050": [
91,
80.00000000000001,
81,
0,
0,
100,
0,
0
],
"000051": [
89,
78.00000000000001,
86,
23,
0,
0,
0,
30
],
"000052": [
68,
100,
46,
47,
0,
0,
0,
0
],
"000054": [
50,
28.000000000000004,
44,
64,
49,
100,
100,
0
],
"000055": [
88,
86.00000000000001,
67,
11,
0,
0,
0,
0
],
"000056": [
86,
20.000000000000004,
38,
51,
28.999999999999996,
15,
71,
0
],
"000058": [
100,
0,
84,
52,
87,
0,
100,
0
],
"000060": [
71,
81.00000000000001,
28.000000000000004,
15,
0,
86,
0,
0
],
"000064": [
71,
91.00000000000003,
45,
50,
0,
23,
0,
0
],
"000065": [
92,
50.000000000000014,
100,
11.999999999999998,
0,
100,
0,
2
],
"000068": [
89,
80.00000000000001,
86,
13,
0,
100,
42.00000000000001,
26
],
"000069": [
72,
98,
86,
14.000000000000002,
0,
31,
18,
0
],
"000071": [
0,
28.999999999999996,
100,
13,
62,
100,
100,
0
],
"000073": [
38,
24,
86,
17,
50,
100,
100,
0
],
"000076": [
81,
100,
87,
0,
0,
16,
0,
0
],
"000077": [
100,
20.000000000000004,
36,
0,
39,
10,
100,
0
],
"000078": [
94,
24,
32,
13,
69,
30,
100,
0
],
"000079": [
68,
87.00000000000003,
46,
11,
0,
19,
0,
37
],
"000080": [
74,
74.00000000000001,
93,
50,
0,
11,
0,
0
],
"000081": [
100,
80.00000000000001,
41,
7.000000000000001,
0,
100,
0,
0
],
"000083": [
34,
13.000000000000004,
42,
11,
89,
33,
100,
0
],
"000085": [
38,
26,
50,
14.000000000000002,
65,
0,
100,
0
],
"000086": [
33,
6.999999999999999,
95,
50,
72,
100,
100,
0
],
"000088": [
50,
13.000000000000004,
50,
14.000000000000002,
50,
100,
100,
0
],
"000091": [
91,
100,
52,
18,
0,
0,
0,
0
],
"000092": [
18,
43,
30,
15,
71,
100,
100,
0
],
"000096": [
100,
30,
83,
15,
67,
14.000000000000002,
100,
0
],
"000097": [
22,
33,
78,
51,
55.00000000000001,
100,
100,
0
],
"000099": [
50,
12.000000000000004,
50,
50,
46,
68,
100,
0
],
"000100": [
28.999999999999996,
34.99999999999999,
45,
14.000000000000002,
74,
32,
100,
0
],
"000103": [
72,
23,
77,
36,
81,
16,
100,
0
],
"000104": [
50,
59.999999999999986,
35,
50,
0,
100,
0,
0
],
"000106": [
100,
21.999999999999996,
46,
9,
57.99999999999999,
100,
100,
0
],
"000108": [
50,
23,
50,
47.99999999999999,
71,
100,
100,
0
],
"000109": [
41,
69,
36,
50,
0,
100,
0,
0
],
"000110": [
27,
34.99999999999999,
30,
50,
43,
100,
100,
0
],
"000111": [
2,
30,
100,
17,
50,
100,
100,
0
],
"000114": [
44,
100,
39,
17,
0,
87,
0,
0
],
"000115": [
0,
83.00000000000001,
40,
50,
0,
13,
0,
0
],
"000116": [
84,
75.00000000000001,
17,
5.999999999999999,
0,
100,
0,
0
],
"000117": [
100,
4,
11,
0,
72,
100,
100,
0
],
"000118": [
56.99999999999999,
24,
13,
10,
63,
9,
100,
0
],
"000121": [
84,
20.000000000000004,
78,
7.000000000000001,
61,
0,
100,
0
],
"000122": [
50,
20.000000000000004,
50,
11,
67,
100,
100,
32
],
"000125": [
93,
83.00000000000001,
43,
50,
0,
17,
0,
48
],
"000126": [
32,
17.999999999999993,
46,
25,
63,
100,
100,
0
],
"000129": [
100,
87.00000000000003,
28.000000000000004,
18,
18,
100,
46.99999999999999,
0
],
"000131": [
96,
20.999999999999996,
65,
0,
60,
100,
100,
0
],
"000132": [
100,
16,
85,
8,
56.99999999999999,
100,
100,
0
],
"000133": [
17,
30,
36,
49,
54,
100,
100,
0
],
"000134": [
67,
92.00000000000003,
45,
0,
0,
100,
0,
0
],
"000135": [
100,
100,
28.000000000000004,
0,
0,
18,
50,
0
],
"000161": [
78,
17.999999999999993,
41,
23.999999999999996,
59,
100,
100,
0
],
"000160": [
90,
86.00000000000001,
43,
14.000000000000002,
0,
22,
0,
0
],
"000157": [
25,
32,
31,
49,
50,
20,
100,
0
],
"000156": [
5,
27,
50,
50,
50,
50,
50,
0
],
"000155": [
12,
19.000000000000004,
39,
4,
64,
100,
100,
0
],
"000137": [
46,
100,
35,
53,
0,
100,
0,
0
],
"000140": [
14.000000000000002,
40,
50,
47.99999999999999,
51,
0,
100,
0
],
"000143": [
69,
85.00000000000001,
50,
50,
0,
100,
0,
0
],
"000145": [
82,
26,
50,
5.999999999999999,
49,
100,
100,
0
],
"000146": [
12,
58.999999999999986,
42,
8,
70,
93,
100,
0
],
"000147": [
27,
28.999999999999996,
50,
50,
50,
100,
50,
0
],
"000148": [
90,
19.000000000000004,
50,
50,
46,
100,
100,
0
],
"000150": [
0,
100,
55.00000000000001,
36,
0,
35,
69,
0
],
"000151": [
81,
25,
46,
0,
61,
100,
100,
0
],
"000152": [
56.00000000000001,
77.00000000000001,
50,
18,
0,
100,
18,
0
],
"000153": [
70,
78.00000000000001,
46,
11.999999999999998,
0,
100,
0,
0
],
"000142": [
50,
50.000000000000014,
50,
50,
50,
13,
50,
0
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// other variables can be in here too
// these control the colors used
const kelly_bg_color = [225, 206, 187];
const kelly_fg_color = [151, 102, 52];
const kelly_stroke_color = [95, 52, 8];
function KellyFace() {
this.hairColor = 50;
this.wrinkleWeight = 50;
this.skinColor = 50;
this.spots = 50;
this.draw = function(positions) {
var base_tone1 = color("#ffcfaf"); //light color
var base_tone2 = color("#a56e48"); //dark color
var blush_base = color("#701702");
var nose_pos = average_point(positions.nose_bridge);
var eye1_pos = average_point(positions.left_eye);
var eye2_pos = average_point(positions.right_eye);
var half_height = positions.chin[7][1] - nose_pos[1];
var face_width = positions.chin[positions.chin.length - 1][0] - positions.chin[0][0];
//mine
var chin_R = positions.chin[positions.chin.length - 1];
var chin_L = positions.chin[0];
var chin_center = positions.chin[8];
var eyecorner_L = positions.left_eye[0];
var eyecorner_R = positions.right_eye[3];
var x = nose_pos[0];
var y = nose_pos[1];
var w = 2 * face_width;
var h = 2.5 * half_height;
// var curHairLength = map(this.hairLength, 0, 100, 0, 3);
var curHairColor = map(this.hairColor, 0, 120, 255, 20);
var curWrinkleWeight = map(this.wrinkleWeight, 0, 100, 0.0001, 0.065);
var curSpots = map(this.spots, 0, 100, 0, 1);
var curSkincolor = map(this.skinColor, 0, 100, 0, 1);
var skin_tone = lerpColor(base_tone1,base_tone2,curSkincolor);
var blush_color = lerpColor(blush_base,skin_tone,0.55);
var extent = 0;
if (h < w) {
extent = h / 2;
} else {
extent = w / 2;
}
var scale = extent / 220.0;
var eyeShift = 0.35;
for (var i = positions.left_eye.length - 1; i >= 0; i--) {
positions.left_eye[i][1]+=eyeShift;
positions.right_eye[i][1]+=eyeShift;
}
eye1_pos = average_point(positions.left_eye);
eye2_pos = average_point(positions.right_eye);
var eye3_pos = average_point([eye1_pos,eye2_pos]);
//head
var foreheadCenter = average_point([chin_L, chin_R]);
var face_height = distanceBetween(foreheadCenter, chin_center);
push();
noFill();
stroke(blush_color);
fill(skin_tone);
strokeWeight(0.07);
//head outline
beginShape();
curveVertex(-1.5, -2);
curveVertex(chin_L[0], chin_L[1]);
curveVertex(positions.chin[2][0], positions.chin[2][1]);
curveVertex(positions.chin[4][0], positions.chin[4][1]);
curveVertex(positions.chin[6][0], positions.chin[6][1]);
curveVertex(chin_center[0], chin_center[1]);
curveVertex(positions.chin[10][0], positions.chin[10][1]);
curveVertex(positions.chin[12][0], positions.chin[12][1]);
curveVertex(positions.chin[14][0], positions.chin[14][1]);
curveVertex(chin_R[0], chin_R[1]);
//forehead
curveVertex(chin_R[0] - 0.5, chin_R[1] - face_height * 0.45);
curveVertex(foreheadCenter[0], foreheadCenter[1] - face_height * 0.65);
curveVertex(chin_L[0] + 0.5, chin_L[1] - face_height * 0.45);
//close
curveVertex(chin_L[0], chin_L[1]);
curveVertex(positions.chin[1][0], positions.chin[1][1]);
endShape();
pop();
//wrinkels
var wrink_width = face_width*0.2;
var wrink_stroke = curWrinkleWeight;
if (wrink_stroke > 0.0001) {
push();
translate(eye3_pos[0],face_height*-0.65);
rotate(angleBetween(eye1_pos,eye2_pos));
noFill();
stroke(blush_color);
strokeWeight(wrink_stroke);
line(-wrink_width,0,wrink_width , 0);
strokeWeight(wrink_stroke);
beginShape();
curveVertex( - 1, + 0.3 + wrink_stroke);
curveVertex( - wrink_width * 0.8, 0.11 );
curveVertex( + wrink_width * 0.8, 0.11 );
curveVertex( + 1, + 0.3 + wrink_stroke);
endShape();
beginShape();
curveVertex( - 1, - 0.3 - wrink_stroke);
curveVertex( - wrink_width * 0.8, -0.11 );
curveVertex( + wrink_width * 0.8, -0.11);
curveVertex( + 1, - 0.3 - wrink_stroke);
endShape();
pop();
}
//brows
var brow_outer_l = positions.left_eyebrow[0];
var brow_inner_l = positions.left_eyebrow[4];
var brow_upper_l = positions.left_eyebrow[2];
var brow_outer_r = positions.right_eyebrow[4]
var brow_inner_r = positions.right_eyebrow[0];
var brow_upper_r = positions.right_eyebrow[2];
var brow_height_left = (distanceBetween(brow_outer_l, brow_upper_l) + distanceBetween(brow_inner_l, brow_upper_l)) / 4;
var brow_height_right = (distanceBetween(brow_outer_r, brow_upper_r) + distanceBetween(brow_inner_r, brow_upper_r)) / 4;
var brow_width_right = distanceBetween(brow_outer_r, brow_inner_r) * 0.7;
var brow_width_left = distanceBetween(brow_outer_l, brow_inner_l) * 0.7;
// console.log(curHairColor);
var brow_color = curHairColor;
var brow_outline = curHairColor*0.95;
push();
fill(brow_color);
stroke(brow_outline);
//left brow
translate(brow_upper_l[0], brow_upper_l[1]);
rotate(angleBetween(brow_inner_l, brow_outer_l));
ellipse(0, brow_height_left / 4 - eyeShift, brow_width_left, brow_height_left);
pop();
push();
//right brow
fill(brow_color);
stroke(brow_outline);
translate(brow_upper_r[0], brow_upper_r[1]);
rotate(angleBetween(brow_outer_r, brow_inner_r));
ellipse(0, brow_height_right / 4 - eyeShift, brow_width_right, brow_height_left);
pop();
//eyes
//eyes are drawn always closed, with glasses
var blink_weight_L = Math.abs(average_point([positions.left_eye[1], positions.left_eye[2]])[1] - average_point([positions.left_eye[4], positions.left_eye[5]])[1]) / 3;
var blink_weight_R = Math.abs(average_point([positions.right_eye[1], positions.right_eye[2]])[1] - average_point([positions.right_eye[4], positions.right_eye[5]])[1]) / 3;
push();
stroke(blush_color);
noFill();
strokeWeight(blink_weight_L);
beginShape(); //left eye
curveVertex(positions.left_eye[5][0], positions.left_eye[4][1]);
curveVertex(positions.left_eye[0][0], positions.left_eye[0][1]);
curveVertex(positions.left_eye[1][0], positions.left_eye[1][1]);
curveVertex(positions.left_eye[2][0], positions.left_eye[2][1]);
curveVertex(positions.left_eye[3][0], positions.left_eye[3][1]);
curveVertex(positions.left_eye[4][0], positions.left_eye[4][1]);
endShape();
strokeWeight(blink_weight_R);
beginShape(); //right eye
curveVertex(positions.right_eye[5][0], positions.right_eye[4][1]);
curveVertex(positions.right_eye[0][0], positions.right_eye[0][1]);
curveVertex(positions.right_eye[1][0], positions.right_eye[1][1]);
curveVertex(positions.right_eye[2][0], positions.right_eye[2][1]);
curveVertex(positions.right_eye[3][0], positions.right_eye[3][1]);
curveVertex(positions.right_eye[4][0], positions.right_eye[4][1]);
endShape();
pop();
// lens size calculated from average distance between each outer point in positions.eye(l/r) and "eye_pos" center
var l_lens_size;
var r_lens_size;
var frame_color = '#494c56';
var lens_color = color(255, 90);
for (var i = 0; i < positions.left_eye.length; i++) {
l_lens_size = distanceBetween(positions.left_eye[i], eye1_pos);
r_lens_size = distanceBetween(positions.right_eye[i], eye2_pos);
}
l_lens_size /= positions.left_eye.length;
r_lens_size /= positions.right_eye.length;
l_lens_size = 0.4 + l_lens_size * 30;
r_lens_size = 0.4 + r_lens_size * 30;
push();
fill(lens_color);
strokeWeight(0.095);
stroke(frame_color);
//lenses
ellipse(eye1_pos[0], eye1_pos[1], l_lens_size, l_lens_size);
ellipse(eye2_pos[0], eye2_pos[1], r_lens_size, r_lens_size);
//glasses legs (called 'temples')
var temple_connect_angle = -TWO_PI / 32;
var temple_connect_l = rim_vert(eye1_pos, l_lens_size / 2, PI - temple_connect_angle);
var temple_connect_r = rim_vert(eye2_pos, r_lens_size / 2, temple_connect_angle);
noFill();
var bridge_control_offset = distanceBetween(eye1_pos, eye2_pos) - (l_lens_size / 2) - (r_lens_size / 2);
beginShape();
curveVertex(positions.nose_bridge[3][0] * -0.30, (positions.nose_bridge[3][1] + bridge_control_offset) / 2);
curveVertex(eye1_pos[0] + (l_lens_size / 2), eye1_pos[1]);
curveVertex(eye2_pos[0] - (r_lens_size / 2), eye2_pos[1]);
curveVertex(positions.nose_bridge[3][0] * -0.30, (positions.nose_bridge[3][1] + bridge_control_offset) / 2);
endShape();
if (temple_connect_l[0] > chin_L[0]) {
line(chin_L[0], chin_L[1], temple_connect_l[0], temple_connect_l[1]);
}
if (temple_connect_r[0] < chin_R[0]) {
line(chin_R[0], chin_R[1], temple_connect_r[0], temple_connect_r[1]);
}
pop();
//mouth
// for positions.top_lip & positions.bottom_lip: inside = 8,9,10 | outside = 2,3,4 | end = 11
// top_lip[0] is in left mouth corner
// bottom_lip[0] is in right mouth corner
// bottom[0] + top[6] || bottom[6] + top[0] will always intersect
var top_lip_outside = [positions.top_lip[2], positions.top_lip[3], positions.top_lip[4]];
var bottom_lip_outside = [positions.bottom_lip[2], positions.bottom_lip[3], positions.bottom_lip[4]];
var mouthCorner_LT = positions.top_lip[0]; // Left/Top
var mouthCorner_RB = positions.bottom_lip[0]; // Right/Bottom
var top_lip_inside = [positions.top_lip[8], positions.top_lip[9], positions.top_lip[10]];
var bottom_lip_inside = [positions.bottom_lip[8], positions.bottom_lip[9], positions.bottom_lip[10]];
// var mouth_angle = angleBetween(positions.bottom_lip[0], positions.top_lip[0]);
var mouth_width = distanceBetween(positions.bottom_lip[0], positions.top_lip[0]);
var smile;
var lip_thickness = 0;
var mouth_open = 0;
var innverAv = [];
for (var i = 2; i > 0; i--) {
mouth_open += distanceBetween(top_lip_inside[i], bottom_lip_inside[i]);
lip_thickness += distanceBetween(top_lip_inside[i], top_lip_outside[i]);
lip_thickness += distanceBetween(bottom_lip_inside[i], bottom_lip_outside[i]);
innverAv.push(top_lip_inside[i]);
innverAv.push(bottom_lip_inside[i]);
}
innverAv = average_point(innverAv);
cornerAv = average_point([mouthCorner_LT, mouthCorner_RB]);
mouth_open /= 3;
lip_thickness /= 6;
smile = cornerAv[1] - innverAv[1];
push();
strokeWeight(lip_thickness * 0.75);
stroke(blush_color);
noFill();
beginShape();
curveVertex(mouthCorner_LT[0] - smile, mouthCorner_LT[1] + smile * 2);
curveVertex(mouthCorner_LT[0] + mouth_width * 0.15, mouthCorner_LT[1] - smile);
curveVertex(mouthCorner_RB[0] - mouth_width * 0.15, mouthCorner_RB[1] - smile);
curveVertex(mouthCorner_RB[0] - smile, mouthCorner_RB[1] + smile * 2);
endShape();
pop();
fill('red');
stroke('red');
// debugShowPoints(positions.left_eye);
//debugShowPoints(hair_L);
function toms_face() {
// head
stroke(kelly_stroke_color);
fill(kelly_fg_color);
beginShape();
for (var i = 0; i < positions.chin.length; i++) {
vertex(positions.chin[i][0], positions.chin[i][1]);
}
for (var i = positions.right_eyebrow.length - 1; i >= 0; i--) {
vertex(positions.right_eyebrow[i][0], positions.right_eyebrow[i][1]);
}
for (var i = positions.left_eyebrow.length - 1; i >= 0; i--) {
vertex(positions.left_eyebrow[i][0], positions.left_eyebrow[i][1]);
}
endShape(CLOSE);
// mouth
noStroke();
fill(kelly_bg_color);
beginShape();
for (var i = 0; i < positions.top_lip.length; i++) {
vertex(positions.top_lip[i][0], positions.top_lip[i][1]);
}
endShape(CLOSE);
beginShape();
for (var i = 0; i < positions.bottom_lip.length; i++) {
vertex(positions.bottom_lip[i][0], positions.bottom_lip[i][1]);
}
endShape(CLOSE);
// nose
beginShape();
vertex(positions.nose_bridge[0][0], positions.nose_bridge[0][1]);
for (var i = 0; i < positions.nose_tip.length; i++) {
vertex(positions.nose_tip[i][0], positions.nose_tip[i][1]);
}
endShape(CLOSE);
// eyes
beginShape();
for (var i = 0; i < positions.left_eye.length; i++) {
vertex(positions.left_eye[i][0], positions.left_eye[i][1]);
}
endShape(CLOSE);
beginShape();
for (var i = 0; i < positions.right_eye.length; i++) {
vertex(positions.right_eye[i][0], positions.right_eye[i][1]);
}
endShape(CLOSE);
fill(kelly_fg_color);
ellipse(eye1_pos[0], eye1_pos[1], 16 * scale, 16 * scale);
ellipse(eye2_pos[0], eye2_pos[1], 16 * scale, 16 * scale);
fill(kelly_stroke_color);
beginShape();
for (var i = 0; i < positions.right_eyebrow.length; i++) {
vertex(positions.right_eyebrow[i][0], positions.right_eyebrow[i][1]);
}
endShape(CLOSE);
beginShape();
for (var i = 0; i < positions.left_eyebrow.length; i++) {
vertex(positions.left_eyebrow[i][0], positions.left_eyebrow[i][1]);
}
endShape(CLOSE);
strokeWeight(1);
}
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.hairColor = settings[0];
this.wrinkleWeight = settings[1];
this.skinColor = settings[2];
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
properties = new Array(3);
properties[0] = this.hairColor;
properties[1] = this.wrinkleWeight;
properties[2] = this.skinColor;
return properties;
}
}
// given a point, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for (var i = 0; i < list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
function rim_vert(vert, rad, angl) { //find the co-oridnates for a point on a circle
var x = Math.cos(angl) * rad;
var y = Math.sin(angl) * rad;
return [x + vert[0], y + vert[1]];
}
function angleBetween(p1, p2) {
//angle given with reference to horizon line
var c;
c = Math.atan2(p2[1] - p1[1], p2[0] - p1[0]) * 180 / Math.PI;
return c;
}
function distanceBetween(p1, p2) {
var a = p1[0] - p2[0];
var b = p1[1] - p2[1];
var c = Math.abs(Math.sqrt(a * a + b * b));
return c;
}
function debugShowPoints(arr, txtsiz) {
push();
textSize(0.25);
if (txtsiz) {
textSize(txtsiz);
}
noStroke();
for (var i = arr.length - 1; i >= 0; i--) {
text(i, arr[i][0], arr[i][1]);
}
pop();
}
{
"000001": [
83,
0,
17
],
"000002": [
54,
41
],
"000058": [
100,
7,
4
],
"000005": [
18,
0,
18
],
"000006": [
45,
27,
57
],
"000007": [
94,
67,
34
],
"000009": [
66,
31,
9
],
"000010": [
20,
40,
20
],
"000013": [
0,
71,
0
],
"000014": [
100,
17,
71
],
"000015": [
74,
64,
36
],
"000016": [
80,
40,
27
],
"000018": [
11,
36,
4
],
"000020": [
76,
47,
17
],
"000023": [
87,
70,
20
],
"000025": [
71,
32,
16
],
"000028": [
59,
66,
21
],
"000029": [
5,
6,
13
],
"000030": [
14,
61,
15
],
"000031": [
29,
93,
0
],
"000032": [
9,
60,
23
],
"000035": [
100,
0,
0
],
"000037": [
100,
16,
67
],
"000038": [
87,
100,
7
],
"000040": [
93,
7,
14
],
"000041": [
98,
100,
19
],
"000042": [
23,
34,
0
],
"000043": [
74,
45,
20
],
"000044": [
100,
0,
93
],
"000045": [
69,
17,
14
],
"000047": [
100,
55,
17
],
"000048": [
90,
7,
0
],
"000050": [
78,
100,
17
],
"000051": [
0,
100,
30
],
"000052": [
70,
100,
22
],
"000054": [
12,
72,
10
],
"000055": [
97,
64,
8
],
"000056": [
100,
23,
7
],
"000060": [
72,
80,
96
],
"000064": [
74,
49,
2
],
"000065": [
80,
25,
9
],
"000068": [
42,
100,
21
],
"000069": [
100,
69,
7
],
"000071": [
5,
39,
14
],
"000073": [
79,
12,
29
],
"000076": [
100,
75,
9
],
"000077": [
100,
0,
0
],
"000078": [
84,
18,
5
],
"000079": [
0,
59,
21
],
"000080": [
98,
21,
0
],
"000081": [
98,
87,
0
],
"000083": [
64,
14,
4
],
"000085": [
71,
18,
6
],
"000086": [
50,
4,
7
],
"000088": [
70,
0,
7
],
"000091": [
94,
22,
5
],
"000092": [
17,
69,
8
],
"000096": [
77,
0,
17
],
"000097": [
31,
21,
19
],
"000099": [
57,
21,
8
],
"000100": [
27,
34,
5
],
"000103": [
67,
0,
5
],
"000104": [
10,
82,
3
],
"000106": [
38,
23,
21
],
"000108": [
2,
36,
4
],
"000109": [
11,
50,
28
],
"000110": [
73,
40,
17
],
"000111": [
34,
13,
65
],
"000114": [
92,
34,
14
],
"000115": [
0,
17,
0
],
"000116": [
59,
85,
36
],
"000117": [
100,
0,
67
],
"000118": [
91,
15,
69
],
"000121": [
91,
67,
37
],
"000122": [
0,
81,
0
],
"000125": [
20,
100,
18
],
"000126": [
0,
35,
21
],
"000129": [
90,
41,
31
],
"000131": [
91,
29,
14
],
"000132": [
100,
33,
59
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
//var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
// var NUM_SLIDERS = 6;
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i=0; i<s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len , sum_y / s_len ];
}
// other variables can be in here too
// here's some examples for colors used
// const bg_color = [225, 206, 187];
// const fg_color = [151, 102, 52];
// const stroke_color = [95, 52, 8];
// example of a global function
// given a segment, this returns the average point [x, y]
// This where you define your own face object
function LeeFace() {
// these are state variables for a face
// (your variables should be different!)
this.mouth_value= 4;
this.petal_colour = 1;
this.petal_layer = 1;
this.petal_length = 2;
this.eye_size_y = 1.5;
this.eye_colour = 1;
this.face_colour =1;
/* Slider 1 - Hair colour - blue for dark hair, cyan for lgiht hair or no hair, red for red hair
Slider 2 - Petal Layers - 1 for feminine, 2 for masculine
Slider 3 - Petal Shape - Pointy for short hair, rounded for long hair
Slider 4 - Eye size
Slider 5 -Eye colour - purple for blue eyes, green for green eyes, brown for brown eyes
Slider 6 -Skin Colour - light for lighter skin, dark for darker skin.
*/
// example of a function *inside* the face object.
// this draws a segment, and do_loop will connect the ends if true
this.draw = function(positions) {
//VARIABLES
const blue = color(83, 40, 237,180);
const cyan_bonus = color(48, 252, 255, 220);
const red = color(227, 29, 23,180);
const red_stroke = color(235, 62, 56 );
const blue_stroke = color(68, 21, 171);
const cyan_b_stroke = color(48, 252, 255);
const purple_eyes = color(92, 0, 163);
const green_eyes = color(0, 122, 104);
const brown_eyes = color(166, 91, 0);
const darker = color(255, 131, 8);
const lighter = color(255, 166, 0);
let bottom_lip3 = positions.bottom_lip[2];
let bottom_lip4 = positions.bottom_lip[3];
let bottom_lip5 = positions.bottom_lip[4];
let top_lip1 = positions.top_lip[1];
let top_lip2 = positions.top_lip[2];
let top_lip3 = positions.top_lip[3];
let top_lip4 = positions.top_lip[4];
let top_lip6 = positions.top_lip[5];
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos= segment_average(positions.right_eye);
let nose_pos = positions.nose_bridge[0];
let mouth_top = positions.top_lip[3];
let mouth_bottom = positions.bottom_lip[3];
let right_eyebrow = positions.right_eyebrow;
let left_eyebrow = positions.left_eyebrow;
let right_brow_0 = positions.right_eyebrow[0];
let right_brow_1 = positions.right_eyebrow[1];
let right_brow_2 = positions.right_eyebrow[2];
let right_brow_3 = positions.right_eyebrow[3];
let right_brow_4 = positions.right_eyebrow[4];
let left_brow_0 = positions.left_eyebrow[0];
let left_brow_1 = positions.left_eyebrow[1];
let left_brow_2 = positions.left_eyebrow[2];
let left_brow_3 = positions.left_eyebrow[3];
let left_brow_4 = positions.left_eyebrow[4];
// rotation in degrees
angleMode(DEGREES);
//rotate(tilt_value);
strokeWeight(0.05);
//PETAL COLOURS--BLUE, CYAN OR RED------------------------------
if(this.petal_colour == 1) {
fill(blue);
stroke(blue_stroke);
}
else if(this.petal_colour ==2) {
fill(cyan_bonus);
stroke(cyan_b_stroke);
}
else if(this.petal_colour ==3) {
fill(red);
stroke(red_stroke);
}
//PETAL LAYERS -- ONE OR TWO------------------------------
if(this.petal_layer == 1) {
beginShape();
curveVertex(0,0);
curveVertex(0, 0);
curveVertex(-2.8, 1.2);
curveVertex(-this.petal_length,-0.8);
curveVertex(-2.8, -2.8);
curveVertex(0,-1.6);
curveVertex(0,-1.6);
endShape();
beginShape();
curveVertex(0,-1.6);
curveVertex(0, -1.6);
curveVertex(2.8, -2.8);
curveVertex(this.petal_length,-0.8);
curveVertex(2.8, 1.2);
curveVertex(0,0);
curveVertex(0,0);
endShape();
beginShape();
curveVertex(-0.8,-0.8);
curveVertex(-0.8,-0.8);
curveVertex(-2, -3.6);
curveVertex(0, -this.petal_length-0.8);
curveVertex(2, -3.6);
curveVertex(0.8, -0.8);
curveVertex(0.8,-0.8);
endShape();
beginShape();
curveVertex(-0.8,-0.8);
curveVertex(-0.8,-0.8);
curveVertex(-2, 2);
curveVertex(0, this.petal_length-0.8);
curveVertex(2, 2);
curveVertex(0.8, -0.8);
curveVertex(0.8,-0.8);
endShape();
}
else if(this.petal_layer ==2){
beginShape();
curveVertex(0,0);
curveVertex(0, 0);
curveVertex(-2.8, 1.2);
curveVertex(-this.petal_length,-0.8);
curveVertex(-2.8, -2.8);
curveVertex(0,-1.6);
curveVertex(0,-1.6);
endShape();
beginShape();
curveVertex(0,-1.6);
curveVertex(0, -1.6);
curveVertex(2.8, -2.8);
curveVertex(this.petal_length,-0.8);
curveVertex(2.8, 1.2);
curveVertex(0,0);
curveVertex(0,0);
endShape();
beginShape();
curveVertex(-0.8,-0.8);
curveVertex(-0.8,-0.8);
curveVertex(-2, -3.6);
curveVertex(0, -this.petal_length-0.8);
curveVertex(2, -3.6);
curveVertex(0.8, -0.8);
curveVertex(0.8,-0.8);
endShape();
beginShape();
curveVertex(-0.8,-0.8);
curveVertex(-0.8,-0.8);
curveVertex(-2, 2);
curveVertex(0, this.petal_length-0.8);
curveVertex(2, 2);
curveVertex(0.8, -0.8);
curveVertex(0.8,-0.8);
endShape();
fill(174, 82, 255, 170);
//SECOND LAYER OF PETALS
beginShape();
curveVertex(-0.8, 0);
curveVertex(-0.8, 0);
curveVertex(-2, 0.4);
curveVertex(-this.petal_length/1.2, -0.8);
curveVertex(-2, -2);
curveVertex(-0.8, -1.6);
curveVertex(-0.8, -1.6);
endShape();
beginShape();
curveVertex(0.8, 0);
curveVertex(0.8, 0);
curveVertex(2, 0.4);
curveVertex(this.petal_length/1.2, -0.8);
curveVertex(2, -2);
curveVertex(0.8, -1.6);
curveVertex(0.8, -1.6);
endShape();
beginShape();
curveVertex(0.8, 0);
curveVertex(0.8, 0);
curveVertex(1.2, 1.2);
curveVertex(0, this.petal_length/1.2 -0.8);
curveVertex(-1.2, 1.2);
curveVertex(-0.8, 0);
curveVertex(-0.8, 0);
endShape();
beginShape();
curveVertex(0.8, -1.6);
curveVertex(0.8, -1.6);
curveVertex(1.2, -2.8);
curveVertex(0, -this.petal_length/1.2 -0.8);
curveVertex(-1.2, -2.8);
curveVertex(-0.8, -1.6);
curveVertex(-0.8, -1.6);
endShape();
}
//FACE COLOUR--LIGHTER OR DARKER----------------------------------------------------------------------
if(this.face_colour ==1){
fill(lighter);
stroke(255, 83, 3);
}
else if(this.face_colour ==2){
fill(darker);
stroke(255, 83, 3);
}
//HEAD
ellipse(0, -0.8, 2.4);
//EYES
//WHITE
fill(255);
strokeWeight(0.05);
stroke(255, 224, 153);
noStroke();
ellipse(left_eye_pos[0], left_eye_pos[1]+0.05,0.6, this.eye_size_y);
ellipse(right_eye_pos[0], right_eye_pos[1]+0.05, 0.6, this.eye_size_y);
//EYE COLOUR
if (this.eye_colour == 1){
fill(purple_eyes);
}
else if(this.eye_colour ==2){
fill(green_eyes);
}
else if( this.eye_colour ==3){
fill(brown_eyes);
}
//IRIS
noStroke();
ellipse(left_eye_pos[0],left_eye_pos[1]+0.05,0.4,this.eye_size_y/2);
ellipse(right_eye_pos[0], right_eye_pos[1]+0.05,0.4,this.eye_size_y/2);
//HIGHLIGHTS------------------
noStroke();
fill(255);
//left hl
ellipse(left_eye_pos[0]+0.1,left_eye_pos[1],this.eye_size_y/6);
//right hl
ellipse(right_eye_pos[0]+0.1,right_eye_pos[1],this.eye_size_y/6);
//MOUTH
noStroke();
if(this.face_colour ==1){
fill(224, 108, 0);
}
else if(this.face_colour ==2){
fill(184, 61, 0);
}
push();
scale(0.8);
translate(0, -0.8);
beginShape();
curveVertex(top_lip1[0], top_lip1[1]);
curveVertex(top_lip1[0], top_lip1[1]);
curveVertex(bottom_lip3[0] - 0.4, bottom_lip3[1] );
curveVertex(bottom_lip4[0], bottom_lip4[1] +0.02);
curveVertex(bottom_lip5[0] + 0.4, bottom_lip5[1]);
curveVertex(top_lip6[0], top_lip6[1]);
curveVertex(top_lip4[0], top_lip4[1]-0.1);
curveVertex(top_lip3[0]+0.1, top_lip3[1]-0.15);
curveVertex(top_lip3[0]-0.1, top_lip3[1]-0.15);
curveVertex(top_lip2[0], top_lip2[1]-0.1);
curveVertex(top_lip2[0], top_lip2[1]-0.1);
endShape();
endShape();
pop();
//EYEBROWS --------------------------
stroke(15, 33, 92);
strokeWeight(0.3);
noFill();
beginShape();
curveVertex(left_brow_0[0], left_brow_0[1]),
curveVertex(left_brow_1[0], left_brow_1[1]),
curveVertex(left_brow_2[0], left_brow_2[1]),
curveVertex(left_brow_3[0], left_brow_3[1]),
curveVertex(left_brow_4[0], left_brow_4[1]),
endShape();
beginShape();
curveVertex(right_brow_0[0], right_brow_0[1]),
curveVertex(right_brow_1[0], right_brow_1[1]),
curveVertex(right_brow_2[0], right_brow_2[1]),
curveVertex(right_brow_3[0], right_brow_3[1]),
curveVertex(right_brow_4[0], right_brow_4[1]),
endShape();
//NOSE -----------------------------
//NOSE COLOUR -- BASED ON SKIN COLOUR
if(this.face_colour ==1){
fill(224, 108, 0);
}
else if (this.face_colour ==2){
fill(194, 78, 0);
}
//DRAW NOSE
noStroke();
ellipse(nose_pos[0], nose_pos[1]+0.4, 0.2, 0.1);
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.petal_colour = int(map(settings[0], 0, 100, 1, 3));
this.petal_layer = int(map(settings[1], 0, 100, 1, 2));
this.petal_length = map(settings[2], 0, 100, 2, 3);
this.eye_size_y = map(settings[3], 0, 100, 0.4, 1);
this.eye_colour = int(map(settings[4], 0, 100, 1, 3));
this.face_colour = int(map(settings[5], 0, 100, 1, 2));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(6);
settings[0] = map(this.petal_colour, 1,3, 0, 100);
settings[1] = map(this.petal_layer, 1, 2, 0, 100);
settings[2] = map(this.petal_length, 2, 3, 0, 100);
settings[3] = map(this.eye_size_y, 0.4, 1, 0, 100);
settings[4] = map(this.eye_colour, 1, 3, 0, 100);
settings[5] = map(this.face_colour, 1, 2, 0, 100);
return settings;
}
}
{
"000001": [
50,
0,
100,
100,
100,
0
],
"000002": [
100,
0,
100,
100,
100,
0
],
"000005": [
50,
0,
100,
81,
50,
0
],
"000006": [
0,
0,
100,
100,
100,
100
],
"000007": [
0,
100,
0,
27.000000000000007,
100,
0
],
"000009": [
100,
0,
100,
100,
100,
0
],
"000010": [
50,
0,
100,
100,
0,
0
],
"000013": [
50,
100,
0,
12.000000000000002,
50,
0
],
"000014": [
0,
0,
100,
100,
100,
100
],
"000015": [
0,
100,
0,
0,
100,
0
],
"000016": [
0,
100,
0,
0,
100,
0
],
"000018": [
50,
0,
100,
51.99999999999999,
50,
0
],
"000020": [
0,
100,
0,
19,
100,
0
],
"000023": [
0,
100,
0,
14.999999999999996,
0,
0
],
"000025": [
0,
100,
0,
25.000000000000007,
100,
0
],
"000028": [
100,
0,
100,
100,
100,
0
],
"000029": [
50,
0,
100,
100,
50,
0
],
"000030": [
50,
100,
0,
93.00000000000001,
50,
0
],
"000031": [
50,
0,
100,
61,
0,
0
],
"000032": [
0,
100,
0,
61,
100,
0
],
"000035": [
0,
0,
100,
100,
100,
0
],
"000037": [
0,
100,
0,
33.000000000000014,
100,
100
],
"000038": [
0,
100,
0,
12.000000000000002,
50,
0
],
"000040": [
0,
0,
100,
100,
100,
0
],
"000041": [
0,
100,
0,
20,
100,
100
],
"000042": [
50,
0,
100,
64,
50,
0
],
"000043": [
0,
0,
100,
100,
100,
0
],
"000044": [
0,
0,
100,
100,
100,
100
],
"000045": [
100,
0,
100,
34.000000000000014,
100,
0
],
"000047": [
0,
0,
100,
0,
100,
100
],
"000048": [
0,
100,
0,
9,
100,
0
],
"000050": [
0,
100,
0,
9,
100,
0
],
"000051": [
50,
100,
0,
78,
100,
0
],
"000052": [
0,
100,
0,
45.00000000000001,
50,
0
],
"000054": [
50,
0,
100,
30.00000000000001,
50,
0
],
"000055": [
0,
100,
0,
13.000000000000004,
100,
0
],
"000056": [
0,
100,
39.000000000000014,
13.000000000000004,
100,
0
],
"000058": [
0,
0,
100,
85.00000000000001,
0,
0
],
"000060": [
100,
100,
0,
20,
100,
100
],
"000064": [
0,
100,
0,
0,
50,
0
],
"000065": [
0,
100,
0,
0,
100,
100
],
"000068": [
0,
100,
0,
0,
100,
0
],
"000069": [
0,
100,
0,
100,
100,
0
],
"000071": [
50,
0,
100,
100,
50,
0
],
"000073": [
0,
0,
100,
52.99999999999999,
100,
0
],
"000076": [
0,
100,
25,
52.99999999999999,
100,
100
],
"000077": [
0,
0,
100,
100,
100,
0
],
"000078": [
0,
0,
100,
100,
100,
0
],
"000079": [
50,
100,
0,
36,
100,
100
],
"000080": [
0,
100,
0,
0,
50,
0
],
"000081": [
0,
100,
0,
0,
100,
100
],
"000083": [
100,
0,
100,
100,
50,
0
],
"000085": [
100,
0,
100,
100,
50,
0
],
"000086": [
100,
0,
100,
100,
50,
0
],
"000088": [
100,
0,
100,
68,
100,
0
],
"000091": [
0,
100,
0,
0,
100,
0
],
"000092": [
50,
0,
100,
78,
50,
0
],
"000096": [
0,
0,
100,
100,
100,
100
],
"000097": [
50,
0,
100,
100,
0,
0
],
"000099": [
50,
0,
100,
100,
50,
0
],
"000100": [
50,
0,
100,
100,
100,
0
],
"000103": [
0,
0,
100,
100,
50,
0
],
"000104": [
50,
100,
0,
0,
0,
0
],
"000106": [
100,
0,
100,
100,
100,
0
],
"000108": [
50,
0,
100,
100,
0,
0
],
"000109": [
50,
100,
0,
48.999999999999986,
50,
0
],
"000110": [
0,
0,
100,
17,
50,
0
],
"000111": [
50,
0,
100,
0,
100,
100
],
"000114": [
0,
100,
0,
100,
100,
0
],
"000115": [
50,
100,
0,
0,
50,
0
],
"000116": [
0,
100,
0,
37,
100,
0
],
"000117": [
0,
0,
100,
100,
100,
100
],
"000118": [
0,
0,
100,
100,
100,
100
],
"000121": [
0,
0,
100,
100,
100,
100
],
"000122": [
50,
0,
100,
81.99999999999999,
100,
0
],
"000125": [
0,
100,
0,
55.99999999999999,
50,
100
],
"000126": [
50,
0,
100,
100,
50,
100
],
"000129": [
0,
100,
0,
32.000000000000014,
100,
0
],
"000131": [
0,
0,
100,
72.00000000000001,
100,
100
],
"000132": [
0,
0,
100,
44.00000000000001,
100,
100
],
"000133": [
50,
0,
100,
100,
0,
0
],
"000134": [
0,
100,
0,
73.00000000000001,
100,
100
],
"000135": [
0,
100,
0,
43.00000000000001,
100,
100
],
"000137": [
0,
100,
0,
0,
100,
0
],
"000140": [
50,
0,
100,
100,
0,
0
],
"000142": [
0,
0,
100,
100,
0,
0
],
"000143": [
50,
100,
0,
32.000000000000014,
50,
0
],
"000145": [
0,
0,
100,
0,
100,
0
],
"000146": [
100,
0,
100,
65,
100,
100
],
"000147": [
50,
0,
100,
100,
50,
0
],
"000148": [
0,
0,
100,
30.00000000000001,
50,
0
],
"000150": [
100,
100,
0,
85.00000000000001,
50,
0
],
"000151": [
0,
0,
100,
26.000000000000007,
100,
100
],
"000152": [
0,
100,
0,
25.000000000000007,
50,
0
],
"000153": [
0,
100,
0,
25.000000000000007,
100,
0
],
"000155": [
100,
0,
100,
100,
100,
0
],
"000156": [
50,
0,
100,
62,
0,
0
],
"000157": [
50,
0,
100,
68,
50,
0
],
"000160": [
0,
100,
0,
42.00000000000001,
100,
0
],
"000161": [
0,
0,
100,
0,
50,
0
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
// var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
// var NUM_SLIDERS = 5;
// other variables can be in here too
// these control the colors used
// const bg_color = [225, 206, 187];
// const fg_color = [151, 102, 52];
// const stroke_color = [95, 52, 8];
function LuoFace() {
// these are state variables for a face
// (your variables may be different)
this.face = 4; // 1-5
this.spot = 5; // 0-10
this.shape = 1;
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
let face = this.face;
let mouth = 5;
let blush = 5;
let spot = this.spot;
let spot_col = 5;
let spot_size = 1;
let eyebrows_rotate = 50;
let glasses = 5;
// Colour Sets
let face1 = '#ffe3fc'; //white
let face2 = '#f5ad8e'; //pink
let face3 = '#fcf06a'; //yellow
let face4 = '#d9764c'; //brown
let face5 = '#66756a'; //grey
let face6 = '#315070'; //blue
let face7 = '#8a5189'; //purple
let face8 = '#a65561'; //red
let face9 = '#5b8a5a'; //green
let face10 = '#de4e26'; //orange
let faceColour;
let left_eye = average_point(positions.left_eye);
let right_eye = average_point(positions.right_eye);
let left_eyebrow = average_point(positions.left_eyebrow);
let right_eyebrow = average_point(positions.right_eyebrow);
let left_d = dist(left_eye[0], left_eye[1], left_eyebrow[0], left_eyebrow[1]);
let right_d = dist(right_eye[0], right_eye[1], right_eyebrow[0], right_eyebrow[1]);
let left_eb_move = map(left_d, 0.4, 0.7, 0, 2, true);
let right_eb_move = map(right_d, 0.4, 0.7, 0, 2, true);
// print(left_d);
left_eye[0] *= 3;
left_eye[1] *= 3;
right_eye[0] *= 3;
right_eye[1] *= 3;
push();
scale(0.33);
// Rabbit (Brown)
//fill(221,168,128);
strokeWeight(0.3);
stroke(0);
beginShape();
endShape();
if(this.shape <2){
//soft SHAPES
noStroke();
// Face Colour
if(face == 1){
faceColour = face1; //***WHITE***//
}else if (face == 2){
faceColour = face2; //***dark***//
}else if (face == 3){
faceColour = face3; //***Yellow***//
}else if (face == 4){
faceColour = face4; //***Brown***//
}else{
faceColour = face5; //***Grey***//
}
fill(faceColour);
strokeWeight(0.3);
stroke(0);
ellipse(-0.5, 1.8, 15, 11);
push();
angleMode(RADIANS);
arc(-3.9, -3, 4.5, 16, -4, -0.4);//ear left
arc(2.4, -3.2, 5, 16, -2.8, 0.65);//ear right
pop();
} else {
//unsoft shape
if(face == 1){
faceColour = face6; //***WHITE***//
}else if (face == 2){
faceColour = face8; //***dark***//
}else if (face == 3){
faceColour = face7; //***Yellow***//
}else if (face == 4){
faceColour = face9; //***Brown***//
}else{
faceColour = face10; //***Grey***//
}
fill(faceColour);
strokeWeight(0.2);
stroke(0);
rect(-8, -4, 15, 11);
push();
angleMode(RADIANS);
rect(-3, -4, -2.5, -9.5);
rect(5, -4, -3, -6.5);
//arc(-3.9, -3, 4.5, 16, -4, -0.4);//ear left
//arc(2.4, -3.2, 5, 16, -2.8, 0.65);//ear right
pop();
}
// spot (Colour, Spot)
let amount = map(spot_col, 0, 10, 0, 1);
let colourWhite = color('#dbdbdb');
let colourDark = color('#e6655c');
let spotColour = lerpColor(colourWhite, colourDark, amount);
let spotFace = map(spot, 0, 100, 0, 100);
let spotS = map(spot_size, 0, 100, 1.3, 15);
strokeWeight(spotS);
stroke(spotColour);
if (spotFace == 0){
}
if (spotFace >= 2){
line(-0.5, -3, -0.5, -2);
}
if (spotFace >=4){
line(-6.5, 3, -3, 3);
}
if (spotFace >=6){
line(2.5, 2, 5.5, 2);
}
if (spotFace >=8){
line(3, 0, 5.5, 0);
}
if (spotFace >=10){
line(-6.5, 0.5, -4.5, 0.5);
}
// Mouth
strokeWeight(0.4);
stroke(0);
line(-1.55, -1, -0.05, -1);
let top_lip_point = positions.top_lip[9];
let bottom_lip_point = positions.bottom_lip[9];
// fill(255, 0, 0);
let d = dist(top_lip_point[0], top_lip_point[1], bottom_lip_point[0], bottom_lip_point[1])
// print(d);
// Mouth Open
if(d < 0.1) {
d = 0;
}
mouth = map(d, 0, 0.5, 0, 10);
let mouth_size = map(mouth, 0, 10, 0, 3.5);
strokeWeight(0.3);
fill('#fffcf7');
rect(-1.6, 2, 1.6, mouth_size, 0.08);
// Blush
noStroke();
if (blush > 3 && blush < 6){
fill('#ed4415'); //red
ellipse(-3.6, 0.5, 1.5, 1);
ellipse(2.3, 0.5, 1.5, 1);
}
// Eyes
noStroke();
fill(0);
// ellipse(-2.2, -2, 1.1, 1.1);
// ellipse(0.5, -2, 1.1, 1.1);
ellipse(left_eye[0], left_eye[1]+ 1.5, 2, 2); //eye size left
ellipse(right_eye[0] - 1.6, right_eye[1] + 1.7, 2, 2);
// Eyebrows
strokeWeight(0.5);
stroke(0);
push();
angleMode(DEGREES);
//translate(left_eye[0]-0.1, left_eye[1]-1);
//translate(0, -left_eb_move);
//rotate(eyebrows_rotate);
line(0.5, -2.5, 2.5, -2.5);
pop();
push();
angleMode(DEGREES);
//translate(right_eye[0]-0.2, right_eye[1]-1);
//translate(0, -right_eb_move);
//rotate(-eyebrows_rotate);
line(-3.5, -2.5, -1.5, -2.5);
pop();
// Glasses
if (glasses > 5 && glasses < 8){
stroke(0);
strokeWeight(0.35);
noFill();
ellipse(-2.3, -2.4, 2.6, 2.6);
ellipse(0.6, -2.4, 2.6, 2.6);
}
// Sunglasses
else if (glasses > 7 && glasses <= 10){
stroke(0);
strokeWeight(0.3);
fill('white');
ellipse(-2.6, -2.4, 3, 2.6);
ellipse(1, -2.4, 3, 2.6);
noStroke();
fill('black');
ellipse(-2.6, -2.37, 2.4, 2);
ellipse(1, -2.37, 2.4, 2);
stroke(0);
strokeWeight(0.3);
line(-1.1, -2.5, -0.65, -2.5);
}
pop();
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.face = int(map(settings[0], 0, 100, 1, 5));
this.spot = int(map(settings[1], 0, 100, 0, 10));
this.shape = map(settings[2],0,100,1,2);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(2);
settings[0] = map(this.face, 1, 5, 0, 100);
settings[1] = map(this.spot, 0, 10, 0, 100);
settings[82] = map(this.shape, 1, 2, 0, 100);
return settings;
}
}
// given an array of [x,y] points, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for(var i=0; i<list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
{
"000001": [
0,
100,
50
],
"000002": [
0,
100
],
"000005": [
20,
100
],
"000006": [
50,
100,
50
],
"000007": [
25,
0
],
"000009": [
25,
100
],
"000010": [
25,
100,
50
],
"000013": [
25,
0
],
"000014": [
75,
100
],
"000015": [
25,
0,
50
],
"000016": [
25,
0
],
"000018": [
75,
100,
50
],
"000020": [
25,
0
],
"000023": [
55,
0
],
"000025": [
10,
0,
50
],
"000028": [
25,
100
],
"000029": [
75,
100,
50
],
"000030": [
25,
0
],
"000031": [
80,
100,
50
],
"000032": [
90,
0
],
"000035": [
40,
100
],
"000037": [
50,
0
],
"000038": [
0,
70,
50
],
"000040": [
0,
90
],
"000041": [
30,
50,
50
],
"000042": [
0,
100,
50
],
"000043": [
10,
100,
50
],
"000044": [
50,
100
],
"000045": [
20,
100
],
"000047": [
50,
100,
50
],
"000048": [
20,
0,
50
],
"000050": [
20,
0
],
"000051": [
0,
20
],
"000052": [
60,
50,
50
],
"000054": [
0,
100
],
"000055": [
90,
40
],
"000056": [
50,
100
],
"000058": [
20,
100,
50
],
"000060": [
100,
0
],
"000064": [
0,
0
],
"000065": [
50,
0
],
"000068": [
0,
30,
50
],
"000069": [
20,
0,
50
],
"000071": [
50,
100
],
"000073": [
40,
100,
50
],
"000076": [
50,
0,
50
],
"000077": [
0,
100
],
"000078": [
50,
100
],
"000079": [
0,
0
],
"000080": [
0,
0
],
"000081": [
0,
0
],
"000083": [
0,
100
],
"000085": [
0,
100
],
"000086": [
25,
100
],
"000088": [
0,
100
],
"000091": [
0,
0
],
"000092": [
0,
100
],
"000096": [
0,
100
],
"000097": [
0,
100
],
"000099": [
25,
100
],
"000100": [
0,
100
],
"000103": [
25,
100
],
"000104": [
25,
0
],
"000106": [
25,
0
],
"000108": [
25,
100
],
"000109": [
0,
0
],
"000110": [
25,
100
],
"000111": [
50,
100
],
"000114": [
0,
0
],
"000115": [
25,
0
],
"000116": [
0,
0
],
"000117": [
100,
100
],
"000118": [
25,
100
],
"000121": [
25,
100
],
"000122": [
0,
100
],
"000125": [
0,
0
],
"000126": [
0,
100
],
"000129": [
0,
0
],
"000131": [
25,
100
],
"000132": [
50,
100
],
"000133": [
0,
100
],
"000134": [
100,
0
],
"000135": [
75,
0
],
"000137": [
0,
0
],
"000140": [
0,
100
],
"000142": [
0,
100
],
"000143": [
0,
0
],
"000145": [
0,
100
],
"000146": [
0,
100
],
"000147": [
0,
100
],
"000148": [
0,
100
],
"000150": [
0,
0
],
"000151": [
50,
70
],
"000152": [
0,
0
],
"000153": [
0,
0
],
"000155": [
25,
100
],
"000156": [
0,
100
],
"000157": [
0,
100
],
"000160": [
0,
0
],
"000161": [
0,
90
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
// var DEBUG_MODE = false;
// this can be used to set the number of sliders to show
// var NUM_SLIDERS = 9;
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i = 0; i < s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len, sum_y / s_len];
}
// This where you define your own face object
function McKendryFace() {
//colours:
this.purple = color(210, 160, 200, 200);
this.pink = color(250, 225, 250, 200);
this.light_red = color(240, 180, 170, 200);
this.dark_red = color(185, 120, 115, 200);
this.orange = color(240, 190, 145, 200);
this.yellow = color(255, 250, 210, 200);
this.light_green = color(230, 250, 220, 200);
this.dark_green = color(150, 175, 135, 200);
this.dark_blue = color(135, 135, 180, 200);
this.light_blue = color(200, 230, 245, 200);
this.other_turq = color(195, 245, 225, 200);
//positions/states:
this.mouthX = 0;
this.mouthY = 0;
this.male_female = 1;
this.chinX = 0;
this.chinY = 0;
this.shapeScale = 1;
this.eye_height = .25;
this.faceColor = 1;
this.eyesX = 0;
this.mouth_OpenClose = 2
this.show_points = function(segment) {
for (let i = 0; i < segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
var number = i.toString();
textAlign(CENTER, CENTER);
textSize(0.2);
fill(0);
text(number, px, py, 0.1);
}
}
// example of a function *inside* the face object.
// this draws a segment, and do_loop will connect the ends if true
this.draw_segment = function(segment, do_loop) {
for (let i = 0; i < segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
ellipse(px, py, 0.1);
if (i < segment.length - 1) {
let nx = segment[i + 1][0];
let ny = segment[i + 1][1];
line(px, py, nx, ny);
} else if (do_loop) {
let nx = segment[0][0];
let ny = segment[0][1];
line(px, py, nx, ny);
}
}
};
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
//this array takes the colours called in the variables above, then I get a random colour from the array to be the fill for the background shapes
this.colourFillArray = [this.purple, this.pink, this.light_red, this.dark_red, this.orange, this.yellow, this.light_green, this.dark_green, this.dark_blue, this.light_blue, this.other_turq];
this.colourFill = random(this.colourFillArray);
//If statement decides if the face is male or female, dictated by slider5.
if (this.male_female < 2) {
//FEMALE SHAPES
fill(this.colourFill);
noStroke();
push();
//scales shapes to size of the face
scale(this.shapeScale);
ellipse(0, 0, 2, 3);
ellipse(0, .5, 3.75, 3.25);
ellipse(-1.25, -1.5, 2, 4);
ellipse(.75, -2.5, 2.5, 2);
ellipse(-.5, 1.75, 2.5, 2);
ellipse(1, -1.5, 2, 2.5);
ellipse(-.75, -2.5, 2, 3);
//HAIRLINE
noFill();
stroke(0);
strokeWeight(0.035);
beginShape();
vertex(-.3, -2.9);
quadraticVertex(1.5, -4, 1.9, -2.5);
endShape();
pop();
//FEMALE MOUTH
//if-else statement decides if the mouth is closed (only a line, no fill) or open (area of mouth filled)
if (this.mouth_OpenClose == 1) {
stroke(0);
noFill();
strokeWeight(0.03);
beginShape();
vertex(positions.bottom_lip[7][0], positions.bottom_lip[7][1]);
quadraticVertex(positions.bottom_lip[3][0] + this.mouthX, positions.bottom_lip[3][1] + this.mouthY, positions.bottom_lip[0][0], positions.bottom_lip[0][1]);
endShape();
} else {
stroke(0);
fill(200, 200, 200, 100);
strokeWeight(0.03);
beginShape();
vertex(positions.bottom_lip[7][0], positions.bottom_lip[7][1]);
quadraticVertex(positions.bottom_lip[3][0] + this.mouthX, positions.bottom_lip[3][1] + this.mouthY, positions.bottom_lip[0][0], positions.bottom_lip[0][1]);
endShape();
strokeWeight(0.01);
line(positions.bottom_lip[7][0], positions.bottom_lip[7][1], positions.bottom_lip[0][0], positions.bottom_lip[0][1]);
}
//FEMALE JAWLINE
stroke(0);
strokeWeight(0.035);
//if statement decides what side of the jaw the face is on, using the tip of the nose as a center point to figure out if the person is looking left or right
if (positions.nose_tip[2][0] < 0) {
beginShape();
noFill();
vertex(positions.chin[8][0], positions.chin[8][1])
quadraticVertex(positions.chin[12][0] + this.chinX, positions.chin[12][1] + this.chinY, positions.chin[16][0], positions.chin[16][1])
endShape();
} else {
beginShape();
noFill();
vertex(positions.chin[0][0], positions.chin[0][1])
quadraticVertex(positions.chin[4][0] + this.chinX, positions.chin[5][1] + this.chinY, positions.chin[8][0], positions.chin[8][1])
endShape();
}
//FEMALE EYEBROWS
noFill();
stroke(0);
strokeWeight(0.02);
beginShape();
vertex(positions.left_eyebrow[1][0], positions.left_eyebrow[1][1]);
quadraticVertex(positions.nose_bridge[1][0], positions.nose_bridge[1][1] - 1.2, positions.right_eyebrow[3][0], positions.right_eyebrow[3][1])
endShape();
//FEMALE NOSE
noFill();
stroke(0);
strokeWeight(0.03);
//same as the jawline if statement- decides which way the nose should be pointing
if (positions.nose_tip[2][0] < 0) {
beginShape();
vertex(positions.nose_bridge[1][0], positions.nose_bridge[1][1])
quadraticVertex(positions.nose_tip[1][0], positions.nose_tip[1][1] + .5, positions.nose_tip[4][0], positions.nose_tip[4][1])
endShape();
} else {
beginShape();
vertex(positions.nose_bridge[1][0], positions.nose_bridge[1][1])
quadraticVertex(positions.nose_tip[3][0], positions.nose_tip[3][1] + .5, positions.nose_tip[1][0], positions.nose_tip[1][1])
endShape();
}
} else {
////MALE FACE////
//MALE SHAPES
this.colourFillArray = [this.purple, this.pink, this.light_red, this.dark_red, this.orange, this.yellow, this.light_green, this.dark_green, this.dark_blue, this.light_blue, this.other_turq];
this.colourFill = random(this.colourFillArray);
noStroke();
fill(this.colourFill);
push();
//scales shapes to size of the face
scale(this.shapeScale);
rect(.75, -2.25, 2, 3.5);
rect(-2.25, -3.25, 2.5, 1.5);
rect(-.75, -2, 2, 2);
rect(-1.75, -1.25, 3, 3.5);
rect(-1.25, -2.75, 1, 5.5);
rect(0, -3.5, 1.5, 1.5);
//HAIRLINE
stroke(0);
strokeWeight(0.035);
line(-1.75, -1.75, -1.75, -2.9);
line(-1.9, -2.75, 1.5, -2.75);
noStroke();
pop();
//MALE MOUTH
if (this.mouth_OpenClose == 1) {
stroke(0);
noFill();
strokeWeight(0.03);
line(positions.bottom_lip[7][0], positions.bottom_lip[7][1], positions.bottom_lip[3][0] + this.mouthX, positions.bottom_lip[3][1] + this.mouthY);
line(positions.bottom_lip[3][0] + this.mouthX, positions.bottom_lip[3][1] + this.mouthY, positions.bottom_lip[0][0], positions.bottom_lip[0][1]);
} else {
stroke(0);
fill(200, 200, 200, 100);
stroke(0);
strokeWeight(0.02);
triangle(positions.bottom_lip[7][0], positions.bottom_lip[7][1], positions.bottom_lip[3][0] + this.mouthX, positions.bottom_lip[3][1] + this.mouthY, positions.bottom_lip[0][0], positions.bottom_lip[0][1]);
strokeWeight(0.03);
line(positions.bottom_lip[7][0], positions.bottom_lip[7][1], positions.bottom_lip[3][0] + this.mouthX, positions.bottom_lip[3][1] + this.mouthY);
line(positions.bottom_lip[3][0] + this.mouthX, positions.bottom_lip[3][1] + this.mouthY, positions.bottom_lip[0][0], positions.bottom_lip[0][1]);
}
//MALE JAWLINE
stroke(0);
strokeWeight(0.035);
if (positions.nose_tip[2][0] < 0) {
line(positions.chin[8][0], positions.chin[8][1], positions.chin[12][0] + this.chinX, positions.chin[12][1] + this.chinY);
line(positions.chin[12][0] + this.chinX, positions.chin[12][1] + this.chinY, positions.chin[16][0], positions.chin[16][1]);
} else {
line(positions.chin[0][0], positions.chin[0][1], positions.chin[4][0] + this.chinX, positions.chin[4][1] + this.chinY);
line(positions.chin[4][0] + this.chinX, positions.chin[4][1] + this.chinY, positions.chin[8][0], positions.chin[8][1]);
}
//MALE EYEBROWS
stroke(0);
strokeWeight(0.02);
line(positions.left_eyebrow[1][0], positions.left_eyebrow[1][1], positions.right_eyebrow[3][0], positions.right_eyebrow[3][1]);
//MALE NOSE
noFill();
stroke(0);
strokeWeight(0.03);
if (positions.nose_tip[2][0] < 0) {
line(positions.nose_bridge[1][0], positions.nose_bridge[1][1], positions.nose_tip[1][0], positions.nose_tip[1][1]);
line(positions.nose_tip[1][0], positions.nose_tip[1][1], positions.nose_tip[3][0], positions.nose_tip[3][1])
} else {
line(positions.nose_bridge[1][0], positions.nose_bridge[1][1], positions.nose_tip[3][0], positions.nose_tip[3][1]);
line(positions.nose_tip[3][0], positions.nose_tip[3][1], positions.nose_tip[1][0], positions.nose_tip[1][1])
}
}
//EYES//
fill(240, 240, 240, 100);
stroke(0)
strokeWeight(0.025);
if (positions.nose_tip[2][0] < 0) {
rect(positions.left_eye[0][0] + this.eyesX, positions.left_eye[0][1], 1, this.eye_height)
ellipse(positions.right_eye[4][0] + this.eyesX, positions.right_eye[4][1], 1.25, .25 + this.eye_height);
} else {
rect(positions.left_eye[0][0] + this.eyesX, positions.left_eye[0][1], 1, this.eye_height)
ellipse(positions.right_eye[4][0] + this.eyesX, positions.right_eye[4][1], 1.25, .25 + this.eye_height);
}
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.mouthX = map(settings[0], 0, 100, -1.25, 1.25);
this.mouthY = map(settings[1], 0, 100, -1.25, 1.25);
this.eyesX = map(settings[2], 0, 100, -1, 1);
this.eye_height = map(settings[3], 0, 100, 0, .75);
this.chinX = map(settings[4], 0, 100, -1.5, 1.5);
this.chinY = map(settings[5], 0, 100, -1.5, 1.5);
this.mouth_OpenClose = int(map(settings[6], 0, 100, 1, 3));
this.shapeScale = map(settings[7], 0, 100, .5, 1.25);
this.male_female = map(settings[8], 0, 100, 1, 3);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(3);
settings[0] = map(this.mouthX, -1.25, 1.25, 0, 100);
settings[1] = map(this.mouthY, -1.25, 1.25, 0, 100);
settings[2] = map(this.eyesX, -1, 1, 0, 100);
settings[3] = map(this.eye_height, 0, .75, 0, 100);
settings[4] = map(this.chinX, -1.5, 1.5, 0, 100);
settings[5] = map(this.chinY, -1.5, 1.5, 0, 100);
settings[6] = int(map(this.mouth_OpenClose, 1, 3, 0, 100));
settings[7] = map(this.shapeScale, .5, 1.25, 0, 100);
settings[8] = map(this.male_female, 1, 3, 0, 100);
return settings;
}
}
{
"000001": [
48,
40,
34,
22,
57,
50,
52,
49,
100
],
"000002": [
34,
66,
26,
50,
54,
68,
100,
34.99999999999999,
0
],
"000005": [
46.99999999999999,
33,
44,
28.999999999999996,
69,
82,
100,
38.99999999999999,
17.999999999999993
],
"000006": [
61,
40,
54,
34.99999999999999,
54,
69,
100,
30,
37.999999999999986
],
"000007": [
46.00000000000001,
43,
46,
51,
44,
69,
0,
54,
100
],
"000009": [
51,
52,
33,
47,
36.99999999999999,
51,
100,
66,
0
],
"000010": [
50,
57.99999999999999,
45,
22,
51,
66,
60,
40.00000000000001,
27
],
"000013": [
50,
44.00000000000001,
55.00000000000001,
23,
54,
62,
100,
73.99999999999999,
100
],
"000014": [
48,
53,
41,
40.00000000000001,
63,
68,
0,
52.99999999999999,
47
],
"000015": [
56.00000000000001,
34,
46,
7.000000000000001,
64,
71,
100,
62,
100
],
"000016": [
46.99999999999999,
45,
61,
27,
57.99999999999999,
53,
0,
56.99999999999999,
100
],
"000018": [
49.00000000000001,
53,
40,
25,
40.00000000000001,
56.99999999999999,
100,
38.00000000000001,
30.000000000000004
],
"000020": [
51,
32,
45,
9.000000000000002,
53,
47,
100,
46,
100
],
"000023": [
49.00000000000001,
45,
48,
16,
56.00000000000001,
53,
100,
51.000000000000014,
100
],
"000025": [
41,
41,
45,
23,
64,
47,
0,
62,
100
],
"000028": [
50,
64,
46,
23,
41,
87,
100,
51.000000000000014,
44.99999999999999
],
"000029": [
50,
49.00000000000001,
44,
31,
41,
48,
100,
54,
44.99999999999999
],
"000030": [
57.99999999999999,
38,
37,
34.99999999999999,
72.00000000000001,
72.00000000000001,
0,
61,
100
],
"000031": [
45,
56.99999999999999,
37,
16,
38.99999999999999,
60,
100,
54,
0
],
"000032": [
48,
27,
41,
36.99999999999999,
52,
62,
100,
61,
100
],
"000035": [
48,
42.00000000000001,
41,
38.99999999999999,
40.00000000000001,
46,
100,
47,
0
],
"000037": [
56.00000000000001,
34,
66,
28.000000000000004,
54,
52,
0,
61,
100
],
"000038": [
46.99999999999999,
44.00000000000001,
45,
23,
46,
47,
100,
69,
100
],
"000040": [
53,
55.00000000000001,
49,
30,
31,
59,
0,
62,
42.99999999999999
],
"000041": [
42.00000000000001,
41,
25,
21,
56.99999999999999,
48,
100,
65,
100
],
"000042": [
50,
60,
40,
36.00000000000001,
43,
57.99999999999999,
0,
46,
0
],
"000043": [
46.99999999999999,
63,
40,
33,
36.99999999999999,
53,
100,
46,
0
],
"000044": [
49.00000000000001,
51,
43,
25,
57.99999999999999,
50,
0,
36.99999999999999,
0
],
"000045": [
46.99999999999999,
63,
43,
17,
69.99999999999999,
52,
100,
36.99999999999999,
0
],
"000047": [
46.99999999999999,
56.99999999999999,
43,
12,
69.99999999999999,
64,
100,
45,
0
],
"000048": [
60,
40,
55.00000000000001,
10.000000000000002,
63,
72.00000000000001,
0,
38.99999999999999,
100
],
"000050": [
54,
43,
55.00000000000001,
21,
77.99999999999999,
77.99999999999999,
100,
47,
100
],
"000051": [
64,
46.99999999999999,
48,
41,
41,
72.00000000000001,
0,
82,
100
],
"000052": [
42.00000000000001,
45,
40,
30,
59,
57.99999999999999,
0,
64,
100
],
"000054": [
45,
64,
44,
16,
59,
67,
100,
44.000000000000014,
0
],
"000055": [
48,
42.00000000000001,
42,
18.000000000000004,
53,
55.00000000000001,
0,
60,
100
],
"000056": [
38,
48,
35,
14.000000000000002,
67,
77,
0,
36.99999999999999,
0
],
"000058": [
56.99999999999999,
51,
35,
26,
41,
53,
20,
36.99999999999999,
0
],
"000060": [
46.00000000000001,
45,
12,
16,
61,
34,
100,
34,
100
],
"000064": [
46.00000000000001,
48,
44,
14.000000000000002,
53,
60,
0,
47,
100
],
"000065": [
46.99999999999999,
45,
44,
21,
62,
56.99999999999999,
100,
55.000000000000014,
100
],
"000068": [
51,
49.00000000000001,
44,
24,
59,
53,
100,
46,
100
],
"000069": [
50,
37,
43,
36.00000000000001,
43,
54,
100,
56.99999999999999,
100
],
"000071": [
46.99999999999999,
53,
43,
36.00000000000001,
64,
73,
100,
43,
0
],
"000073": [
38,
46.99999999999999,
14.000000000000002,
21,
41,
85,
100,
48.99999999999999,
0
],
"000076": [
45,
49.00000000000001,
34,
14.000000000000002,
50,
61,
0,
48.99999999999999,
100
],
"000077": [
49.00000000000001,
46.00000000000001,
48,
28.999999999999996,
69.99999999999999,
64,
0,
38.00000000000001,
0
],
"000078": [
42.00000000000001,
44.00000000000001,
40,
30,
46,
60,
0,
44.000000000000014,
0
],
"000079": [
46.00000000000001,
45,
48,
30,
30,
84,
0,
56.99999999999999,
100
],
"000080": [
44.00000000000001,
43,
37,
22,
42,
28.999999999999996,
0,
56.00000000000001,
100
],
"000081": [
52,
48,
52,
22,
43,
54,
100,
61,
100
],
"000083": [
48,
56.00000000000001,
43,
21,
56.00000000000001,
82,
0,
50,
0
],
"000085": [
41,
55.00000000000001,
43,
46,
65,
73,
0,
50,
0
],
"000086": [
30,
33,
37,
40.00000000000001,
34.99999999999999,
52,
0,
55.000000000000014,
0
],
"000088": [
40,
42.00000000000001,
50,
41,
73,
61,
100,
44.000000000000014,
0
],
"000091": [
44.00000000000001,
41,
41,
13,
56.99999999999999,
66,
0,
55.000000000000014,
100
],
"000092": [
39,
53,
41,
22,
66,
69,
0,
45,
0
],
"000096": [
54,
32,
47,
28.000000000000004,
38.99999999999999,
66,
0,
30.99999999999999,
0
],
"000097": [
46.00000000000001,
31,
42,
25,
68,
51,
100,
36.99999999999999,
0
],
"000099": [
53,
55.00000000000001,
42,
16,
52,
79,
100,
46,
0
],
"000100": [
63,
48,
56.99999999999999,
21,
38.00000000000001,
46,
30,
43,
0
],
"000103": [
41,
38,
44,
23,
43,
69.99999999999999,
40,
34,
0
],
"000104": [
55.00000000000001,
46.00000000000001,
48,
16,
31,
80.00000000000001,
100,
46,
100
],
"000106": [
61,
55.00000000000001,
43,
26,
33,
42,
100,
47,
0
],
"000108": [
43,
55.00000000000001,
43,
36.99999999999999,
55.00000000000001,
63,
100,
40.00000000000001,
0
],
"000109": [
49.00000000000001,
38,
43,
24,
56.99999999999999,
56.99999999999999,
100,
55.000000000000014,
100
],
"000110": [
46.00000000000001,
50,
43,
23,
38.00000000000001,
55.00000000000001,
100,
54,
49
],
"000111": [
36,
54,
48,
13,
61,
57.99999999999999,
100,
48,
0
],
"000114": [
50,
44.00000000000001,
48,
46,
56.00000000000001,
56.99999999999999,
100,
55.000000000000014,
100
],
"000115": [
50,
42.00000000000001,
42,
31,
61,
53,
10,
51.000000000000014,
100
],
"000116": [
46.00000000000001,
44.00000000000001,
42,
27,
50,
53,
100,
50,
100
],
"000117": [
57.99999999999999,
46.00000000000001,
42,
34.99999999999999,
50,
77,
100,
50,
0
],
"000118": [
65,
46.99999999999999,
33,
38.99999999999999,
44,
60,
40,
51.000000000000014,
0
],
"000121": [
46.00000000000001,
48,
43,
34.99999999999999,
33,
64,
50,
48.99999999999999,
0
],
"000122": [
46.00000000000001,
53,
43,
36.99999999999999,
69,
69.99999999999999,
100,
40.00000000000001,
0
],
"000125": [
57.99999999999999,
41,
46,
28.000000000000004,
55.00000000000001,
53,
0,
61,
100
],
"000126": [
38,
46.00000000000001,
54,
28.000000000000004,
66,
69,
100,
48,
0
],
"000129": [
44.00000000000001,
46.00000000000001,
46,
18.000000000000004,
59,
55.00000000000001,
100,
48,
100
],
"000131": [
34,
50,
66,
25,
69.99999999999999,
75,
100,
36.99999999999999,
0
],
"000132": [
46.99999999999999,
56.00000000000001,
40,
17,
63,
48,
100,
36.99999999999999,
0
],
"000133": [
48,
55.00000000000001,
45,
25,
36.00000000000001,
54,
100,
46,
0
],
"000134": [
41,
39,
18,
14.000000000000002,
53,
64,
100,
51.000000000000014,
100
],
"000135": [
53,
42.00000000000001,
56.99999999999999,
17,
49,
46,
0,
50,
100
],
"000137": [
51,
36,
65,
10.000000000000002,
46,
54,
100,
33.00000000000001,
100
],
"000140": [
61,
37,
48,
38.99999999999999,
46,
60,
0,
34.99999999999999,
0
],
"000142": [
61,
31,
48,
19.000000000000004,
61,
72.00000000000001,
100,
43,
0
],
"000143": [
61,
41,
41,
21,
59,
63,
100,
55.000000000000014,
100
],
"000145": [
55.00000000000001,
59,
49,
10.000000000000002,
40.00000000000001,
61,
100,
46,
0
],
"000146": [
68,
46.99999999999999,
66,
24,
30,
71,
100,
41,
0
],
"000147": [
62,
49.00000000000001,
51,
36.99999999999999,
38.99999999999999,
61,
100,
47,
0
],
"000148": [
54,
43,
70,
18.000000000000004,
54,
71,
100,
40.00000000000001,
0
],
"000150": [
52,
43,
48,
24,
50,
38.00000000000001,
10,
48,
100
],
"000151": [
45,
56.00000000000001,
43,
12,
36.00000000000001,
52,
100,
40.00000000000001,
0
],
"000152": [
48,
44.00000000000001,
44,
16,
54,
50,
100,
51.000000000000014,
100
],
"000153": [
48,
40,
44,
21,
42,
36.99999999999999,
100,
48,
100
],
"000155": [
41,
56.99999999999999,
44,
32,
63,
63,
100,
46,
0
],
"000156": [
37,
51,
50,
26,
66,
68,
100,
46,
0
],
"000157": [
46.99999999999999,
42.00000000000001,
44,
27,
28.000000000000004,
62,
70,
45,
0
],
"000160": [
43,
42.00000000000001,
40,
34.99999999999999,
52,
50,
80,
56.99999999999999,
100
],
"000161": [
48,
52,
35,
17,
71,
56.99999999999999,
100,
38.00000000000001,
0
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
// var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
// var NUM_SLIDERS = 4;
// other variables can be in here too
// here's some examples for colors used
// const bg_color = [225, 206, 187];
// const fg_color = [151, 102, 52];
// const stroke_color = [95, 52, 8];
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i = 0; i < s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len, sum_y / s_len];
}
// This where you define your own face object
function McSweeneyFace() {
//frameRate(1);
// these are state variables for a face
// (your variables should be different!)
this.num_eyes = 2; // can be either 1 (cyclops) or 2 (two eyes)
this.eye_shift = -1; // range is -10 to 10
this.mouth_value = 4; // range is 0.5 to 8
//variables between 0-100;
this.jaw = 50;
this.eyes = 50;
this.cheek1 = 50;
this.mouth = 50;
this.cheek2 = 50;
this.colour_picker = 80;
this.horn_size = 50;
this.jaw_ang = 50;
this.eye_evil = 50;
// example of a function *inside* the face object.
// this draws a segment, and do_loop will connect the ends if true
this.draw_segment = function(segment, do_loop) {
for (let i = 0; i < segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
ellipse(px, py, 0.1);
if (i < segment.length - 1) {
let nx = segment[i + 1][0];
let ny = segment[i + 1][1];
line(px, py, nx, ny);
} else if (do_loop) {
let nx = segment[0][0];
let ny = segment[0][1];
line(px, py, nx, ny);
}
}
};
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
// fill(255);
// ellipse(0, 0, 4);
// return;
/*
// draw segments of face using points
fill(128);
stroke(128);
this.draw_segment(positions.chin);
fill(100, 0, 100);
stroke(100, 0, 100);
this.draw_segment(positions.nose_bridge);
this.draw_segment(positions.nose_tip);
strokeWeight(0.03);
fill(200, 0, 0);
stroke(200, 0, 0);
this.draw_segment(positions.top_lip);
this.draw_segment(positions.bottom_lip);
fill(255);
stroke(255);
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye); */
//---------------------------------------------------------------------------
//scale(4/10);
let colour_pic = int(map(this.colour_picker, 0, 100, 1, 3))
let colour = [];
let strokeCol = [];
if (colour_pic == 1) {
colour = [165, 146, 126];
strokeCol = [20];
} else if (colour_pic == 2) {
colour = [227, 218, 201];
strokeCol = [150];
} else if (colour_pic == 3) {
colour = [222, 202, 176];
strokeCol = [255];
}
// head
let cheek = 5;
let cheek_dist = 4;
let cheek_out = 5.5;
let cheek_height = map(this.cheek1, 0, 100, -1.5, -0.7, true);
let cheek_end_x = 4;
let cheek_end_y = 2;
var jaw_width = map(this.jaw, 0, 100, 3, 5);
var jaw_height = 3.5;
var chin_width = 1.5;
var chin_height = 6;
let mouthweight = 0.1;
let genstroke = 0.15;
let eyeposL = segment_average(positions.left_eye);
let eyeposR = segment_average(positions.right_eye);
let eyesizeL = (positions.left_eye[3][0] - positions.left_eye[0][0]);
let eyesizeR = (positions.right_eye[3][0] - positions.right_eye[0][0]);
let eyesizeRV = ((positions.right_eye[2][1] - positions.right_eye[4][1])) * 3;
let eyesizeLV = ((positions.right_eye[1][1] - positions.right_eye[5][1])) * 3;
//fill(colour);
stroke(strokeCol);
//stroke(145,136,116);
strokeCap(ROUND);
smooth();
strokeJoin(ROUND);
strokeWeight(genstroke);
//Crainium ------------------------------------------------------
//Horns ------------------------------------------------------
push();
noFill();
let nosl = positions.nose_bridge[0][1] - positions.nose_bridge[3][1];
let hornpos = ((eyeposR[1] + eyeposL[1])/2) + (nosl)
let horn_height =(map(this.horn_size, 0, 100, 0.75, 2));
//Fill -----
push();
fill(strokeCol);
stroke(strokeCol);
strokeWeight(genstroke/3)
triangle(positions.right_eyebrow[1][0],hornpos*1.1, positions.right_eyebrow[3][0],hornpos,
positions.chin[12][0]*0.95, hornpos + (nosl*horn_height ) );
triangle(positions.left_eyebrow[1][0],hornpos, positions.left_eyebrow[3][0],hornpos*1.1,
positions.chin[4][0]*0.95, (hornpos + (nosl*horn_height)) );
/*//if (horn_desc ==)
fill(255,0,0);
stroke(255,0,0);
triangle(positions.right_eyebrow[1][0]*1.4,hornpos*1.9, positions.right_eyebrow[3][0],hornpos*1.8,
positions.chin[12][0]*0.95, hornpos + (nosl*horn_height ) );
triangle(positions.left_eyebrow[1][0],hornpos*1.8, positions.left_eyebrow[3][0]*1.4,hornpos*1.9,
positions.chin[4][0]*0.95, (hornpos + (nosl*horn_height)) );
*/
pop();
//Top Horn --------
noFill();
beginShape();
curveVertex(positions.right_eyebrow[3][0]*0.8, eyeposR[1]); //
curveVertex(positions.right_eyebrow[3][0],hornpos);
curveVertex(positions.chin[12][0], hornpos + (nosl*horn_height ));
curveVertex(positions.chin[12][0]*1.5, hornpos + (nosl*horn_height)); //
endShape();
beginShape();
curveVertex(positions.right_eyebrow[1][0]*0.8, eyeposR[1]); //
curveVertex(positions.right_eyebrow[1][0],hornpos*1.1);
curveVertex(positions.chin[12][0], hornpos + (nosl*horn_height));
curveVertex(positions.chin[12][0]*2, hornpos + (nosl*horn_height)); //
endShape();
//Bottom horn ----
beginShape();
curveVertex(positions.right_eyebrow[1][0]*0.6,hornpos*1.5); //
curveVertex(positions.right_eyebrow[1][0],hornpos*1.1);
curveVertex(positions.right_eyebrow[3][0],hornpos);
curveVertex(positions.right_eyebrow[3][0]*1.4,hornpos*1.4); //
endShape();
//Left
beginShape();
curveVertex(positions.left_eyebrow[1][0]*0.8, eyeposL[1]); //
curveVertex(positions.left_eyebrow[1][0],hornpos);
curveVertex(positions.chin[4][0], hornpos + (nosl*horn_height));
curveVertex(positions.chin[4][0]*1.5, hornpos + (nosl*horn_height)); //
endShape();
beginShape();
curveVertex(positions.left_eyebrow[3][0]*0.8 , eyeposL[1]); //
curveVertex(positions.left_eyebrow[3][0],hornpos*1.1);
curveVertex(positions.chin[4][0], hornpos + (nosl*horn_height) );
curveVertex(positions.chin[4][0]*2, hornpos + (nosl*horn_height)); //
endShape();
//Bottom horn ----
beginShape();
curveVertex(positions.left_eyebrow[1][0]*1.4,hornpos*1.4); //
curveVertex(positions.left_eyebrow[1][0],hornpos);
curveVertex(positions.left_eyebrow[3][0],hornpos*1.1);
curveVertex(positions.left_eyebrow[3][0]*0.6,hornpos*1.5); //
endShape();
pop();
//Chin
//Chin
push();
let jaw_stroke = 0.3;
strokeWeight(genstroke);
noFill();
let jawrightx = (positions.chin[12][0] * 1.2)
let jawrighty = (positions.chin[12][1] * 1.1)
let jawleftx = (positions.chin[4][0] * 1.2)
let jawlefty = (positions.chin[4][1] * 1.1)
let jaw_angle = int(map(this.jaw_ang, 0, 100, 1, 2));
beginShape();
curveVertex(jawrightx + 1 * jaw_angle, jawrighty * jaw_angle);
curveVertex(jawrightx, jawrighty);
curveVertex(positions.chin[9][0], positions.chin[8][1]);
curveVertex(positions.chin[7][0], positions.chin[8][1]);
curveVertex(jawleftx, jawlefty);
curveVertex(jawleftx - 1* jaw_angle, jawlefty * jaw_angle);
endShape();
//Jaw Side Left ----
beginShape();
curveVertex(positions.chin[2][0] - 1, positions.chin[2][1] - 1);
curveVertex(positions.chin[2][0], positions.chin[2][1]);
curveVertex(jawleftx, jawlefty);
curveVertex(jawleftx - 1, jawlefty + 1);
endShape();
//Jaw Side Right ----
beginShape();
curveVertex(positions.chin[14][0] + 1, positions.chin[14][1] - 1);
curveVertex(positions.chin[14][0], positions.chin[14][1]);
curveVertex(jawrightx, jawrighty);
curveVertex(jawrightx + 1, jawrighty + 1);
endShape();
pop();
//Cheeks-------------------------
strokeWeight(genstroke);
noFill();
let cheekinnerY = (positions.chin[14][1] - positions.chin[15][1]) + positions.chin[15][1]
let cheekinnerX = (positions.chin[14][0] - (positions.chin[14][0] - positions.chin[12][0]));
beginShape();
curveVertex(positions.chin[16][0] - 1, positions.chin[16][1] - 1);
curveVertex(positions.chin[16][0] * 0.9, positions.chin[16][1]);
curveVertex(positions.chin[15][0] * 1.1, positions.chin[15][1]);
curveVertex(positions.chin[14][0] * 1.05, positions.chin[14][1]);
curveVertex(cheekinnerX, cheekinnerY);
curveVertex(cheekinnerX - 1, cheekinnerY + 0.5);
endShape();
let cheekinnerLY = (positions.chin[14][1] - positions.chin[1][1]) + positions.chin[1][1]
let cheekinnerLX = (positions.chin[2][0] - (positions.chin[2][0] - positions.chin[4][0]));
beginShape();
curveVertex(positions.chin[0][0] + 1, positions.chin[0][1] - 1);
curveVertex(positions.chin[0][0] * 0.9, positions.chin[0][1]);
curveVertex(positions.chin[1][0] * 1.1, positions.chin[1][1]);
curveVertex(positions.chin[2][0] * 1.05, positions.chin[2][1]);
curveVertex(cheekinnerLX, cheekinnerLY);
curveVertex(cheekinnerLX + 1, cheekinnerLY + 0.5);
endShape();
//Eyes-----------------------------------------------
push();
let eye_evil2 = map(this.eye_evil,0,100,0,3);
let smalleyeS = 4;
fill(200/eye_evil2,0,0);
strokeWeight(genstroke);
stroke('black');
ellipse(eyeposR[0],eyeposR[1], eyesizeR, eyesizeRV);
ellipse(eyeposL[0],eyeposL[1], eyesizeL, eyesizeLV);
noStroke();
fill(255,33*eye_evil2);
ellipse(eyeposR[0],eyeposR[1], eyesizeR/smalleyeS, eyesizeRV/smalleyeS);
ellipse(eyeposL[0],eyeposL[1], eyesizeL/smalleyeS, eyesizeLV/smalleyeS);
pop();
//mouth ------------------------------
let mouthcurveRy = positions.bottom_lip[0][1] - (positions.bottom_lip[10][1] - positions.bottom_lip[0][1])*3
let mouthcurveLy = positions.bottom_lip[6][1] - (positions.bottom_lip[8][1] - positions.bottom_lip[6][1])*3
let mouthfracLX = (positions.bottom_lip[2][0] + positions.top_lip[4][0]) / 2;
let mouthfracRX = (positions.bottom_lip[4][0] + positions.top_lip[2][0]) / 2;
let mouthfracRX2 = (positions.bottom_lip[6][0] + mouthfracRX) / 2
let mouthfracLX2 = (positions.bottom_lip[0][0] + mouthfracLX) / 2
let mouthheight = (positions.bottom_lip[3][1] - positions.top_lip[3][1])/2;
let mouthcenterheight = positions.bottom_lip[9][1] - ((positions.bottom_lip[9][1] - positions.top_lip[9][1])/2);
push();
noFill();
let check = 6;
translate(0,mouthweight*1/3)
stroke(200,0,0)
strokeWeight(mouthweight)
beginShape();
curveVertex(positions.bottom_lip[0][0] + 0.5, mouthcurveRy);
curveVertex(positions.bottom_lip[0][0], positions.bottom_lip[0][1]);
curveVertex(positions.bottom_lip[6][0], positions.bottom_lip[6][1]);
curveVertex(positions.bottom_lip[6][0] - 0.5, mouthcurveLy);
endShape();
line(mouthfracRX,mouthcenterheight-mouthheight, mouthfracRX, mouthcenterheight+mouthheight);
line(mouthfracRX2,mouthcenterheight-mouthheight, mouthfracRX2, mouthcenterheight+mouthheight);
line(mouthfracLX,mouthcenterheight-mouthheight, mouthfracLX, mouthcenterheight+mouthheight);
line(mouthfracLX2,mouthcenterheight-mouthheight, mouthfracLX2, mouthcenterheight+mouthheight);
pop();
//inner -----
push();
strokeWeight(mouthweight);
stroke(0);
beginShape();
curveVertex(positions.bottom_lip[0][0]+0.5, mouthcurveRy);
curveVertex(positions.bottom_lip[0][0],positions.bottom_lip[0][1]);
curveVertex(positions.bottom_lip[6][0], positions.bottom_lip[6][1]);
curveVertex(positions.bottom_lip[6][0]-0.5, mouthcurveLy);
endShape();
line(mouthfracRX,mouthcenterheight-mouthheight, mouthfracRX, mouthcenterheight+mouthheight);
line(mouthfracRX2,mouthcenterheight-mouthheight, mouthfracRX2, mouthcenterheight+mouthheight);
line(mouthfracLX,mouthcenterheight-mouthheight, mouthfracLX, mouthcenterheight+mouthheight);
line(mouthfracLX2,mouthcenterheight-mouthheight, mouthfracLX2, mouthcenterheight+mouthheight);
pop();
//Nose -------------
push();
fill(colour);
//fill(strokeCol);
strokeWeight(genstroke);
let nose_width = map(jaw_width, 3, 5, 0.5, 1);
let nose_top = positions.nose_bridge[1][1] - positions.nose_bridge[0][1];
triangle(positions.nose_bridge[0][0], positions.nose_bridge[1][1] - nose_top / 2, positions.nose_tip[0][0], positions.nose_tip[0][1], positions.nose_tip[4][0], positions.nose_tip[4][1])
pop();
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.colour_picker = int(map(settings[0], 0, 100, 0, 100));
this.horn_size = map(settings[1], 0, 100, 0, 100);
this.jaw_ang = map(settings[2], 0, 100, 0, 100);
this.eye_evil = map(settings[3], 0, 100, 0, 100);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(0);
settings[0] = map(this.colour_picker, 0, 100, 0, 100);
settings[1] = map(this.horn_size, 0,100, 0, 100);
settings[2] = map(this.jaw_ang, 0, 100, 0, 100);
settings[3] = map(this.eye_evil, 0, 100, 0, 100);
return settings;
}
}
{
"000001": [
0,
0,
100,
0
],
"000002": [
0,
33,
100,
100
],
"000005": [
70,
53,
100,
54
],
"000006": [
78,
41,
100,
79
],
"000007": [
68,
77,
10,
79
],
"000009": [
0,
22,
100,
50
],
"000010": [
0,
0,
100,
0
],
"000013": [
0,
85,
0,
79
],
"000014": [
76,
19,
100,
32
],
"000015": [
0,
93,
0,
78
],
"000016": [
0,
77,
0,
30
],
"000018": [
0,
22,
100,
54
],
"000020": [
0,
62,
0,
22
],
"000023": [
0,
79,
0,
18
],
"000025": [
0,
67,
0,
100
],
"000028": [
56.99999999999999,
22,
100,
73
],
"000029": [
0,
0,
100,
16
],
"000030": [
0,
56.00000000000001,
0,
37
],
"000031": [
0,
37,
100,
18
],
"000032": [
0,
57.99999999999999,
0,
87
],
"000035": [
0,
57.99999999999999,
100,
65
],
"000037": [
77,
100,
0,
66
],
"000038": [
0,
76,
0,
33
],
"000040": [
54,
0,
100,
0
],
"000041": [
54,
73,
0,
24
],
"000042": [
0,
34,
100,
48
],
"000043": [
0,
13,
100,
30
],
"000044": [
94,
13,
100,
30
],
"000045": [
0,
10,
100,
7.000000000000001
],
"000047": [
0,
10,
100,
44
],
"000048": [
0,
69,
0,
71
],
"000050": [
53,
84,
0,
39
],
"000051": [
53,
69,
0,
100
],
"000052": [
0,
87,
0,
39
],
"000054": [
0,
87,
1,
54
],
"000055": [
56.00000000000001,
87,
0,
69
],
"000056": [
0,
56.99999999999999,
0,
84
],
"000058": [
0,
8,
100,
70
],
"000060": [
83,
68,
0,
62
],
"000064": [
0,
67,
0,
62
],
"000065": [
56.99999999999999,
78,
0,
91
],
"000068": [
0,
89,
0,
100
],
"000069": [
0,
75,
0,
100
],
"000071": [
0,
28.000000000000004,
100,
100
],
"000073": [
0,
0,
100,
0
],
"000076": [
0,
100,
0,
0
],
"000077": [
0,
0,
100,
0
],
"000078": [
0,
3,
100,
62
],
"000079": [
0,
81,
0,
62
],
"000080": [
0,
100,
0,
39
],
"000081": [
60,
90,
0,
60
],
"000083": [
0,
12,
100,
60
],
"000085": [
0,
0,
100,
0
],
"000086": [
0,
0,
100,
0
],
"000088": [
64,
0,
100,
12
],
"000091": [
0,
89,
0,
26
],
"000092": [
0,
12,
100,
14.000000000000002
],
"000096": [
0,
0,
100,
26
],
"000097": [
0,
0,
100,
0
],
"000099": [
0,
7.000000000000001,
100,
28.999999999999996
],
"000100": [
0,
31,
100,
37
],
"000103": [
0,
0,
100,
18
],
"000104": [
0,
71,
0,
32
],
"000106": [
0,
10,
100,
14.000000000000002
],
"000108": [
0,
10,
100,
14.000000000000002
],
"000109": [
0,
68,
0,
46
],
"000110": [
0,
4,
100,
16
],
"000111": [
75,
15,
100,
22
],
"000114": [
0,
75,
0,
52
],
"000115": [
0,
100,
0,
76
],
"000116": [
0,
84,
0,
25
],
"000117": [
80,
19,
100,
16
],
"000118": [
64,
0,
100,
0
],
"000121": [
64,
6,
100,
7.000000000000001
],
"000122": [
0,
13,
100,
100
],
"000125": [
0,
81,
0,
64
],
"000126": [
0,
0,
100,
0
],
"000129": [
0,
82,
0,
83
],
"000131": [
66,
10,
100,
31
],
"000132": [
79,
10,
100,
31
],
"000133": [
0,
4,
100,
14.000000000000002
],
"000134": [
84,
77,
0,
62
],
"000135": [
67,
63,
0,
35
],
"000137": [
0,
70,
0,
35
],
"000140": [
0,
0,
100,
13
],
"000142": [
0,
6,
100,
48
],
"000143": [
0,
81,
0,
79
],
"000145": [
0,
4,
100,
18
],
"000146": [
0,
0,
100,
0
],
"000147": [
0,
0,
100,
0
],
"000148": [
0,
9,
100,
38
],
"000150": [
0,
67,
0,
77
],
"000151": [
66,
8,
100,
22
],
"000152": [
0,
68,
0,
11
],
"000153": [
0,
85,
0,
25
],
"000155": [
0,
0,
100,
25
],
"000156": [
0,
8,
100,
41
],
"000157": [
0,
0,
100,
9
],
"000160": [
0,
83,
0,
60
],
"000161": [
0,
10,
100,
12
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
//var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
// var NUM_SLIDERS = 7;
// other variables can be in here too
// here's some examples for colors used
// const bg_color = [225, 206, 187];
// const fg_color = [151, 102, 52];
// const stroke_color = [95, 52, 8];
let cluster = new Cluster();
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i = 0; i < s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len, sum_y / s_len];
}
// This where you define your own face object
function NgFace() {
// these are state variables for a face
// (your variables should be different!)
this.numOfSq = 7;
this.numOfTri = focusedRandom(0, 15);
this.numOfEll = 7;
this.hairColorSelector = 5;
this.faceColorSelector = 5;
this.eyeColorSelector = 5;
this.eye_shift = -1;
this.makeUp = 0;
// example of a function *inside* the face object.
// this draws a segment, and do_loop will connect the ends if true
//
this.draw_segment = function (segment, scaleX, scaleY) {
for (let i = 0; i < segment.length; i += 1) {
let px = segment[i][0];
let py = segment[i][1];
push()
translate(px, py);
scale(scaleX, scaleY);
rotate(focusedRandom(10, 350));
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop();
}
};
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function (positions) {
//Colour initialization
let faceColor = 0;
let faceShad = 0;
let hairColor = 0;
let eyeColor = 0;
let eyeBallColor = 255;
let mouthColor = 255;
//Hair colour range using lerpColor() function
let fromHair = color(0, 0, 0);
let toHair = color(252, 226, 91);
let interHair = lerpColor(fromHair, toHair, this.hairColorSelector);
//Face colour range using lerpColor() function
let fromFace = color(105, 64, 29);
let toFace = color(255, 219, 172);
let interFace = lerpColor(fromFace, toFace, this.faceColorSelector);
//FaceShad colour range using lerpColor() function
let fromFaceShad = color(64, 39, 17);
let toFaceShad = color(227, 195, 154);
let interFaceShad = lerpColor(fromFaceShad, toFaceShad, this.faceColorSelector);
//Eye colour range using lerpColor() function
let fromEye = color(0, 0, 0);
let toEye = color(0, 255, 247);
let interEye = lerpColor(fromEye, toEye, this.eyeColorSelector);
//Shared Variable
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye);
let top_mouth_pos = segment_average(positions.top_lip);
let bottom_mouth_pos = segment_average(positions.bottom_lip);
let avgBrowLine = (positions.left_eyebrow[2][1] + positions.right_eyebrow[2][1]) / 2
const makeupThreshold = 0.475;
noStroke()
//face
let faceback_midpt_x = ((positions.chin[16][0] - positions.chin[0][0]) / 2) + positions.chin[0][0];
let faceback_midpt_y = ((positions.chin[8][1] - avgBrowLine) / 2) + avgBrowLine;
let faceback_height = dist(positions.chin[8][0], avgBrowLine, positions.chin[8][0], positions.chin[8][1]);
let faceback_y_scale = map(faceback_height, 0.01, 3.78, 0.01, 1.85);
let faceback_width = dist(positions.chin[0][0], positions.chin[0][1], positions.chin[16][0], positions.chin[16][1]);
let faceback_x_scale = map(faceback_width, 0.01, 3.31, 0.1, 1.25);
//Cheeks to show face direction
push()
translate(faceback_midpt_x + 0, faceback_midpt_y - 0.55);
scale(faceback_x_scale, faceback_y_scale);
fill(interFaceShad);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop()
let faceMidPtX = ((right_eye_pos[0] - left_eye_pos[0]) / 2) + left_eye_pos[0];
let faceMidPtY = ((positions.chin[8][1] - avgBrowLine) / 2) + avgBrowLine;
let face_height = dist(positions.chin[8][0], avgBrowLine, positions.chin[8][0], positions.chin[8][1]);
let face_y_scale = map(face_height, 0.01, 3.5, 0.01, 1.3);
let face_width = dist(left_eye_pos[0], left_eye_pos[1], right_eye_pos[0], right_eye_pos[1]);
let face_x_scale = map(face_width, 0.01, 1.4, 0.1, 0.8);
push()
fill(interFace)
translate(faceMidPtX, faceMidPtY + 0.1);
scale(face_x_scale, face_y_scale);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);//Lower face
translate(0, -1);
scale(1.2, 1);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);//Upper face
pop()
//eyeball
//Eye shadow
if (this.makeUp > makeupThreshold) {
fill(50, 50);
//Left Eye
push();
translate(left_eye_pos[0], left_eye_pos[1] - 0.1);
scale(0.2, 0.1);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop();
//Right Eye
push();
translate(right_eye_pos[0], right_eye_pos[1] - 0.1);
scale(0.2, 0.1);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop();
}
//Eyes
fill(255);
push();
translate(left_eye_pos[0], left_eye_pos[1]);
scale(0.2, 0.1);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop();
push();
translate(right_eye_pos[0], right_eye_pos[1]);
scale(0.2, 0.1);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop();
//eyebrow
fill(interHair);
//Left Eyebrow
for (let j = 0; j < positions.left_eyebrow.length - 1; j++) {
let v1 = createVector(positions.left_eyebrow[j][0], positions.left_eyebrow[j][1]);
let v2 = createVector(positions.left_eyebrow[j + 1][0], positions.left_eyebrow[j + 1][1]);
let angleBetweenL = v1.angleBetween(v2);
push();
translate(positions.left_eyebrow[j][0], positions.left_eyebrow[j][1]);
rotate(-angleBetweenL);
scale(0.15, 0.05);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop();
}
//Right Eyebrow
for (let k = 0; k < positions.right_eyebrow.length - 1; k++) {
let v3 = createVector(positions.right_eyebrow[k][0], positions.right_eyebrow[k][1]);
let v4 = createVector(positions.right_eyebrow[k + 1][0], positions.right_eyebrow[k + 1][1]);
let angleBetweenR = v3.angleBetween(v4);
push();
translate(positions.right_eyebrow[k][0], positions.right_eyebrow[k][1]);
rotate(angleBetweenR);
scale(0.15, 0.05);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop()
}
// pupils
let curEyeShift = 0.04 * this.eye_shift;
fill(interEye);
//Left pupil
push()
translate(left_eye_pos[0] + curEyeShift, left_eye_pos[1]);
scale(0.07);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop();
//Right pupil
push();
translate(right_eye_pos[0] + curEyeShift, right_eye_pos[1]);
scale(0.07);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop();
//mouth
let mouth_midpt_y = ((positions.bottom_lip[9][1] - positions.top_lip[9][1]) / 2) + positions.top_lip[9][1];
let mouth_midpt_x = ((positions.top_lip[6][0] - positions.top_lip[0][0]) / 2) + positions.top_lip[0][0];
let mouth_height = dist(positions.top_lip[9][0], positions.top_lip[9][1], positions.bottom_lip[9][0], positions.bottom_lip[9][1]);
let mouth_y_scale = map(mouth_height, 0.1, 0.35, 0.005, 0.1);
let mouth_width = dist(positions.top_lip[0][0], positions.top_lip[0][1], positions.top_lip[6][0], positions.top_lip[6][1]);
let mouth_x_scale = map(mouth_width, 0.01, 1.5, 0.01, 0.35);
//Turn mouth black when it is "closed"
if (mouth_height <= 0.1) {
mouthColor = 0;
}
//lipstick
if (this.makeUp > makeupThreshold) {
push()
translate(mouth_midpt_x, mouth_midpt_y);
scale(mouth_x_scale + 0.05, mouth_y_scale + 0.05);
fill(235, 64, 52);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop()
}
push()
translate(mouth_midpt_x, mouth_midpt_y);
scale(mouth_x_scale, mouth_y_scale);
fill(mouthColor);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop()
//nose
blendMode(MULTIPLY)
fill(100, 0, 100);
let noseq1 = color(150);
let noseq2 = color(50);
if (positions.nose_bridge[3][0] <= positions.nose_tip[2][0]) {
noseq1 = color(50);
noseq2 = color(150);
}
fill(noseq1);
beginShape();
vertex(positions.nose_bridge[0][0], positions.nose_bridge[0][1]);
vertex(positions.nose_tip[0][0], positions.nose_tip[0][1]);
vertex(positions.nose_tip[2][0], positions.nose_tip[2][1]);
vertex(positions.nose_bridge[3][0], positions.nose_bridge[3][1]);
endShape(CLOSE);
fill(noseq2);
beginShape();
vertex(positions.nose_bridge[0][0], positions.nose_bridge[0][1]);
vertex(positions.nose_bridge[3][0], positions.nose_bridge[3][1]);
vertex(positions.nose_tip[2][0], positions.nose_tip[2][1]);
vertex(positions.nose_tip[4][0], positions.nose_tip[4][1]);
endShape(CLOSE);
//Blush
if (this.makeUp > makeupThreshold) {
push();
fill(255, 233, 232, 20);
translate(left_eye_pos[0], positions.nose_bridge[3][1] + 0.2);
scale(0.3, 0.5);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop();
push();
fill(255, 233, 232, 15);
translate(right_eye_pos[0], positions.nose_bridge[3][1] + 0.2);
scale(0.3, 0.5);
cluster.draw(this.numOfSq, this.numOfTri, this.numOfEll);
pop();
}
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function (settings) {
this.faceColorSelector = map(settings[0], 0, 100, 0, 1);
this.eye_shift = map(settings[1], 0, 100, -4, 4);
this.eyeColorSelector = map(settings[2], 0, 100, 0, 1);
this.hairColorSelector = map(settings[3], 0, 100, 0, 1);
this.makeUp = map(settings[4], 0, 100, 0, 1);
this.numOfSq = int(map(settings[5], 0, 100, 0, 15));
this.numOfEll = int(map(settings[6], 0, 100, 0, 15));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function () {
let settings = new Array(6)
settings[0] = map(this.faceColorSelector, 0, 1, 0, 100);
settings[1] = map(this.eye_shift, -4, 4, 0, 100);
settings[2] = map(this.eyeColorSelector, 0, 1, 0, 100);
settings[3] = map(this.hairColorSelector, 0, 1, 0, 100);
settings[4] = map(this.makeUp, 0, 1, 0, 100);
settings[5] = map(this.numOfSq, 0, 15, 0, 100);
settings[6] = map(this.numOfEll, 0, 15, 0, 100);
return settings;
}
}
function Cluster() {
this.arrayXSq = [];
this.arrayYSq = [];
this.arraySSq = [];
this.arrayXTri = [];
this.arrayYTri = [];
this.arraySTri = [];
this.arrayXEll = [];
this.arrayYEll = [];
this.arraySEll = [];
for (let i = 0; i < 20; i++) {
this.xPosSq = focusedRandom(-3, 3) * 0.4;
this.yPosSq = focusedRandom(-3, 3) * 0.4;
this.sSizeSq = focusedRandom(4, 7) * 0.3;
this.arrayXSq.push(this.xPosSq);
this.arrayYSq.push(this.yPosSq);
this.arraySSq.push(this.sSizeSq);
this.xPosTri = focusedRandom(-3, 3) * 0.4;
this.yPosTri = focusedRandom(-3, 3) * 0.4;
this.sSizeTri = focusedRandom(4, 7) * 0.2;
this.arrayXTri.push(this.xPosTri);
this.arrayYTri.push(this.yPosTri);
this.arraySTri.push(this.sSizeTri);
this.xPosEll = focusedRandom(-3, 3) * 0.4;
this.yPosEll = focusedRandom(-3, 3) * 0.4;
this.sSizeEll = focusedRandom(4, 7) * 0.3;
this.arrayXEll.push(this.xPosEll);
this.arrayYEll.push(this.yPosEll);
this.arraySEll.push(this.sSizeEll);
}
this.draw = function (testValue1, testValue2, testValue3) {
rectMode(CENTER);
noStroke();
beginShape();
for (let j = 0; j < testValue1; j++) {
let x = this.arrayXSq[j];
let y = this.arrayYSq[j];
if (x < 0 && y < 0) {
x += ((5 / 3) * 0.4);
y += ((5 / 4) * 0.4);
} else if (x < 0 && y > 0) {
x += ((5 / 3) * 0.4);
y -= ((5 / 4) * 0.4);
} else if (x > 0 && y > 0) {
x -= ((5 / 3) * 0.4);
y -= ((5 / 4) * 0.4);
} else if (x > 0 && y < 0) {
x -= ((5 / 3) * 0.4);
y += ((5 / 4) * 0.4);
}
push();
translate(x, y);
//vertex(x, y);
square(0, 0, this.arraySSq[j]);
pop();
}
endShape(CLOSE);
beginShape();
for (let k = 0; k < testValue2; k++) {
let x = this.arrayXTri[k];
let y = this.arrayYTri[k];
if (x < 0 && y < 0) {
x += ((5 / 3) * 0.4);
y += ((5 / 4) * 0.4);
} else if (x < 0 && y > 0) {
x += ((5 / 3) * 0.4);
y -= ((5 / 4) * 0.4);
} else if (x > 0 && y > 0) {
x -= ((5 / 3) * 0.4);
y -= ((5 / 4) * 0.4);
} else if (x > 0 && y < 0) {
x -= ((5 / 3) * 0.4);
y += ((5 / 4) * 0.4);
}
push();
translate(x, y);
//vertex(x, y);
cusTriangle(0, 0, this.arraySTri[k]);
pop();
}
endShape(CLOSE);
beginShape();
for (let l = 0; l < testValue3; l++) {
let x = this.arrayXEll[l];
let y = this.arrayYEll[l];
if (x < 0 && y < 0) {
x += ((5 / 3) * 0.4);
y += ((5 / 4) * 0.4);
} else if (x < 0 && y > 0) {
x += ((5 / 3) * 0.4);
y -= ((5 / 4) * 0.4);
} else if (x > 0 && y > 0) {
x -= ((5 / 3) * 0.4);
y -= ((5 / 4) * 0.4);
} else if (x > 0 && y < 0) {
x -= ((5 / 3) * 0.4);
y += ((5 / 4) * 0.4);
}
push();
translate(x, y);
//vertex(x, y);
ellipse(0, 0, this.arraySEll[l]);
pop();
}
endShape(CLOSE);
};
}
function cusTriangle(x, y, radius) {
let angle = 360 / 3;
beginShape();
for (let a = 0; a < 360; a += angle) {
let sx = x + cos(a) * radius;
let sy = y + sin(a) * radius;
vertex(sx, sy);
}
endShape(CLOSE);
}
{
"000001": [
98,
77,
0,
82,
100,
0,
100
],
"000002": [
100,
54,
0,
0,
100,
0,
100
],
"000005": [
100,
55.00000000000001,
0,
89,
100,
0,
100
],
"000006": [
72,
55.00000000000001,
0,
76,
100,
0,
100
],
"000007": [
48,
55.00000000000001,
0,
0,
0,
100,
0
],
"000009": [
94,
42,
0,
0,
100,
0,
100
],
"000010": [
94,
63,
60,
65,
100,
0,
100
],
"000013": [
94,
63,
74,
73,
0,
100,
0
],
"000014": [
39,
54,
0,
0,
100,
0,
100
],
"000015": [
94,
54,
30,
45,
0,
100,
0
],
"000016": [
94,
78,
0,
0,
0,
100,
0
],
"000018": [
100,
61,
64,
81,
100,
0,
100
],
"000020": [
95,
61,
0,
0,
0,
100,
0
],
"000023": [
95,
99,
96,
0,
0,
100,
0
],
"000025": [
95,
54,
0,
0,
0,
100,
0
],
"000028": [
57.99999999999999,
54,
0,
37,
100,
0,
100
],
"000029": [
91,
69,
100,
100,
100,
0,
100
],
"000030": [
100,
69,
35,
43,
0,
100,
0
],
"000031": [
93,
69,
93,
74,
100,
0,
100
],
"000032": [
93,
57.99999999999999,
0,
23,
0,
100,
0
],
"000035": [
100,
72,
0,
23,
100,
0,
100
],
"000037": [
44,
72,
0,
0,
0,
100,
0
],
"000038": [
100,
54,
62,
25,
0,
100,
0
],
"000040": [
77,
62,
0,
14.000000000000002,
100,
0,
100
],
"000041": [
85,
62,
0,
14.000000000000002,
0,
100,
0
],
"000042": [
100,
62,
80,
54,
100,
0,
100
],
"000043": [
100,
62,
0,
0,
100,
0,
100
],
"000044": [
42,
62,
0,
0,
100,
0,
100
],
"000045": [
74,
73,
0,
0,
100,
0,
100
],
"000047": [
44,
86,
0,
0,
100,
0,
100
],
"000048": [
100,
71,
0,
0,
0,
100,
0
],
"000050": [
87,
42,
0,
0,
0,
100,
0
],
"000051": [
87,
59,
0,
0,
0,
100,
0
],
"000052": [
92,
59,
78,
30,
0,
100,
0
],
"000054": [
100,
70,
55.00000000000001,
38,
100,
0,
100
],
"000055": [
100,
50,
0,
0,
0,
100,
0
],
"000056": [
100,
50,
0,
0,
0,
100,
0
],
"000058": [
100,
74,
76,
0,
100,
0,
100
],
"000060": [
17,
28.000000000000004,
0,
0,
0,
100,
0
],
"000064": [
79,
52,
41,
0,
0,
100,
0
],
"000065": [
80,
52,
0,
0,
0,
100,
0
],
"000068": [
100,
52,
37,
0,
0,
100,
0
],
"000069": [
100,
36,
0,
0,
0,
100,
0
],
"000071": [
100,
55.00000000000001,
38,
71,
100,
0,
100
],
"000073": [
74,
61,
6,
71,
100,
0,
100
],
"000076": [
90,
44,
0,
0,
0,
100,
0
],
"000077": [
72,
75,
0,
0,
100,
0,
100
],
"000078": [
96,
59,
65,
0,
100,
0,
100
],
"000079": [
96,
62,
0,
13,
0,
100,
0
],
"000080": [
100,
38,
61,
13,
0,
100,
0
],
"000081": [
60,
71,
0,
13,
0,
100,
0
],
"000083": [
100,
71,
33,
12,
100,
0,
100
],
"000085": [
100,
71,
46,
12,
100,
0,
100
],
"000086": [
100,
48,
0,
0,
100,
0,
100
],
"000088": [
97,
76,
20,
0,
100,
0,
100
],
"000091": [
100,
47,
1,
0,
0,
100,
0
],
"000092": [
100,
73,
46,
56.00000000000001,
100,
0,
100
],
"000096": [
84,
52,
0,
0,
100,
0,
100
],
"000097": [
84,
68,
57.99999999999999,
63,
100,
0,
100
],
"000099": [
84,
68,
57.99999999999999,
63,
100,
0,
100
],
"000100": [
100,
85,
3,
28.000000000000004,
100,
0,
100
],
"000103": [
100,
52,
71,
19,
100,
0,
100
],
"000104": [
100,
52,
71,
48,
0,
100,
0
],
"000106": [
100,
59,
0,
22,
100,
0,
100
],
"000108": [
100,
59,
84,
84,
100,
0,
100
],
"000109": [
94,
61,
56.00000000000001,
84,
0,
100,
0
],
"000110": [
94,
70,
45,
25,
100,
0,
100
],
"000111": [
48,
73,
12,
55.00000000000001,
100,
0,
100
],
"000114": [
100,
51,
0,
0,
0,
100,
0
],
"000115": [
100,
50,
53,
56.99999999999999,
0,
100,
0
],
"000116": [
100,
46,
4,
21,
0,
100,
0
],
"000117": [
42,
76,
4,
21,
100,
0,
100
],
"000118": [
73,
57.99999999999999,
4,
21,
100,
0,
100
],
"000121": [
64,
73,
4,
21,
100,
0,
100
],
"000122": [
100,
73,
36,
88,
100,
0,
100
],
"000125": [
100,
48,
57.99999999999999,
5,
0,
100,
0
],
"000126": [
81,
51,
92,
91,
100,
0,
100
],
"000129": [
100,
51,
25,
0,
0,
100,
0
],
"000131": [
67,
66,
0,
0,
100,
0,
100
],
"000132": [
50,
66,
0,
0,
100,
0,
100
],
"000133": [
100,
66,
100,
93,
100,
0,
100
],
"000134": [
8,
14.000000000000002,
0,
0,
0,
100,
0
],
"000135": [
37,
71,
0,
0,
0,
100,
0
],
"000137": [
100,
71,
56.00000000000001,
0,
0,
100,
0
],
"000140": [
97,
64,
94,
93,
100,
0,
100
],
"000142": [
84,
67,
0,
0,
100,
0,
100
],
"000143": [
98,
45,
56.99999999999999,
31,
0,
100,
0
],
"000145": [
89,
82,
11,
10,
100,
0,
100
],
"000146": [
60,
82,
11,
10,
100,
0,
100
],
"000147": [
100,
86,
85,
80,
100,
0,
100
],
"000148": [
100,
86,
77,
18,
100,
0,
100
],
"000150": [
100,
39,
63,
18,
0,
100,
0
],
"000151": [
80,
67,
0,
18,
100,
0,
100
],
"000152": [
80,
67,
53,
22,
0,
100,
0
],
"000153": [
80,
35,
0,
0,
0,
100,
0
],
"000155": [
84,
66,
0,
0,
100,
0,
100
],
"000156": [
100,
66,
62,
86,
100,
0,
100
],
"000157": [
100,
68,
87,
94,
100,
0,
100
],
"000160": [
54,
54,
0,
0,
0,
100,
0
],
"000161": [
100,
77,
86,
0,
100,
0,
100
]
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
// var DEBUG_MODE = true;
// this can be used to set the number of sliders to show
// var NUM_SLIDERS = 6;
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i=0; i<s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len , sum_y / s_len ];
}
// This where you define your own face object
function NuescaFace() {
const female_col = color(189,125,106);
const male_col = color(80, 119, 122);
const light_col = color(247, 240, 244);
const med_col = color(221,148,192);
const dark_col = color(13, 32, 33);
const eye_light = color(153, 201, 196);
const eye_med = color(237, 185, 126);
const eye_dark = color(54, 29, 1);
// these are state variables for a face
this.nose_value = 1; // range is 0.8 to 1.5
this.lash_brow_value = 1; //range is 0 to 1
this.eye_size = 1; //range is 0.8 to 1
this.ear_color = 1; // range is 0 to 1
this.skin_color =1; //range is 0 to 2
this.eye_color =1; //range is 0 to 2
// example of a function *inside* the face object.
// this draws a segment, and do_loop will connect the ends if true
this.draw_segment = function(segment, do_loop) {
for(let i=0; i<segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
ellipse(px, py, 0.1);
if(i < segment.length - 1) {
let nx = segment[i+1][0];
let ny = segment[i+1][1];
line(px, py, nx, ny);
}
else if(do_loop) {
let nx = segment[0][0];
let ny = segment[0][1];
line(px, py, nx, ny);
}
}
};
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
//ears
if (this.ear_color == 0){
fill(female_col);
}
else{
fill(male_col);
}
strokeWeight(0.05);
triangle(-1.6, -1.6, -2.3, -3.2, -0.28, -2.2);
triangle(1.6, -1.6, 2.3, -3.2, 0.28, -2.2);
//inner ear
if (this.skin_color == 0){
fill(light_col);
}
else if (this.skin_color == 1){
fill(med_col);
}
else{
fill(dark_col);
}
triangle(-1.4, -1.7, -1.9, -2.8, -0.6, -2.1);
triangle(1.4, -1.7, 1.9, -2.8, 0.6, -2.1);
stroke(0);
strokeWeight(0.05);
if(this.lash_brow_value == 0){
//brows
let left_brow_pos = positions.left_eyebrow[0];
let left_brow_pos2 = positions.left_eyebrow[4];
let right_brow_pos = positions.right_eyebrow[0];
let right_brow_pos2 = positions.right_eyebrow[4];
stroke(0);
strokeWeight(0.2);
line(left_brow_pos[0], left_brow_pos[1] + 0.1, left_brow_pos2[0], left_brow_pos2[1] + 0.1);
line(right_brow_pos[0], right_brow_pos[1] + 0.1, right_brow_pos2[0], right_brow_pos2[1] + 0.1);
}
//eyes
let left_eye_pos = segment_average(positions.left_eye);
let left_eye_pos2 = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye);
let right_eye_pos2 = segment_average(positions.right_eye);
//eyelashes
stroke(0);
if(this.lash_brow_value == 0){
strokeWeight(0);
}
else if(this.lash_brow_value == 1){
strokeWeight(0.1);
}
//left
line(left_eye_pos[0]- 0.3, left_eye_pos[1] + 0.3, left_eye_pos2[0] -0.5, left_eye_pos2[1]- 0.3);
line(left_eye_pos[0], left_eye_pos[1] + 0.2, left_eye_pos2[0], left_eye_pos2[1]- 0.4);
line(left_eye_pos[0]+ 0.3, left_eye_pos[1] + 0.3, left_eye_pos2[0] +0.5, left_eye_pos2[1]- 0.3);
//right
line(right_eye_pos[0]- 0.3, right_eye_pos[1] + 0.3, right_eye_pos2[0] -0.5, right_eye_pos2[1]- 0.3);
line(right_eye_pos[0], right_eye_pos[1] + 0.2, right_eye_pos2[0], right_eye_pos2[1]- 0.4);
line(right_eye_pos[0]+ 0.3, right_eye_pos[1] + 0.3, right_eye_pos2[0] +0.5, right_eye_pos2[1]- 0.3);
//eye_shape
fill(255);
strokeWeight(0.05);
ellipse(left_eye_pos[0], left_eye_pos[1]+0.3, 1, this.eye_size);
ellipse(right_eye_pos[0], right_eye_pos[1]+0.3, 1, this.eye_size);
//eyeColour
noStroke();
if (this.eye_color == 0){
fill(eye_light);
}
else if (this.eye_color == 1){
fill(eye_med);
}
else{
fill(eye_dark);
}
ellipse(left_eye_pos[0], left_eye_pos[1]+0.3, 0.5, this.eye_size);
ellipse(right_eye_pos[0], right_eye_pos[1]+0.3, 0.5, this.eye_size);
//pupil
fill(0);
ellipse(left_eye_pos[0], left_eye_pos[1]+0.3, 0.2, this.eye_size - 0.2);
ellipse(right_eye_pos[0], right_eye_pos[1]+0.3, 0.2, this.eye_size - 0.2);
// nose setup
let nose_center = positions.nose_tip[2];
//mouth setup
let inner_left_lip = positions.top_lip[2];
let outer_left_lip = positions.top_lip[0];
let inner_right_lip = positions.top_lip[4];
let outer_right_lip = positions.top_lip[7];
let right_bottom_lip = positions.bottom_lip[2];
let center_bottom_lip = positions.bottom_lip[4];
let left_bottom_lip = positions.bottom_lip[7];
//mouth draw
fill(0);
stroke(0);
beginShape();
vertex(outer_left_lip[0], outer_left_lip[1]);
vertex(inner_left_lip[0] - 0.1, inner_left_lip[1] + 0.2);
vertex(nose_center[0], nose_center[1] + 0.4);
vertex(nose_center[0], nose_center[1] + 0.1);
vertex(nose_center[0], nose_center[1] + 0.4);
vertex(inner_right_lip[0] + 0.1, inner_right_lip[1] +0.2);
vertex(outer_right_lip[0] - 0.1, outer_right_lip[1]);
vertex(right_bottom_lip[0], right_bottom_lip[1]);
vertex(center_bottom_lip[0], center_bottom_lip[1]);
vertex(left_bottom_lip[0], left_bottom_lip[1]);
endShape(CLOSE);
//teeth
fill(255);
noStroke();
ellipse(inner_left_lip[0], inner_left_lip[1] + 0.32, 0.1, 0.34);
ellipse(inner_right_lip[0], inner_right_lip[1] + 0.32, 0.1, 0.34);
//nose draw
stroke(0);
strokeWeight(0.05);
if (this.skin_color == 0){
fill(light_col);
}
else if (this.skin_color == 1){
fill(med_col);
}
else{
fill(dark_col);
}
ellipse(nose_center[0], nose_center[1], 0.5 * this.nose_value, 0.25 * this.nose_value);
//whiskers
noFill();
strokeWeight(0.04);
line(left_eye_pos[0] - 1.8, left_eye_pos[1] + 1, left_eye_pos2[0], nose_center[1] + 0.04);
line(left_eye_pos[0] - 1.8, left_eye_pos[1] + 1.4, left_eye_pos2[0], nose_center[1] + 0.04);
line(right_eye_pos[0] + 1.8, left_eye_pos[1] + 1, right_eye_pos2[0], nose_center[1] + 0.04);
line(right_eye_pos[0] + 1.8, left_eye_pos[1] + 1.4, right_eye_pos2[0], nose_center[1] + 0.04);
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.nose_value = map(settings[0], 0, 100, 1, 1.5);
this.lash_brow_value=int(map(settings[1], 0, 100, 0, 1));
this.eye_size = map(settings[2], 0, 100, 0.6, 1);
this.ear_color=int(map(settings[3], 0, 100, 0, 1));
this.skin_color=int(map(settings[4], 0, 100, 0, 2));
this.eye_color=int(map(settings[5], 0, 100, 0, 2));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(6);
settings[0] = map(this.nose_value, 1, 1.5, 0, 100);
settings[1] = int(map(this.lash_brow_value, 0, 1, 0, 100));
settings[2] = map(this.eye_size, 0.6, 1, 0, 100);
settings[3] = int(map(this.ear_color, 0, 1, 0, 100));
settings[4] = int(map(this.skin_color, 0, 2, 0, 100));
settings[5] = int(map(this.eye_color, 0, 2, 0, 100));
return settings;
}
}
{
"000001": [
0,
100,
49.000000000000014,
0,
0,
0
],
"000002": [
0,
100,
100,
0,
0,
0
],
"000005": [
0,
100,
45.000000000000014,
0,
0,
0
],
"000006": [
0,
100,
0,
0,
50,
100
],
"000007": [
100,
0,
45.000000000000014,
100,
0,
50
],
"000009": [
0,
100,
45.000000000000014,
0,
0,
50
],
"000010": [
0,
100,
0,
0,
0,
0
],
"000013": [
100,
0,
0,
100,
0,
0
],
"000014": [
0,
100,
0,
0,
50,
100
],
"000015": [
100,
0,
0,
100,
0,
0
],
"000016": [
100,
0,
51.000000000000014,
100,
50,
50
],
"000018": [
0,
100,
0,
0,
0,
0
],
"000020": [
100,
0,
0,
100,
0,
50
],
"000023": [
100,
0,
47.000000000000014,
100,
0,
0
],
"000025": [
100,
0,
0,
100,
50,
50
],
"000028": [
0,
100,
0,
0,
50,
100
],
"000029": [
0,
100,
47.000000000000014,
0,
0,
0
],
"000030": [
100,
0,
100,
100,
50,
50
],
"000031": [
0,
100,
0,
0,
0,
0
],
"000032": [
100,
0,
45.000000000000014,
100,
50,
0
],
"000035": [
0,
100,
45.000000000000014,
0,
0,
50
],
"000037": [
100,
0,
45.000000000000014,
100,
50,
100
],
"000038": [
100,
0,
0,
100,
0,
0
],
"000040": [
0,
100,
46.000000000000014,
0,
0,
50
],
"000041": [
100,
0,
0,
100,
50,
50
],
"000042": [
0,
100,
50.000000000000014,
0,
0,
0
],
"000043": [
0,
100,
100,
0,
50,
50
],
"000044": [
0,
100,
52.000000000000014,
0,
100,
100
],
"000045": [
0,
100,
0,
0,
50,
100
],
"000047": [
0,
100,
0,
0,
50,
100
],
"000048": [
100,
0,
51.000000000000014,
100,
50,
50
],
"000050": [
100,
0,
51.000000000000014,
100,
0,
50
],
"000051": [
100,
0,
51.000000000000014,
100,
0,
50
],
"000052": [
100,
0,
88.99999999999999,
100,
50,
0
],
"000054": [
0,
100,
50.000000000000014,
0,
0,
0
],
"000055": [
100,
0,
50.000000000000014,
100,
0,
50
],
"000056": [
100,
0,
0,
100,
0,
0
],
"000058": [
0,
100,
52.000000000000014,
0,
0,
0
],
"000060": [
100,
0,
0,
100,
100,
100
],
"000064": [
100,
0,
0,
100,
0,
0
],
"000065": [
100,
0,
0,
100,
50,
100
],
"000068": [
100,
0,
47.000000000000014,
100,
0,
50
],
"000069": [
100,
0,
92,
100,
0,
50
],
"000071": [
0,
100,
100,
0,
0,
0
],
"000073": [
0,
100,
100,
0,
50,
50
],
"000076": [
100,
0,
48.000000000000014,
100,
50,
50
],
"000077": [
0,
100,
48.000000000000014,
0,
50,
100
],
"000078": [
0,
100,
48.000000000000014,
0,
50,
50
],
"000079": [
100,
0,
48.000000000000014,
100,
0,
50
],
"000080": [
100,
0,
0,
100,
0,
0
],
"000081": [
100,
0,
49.000000000000014,
100,
50,
50
],
"000083": [
0,
100,
0,
0,
0,
0
],
"000085": [
0,
100,
100,
0,
0,
0
],
"000086": [
0,
100,
53.000000000000014,
0,
0,
50
],
"000088": [
0,
100,
54.000000000000014,
0,
50,
50
],
"000091": [
100,
0,
0,
100,
0,
0
],
"000092": [
0,
100,
0,
0,
0,
0
],
"000096": [
0,
100,
79.00000000000001,
0,
50,
100
],
"000097": [
0,
100,
66,
0,
0,
0
],
"000099": [
0,
100,
0,
0,
0,
0
],
"000100": [
0,
100,
49.000000000000014,
0,
0,
50
],
"000103": [
0,
100,
89.99999999999999,
0,
0,
50
],
"000104": [
100,
0,
0,
100,
0,
0
],
"000106": [
0,
100,
0,
0,
0,
50
],
"000108": [
0,
100,
52.000000000000014,
0,
0,
0
],
"000109": [
100,
0,
52.000000000000014,
100,
50,
0
],
"000110": [
0,
100,
52.000000000000014,
0,
0,
0
],
"000111": [
0,
100,
0,
0,
100,
100
],
"000114": [
100,
0,
48.000000000000014,
100,
0,
50
],
"000115": [
100,
0,
0,
100,
0,
0
],
"000116": [
100,
0,
0,
100,
0,
50
],
"000117": [
0,
100,
84.99999999999999,
0,
100,
100
],
"000118": [
0,
100,
51.000000000000014,
0,
50,
50
],
"000121": [
0,
100,
51.000000000000014,
0,
0,
50
],
"000122": [
0,
100,
51.000000000000014,
0,
0,
0
],
"000125": [
100,
0,
0,
100,
0,
0
],
"000126": [
0,
100,
53.000000000000014,
0,
0,
0
],
"000129": [
100,
0,
0,
100,
0,
0
],
"000131": [
0,
100,
51.000000000000014,
0,
0,
50
],
"000132": [
0,
100,
0,
0,
50,
100
],
"000133": [
0,
100,
52.000000000000014,
0,
0,
0
],
"000134": [
100,
0,
52.000000000000014,
100,
100,
100
],
"000135": [
100,
0,
52.000000000000014,
100,
50,
100
],
"000137": [
100,
0,
0,
100,
0,
0
],
"000140": [
0,
100,
100,
0,
0,
0
],
"000142": [
0,
100,
0,
0,
0,
0
],
"000143": [
100,
0,
53.000000000000014,
100,
0,
0
],
"000145": [
0,
100,
0,
0,
50,
50
],
"000146": [
0,
100,
50.000000000000014,
0,
50,
50
],
"000147": [
0,
100,
50.000000000000014,
0,
0,
0
],
"000148": [
0,
100,
0,
0,
0,
0
],
"000150": [
100,
0,
45.000000000000014,
100,
0,
0
],
"000151": [
0,
100,
0,
0,
50,
100
],
"000152": [
100,
0,
0,
100,
0,
0
],
"000153": [
100,
0,
49.000000000000014,
100,
0,
50
],
"000155": [
0,
100,
45.000000000000014,
0,
50,
100
],
"000156": [
0,
100,
0,
0,
0,
0
],
"000157": [
0,
100,
0,
0,
0,
0
],
"000160": [
100,
0,
48.000000000000014,
100,
0,
50
],
"000161": [
0,
100,
0,
0,
0,
0
]
}
function obrien_draw_one_frame(cur_frac) {
// Define colors
let b1 = color(8,10,22);
let b2 = color(126,150,254);
//Variables
var w = width;
var h = height;
var starSizeBig = height/80;
var starSizeMed = height/80;
var starSizeSmall = height/150;
var headSize = height/2.5;
var moonSize = height/7;
var moonSizeF = height/7;
var earSize = height/10;
// note: to clear the screen draw a rectangle
// that is width x height - like this
noStroke();
fill(10);
rect(0, 0, width, height);
// note: all shape sizes, line widths, etc. should be a
// function of width and height
let rect_width = height / 10.0;
let half_width = rect_width / 2;
// note: animation should progress depending on the
// value of cur_frac which goes from 0 to 1, and it
// should loop seamlessly
let cur_x = map(cur_frac, 0, 1, 0, width) - half_width;
setGradient(0, 0, width, height, b1, b2, 1);
stars(w,h,starSizeBig,starSizeMed,starSizeSmall,cur_frac);
drawMoons(w,h,moonSize);
drawCharacter(w,h,cur_frac,headSize,earSize,moonSizeF);
drawHair(w,h,cur_frac);
}
function setGradient(x, y, w, h, c1, c2) {
noFill();
// Top to bottom gradient
for (let i = y; i <= y + h; i++) {
let inter = map(i, y, y + h, 0, 1);
let c = lerpColor(c1, c2, inter);
stroke(c);
line(x, i, x + w, i);
}
}
function stars(w,h,starSizeBig,starSizeMed,starSizeSmall,cur_frac){
let cur_twinkle;
let cur_twinkleMed;
if(cur_frac < 0.5){
cur_twinkle = map(cur_frac, 0, 0.5, 50, 180);
cur_twinkleMed = map(cur_frac, 0, 0.5, 255, 100);
}
else{
cur_twinkle = map(cur_frac, 0.5, 1, 180, 50);
cur_twinkleMed = map(cur_frac, 0.5, 1, 100, 255);
}
noStroke();
fill(255, cur_twinkle);
//Small Stars
ellipse(w/2,h/2,starSizeSmall);
ellipse(w/3,h/3,starSizeSmall);
ellipse(w/2,h/4,starSizeSmall);
ellipse(w/4,h/5,starSizeSmall);
ellipse(w/5,h/1.5,starSizeSmall);
ellipse(w/1.3,h/1.3,starSizeSmall);
ellipse(w/1.1,h/5,starSizeSmall);
ellipse(w/1.3,h/3,starSizeSmall);
ellipse(w/4,h/2,starSizeSmall);
ellipse(w/8,h/8,starSizeSmall);
ellipse(w/10,h/3,starSizeSmall);
ellipse(w/1.6,h/1.2,starSizeSmall);
ellipse(w/40,h/2,starSizeSmall);
ellipse(w/43,h/20,starSizeSmall);
ellipse(w/35,h/1.1,starSizeSmall);
ellipse(w/20,h/1.5,starSizeSmall);
ellipse(w/7,h/1.2,starSizeSmall);
ellipse(w/1.05,h/2,starSizeSmall);
ellipse(w/1.01,h/40,starSizeSmall);
ellipse(w/4,h/40,starSizeSmall);
ellipse(w/1.5,h/10,starSizeSmall);
ellipse(w/2.2,h/20,starSizeSmall);
ellipse(w/1.2,h/10,starSizeSmall);
ellipse(w/1.2,h/1.5,starSizeSmall);
ellipse(w/1.1,h/1.1,starSizeSmall);
ellipse(w/1.05,h/1.2,starSizeSmall);
ellipse(w/3,h/1.5,starSizeSmall);
ellipse(w/1.5,h/1.5,starSizeSmall);
ellipse(w/1.5,h/2.5,starSizeSmall);
ellipse(w/1.3,h/1.8,starSizeSmall);
//Medium Stars
fill(255, cur_twinkleMed);
ellipse(w/1.35,h/1.5,starSizeMed);
ellipse(w/1.5,h/2.1,starSizeMed);
ellipse(w/1.25,h/2.25,starSizeMed);
ellipse(w/1.35,h/4.5,starSizeMed);
ellipse(w/40,h/4.5,starSizeMed);
ellipse(w/30,h/1.8,starSizeMed);
ellipse(w/8,h/2.3,starSizeMed);
ellipse(w/9,h/1.5,starSizeMed);
ellipse(w/15,h/1.2,starSizeMed);
ellipse(w/9,h/2,starSizeMed);
ellipse(w/3,h/40,starSizeMed);
ellipse(w/1.8,h/35,starSizeMed);
ellipse(w/3.2,h/5,starSizeMed);
ellipse(w/1.18,h/2.7,starSizeMed);
}
function drawCharacter(w,h,cur_frac,headSize,earSize,moonSizeF){
//back hair
push();
stroke(91,94,172);
strokeWeight(w/10);
line(w/1.83,h/3.4,w/1,h/0.8);
line(w/2.2,h/3.4,w/100,h/0.8);
noStroke();
fill(91,94,172);
rect(w/5.9,h/1.3,w/1.5,h/4);
rect(w/3.5,h/1.8,w/2.4,h/4);
let move;
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 8.5, 10);
}else{
move = map(cur_frac, 0.5, 1, 10, 8.5);
}
ellipse(w/move,h/1,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 5.5, 6.5);
}else{
move = map(cur_frac, 0.5, 1, 6.5, 5.5);
}
ellipse(w/move,h/1.1,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 5.5, 5);
}else{
move = map(cur_frac, 0.5, 1, 5, 5.5);
}
ellipse(w/move,h/1.25,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 3.8, 4.2);
}else{
move = map(cur_frac, 0.5, 1, 4.2, 3.8);
}
ellipse(w/move,h/1.4,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 3.5, 4);
}else{
move = map(cur_frac, 0.5, 1, 4, 3.5);
}
ellipse(w/move,h/1.6,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 2.8, 3);
}else{
move = map(cur_frac, 0.5, 1, 3, 2.8);
}
ellipse(w/move,h/1.8,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 2.5, 2.6);
}else{
move = map(cur_frac, 0.5, 1, 2.6, 2.5);
}
ellipse(w/move,h/2.2,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 2.35, 2.4);
}else{
move = map(cur_frac, 0.5, 1, 2.4, 2.35);
}
ellipse(w/move,h/2.6,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 2.15, 2.2);
}else{
move = map(cur_frac, 0.5, 1, 2.2, 2.15);
}
ellipse(w/move,h/3,w/6,h/6);
translate(w/0.99,0);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 8.5, 10);
}else{
move = map(cur_frac, 0.5, 1, 10, 8.5);
}
ellipse(w/-move,h/1,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 5.5, 6.5);
}else{
move = map(cur_frac, 0.5, 1, 6.5, 5.5);
}
ellipse(w/-move,h/1.1,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 5.5, 5);
}else{
move = map(cur_frac, 0.5, 1, 5, 5.5);
}
ellipse(w/-move,h/1.25,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 3.8, 4.2);
}else{
move = map(cur_frac, 0.5, 1, 4.2, 3.8);
}
ellipse(w/-move,h/1.4,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 3.5, 4);
}else{
move = map(cur_frac, 0.5, 1, 4, 3.5);
}
ellipse(w/-move,h/1.6,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 2.8, 3);
}else{
move = map(cur_frac, 0.5, 1, 3, 2.8);
}
ellipse(w/-move,h/1.8,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 2.5, 2.6);
}else{
move = map(cur_frac, 0.5, 1, 2.6, 2.5);
}
ellipse(w/-move,h/2.2,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 2.35, 2.4);
}else{
move = map(cur_frac, 0.5, 1, 2.4, 2.35);
}
ellipse(w/-move,h/2.6,w/6,h/6);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 2.15, 2.2);
}else{
move = map(cur_frac, 0.5, 1, 2.2, 2.15);
}
ellipse(w/-move,h/3,w/6,h/6);
pop();
//neck
noFill();
stroke(176,189,230);
strokeWeight(w/20);
push();
angleMode(DEGREES);
translate(w/2.1,h/1.62);
scale(0.8);
rotate(90);
bezier(0,0,w/4.8,0,w/4.8,h/10.8,w/4.57,h/2.16);
pop();
push();
angleMode(DEGREES);
translate(w/1.9,h/1.62);
rotate(90);
scale(0.8);
bezier(0,0,w/4.8,0,w/4.8,h/-10.8,w/4.57,h/-2.16);
pop();
push();
noStroke();
fill(176,189,230);
rect(w/2.1,h/1.5,w/20,h/2);
translate(0,h/40);
if(h > 1080){
ellipse(w/3.65,h/1.035,w/12,h/6);
}else{
ellipse(w/3.65,h/1.035,w/12,h/5.1);
}
translate(0,(-h/40));
translate(w/2.21,h/40);
if(h > 1080){
ellipse(w/3.65,h/1.035,w/12,h/6);
}else{
ellipse(w/3.65,h/1.035,w/12,h/5.1);
}
translate(-w/2.21,-h/40);
rect(w/3.3,h/1.08,w/2.6,h/10);
rect(w/2.35,h/1.15,w/6.5,h/10);
rect(w/2.2,h/1.2,w/10,h/10);
pop();
push();
angleMode(DEGREES);
//head
translate(0,h/15);
fill(196,206,236);
noStroke();
ellipse(w/2,h/3,headSize);
bezier((w/2)-(0.5*headSize),(h/8)+(0.5*headSize),w/2.5,h/1.35,w/1.68,h/1.35,(w/2)+(0.5*headSize),(h/8)+(0.5*headSize));
//ears
rotate(-25);
translate(w/-15,h/4.5);
ellipse(w/3.15,h/2,earSize,earSize*1.3);
rotate(25);
translate(-w/-15,-h/5.5);
ellipse(w/1.87,h/2.6,earSize,earSize*1.3);
pop();
angleMode(RADIANS);
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 0.01, 0);
}else{
move = map(cur_frac, 0.5, 1, 0, 0.01);
}
push();
translate(0,h/-70);
//eyes
noStroke();
fill(0);
ellipse(w/2.2,h/(2+move),earSize*1.2,earSize);
fill(196,206,236);
ellipse(w/2.2,h/(2.03+move),earSize*1.6,earSize);
push();
translate(w/11,0);
fill(0);
ellipse(w/2.2,h/(2+move),earSize*1.2,earSize);
fill(196,206,236);
ellipse(w/2.2,h/(2.03+move),earSize*1.6,earSize);
pop();
pop();
//eyebrows
stroke(91,94,172);
strokeWeight(w/55);
line(w/2.3,h/(2.25+move),w/2.2,h/(2.23+move));
line(w/1.85,h/(2.23+move),w/1.78,h/(2.25+move));
//nose
push();
stroke(169,183,223);
strokeWeight(w/200);
translate(w/23,h/7);
line(w/2.25,h/(2.25+move),w/2.2,h/(2.23+move));
translate(w/-12,0);
line(w/1.85,h/(2.23+move),w/1.8,h/(2.25+move));
pop();
push();
//mouth
fill(110,112,188);
noStroke();
ellipse(w/1.99,h/(1.55+move),moonSizeF/2.3,moonSizeF/3.3);
stroke(92,94,177);
strokeWeight(w/300);
noFill();
translate(w/2.1,h/(1.58+move));
bezier(0,0,w/96,h/54,w/24,h/54,w/19.2,0);
pop();
push();
//Forehead moon
scale(0.65);
translate(w/3.75,h/3.5);
fill(91,94,172);
noStroke();
ellipse(w/2,h/3,moonSizeF);
fill(196,206,236);
ellipse(w/2,h/3.2,moonSizeF/1.2);
pop();
}
function drawHair(w,h,cur_frac){
push();
noFill();
stroke(110,112,188);
strokeWeight(w/100);
translate(w/1.99,h/3.7);
beginShape();
translate(0,h/12.5);
bezier(w/9.5,0,w/13.71,-h/27,w/24,-h/27,0,0);
bezier(-w/9,0,-w/13.71,-h/27,-w/24,-h/27,0,0);
bezier(-w/9,0,-w/9,-h/4.9,w/9.5,-h/4.9,w/9.5,0);
endShape();
pop();
push();
noStroke();
fill(110,112,188);
rect(w/2.3,h/4.3,w/7,h/12);
rect(w/2.1,h/3.32,w/20,h/25);
rect(w/2.17,h/3.45,w/12,h/25);
rect(w/2.54,h/3.43,w/4.7,h/25);
rect(w/2.473,h/3.9,w/5.265,h/20);
rect(w/2.42,h/4.15,w/5.8,h/20);
rect(w/2.35,h/4.5,w/7,h/20);
rect(w/2.22,h/4.9,w/10,h/20);
pop();
//hair waves
fill(110,112,188);
translate(0,h/-20);
noStroke();
let move;
if(cur_frac < 0.5){
move = map(cur_frac, 0, 0.5, 0, 0.05);
}else{
move = map(cur_frac, 0.5, 1, 0.05, 0);
}
ellipse(w/(2.7+(move*2)),h/1,w/15,h/7);
ellipse(w/(2.4+(move*1.9)),h/0.96,w/15,h/7);
ellipse(w/(2.5+(move*1.8)),h/1.09,w/10,h/7);
ellipse(w/(2.6+(move*1.7)),h/1.22,w/15,h/7);
ellipse(w/(2.6+(move*1.6)),h/1.35,w/12,h/7);
ellipse(w/(2.6+(move*1.5)),h/1.5,w/15,h/7);
ellipse(w/(2.35+(move*1.4)),h/1.2,w/15,h/7);
ellipse(w/(2.4+(move*1.3)),h/1.4,w/15,h/7);
ellipse(w/(2.45+(move*1.2)),h/1.6,w/20,h/10);
ellipse(w/(2.6+(move*1.1)),h/1.7,w/20,h/10);
ellipse(w/(2.45+move),h/1.75,w/20,h/15);
ellipse(w/(2.6+move),h/1.95,w/20,h/10);
ellipse(w/(2.6+move),h/2.1,w/30,h/15);
ellipse(w/(2.45+move),h/1.9,w/30,h/15);
ellipse(w/(2.45+move),h/2.1,w/38,h/15);
ellipse(w/(2.55+(move/4)),h/2.3,w/30,h/15);
ellipse(w/2.52,h/2.5,w/30,h/15);
push();
translate(w/0.99,0);
ellipse(w/(-2.7+(move*2)),h/1,w/15,h/7);
ellipse(w/(-2.4+(move*1.9)),h/0.96,w/15,h/7);
ellipse(w/(-2.5+(move*1.8)),h/1.09,w/10,h/7);
ellipse(w/(-2.6+(move*1.7)),h/1.22,w/15,h/7);
ellipse(w/(-2.6+(move*1.6)),h/1.35,w/12,h/7);
ellipse(w/(-2.6+(move*1.5)),h/1.5,w/15,h/7);
ellipse(w/(-2.35+(move*1.4)),h/1.2,w/15,h/7);
ellipse(w/(-2.4+(move*1.3)),h/1.4,w/15,h/7);
ellipse(w/(-2.45+(move*1.2)),h/1.6,w/20,h/10);
ellipse(w/(-2.6+(move*1.1)),h/1.7,w/20,h/10);
ellipse(w/(-2.45+move),h/1.75,w/20,h/15);
ellipse(w/(-2.6+move),h/1.95,w/20,h/10);
ellipse(w/(-2.6+move),h/2.1,w/30,h/15);
ellipse(w/(-2.45+move),h/1.9,w/30,h/15);
ellipse(w/(-2.45+move),h/2.1,w/38,h/15);
ellipse(w/(-2.55+(move/4)),h/2.3,w/30,h/15);
ellipse(w/-2.52,h/2.5,w/30,h/15);
pop();
stroke(196,206,236);
strokeWeight(w/500);
line(w/1.99,h/4.15,w/1.99,h/2.3);
}
function drawMoons(w,h,moonSize){
noFill();
stroke(255);
strokeWeight(h/220);
//end moons
ellipse(w/15,h/7,moonSize);
ellipse(w/1.075,h/7,moonSize);
//cresent
//left
fill(255);
push();
beginShape();
translate(w/12.5, h/45);
vertex(w/20.16, h/20);
bezierVertex(w/7.56, h/31.5, w/7.56, h/5, w/20.16, h/5);
bezierVertex(w/12.096, h/6.8, w/12.6, h/10, w/20.16, h/20);
endShape();
//right
beginShape();
translate(w/1.19, h/1200);
vertex(-w/20.16, h/20);
bezierVertex(-w/7.56, h/31.5, -w/7.56, h/5, -w/20.16, h/5);
bezierVertex(-w/12.096, h/6.8, -w/12.6, h/10, -w/20.16, h/20);
endShape();
pop();
//half moon
push();
rotate(-1.57);
translate(-w/7.6,h/3.4);
arc(w/19.2, h/10.8, w/12, h/6.75, 0, PI, CHORD);
pop();
//half moon
push();
rotate(1.57);
if(h > 1080){ //not sure why this does not work without the if
translate(w/36,-h/0.645);
}else{
translate(w/36,-h/0.6725);
}
arc(w/19.2, h/10.8, w/12.5, h/6.75, 0, PI, CHORD);
pop();
//nearly full
ellipse(w/3.15,h/7,moonSize/1.2,moonSize);
ellipse(w/1.47,h/7,moonSize/1.2,moonSize);
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// remove this or set to false to enable full program (load will be slower)
var DEBUG_MODE = false;
// this can be used to set the number of sliders to show
var NUM_SLIDERS = 5;
// other variables can be in here too
// here's some examples for colors used
// const bg_color = [225, 206, 187];
// const fg_color = [60];
// const stroke_color = [95, 52, 8];
const spikeRan = 11;
// example of a global function
// given a segment, this returns the average point [x, y]
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i=0; i<s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len , sum_y / s_len ];
}
// This where you define your own face object
function OBrienFace() {
// these are state variables for a face
// (your variables should be different!)
this.num_eyes = 2; // can be either 1 (cyclops) or 2 (two eyes)
this.eye_shift = -1; // range is -10 to 10
this.mouth_value = 1; // range is 0.5 to 8
this.face_shape = 1;
this.hair_length = 1;
this.emotion = 1;
this.hair_colour = 1;
// example of a function *inside* the face object.
// this draws a segment, and do_loop will connect the ends if true
this.draw_segment = function(segment, do_loop) {
for(let i=0; i<segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
ellipse(px, py, 0.1);
if(i < segment.length - 1) {
let nx = segment[i+1][0];
let ny = segment[i+1][1];
line(px, py, nx, ny);
}
else if(do_loop) {
let nx = segment[0][0];
let ny = segment[0][1];
line(px, py, nx, ny);
}
}
};
/*
* Draw the face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
angleMode(DEGREES);
// head
let jaw_dist = positions.chin[16][0] - positions.chin[0][0];
let faceWidth = map(jaw_dist, 3, 4.2, 3.75, 4.5);
noStroke();
//body colour (hair colour)
if(this.hair_colour == 1){
//black hair
fill(15);
}
else if(this.hair_colour == 2){
//grey
fill(80);
}
else if(this.hair_colour == 3){
//brunette light
fill(120, 103, 96);
}
else if(this.hair_colour == 4){
//brunette dark
fill(66, 60, 57);
}
else if(this.hair_colour == 5){
//blonde
fill(224, 205, 164);
}
else if(this.hair_colour == 6){
//red orange
fill(199, 119, 66);
}
else if(this.hair_colour == 7){
//red
fill(204, 73, 73);
}
//spikes
push();
scale(0.25);
translate(0,0.2);
if(this.hair_colour == 1){
//black hair
stroke(15);
}
else if(this.hair_colour == 2){
//grey
stroke(80);
}
else if(this.hair_colour == 3){
//brunette light
stroke(120, 103, 96);
}
else if(this.hair_colour == 4){
//brunette dark
stroke(66, 60, 57);
}
else if(this.hair_colour == 5){
//blonde
stroke(224, 205, 164);
}
else if(this.hair_colour == 6){
//red orange
stroke(199, 119, 66);
}
else if(this.hair_colour == 7){
//red
stroke(204, 73, 73);
}
strokeWeight(0.5);
line(0,-this.hair_length,0,0); //12 //11.5
line(0,this.hair_length,0,0); //6
line(0,0,this.hair_length,0); //3
line(0,0,-this.hair_length,0); //3
rotate(15);
line(0,-this.hair_length,0,0); //12
line(0,this.hair_length,0,0); //6
line(0,0,this.hair_length,0); //3
line(0,0,-this.hair_length,0); //3
rotate(-15);
rotate(30);
line(0,-this.hair_length,0,0); //12
line(0,this.hair_length,0,0); //6
line(0,0,this.hair_length,0); //3
line(0,0,-this.hair_length,0); //3
rotate(-30);
rotate(45);
line(0,-this.hair_length,0,0); //12
line(0,this.hair_length,0,0); //6
line(0,0,this.hair_length,0); //3
line(0,0,-this.hair_length,0); //3
rotate(-45);
rotate(60);
line(0,-this.hair_length,0,0); //12
line(0,this.hair_length,0,0); //6
line(0,0,this.hair_length,0); //3
line(0,0,-this.hair_length,0); //3
rotate(-60);
rotate(75);
line(0,-this.hair_length,0,0); //12
line(0,this.hair_length,0,0); //6
line(0,0,this.hair_length,0); //3
line(0,0,-this.hair_length,0); //3
rotate(-75);
pop();
//face shape
if(this.face_shape == 1){
ellipse(0, 0, faceWidth, 4.5);
}else if(this.face_shape == 2){
rect(0-(faceWidth/2), -2, faceWidth, faceWidth,1);
}else if(this.face_shape == 3){
ellipse(0, 0, faceWidth/1.15, 4.5);
}
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye);
//--------------------------------[Eyes]--------------------------------
noStroke();
let curEyeShift = 0.04 * this.eye_shift;
if(this.emotion == 1) {
// normal
noStroke();
push();
scale(0.221);
fill(255);
ellipse(left_eye_pos[0]-3, left_eye_pos[1], 6.5, 8);
ellipse(right_eye_pos[0]+3, right_eye_pos[1], 6.5, 8);
push();
fill(0);
ellipse(left_eye_pos[0]-3,left_eye_pos[1], 2, 2);
ellipse(right_eye_pos[0]+3,right_eye_pos[1], 2, 2);
pop();
pop();
}
else if(this.emotion == 2) {
//side eye left
noStroke();
push();
scale(0.221);
fill(255);
ellipse(left_eye_pos[0]-3, left_eye_pos[1], 6.5, 8);
ellipse(right_eye_pos[0]+3, right_eye_pos[1], 6.5, 8);
push();
fill(0);
ellipse(left_eye_pos[0]-5,left_eye_pos[1], 2, 2);
ellipse(right_eye_pos[0]+1,right_eye_pos[1], 2, 2);
pop();
pop();
}
else if(this.emotion == 3){
//side eye right
noStroke();
push();
scale(0.221);
fill(255);
ellipse(left_eye_pos[0]-3, left_eye_pos[1], 6.5, 8);
ellipse(right_eye_pos[0]+3, right_eye_pos[1], 6.5, 8);
push();
fill(0);
ellipse(left_eye_pos[0]-1,left_eye_pos[1], 2, 2);
ellipse(right_eye_pos[0]+5,right_eye_pos[1], 2, 2);
pop();
pop();
}
else if(this.emotion == 4){
//happy
push();
scale(0.221);
noStroke();
fill(255);
ellipse(-3+left_eye_pos[0],left_eye_pos[1], 6.5, 8);
ellipse(3+right_eye_pos[0],right_eye_pos[1], 6.5, 8);
stroke(0);
strokeWeight(0.7);
noFill();
//right
bezier(4+right_eye_pos[0]+1,0+right_eye_pos[1],4+right_eye_pos[0]+1,-3+right_eye_pos[1],0+right_eye_pos[0]+1,-3+right_eye_pos[1],0+right_eye_pos[0]+1,0+right_eye_pos[1]);
//left
bezier(4+left_eye_pos[0]-5,0+left_eye_pos[1],4+left_eye_pos[0]-5,-3+left_eye_pos[1],0+left_eye_pos[0]-5,-3+left_eye_pos[1],0+left_eye_pos[0]-5,0+left_eye_pos[1]);
push();
//body colour (hair colour)
if(this.hair_colour == 1){
//black hair
fill(15);
}
else if(this.hair_colour == 2){
//grey
fill(80);
}
else if(this.hair_colour == 3){
//brunette light
fill(120, 103, 96);
}
else if(this.hair_colour == 4){
//brunette dark
fill(66, 60, 57);
}
else if(this.hair_colour == 5){
//blonde
fill(224, 205, 164);
}
else if(this.hair_colour == 6){
//red orange
fill(199, 119, 66);
}
else if(this.hair_colour == 7){
//red
fill(204, 73, 73);
}
noStroke();
scale(2);
//right
translate(-1.5,3);
bezier(4+right_eye_pos[0]-3,0+right_eye_pos[1],4+right_eye_pos[0]-3,-3+right_eye_pos[1],0+right_eye_pos[0]-3,-3+right_eye_pos[1],0+right_eye_pos[0]-3,0+right_eye_pos[1]);
translate(5,0);
//body colour (hair colour)
if(this.hair_colour == 1){
//black hair
fill(15);
}
else if(this.hair_colour == 2){
//grey
fill(80);
}
else if(this.hair_colour == 3){
//brunette light
fill(120, 103, 96);
}
else if(this.hair_colour == 4){
//brunette dark
fill(66, 60, 57);
}
else if(this.hair_colour == 5){
//blonde
fill(224, 205, 164);
}
else if(this.hair_colour == 6){
//red orange
fill(199, 119, 66);
}
else if(this.hair_colour == 7){
//red
fill(204, 73, 73);
}
bezier(4+left_eye_pos[0]-3,0+left_eye_pos[1],4+left_eye_pos[0]-3,-3+left_eye_pos[1],0+left_eye_pos[0]-3,-3+left_eye_pos[1],0+left_eye_pos[0]-3,0+left_eye_pos[1]);
pop();
pop();
}
else if(this.emotion == 5){
push();
//sad
//left
push();
scale(0.221);
translate(-2,3.8);
beginShape();
fill(255);
bezier(2.5+left_eye_pos[0],-7+left_eye_pos[1],1+left_eye_pos[0],0.5+left_eye_pos[1],0+left_eye_pos[0],2+left_eye_pos[1],-4+left_eye_pos[0],-5+left_eye_pos[1]); //big
//body colour (hair colour)
if(this.hair_colour == 1){
//black hair
fill(15);
}
else if(this.hair_colour == 2){
//grey
fill(80);
}
else if(this.hair_colour == 3){
//brunette light
fill(120, 103, 96);
}
else if(this.hair_colour == 4){
//brunette dark
fill(66, 60, 57);
}
else if(this.hair_colour == 5){
//blonde
fill(224, 205, 164);
}
else if(this.hair_colour == 6){
//red orange
fill(199, 119, 66);
}
else if(this.hair_colour == 7){
//red
fill(204, 73, 73);
}
bezier(3+left_eye_pos[0],-7.5+left_eye_pos[1],1+left_eye_pos[0],-2.5+left_eye_pos[1],-4+left_eye_pos[0],-2.5+left_eye_pos[1],-5+left_eye_pos[0],-5.5+left_eye_pos[1]); //small
endShape()
beginShape();
translate(4.2,0)
fill(255);
bezier(-2.5+right_eye_pos[0],-7+right_eye_pos[1],-1+right_eye_pos[0],0.5+right_eye_pos[1],0+right_eye_pos[0],2+right_eye_pos[1],4+right_eye_pos[0],-5+right_eye_pos[1]); //big
//body colour (hair colour)
if(this.hair_colour == 1){
//black hair
fill(15);
}
else if(this.hair_colour == 2){
//grey
fill(80);
}
else if(this.hair_colour == 3){
//brunette light
fill(120, 103, 96);
}
else if(this.hair_colour == 4){
//brunette dark
fill(66, 60, 57);
}
else if(this.hair_colour == 5){
//blonde
fill(224, 205, 164);
}
else if(this.hair_colour == 6){
//red orange
fill(199, 119, 66);
}
else if(this.hair_colour == 7){
//red
fill(204, 73, 73);
}
bezier(-3+right_eye_pos[0],-7.5+right_eye_pos[1],-1+right_eye_pos[0],-2.5+right_eye_pos[1],4+right_eye_pos[0],-2.5+right_eye_pos[1],5+right_eye_pos[0],-5.5+right_eye_pos[1]); //small
endShape();
pop();
//pupils
scale(0.221);
fill(0);
noStroke();
ellipse( 4+left_eye_pos[0], 2.5+left_eye_pos[1], 1.5, 1.5);
ellipse(-3.8+right_eye_pos[0], 2.2+right_eye_pos[1], 1.5, 1.5);
pop();
}
else if(this.emotion == 6){
push();
//angry
//left
push();
scale(0.221);
translate(-3,3.8);
beginShape();
fill(255);
bezier(-2.5+left_eye_pos[0],-7+left_eye_pos[1],-1+left_eye_pos[0],0.5+left_eye_pos[1],0+left_eye_pos[0],2+left_eye_pos[1],4+left_eye_pos[0],-5+left_eye_pos[1]); //big
//body colour (hair colour)
if(this.hair_colour == 1){
//black hair
fill(15);
}
else if(this.hair_colour == 2){
//grey
fill(80);
}
else if(this.hair_colour == 3){
//brunette light
fill(120, 103, 96);
}
else if(this.hair_colour == 4){
//brunette dark
fill(66, 60, 57);
}
else if(this.hair_colour == 5){
//blonde
fill(224, 205, 164);
}
else if(this.hair_colour == 6){
//red orange
fill(199, 119, 66);
}
else if(this.hair_colour == 7){
//red
fill(204, 73, 73);
}
bezier(-3+left_eye_pos[0],-7.5+left_eye_pos[1],-1+left_eye_pos[0],-2.5+left_eye_pos[1],4+left_eye_pos[0],-2.5+left_eye_pos[1],5+left_eye_pos[0],-5.5+left_eye_pos[1]); //small
endShape()
beginShape();
translate(6.5,0)
fill(255);
bezier(2.5+right_eye_pos[0],-7+right_eye_pos[1],1+right_eye_pos[0],0.5+right_eye_pos[1],0+right_eye_pos[0],2+right_eye_pos[1],-4+right_eye_pos[0],-5+right_eye_pos[1]); //big
//body colour (hair colour)
if(this.hair_colour == 1){
//black hair
fill(15);
}
else if(this.hair_colour == 2){
//grey
fill(80);
}
else if(this.hair_colour == 3){
//brunette light
fill(120, 103, 96);
}
else if(this.hair_colour == 4){
//brunette dark
fill(66, 60, 57);
}
else if(this.hair_colour == 5){
//blonde
fill(224, 205, 164);
}
else if(this.hair_colour == 6){
//red orange
fill(199, 119, 66);
}
else if(this.hair_colour == 7){
//red
fill(204, 73, 73);
}
bezier(3+right_eye_pos[0],-7.5+right_eye_pos[1],1+right_eye_pos[0],-2.5+right_eye_pos[1],-4+right_eye_pos[0],-2.5+right_eye_pos[1],-5+right_eye_pos[0],-5.5+right_eye_pos[1]); //small
endShape();
pop();
//pupils
scale(0.221);
fill(0);
noStroke();
translate(0,2.5);
ellipse(-2.8+left_eye_pos[0], left_eye_pos[1], 1.5, 1.5);
ellipse(3.2+right_eye_pos[0], right_eye_pos[1], 1.5, 1.5);
pop();
}
if(this.blushes == 1){
push();
scale(0.4,0.35);
fill(255,184,184);
ellipse(left_eye_pos[0]-2,left_eye_pos[1]+3.5,2,1.5);
ellipse(right_eye_pos[0]+2,right_eye_pos[1]+3.5,2,1.5);
pop();
}else{
}
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.face_shape = int(map(settings[0], 0, 100, 1, 3));
this.hair_length = map(settings[1], 0, 100, 5, 15);
this.emotion = int(map(settings[2], 0, 100, 1, 6));
this.hair_colour = int(map(settings[3], 0, 100, 1, 7));
this.blushes = int(map(settings[4], 0, 100, 1, 2));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(5);
settings[0] = map(this.face_shape, 1, 3, 0, 100);
settings[1] = map(this.hair_length, 5, 15, 0, 100);
settings[2] = map(this.emotion, 1, 6, 0, 100);
settings[3] = map(this.hair_colour,1, 7, 0, 100);
settings[4] = map(this.blushes, 1, 2, 0, 100);
return settings;
}
}
{
"000001": [
100,
89,
60,
66.66666666666666,
0
],
"000002": [
100,
100,
60,
100,
0
],
"000005": [
100,
61,
0,
66.66666666666666,
0
],
"000006": [
100,
100,
40,
66.66666666666666,
0
],
"000007": [
0,
53,
100,
0,
100
],
"000009": [
0,
100,
60,
66.66666666666666,
0
],
"000010": [
0,
100,
0,
66.66666666666666,
0
],
"000013": [
0,
51,
0,
66.66666666666666,
100
],
"000014": [
100,
53,
0,
0,
0
],
"000015": [
50,
58.999999999999986,
20,
33.33333333333333,
100
],
"000016": [
50,
58.999999999999986,
40,
50,
100
],
"000018": [
0,
100,
60,
66.66666666666666,
0
],
"000020": [
0,
100,
40,
33.33333333333333,
100
],
"000023": [
50,
56.000000000000014,
40,
50,
100
],
"000025": [
0,
56.000000000000014,
0,
33.33333333333333,
100
],
"000028": [
0,
56.000000000000014,
60,
83.33333333333334,
0
],
"000029": [
0,
100,
0,
66.66666666666666,
0
],
"000030": [
100,
51,
0,
16.666666666666664,
100
],
"000031": [
100,
56.000000000000014,
60,
50,
0
],
"000032": [
0,
49.00000000000001,
0,
16.666666666666664,
100
],
"000035": [
100,
100,
0,
0,
0
],
"000037": [
50,
0,
100,
0,
100
],
"000038": [
50,
0,
60,
50,
100
],
"000040": [
50,
82,
0,
50,
100
],
"000041": [
50,
68.99999999999999,
20,
0,
100
],
"000042": [
100,
100,
60,
66.66666666666666,
0
],
"000043": [
100,
100,
60,
50,
0
],
"000044": [
100,
100,
0,
0,
0
],
"000045": [
100,
100,
60,
83.33333333333334,
0
],
"000047": [
100,
100,
40,
0,
0
],
"000048": [
100,
53,
20,
50,
100
],
"000050": [
100,
53,
60,
50,
100
],
"000051": [
100,
30.999999999999993,
0,
16.666666666666664,
100
],
"000052": [
100,
51,
40,
33.33333333333333,
0
],
"000054": [
100,
100,
60,
66.66666666666666,
0
],
"000055": [
50,
58.00000000000001,
0,
0,
100
],
"000056": [
50,
71,
20,
0,
100
],
"000058": [
50,
100,
100,
0,
0
],
"000060": [
0,
0,
20,
0,
100
],
"000064": [
100,
51,
0,
33.33333333333333,
100
],
"000065": [
100,
51,
60,
0,
100
],
"000068": [
0,
68,
100,
16.666666666666664,
100
],
"000069": [
50,
51,
100,
0,
100
],
"000071": [
100,
100,
100,
66.66666666666666,
0
],
"000073": [
100,
100,
80,
50,
0
],
"000076": [
0,
74,
80,
0,
100
],
"000077": [
100,
74,
60,
50,
0
],
"000078": [
100,
100,
60,
50,
0
],
"000079": [
50,
0,
0,
16.666666666666664,
100
],
"000080": [
50,
60,
100,
0,
100
],
"000081": [
50,
60,
60,
0,
0
],
"000083": [
100,
100,
60,
100,
0
],
"000085": [
0,
100,
60,
100,
0
],
"000086": [
0,
55.00000000000001,
20,
100,
0
],
"000088": [
0,
100,
20,
100,
0
],
"000091": [
50,
51,
100,
0,
100
],
"000092": [
100,
81.00000000000001,
60,
66.66666666666666,
0
],
"000096": [
50,
100,
0,
50,
0
],
"000097": [
50,
100,
80,
33.33333333333333,
0
],
"000099": [
100,
100,
60,
33.33333333333333,
0
],
"000100": [
100,
55.00000000000001,
60,
66.66666666666666,
0
],
"000103": [
50,
100,
20,
50,
0
],
"000104": [
50,
68,
60,
66.66666666666666,
0
],
"000106": [
100,
82.99999999999999,
60,
66.66666666666666,
0
],
"000108": [
0,
100,
60,
66.66666666666666,
0
],
"000109": [
100,
50,
60,
50,
100
],
"000110": [
0,
68.99999999999999,
60,
33.33333333333333,
0
],
"000111": [
0,
68.99999999999999,
60,
66.66666666666666,
0
],
"000114": [
50,
58.999999999999986,
0,
0,
100
],
"000115": [
100,
0,
80,
16.666666666666664,
100
],
"000116": [
50,
58.999999999999986,
60,
50,
0
],
"000117": [
100,
100,
0,
0,
0
],
"000118": [
100,
100,
0,
0,
0
],
"000121": [
100,
100,
0,
50,
0
],
"000122": [
100,
68,
60,
66.66666666666666,
0
],
"000125": [
50,
56.99999999999999,
0,
16.666666666666664,
0
],
"000126": [
100,
99,
60,
66.66666666666666,
0
],
"000129": [
50,
67,
60,
50,
0
],
"000131": [
0,
100,
40,
0,
0
],
"000132": [
0,
100,
60,
0,
0
],
"000133": [
100,
66.00000000000001,
60,
66.66666666666666,
0
],
"000134": [
50,
36.99999999999999,
20,
0,
100
],
"000135": [
0,
50,
40,
0,
100
],
"000137": [
0,
50,
60,
33.33333333333333,
100
],
"000140": [
100,
100,
80,
66.66666666666666,
100
],
"000142": [
100,
100,
100,
50,
0
],
"000143": [
50,
58.999999999999986,
0,
33.33333333333333,
100
],
"000145": [
0,
100,
60,
0,
0
],
"000146": [
0,
100,
60,
100,
0
],
"000147": [
0,
100,
100,
66.66666666666666,
0
],
"000148": [
0,
49.00000000000001,
100,
50,
0
],
"000150": [
100,
63.000000000000014,
80,
100,
100
],
"000151": [
50,
100,
60,
0,
100
],
"000152": [
50,
61.999999999999986,
60,
33.33333333333333,
100
],
"000153": [
50,
53,
60,
50,
0
],
"000155": [
50,
100,
60,
100,
0
],
"000156": [
50,
66.00000000000001,
60,
66.66666666666666,
0
],
"000157": [
0,
100,
100,
66.66666666666666,
0
],
"000160": [
50,
61.999999999999986,
100,
0,
100
],
"000161": [
0,
100,
60,
0,
0
]
}
This file has been truncated, but you can view the full file.
/*! p5.func.js v0.0.1 2017-05-27 */
/**
* @module p5.func
* @submodule p5.func
* @for p5.func
* @main
*/
/**
* p5.func
* R. Luke DuBois (dubois@nyu.edu)
* Integrated Digital Media / Brooklyn Experimental Media Center
* New York University
* The MIT License (MIT).
*
* https://github.com/IDMNYU/p5.js-func
*
* the p5.func module contains five new objects for extending p5.js :
* p5.Gen() : function generators (waveforms, curves, window functions, noise, etc.)
* p5.Ease() : easing / interpolation functions
* p5.ArrayEval() : equation evaluator to generate pre-computed arrays
* p5.Filt() : biquadratic filter object
* p5.FastFourierTransform() : signal neutral FFT implementation
*
* p5.func also contains some miscellaneous functions:
* imap() : constrainted integer mapping function
* wrap() : wrapping function
* fold() : folding function
* createArray()/normalizeArray()/resizeArray()/multiplyArray()/addArray()/subtractArray()/divideArray()/moduloArray()/sumArray() : array functions
* f2ib() / ib2f() : int<->float coercion with bit parity
* sinc() : sinc (sinus cardinalis) function
* besselI0() : Bessel function
* fplot() : formattable console plot of any array
*
* primary sources:
* RTcmix Scorefile Commands: http://rtcmix.org/reference/scorefile/
* Robert Penner's Easing Functions: http://robertpenner.com/easing/
* Golan Levin's Pattern Master: https://github.com/golanlevin/Pattern_Master
* Robert Bristow-Johnson's Audio EQ Cookbook: http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
* Corban Brook's dsp.js: https://github.com/corbanbrook/dsp.js/
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd)
define('p5.func', ['p5'], function (p5) { (factory(p5));});
else if (typeof exports === 'object')
factory(require('../p5'));
else
factory(root['p5']);
}(this, function (p5) {
// =============================================================================
// p5.Gen
// =============================================================================
/**
* Base class for a function generator
*
* @class p5.Gen
* @constructor
*/
p5.Gen = function() {
//
// this object implements GEN table-style
// algorithms adapted from MUSICN languages
// (e.g. Csound, RTcmix, ChucK, Supercollider, Max).
// these algorithms are solved by direct (0.-1.)
// evaluation with utility functions to compute arrays.
//
// some code below is adapted from RTcmix :
// https://github.com/RTcmix/RTcmix
// Copyright (C) 2005 The RTcmix Development Team, released under the Apache 2.0 License
//
this.version = 0.01; // just some crap for constructor
var that = this; // some bullshit
}; // end p5.Gen constructor
// harmonic / periodic wave from a list of partial strengths.
// Csound / RTcmix GEN10, ported from RTcmix.
p5.Gen.prototype.harmonics = function(_x, _args) {
var u = true; // single value?
if(!Array.isArray(_x) && _x.constructor !== Float32Array && _x.constructor !== Float64Array) {
_x = [_x]; // process all values as arrays
u = false;
}
if(!Array.isArray(_args)) _args = [_args]; // catch single harmonic
var _sum; // match type:
if(Array.isArray(_x)) _sum = new Array(_x.length);
else if(_x.constructor === Float32Array) _sum = new Float32Array(_x.length);
else if(_x.constructor === Float64Array) _sum = new Float64Array(_x.length);
for(var i in _x) {
var j = _args.length;
_sum[i] = 0.0;
while (j--) {
if (_args[j] != 0) {
var _val = TWO_PI * _x[i] * (j + 1);
_sum[i] += (sin(_val) * _args[j]);
}
}
}
return(u ? _sum : _sum[0]);
};
// wave from triples (ratio, amp, phase).
// Csound / RTcmix GEN09, ported from RTcmix.
p5.Gen.prototype.triples = function(_x, _args) {
var u = true; // single value?
if(!Array.isArray(_x) && _x.constructor !== Float32Array && _x.constructor !== Float64Array) {
_x = [_x]; // process all values as arrays
u = false;
}
if(_args.length<2) {
console.log("p5.Gen : we need at least 3 arguments!")
return(0.);
}
else if(_args.length%3!=0) {
console.log("p5.Gen : incomplete <partial, amp, phase> triplet!");
}
var _sum; // match type:
if(Array.isArray(_x)) _sum = new Array(_x.length);
else if(_x.constructor === Float32Array) _sum = new Float32Array(_x.length);
else if(_x.constructor === Float64Array) _sum = new Float64Array(_x.length);
for(i in _x) {
_sum[i] = 0.0;
for (var j = _args.length - 1; j > 0; j -= 3) {
if (_args[j - 1] != 0.0) {
var val;
if (_args[j - 2] == 0.0) val = 1.0; // BGG: harmonic 0 (DC)
else {
val = sin(TWO_PI * (_x[i] / (1.0 / _args[j - 2]) + _args[j] / 360.0));
}
_sum[i] += (val * _args[j - 1]);
}
}
}
return(u ? _sum : _sum[0]);
};
// transfer function from chebyshev polynomials.
// Csound / RTcmix GEN17, ported from RTcmix.
p5.Gen.prototype.chebyshev = function(_x, _args) {
var u = true; // single value?
if(!Array.isArray(_x) && _x.constructor !== Float32Array && _x.constructor !== Float64Array) {
_x = [_x]; // process all values as arrays
u = false;
}
if(!Array.isArray(_args)) _args = [_args]; // catch single value
// compute the transfer function using the chebyshev equation...
var _sum // match type:
if(Array.isArray(_x)) _sum = new Array(_x.length);
else if(_x.constructor === Float32Array) _sum = new Float32Array(_x.length);
else if(_x.constructor === Float64Array) _sum = new Float64Array(_x.length);
for(var i in _x) {
var v=_x[i]*2.-1.;
_sum[i]=0.;
var Tn1=1;
var Tn=v;
for(var j=0; j<_args.length;j++) {
_sum[i]+=_args[j]*Tn;
Tn2=Tn1;
Tn1=Tn;
Tn=2*v*Tn1-Tn2;
}
}
return(u ? _sum : _sum[0]);
}
// linear breakpoint function (time, value pairs with y normalization).
// Csound GEN27 / RTcmix GEN24, rewritten by rld.
p5.Gen.prototype.bpf = function(_x, _args) {
var u = true; // single value?
if(!Array.isArray(_x) && _x.constructor !== Float32Array && _x.constructor !== Float64Array) {
_x = [_x]; // process all values as arrays
u = false;
}
if(_args.length%2!=0) {
console.log("p5.Gen : incomplete <time, value> pair!")
return(0.);
}
var endtime = _args[_args.length - 2];
var starttime = _args[0];
if (endtime - starttime <= 0.0) {
console.log("p5.Gen : bpf times must be in ascending order!");
return(0.);
}
var scaler = 1.0 / (endtime - starttime);
var thistime = 0;
var nexttime = 0;
var thisval = 0;
var nextval = 0;
var _y // match type:
if(Array.isArray(_x)) _y = new Array(_x.length);
else if(_x.constructor === Float32Array) _y = new Float32Array(_x.length);
else if(_x.constructor === Float64Array) _y = new Float64Array(_x.length);
for(i in _x)
{
for (var k = 1; k < _args.length; k += 2) {
thistime = _args[k-1]*scaler;
thisval = _args[k];
if(k<_args.length-1) {
nexttime = _args[k+1]*scaler;
nextval = _args[k+2];
}
else {
nexttime = thistime;
nextval = thisval;
}
if(nexttime - thistime < 0.0) { // okay for them to be the same
console.log("p5.Gen : bpf times music be in ascending order!");
return(0.);
}
if(_x[i]>=thistime && _x[i]<=nexttime) // this point in bpf
{
var _thisval = _args[k+1];
_y[i] = map(_x[i], thistime, nexttime, thisval, nextval);
break;
}
}
}
return(u ? _y : _y[0]);
}
// common random number distributions.
// Csound GEN21 / RTcmix GEN20, written by rld.
// if no seed, auto-generated from millis().
// algorithms adapted from dodge and jerse (1985).
// inspired by denis lorrain's
// 'a panoply of stochastic cannons' (1980):
// http://www.jstor.org/stable/3679442
p5.Gen.prototype.random = function(_x, _type) {
// distributions based on RTcmix GEN20:
// even distribution ["even" or "linear"]
// low weighted linear distribution ["low"]
// high weighted linear distribution ["high"]
// triangle linear distribution ["triangle"]
// gaussian distribution ["gaussian"]
// cauchy distribution ["cauchy"]
//
// a -1 in the seed parameter (or missing) will
// instruct the algorithm to use the millisecond
// clock for a random seed.
var u = true; // single value?
var _s = 0.;
if(!_x) // no arguments, so do linear with random seed
{
_type = 'linear';
_x = [millis()];
u = false;
}
else if(typeof(_x)!='string') // first argument is a number, so seed
{
if(!Array.isArray(arguments[0]) && arguments[0].constructor !== Float32Array && arguments[0].constructor !== Float64Array) {
_x = [_x]; // process all values as arrays
u = false;
}
}
else // argument is a string, so type
{
_type=_x; // it's the type, not the seed
_x = [millis()]; // random seed
u = false;
}
var _v; // match type:
if(Array.isArray(_x)) _v= new Array(_x.length);
else if(_x.constructor === Float32Array) _v = new Float32Array(_x.length);
else if(_x.constructor === Float64Array) _v = new Float64Array(_x.length);
if(_x[0]===-1) randomSeed(millis()*100000.);
for(var i in _x)
{
if(_x[i]!=-1) randomSeed(_x[i]*100000.);
switch(_type) {
case "linear":
case "even":
_v[i] = random();
break;
case "low":
_v[i] = min(random(), random());
break;
case "high":
_v[i] = max(random(), random());
break;
case "triangle":
_v[i] = (random()+random())/2.0;
break;
case "gaussian":
var n = 12;
var sigma = 0.166666;
var randnum = 0.0;
for (var j = 0; j < n; j++) {
randnum += random();
}
_v[i] = sigma * (randnum - n/2) + 0.5;
break;
case "cauchy":
var alpha = 0.00628338;
do {
do {
_v[i] = random();
} while (_v[i] == 0.5);
_v[i] = (alpha * tan(_v[i] * PI)) + 0.5;
} while (_v[i] < 0.0 || _v[i] > 1.0);
break;
default:
_v[i] = random();
break;
}
}
return(u ? _v : _v[0]);
}
// common window functions for signal processing.
// Csound GEN20 / RTcmix GEN25 (paris smaragdis / dave topper)
// and Pattern Master by @golanlevin .
// rewritten / ported from C and Java by rld.
// equations from Wikipedia: https://en.wikipedia.org/wiki/Window_function
p5.Gen.prototype.window = function(_x, _type, _args) {
// flag order based on CSOUND GEN20:
// 1 = hamming
// 2 = hanning
// 3 = bartlett (triangle)
// 4 = blackman (3-term)
// 5 = blackman-harris (4-term)
// 6 = gaussian
// 7 = kaiser
// 8 = rectangle
// 9 = sinc
// these and others are addressible by name.
var u = true; // single value?
if(!Array.isArray(_args)) _args = [_args]; // catch single value
if(!Array.isArray(_x) && _x.constructor !== Float32Array && _x.constructor !== Float64Array) {
_x = [_x]; // process all values as arrays
u = false;
}
var _y; // match type:
if(Array.isArray(_x)) _y= new Array(_x.length);
else if(_x.constructor === Float32Array) _y = new Float32Array(_x.length);
else if(_x.constructor === Float64Array) _y = new Float64Array(_x.length);
var i;
switch(_type) {
// proposed by richard wesley hamming (1915-1998).
// optimized to quash the nearest sidelobe.
case 1:
case "hamming":
var alpha = 0.54;
var beta = 0.46;
for(i in _x) _y[i] = alpha - beta * cos(TWO_PI * _x[i]);
break;
// named for julius von hann (1839-1921).
// sidelobes fall at 18db/oct.
case 2:
case "hanning": // not the guy's actual name
case "vonhann": // the guy's actual name
case "hann": // sort of the guy's actual name
case "hannsolo": // no
case "hanningvonhannmeister": // very much no
for(i in _x) _y[i] = 0.5 * (1-cos(TWO_PI*_x[i]));
break;
// proposed by m.s. bartlett (1910-2002).
// also by lipót (leopold) fejér (1880-1959).
// triangular (2nd order b-spline) window.
case 3:
case "bartlett":
case "fejer":
case "fejér": // get the accent right
case "triangle":
for(i in _x) _y[i] = 1.0 - abs((_x[i]-0.5)/0.5);
break;
// bartlett-hann window.
case "bartlett-hann":
var a0 = 0.62;
var a1 = 0.48;
var a2 = 0.38;
for(i in _x) _y[i] = a0 - a1*abs(_x[i] - 0.5) - a2*cos(2*PI*_x[i]);
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment