Abstract clock

This is my abstract clock, I try to record my schedule in a day. Like during the day, I typed notes, or during the night, I drank coffee. The hour plays a role in changing the background color, the minute plays a role in changing the scene content, and the second plays a role in the flicking of elements.

Abstract Clock

//Jason Jiang
//Section E


function setup() {
    createCanvas(400, 400);
    colorMode(HSB)
    }
    


function draw() { 
//Setting scenes for different time 
    if(hour()>=0 & hour()<=6){
        sleep() 
    }
    if(hour()>=6 && hour()<=18){
        note()
    }
    if(hour()>=18 && hour()<=24){
        coffee() 
    }
}

//0:00-6:00
function sleep(){
    var secondcount = map(minute(), 0, 60, 0, 3600)+second()
    var c = map(hour(), 0, 6, 0, 100)
    var h = map(secondcount, 0, 3600, 0, 90)

    //Changing background color per hour
    background(80, 100-c, 100)

    //Drawing battery
    noFill();
    strokeWeight(10)
    rect(width/2-25, height/2-50, 50, 100)
    rect(width/2-7.5, height/2-60, 15, 5)
    
    //Changing color and height of battery per second, the battery becomes full per hour
    strokeWeight(0)
    push()
    translate(width/2, height/2)
    rotate(radians(180))
    fill(255-c, c, 0)
    rect(-20, -45, 40, h)
    pop()
    //Drawing lightning
    lightning()
}

//Flickering lightning per second
function lightning(){
    if (second()%2==0){
        push()
        translate(width/2, height/2)
        strokeWeight(8)
        rotate(radians(-10))
        line(10, -25, -10, 0)
        line(-10, 0, 10, 0)
        line(10, 0, -10, 25)
        pop()
    }   
}

//6:00-18:00
function note(x, y, m){
    var secondcount = map(minute(), 0, 60, 0, 3600)+second()
    var m = floor(map(minute(), 0, 60, 0, 10))
    var x = map(secondcount, 0, 3600, 0, 340)
    var y = 10+m*40
    var c = map(hour(), 6, 18, 0, 100)
    //Changing background color per hour
    background(30, c, 100)
    
    //Changing line length per second, a row takes 6 minutes
    fill(50)
    strokeWeight(0)
    rect(25, y, x, 15) 
    strokeWeight(5)

    //Flickering line per second
    if(second()%2==0){
        line(x+30, y-5, x+30, y+20)  
        } 
    //Adding lines for previous minutes
    for(var i=0; i<m; i++){
        strokeWeight(0);
        rect(25, 10+i*40, 340, 15)    
        }
}

//18:00-24:00
function coffee() {
    var secondcount = map(minute(), 0, 60, 0, 3600)+second()
    var c = map(hour(), 18, 24, 0, 100)
    var h = map(secondcount, 0, 3600, 0, 140)
    
    //Changing background color per hour
    background(200, c, 50)

    //Drawing coffee cup
    fill(20, 50, 40);
    strokeWeight(10)
    rect(width/2-50, height/2-50, 100, 150)
    noFill();
    strokeWeight(15)
    rect(width/2-92.5, height/2-10, 40, 60)
    strokeWeight(0)
    fill(255)

    //Changing height of coffee per min
    rect(width/2-45, height/2-45, 90, h)

    //Adding heat
    heat()
}

//Flickering heat per second
function heat(){
    strokeWeight(6)
    noFill()
    var w = width/2 
    var h = height/2
    if (second()%2==0){
        for(i=0; i<3; i++){
            bezier(w-30, h-70, w-20, h-80, w-40, h-100, w-30, h-110)
            w+=30
        }
    }
}

3D scanning of Laojun temples

Author: MediaStorm

3D scanning is no longer a novel topic today when everyone can take a series of images of an object and use computer software to process these images to generate a clean model. However, the project I am interested in expands the scope of 3D scanning drastically by reproducing the Laojun mountain temple in China. The immense size of temples requires them to use drones to take images of the temples carefully. To do that, they used software to select a region they wanted to scan. The software then calculated the flying route to control the drone so it could scan the temples accurately.

Temples in real life
Temples in digital forms

The best part I love about this project is that they have to climb up the mountain several times to control the drone and get to appreciate the temples in real life. Many ancient architectures are not properly taken care of, and even for those that get protected, they will eventually collapse someday. Therefore, 3D scanning could be a reliable way to produce 3D models of these buildings and make sure they exist in digital forms forever.

Wallpaper art

I try to build a pattern that fakes depth through gradients in brightness. The important part is to write a function for the arrows so I can make nested loops with them and array the arrows throughout the canvas.

//Jason Jiang
//Section E

//Setting variables 

//Creating Sky
function setup() {
    createCanvas(600, 500);
    background(255);
    colorMode(HSB);
    }
    


function draw() {
    //draw rows of arrows
    for(col = 0; col < 10; col++){
    for(row = 0; row < 32; row++){
        push()
        //Changing size of arrows
        var scale = 0.25 * (col+3)
        var l = 20
        translate(2*scale*l*row, 2*40*(col))
        rotate(radians(180))
        Arrow(0, 0, 20, 20, 250-col*6, 10*(col+1), scale);
        pop()
    }
    }
   noLoop()
}

    //Arrow gradient function
function Arrow(x, y, l, step, H, S, scale){
    strokeWeight(5);
    push()
    translate(x, y)
    for (i = 0; i<step; i++){
        stroke(H, S, 5*i);
        line(0, 5*i, scale*l, l+5*i)
        line(0, 5*i, -scale*l, l+5*i)
    }
    pop()
}

Rowing boats

My string art uses loops to generate wave patterns to create an ocean. In the process, I am trying to control the lines carefully by adjusting the start and end points’ values.

//Jason Jiang
//Section E

//Setting variables 
var dx1;
var dy1;
var dx2;
var dy2;
var numLines = 10;

//Creating Sky
function setup() {
    createCanvas(300, 400);
    background(135, 206, 235, 50);
    }
    


function draw() {
    
    //Waves
    stroke(0, 100, 184);
    var x1 = -30;
    var y1 = 300;
    var x2 = 600;
    var y2 = 500;
    strokeWeight(0);
    line(-30, 300, -50, 400);
    line(600, 300, 400, 500);
    strokeWeight(1);
    dx1 = (-50-(-30))/numLines;
    dy1 = (400-300)/numLines;
    dx2 = (600-300)/numLines;
    dy2 = -(500-300)/numLines;
    for (var i = 0; i <= numLines; i += 1) {
        strokeWeight(i*0.1)
        line(x1, y1, x2, y2);
        x1 += dx1;
        y1 += dy1;
        x2 += dx2;
        y2 += dy2;
    }
    

    x1 = 0;
    y1 = 300;
    x2 = 500;
    y2 = 500;
    strokeWeight(0);
    line(0, 300, -50, 400);
    line(400, 150, 500, 500);
    strokeWeight(1);
    dx1 = (-50-0)/+numLines;
    dy1 = (400-300)/numLines;
    dx2 = (500-400)/numLines;
    dy2 = -(500-150)/numLines;
    for (var i = 0; i <= numLines; i += 1) {
        strokeWeight(i*0.1)
        line(x1, y1, x2, y2);
        x1 += dx1;
        y1 += dy1;
        x2 += dx2;
        y2 += dy2;
    }


    x1 = -100;
    y1 = 300;
    x2 = 400;
    y2 = 300;
    strokeWeight(0);
    line(-100, 300, -250, 500);
    line(300, 200, 400, 300);
    strokeWeight(1)
    dx1 = (-150+50)/+numLines;
    dy1 = (500-300)/numLines;
    dx2 = -(500-400)/numLines;
    dy2 = -(300-200)/numLines;
    for (var i = 0; i <= numLines; i += 1) {
        strokeWeight((numLines-i)*0.1)
        line(x1, y1, x2, y2);
        x1 += dx1;
        y1 += dy1;
        x2 += dx2;
        y2 += dy2;
    
    }


    x1 = -100;
    y1 = 300;
    x2 = 400;
    y2 = 320;
    strokeWeight(0);
    line(-100, 320, -350, 450);
    line(200, 350, 150, 320);
    strokeWeight(1)
    dx1 = (-250-150)/+numLines;
    dy1 = (450-250)/numLines;
    dx2 = -(350-300)/numLines;
    dy2 = -(400-350)/numLines;
    for (var i = 0; i <= numLines; i += 1) {
        strokeWeight((numLines-i)*0.1)
        line(x1, y1, x2, y2);
        x1 += dx1;
        y1 += dy1;
        x2 += dx2;
        y2 += dy2;
    
    }
    

    x1 = -150;
    y1 = 200;
    x2 = 350;
    y2 = 350;
    strokeWeight(0);
    line(-150, 200, -250, 400);
    line(300, 300, 350, 350);
    strokeWeight(1)
    dx1 = (-250+100)/+numLines;
    dy1 = (300-100)/numLines;
    dx2 = -(500-400)/numLines;
    dy2 = -(300-200)/numLines;
    for (var i = 0; i <= numLines; i += 1) {
        strokeWeight((numLines-i)*0.05)
        line(x1, y1, x2, y2);
        x1 += dx1;
        y1 += dy1;
        x2 += dx2;
        y2 += dy2;
    
    }
    

    //Boat
    //Lower Part
    x1 = 85;
    y1 = 260;
    x2 = 130;
    y2 = 270;
    strokeWeight(0);
    line(85, 260, 90, 272);
    line(130, 270, 120, 280);
    strokeWeight(1)
    dx1 = 2*(90-85)/numLines;
    dy1 = 2*(272-260)/numLines;
    dx2 = 2*(120-130)/numLines;
    dy2 = 2*(280-270)/numLines;
    for (var i = 0; i <= 0.5*numLines; i += 1) {
        strokeWeight((numLines-i)*0.15)
        stroke(i);
        line(x1, y1, x2, y2);
        x1 += dx1;
        y1 += dy1;
        x2 += dx2;
        y2 += dy2;
    
    }
    //Upper Part
    x1 = 92;
    y1 = 259;
    x2 = 120;
    y2 = 265;
    strokeWeight(0);
    line(92, 261, 110, 230);
    line(120, 267, 110, 230);
    strokeWeight(1)
    dx1 = (110-92)/numLines;
    dy1 = (230-261)/numLines;
    dx2 = (110-120)/numLines;
    dy2 = (230-267)/numLines;
    for (var i = 0; i <= numLines; i += 1) {
        strokeWeight((numLines-i)*0.15)
        stroke(i+100);
        line(x1, y1, x2, y2);
        x1 += dx1;
        y1 += dy1;
        x2 += dx2;
        y2 += dy2;
    
    }

    //Sun
    x1 = 200;
    y1 = 59;
     //Outer Ring
     for (var i = 0; i <= 10*numLines; i += 1) {
        stroke(253, 184, 19, 50)
        strokeWeight(1)
        push()
        translate(x1, y1);
        rotate(radians(i*180/numLines));
        line(0, 0, 0, 100);
        pop()
 
    }
    //Inner Ring
    for (var i = 0; i <= 10*numLines; i += 1) {
        stroke(200, 92, 60)
        strokeWeight(1)
        push()
        translate(x1, y1);
        rotate(radians(i*0.5*180/numLines));
        line(0, 0, 0, 50);
        pop()
    }

noLoop();

}

Light and sound

This project is all about sound visualization. Amay Kataria visualizes sound by constructing 24 light beams arranged like a synthesizer. Each time there is a sonic input, the corresponding light turns on by performing different notes, the light flickers and continuously changes its pattern. The light and sound are tied in a way that, fundamentally, they are all waves that mark their presence in the outer world. Besides, it also connects to the inner world, which is people’s minds, since user inputs control all patterns.

Performers controlling the installation

The artists showcase his artistic sensibility by developing a system that mimics the human brain, which receives inputs from multiple sources and stores it in the database, which is interpreted and expressed through light and sound. Personally, I like how the system takes into account all users’ input at the same time which emphasizes each individual as a part of the community. It connects individuals in an anonymous way that highlights the hive-mind of humanity.

Windows style dynamic drawing

I am trying to create a grid of circles and using my mouse cursor as an attraction point to control the size and color of the circles. The wavey movement of circles is created by changing the circle rotation angle based on the distance between the mouse cursor and the center of the circles.

//Jason Jiang
//Section E

//Setting variables 
var d = 40;
var size = d/2;
var h = 0;
var s = 0;
var a = 0;
function setup() {
    createCanvas(640, 450);
    angleMode(DEGREES);
    colorMode(HSB);
    
}

function draw() {
    background(0);
    fill(255);
    noStroke();
    //Create Grid of circles using loop
    for (var x = d/2 - d; x < width + d; x = x+d){
        for (var y = d/2 - d; y < height + d; y = y+d){
        var dis = dist(x, y, mouseX, mouseY);
        
        //Change Circle size according to distance
        
        //Remap distance to circle center to angle
        size = map(dis, 0, (width^2+height^2)^0.5, 30, 1);

        //Change Circle color according to distance
        
        //Remap distance to circle center to color value
        h = map(dis, 0, (width^2+height^2)^0.5, 0, 255);
        s = map(dis, 0, (width^2+height^2)^0.5, 50, 100);
        fill(h, s, 100);
        

        //Change circle rotation according to distance

        //Remap distance to circle center to angle
        let a = map(dis, 0, (width^2+height^2)^0.5, 0, 360);
            push();
            translate(x, y);
            rotate(a);
            circle(10, 10, size);
            pop();
        }
    }    
}

Metal and Robot arm

Author: Students in seminar led by Jeremy Ficca

Project Name: Fabricating Customization Seminar

Robot arm deforming the metal. The image is from the project website

The project I admire comes from our school. It is a studio project led by Professor Ficca that experiments with the relationship between how robotic arms interact with metals to create customizable shapes generated by computers. It has the potential to renovate the means of mass-producing metal plates. The precision and rigidity of robot arms make it possible to create them. The process involves using computational design to generate different shapes of metal. Many variables control the final form, such as the panel shape, the number of folds, and the joining location. Such a degree of freedom allows for a range of unique metal forms. The students selectively choose complex shapes to produce manually and experiment with means of producing the shape. Thus, they have to understand how metals are bent to write the correct code to control the robot arms. I adore the project because it not only focuses on generating shapes but also on how to make sure those shapes can be produced physically.

Computational design of ornaments

Muqarnas is elaborate structural ornamentation that transits between floor plans and dome ceilings. This project done by Michael Hansmeyer involves using an algorithm to replicate and generate new patterns of muqarnas. I am intrigued by the dazzling patterns computers generate using simple logic. Thanks to computational design, what took hundreds of hours to design in the past can be done in minutes. This project also has implications for ornamental design in other areas, including clothing, interior design, etc.

Muqarnas generated by the algorithm

The algorithm first draws two contour lines marking the top and bottom of muqarnas, then subdividing the space in between recursively. To add variation, the software subdivides the space selectively based on the topographic features of each tile. Finally, contour lines are drawn between tiles of different tiers to add vertical dimension. The author shows his artistic sensibilities by subdividing the geometry so that each tile is too small to recognize. As a result, the muqarnas look like a continuous surface with concaves and convex features, which is different from traditional muqarnas. It is not just a replication of the past but a new design approach that utilizes the machine’s mighty computing power.

Variable Face

I want to create a simple cartoon face that has many expressions. Therefore, I add many variables including the mouth, hair, eyebrow, and so on. The outcome looks good.

Variable Face

// Setting variables for coding facial actions
var eyeSizeX = 20;
var eyeSizeY = 20;
var faceWidth = 100;
var faceHeight = 150;
var mouthExpression = 1;
var noseExpression = 1;
var hairExpression = 1;
var hairSize = 0.4;
var mouthSize = 0.1;
var r = 225
var g = 175
var b = 125
var rot = 0; 
var eyeOffAry = [-1, -0.5, 0, 0.5, 1];
var eyeOffs = 0;

function setup() {
    createCanvas(480, 640);
    angleMode(DEGREES);
}

function draw() {
    background(180);
    
    //draw face
    fill(r, g, b);
    strokeWeight(0);
    ellipse(width / 2, height / 2, faceWidth,  faceHeight);
    
    //draw hair
    //hair
    if (hairExpression <= 1) {
    fill(r-100, g-100, b-100);
    arc(width / 2, height / 2, faceWidth,  faceHeight, faceWidth*hairSize-160, -faceWidth*hairSize-20, CHORD);
    } 
    //beard
    else if (hairExpression >= 1 & hairExpression <= 2) {
    stroke(r-100, g-100, b-100);
    strokeWeight(faceWidth/5);
    arc(width / 2, height / 2, faceWidth, faceHeight, faceWidth*hairSize+40, 140-faceWidth*hairSize);
    }
    //hair line
    else if (hairExpression >= 2 & hairExpression <= 3) {
    stroke(r-100, g-100, b-100);
    strokeWeight(faceWidth/5);
    arc(width / 2, height / 2, faceWidth, faceHeight, -180+faceWidth*hairSize, -faceWidth*hairSize);
    }
    //long hair
    else if (hairExpression >= 3 & hairExpression <= 4) {
    //draw long hair behind face
    rectMode(CORNER);
    fill(r-100, g-100, b-100);
    stroke(r-100, g-100, b-100);
    strokeWeight(faceWidth/6);
    rect(width/2-faceWidth/2, height/2, faceWidth, faceHeight);
    //draw face forward
    fill(r, g, b); 
    strokeWeight(0);
    ellipse(width / 2, height / 2, faceWidth,  faceHeight);
    //draw hair forward
    fill(r-100, g-100, b-100);
    arc(width / 2, height / 2, faceWidth,  faceHeight, faceWidth*hairSize-160, -faceWidth*hairSize-20, CHORD);
    noFill();
    stroke(r-100, g-100, b-100);
    strokeWeight(faceWidth/5);
    arc(width / 2, height / 2, faceWidth, faceHeight, -180, 0);
    }


    //draw eyes
    stroke(0);
    strokeWeight(0);
    var eyeLX = width / 2 - faceWidth * 0.15;
    var eyeRX = width / 2 + faceWidth * 0.15;
    fill(255);
    ellipse(eyeLX, height / 2, eyeSizeX, eyeSizeY);
    ellipse(eyeRX, height / 2, eyeSizeX, eyeSizeY);
    fill(0);
    ellipse(eyeLX + eyeOffs*(eyeSizeX / 4), height / 2, eyeSizeX / 2, eyeSizeY / 2);
    ellipse(eyeRX + eyeOffs*(eyeSizeX / 4), height / 2, eyeSizeX / 2, eyeSizeY / 2);

    //draw noses
    fill(r-100,g-100,b-100);
    if (noseExpression <= 1) {
    ellipse(width/2, height/2 + faceHeight*0.05, faceWidth/20, faceHeight/20);
    } else if(noseExpression >= 1 & noseExpression <=2) {
    rectMode(CENTER);
    rect (width/2, height/2 + faceHeight*0.08, faceWidth/20, 1.3*faceHeight/20);
    } else {
    triangle(width/2, height/2 + faceHeight*0.05, width/2-faceWidth/20, height/2 + faceHeight*0.1, width/2+faceWidth/20, height/2 + faceHeight*0.1)
    }
    
    //draw eyebrows
    var ebrowLX1 = width / 2 - faceWidth * 0.2;
    var ebrowLY1 = height / 2 - faceHeight * 0.15;
    var ebrowLX2 = width / 2 - faceWidth * 0.35;
    var ebrowLY2 = height / 2 - faceHeight * 0.15;
    var ebrowRX1 = width / 2 + faceWidth * 0.2;
    var ebrowRY1 = height / 2 - faceHeight * 0.15;
    var ebrowRX2 = width / 2 + faceWidth * 0.35;
    var ebrowRY2 = height / 2 - faceHeight * 0.15;
    noFill();
    stroke(0);
    strokeWeight(5);
    
    translate((ebrowLX1+ebrowLX1)/2, (ebrowLY1+ebrowLY2)/2);
    rotate(rot);
    line(10, 0, -10, 0);
    rotate(-rot);
    translate(-(ebrowLX1+ebrowLX1)/2, -(ebrowLY1+ebrowLY2)/2);

    translate((ebrowRX1+ebrowRX1)/2, (ebrowRY1+ebrowRY2)/2);
    rotate(-rot);
    line(10, 0, -10, 0);
    rotate(rot);
    translate(-(ebrowRX1+ebrowRX1)/2, -(ebrowRY1+ebrowRY2)/2);

    //draw mouth
    var mouthLX = width / 2 - faceWidth * 0.25;
    var mouthLY = height / 2 + faceHeight * 0.25;
    var mouthRX = width / 2 + faceWidth * 0.25;
    var mouthRY = height / 2 + faceHeight * 0.25;
    noFill();
    strokeWeight(0);
    if (mouthExpression <= 1) {
    //open happy mouth 
    fill(255);
    beginShape();
    curveVertex(mouthLX, mouthLY);
    curveVertex(mouthLX, mouthLY);
    curveVertex(0.5*(mouthLX+mouthRX)-faceWidth*0.1, mouthLY+faceHeight*0.1);
    curveVertex(0.5*(mouthLX+mouthRX)+faceWidth*0.1, mouthLY+faceHeight*0.1);
    curveVertex(mouthRX, mouthRY);
    curveVertex(0.5*(mouthLX+mouthRX)+faceWidth*0.1, mouthLY+faceHeight*mouthSize/2);
    curveVertex(0.5*(mouthLX+mouthRX)-faceWidth*0.1, mouthLY+faceHeight*mouthSize/2);
    curveVertex(mouthLX, mouthLY);
    curveVertex(mouthLX, mouthLY);
    endShape(); 
    } else if (mouthExpression >= 1 & mouthExpression <= 2) {
    //open sad mouth 
    fill(255);
    beginShape();
    curveVertex(mouthLX, mouthLY);
    curveVertex(mouthLX, mouthLY);
    curveVertex(0.5*(mouthLX+mouthRX)-faceWidth*0.1, mouthLY-faceHeight*0.1);
    curveVertex(0.5*(mouthLX+mouthRX)+faceWidth*0.1, mouthLY-faceHeight*0.1);
    curveVertex(mouthRX, mouthRY);
    curveVertex(0.5*(mouthLX+mouthRX)+faceWidth*0.1, mouthLY-faceHeight*mouthSize/2);
    curveVertex(0.5*(mouthLX+mouthRX)-faceWidth*0.1, mouthLY-faceHeight*mouthSize/2);
    curveVertex(mouthLX, mouthLY);
    curveVertex(mouthLX, mouthLY);
    endShape();
    } else if (mouthExpression >= 2 & mouthExpression <= 3){
    //closed mouth
    strokeWeight(5);
    beginShape();
    curveVertex(mouthLX, mouthLY);
    curveVertex(mouthLX, mouthLY);
    curveVertex(0.5*(mouthLX+mouthRX)-faceWidth*0.1, mouthRY-faceHeight*mouthSize);
    curveVertex(0.5*(mouthLX+mouthRX)+faceWidth*0.1, mouthLY-faceHeight*mouthSize);
    curveVertex(mouthRX, mouthRY);
    curveVertex(mouthRX, mouthRY);
    endShape();
    } else if (mouthExpression >= 3 & mouthExpression <= 4){
    //no expression
    strokeWeight(5);
    beginShape();
    curveVertex(mouthLX, mouthLY);
    curveVertex(mouthLX, mouthLY);
    curveVertex(mouthRX, mouthRY);
    curveVertex(mouthRX, mouthRY);
    endShape();
    }
}   

//Randomize the value of variables when the user clicks to generate a new random face
function mousePressed() {
    faceWidth = random(100, 200);
    faceHeight = random(150, 250);
    eyeSizeX = random(20, 30);
    eyeSizeY = random(10, 30);
    mouthExpression = random(0, 4);
    noseExpression = random(0, 3);
    hairExpression = random(0, 5);//give some chance between 4-5 for no hair
    mouthSize = random(-0.1, 0.1);
    hairSize = random(0.1, 0.2);
    eyeOffs = random(eyeOffAry);
    r = random(100, 255);
    g = random(100, 255);
    b = random(100, 255);
    rot = random(-45, 45);
}

Me in Space

sketch
function setup() {
    createCanvas(800, 640);
    background(0);
    angleMode(DEGREES);
}

function draw() {

    //draw stars
    strokeWeight(0);
    for (let i = 0; i < 100; i++) {
        fill(255, random(180, 200), 130, random(100,255))
        circle(random(0,800), random(0,640), random(5, 10)); 
        }
    
    //draw body
    strokeWeight(1);
    fill(230);
    beginShape();
        vertex(120, 640);
        bezierVertex(150, 550, 700, 500, 800, 560);
        vertex(800, 640);
        vertex(120, 640);
    endShape();
    
    //draw glass
    translate(450, 300);
    rotate(3);
    fill(62, 73, 76);
    ellipse(0, 0, 500-35, 550-35);
    
    //draw neck
    strokeWeight(0);
    fill(133, 130, 119);
    rotate(-3);
    rect(-80, 200, 150, 60);
    
    //draw ears
    rotate(-3);
    ellipse(-180, 25, 50, 90);
    rotate(9);
    ellipse(180, 25, 50, 90);
    
    //draw face
    fill(171, 164, 149);
    rotate(-3);
    ellipse(0, -30, 380, 500);

    //draw hair
    fill(0);
    arc(0, -30, 380, 500, 175, 365, CHORD);
    stroke(0);
    strokeWeight(0);
    fill(171, 164, 149);
    beginShape();
        curveVertex(-190, -10);
        curveVertex(-190, -10);
        curveVertex(-170, -50);
        curveVertex(-120, -100);
        curveVertex(-110, -150);
        curveVertex(-90, -150);
        curveVertex(90, -150);
        curveVertex(125, -140);
        curveVertex(140, -90);
        curveVertex(190, -10);
        curveVertex(190, -10);
    endShape();

    //draw eyebrow
    strokeWeight(5);
    bezier(-120, -40, -40, -40, -40, -30, -50, -80);
    line(30, -45, 110, -55);
    
    //draw eyes
    strokeWeight(0);
    fill(0);
    rect(-80, -40, 20, 20);
    ellipse(-70, -20, 20, 40);
    rect(50, -50, 20, 20);
    ellipse(60, -30, 20, 40);
    
    //draw nose
    strokeWeight(3);
    line(-20, 0, -30, 70);
    line(-30, 70, 10, 68);
    line(10, 68, 0, 0);
    
    //draw mouse
    noFill();
    bezier(-35, 110, -10, 170, 0, 190, 25, 110);

    //draw eyeglasses
    rotate(-3);
    strokeWeight(3);
    stroke(48, 62, 61);
    line(-30, -30, 20, -30);
    line(-130, -30, -190, -15);
    line(120, -30, 190, 0);
    fill(130, 149, 161, 135);
    strokeWeight(0);
    rect(-130, -55, 100, 70, 10);
    rect(20, -55, 100, 70, 10);
    rotate(-2);
    
    //draw detail
    strokeWeight(50);
    stroke(150);
    line(210, 260, 200, 350);
    line(-190, 280, -180, 350);
    
    //draw connection
    strokeWeight(30);
    stroke(62, 73, 76);
    bezier(-160, 260, -80, 340, 100, 340, 180, 240);
    
    //draw highlight
    stroke(255, 255, 255, 130);
    bezier(120, 10, 125, 10, 115, -60, 110, -60);

    //draw suit
    rotate(5);
    noFill();
    stroke(230);
    strokeWeight(70);
    ellipse(0, 0, 500, 550);

    noLoop();
}
    

I find uploading this most difficult.