lee chu – project 07 – curves

lrchu

// lee chu
// section c
// lrchu@andrew.cmu.edu
// project - 07

// variables for equation
var angle;
var t;
var x;
var y;
var xx;
var yy;

// characteristics of shapes
var sizes = [];
var size;
var ct;
var step;

// color
var r;
var g;
var b;

function setup() {
    createCanvas(480, 300);
    noFill();
    strokeWeight(0);
    angle = 0;
    t = 20;

    // create sizing for layers
    for (h = 0; h < 60; h ++) {
        sizes.push(h * 3);
    }
    size = 20;
    ct = 200;

    // color control
    r = 36;
    g = 33;
    b = 40;
    step = 5;
}

function draw() {
    background(r, g, b);

    // change turn direction and rate
    if (mouseX < width / 2 & mouseX > 0 && mouseY < height && mouseY > 0) {
        angle -= (width / 2 - constrain(mouseX, 0, width / 2)) / width / 2 / 6;
    }
    if (mouseX > width / 2 & mouseX < width && mouseY < height && mouseY > 0) {
        angle += (constrain(mouseX, width/2, width) - width / 2) / width / 2 / 6;
    }

    // generate shapes
    for (j = 0; j < sizes.length; j ++) {
        cata(sizes[sizes.length - j]);
        r = (r + step * (j + 1)) % 255;
        g = (g + step * (j + 1)) % 255;
        b = (b + step * (j + 1)) % 255;
    }
    deltoid(sizes[1]);
}

function cata(size) {
    fill(r, g, b);
    push();
    translate(width / 2, height / 2);
    beginShape();
    for (i = 0; i < ct; i ++) {
        t = map(i, 0, ct, 0, 2 * PI);
        xx = 3 * cos(t) + cos(3 * t + 2 * angle) - cos(2 * angle);
        yy = - 3 * sin(t) + sin(3 * t + 2 * angle) - sin(2 * angle);
        vertex(xx * size, yy * size);
    }
    endShape();
    pop();
}

function deltoid(sizeD) {
    fill('black');
    push();
    translate(width / 2, height / 2);
    beginShape();
    for (i = 0; i < ct; i ++) {
        t = map(i, 0, ct, 0, 2 * PI);
        x = 2 * cos(t) + cos(2 * t);
        y = -2 * sin(t) + sin(2 * t);
        vertex(x * sizeD, y * sizeD);
    }
    endShape();
    pop();
}

I was intrigued by the deltoid catacaustic, which consists of the deltoid, a triangle bowing in, and the catacaustic which circumscribes the deltoid as it rotates around its axis. The center of all the layers of the catacaustic is the black deltoid in the middle of the canvas.

lee chu – looking outwards 06


one of many real-time generations

Matt Deslauriers, a creative director, designed a real-time rendered randomly generative art piece. He uses Node.js to quickly render output the program’s results. Simplex noise is utilized to drive the particles, with each particle affected directly by the noise to curl a lot or move straight. Photographs were also used as distortion maps to further refine the end result. According to Deslauriers, photographs of snails, flowers, architecture, and geometry seemed to work the best. For instance, this photo of a rose window at Notre-Dame (rip). Check out more real-time renderings here

lrchu – project 06 – abstract clock

lrchu

// lee chu
// section c
// lrchu@andrew.cmu.edu
// project - 06

var h;
var m;
var s;
var rad = 50;
var start = 58;

var mer;
var ce;
var des;

function setup() {
    createCanvas(480, 300);
    mer = 12;
    ce = 30;
    des = 30;
}

function draw() {
    background(252, 245, 225);
    h = hour();
    m = minute();
    s = second();

    // spinning animation
    mer += 1/60 ; ce += 1/12 ; des += 1/12;

    // digits
    firstDigit(start, 90);
    secondDigit(start + 2 * rad, 90);
    thirdDigit(start + 4.25 * rad, 90);
    fourthDigit(start + 6.25 * rad, 90);

    // second counting dots
    fill(150);
    strokeWeight(0);
    if (s % 2 == 0) {
        ellipse(start + 3.625 * rad, 90 + rad / 2, 10, 10);
        ellipse(start + 3.625 * rad, 90 + 3 * rad / 2, 10, 10);
    }
}

// conditinals for each digit
function firstDigit(x, y) {
    if (h < 10) {
        zero(x, y);
    }
    else if (h > 9 & h < 20) {
        one(x, y);
    }
    else if (h > 19) {
        two(x, y);
    }

}

function secondDigit(x, y) {
    if (h % 10 == 0) {
        zero(x, y);
    }
    else if (h % 10 == 1) {
        one(x, y);
    }
    else if (h % 10 == 2) {
        two(x, y);
    }
    else if (h % 10 == 3) {
        three(x, y);
    }
    else if (h % 10 == 4) {
        four(x, y);
    }
    else if (h % 10 == 5) {
        five(x, y);
    }
    else if (h % 10 == 6) {
        six(x, y);
    }
    else if (h % 10 == 7) {
        seven(x, y);
    }
    else if (h % 10 == 8) {
        eight(x, y);
    }
    else if (h % 10 == 9) {
        nine(x, y);
    }
}

function thirdDigit(x, y) {
    if (m < 10) {
        zero(x, y);
    }
    else if (m > 9 & m < 20) {
        one(x, y);
    }
    else if (m > 19 & m < 30) {
        two(x, y);
    }
    else if (m > 29 & m < 40) {
        three(x, y);
    }
    else if (m > 39 & m < 50) {
        four(x, y);
    }
    else if (m > 49 & m < 60) {
        five(x, y);
    }
}

function fourthDigit(x, y) {
    if (m % 10 == 0) {
        zero(x, y);
    }
    else if (m % 10 == 1) {
        one(x, y);
    }
    else if (m % 10 == 2) {
        two(x, y);
    }
    else if (m % 10 == 3) {
        three(x, y);
    }
    else if (m % 10 == 4) {
        four(x, y);
    }
    else if (m % 10 == 5) {
        five(x, y);
    }
    else if (m % 10 == 6) {
        six(x, y);
    }
    else if (m % 10 == 7) {
        seven(x, y);
    }
    else if (m % 10 == 8) {
        eight(x, y);
    }
    else if (m % 10 == 9) {
        nine(x, y);
    }
}

// pre-assigned positions for each number variation
function zero(x, y) {
    clock(x, y, 3, 30, 15);
    clock(x, y + rad, 12, 30, 0);
    clock(x, y + 2 * rad, 12, 15, 0);
    clock(x + rad, y, 9, 30, 45);
    clock(x + rad, y + rad, 12, 30, 0);
    clock(x + rad, y + 2 * rad, 12, 45, 0);
}

function one(x, y) {
    // mer ce des
    clock(x, y, mer, ce, des);
    clock(x, y + rad, mer, ce, des);
    clock(x, y + 2 * rad, mer, ce, des);

    clock(x + rad, y, 6, 30, 30);
    clock(x + rad, y + rad, 12, 30, 30);
    clock(x + rad, y + 2 * rad, 12, 0, 0);
}

function two(x, y) {
    clock(x, y, 3, 15, 15);
    clock(x + rad, y, 9, 30, 45);
    clock(x + rad, y + rad, 12, 45, 0);
    clock(x, y + rad, 3, 30, 15);
    clock(x, y + 2 * rad, 12, 15, 0);
    clock(x + rad, y + 2 * rad, 9, 45, 45);
}

function three(x, y) {
    clock(x, y, 3, 15, 15);
    clock(x + rad, y, 9, 30, 45);
    clock(x + rad, y + rad, 12, 30, 45);
    clock(x, y + rad, 3, 15, 15);
    clock(x, y + 2 * rad, 3, 15, 15);
    clock(x + rad, y + 2 * rad, 12, 45, 0);
}

function four(x, y) {
    clock(x, y, 6, 30, 30);
    clock(x, y + rad, 12, 15, 15);
    clock(x + rad, y, 6, 30, 30);
    clock(x + rad, y + rad, 12, 30, 45);
    clock(x + rad, y + 2 * rad, 12, 0, 0);
    clock(x, y + 2 * rad, mer, ce, des);
}

function five(x, y) {
    clock(x, y, 3, 30, 15);
    clock(x + rad, y, 9, 45, 45);
    clock(x, y + rad, 12, 15, 15);
    clock(x + rad, y + rad, 9, 30, 45);
    clock(x, y + 2 * rad, 3, 15, 15);
    clock(x + rad, y + 2 * rad, 12, 45, 0);
}

function six(x, y) {
    clock(x, y, 3, 30, 15);
    clock(x + rad, y, 9, 45, 45);
    clock(x, y + rad, 12, 30, 15);
    clock(x, y + 2 * rad, 12, 15, 0);
    clock(x + rad, y + rad, 9, 30, 45);
    clock(x + rad, y + 2 * rad, 12, 45, 0);
}

function seven(x, y) {
    clock(x, y, 3, 15, 15);
    clock(x + rad, y, 9, 30, 45);
    clock(x + rad, y + rad, 12, 30, 0);
    clock(x + rad, y + 2 * rad, 12, 0, 0);
    clock(x, y + rad, mer, ce, des);
    clock(x, y + 2 * rad, mer, ce, des);
}

function eight(x, y) {
    clock(x, y, 3, 30, 15);
    clock(x + rad, y, 9, 30, 45);
    clock(x + rad, y + rad, 12, 30, 45);
    clock(x, y + rad, 12, 30, 15);
    clock(x, y + 2 * rad, 12, 15, 0);
    clock(x + rad, y + 2 * rad, 12, 45, 0);
}

function nine(x, y) {
    clock(x, y, 3, 30, 15);
    clock(x + rad, y, 9, 30, 45);
    clock(x, y + rad, 12, 15, 0);
    clock(x + rad, y + rad, 12, 30, 45);
    clock(x + rad, y + 2 * rad, 12, 0, 0);
    clock(x, y + 2 * rad, mer, ce, des);
}

// basic clock unit

function clock(x, y, h, m, s) {
    push();
    translate(x, y);
    strokeWeight(0);
    fill(150);
    circle(5, 5, rad - 2);
    strokeWeight(0.75);
    fill('white');
    circle(0, 0, rad - 2);

    // hour hand
    push();
    strokeWeight(2);
    rotate(h / 12 * 2 * PI);
    line(0, 0, 0, -rad / 2 + 6);
    pop();

    // minute hand
    push();
    strokeWeight(2);
    rotate(m / 60 * 2 * PI);
    line(0, 0, 0, -rad / 2 + 4);
    lastM = m;
    pop();

    // second hand
    push();
    strokeWeight(1.5);
    rotate(s / 60 * 2 * PI);
    line(0, 0, 0, -rad / 2 + 3);
    lastS = s;
    pop();
    pop();
}

I had seen a clock made of multiple clocks somewhere on the internet before, and I wanted to replicate that effect. However, a main issue I had a difficult time grasping was having each clock rotate its hands to the next assigned position, which would probably require arrays of the old positions and new positions.

lee chu – looking outwards – 05

Human skin complexion and overall face animation has always been difficult to emulate through a computer. The amount of wrinkles and pores, along with the elastic, organic properties of skin make it nearly impossible to capture and record these movements. Because of this, many computer-generated people in games and movies tend to look really close to human, but no quite, resulting in a sensation called the uncanny valley. New researchers at USC have developed new techniques to more accurately replicate skin movement on artificial skin. With this relatively new and seemingly unexplored possibility of recreating anything through a computer now, future media may become much more deceiving and immersive than before.

digital rendering of wrinkling

lee chu – project 05 – wallpaper

lrchu

// lee chu
// section c
// lrchu@andrew.cmu.edu
// project - 05


var spacing;
var size;
var raus;
var x;
var y;

function setup() {
    createCanvas(600, 600);
    noLoop();

    spacing = 150;
    size = 21;
}

function draw() {
    background(249, 246, 219);
    polkadots();
    for (var y = 0; y <= height; y += spacing / 2) {
        if ((y / spacing / 2 * 4) % 2 == 0) {
            for (var x = 0; x <= width; x += spacing) {
                rose(x, y, 1);
            }
        }
        else {
            for (var x = spacing / 2; x <= 3.5 * spacing; x += spacing) {
                rose(x, y, 0);
            }
        }  
    }
}

function polkadots() {
    for (var x = 0; x <= width; x += spacing / 2) {
        for (var y = 0; y <= height; y += spacing / 2) {
            strokeWeight(0);
            fill(168, 218, 220);
            ellipse(x, y, 8, 8);
        }
    }
    /*
    x = 0;
    y = 0;
    */
}

function rose(a, b, raus) {
    // leaves
    fill(26, 158, 81);
    beginShape();
    vertex(a, b);
    bezierVertex(a - 0.5 * size, b - 0.25 * size, a - 0.5 * size, b, a - 0.75 * size, 
    b + 0.5 * size);
    endShape();
    beginShape();
    vertex(a, b);
    bezierVertex(a + 0.5 * size, b - 0.25 * size, a + 0.5 * size, b, a + 0.75 * size, 
    b + 0.5 * size);
    endShape();

    // red
    if (raus == 0) {
        fill(107, 39, 55);
    }

    // blue
    else {
        fill(0, 57, 119);
    }

    // flower
    push();
    translate(a, b - 5);
    rotate(PI/4);
    for (h = 0; h < PI; h += PI / 8) {
        ellipse(0, 0, 28, 6);
        rotate(h);
    }
    fill(249, 246, 219);
    ellipse(0, 0, 4, 6);
    pop();
}

I wanted to create a simple floral repeating pattern.

lee chu – looking outwards – 04

Porter Robinson, a renown EDM artist is also known for amazing visuals at his live performances. His visuals usually consist of animation-esque landscapes and futuristic cityscapes which shift and morph to the music. Some of his visuals seem more computational than others, but I assume that most of them are animated completely digitally. The clip below was recorded during Porter’s Worlds tour probably last year or the year before. Porter Robinson’s personal tastes and artistic sensibilities translate directly to his visuals, as they seem to be inspired greatly by anime and consist of pastel colors.

lee chu – project 04 – string art

lrchu

// lee chu
// section c
// lrchu@andrew.cmu.edu
// project - 04

var x1 = 0;
var y1 = 0;
var x2 = 0;
var y2 = 0;
var xSpacing;
var ySpacing;
var offset = 5;

function setup() {
    createCanvas(400, 300);
    fill(100);
    strokeWeight(0.25);
    xSpacing = width / 100;
    ySpacing = height / 100;
}

function draw() {
    background(50);
    triangle(0, 0, width, 0, width, height);

    // mouse control
    if (height / 2 < mouseY & mouseY < height) {
        offset = (mouseY - height / 2) / (height / 2) * 30;
    }
    if (height / 2 > mouseY & mouseY > 0) {
        offset = (mouseY - height / 2) / (height / 2) * 30;
    }

    // see functions below
    whiteLines();
    orangeLines();
    cyanLines();
}


function whiteLines() {
    stroke('lightGray');
    x2 = xSpacing * offset;
    y2 = ySpacing * offset;

    // left
    for (var y1 = 0; y1 < height + offset * ySpacing; y1 += ySpacing) {
        line(x1, y1, width + x2, height + y2);
        x2 -= xSpacing;
        y2 -= ySpacing;
    }
    x2 = xSpacing * -offset;
    y2 = ySpacing * -offset;

    // right
    for (var y1 = height; y1 > -offset * ySpacing; y1 -= ySpacing) {
        line(width, y1, x2, y2);
        x2 += xSpacing;
        y2 += ySpacing;
    }
    x2 = 0;
    y2 = 0;
}


function orangeLines() {
    stroke('orange');

    // left
    for (var y1 = 0; y1 < height; y1 += ySpacing) {
        line(x1, y1, width - x2, height - y1);
        x2 += xSpacing;
    }
    x2 = 0;

    // right
    for (var y1 = height; y1 > 0; y1 -= ySpacing) {
        line(width, y1, x2, height - y1);
        x2 += xSpacing;
    }
    x2 = 0;
}

function cyanLines() {
    stroke('cyan');
    x2 = xSpacing * offset;
    y2 = ySpacing * offset;

    // left
    for (var y1 = 0; y1 < height - offset * ySpacing; y1 += ySpacing) {
        line(x1, y1, width - x2, height - y2);
        x2 += xSpacing;
        y2 += ySpacing;
    }
    x2 = xSpacing * offset;
    y2 = ySpacing * offset;

    // right
    for (var y1 = height; y1 > offset * ySpacing; y1 -= ySpacing) {
        line(width, y1, x2, y2);
        x2 += xSpacing;
        y2 += ySpacing;
    }
    x2 = 0;
    y2 = 0;
}

I wanted to create a sense of depth by offsetting line functions and including contrasting yet complementary colors. An interesting aspect is that the colors seem to shift as the lines change in overlap.

lee chu – looking outwards 03

Rock, especially gravel, is not often considered a substantial building material on its own, and neither is string; however, when these two elements are combined by laying the string out and entangling it within a pile of rocks to create a solid yet temporary structure. The structure shown above seems to be quite fragile on the surface, but the core is extremely solid due to the tension in the string. Although the uses of this construction type seems quite ambiguous, the potential for temporary strong structures which can be constructed using rubble or scrap materials might be applicable in the future.

lee chu – project 03

lrchu

// lee chu
// section c
// lrchu@andrew.cmu.edu
// project - 03


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

function draw() {
    var topX = 0;
    var topY = 0;
    var widthE = width/12;
    var heightE = height/7 - 30;
    var topR = widthE/2;
    var topH = heightE/2;

    var top1X = topX;
    var top2X = topX + widthE/2;
    var top3X = topX;
    var top4X = topX - widthE/2;
    var top1Y = topY - heightE/2;
    var top2Y = topY;
    var top3Y = topY + heightE/2;
    var top4Y = topY;

    var spacingX = width/12;
    var spacingY = height/7;

    var color1 = 45 + (mouseX / width) * 30;
    var color2 = 125 + (mouseY / height) * 50;
    var color3 = 0;

    background(color2);

    // control
    if (0 <= mouseX & mouseX <= width) {
        top1X += sqrt(mouseX/width) * topR;
        top1Y += pow(mouseX/width, 2) * topH;
        top2X -= pow(mouseX/width, 2) * topR;
        top2Y += sqrt(mouseX/width) * topH;
        top3X -= sqrt(mouseX/width) * topR;
        top3Y -= pow(mouseX/width, 2) * topH;
        top4X += pow(mouseX/width, 2) * topR;
        top4Y -= sqrt(mouseX/width) * topH;
    }

    for (var i = 0; i < 641; i += spacingX) {

        //used this as reference
        //ellipse(topX, topY, widthE, heightE);
        strokeWeight(0.5);
        stroke('red');

        // cube side 1
        fill('white');
        beginShape();
        vertex(top1X, top1Y);
        vertex(top4X, top4Y);
        vertex(top4X, top4Y + 30);
        vertex(top1X, top1Y + 30);
        endShape(CLOSE);

        // cube side 2
        fill(107, 37, 50);
        beginShape();
        vertex(top1X, top1Y);
        vertex(top2X, top2Y);
        vertex(top2X, top2Y + 30);
        vertex(top1X, top1Y + 30);
        endShape(CLOSE);

        // cube side 3
        fill(212, 75, 99);
        beginShape();
        vertex(top4X, top4Y);
        vertex(top4X, top4Y + 30);
        vertex(top3X, top3Y + 30);
        vertex(top3X, top3Y);
        endShape(CLOSE);

        // cube side 4
        fill(40, color1, 99);
        beginShape();
        vertex(top3X, top3Y);
        vertex(top2X, top2Y);
        vertex(top2X, top2Y + 30);
        vertex(top3X, top3Y + 30);
        endShape(CLOSE);

        // cube top
        fill(239, 240, 235);
        beginShape();
        vertex(top1X, top1Y);
        vertex(top2X, top2Y);
        vertex(top3X , top3Y);
        vertex(top4X, top4Y);
        endShape(CLOSE);

        for (var k = 0; k < 481; k += spacingY) {
            translate(0, spacingY);

            // cube side 1
            fill('white');
            beginShape();
            vertex(top1X, top1Y);
            vertex(top4X, top4Y);
            vertex(top4X, top4Y + 30);
            vertex(top1X, top1Y + 30);
            endShape(CLOSE);

            // cube side 2
            fill(107, 37, 50);
            beginShape();
            vertex(top1X, top1Y);
            vertex(top2X, top2Y);
            vertex(top2X, top2Y + 30);
            vertex(top1X, top1Y + 30);
            endShape(CLOSE);

            // cube side 3
            fill(212, 75, 99);
            beginShape();
            vertex(top4X, top4Y);
            vertex(top4X, top4Y + 30);
            vertex(top3X, top3Y + 30);
            vertex(top3X, top3Y);
            endShape(CLOSE);

            // cube side 4
            fill(40, color1, 99);
            beginShape();
            vertex(top3X, top3Y);
            vertex(top2X, top2Y);
            vertex(top2X, top2Y + 30);
            vertex(top3X, top3Y + 30);
            endShape(CLOSE);

            // cube top
            fill(239, 240, 235);
            beginShape();
            vertex(top1X, top1Y);
            vertex(top2X, top2Y);
            vertex(top3X , top3Y);
            vertex(top4X, top4Y);
            endShape(CLOSE);
            }
            translate(spacingX, 0);
            translate(0, -k);
    }
}

I started by creating a cube that could rotate 90 degrees as the mouse is dragged across the canvas By placing multiple cubes corner to corner, A sort of optical illusion happens.

lrchu – looking outwards – 02

Zaha Hadid was an Iraqi-British architect and also the first woman to receive the Pritzker Prize, one of the highest honors as an architect. Hadid is known for her masterful manipulation of curves and parametricism in her almost other-worldly designs. The Guardian of London even referred to Hadid as the “queen of the curve… who liberated architectural geometry, giving it a whole new expressive identity.”

al wakrah stadium

The Al Wakrah Stadium, designed by Zaha Hadid and Patrik Schumacher for the 2022 FIFA world cup, features an openable roof and cooled seating for all-year soccer play. The form of the building is derived from an abstraction of traditional boats, dhows, which can be found in Al Wakrah’s ports. The stadium not only applies a unique and beautiful form, but also modern solutions to conventional stadium issues like temperature regulation.

dhow boats