LO: Randomness

An example of in-game terrain generation from a forest biome to a mountain biome

As a part of my quarantine boredom, I have picked up the game Minecraft again in a serious way, and a good deal of my time in Minecraft is simply spent wandering around the game’s randomly generated terrain. Minecraft has over 60 different types of terrain, each including their own terms of generation (i.e.: a snowy tundra will look very different from a fringe jungle biome). The only uniform constraint is the height limit, y=256, and bedrock y=0. I admire the sheer variety of terrains in Minecraft, and how much work goes into creating them. They are all instantly recognizable and yet always unique. Before 15-104, I had never considered the effects of randomness on terrain, but now I can see just how deep it goes. The caves underneath are random, as is the surface land, the nether connected to the overworld, the generated structures, the ores, the trees, the mobs… the list goes on. I think that that’s the beauty of Minecraft: it is an entirely different experience every time, due to the randomness deeply embedded in the game.

Minecraft (released Nov.18, 2011)
https://www.minecraft.net/en-us

Project 5: Wallpaper

sketch

//Elise Chapman
//ejchapma
//Section D

function setup() {
    createCanvas(200,600);
    background(158,98,64);
    rectMode(CENTER);
}

//light brown: 222,164,126
//red: 205,70,49
//cream: 248,242,220
//blue: 129,173,200
//dark blue: 118,148,159
//wine: 65,11,19

function draw() {
    for (var snowNum=0; snowNum<=50; snowNum+=1) {
        var xPos=random(0,width);
        var yPos=random(0,height);
        interest(xPos,yPos);
    }
    for (var x=0; x<=width; x+=100){
        for (var y=0; y<=height; y+=180) {
            flower(x,y);
        }
    }
    for (var x=50; x<=width; x+=100) {
        for (var y=90; y<=height; y+=180) {
            star(x,y);
        }
    }
    noLoop();
}

function interest(x,y) {
    push();
    translate(x,y);
    noStroke();
    fill(144,82,45);
    ellipse(0,0,20);
    pop();
}

function diamond(x,y) {
    push();
    translate(x,y);
    strokeWeight(8);
    stroke(222,164,126);
    line(0,90,50,0);
    line(50,0,0,-90);
    line(0,-90,-50,0);
    line(-50,0,0,90);
    /*starPiece(60,100);
    rotate(radians(90));
    starPiece(100,60);
    rotate(radians(90));
    starPiece(60,100);
    rotate(radians(90));
    starPiece(100,60);*/
    pop();
}

function star(x,y) {
    push();
    translate(x,y);
    strokeWeight(4);
    stroke(106,146,161); //dark blue
    fill(129,173,200); //light blue
    ellipse(0,0,70);
    ellipse(0,0,50);
    ellipse(0,0,30);
    strokeWeight(2);
    push();
    rotate(radians(45));
    triangle(-9,9,0,30,9,9);
    triangle(-9,-9,0,-30,9,-9);
    triangle(-9,-9,-30,0,-9,9);
    triangle(9,-9,30,0,9,9);
    pop();
    triangle(-9,9,0,35,9,9);
    triangle(-9,-9,0,-35,9,-9);
    triangle(-9,-9,-35,0,-9,9);
    triangle(9,-9,35,0,9,9);
    fill(106,146,161);
    rect(0,0,15,15);
    pop();
}

function flower(x,y) {
    push();
    translate(x,y);
    strokeWeight(2);
    stroke(91,26,36);
    fill(91,26,36); //wine
    ellipse(0,0,70);
    fill(205,70,49); //red
    push();
    rotate(radians(45));
    rect(0,-15,25,40,80,80,80,80);
    rect(-15,0,40,25,80,80,80,80);
    rect(0,15,25,40,80,80,80,80);
    rect(15,0,40,25,80,80,80,80);
    rect(0,-15,4,20,80,80,80,80);
    rect(-15,0,20,4,80,80,80,80);
    rect(0,15,4,20,80,80,80,80);
    rect(15,0,20,4,80,80,80,80);
    pop();
    rect(0,-15,25,40,80,80,80,80);
    rect(-15,0,40,25,80,80,80,80);
    rect(0,15,25,40,80,80,80,80);
    rect(15,0,40,25,80,80,80,80);
    rect(0,-15,6,20,80,80,80,80);
    rect(-15,0,20,6,80,80,80,80);
    rect(0,15,6,20,80,80,80,80);
    rect(15,0,20,6,80,80,80,80);
    ellipse(0,0,30);
    push();
    rotate(radians(45));
    ellipse(0,10,7);
    ellipse(0,-10,7);
    ellipse(10,0,7);
    ellipse(-10,0,7);
    pop();
    ellipse(0,10,7);
    ellipse(0,-10,7);
    ellipse(10,0,7);
    ellipse(-10,0,7);
    ellipse(0,0,10);
    diamond(0,0);
    pop();
}

I love Japanese paper wallpapers from the 1920’s and 1930’s, so I chose them as my particular inspiration for this work. I love the inspiration from nature while keeping with a more geometric feel, consistent with traditional Japanese art. Something about them feels timeless and elegant, but not boring. In particular, these two wallpapers inspired me:

Panel wallpaper with floating circular designs
Panel wallpaper alternating between ornate rectangular strips and simple floating circular designs

The sketch I drew out before approaching the code was as follows:

Simple sketch of overall layout, as well as potential circle fills

I also decided to include color in my design. I’m personally attracted to a lot of primary color schemes, but didn’t want to play too far into that for fear of my wallpaper looking too discordant from my Japanese inspiration. So, I settled on a dark red and a warm blue.

LO: 3D Computer Graphics

Background for the fashion line Bound

Lunar Gala Backgrounds, Danny Cho, 2020

I had the great opportunity to meet a senior designer here at CMU who did very interesting 3D computer graphics. Specifically for the Lunar Gala Collectiva show, Danny Cho created a series of computer generated 3D graphics to become dynamic backgrounds for advertisement and each fashion line. I really admire the attention to color and detail in each of these backgrounds. They were truly thoughtfully designed to fit each and every line, and they feel so immersive and polished. Each asset was carefully rendered in Cinema4D and then spliced together by a team that worked under Danny. I think that the final product is a testament to not only Danny’s work, but work of the entire team, as well as a celebration of the Lunar Gala Designers.

Project 4: String Art

sketch

//Elise Chapman
//ejchapma
//Section D

function setup() {
    createCanvas(400,300);
}

var dx1;
var dy1;
var dx2;
var dy2;

function draw() {
    background(30,50,49); //periwinkle
    var dist=100; //distance from center of spiral
    var angle=5;
    var y=100;
    var x=100;
    push();
    //intricate purple
    translate(width/2+25,height/2+25); //sets center of spiral
    for(y=100; y<=200; y+=0.5) {
        strokeWeight(2);
        stroke(153,141,160); //purple
        rotate(radians(angle*10));
        line(mouseX/15,mouseY/15,mouseX+dist,y);
        dist-=0.5;
    }
    //star
    for (y=10;y<=300;y+=5) {
        strokeWeight(5);
        stroke(196,231,212); //grey
        rotate(radians(-angle+180)); //creates the spiral
        line(x+dist, y+dist, min(mouseX/2,300), min(mouseY/2,50));
        dist-=1;
    }
    //straight line spread
    pop();
    var numLines=20;
    dx1=0/numLines;
    dy1=mouseY/numLines;
    dx2=mouseX/numLines;
    dy2=0/numLines;
    var x1=0;
    var y1=100;
    var x2=500;
    var y2=250;
    for (var i=0; i<=numLines; i+=1) {
        stroke(300);
        strokeWeight(3);
        line(x1,y1,x2,y2);
        x1+=dx1;
        y1+=dy1;
        x2+=dy2;
        y2+=dy2;
    }
}

I wasn’t too sure about my string art going into programming. I didn’t really have a clear vision and in the end I kept playing around with the code until I reached a point I like. In the future, I think I’m going to try to redo this code on my own – I think it would be an engaging entrance piece for my website.

LO: Sound Art

Short video of Klompen

Trimpin, Klompen

I appreciate the works of Trimpin. I originally looked him up because I thought his artist name was neat, but I ended up really enjoying his sculptures. In particular, I enjoy his Klompen sculpture. 120 Dutch wooden clogs are connected to a computer by concealed wires and suspended from the ceiling, which then use small levers hidden inside the clogs to hit the wood of the clogs and create the distinctive rapping wood noises. I find it interesting for the layers of art that are embedded in the sculpture. Firstly, the clogs themselves are art pieces in how they are crafted and then individually painted. Then, hanging them from the ceiling introduces interesting three-dimensional and surrealist aspects. Finally, they make fun music using an unconventional method. You can tell how much digital work went into bringing the sculpture to life. I appreciate that the work isn’t necessarily “deep” or thought provoking, but is fun to look at and fun to listen to, which is all art needs to be sometimes.

Project 3: Dynamic Drawing

chapmanDynamic

//ELise Chapman
//ejchapma
//Section D

function setup() {
    createCanvas(450,600);
    rectMode(CENTER);
}

var stormSize=1;
var rainPos=200;
var rainV=1;

function draw() { //cloud
    noStroke();
    background(149,209,216);
    //as the mouse moves down, the sky gets darker
    if (mouseY<100) {
        background(149,209,216);
        stormSize=1;
    } else if (mouseY>=100 & mouseY<200) {
        background(121,176,190);
        stormSize=2;
    } else if (mouseY>=200 & mouseY<300) {
        background(85,137,157);
        stormSize=3;
    } else if (mouseY>=300 & mouseY<400) {
        background(62,103,124);
        stormSize=4;
    } else if (mouseY>=400 & mouseY<500) {
        background(52,82,102);
        stormSize=5;
    } else {
        background(43,63,81);
        stormSize=6;
    }

    //as the mouse moves left and right, the wind blows
    push();
    rotate(-radians(mouseX/50));

    //as the mouse moves down, the rain gets heavier
    fill(90,195,255);
    rect(width/2,rainPos,5+mouseY/50,25+mouseY/20,80,80,80,80);
    rect(width/2+25,rainPos+50,5+mouseY/50,25+mouseY/20,80,80,80,80);
    rect(width/2+50,rainPos+250,5+mouseY/50,25+mouseY/20,80,80,80,80);
    rect(width/2+75,rainPos+150,5+mouseY/50,25+mouseY/20,80,80,80,80);
    rect(width/2+100,rainPos+75,5+mouseY/50,25+mouseY/20,80,80,80,80);
    rect(width/2-25,rainPos+100,5+mouseY/50,25+mouseY/20,80,80,80,80);
    rect(width/2-50,rainPos-5,5+mouseY/50,25+mouseY/20,80,80,80,80);
    rect(width/2-75,rainPos+200,5+mouseY/50,25+mouseY/20,80,80,80,80);
    rect(width/2-100,rainPos+75,5+mouseY/50,25+mouseY/20,80,80,80,80);
    if (stormSize==1) {
        rainPos=rainPos;
        rainV=3;
    } else if (stormSize==2) {
        rainPos=rainPos;
        rainV=5;
    } else if (stormSize==3) {
        rainPos=rainPos;
        rainV=6.5;
    } else if (stormSize==4) {
        rainPos=rainPos;
        rainV=7;
    } else if (stormSize==5) {
        rainPos=rainPos;
        rainV=8.25;
    } else if (stormSize==6) {
        rainPos=rainPos;
        rainV=9.5;
    }
    rainPos += rainV;
    if (rainPos>height+100) {
        rainPos=200;
    }

    //as the mouse moves down, the cloud gets smaller and darker
    pop();
    if (stormSize==1) {
        fill(207,215,218);
    } else if (stormSize==2) {
        fill(170,180,184);
    } else if (stormSize==3) {
        fill(137,154,162);
    } else if (stormSize==4) {
        fill(128,144,151);
    } else if (stormSize==5) {
        fill(104,118,124);
    } else if (stormSize==6) {
        fill(96,105,109);
    }
    ellipse((width/2)+25,(110+mouseY/50),(150-mouseY/10));
    rect(width/2,160,(300-mouseY/10),(100-mouseY/20),80,80,80,80);
    ellipse((width/2)-50,(125+mouseY/50),(100-mouseY/30));
    ellipse((width/2)-20,130,50+mouseY/20);
    ellipse((width/2)+60,140,40+mouseY/20);

    //when the rain is hard and the mouse is clicked, lightening strikes
    if (mouseIsPressed) {
        if (stormSize==5 || stormSize==6) {
        stroke(260);
        strokeWeight(10);
        line(225,200,125,350);
        line(125,350,250,400);
        line(250,400,200,710);
        }
    }
}

When thinking of things to make, I started by thinking about natural processes. I love watching the rain and how varied rain occurs, so I decided to move with that. I knew I wanted the rain to get bigger as the mouse moved down, along with the sky and cloud growing darker to simulate heavier rain. I also knew I wanted to include lighting on a click – just because lighting is fun. I think I went in with a clear idea in mind of what I wanted, so at that point it was just writing the program.

LO: Computational Fabrication

An exhibit of all four of Bernard’s Mounds pieces

Mounds, Colette Bernard, 2021

While scrolling through Instagram a couple months ago, I came across a video of artist Colette Bernard talking about experimenting with her art: 3D-printing ceramic. Bernard’s meta-forms rely upon the usual layer method of CNC 3D printing, but using clay instead of filament. It was a long process of what state to have the clay at (dry vs. wet, how large does the “filament” line have to be, ect.), but eventually she was able to print moldable ceramic. What I find most interesting about the work is the intersection between the human and the algorithmic components. Bernard mentions that she did use 3D modeling software to initially design her sculptures, but doesn’t talk further about her algorithm. Although a couple of her sculptures rely solely upon her algorithm, sometimes Bernard manually turns the printing plate during the printing process. I think this interplay between man and machine is very intriguing and brings up interesting questions about where “Colette’s” art begins and “machine production” ends. It’s almost as if the computer algorithm has taken life of its own and is participating with Bernard in creating her structures.

LO: Generative Art

3D rendering of a Meander map

Meander, Robert Hodgin, May 2020

While looking through the generative artwork, I was very drawn to Meander by Robert Hodgin. This is a project about generating “historical maps of rivers that never existed”. The work is very aesthetically pleasing as well as interesting from a generation perspective. The rivers are generated, but so are the historical remnants of the river, the “local” geography, the roads, settlements, and even the names on the top of the maps. Hodgin does not talk in depth about the techniques he uses to produce the river maps, but does mention a potential spline technique moving forward with this project. He does, however, show the results of different potential generation patterns and the process of creating the current generational code. The final result has beautiful colors and intriguing patterns, an artwork in every right.

Project 2: Variable Faces

chapmanGenerativeFaces

//Elise Chapman
//ejchapma@andrew.cmu.edu
//Section D

function setup() {
    createCanvas(400, 500);
}

/* variables: skin color, head width, head height, 
eye size eye color, nose, skin color, 
eyebrows, eyebrow color, mouth, ear size */
/* non-variables: eye-spacing, eyebrow height */
var hWidth;
var hHeight;
var skin;
var eyeSize;
var eyeColor;
var noseY;
var earX;
var earY;
var eyebrows;
var eyebrowsY;
var txtY = 250;

function mousePressed() {
    hWidth = int(random(100,200));
    hHeight = int(random(150,225));
    skin = int(random(1,8));
    eyeSize = int(random(20,40));
    eyeSize2 = int(random(20,40));
    eyeColor = int(random(1,7));
    nose = int(random(1,5));
    noseY = int(random(270,300));
    earX = int(random(30,50));
    earY = int(random(40,70));
    eyebrows = int(random(1,7));
    eyebrowsY = random((height/2)-0.1*hHeight,(height/2)-0.27*hHeight)
    txtY = 800;
}

function draw() {
    background(101,222,241);
    //intro text
    fill(300);
    stroke(20);
    loadFont("Courier New");
    strokeWeight(5);
    textSize(18);
    textFont("Courier New");
    text("Dad Generator: Click to begin.",40,txtY);
    noStroke();
    //skin color
    var alien;
    if (skin==1) {
        fill(197,149,123);
    } else if (skin==2) {
        fill(236,188,180);
    } else if (skin==3) {
        fill(290,201,164);
    } else if (skin==4) {
        fill(161,102,94);
    } else if (skin==5) {
        fill(80,51,53);
    } else if (skin==6) {
        fill(89,47,42);
    } else {
        fill(187,219,155);
        var alien="true";
    }
    //head
    ellipse(200,250, hWidth,hHeight);
    //ears
    if (alien=="true") {
        rect((width/2)-(hWidth/2)-(earX/1.25),height/2.25,earX,earY,0,80,80,80);
        rect((width/2)+(hWidth/2.75)+(earX/4),height/2.25,earX,earY,80,0,80,80);
    } else {
        rect((width/2)-(hWidth/2)-(earX/1.25),height/2.25,earX,earY,80,80,80,80);
        rect((width/2)+(hWidth/2.75)+(earX/4),height/2.25,earX,earY,80,80,80,80);
    }
    //nose
    if (skin==1) {
        fill(161,103,68);
    } else if (skin==2) {
        fill(200,136,120);
    } else if (skin==3) {
        fill(206,132,95);
    } else if (skin==4) {
        fill(105,49,29);
    } else if (skin==5) {
        fill(43,24,23);
    } else if (skin==6) {
        fill(38,19,10);
    } else {
        fill(105,122,33);
        var alien="true";
    }
    triangle(width/2,height/2,(width/2)+10,noseY,(width/2)-10,noseY);
    //eyes
    var eyeLX=200-hWidth*0.25;
    var eyeRX=200+hWidth*0.25;
    fill(300); //white
    ellipse(eyeLX, 250, eyeSize, eyeSize);
    ellipse(eyeRX, 250, eyeSize, eyeSize);
    if (eyeColor==1) {
        fill(138,203,136);
    } else if (eyeColor==2) {
        fill(198,224,255);
    } else if (eyeColor==3) {
        fill(58,124,165);
    } else if (eyeColor==4) {
        fill(22,38,46);
    } else {
        fill(58,51,53);
    }
    var pupilRX=200-hWidth*0.25
    var pupilLX=200+hWidth*0.25
    ellipse(pupilRX, 250, eyeSize/1.25, eyeSize/1.25);
    ellipse(pupilLX, 250, eyeSize/1.25, eyeSize/1.25);
    //eyebrows
    fill(30);
    if (eyebrows==1) {
        rect(eyeLX-(eyeSize/2),eyebrowsY,40,10);
        rect(eyeRX-(eyeSize/2),eyebrowsY,40,10);
    } else if (eyebrows==2) {
        rect(eyeLX-(eyeSize/2),eyebrowsY,30,20);
        rect(eyeRX-(eyeSize/2),eyebrowsY,30,20);
    } else if (eyebrows==3) {
        rect(eyeLX-(eyeSize/2),eyebrowsY,40,5);
        rect(eyeRX-(eyeSize/2),eyebrowsY,40,5);
    } else if (eyebrows==4) {
        rect(eyeLX-(eyeSize/2),eyebrowsY,30,10);
        rect(eyeRX-(eyeSize/2),eyebrowsY,30,10);
    } else if (eyebrows==5) {
        rect(eyeLX-(eyeSize/2),eyebrowsY,40,2);
        rect(eyeRX-(eyeSize/2),eyebrowsY,40,2);
    } else if (eyebrows==6) {
        rect(eyeLX-(eyeSize/2),eyebrowsY,40,20);
        rect(eyeRX-(eyeSize/2),eyebrowsY,40,20);
    }
}

Project 1: My Self Portait

chapman_SelfPortrait

function setup() {
    createCanvas(500,600);
    background(195,159,220);
}

function draw() {
    noLoop();
    noStroke();
    
    //hair back
    fill(90,39,14);     //brown
    ellipse(140,180,80);
    ellipse(360,180,80);
    ellipse(130,220,90);
    ellipse(370,220,90);
    fill(255,193,87);   //blonde
    rect(150,100,200,400,80,80,80,80);
    rect(130,150,35,400,80,80,80,80);
    rect(335,150,35,400,80,80,80,80);    
    
    //body
    fill(21,13,3);
    rect(137.5,400,225,300,80,80,80,80);

    //shoulder hair
    fill(90,39,14);
    rect(110,140,50,390,80,80,80,80);
    rect(340,140,50,390,80,80,80,80);
    rect(85,200,50,310,80,80,80,80);
    rect(365,200,50,310,80,80,80,80);
    rect(75,260,50,210,80,80,80,80);    //outermost hair
    rect(65,310,50,160,80,80,80,80);
    rect(375,260,50,210,80,80,80,80);   //outermost hair
    rect(385,310,50,160,80,80,80,80);
    //hair strands
    fill(255,193,87);
    rect(185,300,35,175,80,80,80,80);
    rect(285,300,35,175,80,80,80,80);

     //head
    fill(255,211,155);
    rect(150,100,200,250,80,80,80,80);
    rect(227.5,300,50,100,20,20,80,80); //neck 
    fill(225,162,0);
    rect(215,370,75,75,20,20,80,80);
    fill(21,13,3); 
    rect(215,360,75,75,20,20,80,80);   //turtleneck

    //hair front
    fill(90,39,14);
    rect(150,100,200,50,80,80,80,80);   //top hair
    rect(165,90,90,50,80,20,20,80);    //partL
    rect(250,90,90,50,20,80,80,20);    //partR
    rect(145,110,25,125,80,80,80,80);    //sideburnsL
    rect(330,110,25,125,80,80,80,80);    //sideburnsL
    rect(120,110,125,75,150,80,150,80);    //bangsL
    ellipse(170,125,50);
    rect(260,110,125,75,150,80,150,80);    //bangsR
    ellipse(330,125,50);

    //ears
    fill(255,211,155);
    rect(120,200,45,75,80,80,80,80);
    rect(340,200,45,75,80,80,80,80);
    //earrings
    fill(225,162,0);
    rect(135,260,10,40,80,80,80,80);
    rect(360,260,10,40,80,80,80,80);

    //eyes
    fill(45,139,81);
    ellipse(210,240,30);
    ellipse(290,240,30);

    //blush
    fill(255,146,146,90);
    ellipse(185,280,80);
    ellipse(315,280,80);

    //glasses
    strokeWeight(5);
    stroke(160,160,160)
    fill(300,300,300,70)
    ellipse(200,240,70);
    ellipse(300,240,70);
    line(235,240,265,240);

    //smile
    noStroke();
    fill(255,146,146);
    ellipse(250,275,30);
    fill(255,211,155);
    rect(235,260,30,15);
}


/*'Thank you to Michelle Dang for helping me with the
rounded rectangle corners, guiding the style for the
portait.*/
//black (21,13,3)
//brown hair (90,39,14)
//blonde hair (255,193,87)
//skin (255,211,155)
//eyes (45,139,81)
//glasses (220,220,220)
//purple bkg (195,159,220)
//gold (225,162,0)
//blush (255,146,146)

I found it most challenging to correctly place all “strands” of my hair.