Looking Outwards: 06

Vera Molnar is a pioneer in computational and generative art work. She began writing computer code that introduced randomness to her art in the mid to late 1960s. Even earlier she was creating manual rules and algorithms to generate computational art by hand. She began writing code in Fortran back at a time when they used punch cards to feed a program into the computer. The randomness, she explained, gives her ideas and allows her to try out endless variations of her work. This enables her to create works that she may never have thought of on her own. She explains that the computer is not taking the place of the artist; it is simply a tool.
For this project I became intrigued with her Variations exposition at the Beall Center at the University of California in Irvine. The art works presented are generative both through computer programming and also from her manual algorithms. The piece that resonated with me most is called Interruptions and is presented below. This work is a series of short random lines. She worked with this program and introduced the removal of lines in the randomness algorithm as well. The gaps give the work its name, Interruptions. I really enjoy that she plays with the removal of what is already there. Each iteration of the program creates a unique image. It is compelling to see what gets left behind in the empty spaces.

Interruptions

Project 5: Wallpaper, Section B

Flower of Life Wallpaper

Sketch
/* Evan Stuhlfire
** estuhlfi@andrew.cmu.edu, section B
** Project 05: Wallpaper */

var dot = 5;
var bigDot = 10;

function setup() {
    createCanvas(600, 400);
    background(224, 223, 214);
    rectMode(CENTER);
}

function draw() {
    var rowHeight = 150;
    var colCount = 1; 
    var circleDiam = 50;
    var circleOffset = 10;
    var cosAmplitude = 40; // height of cos wave
    var sinAmplitude = 60; // height of sin wave
    var sinInc = 5; // increase for sin offset

    // Iterate over row to create rows of sin and cos waves
    for(var row = 0; row < height + rowHeight; row += rowHeight) {
        var colCounter = 0; // reset column counter for new row

        // iterate over theta to draw cos waves in background
        for(var theta = 0; theta < width; theta++) {
            stroke(49, 54, 56, 45);
            circle(theta, row + cosAmplitude * cos(radians(theta)), .2);
            circle(theta, row + cosAmplitude * -cos(radians(theta)), .2);
        }

        // iterate over theta to draw sin waves
        for(var theta = 0; theta < width + circleDiam; theta++) {
            stroke(49, 54, 56, 70);
            fill(49, 54, 56, 70);
            // draw sin waves as circles as theta moves across canvas
            // increment the sinAmplitude to create layered affect
            // decrease diam of circles to decrease line weight
            circle(theta, row + sinAmplitude * sin(radians(theta)), 2);
            circle(theta, row + (sinAmplitude + sinInc) * 
                sin(radians(theta)), 1);
            circle(theta, row + (sinAmplitude + 2 * sinInc) * 
                sin(radians(theta)), .2);
            circle(theta, row + sinAmplitude * -sin(radians(theta)), 2);
            circle(theta, row + (sinAmplitude + sinInc) * 
                -sin(radians(theta)), 1);
            circle(theta, row + (sinAmplitude + 2 * sinInc) * 
                -sin(radians(theta)), .2);

            // every 90 degrees draw a design
            if(theta % 90 == 0) {
                colCounter++;
                // when inside the sin waves draw circle of life
                if(colCounter % 2 == 0) {
                    stroke(49, 54, 56, 175);
                    fill(224, 223, 214);
                    drawLife(theta, row);
                } else {
                    // draw ellipses at intersection of sin waves
                    stroke(49, 54, 56, 50);
                    fill(224, 223, 214);
                    // draws concentric ellipses
                    for(var i = circleDiam; i >= 15; i -= 15){
                        ellipse(theta, row, i + circleOffset, i);
                    }
                    fill(49, 54, 56, 140);
                    ellipse(theta, row, bigDot); // draw dots at intersections

                    // draw little flowers
                    drawLittleFlowers(theta, row);
                } 
            }
        }
    }
    noLoop();
}

function drawLife(theta, row) {
    // draw the circle of life
    // set variable for circle dimensions and offset angles
    var bigDiam = 110;
    var diam = 30; // set smaller circle diameter
    var ellipseOffset = 20;
    var rad = diam/2;
    var angle1 = 30;
    var angle2 = 5 * angle1;
    var angle3 = 45;
    var oneEighty = 180;
    var angleOffset = 2;
    var diamOffset = 5;

    push(); // save settings
    translate(theta, row); // reposition origin
    stroke(49, 54, 56, 90); // lighten inner circles
    // draw larger ellipse
    ellipse(0, 0, bigDiam, bigDiam - ellipseOffset);

    // draw center circle
    circle(0, 0, diam);

    noFill();
    // draw layers of circles with drawMoreCircles with 
    // distance from center, diameter, and angle of offset
    // inner layer of circles
    drawMoreCircles(rad, diam, oneEighty/2);
    drawMoreCircles(rad, diam, angle1);
    drawMoreCircles(rad, diam, angle2);

    // second layer of circles
    drawMoreCircles(diam, diam, oneEighty/2);
    drawMoreCircles(diam, diam, angle1);
    drawMoreCircles(diam, diam, angle2);
    drawMoreCircles(diam - diamOffset, diam, oneEighty);
    drawMoreCircles(diam - diamOffset, diam, 0);
    drawMoreCircles(diam - diamOffset, diam, angleOffset * angle1); 
    drawMoreCircles(diam - diamOffset, diam, 2 * angleOffset * angle1);
    
    // third layer of circles
    // adjustments to offset diam and angle
    drawMoreCircles(diam + rad - diamOffset, diam, oneEighty - 
        (5 * angleOffset));
    drawMoreCircles(diam + rad - diamOffset, diam, -5 * angleOffset)

    pop(); // retore settings
    fill(120); // solid grey
    // draw center flower dot
    ellipse(theta, row, dot);
}

function drawMoreCircles(expand, diam, angle) {
    // draw two circles at opposite angles defines by the 
    // distance from the center, diameter, and offset angle
   circle(expand * cos(radians(angle)), expand * sin(radians(angle)), diam);
   if(angle != 180 & angle != 0){
       circle(expand * cos(radians(-angle)), expand * 
        sin(radians(-angle)), diam);
   }
}

function drawLittleFlowers(theta, row) {
    var rowOffset = 75;
    var petalLength = 15;
    var petalWidth = 4;
    var petals = 6;
    var angle = 30;
    var angleIncrease = 60;
    var diam = 30;
    var accentOffset1 = 7;
    var accentOffset2 = 10;
    var ellipseOffset = 10;

    // set color for flower petals
    stroke(49, 54, 56, 100);
    fill(224, 223, 214);

    // draw circle to contain flower
    ellipse(theta, row + rowOffset, diam + ellipseOffset, diam);
    circle(theta, row + rowOffset, diam);
    // draw the petals
    for(var i = 0; i < petals; i++){
        push(); // save settings
        translate(theta, row + rowOffset);
        rotate(radians(angle)); 
        ellipse(petalLength/2, 0, petalLength, petalWidth);

        // draw accent lines with offsets
        line(petalLength + accentOffset1, 0, petalLength + accentOffset2, 0);
        pop(); // restore settings

        angle += angleIncrease;
    }
    // draw the center dot
    fill(120); // solid grey
    ellipse(theta, row + rowOffset, dot);
}

Looking Outwards 05: 3D Computer Graphics, Section B

Mikael Hvidtfeldt Christensen is a generative artist with a background in physics and computational chemistry. He generates 3D images in a project called Syntopia. His works are varied and experimental. He keeps a blog and a Flickr account of his finished works and his experiments. I admire his sharing the results of his experiments with the world. Even though they are not completed works they are inspiring and show the iterative process that goes into creating a project.


Most of Christensen’s images are geometric renderings of complex shapes and building designs; however he has also created color swapping algorithms and texturizing art. The images from these projects take existing images and sort the colors into layers or add disturbing textures, such as lizard scales to lettuce.


Christensen is passionate about complex systems and has written his own software to generate and render his images. His software, Structure Synth, is available for download and can be found here. It is written in C++, OpenGL, and Qt 4.

Project-04: String Art-Section B

All Seeing Eye.

sketch
/*
* Evan Stuhlfire
* estuhlfi@andrew.cmu.edu
* Section B
*
* Project-04: String Art
* This program uses geometric shapes to create
* string art.
*/

function setup() {
    createCanvas(400, 300);
    background(73, 80, 87); //davys grey from coolors.com

}

function draw() {   
    // draw the string lines for the frame in light blue
    stringLeftLower(204, 255, 255, 55);
    stringLeftUpper(204, 255, 255, 55);
    stringRightUpper(204, 255, 255, 55);
    stringRightLower(204, 255, 255, 55);

    // move origin of canvas to center
    translate(width/2, height/2);

    // draw the circle design with light blue
    stringCircle(204, 255, 255); 
    noLoop();
}

/* draw the string pattern at the lower left */
function stringLeftLower(r, g, b, t) {
    var numLines = 40;
    var x1 = 0; // start at top right
    var y1 = 0; // top right
    var y2 = height;
    var x2 = xInc = (width/numLines);
    var yInc = (height/numLines);

    stroke(r, g, b, t);
    // iterate over each line to draw
    for (index = 0; index < numLines; index ++) {
        line(x1, y1, x2, y2);
        y1 += yInc;
        x2 += xInc;
    }
}

/* draw the string pattern at the upper left */
function stringLeftUpper(r, g, b, t) {
    // set vars to start at lower left and draw up
    var numLines = 40;
    var x1 = 0;
    var y1 = height; // lower left
    var y2 = 0;
    var x2 = xInc = width/numLines;
    var yInc = height/ numLines;

    stroke(r, g, b, t);
    // iterate over each line to draw
    for (index = 0; index < numLines; index ++) {
        line(x1, y1, x2, y2);
        y1 -= yInc; // move up the canvas
        x2 += xInc; // move across the canvas
    }
}

/* draw the string pattern at the upper right */
function stringRightUpper(r, g, b, t) {
    var numLines = 40;
    var x1 = xInc = width/numLines;
    var x2 = width;
    var y1 = 0;
    var y2 = 0;
    var yInc = height/ numLines;

    stroke(r, g, b, t);
    // iterate over each line to draw
    for (index = 0; index < numLines; index ++) {
        line(x1, y1, x2, y2);
        y2 += yInc; // move down the canvas
        x1 += xInc; // move right across the canvas
    }
}

/* draw the string pattern at the lower right */
function stringRightLower(r, g, b, t) {
    // set variable
    var numLines = 40;
    var x1 = width; // right side
    var x2 = 0;
    var xInc = width/numLines;;
    var yInc = height/numLines;
    var y1 = height - yInc; // bottom right
    var y2 = height;

    stroke(r, g, b, t); // set color and transparency
    // iterate over each line to draw
    for (index = 0; index < numLines; index ++) {
        line(x1, y1, x2, y2); 
        y1 -= yInc; // move up the canvas
        x2 += xInc; // move right across the canvase
    }
}

/* draw the center string circle */
function stringCircle(r, g, b) {
    // 36 spokes on the circle design
    var circlePoints = 36;
    var angle = 0;
    var rotDeg = 0;

    // iterate over each spoke
    for (index = 0; index < circlePoints; index++) {
        // save settings
        push();

        // map the angle to the perimeter of the circle
        angle = map(index, 0, circlePoints, 0, TWO_PI);

        // convert angle to x y coordinates
        var radius = 90;
        var circleX = radius * cos(angle);
        var circleY = radius * sin(angle);

        // move origin to the starting point of the circle
        translate(circleX, circleY);

        // rotate each spoke to the origin
        rotate(radians(rotDeg));

        // variables for drawing string design
        var circleX2 = -radius * 2;
        var circleY2 = 0;
        var smallCircleDiam = 10;
        var offset = 15;

        // draw small circles at end of spokes
        stroke(r, g, b, 255);
        circle(0, 0, smallCircleDiam * .2);
        noFill();
        circle(0, 0, smallCircleDiam); // outline

        // set stroke color and decrease transparency to
        // see more detail.
        stroke(r, g, b, 125); 

        // draw three lines from each perimeter point to
        // create spokes
        line(0, 0, circleX2, circleY2);
        line(0, 0, circleX2, circleY2 + offset);
        line(0, 0, circleX2, circleY2 -offset);

        // extend lines off of spokes
        stroke(r, g, b, 50);
        line(0, 0, offset * 8, circleY2);
        line(0, 0, offset * 8, circleY2 + offset);
        line(0, 0, offset * 8, circleY2 -offset);

        // call function to draw the background circles with
        // transparancey
        backgroundCircles(index, offset, r, g, b, 80);

        pop(); // restore settings 
        rotDeg += 10; // rotate 10 degrees 36/360
    }
}

/* draw the background circles with design */
function backgroundCircles(index, offset, r, g, b, t) {
    // save settings
    push();
    stroke(r, g, b, t); // light blue with transparency
    // rest origin, space circles out
    translate(25, 0);

    // draw small inner circle on even spoke
    if (index % 2 == 0) {           
        circle(0, 0, 20);
        circle(110, 0, 70);
    } else {
        var diam = offset * 4; // set diameter
        // draw bigger circle on odd spoke
        circle(offset * 3, 0, diam);

        // string design of four circles inside each 
        // bigger circle
        var shiftValue = 10;
        circle(offset * 3, -shiftValue, diam/2);
        circle(offset * 3, shiftValue, diam/2);
        circle(offset * 3 + shiftValue, 0, diam/2);
        circle(offset * 3 - shiftValue, 0, diam/2);
    }
    pop();// restores settings
}

Looking Outwards-04-Section B

Experiments in Musical Intelligence, EMI or EMMY, is a program that analyzes musical compositions and generates entirely new compositions that emulate the sound, style, mood, and emotion of the original. Written by composer, author, and scientist, David Cope, this project allows entirely new compositions to be algorithmically generated in the style of any composer. Compositions have been generated in the styles of Bach, Beethoven, Chopin, and many more, including Cope himself. In fact, Cope’s original inspiration for the software project was writer’s block. He was stuck and wanted to identify his own compositional style.

Although the software is data driven and bases its compositions on works by the original composer, it never repeats or copies the original work. The compositions generated are unique. Cope’s software deconstructs the original works; then records their time signatures. The final step runs the data through a recombinant algorithm for which Cope holds a patent.

This project was truly revolutionary for its time. It inspires questions about creativity and the mind. Originally written in the LISP programming language in the 1980s, it has been modified to use AI techniques as they have advanced. Interestingly, the generative compositions have been used in a type of Turing Test. One particular test set out to see if audiences could identify which of three compositions was actually composed by Bach, which was an emulated composition written by a human, and which was generated by a computer. Audiences chose the EMMY generated composition as the actual Bach. Perhaps EMMY is the first piece of software to pass the Turing Test.

To learn more about David Cope and EMMY click here and here.

Project-03-Dynamic-Drawing: Section B

My process for this project was to alter basic shapes and colors to create a kaleidoscope. I used transformations so I could draw the same images many times in different locations. Moving the mouse left and right shrinks, enlarges, and repositions different elements. Crossing the horizontal midpoint reverses the rotation. Vertical motion with the mouse speeds and slows the rotation. Clicking changes colors.

From my sketchbook.
sketch
// Evan Stuhlfire
// estuhlfi, section B
// Project-03: Dynamic Drawing

var angle = 0; // Angle to increment for rotation
var angleInc = 2; // Controls speed of rotation
var rotateDir = 1; // Direction of rotation
var centerX; // Center of original canvas
var centerY;
var shapeSpace = 30; // Space between shapes
var rectSize = 20;
var startSize = 10;
var circleStart = 10;
var littleCircle = 10;
var colorScheme = 1; // standard = 1, switched = -1

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

    centerX = width/2;
    centerY = height/2;
}

function draw() {
    background(50);

    // If the mouse is left of center set rotation counterclockwise
    if(mouseX < centerX){
        rotateDir = -1;
    } else {
        rotateDir = 1; // Set rotation clockwise
    }

    // Translate the canvas origin to the center
    translate(centerX, centerY);

    // Save the current settings
    push();

    // Rotate the canvas for the shape redraw
    rotate(radians(angle * rotateDir));

    // Draw background circle
    fill(120, 88, 111);
    stroke(120, 88, 111);
    ellipse(0, 0, height, height);

    // Draw center rectangle
    fill(230, 199, 156);
    stroke(230, 199, 156);
    rectMode(CENTER); // Center rect around (0,0)
    rect(0,0, rectSize, rectSize);
    rect(0, 0, rectSize * mouseX/15, rectSize * mouseX/15);

    // Draw center crossing rectangles
    if(colorScheme == 1){
        fill(123, 158, 168); // grey blue
        stroke(123, 158, 168);
    } else {
        fill(111, 208, 140); // green
        stroke(111, 208, 140);
    }
    
    rect(0, 0, 25, width * 1.5);
    rect(0,0, width * 1.5, 25);

    // Draw little circle
    fill(120, 88, 111);
    stroke(120, 88, 111);
    ellipse(0, 0, littleCircle * mouseX/15, littleCircle * mouseX/15);

    // Draw four spokes of ellipses and diamonds 
    // at 90 degree intervals
    drawEllipse();
    drawRects();
    
    rotate(radians(90));
    drawEllipse();
    drawRects();

    rotate(radians(90));
    drawEllipse();
    drawRects();

    rotate(radians(90));
    drawEllipse();
    drawRects();

    // Return to saved settings
    pop();

    angle = angle + mouseY/100;
}

function drawEllipse(){
    // Set color of ellipses
    if(colorScheme == 1){
        fill(111, 208, 140); // green
        stroke(111, 208, 140);
    } else {
        fill(123, 158, 168); // grey blue
        stroke(123, 158, 168);
    }
    

    var circleSize = circleStart;
    var circleInc = 5;

    circleSize = circleSize * (width - mouseX)/150;
  
    // Draw a line of ellipses
    ellipse(shapeSpace, shapeSpace, circleSize, circleSize);
    // Draw first row dots
    var dotSize = 4;
    push(); // Save settings
    fill(205, 223, 160); // yellow
    stroke(0);
    rect(shapeSpace, shapeSpace, circleSize/dotSize, circleSize/dotSize);
    pop(); // restore settings
    
    circleSize += circleInc;
    ellipse(2 * shapeSpace, 2 * shapeSpace, circleSize, circleSize);
    // Draw second row dots
    push(); // Save settings
    fill(120, 88, 111); // purple
    rect(2 * shapeSpace, 2 * shapeSpace, circleSize/dotSize, circleSize/dotSize);
    pop(); // restore settings

    circleSize += circleInc;
    ellipse(3 * shapeSpace, 3 * shapeSpace, circleSize, circleSize);
    // Draw third row of dots
    push(); // Save settings
    fill(205, 223, 160); // yellow
    stroke(0);
    rect(3 * shapeSpace, 3 * shapeSpace, circleSize/dotSize, circleSize/dotSize);
    pop(); // Restore settings

    circleSize += circleInc;
    ellipse(4 * shapeSpace, 4 * shapeSpace, circleSize, circleSize);
    // Draw fourth row of dots
    push(); // Save settings
    fill(120, 88, 111); // purple
    rect(4 * shapeSpace, 4 * shapeSpace, circleSize/dotSize, circleSize/dotSize);
}

function drawRects(){
    // Draws a line of rectangles 

    // Set color of rectangles
    fill(205, 223, 160); // yellow
    stroke(120, 88, 111); // purple

    // Save current settings
    push();

    // Rotate canvase so rectangles craw as diamonds
    rotate(radians(45));

    rectMode(CENTER); // draw rects from center
    var sqSize = startSize * mouseX/100;
    var sqInc = 5;
    // Draw first rectangle
    rect(shapeSpace, shapeSpace, sqSize, sqSize);

    // Draw second rectangle
    sqSize += sqInc;
    rect(shapeSpace + 2 * sqSize, shapeSpace + 2 * sqSize, sqSize, sqSize);

    // Draw third rectangle
    sqSize += sqInc;
    rect(shapeSpace + 3 * sqSize, shapeSpace + 3 * sqSize, sqSize, sqSize);

    // Draw fourth rectangle
    sqSize += sqInc;
    rect(shapeSpace + 4 * sqSize, shapeSpace + 4 * sqSize, sqSize, sqSize);

    // Draw dots
    stroke(0);
    fill(111, 208, 140); // green
    var dotSize = 3;
    ellipse(shapeSpace + 4 * sqSize, shapeSpace + 4 * sqSize, sqSize/dotSize, 
        sqSize/dotSize);

    // third row dots
    fill(120, 88, 111); // purple
    sqSize -= sqInc; // Set sqSize to third square
    ellipse(shapeSpace + 3 * sqSize, shapeSpace + 3 * sqSize, sqSize/dotSize, 
        sqSize/dotSize);

    // second row dots
    fill(111, 208, 140); // green
    sqSize -= sqInc;
    ellipse(shapeSpace + 2 * sqSize, shapeSpace + 2 * sqSize, sqSize/dotSize, 
        sqSize/dotSize);

    // first row dot
    fill(120, 88, 111); // purple
    ellipse(shapeSpace, shapeSpace, sqSize/dotSize, 
        sqSize/dotSize);

    // Return to saved settings
    pop();
}

function mousePressed(){
    colorScheme = -colorScheme;
}

Looking Outwards-03: Section B

Desbians Design Research is a company dedicated to computational fabrication and design. Of their many projects, I find the Fahz, face in a vase, project fascinating. This project transforms photographs of faces in profile by first converting them into vector coordinates. The coordinates of up to four photos are uploaded into software that generates a unique vase design that incorporates each face. The final piece is 3D printed.

There are four distinct faces in this vase.

The faces are not carved into the vase, but are created in the negative space around the vase. The minimalism and simplicity of this project are at odds with the hyper, overproduced world we live in. The art found in the absence inspires me. Sometimes less really is more.

This project was originated by Daniel Desbians in 2014. He modeled the vases with Rhino 3D design software with an add-on called Grasshopper to aid with creating algorithms. Python was also used to put it all together. Each vase is unique and designed by software from a parametric model. This is an example of generative art fabricated into physical form.

Project-02: Variable Faces

My variable faces are all completely computer generated and unique. Every feature is drawn from a set of randomly generated variables. I like the variation in emotions they can express.

sketch
// Evan Stuhlfire
// estuhlfi, Section B
// Project-02: Variable Faces; Face Variables

// Declare global variables


// variable controling head dimensions and shape
var headX = 0; // x value of head center
var headY = 0; // y value of head center
var minHead = 100;
var maxHeadW = 500; //max head width
var maxHeadH = 420; // max head height
var headHeight = 300;
var headWidth = 350;

// variables controling face dimensions and attributes
var eyeSize = 25;
var percentEyeW = 1; // value to adjust eye shape and position
var percentEyeH = 1; // value to adjust eye shape and position
var eyeVert = 2;
var lookAdjustLeft = .25; // Controls eye placement for look direction
var lookAdjustRight = .25;
var lookMax = .45;

// variable to control nose
var nose1 = 1;
var nose2 = 1.1;
var nose3 = 1.1;
var nose4 = 1;
var noseEnd = 1;
var noseLeft1 = 1;
var noseLeft2 = .9;
var noseLeft2 = 1;

// mouth variables
var noseMouthGap = 10;
var mouthStart = 1;
var mouth1 = 1.05;
var mouth2 = 1;
var mouthIncrease = 1.02;

//  color variables
var color1 = 0;
var color2 = 0;
var color3 = 0;

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

    // set head center
    centerX = width/2;
    centerY = height/2;

    // get initial colors
    getRandomColors();
}

function draw() {
    var colorChange = .4; // factor to modify color

    background(color1, color2, color3); // draw background from color variables

    // calculate eyes
    var eyeLeftX = centerX - headWidth * lookAdjustLeft; // x coordingate of left eye
    // x coordinate of right eye, can look different directions
    var eyeRightX = centerX + headWidth * lookAdjustRight; 
    var eyeHeight = min(eyeSize * percentEyeH, headHeight * .90);
    var eyeWidth = eyeSize * percentEyeW;
    var eyePositionY = height / eyeVert; // calculate vertical position of eyes 

    
    // calculate pupils
    var pupilSize = .2;
    var pupilLook = 4;
    var pupilX = eyeLeftX;
    var pupilY = eyeRightX;

    if (lookAdjustLeft > lookAdjustRight){ // looking left move pupils left
        pupilX -= pupilLook;
        pupilY -= pupilLook;
    } else { // looking right move pupils right
        pupilX += pupilLook;
        pupilY += pupilLook;
    }

    // variables for nose
    var maxNose = .90;

    var nose1X = (eyeLeftX + eyeRightX)/2;
    var nose1Y = eyePositionY; 
    if (lookAdjustLeft > lookAdjustRight) { 
        // looking left point nose left
        var nose2X = nose1X * noseLeft1;
        var nose2Y= min(nose1Y * nose2, (centerY + headHeight/2) * maxNose);
        var nose3X = nose2X * noseLeft2;
        var nose3Y= min(nose2Y * nose3, (centerY + headHeight/2) * maxNose);
        var nose4X= nose1X * noseLeft3;
        var nose4Y= min(nose3Y * nose4, (centerY + headHeight/2) * maxNose + noseMouthGap);
    } else { 
        // looking right point nose right 
        var nose2X = nose1X * nose1;
        var nose2Y= min(nose1Y * nose2, (centerY + headHeight/2) * maxNose);
        var nose3X = nose2X * nose3;
        var nose3Y= min(nose2Y * nose3, (centerY + headHeight/2) * maxNose);
        var nose4X= nose1X * noseEnd;
        var nose4Y= min(nose3Y * nose4, (centerY + headHeight/2) * maxNose + noseMouthGap);   
    }

    // calculate mouth
    var maxMouth = .98;
    var mouth1X = centerX * mouthStart;
    var mouth1Y = min(nose4Y * mouth1, (centerY + headHeight/2) - noseMouthGap);
    // keep mouth on face
    if (headHeight > headWidth){
        mouth1X = centerX - noseMouthGap;
    }
    var mouth2X = mouth1X * mouthIncrease;
    var mouth2Y = mouth1Y * mouth2;
    var mouth3X = mouth2X * mouthIncrease;
    var mouth3Y = mouth2Y;
    var mouth4X = mouth3X * mouthIncrease;
    var mouth4Y = mouth1Y;



    // draw head
    fill(color1 * colorChange, color2, color3);
    ellipse(centerX, centerY, headWidth,  headHeight);

    // draw eyes
    fill(color1, color2 * colorChange, color3);
    ellipse(eyeLeftX, eyePositionY, eyeWidth, eyeHeight);
    ellipse(eyeRightX, eyePositionY, eyeWidth, eyeHeight);

    // draw pupils
    fill(10);
    ellipse(pupilX, eyePositionY, eyeWidth * pupilSize, eyeHeight * pupilSize);
    ellipse(pupilY, eyePositionY, eyeWidth * pupilSize, eyeHeight * pupilSize);

    // draw mouth
    beginShape();
    curveVertex(mouth1X, mouth1Y);
    curveVertex(mouth1X, mouth1Y);
    curveVertex(mouth2X, mouth2Y);
    curveVertex(mouth3X, mouth3Y);
    curveVertex(mouth4X, mouth4Y);
    curveVertex(mouth4X, mouth4Y);
    endShape();

    // draw nose 
    fill(color1 * colorChange, color2, color3);
    beginShape();
    curveVertex(nose1X, nose1Y);
    curveVertex(nose1X, nose1Y);
    curveVertex(nose2X, nose2Y);
    curveVertex(nose3X, nose3Y);
    curveVertex(nose4X, nose4Y);
    curveVertex(nose4X, nose4Y);
    endShape();
}

function mousePressed() {
    // When the mouse is clicked random values are generated to control the 
    // dimensions, position, and color of a face

    // randomly generate head value
    headWidth = random(minHead, maxHeadW);
    headHeight = random(minHead, maxHeadH);

    // randomly generate eye values
    eyeSize = headWidth * random(.1, .3);
    percentEyeW = random(.5, 1); 
    percentEyeH = random(.5, 1);
    eyeVert = random(2, 2.25); // vertical position of eyes
    lookAdjustLeft = random(.01, lookMax);
    lookAdjustRight = lookMax - lookAdjustLeft;

    // generate nose values
    nose1 = random(1, 1.1);
    nose2 = random(1, 1.2);
    nose3 = random(1.1, 1.15);
    nose4 = random(.98, 1.05);
    noseEnd = random(.95, 1.05);
    noseLeft1 = random(.95, 1);
    noseLeft2 = random(.85, 1);
    noseLeft3 = random(1, 1.12);

    // generate mouth values
    mouthStart = random(.95, 1.05);
    mouth1 = random(1.05, 1.2);
    mouth2 = random(.98, 1.02);
    mouthIncrease = random(1.02, 1.03);

    // randomly generate a new color combination
    getRandomColors();
}

function getRandomColors(){
    // function generates a random number for color variables
    color1 = random(80, 255); 
    color2 = random(80, 255);
    color3 = random(80, 255);
}


LO 02: Generative Art

“Flow” is an interactive art exhibit by Karl Sims. Developed in 2018, it is a computer simulation that displays particle flows and fluid dynamics in vibrant colors on very large screens. The simulation becomes an interactive art installation when viewers interact with it. A Kinect depth sensor registers the human form and mirrors their appearance, placing the viewer in the art. The program senses human gestures and the algorithm registers these gestures as disruptions in the flow; thus generating new and unique art with each viewer. The particle simulation is reminiscent of Van Gogh’s art and immerses the viewer in their own “Starry Night.” The fluid simulations look as though the viewer can paint with their gestures or as though they are immersed in blooming ink drops. Still others give the effect of being embodied in light or rainbow fabrics. In all there are 10 different effects in this exhibit.

There is simplicity in this installation that I admire. It combines the physics of particle flow and fluid dynamics with color. The flow algorithms give the art its initial form, but this dynamic form becomes dependent on viewers as they interact with it. The physics are based on vectors and fluid flow models. Details can be found here.

Sims has been creating flow simulations and generative art since the 1980s. The progression of his work in combining software, art, and the human experience is evident when viewing his earlier works. This installation was commissioned by MIT’s CSAIL, Computer Science and Artificial Intelligence Laboratory. It is currently on display at the MIT Stata Center, in Boston, Massachusetts.

Project 1: My Self Portrait

sketch
// Evan Stuhlfire
// estuhlfi@andrew.cmu.edu
// Section B 
// 01-project self portrait 

function setup() {
    createCanvas(500, 500);
}

function draw() {
    let circleX = width/2;
    let circleY = height/3;
    let diameter = width/2.5;
    let rectX = circleX - (diameter/2);
    let rectY = circleY + (diameter/2);

    // Set background
    background(144, 195, 209);

    // Draw face
    stroke(25);
    strokeWeight(5);
    fill(141, 186, 153);
    circle(circleX, circleY, diameter);

    fill(207, 117, 54, 200);
    rect(rectX, circleY, diameter, diameter/2);

    fill(39, 62, 176);
    quad(rectX, rectY, rectX + diameter/4, rectY + diameter/2, rectX + diameter*.75, rectY + diameter/2, rectX + diameter, rectY);

    // Draw eyes
    fill(237, 124, 114);
    ellipse(rectX + diameter/3, circleY + 20, diameter/5, diameter/6);
    fill(201, 201, 153);
    ellipse(rectX + diameter*.67, circleY +20, diameter/5, diameter/6);

    // Draw nose
    fill(245, 245, 98);
    triangle(circleX, circleY + 20, rectX + diameter/3, rectY, rectX + diameter*.67, rectY);

    // Draw chin and mouth
    fill(148, 150, 214);
    rect(rectX + diameter/4, rectY, diameter*.5, diameter/2);
    fill(207, 117, 54);
    rect(rectX + diameter/3, rectY + diameter/5.5, diameter/3, 10);



    // Create frame
    noFill();
    stroke(25);
    strokeWeight(20);
    rect(0, 0, 500, 500);

    noLoop();
    
}

I found posting the sketch to be the most difficult part of this exercise.