Steven Fei & Mike Jin – Final Project

Press your mouse to add planets and nebulas and use your mouse to hover around the Canvas and explore the universe!!

sketch

//Steven Fei & Fanjie Mike Jin
//Section A & C
//Final Project
//zfei@andrew.cmu.edu & fjin@andrew.cmu.edu
var starNumber = 150;//number of the stars on the background
var starsize = 1.5;//size of the stars
var sx = [];//array to define the x position of the stars
var sy = [];//array to define the y position of the stars
var sz = [];//array to define the z position of the stars
var amplitude = 3.14 * 3;//define the moving margin of the stars
var waveSpeed;//define the moving speed of the stars on the background
var theta = 0;//define the moving angle of the stars
var glowDefiner = [];//define the true false value for whether to let the star glow
var glowSize = 22;//glowing size of the stars
var newStars = [];//array for making new stars
var mouseXList = [];//arrays to store mouseX value
var mouseYList = [];//arrays to store mouseY value
var img; //load image for the earth texture mapping 
var w = 600 / 7 // devivded the canvas into seven regions and from left to right, the pitches of the piano sound will progressively become higher  
var newExplod = [];//array for making new explosion at the background
var mouseXListEx = [];//arrays to store mouseX value
var mouseYListEx = [];//arrays to store mouseY value


function setup() {
//load the background image for the texture mapping of the earth
//coded by Mike
    img = loadImage("https://i.imgur.com/lamlO83.jpg");
    createCanvas(600, 600,WEBGL);

//create values for the positions of the stars on the background
//coded by Mike
    for (var i = 0; i < starNumber; i++){
        sx.push(random(-width * 0.75, width * 0.75));
        sy.push(random(-height, height));
        sz.push(random(-width, height/2));
        var toggle = random(1.0);
        //define whether the stars on the background will glow
        if(toggle < 0.9){
            glowDefiner.push(false);
        }else{
            glowDefiner.push(true);
        }
    }
    for(var j = 0; j < glowDefiner.length; j++){
    print(glowDefiner[j]);
    }
}

function draw(){
    background(0);
    noStroke();
    normalMaterial();
    centerCube();//create a center star to give a sense of what perspective we are looking at
    makeCamera();//use the makeCamera function to change the viewport angle
    makeearth();
    push();
    //draw the stars on the background
    for(var i = 0; i < starNumber; i++){
        //coded by Mike
        push();
        waveSpeed = map(sz[i], -width, height/2, 15000, 60000);//define the moving speed of the stars
        theta += (TWO_PI / waveSpeed);//define the moving angle of the stars
        if(theta > amplitude){
            theta = -theta;//set the moving margins of the stars
        }
        sy[i] += sin(theta);//set the moving value to the positions
        sx[i] += cos(theta);//set the moving value to the positions
        translate(sx[i], sy[i], sz[i]);
        if(glowDefiner[i]){
            fill(255, 200, 130, 4);
            sphere(glowSize);//draw glow light of the sphere
        }
        fill("white");
        smooth();
        sphere(starsize);//draw the stars
        pop();
    }
    pop();
    //draw some new stars
    //coded by Steven
    if (mouseXList.length != 0){
        for(var k = 0; k < newStars.length; k++){
            newStars[k].updateStar();//animate the expansion of the stars
            push();
            translate(newStars[k].x, newStars[k].y,0);
            rotateX(frameCount * 0.05 + k*2);//rotate the new star
            rotateY(frameCount * 0.05 + k*2);//rotate the new star
            newStars[k].draw();//animate the emergence of the stars
            pop();
        } 
    }
    if(newStars.length > 4){
        newStars.shift();
    }

    push();
    //make the planet
    if (mouseXListEx.length != 0){
        for(var k = 0; k < newExplod.length; k++){
            newExplod[k].updateExplo();//animate the expansion of the stars
            push();
            translate(newExplod[k].x, newExplod[k].y,0);
            rotateX(frameCount * 0.05 + k*2);//rotate the new star
            rotateY(frameCount * 0.05 + k*2);//rotate the new star
            newExplod[k].draw();//animate the emergence of the stars
            pop();
        } 
    }
    if(newExplod.length > 2){
        newExplod.shift();
    }
    pop();

    
}

function makeCamera(){
//coded by Steven
    camX = map(mouseX, 0, width, -width/2, width/2);//changing camera position x
    camY = map(mouseY, 0, height, -height/2, height/2);//changing camera position y
    camZ = height/2;//changing camera position z
    camera(camX, camY, camZ,0,0,0,1,1,0);//allow the viewport angle to change
}
//make object to create new stars
function makeNewStar(x, y, radius){
//coded by Mike
    var newstar = {x: x,
                    y: y,
                    r: radius,
                    updateStar: updateStar,
                    draw: drawNewStar};
    return newstar;
}

function makeNewExplo(x, y, radius){
//coded by Mike
    var newExplo = {x: x,
                    y: y,
                    r: radius,
                    updateExplo: updateExplo,
                    draw: drawNewExplo};
    return newExplo;
}

//function to draw new star
function drawNewStar(){
//coded by Mike
    var color1 = random(150, 255);
    var color2 = random(100,180);
    var color3 = random(100,200);
    var density = random(14,20);//allow different numbers of the spheres to appear on the star
    for(var i = 0; i < density; i++){
        var lengthValue = map(i, 0, density, -PI, PI); //set longitudinal value
        for(var j = 0; j< density; j++){
            var widthValue = map(j, 0, density, -PI/2, PI/2);// set horizontal value
            var pX = this.r * sin(lengthValue) * cos(widthValue);
            var pY = this.r * sin(lengthValue) * sin(widthValue);
            var pZ = this.r * cos(lengthValue);
            push();
            fill(color1, color2, color3);
            translate(pX, pY, pZ);
            sphere(1.6);
            pop();
        }
    }
}

function drawNewExplo(){
//coded by Mike
    var color4 = random(100, 255);
    var color5 = random(100,180);
    var color6 = random(100,200);
    var density = random(12, 15);//allow different numbers of the spheres to appear for the explosion
    for(var i = 0; i < density; i++){
        var lengthValue = map(i, 0, density, -PI, PI); //set longitudinal value
        for(var j = 0; j< density; j++){
            var widthValue = map(j, 0, density, -PI/2, PI/2);// set horizontal value
            var pX1 = this.r * sin(lengthValue) * cos(widthValue * 0.5) * 0.5;
            var pY1 = this.r * sin(lengthValue * 0.5) * sin(widthValue) * 0.5;
            var pZ1 = this.r * cos(lengthValue);
            push();
            fill(color4, color5, color6);
            translate(pX1, pY1, pZ1);
            box(2, 2, 2);
            pop();
        }
    }
}

function updateStar(){
//coded by Mike
    this.r += random(0.5,2);//allow the new star to expand
}

function updateExplo(){
//coded by Mike
    this.r += random(1,2);//allow the new explosion to expand
}


function mousePressed(){
//coded by Steven
    var newStarMaking = [];
    var newMouseXList = [];
    var newMouseYList = [];
    var newExploMaking = [];
    var newmouseXListEx = [];
    var newmouseYListEx = [];
    var clickEx;//check whether there is existing new stars
    var click;//check whether there is existing new stars
    
    if(mouseXList.length == 0){
        click = 0;
        newStarMaking.push(newStars[0]);
        newMouseXList.push(mouseXList[0]);
        newMouseYList.push(mouseYList[0]);
    }
    else{
        for(var l = 0; l < newStars.length; l++){
            var distance = dist(mouseX - width/3, mouseY - height/3, newStars[l].x, newStars[l].y);
            if(distance <= 30){
                click = 1;
            }else{
                click = 0;
                newStarMaking.push(newStars[l]);
                newMouseXList.push(mouseXList[l]);
                newMouseYList.push(mouseYList[l]);
            }
        }
        newStars = newStarMaking;
        mouseXList = newMouseXList;
        mouseYList = newMouseYList;
    }
    if(click == 0){
        mouseXList.push(mouseX - width/3);
        mouseYList.push(mouseY - width/3);
        var newStar = makeNewStar(mouseX - width/3, mouseY-width/3, 30);
        newStars.push(newStar);
    }

    //add value to empty list
    if(mouseXListEx.length == 0){
        clickEx = 0;
        newExploMaking.push(newExplod[0]);
        newmouseXListEx.push(mouseXListEx[0]);
        newmouseYListEx.push(mouseYListEx[0]);
    }
    else{
    //assign initiating position according to the mouse postion
        for(var w = 0; w < newExplod.length; w++){
            var distance = dist(mouseX - width/3, mouseY - height/3, newExplod[w].x, newExplod[w].y);
            if(distance <= 30){
                clickEx = 1;
            }else{
                clickEx = 0;
                newExploMaking.push(newExplod[w]);
                newmouseXListEx.push(mouseXListEx[w]);
                newmouseYListEx.push(mouseYListEx[w]);
            }
        }
        //assign values back to the list
        newExplod = newExploMaking;
        mouseXListEx = newmouseXListEx;
        mouseYListEx = newmouseYListEx;
    }
    //avoid invalid value
    if(clickEx == 0){
        mouseXListEx.push(mouseX - width/3);
        mouseYListEx.push(mouseY - width/3);
        var newExplo = makeNewExplo(mouseX - width/3, mouseY-width/3, 300);
        newExplod.push(newExplo);
    }
}


//function to make a center planet to have some understanding of the perspective
//coded by Mike
function centerCube(){
    //make sure the location of the center planet is always at the center of the canvas
    push();
    var locX = mouseX - height / 2;
    var locY = mouseY - width / 2;
    ambientLight(50);
    directionalLight(255, 0, 0, 0.25, 0.25, 0);
    pointLight(0, 0, 255, locX, locY, 250);
    ambientMaterial(100);
    strokeWeight(0.5);
    stroke(255);
    smooth();
    sphere(40);
    pop();
    //first ring surronding the planet
    push();
    rotateZ(frameCount * 0.01);
    rotateX(frameCount * 0.01);
    rotateY(frameCount * 0.01);
    strokeWeight(0.5);
    smooth();
    stroke(255);
    torus(60, 0.5);
    pop();
    //second ring surronding the planet
    push();
    rotateZ((100+ frameCount) * 0.01);
    rotateX((100 + frameCount) * 0.01);
    rotateY((100+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(70, 0.5);
    pop();
    //third ring surronding the planet
    push();
    rotateZ((200+ frameCount) * 0.01);
    rotateX((200 + frameCount) * 0.01);
    rotateY((200+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(80, 0.5);
    pop();
    //fourth ring surronding the planet
    push();
    rotateZ((300+ frameCount) * 0.01);
    rotateX((300 + frameCount) * 0.01);
    rotateY((300+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(90, 1);
    pop();
}
//function to make a earth adjacent to the center planet 
//coded by Mike
function makeearth(){
    push();
    translate(width / 2, height / 3, -150);
    rotateX(frameCount * 0.05);
    rotateY(frameCount * 0.05);
    texture(img);
    sphere(20);
    pop();
}

 

In this project, we aim to establish an interactive universe made possible by using the P5 3D geometry and 3D lighting. When you are hovering around in this universe, the stars and planets will move according to your mouse position. When you lower the mouse position, the screen will be zoomed out and when you higher the mouse, the screen will zoom in more.  When the mouse is pressed, new “stars” which look like the colorful spheres composed of smaller spheres with galaxy-like explosion will happen randomly on the screen and would expand further until they can be seen no more. However, once you click on the screen, you will be able to see them again. The small spheres are glowing on the background to have an interstellar appearance. The center spindle-like sphere and an “Earth” like sphere are created to give us a general understanding of what perspective we are looking at the canvas. 

sketch

//Steven Fei & Mike Jin
//Section A & C
//Final Project
//zfei@andrew.cmu.edu & fjin@andrew.cmu.edu
var starNumber = 150;//number of the stars on the background
var starsize = 1.5;//size of the stars
var sx = [];//array to define the x position of the stars
var sy = [];//array to define the y position of the stars
var sz = [];//array to define the z position of the stars
var amplitude = 3.14 * 3;//define the moving margin of the stars
var waveSpeed;//define the moving speed of the stars on the background
var theta = 0;//define the moving angle of the stars
var glowDefiner = [];//define the true false value for whether to let the star glow
var glowSize = 22;//glowing size of the stars
var newStars = [];//array for making new stars
var mouseXList = [];//arrays to store mouseX value
var mouseYList = [];//arrays to store mouseY value
var img; //load image for the earth texture mapping 
var w = 600 / 7 // devivded the canvas into seven regions and from left to right, the pitches of the piano sound will progressively become higher  
var mySndC; //Piano note C
var mySndD; //Piano note D
var mySndE; //Piano note E
var mySndF; //Piano note F
var mySndG; //Piano note G
var mySndA; //Piano note A
var mySndB; //Piano note B
var newExplod = [];//array for making new explosion at the background
var mouseXListEx = [];//arrays to store mouseX value
var mouseYListEx = [];//arrays to store mouseY value

function preload(){
//coded by Mike
//preload the soundtrack of each piano notes to the file
    mySndC = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/c-1.wav");
    mySndD = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/d-1.wav");
    mySndE = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/e-1.wav");
    mySndF = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/f-1.wav");
    mySndG = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/g-1.wav");
    mySndA = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/a-1.wav");
    mySndB = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/b-1.wav");
    mySndC.setvolume(1);
    mySndD.setvolume(1);
    mySndE.setvolume(1);
    mySndF.setvolume(1);
    mySndG.setvolume(1);
    mySndA.setvolume(1);
    mySndB.setvolume(1);
}

function setup() {
//load the background image for the texture mapping of the earth
//coded by Mike
    img = loadImage("https://i.imgur.com/lamlO83.jpg");
    createCanvas(600, 600,WEBGL);

//create values for the positions of the stars on the background
//coded by Steven
    for (var i = 0; i < starNumber; i++){
        sx.push(random(-width * 0.75, width * 0.75));
        sy.push(random(-height, height));
        sz.push(random(-width, height/2));
        var toggle = random(1.0);
        //define whether the stars on the background will glow
        if(toggle < 0.9){
            glowDefiner.push(false);
        }else{
            glowDefiner.push(true);
        }
    }
    for(var j = 0; j < glowDefiner.length; j++){
    print(glowDefiner[j]);
    }
}

function draw(){
    background(0);
    noStroke();
    normalMaterial();
    centerCube();//create a center star to give a sense of what perspective we are looking at
    makeCamera();//use the makeCamera function to change the viewport angle
    makeearth();
    push();
    //draw the stars on the background
    for(var i = 0; i < starNumber; i++){
        //coded by Steven
        push();
        waveSpeed = map(sz[i], -width, height/2, 15000, 60000);//define the moving speed of the stars
        theta += (TWO_PI / waveSpeed);//define the moving angle of the stars
        if(theta > amplitude){
            theta = -theta;//set the moving margins of the stars
        }
        sy[i] += sin(theta);//set the moving value to the positions
        sx[i] += cos(theta);//set the moving value to the positions
        translate(sx[i], sy[i], sz[i]);
        //coded by Mike
        if(glowDefiner[i]){
            fill(255, 200, 130, 4);
            sphere(glowSize);//draw glow light of the sphere
        }
        fill("white");
        smooth();
        sphere(starsize);//draw the stars
        pop();
    }
    pop();

    push();
    //make the planet
    if (mouseXListEx.length != 0){
        for(var k = 0; k < newExplod.length; k++){
            newExplod[k].updateExplo();//animate the expansion of the stars
            push();
            translate(newExplod[k].x, newExplod[k].y,0);
            rotateX(frameCount * 0.05 + k*2);//rotate the new star
            rotateY(frameCount * 0.05 + k*2);//rotate the new star
            newExplod[k].draw();//animate the emergence of the stars
            pop();
        } 
    }
    if(newExplod.length > 2){
        newExplod.shift();
    }
    pop();

    push();
    // make the explosion
    if (mouseXList.length != 0){
        for(var k = 0; k < newStars.length; k++){
            newStars[k].updateStar();//animate the expansion of the explosion in the background 
            push();
            translate(newStars[k].x, newStars[k].y,0);
            newStars[k].draw();//animate the emergence of the stars
            pop();
        } 
    }
    if(newStars.length > 4){
        newStars.shift();
    }
    pop();
    
}

function makeCamera(){
//coded by Steven
    camX = map(mouseX, 0, width, -width/2, width/2);//changing camera position x
    camY = map(mouseY, 0, height, -height/2, height/2);//changing camera position y
    camZ = height/2;//changing camera position z
    camera(camX, camY, camZ,0,0,0,1,1,0);//allow the viewport angle to change
}

//make object to create new stars
function makeNewStar(x, y, radius){
//coded by Steven
    var newstar = {x: x,
                    y: y,
                    r: radius,
                    updateStar: updateStar,
                    draw: drawNewStar};
    return newstar;
}

function makeNewExplo(x, y, radius){
//coded by Mike
    var newExplo = {x: x,
                    y: y,
                    r: radius,
                    updateExplo: updateExplo,
                    draw: drawNewExplo};
    return newExplo;
}

//function to draw new star
function drawNewStar(){
//coded by Mike
    var color1 = random(150, 255);
    var color2 = random(100,180);
    var color3 = random(100,200);
    var density = random(14,20);//allow different numbers of the spheres to appear on the star
    for(var i = 0; i < density; i++){
        var lengthValue = map(i, 0, density, -PI, PI); //set longitudinal value
        for(var j = 0; j< density; j++){
            var widthValue = map(j, 0, density, -PI/2, PI/2);// set horizontal value
            var pX = this.r * sin(lengthValue) * cos(widthValue);
            var pY = this.r * sin(lengthValue) * sin(widthValue);
            var pZ = this.r * cos(lengthValue);
            push();
            fill(color1, color2, color3);
            translate(pX, pY, pZ);
            sphere(1.6);
            pop();
        }
    }
}

function drawNewExplo(){
//coded by Mike
    var color4 = random(100, 255);
    var color5 = random(100,180);
    var color6 = random(100,200);
    var density = random(12, 15);//allow different numbers of the spheres to appear for the explosion
    for(var i = 0; i < density; i++){
        var lengthValue = map(i, 0, density, -PI, PI); //set longitudinal value
        for(var j = 0; j< density; j++){
            var widthValue = map(j, 0, density, -PI/2, PI/2);// set horizontal value
            var pX1 = this.r * sin(lengthValue) * cos(widthValue * 0.5) * 0.5;
            var pY1 = this.r * sin(lengthValue * 0.5) * sin(widthValue) * 0.5;
            var pZ1 = this.r * cos(lengthValue);
            push();
            fill(color4, color5, color6);
            translate(pX1, pY1, pZ1);
            box(2, 2, 2);
            pop();
        }
    }
}
function updateExplo(){
//coded by Mike
    this.r += random(1,2);//allow the new explosion to expand
}

function updateStar(){
//coded by Mike
    this.r += random(0.5,2);//allow the new star to expand
}
function mousePressed(){
//coded by Steven
    var newStarMaking = [];//empty list for the making new star when mouse is pressed
    var newMouseXList = [];
    var newMouseYList = [];
    var newExploMaking = [];
    var newmouseXListEx = [];
    var newmouseYListEx = [];
    var clickEx;//check whether there is existing new stars
    var click;//check whether there is existing new stars
    
    if(mouseXList.length == 0){
        click = 0;//count whether the times of starting the object
        newStarMaking.push(newStars[0]);//assign values to new arrays to store valid value
        newMouseXList.push(mouseXList[0]);//assign values to new arrays to store valid value
        newMouseYList.push(mouseYList[0]);//assign value to new arrays to store valid value
    }
    else{
        //define the initiating position according to the mouse position
        for(var l = 0; l < newStars.length; l++){
            var distance = dist(mouseX - width/3, mouseY - height/3, newStars[l].x, newStars[l].y);
            if(distance <= 30){
                click = 1;
            }else{
                click = 0;
                newStarMaking.push(newStars[l]);//assign values to the new array
                newMouseXList.push(mouseXList[l]);//assign values to the new array
                newMouseYList.push(mouseYList[l]);//assign values to the new array
            }
        }
        //get the valid value back to the list
        newStars = newStarMaking;
        mouseXList = newMouseXList;
        mouseYList = newMouseYList;
    }
    //avoid invalid value
    if(click == 0){
        mouseXList.push(mouseX - width/3);
        mouseYList.push(mouseY - width/3);
        var newStar = makeNewStar(mouseX - width/3, mouseY-width/3, 30);
        newStars.push(newStar);
    }

    //add value to empty list
    if(mouseXListEx.length == 0){
        clickEx = 0;
        newExploMaking.push(newExplod[0]);
        newmouseXListEx.push(mouseXListEx[0]);
        newmouseYListEx.push(mouseYListEx[0]);
    }
    else{
    //assign initiating position according to the mouse postion
        for(var w = 0; w < newExplod.length; w++){
            var distance = dist(mouseX - width/3, mouseY - height/3, newExplod[w].x, newExplod[w].y);
            if(distance <= 30){
                clickEx = 1;
            }else{
                clickEx = 0;
                newExploMaking.push(newExplod[w]);
                newmouseXListEx.push(mouseXListEx[w]);
                newmouseYListEx.push(mouseYListEx[w]);
            }
        }
        //assign values back to the list
        newExplod = newExploMaking;
        mouseXListEx = newmouseXListEx;
        mouseYListEx = newmouseYListEx;
    }
    //avoid invalid value
    if(clickEx == 0){
        mouseXListEx.push(mouseX - width/3);
        mouseYListEx.push(mouseY - width/3);
        var newExplo = makeNewExplo(mouseX - width/3, mouseY-width/3, 300);
        newExplod.push(newExplo);
    }

    //coded by Mike
    //load the sound and defines the regions of the sound 
    if(mouseX > 0 & mouseX < w){
            mySndC.play();
        }
        if(mouseX > w & mouseX < 2 *w){
            mySndD.play();   
        }
        if(mouseX > 2 * w & mouseX < 3 * w){
            mySndE.play();
        }
        if(mouseX > 3 * w & mouseX < 4 * w){
            mySndF.play();
        }
        if(mouseX > 4 * w & mouseX < 5 * w){
            mySndG.play();
        }
        if(mouseX > 5 * w & mouseX < 6 * w){
            mySndA.play(); 
        }
        if(mouseX > 6 * w & mouseX < 7 * w){
            mySndB.play(); 
        }
}


//function to make a center planet to have some understanding of the perspective
//coded by Mike
function centerCube(){
    //make sure the location of the center planet is always at the center of the canvas
    push();
    var locX = mouseX - height / 2;
    var locY = mouseY - width / 2;
    ambientLight(50);
    directionalLight(255, 0, 0, 0.25, 0.25, 0);
    pointLight(0, 0, 255, locX, locY, 250);
    ambientMaterial(100);
    strokeWeight(0.5);
    stroke(255);
    smooth();
    sphere(40);
    pop();
    //first ring surronding the planet
    push();
    rotateZ(frameCount * 0.01);
    rotateX(frameCount * 0.01);
    rotateY(frameCount * 0.01);
    strokeWeight(0.5);
    smooth();
    stroke(255);
    torus(60, 0.5);
    pop();
    //second ring surronding the planet
    push();
    rotateZ((100+ frameCount) * 0.01);
    rotateX((100 + frameCount) * 0.01);
    rotateY((100+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(70, 0.5);
    pop();
    //third ring surronding the planet
    push();
    rotateZ((200+ frameCount) * 0.01);
    rotateX((200 + frameCount) * 0.01);
    rotateY((200+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(80, 0.5);
    pop();
    //fourth ring surronding the planet
    push();
    rotateZ((300+ frameCount) * 0.01);
    rotateX((300 + frameCount) * 0.01);
    rotateY((300+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(90, 1);
    pop();
}
//function to make a earth adjacent to the center planet 
//coded by Mike and Steven 
function makeearth(){
    push();
    translate(width / 2, height / 3, -150);
    rotateX(frameCount * 0.05);
    rotateY(frameCount * 0.05);
    texture(img);
    sphere(20);
    pop();
}

Fanjie Mike Jin-LookingOutwards-12

Takio no Tatsujin, Nintendo

Taiko no Tatsujin is a music-related game I found really inspiring for my final project. The main objective of Taiko no Tatsujin games is to hit a simulated Taiko drum following a chosen piece of music, corresponding to notes scrolling from the right. When the screen is scrolling, once the orange circle is landed at the dashed circle at the left side of the screen, if you hit it, at the perfect timing, you are going to get bonus and animation at the bottom is also going to change correspondently.  I really admire this project in that it has a really interesting graphic and depending on the different melody that you are playing, the background animation is also changing correspondently to the music.

neutrino oscillations simulation, Hirosi Ooguri

The scene showing the” rewinding” of the Universe is created using the latest scientific data and it is done by Hirosi Ooguri, a professor at Caltech. This image added some artist expression and its objective is to visualize neutrino oscillations. I really admire this project in that it is visualizing the universe really artistically. 

These two projects are really good precedents for me as I am envisioning my final project to be a music-related project, probably piano. When the user pressed certain buttons on the piano, the universe at the background will be changed accordingly based on the music and different music will yield different visualization of the universe. 

Fanjie Mike Jin and Steven Fei- Project-12-Proposal

In this final project, I am going to collaborate with Steven Fei. The name of our project is called, Interstellar Pianist. Our objective is to use an interaction keyboard to simulate the idea of traveling in space. The pianist will play different notes and all the different notes will trigger different actions correspondently. The background will present a view of the galaxy and viewport of the galaxy can be manipulated by changing the position of the mouse. For example, when the “A” key which is representing C on the keyboard is pressed, a planet of red color will be generated and it will keep revolving and moving slowly towards a random direction. “S” key which is representing B,  another different looking planet of different color will be generated. There is going to be a limited amount of planets that you can generate. Once the maximum amount of planets is generated, the one that has been created at the very beginning will be shifted. Depending on the music you are playing, a different scenery of the universe will be created and you can move the mouse to examine and explore this universe. 

diagram

Fanjie Mike Jin — Project 11 — Landscape

sketch

// Fanjie Mike Jin
// Section C
//fjin@andrew.cmu.edu
//Project-11

// global variables declared to hold objects
// array for tree objects
var trees = []

function setup() {
    //color preprared for the gradient effect
    c1 = color(250, 100, 0);
    c2 = color(204, 143, 0);
    createCanvas(480, 480);
    frameRate(100);  
    }
function draw() {
    //draw the gradient background 
    for (var i = 0; i < height; i++) {
        var inter = map(i, 70, 110, 0, 1);
        var c = lerpColor(c1, c2, inter);
        stroke(c);
        line(0, i, width, i);
    }
    //draw the sun in the background 
    noStroke();
    fill(234, 120, 120, 200);  
    ellipse(100, 60, 90, 90);
    fill(255, 146, 128, 200);  
    ellipse(100, 60, 76, 76);

    mountainBackground(); //mountain 
    land()
    updatetrees();
    removetrees();
    newtrees(); 
}

function updatetrees(){
    // Update the x positions of the trees and display them 
    for (var i = 0; i < trees.length; i++){
        trees[i].move();
        trees[i].display();
    }
}
function removetrees(){
    //remove the building from the array once it dropped off the left edge
    var treesToKeep = [];
    for (var i = 0; i < trees.length; i++){
        if (trees[i].x + trees[i].breadth > 0) {
            treesToKeep.push(trees[i]);
        }
    }
    // the exsiting trees will be kept 
    trees = treesToKeep;
}


function newtrees() {
    // add a new tree to the end
    var probability = 0.017; 
    if (random(0,1) < probability) {
        trees.push(drawtrees(width));
    }
}

//update position of tree every frame
function treesMove() {
    this.x += this.speed;
}
    
//display the trees
function treesDisplay() {
    noStroke();
    //leaves
    fill(50, 235, 173);
    triangle(this.x - 15, 350, this.x + 15, 350, this.x, 320);
    triangle(this.x - 20, 370, this.x + 20, 370, this.x, 330);
    triangle(this.x - 30, 400, this.x + 30, 400, this.x, 350);
    //trunk
    stroke(194, 245, 228);
    line(this.x, 350, this.x, 420);
}


function drawtrees(px) {
    var dt = {x: px,
    //trees obeject properties 
                breadth: 30,
                speed: -1.0,
                move: treesMove,
                display: treesDisplay}
    return dt;
}

function mountainBackground() {
    //makes mountains in the back
    terrain = 0.009;
    terrain2 = 0.014;
    terrainSpeed = 0.0003;
    //use noise function to draw random background contour of the furthest mountains 

    stroke(30, 148, 143,200);
    beginShape(); 
    //make slowly rolling hills
    for (var j = 0; j < width; j++) {
        var t = (j * terrain) + (millis() * terrainSpeed);
        var y2 = map(noise(t), 0, 1, 200, 10);
        line(j, y2, j, height); 
    }
    endShape();

    //use noise function to draw random background contour of the closer mountains 
    stroke(65, 158, 155);
    beginShape(); 
    for (var j = 0; j < width; j++) {
        var t = (j * terrain2) + (millis() * terrainSpeed);
        var y2 = map(noise(t), 0, 1, 400, 10);
        line(j, y2, j, height); 
    }
    endShape();
}


function land() {
//makes the land in the foreground appear 
    fill(46, 84, 78);
    rect(0, 420, 480, 130);
}

When I thought about the “generative landscape”, the first idea that prompted my mind is a landscape with mountains and trees. There are two layers of mountains to show the depth of this generative landscape. There are pine trees in the foreground. I have chosen the colors strategically so that the whole composition can be read clearly and aesthetically pleasing.

quick sketch

Fanjie Jin-LookingOutwards-11

Nataly Gattegno is an artist and one of the two founding partners of FUTUREFORMS. She is primarily focusing on design research and urban speculation through the lens of art and design theory and urban design. She was born and raised in Athens, Greece. She received her MA from Cambridge University and Masters of architecture from Princeton University.

Render of Cosmos by FUTUREFORMS

Cosmos is one of their many interactive pavilion designs. It is a dynamic shading canopy that fosters pedestrian interactions and establishes a visual focal point at the site. Cosmos creates an open shaded space for people to fluidly move through and congregate as it provides a contemplative play of shadow and lights. The people around the area would enjoy spending time underneath the artwork’s intricate organic structure and kaleidoscopic skin and depending on the different times of the day, the shadows will be changed. 

I really admire this project as the geometry of the artwork is really stunning and there is a Fibonacci-like Sequence algorithm underlying the three-dimensional structure and skin of the pavilion. The geometry allows the shadow, which is something that’s always very neglectful, to play the main role and even as interesting as the pavilion itself.

Fanjie Mike Jin – Project 10 – Sonic Sketch

sketch1

// Fanjie Mike Jin
// Section C
//fjin@andrew.cmu.edu
//Project 10

//set the count for the four melodies
var voiceplaying = 1;
var pianoPlaying = 1;
var jazzPlaying = 1;
var electronicPlaying = 1;

function preload() {
//preloads the images
    var imageUrl = "https://i.imgur.com/DcInSlj.jpg";
    pic = loadImage(imageUrl);
//preloads the different types of sound
    jazz = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/jazz.wav");
    voice = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/voice.wav");
    piano = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/piano.wav");
    electronic = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/electronic.wav");
//set the volume of the music track
    jazz.setVolume(1);
    voice.setVolume(1);
    piano.setVolume(1);
    electronic.setVolume(1);
}

function setup() {
//set up the background image for the music choosing
    createCanvas(400, 400);
    background(0);
    image(pic, 0, 0);
}

function mousePressed(){
// when mouse is pressed at the designated area, the voice melody would be played
    if (mouseX > width / 2 & mouseY > height / 2 && mouseX < width && mouseY < height){
//the music will be turned off once it has been clicked the second time 
        voiceplaying = voiceplaying + 1;
        if (voiceplaying % 2 == 0){
            voice.play();
        } else {
            voice.pause();
        }
    }
    
// when mouse is pressed at the designated area, the electronic melody would be played  
    if (mouseX < width / 2 & mouseY > height / 2 && mouseY < height){
        electronicPlaying = electronicPlaying + 1;
//the music will be turned off once it has been clicked the second time 
        if (electronicPlaying % 2 == 0){
            electronic.play();
        } else {
            electronic.pause();
        }
    }

// when mouse is pressed at the designated area, the piano melody would be played
    if (mouseX > width / 2 & mouseY < height / 2 && mouseX < width){
        pianoPlaying = pianoPlaying + 1;
//the music will be turned off once it has been clicked the second time       
        if (pianoPlaying % 2 == 0){
            piano.play();
        } else {
            piano.pause();
        }
    }

// when mouse is pressed at the designated area, the jazz melody would be played
    if (mouseX < width / 2 & mouseY < height / 2){
        jazzPlaying = jazzPlaying + 1;
//the music will be turned off once it has been clicked the second time 
        if (jazzPlaying % 2 == 0){
            jazz.play();
        } else {
            jazz.pause();
        }
    }
}

In this project, I aim to create an interactive program that plays four different types of music genre. By clicking on the icon, you are able to choose to turn on and off each type of music. The most interesting condition is when you turn on two or three type of music together, when they are playing simultaneously, it creates a surreal and yet fun melody.

Fanjie Jin-LookingOutwards-10

Artificial intelligence researchers have made huge gains in computational creativity and there have been a number of artists that employed computational algorithm to produce albums in multiple genres, such as scored films, games and smartphone apps. 

Bach-style Prelude 29, Experiments in Musical Intelligence

David Cope, a professor at California Santa Cruz, has been exploring the intersection of algorithms and creativity for decades and he is specialized in what he terms algorithmic composition which is essentially computer-authored music production. He writes sets of instructions that enable computers to automatically generate complete orchestral compositions. His algorithms have produced classical music ranging for single instruments arrangement all the way up to full orchestral music and it is really hard to believe that the music is composed through a computer. 

I really admire this project “Bach style Prelude 29 Emmy Cope”, which he has let the computer to study the composition style of Bach. As you can hear, the final melody that the AI algorithms generate is an accurate representation of Bach’s composition style and some parts of the AI-generated music have created some unexpected beautiful melodies which is totally based on Bach’s composition techniques. The biggest advantage of the AI algorithmic music composition is perhaps “Algorithms that produce creative work have a significant benefit, then, in terms of time, energy, and money, as they reduce the wasted effort on failed ideas.” said Cope. 

Fanjie Mike Jin- Project 09- Portraits

53

/*  Fanjie Mike Jin
    fjin@andrew.cmu.edu
    Section C
    Project-09*/

var baseimage

function preload() {
//load in the picture of myself
    var myImageURL = "https://i.imgur.com/gIuXiAy.jpg";
    baseimage = loadImage(myImageURL);
}

function setup() {
//drawing the image
    createCanvas(500, 500);
    background(0);
    baseimage.loadPixels();
// makes the pixels load faster
    frameRate(1000);
}

function draw() {
//Enable mouse interactions to gerate stroke elements
    var mousecolor = baseimage.get(mouseX, mouseY);
    var x = random(width);
    var y = random(height);
    var ix = constrain(floor(x), 0, width-1);
    var iy = constrain(floor(y), 0, height-1);
    var color = baseimage.get(ix, iy);

    noStroke();
    fill(mousecolor);
//paint the canvas with the mouse using smaller ellipses
    ellipse(mouseX,mouseY,random(4,20),random(4, 20));
    fill(color);
//Use polygons as pixels with the randomized number of sides and dimensions
    polygon(x,y,random(4,20),random(4,9));

}
//draw the polygons
function polygon(x, y, r, n) {
    var angle = TWO_PI / n;
    beginShape();
    for (var i = 0; i < TWO_PI; i += angle) {
        var a1 = x + cos(i) * r;
        var a2 = y + sin(i) * r;
        vertex(a1, a2);
    }
    endShape(CLOSE);
}

// reset the canvas to blank once the mouse is clicked 
function mousePressed() {
    clear();
}

In this project, I am trying to make the portrait in a rigid pointillism style as I really like the impressionist paintings. By varying the size of the randomized polygons, I am managing to simulate the feelings of that the protrait is being painted by rigid brushstrokes. Also, at the same time, I am able to make some touches to the image as the mouse interaction is enabled to digitally draw part of the portrait.

protrait after 1 min
protrait after 20 second
base image