nerual-Body

It's clouded out there. Why go outside when you can vicariously experience the great outdoors as a cloud? Turn your head and blow yourself back and forth.

Video:

GIFs:

Image:

Process:

I really like clouds. One of the commonalities among some examples of face tracking I've seen is giving non-human objects human qualities, so I thought I'd try it with clouds. I was interested in a fun and cute interaction that lasted a few minutes.

These are some initial sketches and ideas for doing more than just blowing yourself around as a cloud. Unfortunately I didn't get to much beyond that.

I used this p5.js with Glitch and clmTracker template provided. I used Matter.js for the physics, although in rettrospect, the p5.js built in physics would have sufficed.

The CLM tracker gets an array of coordinates from the video input. Here is a screen shot I used to know which points went with which features, so I could isolate the eyes and mouth and calculate ratios to determine if the mouth was open or which way the face was facing.

It was very difficult to get the motion tracker to stabilize and reliably detect movements, so I didn't get around to implementing networking or my other ideas.

As I was transplanting the face points, I discovered some quirky movements that resulted, such as the interesting face created when the eye position, but not rotation, is tracked. It gave the cloud(I call him Claude) a wonky face that I liked. I originally left the mouth as a line/circle(like in the sketches), but I wanted to capture more of the user's orientation and movement, and let it dictate rather than just guide the movement. In general, I liked this aesthetic that arose from selectively misinterpreting and/or ignoring certain features.

Ultimately however, I feel like this project was a disappointment. Part of it was me not taking the time to set up the right structures to handle a bunch of bodies interacting with physics. But another part might have been deciding to go with an idea that relied mostly on a smooth final result, rather than having other aspects to lean on. I think I made some decent efforts with adding in the other clouds, but their movement(move way too fast when video input isn't showing), and in general the color scheme, are pretty lacking.

Code:

/* face-ctrl.js */
var ctracker;
//var mouth_pos;
var mouth_x = 300;
var mouth_y = 300;
var facingLeft, facingRight;
var blowRatio, turnRatio;
var m_width, m_height;
 
var ox,oy;
var prev;
var leye, reye;
var pos1 = [];
var pos2 = [];
var posMid = [];
 
function setup_clm(){
  //setup camera capture
  var videoInput = createCapture(VIDEO);
  videoInput.size(w/4,h/4); 
  //uncomment to view video
  //videoInput.position(w/4*3, h/4*3);
  //videoInput.hide();
 
  ctracker = new clm.tracker();
  ctracker.init(pModel);
  ctracker.start(videoInput.elt);
  mouth_x = 300;
  mouth_y = 300;
}
 
 
 
function updateVars(mx, my, scale){
  var positions = ctracker.getCurrentPosition();
 
  for (var i=positions.length-1; i<positions.length; i++) { ox = positions[60][0]*scale; oy = positions[60][1]*scale; m_width = (positions[44][0] - positions[50][0]); m_height = (positions[47][1] - positions[53][1]); turnRatio = ((positions[44][0]-positions[1][0])/(positions[13][0]-positions[50][0])); facingLeft = turnRatio > 1.5;
      facingRight = turnRatio < 1;
  }
}
 
function isBlowing(){
  return blowRatio < 2.5;
}
 
function drawBlowHole(mx, my, scale){
    var positions = ctracker.getCurrentPosition();
  blowRatio = m_width/m_height;
 
  push();
  noFill();
  strokeWeight(5);
  var mw = m_width*scale;
  var mh = m_height*scale;
 
  if (isBlowing()){
    //wind
    stroke(0);
    var bx1 = mx + (facingLeft ? -1 : 1)*mw*2;
    var bx2 = mx + (facingLeft ? -1 : 1)*mw*3;
    var by = my;
    var sep = 20;
    push();
    strokeWeight(3);
    line(bx1, by, bx2, by);
    line(bx1, by+sep, bx2, by+sep);
    line(bx1, by-sep, bx2, by-sep);
    pop();
  }
 
  //face
  for (var i=0; i<positions.length; i++) {
    var x = positions[i][0]*scale;
    var y = positions[i][1]*scale;
    push();
    stroke(0);
    strokeWeight(scale*1.2);
    strokeJoin(ROUND);
    strokeCap(ROUND);
    //EYES
    if (i == 27 || i==32){
      stroke(0);
      noFill();
      pos1[0]= mx + x-ox;
      pos1[1] = my + y-oy +50;
      ellipse(pos1[0],pos1[1],40,20);
      fill(0);
      noStroke();
      ellipse(pos1[0],pos1[1],20,20);
    }
 
    //REAL MOUTH
    if(i<44 || i>61) continue;
    if (i==58 && !isBlowing()){
      i=62;
      continue;
    }
    if (i == 55) pos2 = [positions[44][0]*scale,positions[44][1]*scale];
    else if (i == 61) pos2 = [positions[56][0]*scale,positions[56][1]*scale];
    else pos2 = [positions[i+1][0]*scale,positions[i+1][1]*scale,x,y];
 
    pos1[0]= mx + x-ox;
    pos1[1] = my + y-oy;
    pos2[0] = mx + pos2[0]-ox;
    pos2[1] = my +pos2[1]-oy;
    posMid[0] = (pos1[0] + pos2[0])/2;
    posMid[1] = (pos1[1] + pos2[1])/2;
 
    line(pos1[0],pos1[1],posMid[0],posMid[1]);
    line(pos2[0],pos2[1],posMid[0],posMid[1]);
  }
  pop();
}
 
/* sketch.js */
 
 
var socket = io();
var clients = {};
var data = {};
var w = 800;
var h = 600;
var size;
var videoInput;
var ctracker;
var claude;
var clouds = [{x:100,y:100,scalar:100, w:3, h:4},
              {x:200, y:h-100, scalar:-150, w:5, h:7},
              {x:w-300, y:h, scalar: 70, w:8, h:5},
              {x:w-100, y:200, scalar: -50, w:6, h:6}
             ]
var t = 0;
var Engine = Matter.Engine,
    Render = Matter.Render,
    World = Matter.World,
    Bodies = Matter.Bodies,
    Body = Matter.Body,
    Constraint = Matter.Constraint;
 
function setup_matterjs(){
  engine = Engine.create();
  world = engine.world;
  engine.world.gravity.y = 0;
  engine.timing.timeScale = 0.2;
  //makeBoundaries(width,height);
  Engine.run(engine);
}
 
function setup() {
  // setup canvas
  var cnv = createCanvas(w,h);
  cnv.position(0, 0);
  setup_clm(); //face-ctrl
  setup_matterjs();
  size = 50;
  claude = new Cloud(mouth_x, mouth_y, size);
  World.add(world, claude.body);
  started=0;
}
 
function drawCloudShape(x,y,h,w){  
  push();
  fill(250, 250, 250);
  noStroke();
  arc(x, y, 25 * h, 20 * h, PI + TWO_PI, TWO_PI);
  arc(x + 10*w, y, 25 * h, 45 * h, PI + TWO_PI, TWO_PI);
  arc(x + 25*w, y, 25 * h, 35 * h, PI + TWO_PI, TWO_PI);
  arc(x + 40*w, y, 30 * h, 20 * h, PI + TWO_PI, TWO_PI);
  pop();
}
 
function drawCloud(x,y,w,h){
  updateVars(x,y,w/2);
  drawCloudShape(x-w*10,y+h*7,w,h);
  drawBlowHole(x,y,w/2);
}
 
function drawSun(){
  push();
  noStroke();
  fill('#FFEC5E');
  var sun =  {x: map(hour(), 0, 60, 150, w-150), y: 150, r:200};
  ellipse(sun.x, sun.y, sun.r);
  pop();
}
 
function draw() {
  background('#A6D7FF');  
  drawSun();
  sass();
 
  push();
  //uncomment to mirror
  //translate(w,0);
  //scale(-1.0,1.0);
  strokeWeight(1);
  claude.update;
  drawCloud(claude.pos.x, claude.pos.y, 7, 5);
  pop();
 
  var wind = 0.1 * (facingLeft ? -1 : 1);
  var force = {x:wind,y:0};
  if (blowRatio < 2) Body.applyForce(claude.body, claude.pos, force);
  for(var i =0; i< clouds.length; i++) otherClouds(clouds[i]); } function sass(){ push(); if (claude.pos.x > w+200 || claude.pos.x < -200){
      textFont('Georgia');
      textSize(30);
      textAlign(CENTER);
      strokeWeight(1);
      fill(0);
      text("the real world doesn't have wrap-arounds, chump\n go outside",w/2,h/2);
    }
  pop();
}
 
function makeBoundaries(w,h){
  console.log("width="+str(w)+" height="+str(h));
  var strength = 20;
  var options = {isStatic:true, restitution: 0.2};
  var bottom = Bodies.rectangle(w/2, h, w+50, strength, options);
  var top = Bodies.rectangle(w/2, 0, w+50, strength, options);
  var left = Bodies.rectangle(0, h/2, strength, h+50, options);
  var right = Bodies.rectangle(w, h/2, strength, h+50, options);
  World.add(world,top);
  World.add(world,bottom);
  World.add(world,left);
  World.add(world,right);
}
 
function otherClouds(cloud){
  var scalar = cloud.scalar;
  var x1 = cloud.x + (scalar * cos(t));
  drawCloudShape(x1, cloud.y, cloud.w, cloud.h);
  //fill(0); noStroke();
  stroke(0); noFill();
  var dir = cloud.scalar < 0 ? 1 : -1;
  var y = cloud.y-cloud.h*4;
  ellipse(x1 + cloud.w*15, y,20,10);
  ellipse(x1 + cloud.w*3, y, 20, 10);
  //ellipse(x1, cloud.y, 70, 70); //mouth?
  t+=0.005;
}

nerual-LookingOutwards03

I was really intrigued by Lauren McCarthy and Kyle McDonald's "How We Act Together," both by the interaction between individuals and between computer and individual. The project shows you a stream of different pictures of other people interacting with the project from before, as long as you continue acting certain facial movements. It explores modern interaction, in both positive and negative ways.

I think it's interesting that it attempts to pose these questions about modern interaction, which involves lots of virtual interaction, through virtual interaction itself, with very distant people. The whole set up itself is already "awkward and intimate" and it's cool that they chose to accentuate that with a kind of interaction that induces a bodily response.

http://lauren-mccarthy.com/How-We-Act-Together

nerual-Telematic

Visual Echos : Let your interactions leave a visual footprint. WASD to move.

Notes on bugs: A player isn't removed if they disconnect. If you refresh, you will start with a fresh screen, but on everyone else's screen, you will appear as a new player and your old particle will just be a moveable object. 

Looks cooler with more people, but also potentially gets buggier.

GIF:

I wanted to explore equal collaboration/competition, creating an environment where either can manifest. In the process of working with a physics engine, I became interested in incorporating the ceding of control to external forces. In this case, you and the other players may be collaborating, but there is still chaos that hinders that, yet creates satisfying after images. The white line between players makes the canvas itself dynamic, as it erases past drawings.

This is getting into "it's a feature not a bug" territory, but I actually like the freedom you have with the thin lines, because now you have to negotiate the speed of your movements as well, in order to create or avoid creating smooth shapes.

I didn't get to try everything I wanted to do, but I think I touch upon some ideas worth exploring further. I think it lacks a lot polish, in terms of the color choice and overall feel, as I definitely could have fiddled around with the design elements more.

My original idea was to create a many headed worm(inspired in part by the cartoon CatDog), but I think I end up exploring the visuals that result from interactions, rather than the gamified mechanics.

These are some progress screen shots of what it might have looked like with a chalkboard kind of aesthetic.

glitch
glitch
2 player interaction
one player

Some things to explore still:

  • using real colors
  • changing the aspect ratio
  • adding constraints
  • smoothing out
  • incorporating instructions
  • distinguishing features for the players
  • different shapes

Below are some sketches of the original idea. I discovered that you could record the path of the interaction and I thought it might be more interesting to deal with geometric relations instead.

Concept sketches
I successfully modeled a worm-like creature but I was unable to make one player the head and the other player the tail.

Code can be found on Glitch: https://glitch.com/edit/#!/visual-echoes

Future Work:

  • Fix bugs: make sure players disconnect properly
  • Fiddle with colors and transparency more
  • Fork project to explore having the midpoint between the two players be the drawing brush

nerual-viewing04

Spectacle describes work that uses technology in novel and spectacular ways, but does it at an inaccessible scale and doesn't acknowledge the context and implications that surround it.

Speculation uses technology as a medium to explore society and technology itself, but it is inaccessible because of its lack of polish, and it out on what could be explored when the artist themself is working directly with the technology.

One project that comes to mind are the "satisfying" simulations done by Andrea Wannerstedt. It seems to fall more into the category of spectacle, engaging the viewer with its polish and using the precision of technology to hit the sweet spot with timing. It comes closer to acceleration than drag, as it seems to have be operating at the height of 3D modeling in a 2D canvas and has some aesthetics that make it universal. It is hard to judge that at this time though. It falls more along visibility because it reaches a large audience. It comes sits between surplus and waste, simply because its scale is so small, although maybe more on the surplus side given its association with quick, cheap social media entertainment. It is closer to commerce than art, in its current contexts at least, because it is so easily accessible, spreading as GIF loops through social media and second-rate news blogs, eventually without credit on many. And it is a style that has already be used in many advertisements. It is very squarely on the function side, scrubbing out all chaos as much as possible to leave us with the impossibly perfect graphic.

nerual-Clock

 

Between 1am and 8am, BERT-O-CLOCK sleeps, but he can be woken to give you the time. Between 8am and 10am, he sleeps, and he won't wake up. Otherwise, he's awake and keeping time.

And at a very particular time, BERT-O-CLOCK likes to have some fun.

I was really interested in the notion of using hands and fingers to count time, like how small children learn math. This lead me on this path of a childish aesthetic and manner of interaction with the piece. I thought it would be interesting to have this snarky little entity that "keeps" the time. So it "keeps time" by keeping track of what time it is, but sometimes it sleeps, and keeps the time from you that way, and sometimes it sleeps and refuses to wake up. I wanted to capture this sense of time being out of your control, something that seems to act on its own accord. And I think that although this is rather apparent to children, it's something we tend to forget as we grow older.

I think I made the right choice following the whim that lead down this hole. It has some liveliness to it, and I think the tick tock animation at the top was a good touch. I personally think it's fun to interact with, especially if you had this as a small app on your mobile device. It doesn't involve much more than basic javascript functions, and my style ended up being guided by what I could figure out in p5.js. The color scheme is an attempt at something, but the success of that attempt is questionable. The binary representation with the fingers was done more out of practicality than purpose, but it contributes to the frustration I intended the viewer to have with the small creature. Whether that frustration translates to anything, I can't say.

Future Work:

  • make Bert into a mobile app
  • animate his hands going up and down
  • animate his mouth

Sketches:

Code:

var r = 175;
var cx,cy;
var e = 60;
var bop = 3;
var state; //"sleep","snark"
var nappyTime = [1,8];
var snarkTime = [8,9];
var funTime = [2,34,60];
var bodyColor = '#f7786b';
var clicked;
var snarked;
 
var H, M, S, mil;
 
function setup() {
  createCanvas(400,600);
  cx = width/2;
  cy = height;
  console.log("setup complete");
  state = "sleep";
  colorBody();
  clicked = false;
  var snarked = false;
}
 
function draw() {
  H = hour();
  M = minute();
  S = second();
  mil = millis();
  background('#00f5eb');
  //debug();
  if (H==funTime[0] && M==funTime[1])
    party();
  updateState();
  drawBert();
  drawText();
  if (snarked)
    snark();
}
 
function debug(){
  text((S >>> 0).toString(2),width/2, 100);
  text(H + ":" + M + ":" + S ,width/2, 120);
  text(bin(H,2) ,width/2, 140);
}
 
function drawText(){
  var def= "This is a \n BERT-O1-CLOCK.\nHe keeps the time."
  var sleep = "Bert is asleep right now. \nI wonder when he'll wake up...\n Maybe you should poke him?";
  var wake = "He's a 1's and 0's\n kind of guy. Have fun.";
  textFont("Courier New");
  stroke('#fdff5c'); fill('#fdff5c');
  //colorBody();
  textSize(30);
  textAlign(CENTER);
  text(def, width/2, height/5);
 
  stroke('#0'); fill('#0');
  textSize(20);
  if (state=="sleep" || (state=="snark" && !snarked)){
    text(sleep, width/2, height/2);
  }
  else{
    text(wake, width/2, height/2 - 50);
  }
 
  if(S%2==1)
    text("tick", 60,60);
  else
    text("tock", width-60, 60);
 
}
 
function colorBody(){
  fill('#f7786b');
    //fill('#ff5147');
  //fill(255,153,153);
}
 
function getTime(){
  return [hour(), minute(), second()];
}
 
function snark(){
  stroke(255); fill(255);
  textSize(20);
  var snark = "BERT-O1-CLOCK wakes up \n when he damn well pleases."
  text(snark, width/2,height/2);
  snarked = true;
}
 
 
function updateState(){
  var t = getTime();
  var yay = false;
  if (nappyTime[0]<=t[0] && t[0]<=nappyTime[1]){
    if(!clicked)
      state = "sleep";
      snarked = false;
  }
  else if (snarkTime[0]<=t[0] && t[0]<=snarkTime[1]){
    state = "snark";
  }
  else{
    state = "wake";
    snarked = false;
  }
  console.log(state);
}
 
function mousePressed(){
  console.log("click");
  if (state=="wake")
    state="sleep";
  else if (state=="snark"){
    if (!snarked)
      snark();
    else
      snarked = false;
  }
  else
    state="wake";
  clicked = true;
}
 
function party(){
  push();
  background('#f000eb');
  textSize(45);
  textStyle(BOLD);
  colorBody();
  text("IT IS THE HOUR",width/2,60);
  stroke(255); fill(255);
  text("IT IS THE HOUR",width/2+5,60+5);
  rotate(PI/4);
  translate(width/2,-height/2);
  pop();
}
 
 
function calcBop(){
  var t = map(mil, 0, 999, 0, 1);
  var yPos = map(cos(t * TWO_PI), -1, 1, 0, bop);
  translate(0,yPos);
}
 
function drawBert(){
  if (state=="wake")
    drawHands();
  push();
    calcBop();
    drawBody();
  pop();
}
 
function drawBody(){
  //draw boi
  noStroke();
  colorBody();
  ellipse(cx, cy, 2*r, 2*r);
  //draw eyes
  drawEyes();
  drawMouth();
  //nose
  stroke(255);
  strokeWeight(5);
  colorBody();
  var nose = 100;
  arc(cx,cy-r/2+10,nose/2,nose,0,PI);
}
 
function drawEyes(){
  if (state=="wake"){
    noStroke();
    fill(255);
    ellipse(cx-r/2, cy-r/2, e, e/2);
    ellipse(cx+r/2, cy-r/2, e, e/2);
    fill(0);
    ellipse(cx-r/2, cy-r/2, e/2, e/2);
    ellipse(cx+r/2, cy-r/2, e/2, e/2);
  }
  else{
    stroke(255);
    strokeWeight(5);
    noFill();
    arc(cx-r/2, cy-r/2, e, e/2, 0, PI);
    arc(cx+r/2, cy-r/2, e, e/2, 0, PI);
  }
}
 
 
//add to this
function drawMouth(){
  //mouth
  stroke(255);
  strokeWeight(5);
  fill(255);
  if (state=="wake")
    ellipse(cx,cy-r/4+10, r, r/10);
  else
    line(cx-r/4,cy-r/4,cx+r/4,cy-r/4);
 
}
 
function drawHands(){
  rectMode(CENTER);
  noStroke();
      colorBody();
  //left
  push();
  translate(cx-r/3,cy);
  drawHand(1,2); //hr1
  translate(-r/3-10, 0);
  drawHand(1,3); //hr2
  pop();
  //right
  push();
  translate(cx+r/3,cy);
  drawHand(-1, 1);  //min2
  translate(r/3+10,0);
  drawHand(-1, 0); //min1
  pop();
}
 
function bin(p, i){
  var b = (p >>> 0).toString(2);
  if (i >= b.length)
    return '0';
  else
    return b.charAt(b.length-i-1);
}
 
var cap = 10;
var w = 50;
var fw = 10; //finger width
var fcap = 5;
var fl = 60;
var arml = r*3
function drawHand(side, place=5){
  //place=0 - min1
  //place=1 - min2
  //place=2 - hr
  colorBody();
  //arm
  rect(0, 0, w, arml, cap);
  switch (place) {
    case 0:
      drawFinger(3, bin(M,3)==1);
      drawFinger(2, bin(M,2)==1);
      drawFinger(1, bin(M,1)==1);
      drawFinger(0, bin(M,0)==1);
      break;
    case 1:
      drawFinger(3, bin(M,7)==1);
      drawFinger(2, bin(M,6)==1);
      drawFinger(1, bin(M,5)==1);
      drawFinger(0, bin(M,4)==1);
      break;
    case 2:
      drawFinger(3, bin(H,3)==1);
      drawFinger(2, bin(H,2)==1);
      drawFinger(1, bin(H,1)==1);
      drawFinger(0, bin(H,0)==1);
      break;
    case 3:
      drawFinger(3, bin(H,7)==1);
      drawFinger(2, bin(H,6)==1);
      drawFinger(1, bin(H,5)==1);
      drawFinger(0, bin(H,4)==1);
      break;
    case 4:
      drawFinger(3, bin(S,3)==1);
      drawFinger(2, bin(S,2)==1);
      drawFinger(1, bin(S,1)==1);
      drawFinger(0, bin(S,0)==1);
      break;
    default:
      drawFinger(3);
      drawFinger(2);
      drawFinger(1);
      drawFinger(0);
      break;
  }
  //thumb
  push();
  translate(side*w/2,fw-arml/2);
  rotate(-PI/2);
  rect(0,0, fw, fl/2, fcap);
  pop();
}
 
function drawFinger(n,up=true) {
  colorBody();
  noStroke();
  var yPos = -arml/2;
  if (!up) 
    yPos=yPos + 2*fl/5;
  switch(n){
    case 3:
      rect(-w/2+fw/2, yPos, fw, fl, fcap);
      break;
    case 2:
      rect(-w/4+fw/2, yPos, fw, fl, fcap);
      break;
    case 1:
      rect(w/4-fw/2, yPos, fw, fl, fcap);
      break;
    case 0:
      rect(w/2-fw/2, yPos, fw, fl, fcap);
      break;
    default:
      fill(0);
      elllipse(width/2,height/2,100,100);
  }
}

nerual-LookingOutwards02

This project by Melanie Hoff is called "15,000 Volts", showcased in 2015. She hooks a a few alligator clips to  a sheet of wood, and sends (presumably) 15,000 volts through them, letting the electricity generate branching patterns as it find its way through the trees veins. I thought it was interesting because the action of creating it was very simple(just sending ludicrous amounts of electricity through wood), and it was an application of the spirit of generative art to a traditional or craftsman kind of material.  Looking at there other works, this doesn't seem to fit in with their style and interests, but I assume the call back to old craftsmanship, with the sepia tones and material itself, was intentional.

In this project, the algorithm or computer is nature, which means surrendering even more control over what is created. Part of appreciating the work is seeing it be created too. You see the rate at which the branches grow. Who grows first, and in what direction? And eventually some branches thicken as the wood essentially melts. There was an attempt to exercise control in intentionally spacing the clips out, and probably picking out the certain type of wood. For the most part it's a kind of predictable randomness; you know what the general shape looks like, but the subtitles are much more difficult to predict.

Later extensions of this project involve non-conductive materials which force the branches into more specific shapes, using the randomness more for texture than as the main feature.

nerual-Reading03

I have developed a particular fondness for the word "muscular," and I think it is a great way to describe last word art. Perhaps the technique or framework is not novel, but the result it achieves is what ultimately makes it longer lasting and impactful. Yet, I think today's short-attention span with regard to which technologies are "trending," is a good thing. If there are enough ideas out there that are that enticing, then they certainly shouldn't be overlooked. It's like we're in the sketching brainstorming. We haven't explored everything enough to decide which ones are worth really diving super deep into.

I see Homestuck as an example of both first and last word art that has fallen victim to changing times. It is essentially a pseudo text adventure on the internet. The webcomic makes use of gifs, flash animations and games, and convoluted narrative paths to follow through hyperlinks. It wasn't the first of it's kind, but I believe it's one of the most significant because of its scale and fanbase. And at the time it was a pretty novel idea. But today, the time for that kind of sensibility and aesthetic has passed, as evidenced in the direction Homestuck itself is moving now, toward the sleek indie game scene. In that way, I think culture almost holds technology and art hostage, because these things (usually) require an audience, and if you're audience is moving in one direction, how can you not follow them? Perhaps sometimes new technology holds itself hostage in this way, sending the masses in one direction, and being compelled to follow it thereafter.

nerual-Reading02

Question 1A.
I really like clouds. It's interesting that it can be easily represented, but they seem very difficult to model. The cloud itself is a collection of gas molecules distinctly different from the molecules around them, and that system interacts with the weather system, to change the shape of the cloud based on wind, temperature, and humidity. It falls more on the total randomness side, but it isn't quite as random as gas molecules alone.

The Problem of Postmodernity intrigues me because I'm personally a greater fan of more traditional art, and I disagree with the notion that the future of art means neglecting or leaving traditional mediums behind. I'm often more impressed with art that uses old techniques in new ways, rather than new techniques in new ways. But I accept that the prospect of a completely new framework to explore literally any aspect of life is exciting,and part of my reason for taking this class is to become more familiar with that.

nerual-AnimatedLoop

"a cursory moment" (get it?)

Perhaps it isn't worthy of a title, but I would like to informally dub it "A Cursory Moment."

The Process:

Some sketches:

 

I was going to follow up the idea of the mouse and pop signs by making the mouse "click" on a place and then bounce off it, like the force of the click sent it flying.  I got as far as making it move in the right physics-like snapping motion with the elastic function, but I didn't get the mouse to rotate, so I decided to play with contrast and repetition to make it look more interesting instead.

This was actually where I was going to stop:

I thought it looked like the James Bond opening, so I wanted to rotate the finger to make it a finger gun. I ended up with the rotated lines of circles lining up on accident and with some tweaking, I got all circles to line up. I thought it looked more interesting that way.

I felt like this work definitely turned out a lot better than expected(although I expected very little at that point). I like the way the repetition and the appearance of the hand go with the elastic movement. It's kind of rhythmic.

It definitely lacks a lot of the mathematical complexity that I would have liked to explore. The black and white was partially an aesthetic choice and mostly a practical one. The elastic movement is rather sloppy. Overall it's very simple. Way back in the beginning I had hoped to made something more along the lines of, well, lines, and I was really disappointed I couldn't manage to incorporate that at all. I think that with more time however, I definitely could have expanded on the concept or at least made the final product smoother.

I later went back and tweaked it a bit more:

Code (easing function from p5.func):

// based on p5.func examples - easing3_animation
// the sound is from the example
// I<3DM rld 


var ease = new p5.Ease();
var speed = 0.02;
var t = 0.;
var doclear;
var x, y, tx, ty, x1, y1;
var osc, rev;
var pause = 0;
var pauseTime = 60;
var fc=0;
var padding = 20;
var ex1,ey1,ex2,ey2,ex3,ey3,ex4,ey4;
var left,right;
var phase;
var startx,starty;
var radius, mr;
var debug = false;

function setup()
{
  frameRate(70);
  createCanvas(640, 640);
  
  radius = 120;
  mr = radius*0.1;
  
  ex1 = left;
  ey1 = height/5;
  ex2 = right;
  ey2 = height/3 + height/6;
  ex3 = left;
  ey3 = ey2 + height/;
  ey4 = 700;
  
  left = width/4;
  right = 3*left;
  phase = 0;
  
  background(255);

  startx = left;
  starty = -radius;
  x = startx;
  y = starty;
  tx = startx;
  ty = starty;
}

function draw()
{
  background(0);
  drawTheThing();
  if (debug){
    push();
    background(255);
    stroke(255);
    text(frameCount, 20,20);  
    pop();
  }
  if (frameCount > 30 && frameCount < 100 && (frameCount%4 ==0)){
    var filename = "myZoetrope_" + nf(frameCount,2) + ".png";
    saveCanvas(filename, 'png');
  }
}

function doPhase(){
    switch(phase){
      case 0:
        ty = starty;
        tx = left;
        phase++;
        break;
      case 1:
        ty = ey1;
        tx = left;
        phase++;
        break;
      case 2:
        ty = ey2;
        tx = right;
        phase++;
        break;
      case 3:
        ty = ey3;
        tx = left;
        phase++;
        break;
      case 4:
        ty = ey4;
        tx = right;
        phase=0;
        phase++;
        break;
      default:
        ty += height/6;
        if (tx==left) tx=right;
        else if(tx==right) tx=left;
        else tx = left;
        phase=0;
        redraw();
        break;
    }
}

function drawTheThing(){
  var func = "elasticOut";
  var q = ease[func](t*2.5);

  var diff = frameCount - fc;
  if (diff > pauseTime){
    doPhase();
    t = 0.;
    fc = frameCount;
  }
  else if (phase==0)
    doPhase();

  x1 = map(q, 0., 1., x, tx);
  y1 = map(q, 0., 1., y, ty);

  fill(255);
  stroke(0);
  ellipse(x1, y1, radius,radius);
  ellipse(x1+left, y1, radius,radius);
  ellipse(x1-left, y1, radius,radius);

  drawMouse(width-x1, height-y1, mr);
  drawMouse(width-x1+left, height-y1, mr);
  drawMouse(width-x1-left, height-y1, mr);

  t+=speed;
  if(t>1.) {
    t=1.;
    x = tx;
    y = ty;
  } 
}

function drawMouse(y,x,s) {
  push(); 
  stroke(255);
  noFill();
  strokeWeight(10);
  ellipse(x,y, 9*s,9*s);
  
  stroke(0);
  strokeWeight(5);
  translate(-1.5*s,0,5);
  rect(x,y,4*s,3*s,5);
  rect(x,y-3.5*s,s,3.5*s,5,5,0,0);
  rect(x+s,y-s,s,s,5,5,0,0);
  rect(x+2*s,y-s,s,s,5,5,0,0);
  rect(x+3*s,y-s,s,s,5,5,0,0);
  rect(x-s,y,s,2*s,5);
  pop();
}

}

nerual-Scope

Process:

I really liked the aesthetics of the line pop explosion thing, so I wanted to make use of it somehow. I was also fixated on making something meta, in preparation for the GIF project.

Actual Code:

function drawArtFrame(whichFrame) {
  // Draw the artwork for a generic frame of the Zoetrope, 
  // given the framenumber (whichFrame) out of nFrames.

  drawMyArtFrame(whichFrame);
}
  
function drawMyArtFrame(whichFrame){
  noFill();
  stroke(0);
  strokeWeight(1);
  var padding = 30;
  var pos = map(whichFrame, 0, nFrames, artAreaHeight-padding, padding);
  var t = map(whichFrame, 0, nFrames, 0, 1);
  var diam = map(cos(t * TWO_PI), -1, 1, artAreaHeight-padding, padding+10);
  //ellipse(0, pos, 10, 10);
  var dir = map(whichFrame, 0, nFrames, -1, 1);
  if(whichFrame > 9 || whichFrame < 3) 
    drawPop(0, padding-10, 5, 10);
  drawMouseScaled(0, diam, 5);
}