Project 03 – Dynamic Drawing

This was inspired by an app I used to use on my mom’s iPod as a kid. I’m not very good at drawing, so I figured I would give the user a chance to draw. I’ve created a program based on degrees of symmetry that lets you alter the size of the brush, number of brushes, color of the brush, color of the background, and movement of the drawn elements. You can also save your creation by pressing p.

``````// variable definitions
var degOfSymmetry = 36;
var curAngle = 0;
var diameter = 10;
let drawnCircs = [];
var showRef = true;
let currentColor = ["red", "green", "blue"];
let colorVals = [255, 255, 255];
let backgroundCols = [0, 0, 0];
var colorIndex = 0;
var currentSelect = "Currently selected: " + currentColor[colorIndex];
var whatKey = "";
var rainbowMode = false;
var rainbowCtr = 0;
var freq = 0.01;

function setup() {
createCanvas(600, 600);
background(220);
text("p5.js vers 0.9.0 test.", 10, 15);
}

function draw() {
// define background based on color arrays
background(backgroundCols[0], backgroundCols[1], backgroundCols[2]);
noStroke();

// set circle color based on user choice
let c = color(colorVals[0], colorVals[1], colorVals[2]);
if (rainbowMode) {
var rr = sin(rainbowCtr) * 127 + 128;
var rg = sin(rainbowCtr + (2*PI/3)) * 127 + 128;
var rb = sin(rainbowCtr + (4*PI/3)) * 127 + 128;
c = color(rr, rg, rb);
}
fill(c);

// self explanatory
getAngle();

// define a center, get relative mouse radius
var centerX = width / 2;
var centerY = height / 2;
var radX = mouseX - centerX;
var radY = mouseY - centerY;

// draw a circle for each degree of symmetry
for (i = 0; i < degOfSymmetry; i++) {
var loopAngle = curAngle - (i * 2*PI / degOfSymmetry)
var tX = centerX + mouseRad * cos(loopAngle);
var tY = centerY + mouseRad * sin(loopAngle);
circle(tX, tY, diameter);

// add to circle history if clicked
if (mouseIsPressed) {
drawnCircs.push([tX, tY, diameter, c, loopAngle]);
}
}

// draw each circle from history
for (i = 0; i < drawnCircs.length; i++) {
fill(drawnCircs[i][3]);
circle(drawnCircs[i][0], drawnCircs[i][1], drawnCircs[i][2]);

// if radiating, begin changing circle positions
if (drawnCircs[i][0] > width || drawnCircs[i][0] < 0) {
drawnCircs.splice(i, 1); // remove circles for speed
} else if (drawnCircs[i][1] > height || drawnCircs[i][1] < 0) {
drawnCircs.splice(i, 1); // remove circles for speed
}
}
}

// increment counter for rainbow mode
rainbowCtr = (rainbowCtr + freq) % (2*PI);

// display onscreen reference
if (showRef) {
fill(255);
text("ref: c=change color, d=change degrees of symmetry " +
"s=change circle size, b=background color \n" +
"o=clear screen, r=radiate outwards, p=save screen as png " +
"v=set radiate velocity\n q=rainbow color cycle, " +
"up/down arrow=color/velocity val+-1, right/left arrow=+-10\n" +
"i=change selected color, enter=hide ref, y=rainbow speed",
10, height - 50);
text(currentSelect, 10, 15);
text("RGB: " + (colorVals.toString(10)), 10, 30);
text("Background RGB: " + (backgroundCols.toString(10)), 10, 60);
text("Circle Size: " + (diameter.toString(10)), 10, 75);
text("Degrees of Symmetry: " + (degOfSymmetry.toString(10)), 10, 90);
text("Rainbow Frequency: " + (freq.toString(10)), 10, 105);
}
}

// gets angle from mouse pos
function getAngle() {
curAngle = atan2(mouseY - height / 2, mouseX - width / 2);
if (mouseX - width / 2 == 0) {
if (mouseY - height / 2 > 0) {
curAngle = HALF_PI;
} else {
curAngle = 3 * HALF_PI;
}
}
}

function keyPressed() {
// checks what key is pressed, performs an action, or sets a flag
if (key == "c") {
whatKey = "c";
currentSelect = "Currently selected: " + currentColor[colorIndex];
}
if (key == "o") {
drawnCircs = [];
}
if (key == "s") {
whatKey = "s";
currentSelect = "Currently selected: circle size";
}
if (key == "b") {
whatKey = "b";
currentSelect = "Currently selected: background color";
}
if (key == "d") {
whatKey = "d";
currentSelect = "Currently selected: degrees of symmetry";
}
if (key == "r") {
}
if (key == "q") {
rainbowMode = !rainbowMode;
}
if (key == "v") {
whatKey = "v";
currentSelect = "Currently selected: velocity"
}
if (key == "p") {
save("canvas_drawing.png");
}
if (key == "i") {
colorIndex = (colorIndex + 1) % 3;
currentSelect = "Currently selected: " + currentColor[colorIndex];
}
if (key == "Enter") {
showRef = !showRef;
}
if (key == "y") {
whatKey = "y";
currentSelect = "Currently selected: Rainbow Cycle Speed";
}

// changing parameters that affect drawing and motion
if (keyCode == UP_ARROW) {
if (whatKey == "d") {
degOfSymmetry += 1;
}
if (whatKey == "c") {
colorVals[colorIndex] += 1;
}
if (whatKey == "v") {
}
if (whatKey == "b") {
backgroundCols[colorIndex] += 1;
}
if (whatKey == "s") {
diameter += 1;
}
if (whatKey == "y") {
freq += 0.01;
}
}
if (keyCode == DOWN_ARROW) {
if (whatKey == "d") {
degOfSymmetry -= 1;
}
if (whatKey == "c") {
colorVals[colorIndex] -= 1;
}
if (whatKey == "v") {
}
if (whatKey == "b") {
backgroundCols[colorIndex] -= 1;
}
if (whatKey == "s") {
diameter -= 1;
}
if (whatKey == "y") {
freq -= 0.01;
}
}
if (keyCode == RIGHT_ARROW) {
if (whatKey == "d") {
degOfSymmetry += 10;
}
if (whatKey == "c") {
colorVals[colorIndex] += 10;
}
if (whatKey == "v") {
}
if (whatKey == "b") {
backgroundCols[colorIndex] += 10;
}
if (whatKey == "s") {
diameter += 10;
}
if (whatKey == "y") {
freq += 0.10;
}
}
if (keyCode == LEFT_ARROW) {
if (whatKey == "d") {
degOfSymmetry -= 10;
}
if (whatKey == "c") {
colorVals[colorIndex] -= 10;
}
if (whatKey == "v") {
}
if (whatKey == "b") {
backgroundCols[colorIndex] -= 10;
}
if (whatKey == "s") {
diameter -= 10;
}
if (whatKey == "y") {
freq -= 0.10;
}
}

return false;
}``````

Getting the symmetry correct was a little difficult, as well as figuring out how to deal with user input.

LO-03

For this week’s Looking Out, I have decided to pick James Tyrwhitt-Drake’s 2015 creation, 4-Dimensional Polytope visualization. A polytope is a geometric shape that has flat sides. Personally, I find this project admirable because I have been interested in visualizing shapes of greater than 3-dimensions for quite a while. As such, I appreciate this visualization a great deal. I am unsure about many of the algorithms that generated this work, but I can assume that many of the parameters of the polytope depend on its number of points, sides, and viewing angle of the polytope. I also believe that, because a polytope is constructed using lower dimensional shapes, the number of points is actually represented by shapes like that one seen below. Although we are unable to truly see what a 4D shape would look like, I find it very interesting that we still have ways to visualize them.

Project 02 – Variable Face

Some of the detail in this project are similar to the program I covered in my Looking Out for this week. There are times when the face does not look as it should, while there are others when it seems as though the face is trying to convey real emotions. Left click to begin and change faces.

``````/* Lance Yarlott (lcy)
Section D */

// variable definitions, names self explanatory
var canvasWidth = 400;
var canvasHeight = 400;

const headCenterX = canvasWidth / 2;
const headCenterY = canvasHeight / 2;

var skinR = 255;
var skinG = 255;
var skinB = 255;

var noseWidth = 10;

var earWidth = 10;

var eyeR = 255;
var eyeG = 255;
var eyeB = 255;

var eyebrowWidth = 10;
var eyebrowThickness = 1;
var eyebrowAngle = 0;
var eyebrowDistance = 0;
var eyebrowHeight = eyeCenterY - (2 * eyeWhiteRadius);

var mouthCurve = 0;
var mouthWidth = 1;
var mouthThickness = 1;

var hairR = 255;
var hairG = 255;
var hairB = 255;

var noseR = 255;
var noseG = 255;
var noseB = 255;

var bgColor = 255;

function setup() {
createCanvas(canvasWidth, canvasHeight);
background(220);
text("p5.js vers 0.9.0 test.", 10, 15);
frameRate(10);
noStroke();
}

function draw() {
if (mouseIsPressed) {
if (mouseButton === LEFT) {
// colors
skinR = random(0, 255);
skinG = random(0, 255);
skinB = random(0, 255);

eyeR = random(0, 255);
eyeG = random(0, 255);
eyeB = random(0, 255);

hairR = random(0, 255);
hairG = random(0, 255);
hairB = random(0, 255);

noseR = random(0, 255);
noseG = random(0, 255);
noseB = random(0, 255);

bgColor = random(0, 255);

// face shapes

eyebrowAngle = random(-HALF_PI, HALF_PI);
eyebrowDistance = random(0, eyebrowWidth);
eyebrowHeight = eyeCenterY - (random(1, 3) * eyeWhiteRadius);

mouthCurve = random(50);
mouthThickness = random(1, 10);
}
}

// set background color
background(bgColor);

// draw face outline, variable skin color?
fill(skinR, skinG, skinB);

// TODO: nose
fill(noseR, noseG, noseB);
triangle(noseX - noseWidth, noseBottomY, noseX + noseWidth, noseBottomY,
noseX, noseTopY);

// TODO: variable eyes w/ variable color
fill(255);

fill(eyeR, eyeG, eyeB);

fill(0);

// TODO: variable eyebrows, match hair color
stroke(hairR, hairG, hairB);
strokeWeight(eyebrowThickness);
line(headCenterX + eyebrowDistance, eyebrowHeight - 10 * sin(eyebrowAngle),
eyebrowHeight + 10 * sin(eyebrowAngle));
line(headCenterX - eyebrowDistance, eyebrowHeight - 10 * sin(eyebrowAngle),
eyebrowHeight + 10 * sin(eyebrowAngle));

// TODO: variable mouth, just shape of curve
stroke(0);
curve(mouthX - mouthWidth, mouthY + mouthCurve, mouthX - mouthWidth / 2,
mouthY - mouthCurve, mouthX + mouthWidth / 2, mouthY - mouthCurve,
mouthX + mouthWidth, mouthY + mouthCurve);
noStroke();
}``````

LO-02 – Generative Art

The work I have looked at this week is called “nQbitor” or “Incubator.” It’s a program created by Mario Klingemann that generates 8-bit tones and imagery from a single line formula. I really appreciate the fact that such intricate designs can be created from a single formula when put into a program. The formula itself seems to be a large number of binary operations on numbers. The result is then presumably put into a tone and image generator, creating the end result. It seems as though the artist has an interest in sound design based on mathematical formulas, given the nature of this project. He understands that semi-random generation does not always lead to good results and accepts that with this generation there will be the need to make multiple attempts. Random generation can yield truly interesting results when given enough time, which is something that I appreciate, and something I hope this program’s author appreciates as well.

Project 1 – Self Portrait

This is me. 100% real-to-life, unedited, me.

my-true-portrait
``````/* Lance Yarlott
Section D */

function setup() {
createCanvas(600, 600);
background(0);
text("p5.js vers 0.9.0 test.", 10, 15);

lightsOn = false;
eyeLocXL = (width / 2) - 90;
eyeLocXR = (width / 2) + 90;
eyeLocY = (height / 2) - 90;
}

// big sorry for magic numbers lol

function draw() {
background(0);
textAlign(CENTER);
fill(255);
textSize(20);
text("Do you agree to the EULA? Press any key to continue.", 300, 300);
if (keyIsPressed === true) licenseAgreement = true;
} else {
if (mouseIsPressed) {
if (mouseButton === LEFT) lightsOn = true;
if (mouseButton === CENTER) lightsOn = false;
}

/* I tried to bound mX and mY with the circumference of the eye and
failed miserably because p5 calculates the angles in a weird way? */

mX = mouseX + 1 < 600 ? mouseX + 1 : 600;
mY = mouseY + 1 < 600 ? mouseY + 1 : 600;

mX = ((mX / 600) * 36) - 18;
mY = ((mY / 600) * 36) - 18;

if (lightsOn) {
background(255, 244, 176); // light yellow

strokeWeight(2);
stroke(0);

fill(0, 255, 0); // green
triangle(width / 2, height / 3 + 140, 0, 600, 600, 600);
fill(0);
text("i am trgl", width / 2, 500);

fill(245, 205, 149); // sort of a tan-ish color
ellipse(width / 2, height / 3, 360, 360); // head shape

fill(255); // eye whites
arc(eyeLocXL, eyeLocY, 80, 80,
0, PI + QUARTER_PI, CHORD); // taken from p5 ref site
arc(eyeLocXR, eyeLocY, 80, 80,
-QUARTER_PI, PI, CHORD);

fill(77, 54, 21); // irises
ellipse(eyeLocXL + mX, eyeLocY + mY, 40, 40);
ellipse(eyeLocXR + mX, eyeLocY + mY, 40, 40);

fill(0); // pupils
ellipse(eyeLocXL + mX, eyeLocY + mY, 20, 20);
ellipse(eyeLocXR + mX, eyeLocY + mY, 20, 20);

strokeWeight(40);
stroke(245, 205, 149);
noFill();
ellipse(eyeLocXL, eyeLocY, 120, 120);
ellipse(eyeLocXR, eyeLocY, 120, 120);
strokeWeight(2);

fill(245, 205, 149); // lids
noStroke();
arc(eyeLocXL, eyeLocY, 82, 82,
PI + QUARTER_PI, 0, CHORD);
arc(eyeLocXR, eyeLocY, 82, 82,
PI, -QUARTER_PI, CHORD);

fill(77, 54, 21);
arc(width / 2, height / 3, 360, 360, -PI + QUARTER_PI, -QUARTER_PI);

fill(0);
triangle(width / 2, eyeLocY + 30, width / 2 - 25, eyeLocY + 80,
width / 2 + 25, eyeLocY + 80);

stroke(0);
strokeWeight(10);
line(eyeLocXL, height / 3 + 120, eyeLocXR, height / 3 + 120);
strokeWeight(2);

} else {
background(0);
textAlign(CENTER);
fill(255);
textSize(20);
text("Click, friend.", 300, 300);

fill(255); // eye whites
ellipse(eyeLocXL, eyeLocY, 80, 80);
ellipse(eyeLocXR, eyeLocY, 80, 80);

fill(0); // irises
ellipse(eyeLocXL + mX, eyeLocY + mY, 40, 40);
ellipse(eyeLocXR + mX, eyeLocY + mY, 40, 40);

strokeWeight(40);
stroke(0);
noFill();
ellipse(eyeLocXL, eyeLocY, 120, 120);
ellipse(eyeLocXR, eyeLocY, 120, 120);
strokeWeight(2);
}
}
}
``````

One difficulty was trying to get the eye tracking working. JS calculates angles in an odd way, so moving in a circular motion was mostly impossible to get right for the time being.

LO 1 – My inspiration

One interactive art piece I admire comes from teamLab Planets TOKYO. It’s a piece called “The Infinite Crystal Universe” and it uses hanging strips of LEDs in a presumably reflective space that simulates an infinite environment. It utilizes pointillism to create visuals for the user. Due to this being a piece put into the museum by its owners, one can assume that a large number of people worked on it. As for the time it took, the project must have lasted for months if not years. The piece utilizes its own app to “throw” elements into the LED galaxy, so custom software was created that took information from the phone such as the direction the user is facing. Although I am not sure if the creators were inspired by any specific past works, the piece is entirely space-themed and the promotional video is occasionally reminiscent of 2001: A Space Odyssey’s stargate scene, with lights flying by the viewer at incredible speeds. The piece is also similar to a large-scale version of the mirrors that use LEDs to create the illusion of an infinite hole. I think that this piece can lead to more art that allows viewers to interact with it in multiple ways, from physical steps to digital apps. I do not believe that the piece itself is so revolutionary that a slew of new space-themed 3D artworks will be created, but I do believe that this piece is incredibly interesting in its own right. I would love to see more interactive art pieces that make use of perspective and 3D space to create seemingly endless environments. Personally, I have always been interested in space and I would love to create something like this myself, had I the time or the budget to do so.