nixel-LookingOutwards03

I played flute for 8 years but still only have surface level knowledge of music. I think this exhibition, which takes a rather abstract concept and turns it into concrete physical representations, is neat. Music and sound usually exist invisibly, without physical indicators. Even when playing instruments, there is a disconnect between where to move your fingers and the ink on the page.  By linking different aspects of sound and music to physicality, it makes the process of learning and creating intuitive. If created on smaller scale, I could see this becoming part of early music education.

Another reason why I like this exhibition because it is very simple on the surface level, and any person with any amount of music knowledge can interact with and enjoy it, but if you're practiced and educated  in the craft, the exhibition also has a lot of potential to create great compositions.

nixel-viewing04

From what I am able to understand:

Spectacle is computer art that is technically proficient, aesthetically pleasing, and made for consumers.

Speculation is art that is aware of its limitations and materials and uses those to create self aware work that usually engages broad non-art related issues.

The first thing I thought of when Warburton started to discuss spectacle art was the iconic Gatorade water ad. It's brought up again and again in different classes over the years, but it is... nearly 100% spectacle I think. It creates animation in such a laborious and complex manner that emphasizes the technical brilliance that it required.  It brings all the attention to how unique and beautiful the end result is, and how it was done in a superfluous manner. It very much reminds me of the commercial that he shows in the beginning of the video. The same result could have easily been achieved using CGI, but instead they used something experimental. In terms of not being speculation, it doesn't really represent or deal with any sort of issue outside of itself, exploit the materials or techniques used, and was definitely very expensive to make.

I had a difficult time figuring out exactly what each scale meant, but this is my guess for the ad. (Like, doesn't surplus and waste essentially mean the same thing...I'm not sure).

nixel-clock

7:10AM

11:30PM

12:01AM

I had a tough time with this project, not because of a lack of ideas, but because of an excess. I'd brainstormed a ton of ideas, all of them relating to the concept of time, but not necessarily to clocks. Below is a snapshot of all the things I was pondering.

My problem was that I didn't know how exactly to relate these ideas to clocks, and how to represent them in an interesting visual way. I honestly think if I'd just focused on one and did some more research it would have turned out fine.

I was still stuck between ideas half way through the week when I thought of hourglasses. Hourglasses are a very visual object that help to keep time, so I started brainstorming for that.

I wanted to create one hourglass to cover the span of one day with day draining into night, then flipping it at sundown and having night drain into day. I was even going to extract the realtime sunrise and sunsets on weather websites to make it more accurate, however this was too difficult to implement in a short amount of time.

The underlying concept behind the hourglass was to represent how much time we have left rather than how much time has passed like a regular clock.  So once again, due to my awareness of the extent of my coding skills and the amount of time (haha) I had left to finish this, I decided to simplify my concept. It ended up being 3 glasses...an hourglass, a minuteglass, and a secondglass. There are a lot of things I want to fix about this...like making the 'sand' more lively, lining up the drop of the ball with the rise of the sand at the bottom, doing an actual flipping animation, somehow coding gravity for the sand, and making everything just flow smoother. My code is also clumsy and could be much more refined and efficient.

However, I think finished is better than perfect, and what I ended up with is an accumulation of many mistakes I made in the process, and I think this needed to happen so that I could learn from it and get it out of the way.

//thank you golan for the template
var millisRolloverTime;
var prevSec;
 
function setup() {
  createCanvas(750, 400);
  rectMode(CORNERS);
  noStroke();
  }
 
function draw() {
  background(200);
  var H = hour();
  var M = minute();
  var S = second();
  if (prevSec != S) {
    millisRolloverTime = millis();
  }
  prevSec = S;
  var mils = (floor(millis() - millisRolloverTime))/1000.0;
  var secmils = S + mils;
  var mins = M+(map(secmils, 0, 59, 0, 1));
  var hours = (H%12)+(map(mins, 0, 59, 0, 1));
 
  //hourglass
  fill(19, 70, 70);
  rect(0, 0, 250, height/2);
  rect(0, height/2 , 250, height);
 
  //minuteglass
  fill(19, 86, 86);
  rect(250, 0, 500, height/2);
  rect(250, height/2 , 500, height);
 
  //secondglass
  fill(52, 119, 106);
  rect(500, 0, width, height/2);
  rect(500, height/2 , width, height);
 
  hrglassBottom();
  hrglassTop();
  minglassBottom();
  minglassTop();
  secglassBottom();
  secglassTop();
 
  secBall(mils);
  minBall(secmils);
  hrBall(mins);
 
  fill(255);
 
  //hr mask
  triangle(250, 0,  145, height/2 , 250, height/2 );
  triangle(0, 0,  110, height/2 , 0, height/2 );
  triangle(0, height/2,  110, height/2 , 0, height);
  triangle(145, height/2,  250, height , 250, height/2);
 
  //min mask
  triangle(250, 0,  360, height/2 , 250, height/2 );
  triangle(250, height/2,  360, height/2 , 250, height );
  triangle(500, 0,  390, height/2 , 500, height/2);
  triangle(390, height/2,  500, height , 500, height/2);
 
  //sec mask
  triangle(500, 0,  610, height/2 , 500, height/2 );
  triangle(500, height/2,  610, height/2 , 500, height );
  triangle(width, 0,  645, height/2 , width, height/2);
  triangle(645, height/2,  width, height , width, height/2);
}
 
 
function minBall(mils){
  var y = map(mils, 0, 1, height/2, 435);
  var x = width/2;
  ellipse(x, y, 30, 30);
}
 
function secBall(mils){
  var x = 625;
  var y = map(mils, 0, 1, height/2, 435);
  ellipse(x, y, 30, 30);
}
 
function hrBall(mils){
    var r = map(hour(), 0, 60, 0, 255);
    fill(r, 0, 100);
    var x = 125;
    var y = map(mils, 0, 1, height/2, 435);
    ellipse(x, y, 30, 30);
}
 
//hr
function hrglassTop(){
  var r = map(hour(), 0, 24, 110, 190);
  fill(r, 9, 9);
  let glassHeight = map(hour(), 0, 24, 0, height/2);
 
  rect(0, glassHeight, 250, height/2);
}
 
function hrglassBottom(){
  let glassHeight = map(hour(), 0, 24, height, height/2);
  beginShape();
  var r = map(hour(), 0, 24, 110, 190);
  fill(r, 9, 9);
  vertex(0, height);
  for (var i = 0; i <= 250; i++){
    vertex(i, glassHeight);
  }
  vertex(250, height);
  endShape();
}
 
//minute
function minglassTop(){
  let glassHeight = map(minute(), 0, 60, 0, height/2);
  var r = map(minute(), 0, 60, 255, 100);
  fill(r, 0, 0);
  rect(250, glassHeight, 500, height/2);
}
 
function minglassBottom(){
let glassHeight = map(minute(), 0, 60, height, height/2);
  beginShape();
  var r = map(minute(), 0, 60, 255, 100);
  fill(r, 0, 0);
  vertex(250, height);
  for (var i = 250; i <= 500; i++){
    vertex(i, glassHeight);
  }
  vertex(500, height);
  endShape();
}
 
//second
function secglassTop(){
  let glassHeight = map(second(), 0, 60, 0, height/2);
  var g = map(second(), 0, 60, 150, 100);
  fill(255, g, g);
    rect(500, glassHeight, width, height/2);
}
 
function secglassBottom(){
  let glassHeight = map(second(), 0, 60, height, height/2+20);
  beginShape();
  var g = map(second(), 0, 60, 150, 100);
  fill(255, g, g);
  vertex(500, height);
  for (var i = 500; i <= width; i++){
    vertex(i, glassHeight);
  }
  vertex(width, height);
  endShape();
}

nixel-Reading03

"Why bother if it's already been done?"

Not to be overly critical but this phrase has rubbed me the wrong way every time I've heard it. I don't understand the obsession with wanting to create new, novel, and mind-blowing art. In my opinion, striving to only create first word art, or seeing first word art as the only true art, will bring a great deal of turmoil and suffering upon the artist.

Categorizing everything that is an iteration or inspired from existing work as "merely entertainment, not art" is pretty pretentious.  It insinuates that entertainment and art can't coexist within a piece, as if art can't be entertaining, or something entertaining can't be art. If we forever strive to make only first word art, then where is the substance? First word art is a proposal for the future. Without further iterations and deep dives into what that art could become, it remains quite useless. And at the same time, last word art can't exist without first word art.

I guess I just don't understand the need to categorize art in this way at all.  First and last word art can't exist without each other, and they can't exist without everything that comes in between, so why bother with the distinction? Why try to create black and white borders where there don't need to be any?

 

 

nixel-AnimatedLoop

I had a lot of fun with this project!

My process:

I started with some messy brainstorms from when we first got the prompt:

I thought that loops of characters bouncing down stairs, or being transported by a never ending escalator would be fun. I also considered doing skyscapes that looped between sunrise and sunset and a swinging character. In the end, I went with rain because it was the simplest in terms of shape and color design.

I thought that I would do some sort of walk cycle and plotted some leg rotations.

I went online and found a shape-heavy walk cycle gif and spliced some frames out to break it down.

However, when I began to code and actually look into the easing functions, I realized that it would be simpler to pair them with a bouncing animation instead of a walking one. It was sad to leave all the walking animation work I did, but I think I made a better choice in terms of time and simplicity. I think I will go back one day and make all of the ideas I had initially.

After a lot of experimentation (and suffering) I chose to use primarily the Flat Top Window easing function since it was bouncy, playful, and worked well for a looping animation since it was symmetrical.

Here is a thumbnail I made half way through coding in order to hash out the locations of some body parts.

I struggled with the rain since I thought it added to the narrative of the gif, but didn't necessarily loop. I also struggled with the umbrella since it's an interesting visual element but doesn't make much sense since the character isn't holding on to it. I did at one point code an umbrella handle and hands, but it made the image too complex so I got rid of them.

Critiquing myself, I think that I did well in keeping the design simple and appealing. I could have been more ambitious with connecting the umbrella to the character and been more efficient with my code (I organized it in groups of body parts but ended up repeating a lot of simple functions like noStroke() or fill() when I could have just organized the code more efficiently).

 

 
// This is a template for creating a looping animation in Processing/Java. 
// When you press the 'F' key, this program will export a series of images
// into a "frames" directory located in its sketch folder. 
// These can then be combined into an animated gif. 
// Known to work with Processing 3.3.6
// Prof. Golan Levin, January 2018
 
 
//===================================================
// Global variables. 
String  myNickname = "nixel"; 
int     nFramesInLoop = 60;
int     nElapsedFrames;
boolean bRecording; 
Drop[] drops = new Drop[50];
 
//===================================================
void setup() {
  size (640, 640); 
  bRecording = false;
  nElapsedFrames = 0;  
  for (int i = 0; i < drops.length; i++) {
   drops[i] = new Drop(); 
  }
}
//===================================================
void keyPressed() {
  if ((key == 'f') || (key == 'F')) {
    bRecording = true;
    nElapsedFrames = 0;
  }
}
//===================================================
void draw() {
  // Compute a percentage (0...1) representing where we are in the loop.
  float percentCompleteFraction = 0; 
  if (bRecording) {
    percentCompleteFraction = (float) nElapsedFrames / (float)nFramesInLoop;
  } else {
    percentCompleteFraction = (float) (frameCount % nFramesInLoop) / (float)nFramesInLoop;
  }
 
  // Render the design, based on that percentage. 
  renderMyDesign (percentCompleteFraction);
 
  // If we're recording the output, save the frame to a file. 
  if (bRecording) {
    saveFrame("frames/" + myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames >= nFramesInLoop) {
      bRecording = false;
    }
  }
}
//===================================================
void renderMyDesign (float percent) {
  int bgColor = 255;
  background (bgColor);
  stroke (0, 0, 0); 
  strokeWeight (2); 
  float pennerEase = FlatTopWindow(percent);
  noStroke();
 
  //umbrella
  float umbrellashift = (map(pennerEase, 0, 1, -50, -20)); 
  fill(255, 0, 0);
  ellipse(width/2, 240 + umbrellashift, 360, 360);
 
  //cutout umbrella
  fill(bgColor);
  int r = 250;
  for (int i = 0; i < 360; i += 30){
  float dy = sin(radians(i)) * r;
  float dx = cos(radians(i)) * r;
  ellipse(width/2 + dx, 240 + umbrellashift + dy, 180, 180);
  }
 
  rectMode(CENTER);
 
  //ground
  fill(10, 95, 223);
  rect(width/2, 600, width, 200);
 
  //puddle
  noFill();
  stroke(255);
  float jumpWeight = map(percent, 0, 1, 15, 0);
  float puddleEase = map(PennerEaseOutExpo(percent-0.7), 0, 1, 100, 1000);
  float puddleEaseY = map(PennerEaseOutExpo(percent), 0, 1, 0, 50); 
  strokeWeight(jumpWeight);
 
  if (percent >= 0.7){
    ellipse(355, 530, puddleEase, puddleEaseY);
    ellipse(200, 560, puddleEase, puddleEaseY);
    ellipse(300, 600, puddleEase, puddleEaseY);
    ellipse(50, 650, puddleEase, puddleEaseY);
    ellipse(550, 610, puddleEase, puddleEaseY);
  }
 
  //hair
  noStroke();
  float hairshift = (map(pennerEase, 0, 1, 60, -40)); 
  fill(0);
  arc(width/2, 240 + hairshift, 180, 300, PI, TWO_PI);
 
 
  //legs 
  float rX = map(pennerEase, 0, 1, 350, 340);
  float Y = map(pennerEase, 0, 1, 560, 510);
  float squishX = map(pennerEase, 0, 1, 10, 0);
  float lX = map(pennerEase, 0, 1, width - 360, width - 350);
  fill(247,227,40);
 
  //right leg
  triangle(rX, Y, rX - 5 - squishX, Y - 150, rX + 10 + squishX, Y - 150);
 
  //left leg
  triangle(lX, Y, lX - 5 - squishX, Y - 150, lX + 10 + squishX, Y - 150);
 
  //body
	float bsquish = map(pennerEase, 0, 1, 10, -10);
  float bodyshift = (map(pennerEase, 0, 1, 50, -20)); 
  fill(247, 227, 40);
  triangle(width/2, 170 + bodyshift, width/2 - 100 - bsquish, 380 + bodyshift, width/2 + 100 + bsquish, 380 + bodyshift);
 
  //mirrored legs 
  float mrX = map(pennerEase, 0, 1, 350, 340);
  float mrY = map(pennerEase, 0, 1, 510, 560);
  float msquishX = map(pennerEase, 0, 1, 10, 0);
  float mlX = map(pennerEase, 0, 1, width - 360, width - 350);
  fill(247,227,40);
 
  //right leg
  triangle(mrX, mrY + 50, mrX - 5 - msquishX, mrY + 175, mrX + 10 + msquishX, mrY + 175);
 
  //left leg
  triangle(mlX, mrY + 50, mlX - 5 - msquishX, mrY + 175, mlX + 10 + msquishX, mrY + 175);
  //head
  float headshift = (map(pennerEase, 0, 1, 55, -30)); 
  fill(255);
  ellipse(width/2, 170 + headshift, 100, 100);
 
  //mouth
  float mouthshift = (map(pennerEase, 0, 1, 30, -70)); 
  float mouthY = (map(pennerEase, 0, 1, -5, 10)); 
  fill(255, 0, 0);
  ellipse(width/2, 225 + mouthshift, 20, 15 + mouthY);
 
  //bangs  
  fill(0);
  arc(width/2, 150 + hairshift, 100, 100, PI, TWO_PI);
 
  //eyes
  float eyeY = (map(pennerEase, 0, 1, 1, 5)); 
  float eyeX = (map(pennerEase, 0, 1, 1, 5)); 
  ellipse(width/2 - 30, 200 + mouthshift, 10 + eyeX, 15 + eyeY);
  ellipse(width/2 + 30, 200 + mouthshift, 10 + eyeX, 15 + eyeY);
 
  //arms
  fill(247,227,40);
 
  float Ya = map(pennerEase, 0, 1, 10, 80);
  //right arm
  triangle(345, 230 + bodyshift, 345, 260 + bodyshift, 450, 250 + Ya);
 
  //left arm
  triangle(width - 345, 230 + bodyshift, width - 345, 260 + bodyshift, width - 450, 250 + Ya);
 
  //rain
  for (int i = 0; i < drops.length; i++){
  drops[i].fall();
  drops[i].show();
  }
 
}
 
//===================================================
//rain code refenced from Dan Shiffman's Purple Rain Coding Challenge
class Drop {
 float x = random(width);
 float y = random(0, height);
 float yspeed = 11;
 float len = 15;
 
 void fall(){
   y += yspeed;
 
  if (y > height) {
   y = 0;
   yspeed = 11;
  }
 
   }
 
 void show(){
  stroke(10, 95, 223);
  strokeWeight(2);
  line(x, y, x, y+len);
 }
}
 
//===================================================
float FlatTopWindow (float x) {
  //easing functions from Pattern Master https://github.com/golanlevin/Pattern_Master
  // http://en.wikipedia.org/wiki/Window_function 
 
  final float a0 = 1.000;
  final float a1 = 1.930;
  final float a2 = 1.290;
  final float a3 = 0.388;
  final float a4 = 0.032;
 
  float pix = PI*x;
  float y = a0 - a1*cos(2*pix) + a2*cos(4*pix) - a3*cos(6*pix) + a4*cos(8*pix);
  y /= (a0 + a1 + a2 + a3 + a4); 
 
  return y;
}
 
float PennerEaseOutExpo(float t) {
  return (t==1) ? 1 : (-pow(2, -10 * t) + 1);
}

nixel-Scope

 

pdf: zoetrope-output

For my zoetrope design, I experimented a lot with arcs. I started off with just one eye because I wanted to make some sort of illuminati related loop, but then decided to go in a simpler direction. I like the result, although I wish there was more time to make the animation actually loop instead of clearly starting over every time.

Here are some very rough initial designs. My first idea was a jump roping ball. Second was a blinking eye looking around. I initially programmed this one using ellipses but was not satisfied so I switched to arcs and got the final result you see.

 
// Processing Template for Zoetrope toy by Eye Think
// https://www.amazon.com/Zoetrope-Animation-Toy-Victorian-Illusion/dp/B007VM9HZO/
// Developed for Processing 3.3.6 * http://processing.org
// 24 January 2018 * Golan Levin 
 
// See information about Processing PDF export at: 
// https://processing.org/reference/libraries/pdf/index.html
// PDF generated by Processing can be opened in Adobe Illustrator.
import processing.pdf.*;
boolean bRecordingPDF = false;
 
float inch = 72; 
float paperStripWidth = inch * 12.625;
float paperStripHeight = inch * 1.3125;
float overlapMargin = inch * 0.4375;
float artAreaWidth = paperStripWidth - overlapMargin;
float artAreaHeight = paperStripHeight;
 
final int nFrames = 11; 
int myFrameCount = 0;
int exportFrameCount = 0; 
boolean bAnimate = true; 
boolean bExportFrameImages = false;
 
//-------------------------------------------------------
void setup() {
  size(1224, 792); // 17x11" at 72DPI
  frameRate(15);
  smooth();
} 
 
//-------------------------------------------------------
void draw() {
  background(240); 
  if (bRecordingPDF) {
    beginRecord(PDF, "zoetrope-output.pdf");
  }
 
  // Do all the drawing. 
  pushMatrix(); 
  translate(width/2, height/2);
  translate(0-paperStripWidth/2, 0-paperStripHeight/2); 
 
  drawCutLines(); 
  drawGuides(); 
  drawAllFrames();
  popMatrix();
 
  if (bExportFrameImages) {
    // If activated, export .PNG frames 
    if (exportFrameCount < nFrames) {
      String filename = "frame_" + nf((exportFrameCount%nFrames), 3) + ".png";
      saveFrame("frames/" + filename);
      println("Saved: " + filename); 
      exportFrameCount++;
      if (exportFrameCount >= nFrames) {
        bExportFrameImages = false;
        exportFrameCount = 0;
      }
    }
  }
 
  if (bRecordingPDF) {
    endRecord();
    bRecordingPDF = false;
  }
}
 
 
//-------------------------------------------------------
void keyPressed() {
  switch (key) {
  case ' ': 
    // Press spacebar to pause/unpause the animation. 
    bAnimate = !bAnimate;
    break;
 
  case 'p': 
  case 'P':
    // Press 'p' to export a PDF for the Zoetrope. 17x11" paper!
    bRecordingPDF = true; 
    break;
 
  case 'f': 
  case 'F': 
    // Press 'f' to export .png Frames (to make an animated .GIF)
    myFrameCount = 0; 
    exportFrameCount = 0; 
    bExportFrameImages = true;
    bAnimate = true; 
    break;
  }
}
 
//-------------------------------------------------------
void drawCutLines() {
  fill(0); 
  textAlign(CENTER, BOTTOM); 
  text("Zoetrope Template", paperStripWidth/2, -20); 
 
  stroke(0); 
  strokeWeight(1.0);
  noFill(); 
  if (!bRecordingPDF) {
    fill(255);
  }
  rect(0, 0, paperStripWidth, paperStripHeight);
}
 
//-------------------------------------------------------
void drawGuides() {
  // This function draws the guidelines. 
  // Don't draw these when we're exporting the PDF. 
  if (!bRecordingPDF) {
    float frameSpacing = artAreaWidth / nFrames;
 
    stroke(128); 
    strokeWeight(0.2);
    for (int i=0; i<nFrames; i++) {
      pushMatrix();
      translate(i * frameSpacing, 0);
      rect(0, 0, frameSpacing, artAreaHeight); 
      popMatrix();
    }
  }
}
 
//-------------------------------------------------------
void drawAllFrames() {
  for (int i=0; i<nFrames; i++) {
 
    float frameSpacing = artAreaWidth / nFrames;
 
    pushMatrix();
    translate((i + 0.5) * frameSpacing, 0);
 
    int whichFrame = i; 
    if (bAnimate) {
      whichFrame = (i+myFrameCount)%nFrames;
    }
     drawArtFrame (whichFrame); 
 
 
    popMatrix();
  }
  myFrameCount++;
}
 
 
 
//-------------------------------------------------------
//thank you to golan for the template and examples
void drawArtFrame(int whichFrame) { 
 
  noFill();
  strokeWeight(2);
  stroke(0,0,0);
  float eyeY = map(whichFrame, 0, nFrames-1, 0, artAreaHeight*0.30);
  float eyeLid = map(whichFrame, 0, nFrames-1, artAreaHeight*0.30, 0);
  float irisY = map(whichFrame, 0, nFrames-1, 0, artAreaHeight*0.15);
  float eyebrow = map(whichFrame, 0, nFrames-1, 0, artAreaHeight*0.1);
  float tearY = map(whichFrame, 0, nFrames-1, artAreaHeight*0.7, artAreaHeight*1.1);
  float tearY2 = map(whichFrame, 0, nFrames-1, artAreaHeight*0.9, artAreaHeight*1.2);
 
  //right eye
  fill(255,255,255);
  stroke(0,0,0);
  arc(20, artAreaHeight/2, 30, eyeY, 0, PI);
  stroke(50,100,200);
  strokeWeight(2);
  fill(0,0,0);
  arc(20, artAreaHeight/2+1, 15, irisY, 0, PI);
  stroke(0,0,0);
  strokeWeight(3);
  fill(255,255,255);
  arc(20, artAreaHeight/2-1, 30, eyeLid, 0, PI);
 
 
  //left eye
  fill(255,255,255);
  stroke(0,0,0);
  arc(-20, artAreaHeight/2, 30, eyeY, 0, PI);
  stroke(50,100,200);
  strokeWeight(2);
  fill(0,0,0);
  arc(-20, artAreaHeight/2+1, 15, irisY, 0, PI);
  stroke(0,0,0);
  strokeWeight(3);
  fill(255,255,255);
  arc(-20, artAreaHeight/2-1, 30, eyeLid, 0, PI);
 
  //eyebrows
  strokeWeight(2);
  line(7, -eyebrow+40, 35, 40);
  line(-35, 40, -7, -eyebrow+40);
 
  //sad water
  fill(10,50,200,whichFrame*0.9+200);
  noStroke();
  ellipse(-25, tearY, 2, 10);
  ellipse(-25, tearY2, 2, 10);
}

nixel-LookingOutwards02

I've chosen to talk about a fellow CMU student's project for this Looking Outwards report. The project, Hermit, was made by Lingdong Huang for his 15-112 term project in 2015 and is fairly well known throughout the school. It is a procedurally generated interactive environment.

I like this work because I think it's elegant and sophisticated, especially considering the constraints under which it was made (python, 112 term project deadlines).  It is aesthetically pleasing, and it has a narrative. The elements of the project all work together to create something that is able to give the viewer a peaceful feeling.

I did open up the code for the project, but I don't think I'm well versed enough in generative art to know what each part of the program is doing. I do know that it is recursive at its root, but I don't know how he used that to get the generative result achieved.

In terms of effective complexity, I would say it leans more on the side of order rather than chaos. The project is predictable and clean but still interesting in the many possibilities it offers in terms of interaction and uniquely generated landscapes and creatures.

Check it out here:

nixel-Reading02

 

Question 1A. 

In my experience, learning to dance, like most art, has two main components: technical understanding and intuitive understanding. The technical side is orderly and logical, and you can apply any number of systems in order to understand it. However, the intuitive side is chaotic and often illogical, and results in many different interpretations by different people. You can't go extreme on either side because that risks oversimplification and a lack of true understanding of the art, so in employing a mix of the two, you achieve successful execution and therefore effective complexity.

 

Question 1B.

For my personal work, relating to the problem of intent, I don't see why I would use generative methods to create art over other more meaningful and comfortable methods for me. When I look at generative art, I'm not always able to identify the intent behind using that method, and I don't exactly know why people would choose to make art that way, but I think this is just a side effect of me needing to study and understand [technological] art in general.

 

nixel-Interruptions

My Observations:

1. The artwork is square
2. The artwork is a series of consistently thick short black lines on a blank white background
3. Each side seems to have 50-60 lines
4. The lines are arranged in a grid-like pattern along their centers
5. The distance between lines is about half the length of a line
6. The lines are long enough and close enough to each other to overlap
7. The artworks all seem to have a primary direction in which the lines are facing (vertically or horizontally)
8. Otherwise, the lines are pointing in a somewhat arbitrary direction in an 'organized chaos' way
9. There are gaps in the work where no lines exist
10. There are usually around 10 gaps in each work
11. The size of the gaps are arbitrary but generally small, around 5x5 line spots

My process in recoding this work was firstly to get all of the lines on screen and tilting the way they were supposed to. This part wasn't too hard with the transformation function and randomGaussian(). The only troubles I ran into in this phase was the placement of push() and pop(), which had drastically different results depending on where I put them in the code.

The most trouble I had with this project was creating the gaps. I started with creating many randomly placed rectangles as placeholders for the gaps and thought that I could use some sort of distance function to omit the lines close to it. Then, I realized this was annoying and changed the rectangles to ellipses which had a much easier distance measurement using the radius. Here, I found that giving the distance measurement some leeway with radius*random(0,0.7) was very important, or else it would end up looking something like this:

I learned a lot about the nuance and finesse this work demanded, and how order really does matter a whole lot.

I think my end result is pretty close to the original.

nixel-Intersections

let lines = [];
let slider;
let intersectionsArray = [];
let intersection = [];
 
function setup() {
  createCanvas(720, 480);
  background(255, 204, 0);
 
  slider = createSlider(12, 100, 12);
  slider.position(50, 80);
  stroke(0,0,255);
  textSize(15);
  text('click to begin', width/2,height/2);
}
 
function mousePressed(){
 
  intersectionsArray = [];
  lines = [];
  background(255, 204, 0);
  var lineNumber = slider.value();
 
  for (var i = 0; i &lt; lineNumber; i++){
    var newLine = new Line(random(50,width-100), random(50, height-100), random(50,width-100), random(50, height-100));
    lines.push(newLine);  
  }
 
 
  for (i = 0; i &lt; lines.length-1; i++){
   for (var j = 1; j &lt; lines.length; j++) {
     if (lines[i] !== lines[j]){
      intersection = (intersect(lines[i].x1, lines[i].y1, lines[i].x2, lines[i].y2, lines[j].x1, lines[j].y1, lines[j].x2, lines[j].y2));
     }
     if (intersection !== false &amp;&amp; intersectionsArray.includes(intersection) == false){
       intersectionsArray.push(intersection);
      }
     }    
  }
  fill(255,0,0,50);
  text('number of lines:', 50,70);
  text(lines.length, 170,70);
  for (let l of lines){
    l.drawLine();
  }
 
  for (i = 0; i &lt; intersectionsArray.length; i++) {
    ellipse(intersectionsArray[i][0], intersectionsArray[i][1],15);
  }
}
 
 
class Line {
  constructor(x1, y1, x2, y2){
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
 }
  drawLine(){
    line (this.x1, this.y1, this.x2, this.y2);
  } 
}
 
 
//intersection calculations from paul bourke and leo bottaro
function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {
 
  if ((x1 === x2 &amp;&amp; y1 === y2) || (x3 === x4 &amp;&amp; y3 === y4)) {
    return false;
	}
 
  denominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
 
  if (denominator === 0) {
    return false;
	}
 
  let ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator;
  let ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator;
 
  if (ua &lt; 0 || ua &gt; 1 || ub &lt; 0 || ub &gt; 1) {
    return false;
	}
 
  let x = x1 + ua * (x2 - x1);
  let y = y1 + ua * (y2 - y1);
 
  return [x, y]
}