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.
Author: Stuhlfire
Project 5: Wallpaper, Section B
Flower of Life Wallpaper
/* 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.
/*
* 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.
// 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.
// 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
// 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.