Hannah Cai—Looking Outwards—07

https://www.creativeapplications.net/vvvv/melting-memories-drawing-neural-mechanisms-of-cognitive-control/

This project by Refik Anadol Studio caught my eye because it’s so beautiful and haunting—it really looks like something from a sci-fi movie. In reality, it’s a visualization of brain wave activity of participants who were asked to recall specific childhood memories. These memories weren’t mentioned; I’m really curious what they were. Even without that information though, the project still gives off a really nostalgic feeling.

I didn’t really understand the technical details behind the visualization, but the designer(s) seemed to have taken EEG data and input it into algorithms for 3d structures. While the concept behind that is really neat, I feel like the actual structures created would be very subjective based on the algorithm used, and I wish there was more context about the how one was translated into the other. I feel like this type of visualization has a lot of potential in research and education; I’d love to see a more concrete approach used to describe brain activity—for example, what different emotions look like, brain activity mapped to height of data points, etc. However, I do still think the end result of this project is really beautiful and innovative on its own.

Hannah Cai—Project 07—Curves

(click to reset.)

/* Hannah Cai
Section C
hycai@andrew.cmu.edu
Project-07-Curves
*/


var ra = 50; //radius of base circle
var rb = 10; //radius of revolving perimeter circle
var h = 0; //height of curve from the center of rb
var t; //time
var o; //opacity of background
var x;
var y;
var v; //velocity


function setup() {
    createCanvas(480,480);
    background(0);
    stroke(255);
    strokeWeight(1);
    frameRate(30); //.5x animation
}

function draw() {
    o = map(mouseY, 0, height, 100, 25); //maps mouseY to background opacity
    mouseY = constrain(mouseY, 0, height); //constrains mouseY to canvas
    background(0, o);
    v = map(mouseX, 0, width, 1, -1); //maps velocity of ra and h to mouseX 
    ra += v; 
    h += v;

    for (t = 0; t < TWO_PI; t += .01) { 
        push();
        translate(width / 2, height / 2); //moves origin to center
        //epitrochoid equation
        x = (ra + rb) * cos(t) - h * cos(((ra + rb) / rb) * t); 
        y = (ra + rb) * sin(t) - h * sin(((ra + rb) / rb) * t);
        point(x, y); //draws points on the curve
        pop();
    }
}

//resets animation when mouse is clicked
function mouseClicked() {
    ra = 50;
    h = 0;
    t = 0;
}


inverted
starting point
opening
expanding
expanded (mouse in center)
expanded (mouse in bottom left or right)

For my project, I chose the epitrochoid:

When writing the code for it, I felt more interested by the particle patterns formed by the curve rather than the curve itself, so I chose to focus on those. While I didn’t enjoy the math involved (there were some really interesting/beautiful curves that I wanted to try creating, but just couldn’t understand), I do think it’s cool that you can basically plug equations straight into code and generate visual effects with them. Overall, I enjoyed the project.

Hannah Cai—Looking Outwards-06

This simulation, created with Processing, utilizes randomness in simulating evolution. In each “generation,” 1000 creatures are created and the 500 that “walk” the furthest distance forward survive; new creatures are generated based on the survivors, and so on. I thought this was a fun and interesting application of randomness. Some of the early creatures are really derpy and funny, which is cute. But the really cool thing is seeing how much the creatures adapt after a couple of generations, and how certain “species” eventually dominate, ending up with one best optimized model. Since randomness is inherent in many parts of our everyday lives, it makes sense that randomness in computation, especially in experiments like this, can be very useful. I can see this type of prototyping being used in developing robot motion, finding the most aerodynamic shape for a plane, etc.

Hannah Cai—Project 06—Abstract Clock

/* Hannah Cai
Section C
hycai@andrew.cmu.edu
Project-06-Abstract Clock
*/

function setup() {
    createCanvas(480,480);
    background(255);
}

function draw() {
    //background
    //wall
    noStroke();
    fill(222, 255, 251);
    rect(0, 0, 480, 420);
    //table
    fill(255, 192, 224);
    rect(0, 380, 480, 90);

    //tv
    //antennae base
    fill(0);
    ellipse(233, 165, 40, 40); 
    //antennae
    stroke(0);
    strokeWeight(2);
    line(185, 35, 220, 150); 
    line(285, 35, 245, 150); 
    //antennae tips
    strokeWeight(5);
    point(185, 35); 
    point(285, 35); 
    //feet
    noStroke();
    fill(255);
    rect(115, 408, 20, 10, 0, 0, 3, 3); 
    rect(340, 408, 20, 10, 0, 0, 3, 3); 
    //base
    fill(40);
    rect(104, 398, 265, 10); 
    //body
    rect(66, 165, 345, 233, 13, 13, 25, 25); 
    fill(0);
    rect(76, 172, 325, 220, 13, 13, 25, 25);
    //screen
    noStroke();
    fill("White");
    rect(108, 213, 192, 138, 25, 25, 28, 28); 
    //control bar
    fill(80);
    rect(327, 185, 45, 190, 3, 3, 3, 3); 
    fill(0);
    rect(329.5, 269, 40, 11);
    rect(329.5, 283, 40, 90);
    //knob 1
    fill(0);
    ellipse(350, 207, 36, 36);
    fill(80);
    ellipse(350, 207, 12, 12); 
    stroke(0);
    strokeWeight(2);
    line(350, 188, 350, 220);
    //knob 2
    fill(0);
    ellipse(350, 247, 30, 30);
    fill(80);
    ellipse(350, 247, 8, 8);
    line(350, 230, 350, 233);
    //other knobs
    fill(40);
    ellipse(387, 196, 14, 14);
    ellipse(387, 216, 11, 11);
    noFill();
    stroke(255);
    strokeWeight(1);
    ellipse(387, 271, 8, 8);
    ellipse(387, 312, 8, 8);
    ellipse(387, 354, 8, 8);

    //time variables
    // var H = hour();
    // var M = minute();
    // var S = second();
    var H = hour();
    var M = minute();
    var S = second();
    //maps time to screen width
    var mappedH = map(H, 0, 24, 0, 192);
    var mappedM = map(M, 0, 60, 0, 192);
    var mappedS = map(S, 0, 60, 0, 192);
    //color blocks
    push();
    blendMode(DIFFERENCE); //overlays the screen colors
    noStroke();
    fill("Red");
    rect(108, 213, mappedH, 138);
    fill("Green");
    rect(108, 213, mappedM, 138);
    fill("Blue");
    rect(108, 213, mappedS, 138);
    pop();

    //screen border
    noFill();
    stroke(0);
    strokeWeight(20);
    rect(98, 205, 212, 153, 32, 32, 38, 38); 
    stroke(40);
    strokeWeight(2);
    rect(90, 200, 227, 163, 4, 4, 7, 7);

}


For this project, I was initially planning to just have a simple square with overlaid colors, but while writing that code, I was reminded of old tvs, especially those with glitched screens:

I was inspired by that idea, so I sketched up a tv in Illustrator, put it into p5, and then modified my code so that the colors would fit to the screen.

The color layers are red, blue, and green (RBG) under the blend mode “difference,” so as they overlap and interact with each other, the screen’s color palette changes. The colors on the screen do not change only by the minute, but also by the time of day (based on the position of the hours, minutes, and seconds layers in relationship to each other).

Hannah Cai—Looking Outwards—05

This music video for Damon Albarn’s (you might know him from the Gorillaz) song “Everyday Robots” is actually a sculpture video. I don’t know the actual software being used for it, but I really love the way the music and the video go together, even through some unexpected moments. Focusing on the 3D graphics portion of this prompt though, it’s really amazing how detailed the skull is, as well as how realistic you can get with the final sculpture, including lighting effects. In theory, it makes sense for 3D graphics to be easy to compute—instead of just having x and y, there’s just another axis added on. But I never understood textures, lighting, and basically everything else that make 3D graphics look realistic. If I had to guess how those things were programmed, I’d guess that textures might be able to be implemented with for loops and randomization, and lighting could be some kind of vector with a gradient, but I really don’t know. I know there are lighting and texture functions in p5 as well; now that my curiosity has been piqued, I might do some research into how and why those functions work.

Hannah Cai—Project 05—Wallpaper

/* Hannah Cai
Section C
hycai@andrew.cmu.edu
Project-05-Wallpaper
*/

var x;
var y;
var x1;
var y1;
var x2;
var y2;
var x3;
var y3;
var x4;
var y4;

function setup() {
    createCanvas(480, 480);
    background(250);
}

function draw() {
    noLoop();
    smooth();
    angleMode(DEGREES);
    scale(1);
    translate(-90, 90);
    //dot grid
    for (x = 20; x < 1000; x += 50) {
        for (y = -99; y < 5000; y += 50) {
            stroke(0); 
            strokeWeight(1);
            point(x, y);
        }
    }

//yellow leaf
    for (x2 = 80; x2 < 2000; x2 += 320) {
        for (y2 = 70; y2 < 5000; y2 += 200) {
            //leaf
            fill(239, 211, 94);
            noStroke();
            push();
            translate(x2, y2 - 115);
            rotate(45);
            rect(0, 0, 55, 55, 15, 75, 0, 75);
            pop();
            //spot1
            stroke(192, 119, 50); 
            strokeWeight(5);
            point(x2 - 10, y2 - 85);
            //spot 2
            strokeWeight(2);
            point(x2 + 10, y2 - 73);
            //spot 3
            point(x2 - 12, y2 - 55);
            //stem
            strokeWeight(1);
            line(x2, y2 - 108, x2, y2 - 10);
        }
    }

//purple leaves
    for (x4 = 160; x4 < 1000; x4 += 320) {
        for (y4 = -90; y4 < 5000; y4 += 200) {
            //leaf 1
            noStroke();
            fill(149, 84, 90);
            ellipse(x4 + 0.5, y4 - 90, 12, 22); 
            //right leaves/branches
            for (i = 0; i < 3; i ++) {
                push();
                noStroke();
                translate(x4 + 9, y4 - (80 - 25 * i));
                rotate(45);
                ellipse(0, 0, 12, 22); 
                pop();
                stroke(89, 37, 37); 
                strokeWeight(1);
                line(x4, y4 - (72 - 25 * i), x4 + 15, y4 - (88 - 25 * i));
            }
            //left leaves/branches
            for (i = 0; i < 3; i ++) {
                push();
                noStroke();
                translate(x4 - 8, y4 - (80 - 25 * i));
                rotate(-45);
                ellipse(0, 0, 12, 22); 
                pop();
                line(x4, y4 - (72 - 25 * i), x4 - 15, y4 - (88 - 25 * i));
            }
            //stem
            line(x4, y4 - 100, x4, y4);
            //spot 1
            stroke(239, 211, 94); 
            strokeWeight(1);
            point(x4 + 13, y4 - 80);
            //spot 2
            point(x4 - 6, y4 - 33);
        }
    }

    //green leaves
    for (x1 = 250; x1 < 1000; x1 += 320) {
        for (y1 = -240; y1 < 5000; y1 += 200) {
            //leaf 1
            fill(159, 193, 64);
            noStroke();
            ellipse(x1, y1 - 75, 8, 52); 
            //leaf 2
            push();
            translate(x1 + 17, y1 - 60);
            rotate(208);
            ellipse(0, 0, 5, 35); 
            pop();
            //leaf 3
            push();
            translate(x1 - 18, y1 - 50);
            rotate(337);
            ellipse(0, 0, 4, 35); 
            pop();
            //branch for leaf 2
            stroke(104, 140, 27); 
            strokeWeight(1);
            line(x1, y1 - 30, x1 + 25, y1 - 75);
            //branch for leaf 3
            line(x1, y1 - 10, x1 - 25, y1 - 65);
            //stem
            line(x1, y1 - 100, x1, y1);
        }
    }

//purple flowers
    for (x3 = 330; x3 < 5000; x3 += 390) {
        for (y3 = -260; y3 < 5000; y3 += 200) {
            //stem
            stroke(159, 193, 64); 
            line(x3, y3 - 108, x3, y3);
            //flower 1
            fill(250, 204, 255);
            noStroke();
            ellipse(x3, y3 - 108, 5);
            ellipse(x3 - 2.5, y3 - 105.5, 5);
            ellipse(x3 + 2.5, y3 - 105.5, 5);
            ellipse(x3, y3 - 103, 5);
            //flower 1 center
            push();
            fill(149, 84, 90);
            rect(x3 - 0.5, y3 - 106, 1, 1);
            //flower 2
            x3 -= 2;
            y3 += 7;
            fill(250, 204, 255);
            ellipse(x3, y3 - 108, 5);
            ellipse(x3 - 2.5, y3 - 105.5, 5);
            ellipse(x3 + 2.5, y3 - 105.5, 5);
            ellipse(x3, y3 - 103, 5);
            //flower 2 center
            fill(149, 84, 90);
            rect(x3 - 0.5, y3 - 106, 1, 1);
            //flower 3
            x3 += 6;
            y3 += 7;
            fill(250, 204, 255);
            ellipse(x3, y3 - 108, 5);
            ellipse(x3 - 2.5, y3 - 105.5, 5);
            ellipse(x3 + 2.5, y3 - 105.5, 5);
            ellipse(x3, y3 - 103, 5);
            //flower 3 center
            fill(149, 84, 90);
            rect(x3 - 0.5, y3 - 106, 1, 1);
            //flower 4
            x3 -= 7;
            y3 += 5;
            fill(250, 204, 255);
            ellipse(x3, y3 - 108, 5);
            ellipse(x3 - 2.5, y3 - 105.5, 5);
            ellipse(x3 + 2.5, y3 - 105.5, 5);
            ellipse(x3, y3 - 103, 5);
            //flower 4 center
            fill(149, 84, 90);
            rect(x3 - 0.5, y3 - 106, 1, 1);
            //flower 5
            x3 += 8;
            y3 += 8;
            fill(250, 204, 255);
            ellipse(x3, y3 - 108, 5);
            ellipse(x3 - 2.5, y3 - 105.5, 5);
            ellipse(x3 + 2.5, y3 - 105.5, 5);
            ellipse(x3, y3 - 103, 5);
            //flower 5 center
            fill(149, 84, 90);
            rect(x3 - 0.5, y3 - 106, 1, 1);
            //flower 6
            x3 -= 8;
            y3 += 6;
            fill(250, 204, 255);
            ellipse(x3, y3 - 108, 5);
            ellipse(x3 - 2.5, y3 - 105.5, 5);
            ellipse(x3 + 2.5, y3 - 105.5, 5);
            ellipse(x3, y3 - 103, 5);
            //flower 6 center
            fill(149, 84, 90);
            rect(x3 - 0.5, y3 - 106, 1, 1);
            pop();
            //leaves
            fill(149, 84, 90);
            push();
            translate(x3 + 7, y3 - 90);
            rotate(-45);
            ellipse(0, 0, 10, 3);
            pop();
            push();
            fill(149, 84, 90);
            translate(x3, y3 - 90);
            rotate(45);
            ellipse(0, 0, 10, 3);
            pop();
        }
    }
    noLoop();
}



I knew I wanted to do something with plants for this project, so I made a few sketches in Illustrator:

plant #1
plant #2
plant #3
plant #4

I then sketched how I generally wanted the different designs to piece together:

Figuring out how to orient everything on the canvas was the hardest and most time-consuming part, but I feel like it got me a lot more comfortable with for loops and spacing.

Hannah Cai—Looking Outwards—04

Imogen Heap demonstrating her mi.mu gloves

Mi.mu

While looking for stuff on youtube, I came across this video. It caught my eye because I’m a fan of Imogen Heap, and I have to say that after watching this, I’ve become an even bigger fan of her. Using these “mi.mu” gloves developed by Imogen Heap, a person can basically generate music with a flick of the wrist. I’d love to see a dancer wearing them, composing music from choreography, rather than choreographing to music.

The gloves connect to her computer, and change the sound produced based on factors such as position in space, pressure, hand position, etc. Altering the filter and other details basically makes for real-time generated sound. The computational part is deciding how all the variables would influence the sound that’s generated; how pitch, range, and other factors are mapped to 3d space. Since Imogen Heap usually works a lot with free-flowing, unstructured electronic music (check out her song “you know where to find me”), her characteristic style is present in her use of these gloves, and the two really mesh well and augment each other. I know that a few other artists have used these gloves for performances as well (including Ariana Grande), but I doubt that their music would really benefit as much from these gloves as Imogen’s does, due to stylistic differences. All in all, I’m really impressed with how Imogen Heap created what’s basically an amazing instrument of her own, and how she’s using it to enhance and showcase her already distinctive approach to music.

Hannah Cai—Project 4—String Art

/* Hannah Cai
Section C
hycai@andrew.cmu.edu
Project-04-String Art
*/

var x1 = 100;
var y1 = 50;
var x2 = 300;
var y2 = 250;
var t = 25;


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

function draw() {
    frameRate(40); //slowed down speed
    background(0,5); //translucent background
    stroke(255);
    strokeWeight(.3);

    //dotted square frame
    for (i = 100; i <= 300; i += 5) {
        point(i,50);
        point(i,250);
    }
    for (i = 50; i <= 250; i += 5) {
        point(100,i);
        point(300,i);
    }

    // bottom left and top right corner curves
    line(x1,250,100,y1);
    line(300,height - y1,width - x1,50);
    line(width - x1,250,100,height - y1);
    line(300,y1,x1,50);

    // top left and bottom right corner curves
    line(100,y2,x1,50);
    line(300,height - y2,width - x1,250);

    //string animation
    x1 += .5;
    y1 += .5;
    x2 -= .5;
    y2 -= .5;

    //constrain movement within square
    x1 = constrain(x1,100,300);
    y1 = constrain(y1,50,250);
    x2 = constrain(x2,100,300);
    y2 = constrain(y2,50,250);

    //resets string animation when it hits the square's sides
    if (x1 == 300 & y1 == 250 && x2 == 100 && y2 == 50) {
        x1 = x2;
        y1 = y2;
        y2 = 250;
    }
}

sketches/notes

Since this project required four curves, I focused on drawing those curves, and this animation sort of evolved from that process. It took a while for me to figure out how to make curves, and for me to figure out the math for each curve. I know that we were supposed to use for() loops for our strings, but I found using if() made more sense for all the different curves, since there were quite a few different parameters. I’ll probably edit my code to use for() loops instead of if() for the string code as a challenge for myself sometime in the future.

Hannah Cai—Looking Outwards—03

3D-printed shells
close-up
example pattern 1
example pattern 2

fdecomite on flickr’s work caught my eye, first because the shells seemed so realistic, and secondly because all the computation and experimentation that had to have gone into the this level of biomimicry is extremely impressive. Imagining going back to the spiral exercise we did in lab last week and creating a 3d plane out of it blows my mind. Although there weren’t any details provided for the reasons behind this project (I suspect it was just done out of curiosity/for fun), I can easily see how this kind of prototyping would be useful in scientific research. The possibility of adding a variation aspect, like we did in project 2, basically means that an infinite amount of shell models could be created, and the addition of 3d printing using calcium or other more realistic materials would provide an quick and environmentally friendly way of studying, for example, how calcium in seashells is affected by rising levels of acidity in the ocean.

Hannah Cai—Project 3—Dynamic Drawing

/* Hannah Cai
Section C
hycai@andrew.cmu.edu
Project-03-Dynamic Drawing
*/

var R = 211; //sky color variables
var G = 239;
var B = 252;
angleSun = 0; //sun and moon rotation angles
angleMoon = 0;
cloudColor = 250; 
cloudX = 0;
var dimness = 0;

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

function draw() {
  scale(.9375);
  rectMode(CORNER); 
  var cmouseX = constrain(mouseX,0,600); //constrains mouseX to canvas
  // sky
  background(R,G,B);
  // stars
  fill(211,239,252);
  strokeWeight(1);
  stroke(211,239,252);
  point(386,153);
  point(360,200);
  point(266,225);
  point(395,355);
  // sun
  push();
  noStroke();
  fill(255,247,215);
  ellipseMode(CENTER);
  translate(675,500);
  angleMode(DEGREES);
  rotate(angleSun); //rotates the sun
  ellipse(-390,-300,10,10); //relative to translated origin
  pop();
  // moon
  push();
  noStroke();
  fill(250);
  ellipseMode(CENTER);
  translate(675,500);
  angleMode(DEGREES);
  rotate(angleMoon); //rotates the moon
  ellipse(-390,-300,10,10); //relative to translated origin
  fill(R,G,B); //fills with sky color
  ellipse(-389,-301,10,10); //second circle that forms the moon
  pop();
  // clouds
  noStroke();
  fill(cloudColor);
  rect(286 + cloudX,226,54,17,10);
  rect(306 + cloudX,236,55,17,10);
  rect(242 + cloudX,265,91,17,10);
  rect(215 + cloudX,275,73,17,10);
  rect(353 + cloudX,305,67,17,10);
  rect(338 + cloudX,314,58,17,10);
  rect(150 + cloudX,340,70,17,10);
  rect(150 + cloudX,350,40,17,10);
  //wall
  fill(255 - dimness,232 - dimness,204 - dimness);
  rect(440,0,200,480);
  rect(165,0,310,80);
  rect(0,0,200,480);
  rect(180,400,310,80);
  //window shadow
  noFill();
  stroke(244 - dimness,216 - dimness,216 - dimness);
  strokeWeight(30);
  rect(206,80,250,335); //big frame
  strokeWeight(10);
  line(204,134,444,134); //horizontal part of 'T'
  line(324,134,324,389); //vertical part of 'T'
  //window frame
  stroke(255 - dimness);
  strokeWeight(30);
  rect(200,60,250,335); //big frame
  strokeWeight(10);
  line(200,130,440,130); //horizontal part of 'T'
  line(320,130,320,385); //vertical part of 'T'
  //shades
  noStroke();
  fill(255 - dimness,232 - dimness,204 - dimness);
  rect(200,70,250,5); 
  rect(200,80,250,5);
  rect(200,90,250,5);
  rect(200,100,250,5);
  rect(200,110,250,5);
  stroke(255 - dimness,232 - dimness,204 - dimness)
  strokeWeight(1);
  line(266,70,266,110); //hanging lines
  line(377,70,377,110);
  strokeWeight(1);
  line(425,70,425,351); //pull line
  rectMode(CENTER);
  rect(425,350,2,8,2,2,0,0); //pull line handle
  stroke(250 - dimness);
  strokeWeight(3);
  line(230,60,230,260); //rod

  //changes based on mouseX's position on the canvas 
  R = ((527.5 - mouseX) / 2.5); 
  G = ((597.5 - mouseX) / 2.5);
  B = ((630 - mouseX) / 2.5); //lighter/darker sky color
  angleSun = ((0 - mouseX) / 10);
  angleMoon = ((cmouseX - 600) / 10);
  cloudColor = ((775 - cmouseX) / 3); //lighter/darker
  cloudX = ((640 - cmouseX) / 12); //horizontal shift
  dimness = ((25 + cmouseX) / 25);
}

my actual window
sketches/notes
day
night

Like many other people, I struggled with starting this project because it’s so open-ended. I initially wanted to do something abstract, but after a few experiments, I decided to just stick with imagery that I was familiar with. This sketch was based on my dorm’s window. I wanted to show the passage of time by having the sun and moon rotate, as well as having the sky change color. Both of those variables ended up being challenging to manipulate in a way that would look realistic, but still keep them relative to the mouse; I ended up doing a lot more math than I liked, but I figured it out in the end. I realize now that I could’ve used map() rather than doing so much math, similar to the second project, where I did rotations and shears the longer way rather than using push() and pop(), which I hadn’t known about yet. Oh well…

I also wanted to add an interaction where you could click the canvas to turn a light on and off, but after I figured out how to make it work, I didn’t like the effect (it looked weird during the daytime). So I instead just mapped the room to change brightness with the mouse’s movement as well, which also made the passage of time more convincing.

(note: I scaled down my sketch so it wouldn’t get cropped.)