Looking Outwards 6

For this week I am talking about the YouTuber Answer in Progress, and her video “the science behind lofi music”. Lofi hip hop music has become popular in the late 2010s and early 2020s as background music for studying and gaming amongst Millennials and Gen Z. Answer in Progress sought to write an AI that could randomly produce lofi music. She gave the program a bunch of different drum and instrumental audio files and background noise, told it what frequencies and RPMs to play at that most lofi music plays at, and has the AI learn what notes should come after what other notes. Then her code should be able to produce a lofi song on its own. There are a few errors, including one song that just plays the same note over and over again, so the program does not produce a very sonically pleasing songs. It lacks an ear for what makes some notes and chords more pleasing than others that humans have, but its pretty impressive for randomly generated music with no human help.

the science behind lofi music

Project 5: Wallpaper

wpf-wallpaper
var size = 40; //variable that determines the size of the indvidiual flowers
var ypos = size;
var xpos = size;
var oDist = size * 1.4 //distance between two origins for the rings
var storedY; //variable to store previous ypos

function setup() {
    createCanvas(600, 600);
    background(231,227,210);
}

function draw() {
    for(ypos = size; ypos <= height; ypos +=(2*size)+oDist) { //loop that increases the ypos and repeats the x loops

        for(var xpos = size; xpos <= width + size; xpos += 2*size){ //loop to draw the line of flowers
            storedY = ypos; //stores ypos
            fill(0);
            push();
            translate(xpos,ypos);
            flower(0,0);
            pop();
        }
        ypos += oDist + (7*size/24);

        for(var xpos = oDist/2; xpos <= width + size; xpos += oDist){ //loop to draw the line of rings
            push();
            fill(230,192,71);
            translate(xpos,ypos);
            criss(0,0);
            pop();
        }
        ypos = storedY; //sets ypos back to what it was when the loop began so the loop iteration works properly and fills the screen
    }
    noLoop();
}

function criss(x,y){ //function that draws the ring shaps by drawing rotated flowers
    push();
    rotate(radians(45));
    flower(x,y);
    pop();
}

function flower(a,b){ //function that draws the flower by drawing a petal and then rotating 90 degrees and repeating
    petal(a,b);
    push();
    rotate(radians(90));
    petal(a,b);
    pop();
    push();
    rotate(radians(180));
    petal(a,b);
    pop();
    push();
    rotate(radians(270));
    petal(a,b);
    pop();
}

function petal(x,y) { //function that draws an idvidual petal composed of two triangles and a square
    noStroke();
    var side = size/(1+sqrt(3)); //variable that determins the length of the side of the square and equilateral triangle
    var triHigh = side*(sqrt(3)/2); //variable that determins the height of the triangle based on the length of the side
    triangle(x,y,x-(side/2),y+triHigh,x+(side/2),y+triHigh);
    square(x-(side/2),y+triHigh,side);
    triangle(x,y+size,x-(side/2),y+size-triHigh,x+(side/2),y+size-triHigh);
}

I loved this project. I had a really great time breaking down the steps of drawing into individual functions to make the process easier. Additionally, it was very satisfying to get the loops working properly because I had to iterate on that a few times. The patterns would either be too far apart or on top of one another.

Looking Outwards 5

For 3D computer art, I looked at the artist known as Chaotic Atmospheres from Switzerland. They have made digital art since 2012. As their name implies, Chaotic Atmospheres makes atmospheres and landscapes but alters them in a surrealist way. Specifically, for their project “Shapes in Nature”, their environments will often be large in scale, have exaggerated features of the environment being depicted, and some large geometric shape in the middle that is reflective. The reason I find their work so impressive is their attention to detail. They make both art from scratch and art made from imported textures, both of which are laborious tasks, either writing code to create the images or writing code to take the textures and create realistic environments out of them. Additionally, creating the reflection must be difficult, whether it be algorithmic like ray tracing or hard-coded into the work.

Chaotic Atmospheres

Adobe Portfolio shape Nature terrain erosion Procedural cube cone sphere cylinder pyramid torus plane Landscape mountain people

Adobe Portfolio shape Nature terrain erosion Procedural cube cone sphere cylinder pyramid torus plane Landscape mountain people

Project 4: String Art

wpf-string-art
//Patrick Fisher Section B

var dx1;
var dy1;
var dx2;
var dy2;
var numLines = 50;

function setup() {
    createCanvas(400, 300);
    background(50);
    fill(10);
    rectMode(CENTER);
    rect(200,150,250,250)
    dx1 = (275-25)/numLines;
    dy1 = (275-25)/numLines;
    dx2 = (25-275)/numLines;
    dy2 = (25-275)/numLines;
}

function draw() {
    var x1 = 75;
    var y1 = 25;
    var x2 = 275;
    var y2 = 275;
    stroke(255,0,0,200);
    for (var i = 0; i <= numLines; i += 1) { //crates x design that goes from upper left to bottom right
        line(x1, y1, x2, y2);
        x1 += dx1;
        y1 += dy1;
        x2 += dx2;
        y2 += dy2;

    }

    x1 = 375;
    y1 = 25;
    x2 = 75;
    y2 = 275;
    for ( i = 0; i <= numLines; i += 1) { //creates x design that goes from lower left to upper right
        line(x1, y1, x2, y2);
        x1 += -dx1;
        y1 += dy1;
        x2 += -dx2;
        y2 += dy2;
    }

    dx1 = (325-25)/numLines;
    dy1 = (75-25)/numLines;
    dx2 = (25-275)/numLines;
    dy2 = (25-0)/numLines;

    x1 = 75;
    y1 = 25;
    x2 = 325;
    y2 = 75;
    stroke(0,0,255,200);
    for ( i = 0; i <= numLines; i += 1) { //creates the blue pattern at the top
        line(x1, y1, x2, y2);
        x1 += dx1;
        y1 += dy1;
        x2 += dx2;
        y2 += dy2;

    
    }



    x1 = 325;
    y1 = 75;
    x2 = 75;
    y2 = 25;
    for ( i = 0; i <= numLines; i += 1) { //creates the second half of the top blue pattern
        line(x1, y1, x2, y2);
        x1 += -dx1;
        y1 += -dy1;
        x2 += -dx2;
        y2 += -dy2;

    
    }

    x1 = 325;
    y1 = 175;
    x2 = 75;
    y2 = 250;
    stroke(0,0,255,200);
    for ( i = 0; i <= numLines; i += 1) { //creates the botom blue pattern
        line(x1, y1, x2, y2);
        x1 += -dx1;
        y1 += dy1;
        x2 += -dx2;
        y2 += dy2;   
    }

    x1 = 75;
    y1 = 250;
    x2 = 325;
    y2 = 175;
    stroke(0,0,255,200);
    for ( i = 0; i <= numLines; i += 1) { //creates the top half of the bottom blue pattern
        line(x1, y1, x2, y2);
        x1 += dx1;
        y1 += -dy1;
        x2 += dx2;
        y2 += -dy2;

    }
    noLoop();
}

I really struggled with this project, both creatively and technically. I had to take the sample code and finger with it mostly randomly to create anything that I was remotely satisfied with it.

Looking Outward 4

The video “Sound Machines” on the YouTube channel MediaArtTube demonstrates a machine that uses light recognition to play sound. The machine has three sensors and takes in visual information from vinyl record sized discs with patters engraved. The three discs have different types of patterns which the sensors read. The first reads color, with the disk having red, yellow, and blue lines on a white disc, depending on where the sensor is located up or down the radius changes the sequence of colors, therefore changing the sound. The second disc reads either black or white, with 3 patterns made using a black disc hollowed out. When the sensor detects black is plays a noise. The final disk is split into thirds, where white becomes more and more grey. The sensor reads the grey scale and increases the volume the grayer the image gets.

Project 3: Dynamic Drawing

wpf-dynamic-drawing
function setup() {
    createCanvas(600, 450);
}

function draw() {
    var positionY = constrain(mouseY, 80, 400); //relative Y position for everything that is constrained so the sun doesnt shoot off into the sky etc
    background(139,214,241);
    fill(21,8,29, mouseY - 80); //transitions background to night sky by decreasing transparency with mouseY position
    rect(0,0,600,300);

    var rainbowAlpha = map(constrain(mouseY,80,400), 80, 250, 255, 0); //variable to control transparency of the rainbow as it goes down

    noStroke();
    
    fill(255,0,0,rainbowAlpha); //the rainbow: red
    ellipse(300, positionY + 100, 700, 200);
    fill(254,98,48,rainbowAlpha); //orange
    ellipse(300, positionY + 120, 700, 200);
    fill(255,246,2,rainbowAlpha); //yellow
    ellipse(300, positionY + 140, 700, 200);
    fill(1,179,2,rainbowAlpha); //green
    ellipse(300, positionY + 160, 700, 200);
    fill(4,1,119,rainbowAlpha); //blue
    ellipse(300, positionY + 180, 700, 200);
    fill(35,3,114,rainbowAlpha); //violet
    ellipse(300, positionY + 200, 700, 200,);
    fill(139,214,241); //"clear" ellipse that is the same color as the day background
    ellipse(300, positionY + 220, 700, 200,); 
    fill(21,8,29, mouseY - 80); //"clear" ellipse that tranistions to night sky same why the regular background does
    ellipse(300, positionY + 220, 700, 200); 


    fill(255,246,2); //sun
    circle(150, positionY - 50, 50);

    fill(241,222,150); //moon
    circle(390, positionY - 325, 30);

    fill(233,233,255,mouseY - 250); //stars
    circle(40,96,10);
    circle(250,15,10);
    circle(330,62,10);
    circle(470,340,10);
    circle(580,70,10);
    circle(346,54,10);
    circle(200,30,10);
    circle(475,120,10);
    circle(175,60,10);
    circle(275,115,10);
    circle(430,50,10);
    circle(20,20,10);
    circle(100,40,10);
    circle(270,50,10);
    circle(80,130,10);
    circle(500,25,10);
    circle(400,100,10);
    circle(150,85,10);
    circle(500,55,10);


    var positionX = constrain(mouseX,35,565);

    fill(141,196,39); //green "field"
    rect(0,300,600, 150);

    var oppositeX = map(positionX, 0, 600, 600, 0);

    fill(103,62,16); //left dog
    ellipse(positionX, 350,30,15); //body
    circle(positionX + 15, 345,15); //head
    ellipse(positionX-10,355, 5,8); //leg
    ellipse(positionX + 10, 355, 5, 8); //leg
    ellipse(positionX-15,350,15,5); //tail
    triangle(positionX+9,340,positionX+12,335,positionX+16,340); //ear
    triangle(positionX+14,340,positionX+17,335,positionX+20,340); //ear
    fill(0);
    circle(positionX+16,343,2); //eyes
    circle(positionX+19,343,2);

    fill(103,62,16); //right dog
    ellipse(oppositeX, 390,30,15); //body
    circle(oppositeX - 15, 385,15); //head
    ellipse(oppositeX + 10,395, 5,8); //leg
    ellipse(oppositeX - 10, 395, 5, 8); //leg
    ellipse(oppositeX + 15,390,15,5); //tail
    triangle(oppositeX - 9,380,oppositeX - 12,375,oppositeX - 16,380); //ear
    triangle(oppositeX - 14,380,oppositeX - 17,375,oppositeX - 20,380); //ear
    fill(0);
    circle(oppositeX - 16,383,2); //eyes
    circle(oppositeX - 19,383,2);



}

I had difficulty with this project. I had a hard time coming up with something to draw. Once I had an idea I really enjoyed coming up with ways as to how I could incorporate dynamic elements into it. One thing, in particular, I am proud of is figuring out that the map function can work backwards, with the higher value being the start point and the lower value being the stop point, which allows you to invert the value of a variable in a sense.

Looking Outwards 3

I looked at Torolf Saurmann’s Moebius Ring. I chose this piece because I find its intricacy really beautiful. The strange spiral the ring inverts itself on is facilitating to look at and the mesh design it has increases that enjoyment. Because of the mesh design, the ring is somewhat see through. This further complicates of the spiral inverts itself and requires the viewer to focus to understand it. I find it really fun and enjoy the design. The algorithm that generated this work was likely very versatile and I think that comes from the mesh design. Not only does the mesh save material, it also puts the entire project into component parts that were likely much easier to code into larger designs. The Ring is also able to stand up on its own and I wonder if that is a coincidence or something the algorithm makes sure can happen. Saurmann as an artist really likes round and circular shapes, which one can see in his other work. In this piece he doubles down on that by basing his design on a Mobius Strip, a circle that inverts and doubles back on itself. This piece does that multiple times, to the point where its hard to tell where one inversion stops another the next begins.

Torolf Saurmann

LookingOutwards-02 Dave Bollinger

I really loved Dave Bollinger’s collection of glass like geometric pieces. The pieces look like abstract stained glass, with really natural looking curves and divisions that look like it was shattered. I really like this randomness as it is satisfying how different each work looks while still being part of the same collection, and demonstrates a robust algorithm for randomization with many possible ways the “shards” could have been created. Also, the use of color is really amazing, the way some of the colors fade out looks the same way worn stained glass fades over time. It feels as if the sun is behind the patterns shining through. I admire this use of color because it shows dedication to recreating the effect of real glass and it must have been a complex effect to code. Most of these pieces focus on one color but a few of them have many colors which demonstrates that the algorithm must have been versatile in the way it filled in the shards.

Dave Bollinger

Project 2: Variable Faces

wpf-variable-face
//Patrick Fisher, section B

var eyeSize = 20;
var faceWidth = 100;
var faceHeight = 150;
var eyeColor = 2;
var mouthType = 1;
var noseType = 1;
var browLength = (1.15 * eyeSize);
var r = 0; //color value for eyebrows
var m = 1; //coefficent for for size of mouth and nose
var skinColor = 1;

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

function draw() {
    var midX = width / 2; //intermediate varriable for half the canvas length
    background(180);
    
    if(skinColor == 1){ //chooses a variety of skin colors from paper white to dark brown
        strokeWeight(1);
        fill(255);
        ellipse(midX, height / 2, faceWidth,  faceHeight); 
    
    } else if(skinColor == 2){
        strokeWeight(1);
        fill(254, 219, 117); 
        ellipse(midX, height / 2, faceWidth,  faceHeight); 
    
    } else if(skinColor == 3){ 
        strokeWeight(1);
        fill(241, 194, 125);
        ellipse(midX, height / 2, faceWidth,  faceHeight); 
    
    } else if(skinColor == 4){ 
        strokeWeight(1);
        fill(224, 172, 105); 
        ellipse(midX, height / 2, faceWidth,  faceHeight); 
    
    } else if(skinColor == 5){ 
        strokeWeight(1);
        fill(198, 134, 66); 
        ellipse(midX, height / 2, faceWidth,  faceHeight); 
    
    } else if(skinColor == 6){
        strokeWeight(1);
        fill(140, 85, 36); 
        ellipse(midX, height / 2, faceWidth,  faceHeight); 
    
    } else if(skinColor == 7){
        strokeWeight(1);
        fill(54, 30, 2);        
        ellipse(midX, height / 2, faceWidth,  faceHeight); 
    
    }

    var eyeLX = midX - faceWidth * 0.25; //variable for x position of left eye
    var eyeRX = midX + faceWidth * 0.25; //wariable for x position of left eye
    var eyeBrowL = (eyeLX - (.65 * eyeSize)); //variable for left eyebrow x position based off of left eye position
    var eyeBrowR = (eyeRX - (.5 * eyeSize)); //wariable for right eyebrow x position based off of the right eye position
    strokeWeight(1);
    fill(r);
    rect(eyeBrowL, ((height / 2) - eyeSize), browLength, (0.25 * eyeSize)); //left eyebrow
    
    strokeWeight(1);
    fill(r);
    rect(eyeBrowR, ((height / 2) - eyeSize), browLength, (0.25 * eyeSize)); //right eyebrow
    
    strokeWeight(1);
    fill(255);
    ellipse(eyeLX, height / 2, eyeSize, eyeSize); //creates left eye
    
    strokeWeight(1);
    fill(255);
    ellipse(eyeRX, height / 2, eyeSize, eyeSize); //creates right eye

    if(eyeColor == 1){ //makes brown irises       
            strokeWeight(1);
            fill(100,63,33);
            ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));

            strokeWeight(1);
            fill(100,63,33);
            ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
    
    }    else if(eyeColor == 2){   //makes green irises     
            strokeWeight(1);
            fill(0,125,75);
            ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));

            strokeWeight(1);
            fill(0,125,75);
            ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));    
    
    }    else if(eyeColor == 3){   //makes blue irises     
            strokeWeight(1);
            fill(35,164,242);
            ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));

            strokeWeight(1);
            fill(35,164,242);
            ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));    
    
    }    else if(eyeColor == 4){   //makes heterochromia, brown right blue left     
            strokeWeight(1);
            fill(100,63,33);
            ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));

            strokeWeight(1);
            fill(35,164,242);
            ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));    
    
    }    else if(eyeColor == 5){   //makes heterochromia, blue right brown left     
            strokeWeight(1);
            fill(35,164,242);
            ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));

            strokeWeight(1);
            fill(100,63,33);
            ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));    
    
    }    else if(eyeColor == 6){   //makes heterochromia, blue right green left     
            strokeWeight(1);
            fill(0,125,75);
            ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));

            strokeWeight(1);
            fill(35,164,242);
            ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));    
    
    }   else if(eyeColor == 7){   //makes heterochromia, green right blue left     
            strokeWeight(1);
            fill(35,164,242);
            ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));

            strokeWeight(1);
            fill(0,125,75);
            ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));    
    
    }    else if(eyeColor == 8){   //makes heterochromia, brown right green left     
            strokeWeight(1);
            fill(0,125,75);
            ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));

            strokeWeight(1);
            fill(100,63,33);
            ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));    
    
    }    else if(eyeColor == 9){   //makes heterochromia, green right brown left     
            strokeWeight(1);
            fill(100,63,33);
            ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));

            strokeWeight(1);
            fill(0,125,75);
            ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));    
    
    }
    //variables for positioning and drawing the mouth
    var mouthWidth = (faceWidth * (1/3));
    var mouthHeight = (faceHeight * .25);
   //intermediate variables for the x,y coordiantes for the tirangle nose type
    var tx1 = midX;
    var ty1 = ((height / 2) - (faceHeight / 16));
    var tx2 = (midX - (faceWidth / 8));
    var ty2 = ((height / 2) + (faceHeight / 6))
    var tx3 = (midX + (faceWidth / 8));
    var ty3 = ((height / 2) + (faceHeight / 6));

    if(mouthType == 1){
        strokeWeight(1);
        fill(0);
        arc(midX , ((height / 2) + (faceHeight * .25)), mouthWidth, mouthHeight, m * TWO_PI, m * PI); //creates a smiling mouth

    } else if(mouthType == 2){ //creates a frowning mouth
        strokeWeight(1);
        fill(0);
        arc(midX , ((height / 2) + (faceHeight * .375)), mouthWidth, mouthHeight, m * PI, m * TWO_PI,);

    } else if(mouthType == 3) { //creates a neutral line mouth
        
        strokeWeight(3);
        line(m * (midX - (mouthWidth / 2)), ((height / 2) + (faceHeight * .25)), m * (midX + (mouthWidth / 2)), ((height / 2) + (faceHeight * .25)));
    }
    
    if(noseType == 1){ //creates a half circle nose
        strokeWeight(1);
        fill(255);
        arc(((width * (51/100))), (height * (51/100)), (faceWidth / 4), (faceHeight / 6), m * HALF_PI, m * PI + HALF_PI);
    }

    else if(noseType == 2){ //creates a triangle nose
        strokeWeight(1);
        fill(255);
        triangle(tx1, ty1, m * tx2, ty2, m * tx3, ty3);
    }

    else if(noseType == 3){ //creates a line nose
        
        strokeWeight(3);
        line(midX, m * ((height / 2) + (faceHeight / 8)),midX, ((height / 2) - (faceHeight / 8)));
    }

}

function mousePressed() {
    // when the user clicks, these variables are reassigned
    // to random values within specified ranges. For example,
    // 'faceWidth' gets a random value between 75 and 150.
    faceWidth = random(75, 150);
    faceHeight = random(100, 200);
    eyeSize = random(10, 30);
    browLength = random((eyeSize * .95), (eyeSize * 1.35));
    eyeColor = floor(random(1,10)); //chooses one of the eye color combinations
    mouthType = floor(random(1,4)); //choose the mouth type
    noseType = floor(random(1,4));  //chooses the nose type
    r = random(255); //changes eyebrow color
    m = (random(.95,1.05));
    skinColor = floor(random(1,8)); //changes the skin color

}

I had a lot of fun with this project. It was interesting trying to come up with more and more ways to make the face different. One of my early troubles was a problem with my eye colors. I was using “if(eyeColor == x)…” and eyeColor = “random(1,10)” but most clicks would end with no irises at all. I then realized the problem was that random() gives a floating point number and I was asking for a specific integer, so the odds of getting one were super low, so I changed the line to “floor(random(1,10))” which thankfully fixed it.

Project 1: Self Portrait

wpf-portrait
function setup() {
    createCanvas(400, 600);
    background(0,186,247);
}

function draw() {

    fill(70,44,26);
    arc(200, 150, 200, 200, PI, TWO_PI,);

    fill(70,44,26);
    arc(200, 125, 200, 200, PI, TWO_PI,);

    fill(233,168,139);
    ellipse(200,150,175,175);

    stroke(70,44,26);
    fill(70,44,26);
    rect(125,60,150,30);

    fill(70,44,26);
    rect(225,120,22.5,5);

    fill(70,44,26);
    rect(152,120,22.5,5);

    fill(255,255,255);
    ellipse(165,140,17.5,17.5);

    fill(255,255,255);
    ellipse(235,140,17.5,17.5);

    fill(35,163,102);
    ellipse(235,140,10,10);

    fill(35,163,102);
    ellipse(165,140,10,10);

    fill(0);
    ellipse(165,140,5,5);

    fill(0);
    ellipse(235,140,5,5);

    fill(239,139,129);
    arc(200, 200, 40, 40, TWO_PI, PI);

    fill(0);
    arc(200, 202.5, 30, 30, TWO_PI, PI);

    fill(241,215,212);
    arc(200, 202.5, 10, 10, TWO_PI, PI);

    fill(241,215,212);
    arc(210, 202.5, 10, 10, TWO_PI, PI);

    fill(241,215,212);
    arc(190, 202.5, 10, 10, TWO_PI, PI);

    fill(255,175,145);
    arc(200, 175, 15, 30, PI, TWO_PI,);

    fill(0);
    arc(197.5, 175, 4, 4, PI, TWO_PI,);

    fill(0);
    arc(202.5, 175, 4, 4, PI, TWO_PI,);

    fill(46,56,66)
    arc(200, 637.5, 200, 800, PI, TWO_PI,);


    


    
    

}

I found this self-portrait very challenging, particularly creating hair that looked even remotely human, but I had a lot of fun trying to draw myself.