yunzhous-project-09

sketch

var dx = 2;
var dy = 2;
var dx1 = 2;
var dy1 = 2;
var dx2 = 2;
var dy2 = 2;
var dx3 = 2;
var dy3 = 2;
var dx4 = 2;
var dy4 = 2;
var px1;
var py1;
var py2;
var px2;
var py3;
var px3;
var py4;
var px4;
var py5;
var px5;
var py6;
var px6;
var py7;
var px7;
var py8;
var px8;

function preload(){
    var portraitURL = "https://i.imgur.com/voTtRT8.jpg";
    underlyingImage = loadImage(portraitURL);//load image
}
function setup() {
    createCanvas(480, 480);
    background(220);
    underlyingImage.loadPixels();
    frameRate(20);
}

function draw() {

    //draw balls in eight directions
    makeBall1();
    makeBall2();
    makeBall3();
    makeBall4();
    makeBall5();
    makeBall6();
    makeBall7();
    makeBall8();
}

function mousePressed() {
    //update the loaction to draw balls
    px1 = mouseX;
    py1 = mouseY;
    px2 = mouseX;
    py2 = mouseY;
    px3 = mouseX;
    py3 = mouseY;
    px4 = mouseX;
    py4 = mouseY;
    px5 = mouseX;
    py5 = mouseY;
    px6 = mouseX;
    py6 = mouseY;
    px7 = mouseX;
    py7 = mouseY;
    px8 = mouseX;
    py8 = mouseY;

}

function makeBall1(){

    var ix = constrain(px1, 0, width-1);
    var iy = constrain(py1, 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(ix, iy);//get the color at that pixel
    //keeping drawing balls along its motion
    px1 += dx1;
    py1 += dy1;
    noStroke();
    fill(theColorAtLocationXY);
    ellipse(px1, py1, 6, 6);
    if (px1 >= width || px1 <= 0) {//bounces off right and left
        dx1 = -dx1;
    }  
    if (py1 >= height || py1 <= 0) {//bounces off top and bottom
        dy1 = -dy1;        
    } 
}

function makeBall2(){
    var ix = constrain(px2, 0, width-1);
    var iy = constrain(py2, 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(ix, iy);
    px2 -= dx2;
    py2 -= dy2;
    noStroke();
    fill(theColorAtLocationXY);
    ellipse(px2, py2, 6, 6);
    if (px2 >= width || px2 <= 0) {//bounces off right and left
        dx2 = -dx2;
    }  
    if (py2 >= height || py2 <= 0) {//bounces off top and bottom
        dy2 = -dy2;        
    } 
}

function makeBall3(){
    var ix = constrain(px3, 0, width-1);
    var iy = constrain(py3, 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(ix, iy);
    px3 += dx3;
    py3 -= dy3;
    noStroke();
    fill(theColorAtLocationXY);
    ellipse(px3, py3, 6, 6);
    if (px3 >= width || px3 <= 0) {//bounces off right and left
        dx3 = -dx3;
    }  
    if (py3 >= height || py3 <= 0) {//bounces off top and bottom
        dy3 = -dy3;        
    } 
}

function makeBall4(){
    var ix = constrain(px4, 0, width-1);
    var iy = constrain(py4, 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(ix, iy);
    px4 -= dx4;
    py4 += dy4;
    noStroke();
    fill(theColorAtLocationXY);
    ellipse(px4, py4, 6, 6);
    if (px4 >= width || px4 <= 0) {//bounces off right and left
        dx4 = -dx4;
    }  
    if (py4 >= height || py4 <= 0) {//bounces off top and bottom
        dy4 = -dy4;        
    } 
}

function makeBall5(){
    var ix = constrain(px5, 0, width-1);
    var iy = constrain(py5, 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(ix, iy);
    px5 += dx;
    noStroke();
    fill(theColorAtLocationXY);
    ellipse(px5, py5, 6, 6);
}

function makeBall6(){
    var ix = constrain(px6, 0, width-1);
    var iy = constrain(py6, 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(ix, iy);
    px6 -= dx;
    noStroke();
    fill(theColorAtLocationXY);
    ellipse(px6, py6, 6, 6);
}

function makeBall7(){
    var ix = constrain(px7, 0, width-1);
    var iy = constrain(py7, 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(ix, iy);
    py7 -= dy;
    noStroke();
    fill(theColorAtLocationXY);
    ellipse(px7, py7, 6, 6);
}

function makeBall8(){
    var ix = constrain(px8, 0, width-1);
    var iy = constrain(py8, 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(ix, iy);
    py8 += dy;
    noStroke();
    fill(theColorAtLocationXY);
    ellipse(px8, py8, 6, 6);
}

For this project, I wanted to control the motion of the paint brush(where the points go). I thought of the motion of fireworks and decided to go with that. A firework would be made each time the user clicks on the screen. To make the drawing process easier, I made the balls bounce off the four edges of the canvas.

yunzhous-LookingOutwards-08

Robert Hodgin is a artist/coder. He does various type of work, ranging from 2D data visualizations and to immersive 3D simulations. His primary interests include theoretical physics, astronomy, particle engines, and audio visualizations. One fun fact, as a coder, he graduated from RISD with a degree in sculpture.

Hodgin visualizes&simulate data with code. For example, he visualizes fishes’ motion in the sea according to their speed, direction, etc. He visualizes lighting on earth according to data. He is very playful with his work: he gives the fish various shape. I found the playfulness delicate and interesting.

Hodgin’s lecture is very humorous. This actually grabbed my attention and made this 45min assignment engaging rather than tedious. He used metaphors(usually funny ones) to explain his work. For example, in explaining creative coding, he make a short video of painting intuitively until stopped by a bug in the code, with funny sound and visual effect. By doing this the audience would pay full attention to his lecture and easily understand.

This is the full lecture

 

This is another work by Hodgin I found amazing, “Fish Tornado”

Here is Hodgin’s website

 

yunzhous-project-07

sketch

function setup() {
    createCanvas(480, 480);
    angleMode(DEGREES);
}

function draw() {
    background("lightcyan");
    curve1();
    curve2();
}

function curve1(){
    //astroid
    beginShape();
    stroke(178, 240, 241);
    noFill();
    translate(width/2, height/2);
    for (var i = 0; i < mouseX/2; i ++){ //mouseX controls number of curves
        LimMouseX = constrain(mouseX, 0, width);
        var a = map(LimMouseX, 0, width, 10, 80); //relate to mouseX
        var theta = map(i, 0, mouseX, 20, 360);
        var x = 2 * a * cos(theta) + a * cos(2 * theta);
        var y = 2 * a * sin(theta) - a * sin(2 * theta);
        vertex(x, y);
    endShape();
    rotate(mouseX); //rotate according to position of mouseX

    }
}
function curve2(){

    //Epicycloid Involute
    beginShape();
    stroke(178, 230, 241);
    noFill();
    for (var i = 0; i < mouseX; i ++){ //mouseX controls number of curves
        LimMouseX = constrain(mouseX, 0, width);
        var a = map(LimMouseX, 0, width, 0, 80); //relate to mouseX
        var theta = map(i, 0, mouseX/5, 20, 360);
        var b = map(mouseY, 0, height, 0, 50);
        var x2 = (a+b)*cos(theta) - b*cos(((a+b)/b)*theta);
        var y2 = (a+b)*sin(theta) - b*sin(((a+b)/b)*theta);
        vertex(x2, y2);
    endShape();
    }
}

For this project, I started with researching for curves. I found astroid and epicycloid involute to be interesting and not overly complicated. I wrote two for loops to create multiple curves, and the curves rotate to create repetition. The curves are centered at the canvas and as mouseX and mouseY moves, they generate different pattern

 

yunzhous-LookingOutward-07

Swedish Morality

Swedish Morality

 

The is a project done by Skye Moret in 2017 to visualize 264 years of Swedish mortality. This is a unconventional yet visually pleasing and intuitionistic diagram. I particularity appreciate two aspects of it: it uses not only the conventional x, y axis, but also incorporate z-axis to make the chart 3D. Also, the visualization is not only a still image, but a motion that rotates the perspective, and shows the timeline step by step. With computers we can explore many ways to demonstrate and convey data. Moret’s choice of color, gradient, and the shadow effect, all demonstrate her artistic sensibility.

The software Moret used is  Processing—a free and “flexible software sketchbook and language for learning how to code within the context of visual arts.” It has amazing mapping data to visual attributes that allow users to change aspects such as opacity, color, and perspective.

You can read more here

yunzhous-LookingOutward-06

(example shown by the author)

(my work)

After some research online, I found an algorithm named “HTML5 Canvas Fractal Flame Generator” that generates random fractals. The users are free to change the type of lines, colors, scales, rotation, etc.  This algorithm is a simplified version of the “Fractal Flame algorithm” invented by Scott Draves. According to the author, “The algorithm is based on iterating a set of affine transformations to move a point around the plane a very large number of times, then rendering an image which records all of the positions the point visited.” I attached two images in the post, one is an example made by other people, another is the one I generated using this algorithm.

Since this type of “art” can be created by anyone with just a couple of simple clicks, I started to question the definition of “art”. The results are for sure visually pleasing, but is this real art? Generated with some simple operation on computer?

I chose this algorithm to write in LookingOutward because it was fun to play with it. It’s nice that people who barely know about computer science(like me) have access to simple algorithm like this, and have fun with it. Maybe this isn’t real art, but the interesting interaction is real.

You can read more about the algorithm here.

yunzhous-project-06

sketch

var eW = 30; //top of shishi odoshi
var eH = 15; //top of shishi odoshi
var yShift = 50; //mition of shishi odoshi
var SbeadD = 5;
var MbeadD = 8;
var HbeadD = 15;
var Mx = 110; //x position of minute moving bead
var Hx = 110;//x position of hour moving bead
var Sy = 5;////y position of second moving bead
var My = 100; ////y position of minute moving bead
var Hy = 260;////y position of hour moving bead


function setup() {
    createCanvas(240, 480);
    angleMode(DEGREES);
}

function draw() {
    var s = second();
    var m = minute();
    var h = hour();
    var mil = millis();

    //backgound color change from day to night
    if (h > 5 & h < 18){
        background(251, 237, 160);//yellow
    } else{
        background(70, 134, 186);//blue
    }

    //shishi odoshi pivot - second
    if (s % 2 != 0){
        shishiUP();
        plate();
        Sbead();
    } else{
        shishiDown();
        plate();
        Sbead();
    }

    //shishi odoshi pivot - minute
    if (s > 58){
        push();
        translate(0, 160);
        shishiDown();
        plate();
        Mbead();
        pop();
    } else{
        push();
        translate(0, 160);
        shishiUP();
        plate();
        Mbead();
        pop();
    }

    //shishi odoshi pivot - hour
    if (m > 58 & s > 58){
        push();
        translate(0, 320);
        shishiDown();
        plate();
        Hbead();
        pop();
    } else{
        push();
        translate(0, 320);
        shishiUP();
        plate();
        Hbead();
        pop();
    }

    //moving bead for second
    if (s % 2 != 0){
        Sy += 1;
        fill(199, 240, 245);
        ellipse(65, Sy, SbeadD, SbeadD);
    } else{
        //limit bead position
        Sy = 5;
    }
    
    //moving bead for minute
    if (s > 57 & s < 59){
        Mx -= 1.3;
        My += 3.2;
        fill(199, 240, 245);
        ellipse(Mx, My, MbeadD, MbeadD);
        //limit the bead position
        } else{
            Mx = 110;
            My = 100;
        }

    //moving bead for hour
    if (m > 58 & s > 57 && s < 59){
        Hx -= 1.3;
        Hy += 3.2;
        fill(199, 240, 245);
        ellipse(Hx, Hy, HbeadD, HbeadD);
        //limit the bead position
    } else {
        Hx = 110;
        Hy = 260;
    }

}

function shishiUP(){
    //shishi odoshi
    fill("green");
    rect(55, 45, 5, 35);//support
    quad(50, 30, 80, 30, 30, 80, 0, 80);
    arc(15, 79, eW, eH, 0, 180);
        //top
    ellipse(65, 30, eW, eH);
    fill(0);
    ellipse(65, 30, eW - 7, eH - 7);
            //support
    fill("green");
    rectMode(CORNER);
    quad(42, 55, 52, 45, 52, 50, 47, 55);
    rect(40, 50, 5, 35);
}

function shishiDown(){
    fill("green");
    rect(55, 45, 5, 35);//support
    quad(65, 30 + yShift, 95, 30 + yShift, 45, 80 - yShift, 15, 80 - yShift);
    arc(30, 81 - yShift, eW, eH, 180, 0);
    arc(80, 79, eW, eH, 0, 180);     //top
            //support
    fill("green");
    rectMode(CORNER);
    quad(42, 55, 52, 45, 52, 50, 47, 55);
    rect(40, 50, 5, 35);
}

function plate(){
    fill(255);
    //base
    ellipse(150, 110, 40, 20);
    //top
    ellipse(150, 100, 90, 30);
}

function Sbead(){ //beads accumulating according to seconds
    var s = second();
    var x = [110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,
        115,120,125,130,135,140,145,150,155,160,165,170,175,180,
        120,125,130,135,140,145,150,155,160,165,170,175,
        125,130,135,140,145,150,155,160,165,170,
        130,135,140,145,150,155,160,165];
    var y = [100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
        96,96,96,96,96,96,96,96,96,96,96,96,96,96,
        92,92,92,92,92,92,92,92,92,92,92,92,
        88,88,88,88,88,88,88,88,88,88,
        84,84,84,84,84,84,84,84,];
    for (i = 0; i < s; i ++){
        frameRate(20);
        fill(199, 240, 245);
        ellipse(x[i], y[i], SbeadD, SbeadD);
    }

}

function Mbead(){//beads accumulating according to minutes
    var m = minute();
    var x = [110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,
        115,120,125,130,135,140,145,150,155,160,165,170,175,180,
        120,125,130,135,140,145,150,155,160,165,170,175,
        125,130,135,140,145,150,155,160,165,170,
        130,135,140,145,150,155,160,165];
    var y = [100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
        96,96,96,96,96,96,96,96,96,96,96,96,96,96,
        92,92,92,92,92,92,92,92,92,92,92,92,
        88,88,88,88,88,88,88,88,88,88,
        84,84,84,84,84,84,84,84,];
    for (i = 0; i < m; i ++){
        frameRate(20);
        fill(199, 240, 245);
        ellipse(x[i], y[i], MbeadD, MbeadD);
    }

}

function Hbead(){//beads accumulating according to hours
    var h = hour();
    if (h > 12){
        h -= 12;  //12-hour clock
    }
    var x = [110,125,140,155,170,185,
            125,140,155,170,
            140,155,];
    var y = [100,100,100,100,100,100,
            88,88,88,88,
            76,76];
    for (i = 0; i < h; i ++){
        frameRate(20);
        fill(199, 240, 245);
        ellipse(x[i], y[i], HbeadD, HbeadD);
    }
}

I got the idea from shishi odoshi, a Japanese devices that’s made to frighten away animals. The weight of running water makes the bamboo pivot. I feel like water could be a metaphor for time, so I made three shishi odoshis, each representing second, minute, and hour, respectively. Beads that represent water, fall into the shishi odoshis, and the weight of the beads make the bamboo pivot and fall down to a plate nearby. The beads are passed down like time flows. The number of beads in the plate indicate the second/minute/hour. The background color indicate day/night.

I had problem making the bamboo to pivot according to time at first. Then I break the motion down to two parts: one with the bamboo up, one with bamboo down, and wrote conditions according to time to control motion. I also had trouble matching the motion of the bamboo with that of the moving beads. After hours of test/adjustments they finally match.

 

yunzhous-LookingOutwards-05

Boulon

Metaballs

Metaballs

I picked two artwork to show how 3D rendering can be applied to both large scene and small scale. Boulon is done by Florent Duport and Metaballs is done by Elmar Glaubauf. I really like the depth of field of the scene in Boulon, and the poping signboard. The contrast is well controlled, just enough for the lanterns and  signs to pop out.

The balls in Metaballs has a gradient color, and semi-opaque and glossy texture. It seems to be reflecting the background color, which is very delicate.

The algorithm used for rendering is vray. It is commonly used in architectural rendering, and now I learned it can be applied to wider fields. The users can adjust many settings in vray, such as amount of light, amount of reflection, etc.

You can see larger images here: metaballs  Boulon

yunzhous-project-05

sketch

function setup() {
    createCanvas(480, 480);
    background(41, 90, 141);
    angleMode(DEGREES);
    noLoop();
    
}

function draw() {

    for (var x = 0; x < 480; x += 96){
        for (var y = 0; y < 480; y += 96){
            push();
            translate(x, y);
            pattern();
            pop();

        }
    }
}

function pattern(){
    var radius = 20;
    var centerX = 40;
    var centerY = 40;

    //main piece
    strokeWeight(1.5);
    stroke(0);
    fill(214, 151, 0);
    arc(centerX, centerY, radius * 2 + 10, radius * 2 + 10, 0, 315); //edge
    fill(243, 210, 132);
    arc(centerX, centerY, radius * 2, radius * 2, 0, 315); //inside

    //separate piece
    push();
    rotate(-45);
    strokeWeight(1.5);
    stroke(0);
    fill(214, 151, 0);
    arc(centerX - 25, centerY + 22, radius * 2 + 10, radius * 2 + 10, 0, 45); //edge
    fill(243, 210, 132);
    arc(centerX - 25, centerY + 22, radius * 2, radius * 2, 0, 45); //inside
    pop();

    //toppings
    strokeWeight(1/2);
    fill(238, 97, 69);
    ellipse(centerX, centerY - 8, 6, 6);
    ellipse(centerX - 3, centerY + 5, 6, 6);
    ellipse(centerX - 10, centerY - 3, 6, 6);
    ellipse(centerX - 10, centerY - 13, 6, 6);
    ellipse(centerX + 8, centerY - 13, 6, 6);
    ellipse(centerX - 18, centerY + 3, 6, 6);
    ellipse(centerX - 12, centerY + 9, 6, 6);
    ellipse(centerX - 3, centerY + 13, 6, 6);
    ellipse(centerX + 7, centerY + 9, 6, 6);
    ellipse(centerX + 17, centerY + 4, 6, 6);
    ellipse(centerX + 27, centerY - 11, 6, 6);

    //division
    for (i = 0; i < 360; i += 45){
        strokeWeight(1);
        line(40, 40, centerX + cos(i) * (radius + 5), centerY + sin(i) * (radius + 5));
    }
    
}

For this project, I wanted to make the wallpaper fun and cute (as always). I thought food that’s partially bitten is very cute. I thought of lollipops, popsicles, donuts, and finally decided to go with pizza because I really wanted to have pizza. I tried creating my own function for the pizza pattern. Then I used for loop to repeat the pattern. I was actually amazed at how easily I could create only one single for loop and put the function inside rather than writing multiple loops for each element.

yunzhous-LookingOutward-04

Lumière III

Lumière III

Lumière III

This is Lumière III by Robert Henke. It is a audiovisual laser performance, in which an algorithm generates laser curves to bounce off the pre-designed spaces in the auditorium to create series of visual effect, including geometries, curves, lights, colors, etc. Sound also generated from the lasers. A dedicated sound synthesis engine was built for this particular project. Therefore, the artist built a custom algorithm for generating sound.

I appreciate that the algorithm generates both visual and sonic effect. Therefore, changing the laser would make change to both of them. From the geometries and colors, the observer can guess what the sound would be, because certain shapes and colors probably represent certain aspects of music. (eg. red represent dramatic emotion, etc). I thought the randomness of the lasers, and the random yet inter-connected visual and sonic effect generated by it is very interesting.

You can read more here

yunzhous-project-04-string art

sketch

var spacing = 5;

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

function draw() {
    background(0);
    //botton right corner
    for (i = 0; i < 100; i++){
        stroke(251, 201, 137);
        //limit mouseX
        if (mouseX < 100){
            mouseX = 100;
        }
        if (mouseX > 300){
            mouseX = 300;
        }
        map(mouseX, 0, width, 0, 30);
        line(0, height, mouseX * i, 5*i);
    }
    for (i = 0; i < 20; i++){
        map(mouseY, 0, height, 0, 20);
        //upper left corner
        //color gradient
        stroke(50, 200, mouseX);
        line(0, i * spacing * 5, width - i * spacing * 3, 0);
        //upper right corner
        stroke(255, 255 - i * 3, 255 - i *10);
        line(width - i * spacing, 0, width - i * spacing, height - i * spacing *5);
        //red lines
        //limit mouseY
        if (mouseY > 50){
            mouseY = 50;
        }
        stroke("red");
        line(width - i * mouseY, 0, i * spacing, height);
    }
    //background white lines
    for (i = 0; i < 50; i++) {
        stroke(255);
        line(width, height - i * spacing * 3, sq(i * spacing/6), height - i * spacing * 3);
    }
}

I played around with different variables, compositions, color gradient to create a visually harmonious image.