sapeck-Reading03

While I agree with Naimark's claim, I don't think that it can should be used as a scale to evaluate work. Between every first and last word is an always-growing, still-significant body of work. If the first word is determined chronologically but the last word is determined by comparison of importance, then there is no definition for what else is notable. The general public may best remember the first and last word artists best (e.x. Beethoven, Pollock, Warhol), but that doesn't void the value of other artists.

The intent to develop first or last word art also creates a dilemma. If an artists attempts to create a last word art piece, then they will work forever and maybe never create a final work unless they are the next Beethoven. As Naimark's article notes, Beethoven's work has withstood the test of time. If an artist works to create as many first word pieces as possible, then their body of work will be rushed and never reach beyond a shallow degree of complexity.

sapeck-Clock

With no human present:

When a human is present, the time runs away from the human (either via face detection or mouse click):

The time running away to the other side of the screen:

Embeded demo (responds to both mouse clicks and face detection in the browser):

This clock is scared of people. You can't run away from time if it runs away from you. I imagine this clock on someone's nightstand or in their kitchen like a pet fish. Like a fish swims to the opposite side of the bowl when a hand nears, the time runs to the opposite side of the screen when anyone is in view. The clock is both infuriating, as it doesn't tell you the time when you need it and reflective how necessary time is. I don't think I am as experienced enough to make the time look truly animated and living. I added a flicker and blinks to make it seem more alive, but the motion from an easing function isn't natural enough.

/* Sapeck    9/20/2017
/* Sapeck    9/20/2017
"sapeck-Clock"
60-212                        Carnegie Mellon University
Copyright (C) 2018-present  Sapeck
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
 
var DEBUG = false;
 
var prevSec;
var millisRolloverTime;
var mils;
var moveStartTime = 0;
var sideCounter = 0;
var backColor = 255;
var returning = false;
 
var moveTime = [0, 0, 0];
var sideMoveTime = 0;
var currSideToX = 0;
var moving = false;
var sideMoving = false;
 
var ctracker;
 
function setup() {
  createCanvas(800, 800);
  millisRolloverTime = 0;
 
  var videoInput = createCapture();
  videoInput.size(640, 480);
  //videoInput.position(0, 0);
 
  ctracker = new clm.tracker();
  ctracker.init();
  ctracker.start(videoInput.elt);
}
function draw() {
  time = [hour(), minute(), second(),0];
  updateMils(time[2]);
  time[3] = mils;
  showTime = [nf(time[0],2), nf(time[1],2), nf(time[2],2), nf(time[0],3)];
  stutterDelay = false;
 
 
  if (moving) backColor--;
  else backColor++;
  if (backColor > 255) backColor = 255;
  else if (backColor < 0) backColor = 0;
  background(backColor);
 
  var positions = ctracker.getCurrentPosition();
  noFill();
  stroke(color(0,255,0));
  if (positions.length > 0 && DEBUG) {
    rect(map(positions[0][0], 0, 640, 0, width), map(positions[0][1], 0, 480, 0, height), 100, 100);
  }
 
  if (positions.length > 0 || mouseIsPressed) {
    moving = true;
    sideCounter++;
    if (!sideMoving) moveStartTime = millis();
  } else {
    moving = false;
  }
 
  push();
  translate(width/2, height/2);
  y = [
    int(height/2 * function_PennerEaseOutElastic(moveTime[0])),
    int(height/2 * function_PennerEaseOutElastic(moveTime[1])),
    int(height/2 * function_PennerEaseOutElastic(moveTime[2]))
  ];    
  showTime[1] = nf(int(time[1]+(30*function_PennerEaseOutElastic(moveTime[0])*noise(moveTime[0]))),2);
  showTime[0] = nf(int(time[0]+(30*function_PennerEaseOutElastic(moveTime[0]+0.0025)*noise(moveTime[0]+0.0025))),2);
  showTime[2] = nf(int(time[2]+(30*function_PennerEaseOutElastic(moveTime[0]+0.0025)*noise(moveTime[0]+0.0025))),2);
  if (!sideMoving) {
    if (moving) {
      moveTime[0] += 0.005;
      if (moveTime[0] >= 0.020) moveTime[1] += 0.005;
      if (moveTime[1] >= 0.040) moveTime[2] += 0.005;
      for (var i=0;i<moveTime.length;i++) if (moveTime[i] > 1) moveTime[i] = 1;
    } else if (!moving && (moveTime[0] > 0 || moveTime[1] > 0 || moveTime[2] > 0)) {
      moveTime[0] -= 0.0025;
      if (moveTime[0] <= 0.980) moveTime[1] -= 0.0025;
      if (moveTime[1] <= 0.960) moveTime[2] -= 0.0025;
      for (var j=0;j<moveTime.length;j++) if (moveTime[j] < 0) moveTime[j] = 0;
    } else {
      for (var k=0;k<moveTime.length;k++) moveTime[k] = 0;
 
      if (time[3] % 22 == 0) {
        var jitterRand = int(random(0,3));
        var change = int(random(-1,2));
        showTime[jitterRand] = nf(time[jitterRand] + change, 2);
        stutterDelay = true;
      }
    }
  }
  textFont('VT323');
  textSize(100);
  fill(255 - backColor);
  if (stutterDelay) fill((255 - backColor) + random(80, 100));
  noStroke();
  textAlign(CENTER, CENTER);
 
  var xShift = 0;
  if (moveTime[0] > 0.40) {
    showTime[1] = "00";
    var blink = (""+frameCount).substr(-2, 1);
    var blinkB = (""+frameCount).substr(-3, 1);
    if (4 < blink && blink < 7 && (blinkB == 4 || blinkB == 9)) showTime[1] = "++";
  }
  if (moveTime[0] == 1 && moving) {
    if (millis() - moveStartTime >= 5000 || sideCounter > 200) {
      if (!sideMoving) {
        if (!mouseIsPressed) currSideToX = width - int(map(positions[0][0], 0, 640, 0, width));
        else currSideToX = mouseX;
        console.log(currSideToX, width, mouseX);
      }
      sideMoving = true;
 
      xShift = int((width/2 - currSideToX) * function_PennerEaseOutElastic(sideMoveTime));
 
      sideMoveTime += 0.0025;
      if (sideMoveTime > 1) sideMoveTime = 1;
    }
  } else if (!moving && sideMoving) {
    xShift = int((width/2 - currSideToX) * function_PennerEaseOutElastic(sideMoveTime));
 
    sideMoveTime -= 0.0025;
    if (sideMoveTime < 0) sideMoving = false;
  }
 
  push();
  translate(xShift, y[0]);
  text(showTime[1], 0, 0);
  pop();
 
  if ((moveTime[0] <= 0.470 && moving) || (moveTime[0] <= 0.2 && !moving)) {
    push();
    translate(0, y[1]);
    text(":", -50, 0);
    pop();
 
    push();
    translate(0, y[1]);
    text(":", 50, 0);
    pop();
 
    push();
    translate(0, y[2]);
    text(showTime[0], -100, 0);
    pop();
 
    push();
    translate(0, y[2]);
    text(showTime[2], 100, 0);
    pop();
  }
 
  pop();
 
  //if (stutterDelay) delay(500);
}
 
function updateMils(S) {
  if (prevSec != S) {
    millisRolloverTime = millis();
  }
  prevSec = S;
  mils = floor(millis() - millisRolloverTime);
}
 
// From https://github.com/golanlevin/Pattern_Master converted from Java
function function_PennerEaseOutElastic(t) {
  if (t==0) return 0.0; 
  if (t==1) return 1.0;
  var  p = 0.3;
  var  s = p/4;
 
  return (pow(2, -10*t) * sin( (t-s)*(2*PI)/p ) + 1);
}

sapeck-Reading02

  1. I appreciate the beauty and effective complexity of a sunset. Every sunset is affected by the shapes, sizes, and positions of the cloud, the position of the sun in relation to the earth, and where you are on earth. A sunset is much closer to total randomness than total order--every factor changes sporadically.
  2. I have struggled with that Galanter labels as The Problem of Meaning. Nearly all of my computer-based art is created with an image of the final product in my head. I find it much more difficult to find emotion in something that I have created than it is to create something "forced." Creating something aesthetically pleasing seems easy when the conceptual aspect is mostly ignored.

sapeck-AnimatedLoop


1920x1920 H.264 (MP4) video version (2.8 MB)

I began this piece by mapping my pixel art from my sketchbook into a spreadsheet. This gave me a grid of 0's and 1's to create my stick figure bitmaps. I gave each row the same Generalized Blackman Window easing function but with slightly different parameters based based on Perlin noise. The differing parameters adds the "lagging" effect to the animation. The Blackman Window function starts with a slowly-ramping curve that then spikes and returns slows down. I feel that the animation is a little boring. A continuous scroll of five or so figures would be more interesting. The background gradient reminds me more of Nyan Cat than I want it to. A single-tone gradient for each row would be less eye-straining and just as appealing.

/* Sapeck    9/12/2017
"sapeck-AnimatedLoop"
Based on a template for creating a looping animation in Processing/Java by Prof. Golan Levin, January 2018
60-212                        Carnegie Mellon University
Copyright (C) 2018-present  Sapeck, Prof. Golan Levin
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
 
//===================================================
// Global variables. 
String  myNickname = "sapeck"; 
int     nFramesInLoop = 500;
int     nElapsedFrames;
boolean bRecording; 
 
//===================================================
void setup() {
  size (640, 640);
  noiseSeed(283092);
  colorMode(HSB, 100);
  bRecording = false;
  nElapsedFrames = 0;
}
//===================================================
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"+width+"/" + myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames >= nFramesInLoop) {
      bRecording = false;
    }
  }
}
 
int DIMENSION = 20;
int colorFilled = color(0,0,100,255);
int LOOPS = 3;
PVector easeCurveBase = new PVector(0.1, 0);
int NOISESEED = 283092;
 
void renderMyDesign (float percent) {
  background(0);
  smooth();
 
  for (int y=0;y<DIMENSION;y++) {
    pushMatrix();
    boolean right = (y % 2 == 0);
    right = false;
    int moveX = 0;
    int startRow = 0;
    PVector thisEaseCurve = new PVector(easeCurveBase.x+0.3*noise(y*10)/1, easeCurveBase.y+noise(y*10)/1);
    if (y > (DIMENSION-1)/2) thisEaseCurve = new PVector(easeCurveBase.x-0.3*noise(y*10)/1, easeCurveBase.y-noise(y*10)/1);
    float thisPercent = percent;
    thisPercent = function_GeneralizedBlackmanWindow(percent,thisEaseCurve.x);
    if (right) {
      startRow = -1*(LOOPS-1)*width;
      moveX = int(thisPercent*(LOOPS-1)*width);
    } else {
      moveX = int(-1*thisPercent*(LOOPS-1)*width);
    }
    translate(moveX ,0);
    for (int loop=0;loop<LOOPS;loop++) {
      for (int x=0;x<DIMENSION;x++) {
        int thisBox = 0;
        if (loop == LOOPS-1 && right) thisBox = MAN1[y][x];
        else if (loop == LOOPS-1 && !right) thisBox = MAN2[y][x];
        else if (loop == 0 && right) thisBox = MAN2[y][x];
        else if (loop == 0 && !right) thisBox = MAN1[y][x];
        PVector thisLoc = new PVector(x*(width/DIMENSION)+(loop*width)+startRow, y*(height/DIMENSION));
        if (thisBox == 1) {
          fill(colorFilled);
          rect(thisLoc.x, thisLoc.y, width/DIMENSION, height/DIMENSION);
        } else {
          int colorX = x+y;
          if (colorX > DIMENSION) colorX -= DIMENSION;
          fill(color(map(colorX,0,DIMENSION,0,100),
                     100,
                     100));
          rect(thisLoc.x, thisLoc.y, width/DIMENSION, height/DIMENSION);
        }
      }
    }
    popMatrix();
  }
}
 
int[][] MAN1 = {
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0},
  {0,0,0,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
int[][] MAN2 = {
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
 
 
//===================================================
// Taken from https://github.com/golanlevin/Pattern_Master
float function_GeneralizedBlackmanWindow (float x, float a) {
  // http://en.wikipedia.org/wiki/Window_function
  float a0 = (1.0 - a)/2.0;
  float a1 = 0.5;
  float a2 = a / 2.0;
 
  float pix = PI*x;
  float y = a0 - a1*cos(2*pix) + a2*cos(4*pix);
  return y;
}

sapeck-Scope

My design is a simple yet slightly humorous attempt to animate an emoji. The head and eyes move with in a sinusoidal manner, and the tongue stays stationary but lengthens in accordance with the frame number.

sapeck-praxinoscope-output (PDF download)

/* Sapeck    9/12/2017
"sapeck-Scope"
60-212                        Carnegie Mellon University
Copyright (C) 2018-present  Sapeck
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
void drawArtFrame (int whichFrame) { 
  pushMatrix();
  // move the head up and down sinusoidally
  translate(0, -10+30*sin(map(whichFrame, 0, 10, 0, 6)));
 
  // draw the head
  fill(0);
  ellipse(0, 0, 50, 50);
 
  // draw the eye sockets
  fill(255);
  ellipse(-10, -10, 20, 20);
  ellipse(10, -10, 20, 20);
 
  // draw the eyes
  fill(0);
  int eyeSize = 6+int(6*sin(map(whichFrame, 0, 10, 6, 2)));
  ellipse(-10, -10, eyeSize, eyeSize);
  ellipse(10, -10, eyeSize, eyeSize);
 
  // draw the tongue
  fill(color(255,0,0,255));
  rect(-10, 10, 20, 10+2*whichFrame, 7);
 
  popMatrix();
}

sapeck-Interruptions

Observations:

    • The lines are black.
    • The lines are all of the same weight.
    • The background is white.
    • The lines appear to be arranged in relation to some sort of grid.
    • Most of the lines have angles close to 90° or 180°, but fewer of the lines have slopes that appear to be around 45°.
    • The lines are all of the same length.
    • The lines appear to be arranged in columns and rows with the same midpoint.
    • The blank spaces are created by the rotation of the line segments.
    • There are no missing line segments at each point of line midpoint on the grid except in large blobs.
    • There are lines missing in certain areas.

I created my "re-code" of Molnár's project by creating a grid of line segments rotated at random angles. To recreate the similarity between many of the lines (most are nearly vertical), I started with Perlin noise and added a random rotation deviation. I created gaps with a Perlin noise threshold. To randomize the gaps, I add a random value to the Perlin noise coordinates to act as a randomness "seed." My original solution was to subtract standard geometric shapes to create the spaces, but this did not yield the same "random blob" affect that Molnár achieved. I am impressed with how she created the empty swaths, as her work predates the publication of Perlin noise. She was also working with punch cards, an analog plotter, and very early, slow computers.

/* Sapeck    9/6/2017
"sapeck-Interruptions"
60-212                        Carnegie Mellon University
Copyright (C) 2018-present  Sapeck
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
 
var SPACING_X = 18
var SPACING_Y = 18
var LENGTH = 30
var NOISE_THRESHOLD = 0.26
 
// Based on starter Code for "Embedded Iteration + Randomness"
 
var LENGTH_HALF = LENGTH/2
var boolDoRefresh;
 
function setup() {
  createCanvas(720, 720)
  boolDoRefresh = true
}
 
function draw() {
  if (boolDoRefresh) {
    background(255);
		var NOISEX_SEED = random(0, 20000)
		var NOISEY_SEED = random(0, 20000)
 
    let MAX_ROWS = (height-2*SPACING_Y) / SPACING_Y
    let MAX_COLS = (width-2*SPACING_X) / SPACING_X
 
    for (let col=1;col<MAX_COLS;col++) {
      for (let row=1;row<MAX_ROWS;row++) {
        m = noise(col/10, row/10)
        m += random(-2, 2)
 
        let x1 = col*SPACING_X + SPACING_X
        let y1 = row*SPACING_Y + SPACING_Y
 
        let g = noise(col/10+NOISEX_SEED, row/10+NOISEY_SEED)
 
        if (g > NOISE_THRESHOLD) {
          let x2 = x1 + LENGTH_HALF*cos(m)
          let y2 = y1 + LENGTH_HALF*sin(m)
          let x3 = x1 - LENGTH_HALF*cos(m)
          let y3 = y1 - LENGTH_HALF*sin(m)
          line(x1, y1, x2, y2)
          line(x1, y1, x3, y3)
        }
      }
    }
 
  	boolDoRefresh = false
  }
}
 
function mousePressed() {
  boolDoRefresh = true
}

sapeck-Intersections

/* Sapeck    9/6/2017
"sapeck-Intersections"
60-212                        Carnegie Mellon University
Copyright (C) 2018-present  Sapeck
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
 
var NUM_LINES = 12
 
function setup() {
  createCanvas(720, 480)
  boolDoRefresh = true
}
 
function draw() {
  if (boolDoRefresh) {
    background(255);
 
		let lines = []
		let intersects = []
		for (let i=0;i&lt;NUM_LINES;i++) {
			let thisLine = {
				x1: floor(random(0, width)),
				y1: floor(random(0, height)),
				y2: floor(random(0, height))
			}
			thisLine.x2 = floor(random(thisLine.x1+1, width))
			thisLine.m = (thisLine.y2 - thisLine.y1) / (thisLine.x2 - thisLine.x1)
			lines.push(thisLine)
		}
		for (let i=0;i&lt;lines.length;i++) {
			for (let j=i+1;j&lt;lines.length;j++) {
				if (i !== j) {
					let thisLine = lines[i]
					let testLine = lines[j]
 
					// My brute-force-test-x method that didn't entirely work
					// for (let thisX=thisLine.x1;thisX&lt;=thisLine.x2;thisX+=0.1) {
					// 	let thisY = floor((thisLine.m * (thisX-thisLine.x1)) + thisLine.y1)
					// 	let testY = floor((testLine.m * (thisX-testLine.x1)) + testLine.y1)
					// 	if (thisY==testY) intersects.push({x: thisX, y: thisY})
					// }
 
					// Paul Bourke's method (see function defintion below for full citation)
					let x1 = thisLine.x1, x2 = thisLine.x2, x3 = testLine.x1, x4 = testLine.x2
					let y1 = thisLine.y1, y2 = thisLine.y2, y3 = testLine.y1, y4 = testLine.y2
					let intersection = intersect(x1, y1, x2, y2, x3, y3, x4, y4)
					if (intersection !== false) intersects.push({x: intersection.x, y: intersection.y})
				}
			}
		}
		for (let i=0;i&lt;lines.length;i++) {
			let thisLine = lines[i]
			stroke(color(0,0,255))
			line(thisLine.x1, thisLine.y1, thisLine.x2, thisLine.y2)
		}
		for (let i=0;i&lt;intersects.length;i++) {
			let intersection = intersects[i]
			noStroke();
			fill(color(255,0,0,50))
			ellipse(intersection.x,intersection.y,20,20)
		}
 
    boolDoRefresh = false
  }
}
 
function mousePressed() {
  boolDoRefresh = true
}
 
// line intercept math by Paul Bourke http://paulbourke.net/geometry/pointlineplane/
// Determine the intersection point of two line segments
// Return FALSE if the lines don't intersect
function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {
 
  // Check if none of the lines are of length 0
	if ((x1 === x2 &amp;&amp; y1 === y2) || (x3 === x4 &amp;&amp; y3 === y4)) {
		return false
	}
 
	denominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))
 
  // Lines are parallel
	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
 
  // is the intersection along the segments
	if (ua &lt; 0 || ua &gt; 1 || ub &lt; 0 || ub &gt; 1) {
		return false
	}
 
  // Return a object with the x and y coordinates of the intersection
	let x = x1 + ua * (x2 - x1)
	let y = y1 + ua * (y2 - y1)
 
	return {x, y}
}

sapeck-IterationExercise

/* Sapeck    9/6/2017
"sapeck-IterationExercise"
60-212                        Carnegie Mellon University
Copyright (C) 2018-present  Sapeck
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
 
// Based on starter Code for "Embedded Iteration + Randomness"
var boolDoRefresh;
 
function setup() {
  createCanvas(400, 400)
  boolDoRefresh = true
}
 
function draw() {
  if (boolDoRefresh) {
    background(255);
 
		var rows = width/50
		var cols = width/50
 
		for (var i=0;i<rows;i++) {
			for (var j=0;j<cols;j++) {
				if (random(50) < 5) {
					fill(color(255,0,0))
					ellipse((i*50) + (45/2) + 2.5, (j*50) + (45/2) + 2.5, 45, 45)
				} else {
					fill(color(0,255,0))
					rect(i*50 + 2.5, j*50 + 2.5, 45, 45)
				}
			}
		}
 
    boolDoRefresh = false
  }
}
 
function mousePressed() {
  boolDoRefresh = true
}

sapeck-reading01

9. The Critical Engineer notes that written code expands into social and psychological realms, regulating behaviour between people and the machines they interact with. By understanding this, the Critical Engineer seeks to reconstruct user-constraints and social action through means of digital excavation.

This belief demonstrates that engineering is truly an art form. While engineering advances society technologically, the nature of the advancements can change the way that people think and act--intentionally or unintentionally. By understanding that spaces, machines, and computers influence how people act, Critical Engineers seek to design with social intention in mind. I'm fascinated by how the subtleties of engineering affect society. While artists often write stories about society, engineers write society itself. Engineers can control someone's mood by how long an elevator takes to get to their floor. Engineers make it possible to stay in touch without someone around the world in realtime. A credit or debit card and ATM prevents the need to carry around lots of cash, allowing consumers to carry their money virtually and spend more.

sapeck-lookingoutwards01

Kinetic Lights is a project from Christopher Bauder and his creative studio WHITEvoid. The DMX-controlled winch and LED platform allows for hanging structures, lights, and mirrors to move and change form. I find objects animated by light captivating. The structures seem like they are from science fiction films, but they aren't images on a screen--they are nearly surreal, breathing spheres, rods, and beams of light.

The ecosystem of winches, light fixtures, and controllers appears to be built from the ground up. Each winch can be connected to an assortment of shapes of light-up forms. WHITEvoid designed software to map out and program in the system in 3D while still controlling the lights through standard DMX. Unfortunately, Kinetic Lights is a commercial product, so not much information on the development of is published.

Bauder developed this project after he created Lichtgrenze, a massive outdoor installation commemorating the 25th anniversary of the fall of the Berlin wall. The same light-up balloon system used in that project are available as Kinetic Lights fixtures. The floating nature of glowing spheres may have inspired the Kinetic Lights project.

The system is primarily used in very large installation art, but there are more possibilities. It may be used in performances where light and movement usually complement performers (ex. concerts, dance, plays). Kinetic Lights would also fit well in malls and large atriums where kinetic, hanging art is already found.

Kinetic Lights by Christopher Bauder as a part of WHITEvoid

MIRROR-MIRRORMIRROR-MIRROR

DEEP WEB - kinetic audiovisual installation and performance