casher-body

(wow I look tired)

I had been intrigued by the last project's option to design a drawing program in Glitch, so I thought it would be fun to explore that in this project. I also wanted to create something that involves the whole body in order to make the user look ridiculous. Combining the two, I made this silly drawing application (which, I realized, can also double as an exercise "machine," if the user plays with it intensely enough). In my process, since this is a live application, I had to figure out how to track the different motions of various body parts and calculate their distances from specific points on the screen. Originally I had planned for the wideness of the opening of your mouth to control the stroke weight of the lines, but I discovered that using this code template, which doesn't analyze the mouth, was easier for me to use, so I had to change my idea a little bit. I am mostly happy with the product here -- it is very similar to the vision I had in the beginning, which is awesome because it means that I have either (or both) made progress in my coding abilities or learned to not be overly ambitious in my projects! If I could change a few things, I would first try to make it collaborative, so that people could draw together; and once I realized that it could be a form of exercise, I thought it could be cool to make it a game where the user would have to race a clock to draw something of specific shape, color, and size, which would force them to hop, squat, and move pretty quickly.

Directions:

You draw around the board with your nose. To turn on the pen, lift your left hand until it crosses the top white bar. Pick up the pen by touching the left bar with your left hand, and back up to the top to turn it on again. To change the color of the pen, jump high enough that both feet cross above the bottom white line. To make the pen thicker, jump so your nose crosses the top line; to thin the pen, duck low enough that your nose crosses the bottom line. To erase all lines, cross the right bar with your right hand.

 

let video;
let poseNet;
let poses = [];
let colors = ["black", "white", "red", "orange", "yellow", "green", "blue", "purple", "pink", "brown", "grey"]
let colorindex = 0;
let inArea = false;
let drawing = false;
let inArea2 = false;
let inArea3 = false;
let allLines = [];
let lines = [];
let circle = [65, 50, 30, 30];
let prevKpX;
let prevKpY;
let strokewidth = 3;
 
// Storing the last keypoint position
let lastKeypoints = [];
 
function setup() {
  createCanvas(640, 480);
  frameRate(24);
  video = createCapture({
    audio: false,
    video: {
      width: {
        ideal: 640
      },
      height: {
        ideal: 480
      }
    }
  });
  video.size(width, height);
 
  // Create a new poseNet method with a single detection
  poseNet = ml5.poseNet(video);
  // This sets up an event that fills the global variable "poses"
  // with an array every time new poses are detected
  poseNet.on('pose', function(results) {
    poses = results;
  });
  // Hide the video element, and just show the canvas
  video.hide();
 
  //print(lastKeypoints); 
  // setup original keypoints
  createDefaultKeypoints();
  //print(lastKeypoints);
}
 
// Create default keypoints for easing. 
function createDefaultKeypoints() {
  let numKeypoints = 17;
  for (let i = 0; i < numKeypoints; i++) {
    newKeypoint = {
      x: width / 2,
      y: height / 2
    }
 
    lastKeypoints.push(newKeypoint);
  }
}
 
function updateKeypoints() {
  // If there are no poses, ignore it.
  if (poses.length <= 0) {
    return;
  }
 
  // Otherwise, let's update the points; 
 
  let pose = poses[0].pose;
  let keypoints = pose.keypoints;
 
  for (let kp = 0; kp < keypoints.length; kp++) {
 
    let oldKeypoint = lastKeypoints[kp];
    let newKeypoint = keypoints[kp].position;
 
    let interpX = lerp(oldKeypoint.x, newKeypoint.x, .3);
    let interpY = lerp(oldKeypoint.y, newKeypoint.y, .3);
 
    let interpolatedKeypoint = {
      x: interpX,
      y: interpY
    }
 
    lastKeypoints[kp] = interpolatedKeypoint;
  }
}
 
function draw() {
  push();
  translate(width, 0, 0);
  scale(-1, 1);
  image(video, 0, 0, width, height);
 
 
  updateKeypoints();
 
  drawKeypoints();
  pop();
 
  strokeWeight(5);
  stroke(255);
  fill(255);
  line(0, height * .9, width, height * .9);
  line(0, height *.1, width, height*.1);
  line(width*.1, 0, width*.1, height);
  line(width*.9, 0, width*.9, height);
  stroke(colors[colorindex]);
  ellipse(circle[0], circle[1], circle[2], circle[3]);
}
 
// A function to draw ellipses over the detected keypoints
function drawKeypoints() {
  for (let i = 0; i < lastKeypoints.length; i++) {
    if (i == 0) {
      keypoint = lastKeypoints[i];
      fill(colors[colorindex]);
      //console.log(allLines);
      for (let i = 0; i < allLines.length; i++) {
        for (let j = 0; j < allLines[i].length; j++) { //console.log("c"); stroke(colors[allLines[i][j][4]]); strokeWeight(allLines[i][j][5]); line(allLines[i][j][0], allLines[i][j][1], allLines[i][j][2], allLines[i][j][3]); } } if (drawing == true) { if (lastKeypoints[9].y > height * .1) {
          stroke(colors[colorindex]);
          //console.log(lines);
					lines[0] = [lastKeypoints[0].x, lastKeypoints[0].y, lastKeypoints[0].x, lastKeypoints[0].y, colorindex, strokewidth]
          x1 = prevKpX;
          y1 = prevKpY;
          x2 = lastKeypoints[0].x;
          y2 = lastKeypoints[0].y;
          lines.push([x1, y1, x2, y2, colorindex, strokewidth]);
          for (i = 1; i < lines.length; i++) {
            stroke(colors[lines[i][4]]);
            strokeWeight(lines[i][5]);
            line(lines[i][0], lines[i][1], lines[i][2], lines[i][3]);
          }
          prevKpX = x2;
          prevKpY = y2;
        }
 
      }
      if (lastKeypoints[9].y < height * .1) { if (drawing == false) { drawing = true; } } if (lastKeypoints[9].x > width * .9) {
        if (drawing == true) {
          allLines.push(lines);
          lines = [];
          drawing = false;
        }
      }
      if (lastKeypoints[10].x < width*.1) {
        allLines = [];
        lines = [];
        drawing = false;
      }
      if (lastKeypoints[0].y < height*.1) {
        if (inArea2 == false) {
          if (circle[2] < 80 && circle[3] < 80 && strokewidth < 52) { circle[2] += 5; circle[3] += 5; strokewidth += 3; inArea2 = true; } } } else { inArea2 = false; } if (lastKeypoints[0].y > height*.9) {
        if (inArea3 == false) {
          if (circle[2] > 10 && circle[3] > 10 && strokewidth > 3) {
            circle[2] -= 5;
            circle[3] -= 5;
            strokewidth -= 3;
            inArea3 = true;
          }
        }
      }
      else {
        inArea3 = false;
      }
      stroke(255);
      fill(255);
      strokeWeight(0);
      ellipse(lastKeypoints[0].x, lastKeypoints[0].y, 10, 10);
      ellipse(lastKeypoints[9].x, lastKeypoints[9].y, 20, 20);
      ellipse(lastKeypoints[10].x, lastKeypoints[10].y, 20, 20);
      ellipse(lastKeypoints[15].x, lastKeypoints[15].y, 20, 20);
      ellipse(lastKeypoints[16].x, lastKeypoints[16].y, 20, 20);
      if (lastKeypoints[15].y < height * .9 && lastKeypoints[16].y < height * .9) {
        if (inArea == false) {
          colorindex = (colorindex + 1) % colors.length;
          inArea = true;
        }
      } else {
        inArea = false;
      }
    }
  }
}

casher-LookingOutwards03

I looked at Danny Rozin for this Looking Outwards, as I recognized his name when I saw it on the list of artists Golan provided. When I clicked on his website, I realized that I knew him from my Art and Arudino class -- I am working on an "Interactive" project in that class right now as well, and my professor had also used the wooden mirror as an example of what kinds of interactivity can be achieved with Arduino (Rozin made the wooden one just with servos). It amazes me how basically anyone could make this kind of art, since Arduino is so accessible and easy to learn. There is a beauty to how simple it is, yet this idea is so creative.

I love how there is a juxtaposition between the facts that many of his "mirrors" are made with natural or recycled materials, but they are technically put together and controlled in a calculated and digitized way with software. I also like how Rozin questions the self in his artwork, as he has come up with so many ways to represent reflection. It's interesting to discuss whether he is trying to critique society and its narcissism by showing how we interact with our reflections even when we are reduced to just shadows, or if he means for individuals to look deeper within themselves and discover things they couldn't see on their obvious surfaces.

casher-Telematic

Starry Night AgarioInteractive Embedded App

Gif

Sequential Sketches
My game is a simple take on Agar.io. To play, move the mouse around the screen, and your circle will follow in the center. The larger stars can be eaten to make you bigger, whereas if you eat the smaller stars they will release all of your current points and return you to the starting size. You can also eat other players to gain points. The goal is to try and get as big as possible without exploding from the little stars.
As seen in my sketches, this game was not my original plan. I ended up being too ambitious for my abilities in my first two ideas. The first was a "Hungry Hungry Hippo" type game, where all players would move their triangle characters around with the mouse, take pebbles from the center of the screen, stash them in their respective circles, and then proceed to steal pebbles from each other until one had 10 in their circle. When I realized that was too complicated, I tried to make a simpler shooter game, where each character controlled a triangle with the mouse and could shoot other players out of the game with the space bar. You can see all the geometric transformation calculations I was trying to do; unfortunately I was unable to figure those out, so finally I moved on to this simpler idea.
I wanted from the beginning for my environment to be mostly anonymous, as I was intrigued by the idea of creating competition that didn't really stem from anywhere. A lot of the time, people say that competition is based on social norms and expectations that society has created for specific groups, so we tend to feel the need to meet them in order to fit in. However, anonymously, in my game there is nothing to prove and no one to impress -- therefore, it shows how people are still eager to come out on top even without a reason, and that we are competitive by nature. I show each player their own name to create an identity for themselves, but I hide the names of other players to give the least information out as possible. The only number that defines them is how many points they have -- or, how competitive they are.

casher-Viewing04

Spectacle: art that has some kind of intentional aesthetic appeal, mainly to impress the viewer/consumer and introduce new technological advancements; technical, straightforward, and unidimensional.

Speculation: art that intends to bring awareness to a specific topic of societal concern; metaphorical, critical, and self-aware.

I decided to explore to work of Warburton himself, and I found that he tends to test the limits of software while also questioning reality and societal conventions -- in doing so, he often blends spectacle and speculation in his projects. One that struck me in particular was Primitives, an exploration and experimentation with crowd simulation. In this project, he worked with a dancer to highlight the nuance and relevance of crowd simulation in today's graphics; how such algorithms have made it so easy for designers to manipulate multiple "beings" and their parameters in the same way, all at once, at the click of a button. Crowd simulation is useful for effortless but accurate creations of conflict, disaster, and death in films and TV.

At first thought, this is merely technical. However, Warburton dives deeper into speculation by questioning how crowd simulation software could be challenging our definitions of freedom and agency -- that a computer having such power over "human" entities with so much ease of manipulation could be representational of the future we may have, with artificial intelligence eventually gaining control over us and finding ways to manipulate our own daily "parameters." In the project videos, he tries to simultaneously individualize and humanize the dancers while testing the limits of the software, illustrating how core standards of life are being called into question.

casher-clock

 

For my clock, I made a graphic that increases the number of sides in the shape according to the hour, has an increasing number of rings according to the minute, and pulses according to the second. The color also changes according to the specific time. I really wished I had had more time to work on this because there were some cool effects that I didn't get the chance to code. I had a lot of other work this week so I actually couldn't find a time to truly start it until tonight; nevertheless, I worked hard, and as you can see my third GIF render is from right now -- 2:10am. Gotta love coding.

I was stuck for a while at the beginning on how to actually generate shapes with sides according to the hour, so that it changes without me having to draw 12 different shapes and call them individually using if statements. Golan told me about beginShape(), so that new function with a bit of trig helped me generate the hourly shapes. And of course, Char came along and aided with the pulsing. However, this code is 100% my own! There were no templates from Golan or chunks from the internet. I am proud of that. Learning is cool!

casher-Reading03

In my senior year of high school (last year), I was a visual design major. In most of the years before that, the teacher had her students do a few big projects each year; however, in my year, we got a huge proposal from the principal to create a piece of public art that represents our mission statement to hang in the school. It was very important to the principal that a lot of work went into its production, so before any sketching, we spent the whole first semester doing market research on how to create the perfect piece. We had to make sure that it would not only represent our large body of students, but "stand the test of time." That exact quote was written on every brainstorm sheet.

I bring this up because Naimark's student's remark about surviving time reminded me of how true it is (in my opinion) that artists cannot only make art for the now -- after researching for so long, I learned that we have to predict how people will interpret our pieces in the future, and strategically plan around that so they aren't forgotten. If the piece won't have cultural or social significance come the next generation of artists, is it worth making at all? Artists shape artists; first word art depends on last word art, and vice versa. I agree that when work is technologically novel, it can age poorly, but that's only if people aren't willing to accept that this is the direction our cultures and societies are moving toward. It's important for artists themselves to be adaptable to changing times, and as a result they learn how to make their art robust. I think it's ultimately more important for artists to make first word than last word because we will no longer learn anything if we stop experimenting and innovating.

casher-LookingOutwards02

I have chosen to look at Tentasho (2016), a work of Lia, a generative software artist based in Austria. It is a procedural installation on a touchscreen, and it can either be interactive, where the user touches the screen to drag a path in the application, or it is automatic (and completely generative) when there is no user and the application draws paths itself. These paths are randomly calculated but follow a specific algorithm that creates "tentacle"-like splines coming off the main spline. The drawings end up looking similar to caterpillars, or like some kind of many-legged creatures.

As mentioned in the description on the main website, I too appreciate the minimalist design. There are only three colors, and every image only consists of lines on a white background. I can tell that Lia has a good eye for clean design and aesthetics. It gives the piece a sense of simplicity.  Therefore, I would say that it has a moderate amount of effective complexity -- the lines follow a general order, or what seems to be algorithmic "rules," but the paths in total are somewhat disordered. I suppose that the algorithm simultaneously generates the main center line and the smaller spline lines as the path gets larger, but the length limit of the splines gets smaller as the path is drawn.

https://www.liaworks.com/theprojects/tentasho/

casher-AnimatedLoop

https://editor.p5js.org/cassiescheirer/sketches/SknMGG_O7

I don't know why but my computer was having an incredibly hard time exporting my frames -- some were being skipped, and everything was patchy. I had Char help me export and the GIF still ended up being way too slow. Click the link above it or here (https://editor.p5js.org/cassiescheirer/sketches/SknMGG_O7) to see it in the p5.js editor. Sorry about this.

Anyway, I am mostly happy with this project. I wish I had had more time to make it more fancy, and a better laptop so that I wouldn't have gotten so frustrated at the lag, but overall I am proud. It took a little while to come up with the idea, but once I knew what I wanted to do, I had to make it happen. Again I had Char talk through the syntax I didn't know, but a lot of it I figured out myself this time. For the easing function, I knew that I was probably going to need one to simulate the "bouncing" of the ball, so I looked for one that matched that motion the most. I went through a couple of them before concluding that the doubleExponentialSigmoid, which Golan had already used in the template, was actually the best one. Having that as a guide was helpful.

I'm proud of myself for having a set idea in mind and then putting in the effort to execute it, even though it was hard. I also really like the simplicity of my GIF. At one point I was about to add some flashing circles in the background, but Char told me that the minimalist-ness of it was what made it so nice. However, I think it is only that way because I hadn't allotted enough time to make it super grand. If I had more time and had known more of the p5.js syntax, I definitely would have made it more complicated.  As you can see in my sketch (bottom left), I started an idea that branched off of the flipping square -- a skillet flipping a pancake. I stopped myself there though, as I knew I probably didn't know enough to do that. I hope I can come back to this project when I have time and make the pancake idea.

 

//===================================================
// User-modifiable global variables. 
var myNickname = "Cassie";
var nFramesInLoop = 120;
var bEnableExport = true;
 
// Other global variables you don't need to touch.
var nElapsedFrames;
var bRecording;
var theCanvas;
 
var canvaswidth = 645;
var canvasheight = 645;
 
var flipper = false;
 
//===================================================
function setup() {
  theCanvas = createCanvas(canvaswidth, canvasheight);
  bRecording = false;
  nElapsedFrames = 0;
  rectMode(CENTER);
}
 
//===================================================
function keyTyped() {
  if (bEnableExport) {
    if ((key === 'f') || (key === 'F')) {
      bRecording = true;
      nElapsedFrames = 0;
    }
  }
}
 
//===================================================
function draw() {
 
  // Compute a percentage (0...1) representing where we are in the loop.
  var percentCompleteFraction = 0;
  if (bRecording) {
    percentCompleteFraction = float(nElapsedFrames) / float(nFramesInLoop);
  } else {
    percentCompleteFraction = float(frameCount % nFramesInLoop) / float(nFramesInLoop);
  }
 
  // Render the design, based on that percentage. 
  // This function renderMyDesign() is the one for you to change. 
  renderMyDesign (percentCompleteFraction);
 
  // If we're recording the output, save the frame to a file. 
  // Note that the output images may be 2x large if you have a Retina mac. 
  // You can compile these frames into an animated GIF using a tool like: 
  if (bRecording && bEnableExport) {
    var frameOutputFilename = myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png";
    print("Saving output image: " + frameOutputFilename);
    saveCanvas(theCanvas, frameOutputFilename, 'png');
    nElapsedFrames++;
 
    if (nElapsedFrames >= nFramesInLoop) {
      bRecording = false;
    }
  }
}
 
//===================================================
function renderMyDesign (percent) {
  //
  // THIS IS WHERE YOUR ART GOES. 
  // This is an example of a function that renders a temporally looping design. 
  // It takes a "percent", between 0 and 1, indicating where we are in the loop. 
  // Use, modify, or delete whatever you prefer from this example. 
  // This example uses several different graphical techniques. 
  // Remember to SKETCH FIRST!
 
  //----------------------
  // here, I set the background and some other graphical properties
  var x = abs(cos(percent*TWO_PI))
  var y = doubleExponentialSigmoid(x, 0.25);
  var squish =  map(y, 0, 1, 10, 30);
 
  background(0);
  rectMode(CENTER);
  strokeWeight(2);
  stroke(255);
 
  // flipping base
  push();
  translate(width / 2 + 20*sin(TWO_PI*percent), height-250);
  rotate(sin(TWO_PI*percent));
  var flipx = map(-cos(frameCount/9.5), -1, 1, 0, 200);
 
  if (frameCount % 120 >= 60) {
		fill(200, 100, 200);
  }
  else {
    fill(200,200,100);
  }
  rect(0, 20, flipx, 200);
  pop();
 
  translate(width / 2, height / 2);
 
  // ball shadow
  push();
  var shadowbounce = map(y, 0, 1, 100, 40);
  fill(0);
  noStroke();
  rotate(-abs(cos(TWO_PI*percent)));
  ellipse(0, shadowbounce, cos(frameCount/20)*20, cos(frameCount/20)*15);
  pop();
 
  // ball
  push();
  fill(255);
	var ballbounce = map(-y,0,1,100,360);
  distance = height - ballbounce;
  ellipse(0, ballbounce, 30, squish);
  pop();
 
// Symmetric double-element sigmoid function ('_a' is the slope)
// See https://github.com/IDMNYU/p5.js-func/blob/master/lib/p5.func.js
// From: https://idmnyu.github.io/p5.js-func/
//===================================================
function doubleExponentialSigmoid (_x, _a){
  if(!_a) _a = 0.75; // default
 
  var min_param_a = 0.0 + Number.EPSILON;
  var max_param_a = 1.0 - Number.EPSILON;
  _a = constrain(_a, min_param_a, max_param_a);
  _a = 1-_a;
 
  var _y = 0;
  if (_x<=0.5){
    _y = (pow(2.0*_x, 1.0/_a))/2.0;
  }
  else {
    _y = 1.0 - (pow(2.0*(1.0-_x), 1.0/_a))/2.0;
  }
  return(_y);
	}
}

casher-Scope

Since I am still new to Javascript/p5.js, I didn't totally understand what the code in the template meant when I began this assignment. As a result, most of my design is from experimentation. I started out by writing some groups of statements similar to the template's, and then I just started changing values of variables and parameters, testing the limits of the application. I spent a long time perfecting everything so it looked aesthetic.

There's not much else to explain, but I love the way it turned out! And I am pleased with the effort I put in because now I definitely better understand how the code works.

/*
// Template for KidzLabs/4M/Toysmith Animation Praxinoscope
// https://www.amazon.com/4M-3474-Animation-Praxinoscope/dp/B000P02HYC
// https://www.walmart.com/ip/Animation-Praxinoscope-Science-Kits-by-Toysmith-3474/45681503
// Developed for p5.js, September 2018 * Golan Levin 
 
*/
 
var bRecordingPNG = false;
 
var inch = 72.0; 
var diamArtInner = inch * 1.50; 
var diamArtOuter = inch * 4.80; 
var diamCutInner = inch * 1.41; 
var diamCutOuter = inch * 4.875; 
var holeDy = inch * 0.23;
var holeDx = inch * 0.20;
var holeD = inch * 0.1;
 
var nFrames = 10; 
var myFrameCount = 0;
var exportFrameCount = 0; 
var bAnimate = true; 
var bExportFrameImages = false;
 
//-------------------------------------------------------
function setup() {
  createCanvas(792, 612); // 11x8.5" at 72DPI
  frameRate(20);
  smooth();
} 
 
 
//-------------------------------------------------------
function draw() {
  background(255); 
 
  // Do all the drawing. 
  push(); 
  translate(width/2, height/2);
  drawCutLines(); 
  //drawGuides(); 
  drawAllFrames();
  pop();
 
 
  if (bRecordingPNG) {
    saveCanvas('myPraxinoscope.png', 'png');
    bRecordingPNG = false;
  }
}
 
 
//-------------------------------------------------------
function keyPressed() {
  switch (key) {
  case ' ': 
    // Press spacebar to pause/unpause the animation. 
    bAnimate = !bAnimate;
    break;
 
  case 'p': 
  case 'P':
    // Press 'p' to export a PNG for the Praxinoscope.
    bRecordingPNG = true; 
    break;
 
  case 'f':
    case 'F':
      // Press 'f' to export multiple frames 
      // (in order to make an animated .GIF)
      // such as with http://gifmaker.me/
      myFrameCount = 0;
      exportFrameCount = 0;
      bExportFrameImages = true;
      bAnimate = true;
 
      if (bExportFrameImages) {
        var recordFramerate = 1.0;
        var recordDuration = nFrames * 1.01; 
        frameRate(recordFramerate); // 1 FPS baby
        saveFrames('Praxinoscope_', 'png', recordDuration, recordFramerate); 
        bExportFrameImages = false;
      }
 
      break;
  }
}
 
//-------------------------------------------------------
function drawCutLines() {
  fill(0); 
  textAlign(CENTER, BOTTOM); 
  text("Praxinoscope Template", 0, 0-diamCutOuter/2-6); 
 
  stroke(0); 
  strokeWeight(1.0);
 
  noFill(); 
  if (!bRecordingPNG) {
    fill(255); 
  }
  ellipse(0, 0, diamCutOuter, diamCutOuter);
 
  noFill(); 
  if (!bRecordingPNG) {
    fill(240); 
  }
  ellipse(0, 0, diamCutInner, diamCutInner);
 
  noFill(); 
  ellipse(diamCutOuter/2 - holeDx, 0-holeDy, holeD, holeD); 
 
  line (diamCutInner/2, 0, diamCutOuter/2, 0);
}
 
//-------------------------------------------------------
function drawGuides() {
  // This function draws the guidelines. 
  // Don't draw these when we're exporting the PNG. 
  if (!bRecordingPNG) {
 
    noFill(); 
    stroke(128); 
    strokeWeight(0.2); 
    ellipse(0, 0, diamArtInner, diamArtInner); 
    ellipse(0, 0, diamArtOuter, diamArtOuter);
 
    for (var i=0; i<nFrames; i++) {
      var angle = map(i, 0, nFrames, 0, TWO_PI); 
      var pxi = diamArtInner/2 * cos(angle);
      var pyi = diamArtInner/2 * sin(angle);
      var pxo = diamArtOuter/2 * cos(angle);
      var pyo = diamArtOuter/2 * sin(angle);
      stroke(128); 
      strokeWeight(0.2);
      line (pxi, pyi, pxo, pyo);
    }
 
    // Draw the red wedge outline, highlighting the main view.
    var redWedge = 7; // assuming nFrames = 10
    for (var i=redWedge; i<=(redWedge+1); i++) {
      var angle = map(i, 0, nFrames, 0, TWO_PI); 
      var pxi = diamArtInner/2 * cos(angle);
      var pyi = diamArtInner/2 * sin(angle);
      var pxo = diamArtOuter/2 * cos(angle);
      var pyo = diamArtOuter/2 * sin(angle);
      stroke(255, 0, 0); 
      strokeWeight(2.0);
      line (pxi, pyi, pxo, pyo);
    }
    noFill(); 
    stroke(255, 0, 0); 
    strokeWeight(2.0);
    var startAngle = redWedge*TWO_PI/nFrames;
    var endAngle = (redWedge+1)*TWO_PI/nFrames;
    arc(0, 0, diamArtInner, diamArtInner, startAngle, endAngle); 
    arc(0, 0, diamArtOuter, diamArtOuter, startAngle, endAngle); 
 
 
    for (var i=0; i<nFrames; i++) {
      var angle = map(i, 0, nFrames, 0, TWO_PI); 
 
      push();
      rotate(angle); 
      var originY = ((diamArtOuter + diamArtInner)/2)/2;
      translate(0, 0-originY); 
 
      noFill(); 
      stroke(128); 
      strokeWeight(0.2);
      line (-inch/2, 0, inch/2, 0); 
      line (0, -inch/2, 0, inch/2); 
 
      pop();
    }
  }
}
 
//-------------------------------------------------------
function drawAllFrames() {
  for (var i=0; i<nFrames; i++) {
    var angle = map(i, 0, nFrames, 0, TWO_PI); 
    var originY = ((diamArtOuter + diamArtInner)/2)/2;
 
    push();
    rotate(angle); 
    translate(0, 0-originY); 
    scale(0.8, 0.8); // feel free to ditch this 
 
    var whichFrame = i; 
    if (bAnimate) {
      whichFrame = (i+myFrameCount)%nFrames;
    }
    drawArtFrame (whichFrame); 
    // drawArtFrameAlternate (whichFrame); 
 
    pop();
  }
  myFrameCount++;
}
 
 
//-------------------------------------------------------
function drawArtFrame ( whichFrame ) { 
 
  //ellipses
  fill(random(0, 255), random(150,200), random(200,230));
  stroke(255);
  strokeWeight(2);
  for (var i = 0; i < nFrames; i++)
  {
    var t = map(whichFrame, 1, nFrames, 1, i*.38);
  	var diam = map(cos(t*TWO_PI*.22), -1, 1, -i*8, i*8);
  	ellipse(0,i*7-10,diam*.7,diam*0.4);
  }
 
  //lines
  p1 = -45;
  p2 = 70;
  p3 = -0;
  p4 = 54;
  stroke(100);
  strokeWeight(1.2);
  line2 = map(whichFrame, -1, 1, -50, 50);
  for (var i = 0; i < nFrames; i++) {
    line(p1+8*whichFrame,p2,p3,p4);
  }
 
  //triangles
  var p1x = 50;
  var p1y = -25;
  var p2x = 60;
  var p2y = -60;
  var p3x = -40;
  var p3y = -10;
  strokeWeight(2);
  stroke(255);
  for (var i = 0; i < nFrames; i++) {
    fill(25*whichFrame);
    triangle(p1x/(whichFrame*-1)-10, p1y-40, p2x/(whichFrame**2)+20, p2y+20, p3x+whichFrame*10, p3y);
    fill(30*whichFrame);
    triangle(p1x/(whichFrame*2)-3, p1y-30, p2x/(whichFrame)+20, p2y+20, p3x+whichFrame*-2+15, p3y);
  }
 
  //circles
  var p1 = -50;
  var p2 = 0;
  noFill();
  stroke(50);
  strokeWeight(1);
  for (var i = 0; i < nFrames-4; i+=2) {
    stroke(2**whichFrame);
    ellipse(p1-whichFrame*5, p2+20, 10, 10);
    p1 = 0;
    p2 = 0;
  }
}

casher-Reading02

1A: One family of things I like that exhibits effective complexity is snowflakes, which lie almost in the middle of total order and total randomness. Snowflakes as a whole are technically just small pieces of ice, which means at a molecular level they are completely ordered, exhibiting crystal lattice-type structures.  The unique look of each snowflake, however, is completely influenced by the flow of heat in the air at that moment, which is ultimately unpredictable; heat itself is random at a molecular level, so it is impossible to know beforehand the rate at which the temperature will microscopically change. Therefore, the outcome of each snowflake is random.

1B: In response to The Problem of Creativity:

I feel like creativity applies the most to me as an artist, but it is hard for me to agree with one "side" or the other because I don't really see sides. I don't think creativity should be considered a problem in the first place -- there is no way to prove that any certain expression of creativity is wrong. Something is creative if it can create. And technically, all generative art is obviously creative at some point -- a human had to create the ideas in their mind before it was computed. I guess it's just a matter of whether one considers using a computer to execute the ideas to be progressive or inauthentic.