Week 1: ‘Carefree’: A Self Portrait

In our very first week of Intro to IM, we covered the basic concepts of programming and got a peek into the creative potential of computation as we were shown famous and popular digital arts from around the world. We also learned about this wonderful platform p5js.org where creative coding can be done and executed right inside the browser! (powerful, right?)

For our very first assignment of Intro to IM, we were asked to construct a self-portrait using code on p5.js. We were demonstrated how to construct primitive shapes in class. What I found most useful on this platform was the in-site Reference page, which contained documentation of different built in functions and libraries (which I referenced to countless times during this assignment). This is the result of a weekend of experimentation and countless trials and errors:

I decided to start with the face first. Instead of going for an ellipse for the face, I googled to find out how to make custom shapes and stumbled upon the use of Bezier curves. This short video on YouTube intrigued me:

This video explained every question I had in mind about custom shapes. The only challenge now was determining the anchor points for the exact type of curve I wanted. For that I used Desmos Cubic Bezier Curve visualizer, and I plotted the points in reference to a 400 X 400 px canvas. Then I was able to use the Bezier function on p5.js. Here’s a demo of what that looked like:

stroke(0, 0, 0);
  strokeWeight(18);
  noFill();
  bezier(130, 214, 175, 185, 225, 185, 270, 214);

Bezier functions seemed so powerful and fun, I got kind of hooked to it and it was hard to stop myself from using them at times. I also used beginShape() and endShape() to create closed bezier shapes, using guide from the above YouTube video. The face, the cap, the lips, and the ears were all created using closed Bezier forms. For all the colors, I used the RGB color chart from RapidTables.

I did, however, use plenty of primitive shapes. The glasses, for instance, were created using the built in ellipse() and line() functions. The nose was also easy to create using the triangle() function. For the syntax of these functions I took help from the Reference page. For the t-shirt, I created a closed polygon by calculating vertices from the center and using the vertex() function.

Now that I had a basic self portrait with a clear blue sky as background, I had this urge to add more to make the portrait interesting. Down I went again into my Googling rabbit-hole and discovered that I could use custom function and classes similar to Python! I have coded in Python before, so these concepts were known to me. I went to w3Schools JavaScript Tutorial and read the documentation for classes and functions in JavaScript (it was mostly similar to Python which helped). Using my newfound power, I went back to my p5.js code and created a simple function to make the left eye blink randomly. The function has a basic if statement and when executed, instead of the eyeball, I simply printed a line across the eye to make it look like the eyelid shut. Else, the function just printed an eyeball (an ellipse).  But then I faced the challenge of how to show the motion. I googled a bit and learned about the frameRate() function from References and that was perfect to make idea work. Here’s the code snippet showing the custom eye(x,y) function:

// custom eye function

function eye(x, y) {
  fill(255, 255, 255);
  ellipse(x, y, 20, 20);

  //winking motion
  if (random(1000) > 20) {
    fill(0, 0, 0);
    ellipse(x, y, 7, 7);
  } 
  else {
    stroke(0, 0, 0);
    line(x - 10, y, x + 10, y);
  }
}

Next, the background looked really empty. Back in my home country we have plenty of cloudy days which I love so I decided to put clouds using ellipses(). Then I realized I was already using the frameRate() function, so why not try moving the clouds as well. Thankfully, the frameRate() reference page had the exact example to moving an object across the screen. I only needed to increment the X or Y coordinate in one direction to make it seem they are moving. I decided using Javascript classes so I could easily produce multiple moving clouds since I was already familiar with classes in Python. I was able to create my own Cloud class with two methods– one for incrementing the X coordinates of  the clouds so they seem to be moving, and one to display the created clouds. And voila! After some experimentation, I achieved my desired result. Here’s the code snippet of the Cloud class:

// Cloud JS Class

class Clouds {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  //method for horizontal cloud motion
  moveCloud() {
    this.x += 1;
    if (this.x > width) {
      this.x = 0;
    }
  }

  //method to show the cloud
  displayCloud() {
    noStroke();
    fill(255, 255, 255);
    ellipse(this.x, this.y, 70, 60);
    ellipse(this.x + 50, this.y + 10, 70, 40);
    ellipse(this.x - 50, this.y + 10, 80, 50);
  }
}

Now I had to put the finishing touches. I added a sun behind the clouds (because what’s better than a nice sunny day?), the letters Q and M of my name on the cap using ellipses and lines and finally for the t-shirt color I had to go with NYU’s trademark shade of violet (manifesting Violet Pride haha).

I called this portrait “Carefree” because this reflects my persona. Nothing makes me more happy than getting to relax on a nice green field on a breezy day with a clear blue sky and floating clouds, carefree and in peace.

 

 

 

 

 

My Self Portrait…

…and I am perhaps two different beings altogether!

Trying processing for the first time was definitely a handful of a task. I mainly envisioned my portrait as an amalgamation of basic geometric shapes and structures. And even though the final result was not an exact mirror reflection, the playful bits that were coded together did seem to capture the essence of the assignment. 

In the process, I found the positioning of codes quite crucial. I had to move back and forth a few times to ensure that the right shape was being overlaid by another. Also, making sure that each side was symmetrical to the other was another important bit. The values had to be adjusted time and again through trial and error to find the exact coordinates. For example, the eyebrows were the hardest feature on the face and took quite some time to be shaped via curves. 

To highlight a bit of my artsy side through this digital mode of expression, I put a small rose in my hair wherein I primarily interacted with concentric circles and arcs. I  further hope to build upon such ideas through the usage of spiral and other animations in the upcoming tasks.

But the portion of the code that turned out to be surprisingly well was when I mapped the eyes to lend the pupils movement. It just seemed to be a clever take on a “typical eye-roll” that we do while putting a lot of effort into a new task for the first time.

I really hope to learn more about other coding functions and their implementation so that I can further sharpen my skills to more clearly express my ideas in the future. Nonetheless, I am surprised by the content I could put up in my initial take on coding and self-portraiture.

Here it is,

 

 

Assignment 1 – Self Portrait

Concept

For my self portrait assignment, I decided to go with a simple cartoon-y style. I was kind of inspired by anime style art, so I sketched out how I wanted my final result to look like on a piece of paper:

It didn’t really turn out like that sketch, but the overall idea was still followed through. I mainly used ellipses and arcs. Originally, I was going to go for just my head, but I decided to add a neck and shoulders to add a more to the self portrait element. There was a lot of guessing and adjusting with this assignment, such as the eyes and the hair. Additionally, I wanted to add some sort of interactivity, so I made the blush appear if the mouse X-position was within the face. I feel like with this, it makes it a bit more fun as opposed to just having the blush there statically.

Highlights

The part I struggled the most with was my bangs, but it turned out to be what I’m most proud of in the assignment because it took perseverance and a lot of trial and error to get it to look like the way I wanted it to.  At first, I tried to use bezierVertex(), which was in the shapes section of the reference. However, it was really hard to understand where to put the points to make the shape I wanted. It also took a lot of guessing and still didn’t turn out the way I wanted.

The second method I tried was doing two ellipses for the bangs and a rectangle for my hair. I had to add another ellipse for the top of my head or else it would look like I was bald. The rectangle for my hair was perfectly fine, but I still wasn’t completely satisfied with the look and shape of my bangs.

So the final shape I tried was the arc for my bangs. I used arc for my eyebrows as well, so I feel like I should’ve done this method first but I wanted to experiment with bezierVertex(). The arcs were a bit tedious because it was a lot of guessing where each side of the bangs would be positioned. I also had to adjust the arc shape, width, and height multiple times before I got the final product.

Reflection and Future Directions

A future improvement or idea I want to incorporate is a blinking animation when the mouse is pressed. I would also like to add different facial features, such as anger or sadness. Right now, the background is also quite plain so it would be nice to add something else to it, for instance a landscape or abstract art. Overall, since I’ve done p5 in the past, this was a nice refresher and a fun assignment.

[Assignment 1] Self Portrait

Concept

For this assignment, I created a self-portrait using p5js. Various shapes (ellipses, triangles, arcs, and splines) were used to make a portrait of myself. This project contains a user interactive feature, in which the color wheel behind the portrait rotates as cursor moves. Not to mention, once the cursor rotates fast enough, color wheels will begin to randomly change for 2 seconds. Thick lines (strokes) and vibrant colors are used to make this portrait appear like a pop art piece.

Code

Writing codes for the hairs was the most challenging part of this project. To draw my hair, I had to read through the p5js reference page (https://p5js.org/learn/curves.html). In the end, I used spline lines to make custom shapes. A considerable amount of time was used to draw even a single spline line because it required coordinates of all points it passes through.

Code for hairs using spline lines:
//Left part of the hair
fill(0);
stroke(0);
beginShape();
curveVertex(314, 192);
curveVertex(314, 192);
curveVertex(302, 215);
curveVertex(292, 250);
curveVertex(222, 255);
curveVertex(227, 205);
curveVertex(247, 180);
curveVertex(277, 160);
curveVertex(307, 155);
curveVertex(327, 163);
curveVertex(327, 180);
curveVertex(324, 188);
curveVertex(314, 192);
curveVertex(314, 192);
endShape();
//Right part of the hair
beginShape();
curveVertex(324, 185);
curveVertex(324, 185);
curveVertex(326, 175);
curveVertex(337, 170);
curveVertex(366, 177);
curveVertex(374, 198);
curveVertex(375, 225);
curveVertex(372, 232);
curveVertex(362, 210);
curveVertex(347, 200);
curveVertex(324, 185);
curveVertex(324, 185);
endShape();

Another challenge I confronted while working on this project was the translation and rotation of reference points (axis). I translated the origin from the top-left corner to the center of my canvas because color wheels had to rotate around the portrait at the center. Yet, I noticed return values of mouseX and mouseY are not affected by the translation; therefore, I had to manually adjust cursor coordinates as shown below:

let mouseVecCurrent = createVector(mouseX - 300, mouseY - 300);

I expected rotate() to simply rotate objects without altering the axis, but p5js uses a rotation matrix, which means the whole axis will rotate with the object. For this reason, I had to reset the reference point before drawing any shapes:

rotate(radians(350)); //Reset the reference point

To create a responsive color wheel, I had to write several lines of code that calculate the position and rotational speed of the cursor. To do this, I compared current position and previous position of the cursor (pWinMouseX and pWinMouseY are functions that return cursor position in the previous frame). Then, I wrote some conditional statements to determine if the color should change based on the calculated rotational speed.

let mouseVecCurrent = createVector(mouseX - 300, mouseY - 300); //Vector holding current mouse position
let mouseVesPrev = createVector(pwinMouseX - 300, pwinMouseY - 300); //Vector holding previous mouse position

let mouseAngle = mouseVecCurrent.heading(); //Angle of mouse pointer relative to the origin
let mouseAngularV = 9 * abs(mouseAngle - mouseVesPrev.heading()); //Angular velocity of the cursor

//If cursor is rotating rapidly enough around the origin, set colorChange to true. OR, if colorChange is already and it has not been 2 seconds since the last rapid rotation, keep colorChange as true.
if (mouseAngularV > 53 || (colorChange && millis() - t < 2000)) {
if (!colorChange) { //If colorChange is false, set t to current millis time.
t = millis();
}
colorChange = true;
}else colorChange = false;

With the help of trigonometry and cursor information, I made color wheels that follow the cursor using triangles. The triangles were placed using for loop and their colors were randomly assigned using random()  function.

for (let i = 1; i <= divNum; i++) {
fill(i * 10 + 70, 3 * i + 125, 5 * i); //Default color regardless of the cursor movement.
if (colorChange) fill(random(255), random(255), random(255)); //If colorChange is true, wheel colors will totally be random for 2 seconds.
triangle(
0,
0,
700 * cos(((i - 1) * 2 * PI) / divNum + mouseAngle),
700 * sin(((i - 1) * 2 * PI) / divNum + mouseAngle),
700 * cos((i * 2 * PI) / divNum + mouseAngle),
700 * sin((i * 2 * PI) / divNum + mouseAngle)
);
}

Reflections / Future Improvements

Although I faced some challenges making this self-portrait, the project was very fun and exciting to work on. My portrait may not be perfect, but I am very satisfied with the project and willing to continue working on more intricate codes in this course.

In the future, I would like to write a piece of code that will open and close the mouth when the cursor is clicked. Adding a portion of my upper body that can interact with user input may also be interesting improvements to make in the future.

Assignment 1: Self Portrait

Two lectures. One assignment.

During the first lecture, we learned how p5.js work and the ways to create (seemingly) simple shapes. Second lecture, we dipped tip of our toes on making simple animations. And now we have an assignment: making a self-portrait. Although I do not have an artistic background, I did not want to create an ugly object and call it a portrait of myself. So, I discarded the difficult details. Instead of filling the entire canvas with my face, I decided to make it small. Still, I was pretty sure that I am not good at creating faces, so I turned the head sideway.

Initial Design

Better. But now, it became hard to say that it is my portrait. It looks as it a random person sitting. So, I started to lay out what characteristics I can give to this random person so that it somehow resembles myself. So, I took a picture of myself doing this assignment. Then I extracted some visible characteristics: pose, skin tone, color of clothes, and so on. After some time of planning, I started to think about how I should build this image of myself. So, I went to the p5.js reference page and skimmed through it. For pose, I could use rotate(). For color of clothes, fill(). Using circles and rounded rectangles seemed a good way to create less stiff image. At one point, I thought to myself that it is enough of planning, so I started to work on p5.js.

Difficulties

I knew I would have to go though a ton of trials and errors just to create something that may resemble what I planned. But there was one thing that kept annoyed me: rotate(). I now know better about it, but at the time, I could do nothing but to see my arms fly out of my body and disappear from my sight. After a lot of trials and errors, I could somehow bring back my arms and put it on my body. The outcome somewhat resembled myself, but I was not satisfied. I learned and know how to create animate objects in p5.js, and I wanted to somehow use it. So, I tried to change my arm’s angle of rotation to make it look as if I am typing something. And I saw my arms fly again. It is time for trials and errors.

// this is a pseudo code
rotate(radians(30));
rect(100, 100, 4, 95, 2);

Luckily, soon enough, I realized that there was a way to have a control over the axis of rotation: use translate() and then create objects at relative coordinate of 0, 0. This way, I get to move my arms while my arms still attached to my body.

let rArmAngle = 168;
let v1 = -0.2;

function animateRightArm() {
  fill(250,240,230);
  translate(width/2,height/2);
  translate(95,47);
  rArmAngle += v1;
  if (rArmAngle >= 168 || rArmAngle <= 161) {v1=-v1;}
  rotate(radians(rArmAngle));
  rect(0, 0, 100, 28, 20);
  resetMatrix();
}

And here is my final result: me making my self-portrait.

Maybe I should have figured out how to use rotation() properly before using it right away and manually fix problems. But for next time, now that I figured out how to fix an axis of rotation, I will work on figuring out how to move multiple axis of rotation to create joints, before I start typing codes.

Self-Portrait

THE SKETCH
Shown below is my self-portrait coded with p5.js. The link to the code online can be found here.

 

INSPIRATION & DESIGN 

For this piece, I was inspired by the human face sketches that we are commonly taught in beginner art classes that are meant to teach us proportions/anatomy/ratios. The sketch is realistic in this sense, but it also purposefully lacks detail when it comes to the eyes, ears, and nose for example. The portrait has been drawn exclusively black and white, and the features consist of several of the same shape layered on top of each other. All of these aspects I chose intentionally to mimic real pencil strokes and the process of re-outlining and re-tracing that happens when sketching on paper. Finally, the sketch is dynamic in that the face shifts slightly and the eyes blink according to the frame count. This was a feature that was later added on because it reminded me of primitive 2D animations.

 

CODING SPECIFICS

The code itself is not particularly complex; I made separate functions to draw each of the features: face shape, eyebrows, eyes, nose, ears, and mouth. A method I found particularly helpful for this project was curveVertex(); I used this to create custom shapes for the chin, ears, and mouth. The eyes, eyebrows, and nose were drawn using simple lines and arcs. The “sketch” effect is created by layering shapes/line of different sizes and positions 6 times using a for loop, as shown in the code snippet below:

for (let i=0; i<=6; i++) {
  x = random(-8, 8); 
  y = random(-8, 8);
  b = random(-8, 8); 
  draw_face(x, y, b);
  draw_ears(x, y, b);

The variation of shapes is determined by variables x, y, and b that are passed through the functions draw_face(), draw_ears(), etc. The x and y variables were used mainly to shift the overall position of a shape, as it was used in the translate() function, and b was used as an additional variable to manipulate proportions such as an arc’s width or a line’s length or intensity of a curve.  For example, in the draw_ears, the x and y variables manipulate the position of  the ears on the canvas.

function draw_ears(x, y) { 
  push(); 
  translate(x, y); 
  scale(1.25);

  //right
  beginShape();
  curveVertex(140, -10);
  curveVertex(140,-10); 
  curveVertex(160,-20);
  curveVertex(170,10);
  curveVertex(155,53);
  curveVertex(140,50);
  curveVertex(140,50);
  endShape();

In the case of the eyebrows, b is used to draw eyebrows of varying “arched-ness”.

function draw_eyebrow(x, y, b) { 
  translate(x, y); 
  push(); 
  rotate(8); 
  arc(-90, 0, 90+b, 12+b, 180, 360); 
  pop(); 
  push()

The lines that bisect the center of the face, the mouth, and eyebrows were created in a separate for loop that executed only 4 times and calculated random x, y and b values from a smaller range (see below). The decision behind making a second for loop was for visual purposes only.

for (let i=0; i<=5; i++) {
  x = random(-3, 3); 
  y = random(-3, 3);
  buffer = random(-6, 6);
  draw_eyebrow(x, y, b); 
  // draw_mouth(x, y);
  draw_mouth(x, y, b); 
  draw_outlines(x, y); 
}

 

Using the two loops and the randomized variables allowed every line, curve, and shape on the face to be drawn differently with each frame, giving the face its movement.  While p5.js’ standard frame rate is 60, I also altered the frame rate to be slower so that the sketch would look like real hand drawn animation. Contrarily, I played around using randomSeed() to create a still image, but in the end I prefer the dynamic one.

My favorite feature of this sketch are the blinking eyes. This was achieved by having two functions draw_eyes() and draw_eyes_closed, which were called upon depending on an if block in the for loop:

if (frameCount%6==0) { 
  draw_eyes_closed(x,y); 
}
else { 
   draw_eyes(x,y);

In short, the if statement inside the for loop executes every 6 frames and calls draw_eyes_closed(); the shape of a closed eye was simply the bottom half of the parallelogram that is the open eye. Otherwise, draw_eyes() is called and thus shows its eyes open.

REFLECTIONS

Overall I am happy with this first sketch; I think I was able to explore my creativity and create something that was uniquely my style. Personally I do not enjoy drawing myself, but I think choosing this style allowed me to not be so focused on details and instead accentuate features on myself that I like, such as the eye shape and mouth. I challenged myself by making the sketch dynamic and including the blinking feature. One thing I wish I could have included is eyelashes and pupils that moved with each blink, and I would love to try to expand the sketch to a full body self-portrait.

How to use the class WordPress blog

Logging in

WordPress login page: https://intro.nyuadim.com/wp-admin

username:

  1. For Mang’s section your username is your NetID (e.g. ghl2001)
  2. For Michael’s section you have received email with your username

password:

  1. Mang’s section: check Brightspace -> Content -> Overview/Links
  2. Michael’s section: it was emailed to you

Embedding your P5js sketch directly into your post

Instructions: https://intro.nyuadim.com/2022/01/06/how-to-embed-a-p5js-sketch-in-your-blog-post/

Finishing your post

  1. Make sure you tag your post for the correct section (either “Fall 2022 – Mang” or “Fall 2022 – Shiloh”

After publishing your blog post it should appear in the post for your section linked from the main page.

Mang’s section: https://intro.nyuadim.com/category/fall-2022-mang/

Michael Shiloh’s section: https://intro.nyuadim.com/category/fall-2022-shiloh/

Assignment 1: Self Portrait

After the first session, I played around with p5.js and made this embarrassed-looking koala using shapes, lines, fills, and the mouseX and mouseY variables. Clicking the koala makes it blush, because why not?

Embarrassed Koala

I thought it was pretty cute, so I decided to use it as a template for my actual self-portrait. I wanted to make it funny and representative of my personality of not taking things too seriously, especially with a practice as playful as IM.

In the process, I found p5.js to be an interesting adjustment. Instead of seeing color or stroke width as a property of an object, I had to type them out as separate lines of code every time I wanted something to have a different property. I couldn’t just do leftEye.color = “black” – I had to first declare the fill, then draw the left eye.  This was rather tedious, so next time, I will probably plan ahead so that I can more effectively group colorways and avoid back-and-forth switching.

After drawing the basic shapes of my self-portrait, I accidentally wrote an infinitely calling while loop, which auto-ran (because auto-running was turned on) and immediately crashed and destroyed the entire self-portrait, which I thought was being auto-saved, but was actually not. I was very sad, but I soldiered on and started again from scratch, a little faster this time around. Advice to anyone else doing this: turn off auto-run when making risky decisions like while loops.

I eventually decided to have the character hover around (to somewhat reveal NYUAD! WOO on its shirt), the eyes follow the mouse, and the background color also respond to the user’s mouse.

Originally, I was going to use a slider for changing background color, but I found that it distracted from the user experience of moving your mouse around. I also added a little “click for awesome” so that they know something will happen (the character blushes and the background goes neon yellow) when they click.

Making the portrait was quite time consuming because I had to restart, do a lot of little tweaks to put my layers in the right order, and make everything more or less symmetrical. Nevertheless, I was able to use circles, ellipses, lines, rectangles, arcs, text, a rotating transform, and mouseX and mouseY to achieve this very memey final self portrait. I think I’m pretty proud of it!

Overall, the activity made me more excited to learn more time-efficient way of doing things on p5.js, as well as more advanced techniques in producing generative effects and interesting animations. I enjoyed the process and am looking forward to figuring out more complex interactions.

Final Self-Portrait