Final Draft Progress 2 – Developing Concept

In the time from my previous draft, I actually made two more draft programs and solidified my concept. Essentially, I am taking inspiration from Nam-June Paik’s piece TV Garden. Essentially, using the algorithms from cellular automata and the game of life, the program will develop a garden filled with several different types of flowers. The user will be able to tweak some of the parameters for the game of life to change how the flowers will grow and die on the tile. I also plan to add some user interaction by changing the Hydra visuals, but these will be somewhat limited due to how Hydra visuals are made. The second sketch focused on using the webcam aspect from Hydra and creating visuals that are intended to look like an old RGB TV overlayed on the camera. There is a slider there to modify the glitchiness of the webcam visual. The third draft focuses on developing the concept, creating 3D flowers and a basic grid for the cellular automata aspect. Here are the two sketches:

The flowers are a complex shape created using beginShape() that plots each vertex via a sine and cosine graph mapped to polar coordinates. Each vertex is made four at a time, to create a rectangle. This is repeated throughout the algorithm until the full flower is created. I also had to map these coordinates to a UV map to allow the overlaying of textures onto the flower, which are Hydra visuals. There are also two other types of flowers that are created with essentially the same algorithm, although a little simpler since they do not have faces created, only the vertices. These vertex points then have either a 2D repeating letter or symbol laid onto it or a simple block, creating flowers that are made out of text and blocks. These serve to add more variety to the garden, and also lessen the reliance on the Hydra visual flowers, which are extremely resource-intensive for the program and slows it down significantly. The code for the Hydra flowers can be seen here:

class Flower {
  constructor(x, y, z) {
    this.origin = createVector(x, y, z+15);
    this.v = []; //holds all the vertices
    this.rows = 15; //this is essentially the "resolution" of the flower, its polygon count
    this.cols = 30;
    this.minX = 1000000;
    this.maxX = -1000000;
    this.minY = 1000000;
    this.maxY = -1000000;
    this.choice = random(1) //used to choose one of the hydra canvases randomly
  }
  generate() {
    for (let theta = 0; theta < this.rows; theta++) { //create the coordinates for each vertex
      this.v.push([]);
      for (let phi = 0; phi < this.cols; phi++) { //r essentially maps x and y to polar coordinates
        let r =
          ((60 * pow(abs(sin(((5 / 2) * phi * 360) / this.cols)), 1) + 200) *
            theta) /
          this.rows;
        let x = r * cos((phi * 360) / this.cols);
        let y = r * sin((phi * 360) / this.cols);
        let z =
          this.vShape(180, r / 100, 0.8, 0.2, 1.5) -
          200 +
          this.bumpiness(2.5, r / 100, 12, (phi * 360) / this.cols);

        let pos = createVector(x, y, z);
        this.v[theta].push(pos);

        this.minX = min(this.minX, x); //this will be used to find the min-max range for the sin and cos waves, which will be needed to map the vertices to a UV map
        this.maxX = max(this.maxX, x);
        this.minY = min(this.minY, y);
        this.maxY = max(this.maxY, y);
      }
    }
  }
  show(pg,pg2) {
    push();
    if(this.choice <= 0.5) {
      texture(pg)
    } else {
      texture(pg2)
    }
    translate(this.origin);
    scale(0.1)
    for (let theta = 0; theta < this.v.length; theta++) { //grabs a vertex and three adjacent ones, which will combine to create a rectangle face
      for (let phi = 0; phi < this.v[theta].length; phi++) {
        if (theta < this.v.length - 1 && phi < this.v[theta].length - 1) {
          beginShape();
          vertex(
            this.v[theta][phi].x,
            this.v[theta][phi].y,
            this.v[theta][phi].z,
            map(this.v[theta][phi].x, this.minX, this.maxX, 0, 1), //uv mapping for texture
            map(this.v[theta][phi].y, this.minY, this.maxY, 0, 1)
          );
          vertex(
            this.v[theta + 1][phi].x,
            this.v[theta + 1][phi].y,
            this.v[theta + 1][phi].z,
            map(this.v[theta + 1][phi].x, this.minX, this.maxX, 0, 1),
            map(this.v[theta + 1][phi].y, this.minY, this.maxY, 0, 1)
          );
          vertex(
            this.v[theta + 1][phi + 1].x,
            this.v[theta + 1][phi + 1].y,
            this.v[theta + 1][phi + 1].z,
            map(this.v[theta + 1][phi + 1].x, this.minX, this.maxX, 0, 1),
            map(this.v[theta + 1][phi + 1].y, this.minY, this.maxY, 0, 1)
          );
          vertex(
            this.v[theta][phi + 1].x,
            this.v[theta][phi + 1].y,
            this.v[theta][phi + 1].z,
            map(this.v[theta][phi + 1].x, this.minX, this.maxX, 0, 1),
            map(this.v[theta][phi + 1].y, this.minY, this.maxY, 0, 1)
          );
          endShape(CLOSE);
        } else if (
          theta < this.v.length - 1 &&
          phi == this.v[theta].length - 1
        ) {
          beginShape(); //the first and last values are disconnected, because an array overflow would happen, so we have to manually create a second shape that closes the gap
          vertex(
            this.v[theta][phi].x,
            this.v[theta][phi].y,
            this.v[theta][phi].z,
            map(this.v[theta][phi].x, this.minX, this.maxX, 0, 1),
            map(this.v[theta][phi].y, this.minY, this.maxY, 0, 1)
          );
          vertex(
            this.v[theta][0].x,
            this.v[theta][0].y,
            this.v[theta][0].z,
            map(this.v[theta][0].x, this.minX, this.maxX, 0, 1),
            map(this.v[theta][0].y, this.minY, this.maxY, 0, 1)
          );
          vertex(
            this.v[theta + 1][0].x,
            this.v[theta + 1][0].y,
            this.v[theta + 1][0].z,
            map(this.v[theta + 1][0].x, this.minX, this.maxX, 0, 1),
            map(this.v[theta + 1][0].y, this.minY, this.maxY, 0, 1)
          );
          vertex(
            this.v[theta + 1][phi].x,
            this.v[theta + 1][phi].y,
            this.v[theta + 1][phi].z,
            map(this.v[theta + 1][phi].x, this.minX, this.maxX, 0, 1),
            map(this.v[theta + 1][phi].y, this.minY, this.maxY, 0, 1)
          );
          endShape(CLOSE);
        }
      }
    }
    pop();
  }

  vShape(A, r, a, b) { //creates the downward curve on the z-axis towards the center
    return A * pow(Math.E, -b * pow(abs(r), 1.5)) * pow(abs(r), a);
  }

  bumpiness(A, r, f, angle) { //creates "bumps" on the flower petals, so they are not completely flat
    return 1 + A * pow(r, 2) * sin(f * angle);
  }
}

It is a very long algorithm that has to be called each draw() frame, so it ends up slowing the program a lot. This is more apparent the more of these flowers there are. I greatly lowered the polygon count of these flowers, but it still has framerate problems, albeit much less than before. Ideally, these would be lowered even more, but too much detail is lost if they are lowered more, and the shape will start not resembling a flower.

The game of life aspect I used is very similar to our class example, just modified to show the flowers on top of the cells that are alive. Because it would overwhelm the program, the next generation of cells has to be done manually, with the press of a button by the user. Because of the resource intensiveness of the flowers, the grid is very small, only 5×5, which creates uninteresting patterns oftentimes.

My next steps will be to try to see if I can optimize the flowers even more, to reclaim more framerate for the program, which will hopefully allow me to create a larger grid to use. I am going to try to experiment with p5.framebuffers instead of p5.graphics, which are supposed to have better performance when working with WEBGL. After that, I will add the user interaction, which will be the modifying of the game of life rules, and finally brush up on visuals. If I have the time, I want to also try and implement more Hydra visuals that the Hydra instances can cycle through, so there is more variety than the current two that are there. I am not quite sure how to implement this yet, so I will have to experiment somewhat. I don’t want to create too many hydra canvases running at once, which would slow the program even more, so I might instead implement some sort of state machine that will cycle through different visuals. I also wanted to add some grass or other greenery so the flat plane is not as visible, but I think I won’t be able to add this due to performance. The camera is also offset right now, and I need to move it so it is properly looking at the garden. I’ve been having trouble doing this as of now, but hopefully, it won’t be too difficult to find a fix. One last thing I am considering is adding TVs of some sort, to further show how this program’s influence from TV Garden. This is a low priority for now though.

Final Draft – Experimenting with Hydra in P5.js

My final project uses a library I used in a previous class: Live Coding. The library is called Hydra, which is used to create visuals within a webpage. While it is intended to be used with live coding, it can also simply be used for its visuals. Normally, variations of visuals are created through the use of musical beats and sounds, but I plan on having the user interact to change these visuals instead.

I have not completely decided what my concept exactly is, nor what I want my program to do, but I know I wanted to use hydra in some way, because it can create these trippy and colorful visuals. An idea I had was to make the visuals be split between TV screens, similar to a Nam June Paik piece. However, at this point, I need to put some more time into finalizing the concept of my program. I had to do so much troubleshooting to re-familiarize myself with hydra and get it to work properly in P5.js, that I did not have time to work on my concept.

Currently, the program is still bare bones. There is a background canvas with a hydra visual on it, and a second one that is wrapped around a rotating torus. There are some lines on the screen, which I intend to be a grid that will make it appear the visuals are being shown through a grid of TVs. There is one bit of interactivity that I experimented with, a slider that allows you to shift the colors of the background visual, which was there to test the interaction of P5 and hydra. My one problem that I know i will run into with the visuals is adding or removing aspects of them, since I don’t think they can be coded in a modular way, since they are essentially a long string of methods together. Here is what the two visuals look like in code:

h1.osc(6, 0.1, 0.4).modulatePixelate(h1.noise(25,0.5),100).out(h1.o0);
h1.render(h1.o0);

h2.src(h2.o2)
     .modulate(h2.voronoi(10), 0.005)
     .blend(h2.osc(4, 0.1, 3).kaleid(30), 0.01)
     .out(h2.o2);
   h2.render(h2.o2);

 

Much of the issues I ran into had to do with me being unsure how to use hydra properly in p5. I had to do some coding within the index.html to make it work. To make the visuals more interesting, I tried adding a second hydra canvas to allow for more visual differences. This took a very long time to troubleshoot, because the two instances of hydra together did not like each other. I had to work with a lot of new things, like p5.graphics and the js canvas to make them work together. The next step for me will be to try to finalize my concept so I have a clear goal to work towards. I also want to try to utilize more aspects of things we learned in class, which at this point is not really implemented, other than the use of an external library. I think deciding an aspect to focus on will help me to finalize my concept. After this, I can finalize the program and add more user interaction, ideally with the visuals. I am also worried about the program being slow, since I am working in 3D. While it is fine for now, I worry that complexity will hurt this program.

Week 11 – Experimenting With 3D Cellular Automata

The project I have this week is relatively simple, it is using the 3D Cellular Automata algorithm in 3D. It was inspired by the 3D model we saw in class made in babylonjs. Here is the sketch:

There is a bit of interaction, where you can press to advance to the next stage of the automata, yielding a new pattern. You can also enable manual camera control if you want to take a closer look at the shape. The color changes over time to make it a bit more visually appealing to look at.

In the code, there are values a, b, c, and d. You can modify these in the code to change how the cells develop. Feel free to experiment and see what looks interesting.

The biggest problem I ran into had to do with computer limitations. The cell is relatively small, 20×20 cells, because adding anymore would slow the program down too much. Even with the current resolution I have the program can get slow when there are a large number of cells. I really wish I had a stronger computer to try to render a larger cell array, I think it could be really interesting.

Week 10 – Pong Game

For this week’s project I decided to make a classic game: Pong. Pong is a game where you and an AI (or another player) have to knock a ball back and forth until the ball gets past someone. Seeing as we were working with collision and physics for our projects, I thought creating a game would be fun. I thought that paying homage to the very first game ever made would be a cool idea. The sketch is here:

Currently, you can only do PvE and fight a bot in the game. It will follow the ball’s position and try to hit it back towards you. The player’s board will follow the y-axis of your mouse’s position. With each hit, the ball increases in speed, making it harder to hit the longer the round goes. Once it reaches past one of the players, the score will be increased by one for the winning player and the ball will be reset. Currently, when the ball is reset, it will always start going towards the player and not the AI.

Using the Matter.js library for the first time was intimidating. It’s quite an expansive library that is capable of doing a lot. I also found the documentation for the library to not be the best, as it has very limited writing explaining functions (especially how to use them properly) and there are essentially no examples to work with. The examples on GitHub are made to be used with actual JS, and not p5, which meant that the examples can’t be looked at and you have to infer what the programs are trying to do. After some testing, I was more or less able to understand the parts of the library I needed to use and made the program.

The biggest issue I ran into while creating this program had to do with the collision. Firstly, I was very confused on how to properly implement collision detection, because of the aforementioned lack of documentation. There are multiple ways to have collision detection, and I wasn’t sure which was best. I ended up opting for an event listener that also had an embedded collision detection if statement to ensure that it would properly detect the ball collision. Here is the code for this:

Events.on(engine, "collisionStart", collisionEvent);

...

function collisionEvent(event) {
  if (
    Collision.collides(player.body, ball.body) != null ||
    Collision.collides(
      ai.body,
      ball.body || Collision.collides(ball.body, ai.body) != null
    )
  ) {
    Body.setVelocity(ball.body, {
      x: -ball.body.velocity.x * 1.15,
      y: ball.body.velocity.y,
    });
    Body.setPosition(ai.body, { x: width - 20, y: ai.body.position.y });
  }
}

While this is a small line of code, this was arguably the part that took longest to figure out, so I am particularly proud of this working.

I also had an issue where the ball would not collide with the player’s board, and would simply go right through it. After sifting through the documentation many times, I realized that the way I was changing the position of the board in the physics engine was not actually changing it, and I fixed it to use the proper setPosition() method. There are some other issues with the program that I wasn’t able to properly fix because I didn’t have enough time. First, when the ball gets faster, it starts to push the AI board backwards and can knock it off screen when it gets fast enough. I tried to make a bandaid fix to reset its x-position when there was collision detected, but the collision detection for the AI is very inconsistent and only works sometimes. There’s also a weird issue where there seems to be an invisible box the ball can collide with that is in the middle of the edges of the left and right of the screen. I’m not really sure why this is happening, perhaps an issue regarding how the positions are moved on the player. The final issue I’ve seen is that occasionally the ball will gain way more velocity than intended and shoots off the screen really quickly. Occasionally it will also do the opposite and lose all its velocity which renders the game unplayable somewhat. I think this is because the collision is detecting multiple times sometimes, but I don’t know how I could fix this.

Other than fixing these problems, I think there are a few changes I could make to improve the program. First, I want to add options to the game, such as two player support, keyboard controls and AI difficulties. I also would want to improve the AI, making them accelerate towards the ball when it is very close, which is more similar to actual AI in Pong. Due to time constraints, I couldn’t figure this out, but it is definitely something I would want to improve on. The last thing I could consider is a score threshold or some other way to reset the game, which currently will go on forever until the program is restarted. These are the many things that I would like to improve on.

References:

https://www.ponggame.org/

MUJO Reflection

I found MUJO to be a really interesting piece, and one that is very applicable to what we learn in this class specifically. I have taken classes with Aaron before, notably Live Coding, so I know how creative his pieces can be. I really liked the concept of projecting onto the dunes, and using light and the lack thereof to create contrasts in the medium. I really enjoy pieces that cross digital and physical mediums such as this, and I think it made me appreciate the piece more. Also, as someone who cares a lot about sound, I really liked the experimental sounds that are used. The panting and other human noises combined with the dreary background sounds really emotionally impact the piece. I enjoyed Aaron breaking down what he did to make the dunes and the different ways he modified them, and I hope that I can try to use these ideas in a future work. In particular, I really liked the one that used the liquid equation (the name escapes me) and I want to experiment with that in a future work. Overall, I really enjoyed listening to how MUJO came to be, the concept, and the process that happened to make the piece a reality.

Week 8 – Prismatic Light

For my assignment, I created a ball that looks like it’s refracting light. There is a leader that is a large white ball that moves along flow lines. The rest of the vehicles also move along the flow but have randomized colors and draw a line from their position to the leader’s position. There is also an afterimage on everything to make it a bit more lively. Here is the sketch:

The code is taken from the flow line base we looked at in class, which I then modified slightly. I gave it a higher resolution of 10, to make everything move a bit more erratically. I also slightly modified the edges function for the vehicles, so that the vehicles won’t end up clumping into one of two flows. Instead, when reaching the end, they start at a random y position on the right of the screen, so the vehicles are more spread out.

The line effect I created was a pure accident. I was doing a lot of experimenting with code when I accidentally made an error with an algorithm. Originally, the idea I had was to have a really high-resolution flow field because it created a really cool effect, and then have lines that would run through the flow lines, and perhaps pulse a bit before disappearing. The lines I was trying to make were instead appearing around (0,0), but it made a really interesting-looking effect that made me decide to pivot my idea. The other issue with my original idea was that having the flow resolution be 1 made the program extremely slow, so I don’t think it would have worked properly and froze a lot.

Probably the only code of note is the parts that create the actual visuals, since in the back most of it is not changed:

  show() {

    if (this.isLeader) { //leader is a white ball with a "glow"
      noStroke();
      fill(200, 50);
      circle(this.position.x, this.position.y, 50);
      fill(255);
      circle(this.position.x, this.position.y, 30);
    } else { //rest follow flow lines, but also draw a line from its position to leader
      stroke(this.red, this.blue, this.green, 150);
      strokeWeight(5);
      line(
        this.position.x,
        this.position.y,
        leader.position.x,
        leader.position.y
      );
    }
  }
}

I think there could be more to improve visually, but I couldn’t figure out what else to add. Perhaps adding a simple particle system on the leader to make it more visually interesting could be interesting. I also had some trouble with the color blending. I can’t tell if they are blending or not, and I experimented with different blend modes but they all looked much worse. I also tried to put a glow on the leader but it doesn’t look too realistic, I’d have to research on how to make it look better. It probably would be a good idea to add some interaction too, to make it less static.

Midterm – Making Generative Pollack Paintings

Jackson Pollack was a painter during the abstract expressionist movement known for his paint drip paintings. He would splash paint onto a surface using the force of his entire body and painted from every angle. Due to him using his body to propel the paint, this combined with the use of colors create strongly emotional paintings where every drop of paint has deep emotion and meaning behind it.

As someone who enjoys abstract art, Pollack was one of the first abstract artists I was exposed to. His paintings hold special meaning to me due to this. When thinking of a generative art piece to create, I knew I wanted to do something more abstract, and I felt that using layers of randomly generated lines to emulate a Pollack painting would be a really interesting idea. My code randomly generates layers of lines and blobs that are place on top of another. The colors are semi random, some are lighter/darker shades of a randomly chosen color, while others are simply black or white. Shown below are some of the pictures that were generated, along with a pen-plotted image time-lapse video.

Video: https://drive.google.com/file/d/1zT2N_VmV7RY4kdVUCM4nddNGrpFSZkek/view?usp=sharing

There was much trouble using the pen plotter. First, since the lines are individual segments, it was really difficult to modify the layers of the SVG file. This is one of the reasons why I changed the line algorithm which will be explained later. Once this was fixed, I was now worried about how long the plotter would take to finish, and the fact that I had to constantly change the color of the pen to emulate the different colors. The colors did not necessarily work as I wanted, as the black would often drown out the other colors, making the colors look less layered. There was also a limitation regarding the thickness of the pens, which meant I could not really show the extremely varying widths of the lines on the plotter. I had made a separate program specifically to make my program work with the plotter, which can be seen here. Finally, I had issues relating to the plotter, which would malfunction at times and jerk downwards, messing up the home position. This meant it occasionally would draw outside the paper, and I would have to pause and reset the positioning often to make the plotter work again. While it is not perfect, it came out nice enough for what I wanted.

Sketch:

The code features an algorithm that will generate lines and blobs layer-by-layer. It first chooses a random color for the first layer. From there, it has a 65% to make the current color slightly lighter or darker. The other 35% chance has a 50% chance to choose a new color, or a 50% chance to choose white or black. The final two layers will always be white then black, respectively. The reason I chose to make the colors sometimes black or white is because I felt like using those colors more made the paintings have a more similar color scheme to Pollack’s. I also found it more aesthetically pleasing to look at, which is also why I did this. The reason for having a bias towards hues was because it also makes the piece more aesthetically pleasing to look at, since having only randomized colors created ugly and less coherent paintings.

The lines of the painting are generated in small segments. Each point will rotate slightly over sin for x and cos for y in a random direction, making the lines sort of snake around the canvas. When they are too far out of bounds, the lines will change course to ensure it remains visible. The newly created point is then connected to the previous point. There is a low chance for the algorithm to also randomly end the line and choose a new random starting place, so that it’s not all just one line. The line will also vary in its thickness from point to point, and new lines will have a more varying thickness. Once the lines of one layer have finished, it will then generate a random amount of paint blobs in the same color. These are made similarly, except that the points will move in a circular way so that it creates an irregularly shaped circle. Once this is finished, the code will start the next layer and repeat this until it finishes. At any time you can press a button labeled “Generate” to clear the canvas and start a new painting.

I am particularly proud of the Drawer object, the one that makes the lines. I based it off of this reference here, and then modified it to make it an object that I could call instead. I also slightly changed the way it draws, because the reference code uses line() instead of curveVertex(). The reason I changed this was because I found that using lines made the program really slow and it made it difficult to generate a lot of layers, which I wanted. When I changed to curveVertex(), the program worked much faster and was actually able to complete the painting relatively quickly. The code for the drawer object can be seen here:

class Drawer {
  //drawer class, this draws all the lines
  constructor() {
    this.seg = 0;
    this.swScale = 0; //line width multiplier
    this.sw = width * random(0.0002, 0.005); //choose random line width
    this.angVary = PI * 0.02; //how much the line varies its path
    this.lineLength = height * 0.001; //length of each segment
    this.x = 0;
    this.y = 0;
    this.setXY(); //choose random starting position
  }
  setXY() {
    //choose random starting point, angle, and line width
    this.x = round(random(width * 0.1, width - width * 0.1));
    this.y = round(random(height * 0.1, height - height * 0.1));
    this.ang = random(PI * 2);
    if (random(2) < 1) {
      //randomly vary the angle a bit more
      this.ang = PI * 0.25;
    } else {
      this.ang = PI * 0.75;
    }
    this.sw = width * random(0.0002, 0.005); //set width
  }
  makeLines(seg, swScale) {
    //line drawer. creates a small segment that will connect and form a line. once in a while, end the line and start randomly in a new place
    this.seg = seg;
    this.swScale = swScale;
    beginShape();
    for (let i = 0; i < this.seg; i++) {
      this.ang = this.ang + random(-this.angVary, this.angVary); //randomly choose a direction for the line to go
      this.x = this.lineLength * sin(this.ang) + this.x; //add angle to xy coords
      this.y = this.lineLength * cos(this.ang) + this.y;
      if (
        width * 0.1 * sin(this.ang) + this.x > width + width * 0.05 ||
        width * 0.1 * sin(this.ang) + this.x < 0 - width * 0.05 ||
        height * 0.1 * cos(this.ang) + this.y > height + height * 0.05 ||
        height * 0.1 * cos(this.ang) + this.y < 0 - height * 0.05
      ) {
        //if the next segment will go too far out of bounds, have it turn so it doesnt do that
        this.ang += 0.2;
      }
      this.sw += width * random(-0.00005, 0.00005); //make the line width get slightly smaller/larger for each segment
      this.sw = constrain(this.sw, width * 0.0001, width * 0.009); //make sure its not too big or small
      strokeWeight(this.sw * this.swScale); //apply line width and scaling
      curveVertex(this.x, this.y); //connect the new point to the previous one
      if (random(1000) < 1) {
        //once in a while, stop the line and start a new one
        this.setXY();
        endShape();
        beginShape();
      }
    }
    endShape();
    this.reset();
  }
  reset() {
    //reset the position
    this.setXY();
  }
}

Trying to understand this code and optimize it was definitely the most difficult part. It took much trial and error and tinkering with numbers to make the program work in a way that I liked it. This and making the colors look aesthetically pleasing were the two hardest parts for me. It took a lot of trial and error with the coloring to make sure it looked nice.

Some parts I would try to improve is make the code show itself drawing out the lines. I had this originally, but the program would slow down too much and would never be able to finish a painting because of the speed. Also, when using curveVertex(), the entire shape is made at once meaning it’s impossible to show this anyway. I would have to go back to using line(), which is really slow and inefficient. I also would want to add more user interaction, adding ways to modify parts of the paintings like how many layers, color schemes, or how many lines or blobs are drawn. I was having a lot of trouble adding these, so I decided against adding them, so all that’s left is the generate button. One last problem I have is that the lines seem to draw more towards the right, meaning sometimes the left side will have more empty space. I wasn’t sure at all how to fix this issue. These would be the things I would try to add for future iterations of the program.

Midterm Progress

My midterm assignment tries to emulate the work of Jackson Pollack, an artist whose work I really enjoy. I really enjoy abstract art, and I thought the idea of trying to emulate the strokes he makes through code could make for a really interesting midterm project. I like the idea of bridging the physical into the digital, which is another reason why I wanted to try this.

Currently, my program creates a series of lines that will travel randomly and vary in its stroke size. It creates the lines in segments, and will occasionally break the line and start in a new place. I have 3 of these objects, all in different colors, that will draw the segments. You can click on the screen to generate a new set of lines, replacing the old ones. The code for the line drawer can be seen here:

class Drawer {
  constructor(seg, swScale) {
    this.seg = seg;
    this.swScale = swScale;
    this.sw = width * random(0.0002, 0.005);
    this.frame = width * 0.05;
    this.angVary = PI * 0.02;
    this.edgeBuff = height * 0.08;
    this.lineLength = height * 0.001;
    this.x = round(random(width));
    this.y = round(random(height));
    this.prevX = this.x;
    this.prevY = this.y;
    this.ang = random(PI * 2);
    if (random(2) < 1) {
      this.ang = PI * 0.25;
    } else {
      this.ang = PI * 0.75;
    }
  }
  makeLines() {
    for (let i = 0; i < this.seg; i++) {
      this.ang = this.ang + random(-this.angVary, this.angVary);
      this.x = this.lineLength * sin(this.ang) + this.x;
      this.y = this.lineLength * cos(this.ang) + this.y;
      if (
        this.x > width ||
        this.x < 0 ||
        this.y > height ||
        this.y < 0
      ) {
        this.ang += 0.2;
      }
      this.sw += width * random(-0.00003, 0.00003);
      this.sw = constrain(this.sw, width * 0.0001, width * 0.009);
      strokeWeight(this.sw * this.swScale);
      line(this.prevX, this.prevY, this.x, this.y);
      this.prevX = this.x;
      this.prevY = this.y;
      if (random(1000) < 1) {
        this.sw = width * random(0.0002, 0.005);
        this.x = round(random(width));
        this.y = round(random(height));
        this.prevX = this.x;
        this.prevY = this.y;
        this.ang = random(PI * 2);
        if (random(2) < 1) {
          this.ang = PI * 0.25;
        } else {
          this.ang = PI * 0.75;
        }
      }
    }
  }
}

Creating this object was the most difficult part so far. I was trying to figure out ways to make the lines move randomly but not too erratically. After much trial and error, I managed to make some numbers that looked good to me.

My next steps are to add the paint blobs, which I think could be the hardest part, because I want them to be misshapen. After that, I can work more on the interactivity by adding such things as ways to modify the amount of lines made. I also want to add more layers, because right now there is a lot of empty space and I want to minimize that at bit more. Adding more layers will also make the pieces look more interesting and make them look more like a Pollack piece, which has countless layers of paint on them. The last part I intend to do is work on is adding more colors, I am perhaps thinking about using random colors, but I am unsure how this will end up looking.

Letter Jellyfish

The project I made this week was a pure accident. While trying to experiment with one concept, I made a mistake in my code that created something so interesting I decided to keep it. I named this piece “Letter Jellyfish” because the movement of the sine waves reminded me of a jellyfish swimming. The code is on GitHub here.

My original concept, while not fully fleshed out, was intended to be a program where I experimented with creating moving 3D text over a sine wave. From there I planned to experiment with the core to make the program look more interesting. To do this, I would layer multiple sine waves made up of letters to create a “3D” effect of the text. Originally, I wanted the sine wave to iterate over the English alphabet, which would be mapped to its x-coordinate. I decided to make the wave choose random letters instead because it made the piece feel more animated and chaotic. Because the coordinate system is different in WEBGL than in 2D mode, I had trouble seeing the sine wave. I was using the camera() method to try to fix this. After this, I wanted to try to rotate the letters so they spin around while oscillating. While doing this, I accidentally rotated the entire sine waves, creating something similar to what my final piece looks like. I liked how this looked so much, that I pivoted my piece to incorporate these multiple sine waves in a 3D space instead. I tried keeping the aspect of the “3D” text as well, but the program ended up being too laggy to keep it this way. After this, to add some more visual flair to the piece, I made the waves shift their colors over time, based on the current frameCount. The code for these sine waves can be seen here:

for (let i = 0; i < total; i++) {
    let y = map(sin(angles[i]), -1, 1, -height, height / 2);
    let x = map(i, 0, total, -width * 2, width / 2, true);
    let letter;
    letter = map(x, -width / 2, width / 2, 0, alphabet.length - 1, true);
    push();
    for (let i = 0; i < 25; i++) {
      rotateY(45);
      translate(0, 0, 0.5);
      fill((i * 2 + frameCount) % 360, 100, 100);
      text(alphabet[floor(random(alphabet.length))], x, y);
    }
    pop();
    let increment = TWO_PI / 60;
    angles[i] += increment;
  }

 

I was doing a lot of experimenting using the camera() function, something I’d never used before. I was not able to make the camera move as I wanted it to, but I made a nice rudimentary one that would rotate around the piece. Ideally, I wanted the camera to occasionally go inside the center of the piece so that the camera would be surrounded by the letters close-up. This would probably be the main thing I want to improve on for this piece. I would also like to add more waves and make the pseudo-3D text, since it looked even more visually pleasing, but the program becomes too laggy to do this.

Moths to a Light Source

For this week’s assignment, the first thing I thought of when I saw “attractors,” I thought of moths and other insects flying around a light. Right outside my home’s front door is a light that always has bugs flying around it. Whenever I leave or return home, I see them while unlocking my front door. So, I decided I would try to emulate this with a program. It can be seen here:

Code on GitHub here.

The image in the background is the lamp in front of my house. Since I can’t easily get home from Abu Dhabi, I asked my brother to take a picture of it at night, while the light was on. The code is simple, it has a point that is an attractor and then a Moth class that will move towards and away from the light, simulating insects hovering around a light. I also added some random positioning when calculating the movement of the moths, to emulate the erratic way insects sometimes fly. The colors of the moths get lighter or darker depending on the distance from the light, to emulate actual light. I also tried to add wings to the moth that would constantly move. It’s not perfect, but it is at least somewhat animated. The moths also rotate themselves so they are always facing the light. This all can be seen here:

display(light) {
    noStroke();
    let distance = Math.abs(Math.sqrt(Math.pow(this.pos.x-light.pos.x, 2)+Math.pow(this.pos.y-light.pos.y, 2)))
    let theta = this.vel.heading() + PI / 2;
    map(distance, 0, height, 50, 200)
    fill(Math.abs(255-distance));
    push()
    translate(this.pos.x, this.pos.y)
    rotate(theta);
    ellipse(0, 0, this.size*0.6, this.size);
    if (this.counter%2 == 0) {
      rotate(290)
    } else {
      rotate(310)
    }
    fill(Math.abs(200-distance));
    ellipse(4, -2, this.size*0.8, this.size*0.5);
    ellipse(-4, -2, this.size*0.8, this.size*0.5);
    pop()
    this.counter++
  }

If I were to improve this, I think I would try to make the wings more accurate for the moths. Also, I would want to try making the movement better, perhaps adding variable speeds for the insects or allowing them to stop and land on the light, before taking off into flight again.