Lan Wei-Final Project-MUSICAL UNIVERSE

sketch

//Lan Wei
//lanw@andrew.cmu.edu
//Section // D
//Final Project-Musical Universe

var snd = []; //this array will hold the sounds
var amplitude = [];
var ampTotal; //Total amplitude to change background color
var mouseXArray = []; //the array of X values
var mouseYArray = []; //the array of y values
var balls = []; //the array of ball objects
var np = 26; //the number of background lines
var pArray = []; //the array of particles

//preload the sounds
function preload() {
    var PREFIX = "https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/";
    for (var i = 1; i < 10; i++){
        var sound = loadSound(PREFIX + "sound" + i + ".wav"); //load sounds
        sound.setVolume(0.5);
        snd.push(sound); //push the sounds in snd. var sound will never be used again
    }
}

//make ball objects
function makeBalls(bx, by, br){
    var ball = {x: bx,
                y: by,
                r: br, //radius of the ball
                update: updateBall, //update the size of the balls
                sound: whichSound, //which amplitude is the ball related to
                draw: drawBall,
                play: playSound};
    return ball; //return the new object
}

function drawBall(){
    stroke(255);
    //ellipse(this.x, this.y, this.r, this.r);
    var total = 20; //control the density of the points on the balls
    for (var i = 0; i < total; i++){
        var longtitude = map(i, 0, total, -PI, PI);
        for (var j = 0; j < total; j++){
            var latitude = map(j, 0, total, -HALF_PI, HALF_PI);
            //fold the longtitude-latitude panel into a sphere
            var ptX = this.r * sin(longtitude) * cos(latitude);
            var ptY = this.r * sin(longtitude) * sin(latitude);
            var ptZ = this.r * cos(longtitude);
            push();
            stroke(255);
            translate(ptX, ptY, ptZ);
            sphere(0.1);
            pop();
        }
    }
}

function whichSound(){
    if (zone(this.x, this.y) == 1){
        return snd[0];
    }
    if (zone(this.x, this.y) == 2){
        return snd[1];
    }
    if (zone(this.x, this.y) == 3){
        return snd[2];
    }
    if (zone(this.x, this.y) == 4){
        return snd[3];
    }
    if (zone(this.x, this.y) == 5){
        return snd[4];
    }
    if (zone(this.x, this.y) == 6){
        return snd[5];
    }
    if (zone(this.x, this.y) == 7){
        return snd[6];
    }
    if (zone(this.x, this.y) == 8){
        return snd[7];
    }
    if (zone(this.x, this.y) == 9){
        return snd[8];
    }
}

function playSound(){
    var soundLocal = this.sound();
    soundLocal.play();
}

function updateBall(){
    var amp = amplitude[zone(this.x, this.y) - 1];
    var level = amp.getLevel(); //get the level
    this.r = 30 + 300 * level; //the size of balls
}

//particles to make background lines
function makeParticle(px, py, pdx, pdy){
    p = {x: px,
         y: py,
         dx: pdx,
         dy: pdy,
         update: pUpdate,
         draw: pDraw}
    return p;
}

function pUpdate(){
    this.x += this.dx;
    this.y += this.dy;

    //limit the lines in a certain area of 500 * 500 using 'bouncing'
    if (this.x < -250){ //left boundary
        this.x = -this.x - 250;
        this.dx = -this.dx - 250;
    }
    else if (this.x > 250){ //right boundary
        this.x = 300 - this.x;
        this.dx = 300 - this.dx;
    }
    if (this.y < -250){ //downward boundary
        this.y = -this.y - 250;
        this.dy = -this.dy - 250;
    }
    else if (this.y > 250){ //upward boundary
        this.y = 300 - this.y;
        this.dy = 300 - this.dy;
    }
}

function pDraw(){
    ellipse(this.x, this.y, 5, 5);
}
/////////////////////////////////////////////////////////////////////////////////////
function setup() {
    createCanvas(450, 450, WEBGL); // 3D mode. (0, 0)locates in the center of the canvas
    background(0);
    stroke(255);
    perspective(); //perspective view

    for (var i = 0; i < 9; i++){
        amplitude[i] = new p5.Amplitude();
        amplitude[i].setInput(snd[i]); //get independent amplitude
    }
    ampTotal = new p5.Amplitude(); //total amplitude

    for (var i = 0; i < np; i++){
        //the boundary of particles is a little bigger than the canvas
        var p = makeParticle(random(-300, 300), random(-300, 300), random(-2, 2), random(-2, 2));
        pArray.push(p);
    }
}

function draw() {
    var levelTotal = ampTotal.getLevel();
    var col = map(levelTotal, 0, 1, 0, 100);//background color
    background(col, 0, 2 * col);
    //draw background lines
    for (var i = 0; i < np; i++){
        pArray[i].update();
        pArray[i].draw();
        //lines between particles
        for (var j = 0; j < np/2; j++){
            stroke(random(0, 150));
            strokeWeight(0.2);
            line(pArray[j].x, pArray[j].y, pArray[j + np/2].x, pArray[j + np/2].y);
        }
    }
    //the canvas is divided by a 3*3 grid
    strokeWeight(1);
    stroke(random(20, 70));
    line(-75, -225, -75, 225);
    line(75, -225, 75, 225);
    line(-225, -75, 225, -75);
    line(-225, 75, 225, 75);

    if (mouseXArray.length != 0){ //after the 1st mouse press
        stroke(255);
        fill(255);
        // draw all the balls
        for (i = 0; i < balls.length; i ++){
            balls[i].update(); //update the radius of the balls
            push();
            translate(balls[i].x, balls[i].y, 0);
            //rotate with randomness
            rotateX(frameCount * 0.05 + i);
            rotateY(frameCount * 0.05 + i * 5);
            rotateZ(frameCount * 0.05 + i * 5);
            balls[i].draw(); //draw the balls
            pop();
        }
    }
}

//To identify which zone is the ball in
//translate the coordinate to normal mode
function zone(x, y){
    if ((y > -225 )& (y < height/3 - 225)){
        if ((x > -225) && (x < width/3 - 225)){ //position 1
            return 1;
        }
        if ((x > width/3 - 225) & (x < 2 * width/3 - 225)){ //position 2
            return 2;
        }
        if ((x > 2 * width/3 - 225) & (x < width - 225)){ //position 3
            return 3;
        }
    }

    if ((y > height/3 - 225) & (y < 2 * height/3 - 225)){
        if ((x > -225) && (x < width/3 - 225)){ //position 4
            return 4;
        }
        if ((x > width/3 - 225) & (x < 2 * width/3 - 225)){ //position 5
            return 5;
        }
        if ((x > 2 * width/3 - 225) & (x < width - 225)){ //position 6
            return 6;
        }
    }

    if ((y > 2 * height/3 - 225) & (y < height - 225)){
        if ((x > -225) && (x < width/3 - 225)){ //position 7
            return 7;
        }
        if ((x > width/3 - 225) & (x < 2 * width/3 - 225)){ //position 8
            return 8;
        }
        if ((x > 2 * width/3 - 225) & (x < width - 225)){ //position 9
            return 9;
        }
    }
}

//when mouse is clicked, a sound will be played and a ball will be drawn
function mouseClicked(){
    var clickOn; //to check whether click on an existing ball
    var newBalls = [];
    var newMouseXArray = [];
    var newMouseYArray = [];

    if (mouseXArray.length == 0){ //when there is no existing balls
        clickOn = 0;
        newBalls.push(balls[0]);
        newMouseXArray.push(mouseXArray[0]);
        newMouseYArray.push(mouseYArray[0]);

    }

    // a ball will be removed when clicked again
    else{ //after the 1st click
        for (i = 0; i < balls.length; i++){
            var distance = dist(mouseX - 225, mouseY - 225, balls[i].x, balls[i].y);
            //is clicked
            if (distance <= 20){ //minimum distance
                var soundBall = balls[i].sound();
                soundBall.setVolume(0); //stop the sound of the ball that's clicked
                // balls.splice(i, 1); //remove the ball
                // mouseXArray.splice(i, 1);
                // mouseYArray.splice(i, 1);
                clickOn = 1;
            }
            //is not clicked
            else{
                clickOn = 0;
                newBalls.push(balls[i]);
                newMouseXArray.push(mouseXArray[i]);
                newMouseYArray.push(mouseYArray[i]);
            }
        }
        balls = newBalls;
        mouseXArray = newMouseXArray;
        mouseYArray = newMouseYArray;
    }
    if (clickOn == 0){
        mouseXArray.push(mouseX - 225);//translate to WEBGL coordinates
        mouseYArray.push(mouseY - 225);
        // initial radius: 30
        //make ball objects
        var newBall = makeBalls(mouseX - 225, mouseY - 225, 30);
        balls.push(newBall);

    }
    //play sound using the object
    for (i = 0; i < balls.length; i++){
        var soundLocal = balls[i].sound();
        balls[i].play();
        soundLocal.loop();
    }
}

//YOU'VE GOT A MUSICAL UNIVERSE!!!

[How to play]: Click on different positions of the canvas to get different mixtures of ‘UNIVERSE MUSIC’,click the balls again to remove them as well as the sound (in the opposite order you created the balls). Play slowly! (Sometimes it doesn’t work well if played fast, maybe it’s my browser’s problem.)

My initial idea of the project is to create a simple instrument that enables users to mix several pieces of music. In the proposal stage, I have imagined many sound effects and interaction methods, but have only achieved part of them. The actual coding process is much harder than I thought, and the final result becomes more visual than auditory. But actually, I’m very happy about the project because it is really a reviewing as well as a learning process. I’m not very good at using objects and particles so I tried to include these contents in my project. And I also watched some online tutorials to create the 3D effect of the balls. The final result is very satisfying for me, especially the 3D ball effect!

Have Fun!

 

Lan Wei-Project 12-Proposal

What I want to do for the final project is something about music but also has visual effects. I want the project to be interactive, meaning that people can create their own music (probably unconsciously). The detailed effect that I’ve imagined is that in the canvas of ‘universe’, people can create planets every time they click, and each zone of the canvas is related to a related piece of rhythm. By clicking in different areas of the canvas different sound effects are created. The visual effect of the planets needs some planning. I’m thinking that when a point is clicked, some repulsion is generated from this point and shapes are pushed away from the point, and thus a planet is generated. It would be nice if the planets can rotate from its position in a 3D mode and also oscillate with the volume of the rhythm. Other effects might be added to make the project more interactive and playful. I’m really looking forward to it.

Lan Wei-Looking Outwards-12

The project ‘Rotary tumble’ was created by Muharrem Yildirim and David Tinapple in 2012. The amazing part of the project is that both human action and physical principles are integrated into it. The blurring boundary of the physical world and the virtual world is also one idea that I want to achieve in my final project. In addition, the use of sound in the project also strengthens the visual effect. Thinking about how to improve the project, I feel it’s even better to make the screen touchable, meaning that people can move the shapes with their hands, and more sound effects can be added.

The second project is Dream Catcher created by Oggy (full name and date unknown). The amazing beauty of processing can be fully seen in this project. The common feature of this project with the first one and also what interests me the most is that they both imitate natural principles, which in this one is the flow of wind. What I feel missing in the project is sound. Compared to the first one, this one can be seen both as an interactive project and merely a visual project. But both of the projects are very inspiring to my final project.

Lan Wei-Project 11-Composition

my-sketch.js

//Lan wei
//Section D
//lanw@andrew.cmu.edu
//Project-11

var img;
var repeatTime = 1; // time repeated before the painting is finished
var numEachTime = 10; // number of turtles in each repeat time
var randomYArrays = []; //nested arrays including Y in each repeat time
var randomY = []; //arrays of Y in each repeat time
var bri; //brightness of the pixel

function preload(){
    img = loadImage("https://i.imgur.com/9e7ATQI.jpg?1.jpg");
}

function setup() {
    createCanvas(450, 450);
    img.loadPixels();
    background(0);
    for (var i = 0; i < repeatTime; i ++){
        for (var j = 0; j < numEachTime; j ++){ //add "numEachTime" values in randomY
            randomY.push(random(0, height));
        }
        randomYArrays.push(randomY);
        randomY = [];
    }
    frameRate(1);
}

function draw() {
    for (var i = 0; i < repeatTime; i ++){
        randomY = randomYArrays[i];
        for (var n = 0; n < numEachTime; n ++){
            drawTurtle(-100, randomY[n]);
        }
    }
}

function drawTurtle(tx, ty){
    var ttl = makeTurtle(tx, ty);
    ttl.penDown();

    //step 1
    bri = brightness(img.get(ttl.x, ttl.y)); //brightness of the pixels
    ttl.setColor(map(bri, 0, 100, 255, 70));
    ttl.setWeight(map(bri, 0, 100, 1, 2)); //change light weight according to brightness
    ttl.forward(random(20, 50));

    //step 2
    for(var i = 0; i < 15; i ++){
        var angle = 0;
        while (angle < 30){
            var angleSingleTime = random(0, 20);
            ttl.left(angleSingleTime);
            bri = brightness(img.get(ttl.x, ttl.y)); //brightness of the pixels
            ttl.setColor(map(bri, 0, 100, 255, 70));
            ttl.setWeight(map(bri, 0, 100, 1, 2)); //change light weight according to brightness
            ttl.forward(random(1, 3));
            angle += angleSingleTime;
        }

        //step 3
        while (angle < 90){
            var angleSingleTime = random(0, 20);
            ttl.right(angleSingleTime);
            bri = brightness(img.get(ttl.x, ttl.y)); //brightness of the pixels
            ttl.setColor(map(bri, 0, 100, 255, 70));
            ttl.setWeight(map(bri, 0, 100, 1, 2)); //change light weight according to brightness
            ttl.forward(random(1, 3));
            angle += angleSingleTime;
        }

        //step 4
        while (angle < 120){
            var angleSingleTime = random(0, 20);
            ttl.left(angleSingleTime);
            bri = brightness(img.get(ttl.x, ttl.y)); //brightness of the pixels
            ttl.setColor(map(bri, 0, 100, 255, 70));
            ttl.setWeight(map(bri, 0, 100, 1, 2)); //change light weight according to brightness
            ttl.forward(random(1, 3));
            angle += angleSingleTime;
        }

        //step 5
        bri = brightness(img.get(ttl.x, ttl.y)); //brightness of the pixels
        ttl.setColor(map(bri, 0, 100, 255, 70));
        ttl.setWeight(map(bri, 0, 100, 1, 2)); //change light weight according to brightness
        ttl.forward(random(20, 50));
    }
}

/////////////////////////////////////////////////////////
function turtleLeft(d){this.angle-=d;}function turtleRight(d){this.angle+=d;}
function turtleForward(p){var rad=radians(this.angle);var newx=this.x+cos(rad)*p;
var newy=this.y+sin(rad)*p;this.goto(newx,newy);}function turtleBack(p){
this.forward(-p);}function turtlePenDown(){this.penIsDown=true;}
function turtlePenUp(){this.penIsDown = false;}function turtleGoTo(x,y){
if(this.penIsDown){stroke(this.color);strokeWeight(this.weight);
line(this.x,this.y,x,y);}this.x = x;this.y = y;}function turtleDistTo(x,y){
return sqrt(sq(this.x-x)+sq(this.y-y));}function turtleAngleTo(x,y){
var absAngle=degrees(atan2(y-this.y,x-this.x));
var angle=((absAngle-this.angle)+360)%360.0;return angle;}
function turtleTurnToward(x,y,d){var angle = this.angleTo(x,y);if(angle< 180){
this.angle+=d;}else{this.angle-=d;}}function turtleSetColor(c){this.color=c;}
function turtleSetWeight(w){this.weight=w;}function turtleFace(angle){
this.angle = angle;}function makeTurtle(tx,ty){var turtle={x:tx,y:ty,
angle:0.0,penIsDown:true,color:color(128),weight:1,left:turtleLeft,
right:turtleRight,forward:turtleForward, back:turtleBack,penDown:turtlePenDown,
penUp:turtlePenUp,goto:turtleGoTo, angleto:turtleAngleTo,
turnToward:turtleTurnToward,distanceTo:turtleDistTo, angleTo:turtleAngleTo,
setColor:turtleSetColor, setWeight:turtleSetWeight,face:turtleFace};
return turtle;}

I planned to draw abstract ‘Sherlock’ with turtles. The process didn’t go smoothly. I tested different moving modes of the turtles and finally decided to use the one with some randomness but generally moving from the left of the canvas to the right. There are some aspects of the project that don’t reach my expectation (for example the nested loop might have some problems), but the result is good and the effect of old movie is kind of surprising.

Process Sherlock 1
Process Sherlock 2

Lan Wei-Looking Outwards-11

The name of the project is ‘Mr Shadow’ and the project was created by Scientists at SONY CSL Research Laboratory in 2016.

I looked at lots of videos about computer music before decided to investigate this one. The reason is that for me most of the ‘computer music’ are only making use of computers to save time in producing the rhythms without digging into the specialities of computers. But this one produced by Artificial Intelligence is special in my perspective. It contains not only rhythms that lift people’s spirit, but also, most importantly, human motions. It’s exciting to see how a ‘dead’ computer can produce such vivid music with ups and downs through analysing precedents. And this leads to another question: whether computers will replace artists totally in the future? I can write an essay about this but I’m not going to discuss the topic here. I just want to say this project is very exciting and inspiring.

Besides the music itself, the graphic effect is also very good and it echoes with the music very well. In general, the computer-generated music really takes me into its world.

Lan Wei – Project 10 – Generative Landscape

my-sketch.js

//Lan Wei
//Section D
//lanw@andrew.cmu.edu
//Project 10 - Generative Landscape

//Cave people

var groundDetail = [0.004, 0.0001, 0.005, 0.002];
var groundSpeed = 0.0005;
var minY = [-10, 70, 110, 300]; //min values of terrain domains
var maxY = [150, 120, 300, 400]; //max values of terrain domains
var people = [];

function setup() {
    createCanvas(450, 450);
    frameRate(10);

    // initial people
    for (var i = 0; i < 7; i++){
        var rx = random(width);
        var ry = random(290, 313);
        people[i] = makePeople(rx, ry);
    }
}

var moonX = 450;

function draw() {
    //mountains & ground
    background(8, 46, 84);
    var colMountain = color(0);
    var colGround = color(176, 23, 31);
    var colHole = color(255, 222, 173);
    var col = [colMountain, colGround, colHole, colGround];
    noStroke();

    //moon
    moonX -= 1;
    fill(190);
    ellipse(moonX, 30, 70, 70);
    fill(255);
    ellipse(moonX, 30, 60, 60);

    for (var i = 0; i < 4; i ++){
        var yRange = [];
        fill(col[i]);
        beginShape();
        for (var x = 0; x < width; x++) {
            var t = (x * groundDetail[i]) + (millis() * groundSpeed);
            var y = map(noise(t), 0, 1, minY[i], maxY[i]);
            if (i === 0){ // reverse the direction of the mountains
                y = ((maxY[i] - minY[i]) - 1.5 * y);
            }
            vertex(x, y);
            yRange.push(y);
        }
        vertex(width, yRange[width - 1]);
        vertex(width, height);
        vertex(0, height);
        vertex(0, yRange[0]);
        endShape();

        if (i === 2){  ////the legs should be coverd by the bottom ground
            updateAndDisplayPeople();
            removePeopleThatHaveSlippedOutOfView();
            addNewPeopleWithSomeRandomProbability();
        }
    }
}

function updateAndDisplayPeople(){
    for (var i = 0; i < people.length; i++){
        people[i].move();
        people[i].display();
    }
}

function removePeopleThatHaveSlippedOutOfView(){
    var peopleToKeep = [];
    for (var i = 0; i < people.length; i++){
        if (people[i].x + people[i].bellyWidth/2 > 0) {
            peopleToKeep.push(people[i]);
        }
    }
    people = peopleToKeep; // remember the surviving buildings
}

function addNewPeopleWithSomeRandomProbability() {
    var newPeopleLikelihood = 0.2;
    if (random(0,1) < newPeopleLikelihood) {
        people.push(makePeople(width, random(290, 303)));
    }
}

function makePeople(bellyX, bellyY){
    var ppl = {x: bellyX,/////////////////////////belly
               y: bellyY,
               speed: -10,
               bellyWidth: random(23, 47),
               bellyHeight: random(50, 59),
               bellyCol: random(70, 255),
               headD: 10,/////////////////////////head
               headCol: random(20, 90),
               legY: bellyY,//////////////////////legs
               move: pplMove,
               display: pplDisplay}
    return ppl;
}

function pplMove(){
    this.x += this.speed;
}

function pplDisplay(){
    //head
    noStroke();
    fill(this.headCol);
    ellipse(this.x, this.y - this.bellyHeight/2 - 10, this.headD, this.headD);
    //legs
    noFill();
    stroke(0);
    strokeWeight(2);
    line(this.x - this.bellyWidth/4, this.legY, this.x - this.bellyWidth/4, height);
    line(this.x + this.bellyWidth/4, this.legY, this.x + this.bellyWidth/4, height);
    //belly
    noStroke();
    fill(this.bellyCol);
    ellipse(this.x, this.y, this.bellyWidth, this.bellyHeight);
}

This is my first time to practice using objects and it was tough but very fun.  I started with doing sketches and decided to make cave people at the end. Making mountains ground and the cave took me a while since I need to create several different noises with different qualities and I would like to do it with  loops. For the people part, I studied the building example and did modifications based on that, which is also challenging. To be honest, at the beginning I planned to achieve something more complicated but the process is more challenging than I’ve imagined so I simplified it a bit. But anyway, I feel that the  project helps me a lot to understand objects and the result makes me very happy.

Sketch

Lan Wei-Looking Outwards 10

                                         People interacting with the structure
                                                              Part of the structure

The project’s name is Branching Morphogenesis, created by Jenny Sabin. I love the spatial effect of the project. People can walk through and see through the structure at the same time and get varies of experiences because of different densities of the elements in different places. When looking at the project closely, I’m surprised to know that the whole structure was made out of 75,000 zip ties, and it is just so amazing to see how the small forces inside of each zip tie can work together and support such a huge structure.

Jenny Sabin is an architect, designer, artist and professor (Cornell University) who draws upon biology and mathematics to design material structures. She emphasises computaional design and digital fabrication a lot in her projects. Her projects, whether large-scale or small-scale, generally have strong spatial effect and interactive possibilities. It is easy to notice that she creates a lot of holes in many of her projects, and I believe her intention is to encourage visual connections.

                                               Material: zip ties

Lan Wei-Project 09-Portrait

my-sketch.js

//Lan wei
//lanw@andrew.cmu.edu
//Section D
//Project-09

var img;
var url;
function preload() {
    url = "https://i.imgur.com/LwxpUPT.jpg";
    img = loadImage(url);
    frameRate(10);
}

function setup() {
    createCanvas(300, 400);
    background(255);
    img.loadPixels();
}

function draw() {
   var x = floor(random(img.width));
   var y = floor(random(img.height));
   push();
   translate(x, y);
   var col = img.get(x, y);
   stroke(col);
   strokeWeight(map(brightness(col), 0, 100, 3, 1)); //line weight depending on brightness
   var length = map(brightness(col), 0, 100, 25, 5); //line length depending on brightness
   rotate(random(0, PI));
   line(- length/2, 0, length/2, 0);
   pop();
}

My idea is using lines to create the abstract portrait. To emphasize the human figure instead of the dark background, and also to make bright areas look brighter, I made the lines in areas with smaller brightness thicker and longer. I think it would look nicer if I choose a picture with more color changes.

Process effect

Lan Wei-LookingOutwards-09

Cylindrical Mesh Topologies
Hyper-Toroidal Deep Surface

The works are shown in the exhibition ‘Textile Morphologies'(2013)  showcasing the doctoral work of Sean Ahlquist. And the original post is from Sophia Kim in Section C. I agree with her the impression of molecules and I did more background research after reading her post.

At first, what fascinates me of the project was the designer making use of the inner tension between objects to create forms. I felt the technological as well as the aesthetic thinkings behind the artwork. After further research, I’m even more interested because of the spatial potention of it. What presented in the exhibition was actually prototypes of tactile interfaces and environments for developing motor skills and social interaction in children with autism. I regarded the work as ‘art’ at the first glance but suddenly the scientific thinkings and profund meaning behind unveil before my eyes. I think computational tools play very important roles in the design process in analyzing the relationship between the form and effects on human such as visuality and touchability and also the integration of the forms and other technologies such as projection.

Children playing with the installation
Form analysis

The project

Textile Morphologies

LookingOutwards-03 Sophia Kim-Sec C

Lan Wei-LookingOutwards-08

The lecture is given by James Paterson, a Montreal-based artist and coder who dedicates to explore the intersection of animation, art and code. James is interested in the boundary between reality and virtuality, which is also the main topic of the lecture. His projects cover a wide domain, which includes art direction, VR & AR and animation.

This lecture interests me because it unveils new possibilities for artists in creating things. Animation is not about something that just happens in computers any more, but things that can merge with everyday life and blur the boundary between real life and virtuality. The work I admire the most of James is created by a tool he created called Norman, which enables him to create 3D animation easily with only lines. In the later part of the lecture, there is even examples that Norman being integrated with real-world scenes. I totally think the tool gives drawings a new life.

James presents his work clearly by dividing his works into different categories and talking about one category at one time. This is an useful presenting method that I can learn from the lecture.

James Paterson’s website:

http://presstube.com/hello/