harsh-arsculpture

 

This project is an android app intended to make sound from movement - each GPS coordinate in the general CMU region is mapped to a particular note, and as you move through space, say your walk from home to school, you make music.

I asked some friends of mine to use the app while on their commute from home to school, and these are the results I got:

 

Here's a screenshot of the current app:

 

 

To be a little more projective, in another iteration I'd like to have the mapping of space and sound be a little more deliberate, instead of working at this large scale, it would be more interesting for example, to turn a street into a piano, where each step creates a note, and you need to hop between steps to make music. Here's a short video of what I imagine:

harsh-UnityEssentials

   

 

Some Notes

  • Unity is NOT a modeling software - assets must be made outside of the editor
  • The physics engine is AWESOME, so is the particle collider
  • Textures / Materials quite similar to Rhino
  • Animations are cool, but the scripting interface's "Update" function seems more useful
  • Lighting also similar to Rhino
  • Particles are interesting, but seem more like a gimic / VR thing
  • Timeline's functionality seems better done via scripting...

casher-harsh-justaline

This project is a treasure hunt for stars in the CFA staircase. Follow the thread up and down to find your star - casher & harsh.

We imagine a world where buildings become spaces of intrique and mystery, ever changing, with all kinds of secrets and treasures hiden within. It's kind of like Hogwarts, except with a Wifi connection. This "star" treasure hunt could expand into other sorts of ideas, where we pull people in using threads into all kinds of different events and playscapes. Imagine a secret room filled with virtual pets you can play with.

 

harsh-Book

Title: Make Limericks Not Hate
Description: A collection of Limericks made out of the President's tweets.

link

Narrative

 

Needless to say, this project was super fun to work on (though frustrating at times). Here's a short description of the steps I took to make it:

  1. Collect a JSON with tweets with certain keywords from : http://www.trumptwitterarchive.com/
  2. Parse those keywords with Rita.js and break the sentences down into 8-ish syllable long strings with the keyword at the end, eg "bad" or "fake news".
  3. Key Words: [fake news, wall, bad, winning, loser, stupid]
  4. Come up with the starting lines for the limericks, because a limerick has the structure of AABBA, I chose to come up with some defaults for the first A, first B and last A, and then inject the parsed sentences into the other remaining A and B, so there would be some continuity and narrative in the limericks
  5. Program in Rita to construct the limerick and export as a JSON with individual limericks, I essentially mixed and matched my keywords between the A's and B's - so you could find 'news' as A and 'bad' as B and vice versa
  6. Program a particle system using twitter icon in Basil.js - this would serve as background for the chapter
  7. Randomly mix and match limericks and place into the document in Basil.
  8. Huzzah!

Overall, I'm happy with the results I got - in another iteration of this project I'd focus on parsing the tweets in a smarter manner, possibly using sentiment analysis or something else to understand the meaning in the tweet.

Code - Rita.js

var wall;
var stupid; 
var sad;
var bad;
var news ;
var loser;
 
var news_st_end = ['There was once a man who was known to accuse', 'It just seemed like he was confused'];
var news_end = ["Often he'd overuse"];
 
var bad_st_end = ["There was once a man who was very mad","But now we know he was just a fad"];
var bad_end = ["He was often mad"];
 
var wall_st_end = ["There was once a man who would often bawl","But to be fair, he wasn't very tall"];
var wall_end = ["He would often call"];
 
var loser_st_end = ["There was once an old schmoozer","He came to be known as quite the abuser"];
var loser_end = ["He'd often doozer"];
 
var stupid_st_end = ["There was once a man who wasn't exactly lucid","All of his claims were later disputed"];
var stupid_end = ["He concluded"];
 
var winning_st_end = ["There was once a man who'd keep singing","Yeah, he was crazy from the beginning"];
var winning_end = ["He'd be grinning"];
 
var list = ['news', 'bad', 'wall', 'loser', 'stupid', 'winning'];
var stList = [news_st_end, bad_st_end, wall_st_end, loser_st_end, stupid_st_end, winning_st_end];
var endList = [news_end, bad_end, wall_end, loser_end, stupid_end, winning_end];
 
function preload(){
    winning = loadStrings('trump_winning.txt');
    wall = loadStrings('trump_wall.txt');
    stupid = loadStrings('trump_stupid.txt');
    sad = loadStrings('trump_sad.txt');
    bad = loadStrings('trump_bad.txt');
    news = loadStrings('trump_fake_news.txt');
    loser = loadStrings('trump_loser.txt');
}
 
 
 
function setup()
{ var strings = [news, bad, wall, loser, stupid, winning];
  createCanvas(300, 300);
  background(255);
  fill(255);
  var json = {};
  var temp;
 
 
  for(var i=0; i<list.length; i++){
    for(var j=0; j<list.length; j++){
        if(i==j){continue;}
            temp = make_limerick(strings[i], strings[j], stList[i], endList[j], list[i]+'+'+list[j]);
            json[list[i]+'+'+list[j]] = temp;
    }
  }
 
  saveJSON(json, 'master');
}
 
function draw(){
 
}
 
 
function make_limerick(A, B, A_st_end, B_end,name){
    var lower = Math.min(A.length, B.length);
    result = [];
 
    for(var i=0; i<lower; i++){
        var temp = A_st_end[0] + "," + "\n";
        temp += "He'd say, " + '"' + cap_first(A[i].trim()) + '"' + "," + "\n";
        temp += B_end[0] + "," + "\n";
        temp += '"' + cap_first(B[i].trim()) + '"';
        temp += "," + "\n";
        temp += A_st_end[1] + "."
        console.log(temp);
        result.push(temp);
    }
    var txt = parse('%s.json', name);
    return result;
}
 
function cap_first(string) 
{
    return string.charAt(0).toUpperCase() + string.slice(1);
}
 
function parse(str) {
    var args = [].slice.call(arguments, 1),
        i = 0;
 
    return str.replace(/%s/g, function() {
        return args[i++];
    });
}
 
function clean_up (stuff){
    var master = '';
    var expression1 = /[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/; 
    var expression2 = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9]\.[^\s]{2,})/;
    var expression3 = /(@[A-Za-z0-9]+)|([^0-9A-Za-z \t])|(\w+:\/\/\S+)/;
    var expression4 = /^[ \t]+|[ \t]+$/; 
    var expression5 = /a@(foo|bar|baz)\b/; 
 
 
    var regex1 = new RegExp(expression1);
    var regex2 = new RegExp(expression2);
    var regex3 = new RegExp(expression3);
    var regex4 = new RegExp(expression4);
    var regex5 = new RegExp(expression5);
 
 
    for(var i=0; i < 100; i++){ var cur_text = stuff[i].text; var rs = new RiString(cur_text); rs.replaceAll(regex1, " "); rs.replaceAll(regex2, " "); rs.replaceAll(regex3, " "); rs.replaceAll(regex4, ""); rs.toLowerCase(); if(rs._text.search("stupid") != -1 ){ var tokens = RiTa.tokenize(rs._text); var badIndex = tokens.indexOf("stupid"); if(badIndex > 5){
                tokens = tokens.slice(badIndex-10, badIndex+1);
                var token_string = ''
 
                for(var j=0; j<tokens.length; j++){
                    token_string += tokens[j];
                    token_string += ' ';
                }
 
                master+=token_string;
                master+= '\n'
            }          
        }      
    }
 
    return master;
}

Code - Basil.js

#include "../../bundle/basil.js";
 
// Version for basil.js v.1.1.0
// Load a data file containing your book's content. This is expected
// to be located in the "data" folder adjacent to your .indd and .jsx. 
// In this example (an alphabet book), our data file looks like:
// [
//    {
//      "title": "A",
//      "image": "a.jpg",
//      "caption": "Ant"
//    }
// ]
var jsonString;
var jsonData;
 
//--------------------------------------------------------
function setup() {
 
  // Load the jsonString. 
  jsonString = b.loadString("master.json");
 
 
 
  // Clear the document at the very start. 
  b.clear (b.doc());
 
 
 
var offset = 0;
 
for(var f=0; f<25; f++){
 
    // Make a title page.
 
    var pageNum = 0;
    b.addPage();
    var birds = generateBirds();
    b.fill(0,0,0);
    b.textSize(30);
    b.textFont("Helvetica","Bold"); 
    b.textAlign(Justification.LEFT_ALIGN); 
    b.text("Build Limericks Not Walls", 100,390,450,36);
 
    var obj = b.JSON.decode(jsonString);
    var list = ['news', 'bad', 'wall', 'loser', 'stupid', 'winning'];
 
    for(var i=0; i<6; i++){
      b.textFont("Helvetica","Regular");
      b.textSize(16);
      var curBroadTopic = list[i]; 
      for(var j=0; j<4; j++){     
        var rand = Math.floor(Math.random() * 6);
        while(rand == i){
          rand = Math.floor(Math.random() * 6);
        }
        var curSpecificTopic = curBroadTopic + "+" + list[rand];
        var curValList = obj[curSpecificTopic];
        var randomVal = Math.floor(Math.random() * curValList.length-1);
        curVal = curValList[randomVal];
          if(j%2 == 0){
            b.addPage();
            pageNum += 1;
            moveBirds(birds,pageNum);         
            b.textFont("Helvetica","Bold");
            var curTopicSplit = curSpecificTopic.split('+');
            b.textSize(16);
            b.text(curTopicSplit[0].toUpperCase(),60,60,400,100);
            b.textSize(16);
            b.textFont("Helvetica","Regular");
            while(curVal === undefined){
              var randVal = Math.floor(Math.random() * curValList.length-1);
              curVal = curValList[randVal];
            }
            b.text(curVal,60,150,500,200);
          }
          else{
            while(curVal === undefined){
              var randVal = Math.floor (Math.random() * curValList.length-1);
              curVal = curValList[randVal];
            }
            b.text(curVal,60,400,500,200);
          }   
      }   
 
    offset+= 1;
    // b.savePDF(f.toString());
    // for(var i=0; i<13; i++){
    //   b.removePage();
    // }
  }
 
}
};
 
function randomN(seed) {
    var x = Math.sin(seed++) * 10000;
    return x - Math.floor(x);
}
 
 
function generateBirds(){
  var birds = [];
  var posx;
  var posy;
 
  for(var i=0; i<7; i++){
 
      posx = Math.floor(randomN(i) * 436);
      posy = Math.floor(randomN(1000-i) * 300);
 
      birds.push([posx, posy]);
      var angle = Math.atan((648-posy)/(432-posx));
      b.pushMatrix();
      b.noStroke();
      b.rotate(angle);
      var anImage = b.image("twit.png", posx, posy, 15, 15);
      anImage.fit(FitOptions.PROPORTIONALLY);
      b.opacity(anImage, 50);   
      b.popMatrix();  
  }  
  return birds;
}
 
function moveBirds(birds,pageNum){
  for(var i=0; i<birds.length; i++){
    var curBird = birds[i];
    var posx = curBird[0]+(30*pageNum);
    var posy = curBird[1]+(50*pageNum);
    var angle = Math.atan((576-posy)/(400-posx));
    b.pushMatrix();
    b.noStroke();
    b.rotate(angle);
    var anImage = b.image('twit.png', posx, posy, 15, 15);
    anImage.fit(FitOptions.PROPORTIONALLY);
    b.opacity(anImage, 50);
    b.popMatrix();
  }
}
// This makes it all happen:
b.go();

 

harsh-parrish

Being a connoisseur of space exploration, robotics, and linguistics, this video hit right home with me. There's one thing, in particular, I'd like to mention here however, and that is the beautiful use of metaphor by Allison. The use of 'bots' we're sending out on a journey into linguistic space and who are sending us signals back from their exploration is an incredibly powerful one in my mind, and it really helped me shape my project. It allowed me to think of my work as all of these little creatures I was sending out into the void and getting answers back from - quite a novel approach to creative thought.

harsh-Body

1. Wolly-Willy

This was a reference to the children's toy Wolly-Willy, but done in a digital format.

2. Beard of Boids

Here's a beard made out of tiny hair follicles that behave like boids.

3. Animate Artworks

Here I tried to bring to life already made artwork - I liked the recursion in the Dali piece and how computation enabled changing it dynamically.

Bonus: Here's one with Mona-Lisa

 

Code: Wolly Willy

//
// a template for receiving face tracking osc messages from
// Kyle McDonald's FaceOSC https://github.com/kylemcdonald/ofxFaceTracker
//
// 2012 Dan Wilcox danomatika.com
// for the IACD Spring 2012 class at the CMU School of Art
//
// adapted from from Greg Borenstein's 2011 example
// http://www.gregborenstein.com/
// https://gist.github.com/1603230
//
import oscP5.*;
OscP5 oscP5;
import processing.video.*;
 
 
// num faces found
int found;
 
float[] rawArray;
 
// pose
float poseScale;
PVector posePosition = new PVector();
PVector poseOrientation = new PVector();
 
int numPoints = 4000;
Vehicle[] vehicles;
PVector[] lowPoints;
 
float prevMouseX;
float prevMouseY;
 
PImage img;
PImage lightOff;
PImage lightOn;
Capture cam;
 
float mappedPoseScale;
 
float[][] mouseCircle;
 
float[][] setupPoints;
float[][] centDist;
 
String mode;
 
void setup() {
  size(640, 480);
  frameRate(30);
  rawArray = new float[132];
  cam = new Capture(this, 640, 480, 30);
  cam.start();
  img = loadImage("hair.png");
  lightOff = loadImage("lightoff.png");
  lightOn = loadImage("lighton.png");
 
 
  oscP5 = new OscP5(this, 8338);
  oscP5.plug(this, "found", "/found");
  oscP5.plug(this, "rawData", "/raw");
  oscP5.plug(this, "poseScale", "/pose/scale");
  oscP5.plug(this, "posePosition", "/pose/position");
  oscP5.plug(this, "poseOrientation", "/pose/orientation");
 
  vehicles = new Vehicle[numPoints];
  lowPoints = new PVector[numPoints];
  initializeVehicles();
 
  setupPoints = new float[numPoints][2];
  centDist = new float[numPoints][2];
 
  mode = "setup";
}
 
void draw() {  
  //println(posePosition.x,posePosition.y);
  background(255);
  stroke(0);  
  mappedPoseScale = map(poseScale,0,6,0,1);
 
  if(keyPressed){
    if(key == ' '){
      mode = "follow";
    }
    if(key == 'r'){
      mode = "reset";
    }
  }
 
 ////////////////////// DISPLAY WEBCAM IMAGE //////////////////////
  if(cam.available()) {
    cam.read();
  }
  image(cam,0,0);
  //////////////////////////////////////////////////////////////////
  if(mode == "setup"){  
    mouseCircle = getCirclePoints(30, mouseX, mouseY);   
 
    moveBoidsInside(mouseCircle, mouseX,mouseY,30);
    for(int i=0; i<numPoints; i++){
      float[] curLoc = new float[2];
      curLoc[0] = vehicles[i].location.x;
      curLoc[1] = vehicles[i].location.y;
 
      float[] curDist = new float[2];
      curDist[0] = vehicles[i].location.x-posePosition.x;
      curDist[1] = vehicles[i].location.y-posePosition.y;   
      setupPoints[i] = curLoc;
      centDist[i] = curDist;
    }
    //if(mousePressed){ 
    //    image(lightOn,mouseX,mouseY);
    //}
    //else{
    //    image(lightOff,mouseX,mouseY);
    //}
  }
 
 
  if(mode == "follow" && found != 0){
    for(int i=0; i<numPoints; i++){
      Vehicle curBoid = vehicles[i];
      float[] curBoidLoc = new float[2];
      curBoidLoc[0] = curBoid.location.x;
      curBoidLoc[1] = curBoid.location.y;
      curBoid.maxspeed = 5;
      curBoid.maxforce = 0.2;
 
      if(curBoid.location.y < height-60){
        PVector newLoc = new PVector(posePosition.x+centDist[i][0]*mappedPoseScale,posePosition.y+centDist[i][1]*mappedPoseScale);
        //println(newLoc);
        curBoid.arrive(newLoc);
        curBoid.update();
        curBoid.display();
      }
    }
  }
 
  if(mode == "reset"){
    int num = 0;
    for(int i=0; i< numPoints; i++){
      Vehicle curBoid = vehicles[i];
      curBoid.maxspeed = 50;
      curBoid.maxforce = 10;
      curBoid.jiggleRadius = 1;
      curBoid.arrive(lowPoints[i]);
      curBoid.update();
      curBoid.display();
      if((curBoid.location.y-lowPoints[i].y) < 2){ num++; } } if(num >= numPoints){
        mode = "setup";
      }
  }
 
}
 
 
 
////////////////////////////////////////////////////////////////////////
/////////////////////Vehicle Settings //////////////////////////////////
////////////////////////////////////////////////////////////////////////
 
void initializeVehicles(){
  for(int i=0; i<numPoints; i++){
    PVector pos = new PVector(random(width), random(height-30,height));
    lowPoints[i] = pos;
    Vehicle new_vehicle = new Vehicle(pos.x,pos.y);
    vehicles[i] = new_vehicle;
  }
}
 
void jiggle(){
  for(int i=0; i<numPoints; i++){
    Vehicle v = vehicles[i];
    v.arrive(v.location);
    v.update();
    v.display();
  }
}
 
void display(){
    for(int i=0; i<numPoints; i++){
    Vehicle v = vehicles[i];
    v.update();
    v.display();
  }
}
 
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
 
// OSC CALLBACK FUNCTIONS
 
public void found(int i) {
  //println("found: " + i);
  found = i;
}
 
public void poseScale(float s) {
  //println("scale: " + s);
  poseScale = s;
}
 
public void posePosition(float x, float y) {
  //println("pose position\tX: " + x + " Y: " + y );
  posePosition.set(x, y, 0);
}
 
public void poseOrientation(float x, float y, float z) {
  //println("pose orientation\tX: " + x + " Y: " + y + " Z: " + z);
  poseOrientation.set(x, y, z);
}
 
public void rawData(float[] raw) {
  rawArray = raw; // stash data in array
}
 
// all other OSC messages end up here
void oscEvent(OscMessage m) {
  if(m.isPlugged() == false) {
    //println("UNPLUGGED: " + m);
  }
}

Code: Artwork

 

// Processing 3.0x template for receiving raw points from
// Kyle McDonald's FaceOSC v.1.1 
// https://github.com/kylemcdonald/ofxFaceTracker
//
// Adapted by Kaleb Crawford and Golan Levin, 2016-7, after:
// 2012 Dan Wilcox danomatika.com
// for the IACD Spring 2012 class at the CMU School of Art
// adapted from from Greg Borenstein's 2011 example
// https://gist.github.com/1603230
 
import oscP5.*;
OscP5 oscP5;
int found;
float[] rawArray;
int highlighted; //which point is selected
float poseScale;
 
PImage background;
PImage mouth;
PImage left_eyebrow;
PImage right_eyebrow;
PImage small_eyebrows;
PImage smallest_eyebrows;
PImage eyes;
 
 
 
float mouthOff;
 
float rightBrowOff;
float leftBrowOff;
float smallBrowOff;
 
float prevRightBrowOff;
float prevLeftBrowOff;
float mappedScale;
 
//--------------------------------------------
void setup() {
  size(800, 682);
  frameRate(30);
 
  rawArray = new float[132]; 
  oscP5 = new OscP5(this, 8338);
  oscP5.plug(this, "found", "/found");
  oscP5.plug(this, "rawData", "/raw");
  oscP5.plug(this, "poseScale", "/pose/scale");
 
  background = loadImage("base.png");
  mouth = loadImage("mouths.png");
  left_eyebrow = loadImage("left eyebrow.png");
  right_eyebrow = loadImage("right eyebrow.png");
  small_eyebrows = loadImage("small eyebrows.png");
  eyes = loadImage("eyes.png");
  smallest_eyebrows = loadImage("smallest eyebrows.png");
 
 
}
 
//--------------------------------------------
void draw() {  
  mappedScale = map(poseScale, 0,5,0,1);
 
  prevRightBrowOff = rightBrowOff;
  prevLeftBrowOff = leftBrowOff;
 
  rightBrowOff = (getLeftBrowHeight());
 
  leftBrowOff =  (getRightBrowHeight());
 
  smallBrowOff = (getRightBrowHeight());
 
  image(background, 0, 0);
 
  pushMatrix();
  translate(0,-(rightBrowOff*2));
  image(left_eyebrow, 0, -2);
  popMatrix();
 
  pushMatrix();
  translate(0,-(leftBrowOff*8));
  image(right_eyebrow, 0, 0);
  popMatrix();
 
  pushMatrix();
  translate(0,-(leftBrowOff));
  image(small_eyebrows, 0, 0);
  popMatrix();
 
  pushMatrix();
  translate(0,-(leftBrowOff*0.5));
  image(smallest_eyebrows, 0, 0);
  popMatrix();
 
  if(leftEyeClosed() || rightEyeClosed()){
    image(eyes, 0, 0);
  }
 
  pushMatrix();
  tint(255, 300-(getMouthMovement())*5);
  image(mouth, 0, 0);
  popMatrix();
 
 
 
 
}
 
//--------------------------------------------
void drawFacePoints() {
  int nData = rawArray.length;
  for (int val=0; val<nData; val+=2) {
    if (val == highlighted) { 
      fill(255, 0, 0);
      ellipse(rawArray[val], rawArray[val+1], 11, 11);
    } else {
      fill(100);
      ellipse(rawArray[val], rawArray[val+1], 8, 8);
    }
  }
}
 
//--------------------------------------------
void drawFacePolygons() {
  noFill(); 
  stroke(100); 
 
  // Face outline
  beginShape();
  for (int i=0; i<34; i+=2) { vertex(rawArray[i], rawArray[i+1]); } for (int i=52; i>32; i-=2) {
    vertex(rawArray[i], rawArray[i+1]);
  }
  endShape(CLOSE);
 
  // Eyes
  beginShape();
  for (int i=72; i<84; i+=2) {
    vertex(rawArray[i], rawArray[i+1]);
  }
  endShape(CLOSE);
  beginShape();
  for (int i=84; i<96; i+=2) {
    vertex(rawArray[i], rawArray[i+1]);
  }
  endShape(CLOSE);
 
  // Upper lip
  beginShape();
  for (int i=96; i<110; i+=2) { vertex(rawArray[i], rawArray[i+1]); } for (int i=124; i>118; i-=2) {
    vertex(rawArray[i], rawArray[i+1]);
  }
  endShape(CLOSE);
 
  // Lower lip
  beginShape();
  for (int i=108; i<120; i+=2) { vertex(rawArray[i], rawArray[i+1]); } vertex(rawArray[96], rawArray[97]); for (int i=130; i>124; i-=2) {
    vertex(rawArray[i], rawArray[i+1]);
  }
  endShape(CLOSE);
 
  // Nose bridge
  beginShape();
  for (int i=54; i<62; i+=2) {
    vertex(rawArray[i], rawArray[i+1]);
  }
  endShape();
 
  // Nose bottom
  beginShape();
  for (int i=62; i<72; i+=2) {
    vertex(rawArray[i], rawArray[i+1]);
  }
  endShape();
}
 
 
//--------------------------------------------
public void found(int i) {
  found = i;
}
public void rawData(float[] raw) {
  rawArray = raw; // stash data in array
}
 
public void poseScale(float s) {
  //println("scale: " + s);
  poseScale = s;
}
 
//--------------------------------------------
void keyPressed() {
  int len = rawArray.length; 
  if (keyCode == RIGHT) {
    highlighted = (highlighted + 2) % len;
  }
  if (keyCode == LEFT) {
    highlighted = (highlighted - 2 + len) % len;
  }
}

harsh-LookingOutwards03

Delicate Boundaries - Chris Sugrue

This project interests me not because of the artistic concept behind it(which I find a bit simplistic), but because of the novel use of media. The way the artist uses projection mapping to bridge the divide between the digital and the physical is incredible - giving digital objects a "presence" without much effort. This served as a reference point for my "Augmented Body" project.

 

harsh-viewing04

Spectacle: The use of digital technologies for mostly aesthetic and commercial purpose - wowing the viewer with technological marvel or obsessiveness about craft.

Speculation: Being self-aware of the nature of digital media, and reflecting/expressing this awareness through means of irony. Usually separated from the technical craft of creation itself.

 

 

Ugly Dynamics - this example from the video just blew my mind - both in its conceptual brilliance and incredible affect and experience.
Warburton clearly thinks of this as a combination of Speculation and Spectacle - and I could not agree more. It is incredibly self-aware, both in terms of aesthetics as well as conceptual execution (the project is filled to the brim with irony). I also think that this project reclaims spectacle as speculation - looking beyond the normal's of "simulation" and shifting the context of what we think simulation is. It's incredibly subversive - while still pushing the frontier on human experience. I'm incredibly jealous of both the technical and conceptual brilliance shown by Nikita Daikur here, never seen anything like this before.

Here's where it lies:
Drag -----/----- Acceleration
Visibility -/--------- Invisibility
Surplus -----/----- Waste
Commerce ---------/- Art

Ugly Dynamics from nikita diakur on Vimeo.

harsh-telematic

 

link

This interactive environment is called "Bird-Do-Or-Die" where users compete or collaborate to either save or kill the bird(s). This is best played over a period of time. People should use their asynchronous free time to either protect or kill the bird - competing against other users over longer durations.

The network model here is ideally a many-to-many setup - where people form teams to work on saving/and or killing the bird over time. This also makes the system asynchronous - where people can work on increasing the bridge blocks over time, which then others must overcome to kill the bird. The roles are essentially oppositional - where people work to defeat the other's work.