Reading Response – Week #3 Redha Al Hammad

The main point which stood out to me from this reading was the author’s definition of interactivity as clarified by the analogy of a conversation. I found the comparison of “input, process, output” to “listen, think, speak” to be effective in conveying interactivity today (especially since the piece was written two decades ago). On this same note, I found the mention of an interactive process requiring “two actors” to be interesting. As someone who grew up with digital technology, I subconsciously tend to either view it as a tool or an extension of myself and my actions – not as a separate active party that has the agency to “listen, think and speak” in conversation with me. I feel that the only time I consider technology’s agency is when it does not cooperate with my goal as a user as, for example, oftentimes when a website does not load or is difficult to use we place the blame on it and not the interaction itself.

Another point I found interesting was the misuse of interaction in varying different contexts. More specifically, the distinction between integration and reaction stood out to me as the author strongly claims that they have nothing to do with one another. However, I do feel that there is some element of reaction within interaction (on the human side at the very least). In the aforementioned example, a poorly constructed website will surely garner a specific reaction in the user and, in turn, will affect how they interact with it. As such, I feel that in certain cases, the two are interlinked and should not be considered entirely separate processes.

Assignment 3: State of Mind

Concept

The goal of this week’s assignment was to create a unique work of art through imagination and creativity. The original idea was to create a dynamic screensaver with a range of shapes that had different colors and speeds and interacted with the canvas and each other when they collided. However, this concept was disregarded because a more abstract art piece was needed.

So I used the original code as the template, and the project developed into a complex particle-mimicking display of forms. These particles used the idea of flow fields to mimic more organic and natural motions, leaving behind a vibrant trail as they moved. The chaos of these trails of particles is a representation of my “State of Mind” while thinking of ideas for the assignment.

Sketches


Code

The particles’ motion is directed by a grid of vectors called the flow field. Perlin noise is used in its generation to provide a fluid, flowing transition between the grid’s vectors.

for (let i = 0; i < cols; i++) {
    for (let j = 0; j < rows; j++) {
      let index = i + j * cols;
      let angle = noise(i * 0.1, j * 0.1, zoff) * TWO_PI * 4;
      flowField[index] = p5.Vector.fromAngle(angle);
    }
  }

The snippet is in the draw() loop that creates the flow field. It simulates a natural flow by using Perlin noise to generate vectors with smoothly shifting angles.

The shapes follow the flow field vectors, which guide their movement. This interaction is encapsulated in the follow() method of the BaseShape class.

follow(flowField) {
  let x = floor(this.pos.x / resolution);
  let y = floor(this.pos.y / resolution);
  let index = x + y * cols;
  let force = flowField[index];
  this.vel.add(force);
  this.vel.limit(2);
}

The shape’s position (this.pos) is used to determine its current cell in the flow field grid by dividing by the resolution. The index in the flowField array corresponding to the shape’s current cell is calculated using x + y * cols.
The vector (force) at this index is retrieved from the flowField array and added to the shape’s velocity (this.vel), steering it in the direction of the flow. this.vel.limit(2) ensures that the shape’s velocity does not exceed a certain speed, maintaining smooth, natural movement.

The trail effect is created by not fully clearing the canvas on each frame, instead drawing a semi-transparent background over the previous frame. This technique allows shapes to leave a fading trail as they move.

background(0, 0.3);

The purpose of the resetAnimation() method is to reset the animation setup and clean the canvas. To restart the flow field pattern, it first uses clear() to remove any existing shapes from the canvas, resets the shapes array to its initial state, initializeShapes() method to add a new set of randomly placed shapes, and resets the zoff variable for flow field noise.

function resetAnimation() {
  clear();
  // Clear existing shapes
  shapes = []; 
  // Repopulate with new shapes
  initializeShapes(); 
  // Reset the z-offset for flow field noise
  zoff = 0; 
 
}

The resetAnimation() method is called when the frameCount has reached 500 frames. This helps to see how the flow field changes every time it restarts.

Full Code

// array for shapes
let shapes = [];
// declare flow field variable
let flowField;
let resolution = 20;
// 2d grid for flow field
let cols, rows;
// noise increment variable
let zoff = 0;
// make the sketch again after this value
let resetFrameCount = 500;


function setup() {
  createCanvas(800, 600);
  colorMode(HSB, 255);
  blendMode(ADD);
  cols = floor(width / resolution);
  rows = floor(height / resolution);
  flowField = new Array(cols * rows);
  initializeShapes(); 
}

function draw() {
  
  if (frameCount % resetFrameCount === 0) {
    resetAnimation();
  } else {
    background(0, 0.3); 
  }

  // Flow field based on Perlin noise
  for (let i = 0; i < cols; i++) {
    for (let j = 0; j < rows; j++) {
      let index = i + j * cols;
      let angle = noise(i * 0.1, j * 0.1, zoff) * TWO_PI * 4;
      flowField[index] = p5.Vector.fromAngle(angle);
    }
  }
  
  // Increment zoff for the next frame's noise
  zoff += 0.01; 

  // Update and display each shape
  // For each shape in the array, updates its position according to the flow field, moves it, displays its trail, and display it on the canvas.
  shapes.forEach(shape => {
    shape.follow(flowField);
    shape.update();
    shape.displayTrail();
    shape.display();
    shape.particleReset();
    shape.finish();
  });

}

function resetAnimation() {
  clear();
  // Clear existing shapes
  shapes = []; 
  // Repopulate with new shapes
  initializeShapes(); 
  // Reset the z-offset for flow field noise
  zoff = 0; 
 
}

// Initialized 30 number of shapes in random and at random positions
function initializeShapes() {
  for (let i = 0; i < 30; i++) {
    let x = random(width);
    let y = random(height);
    // Randomly choose between Circle, Square, or Triangle
    let type = floor(random(3)); 
    if (type === 0) shapes.push(new CircleShape(x, y));
    else if (type === 1) shapes.push(new SquareShape(x, y));
    else shapes.push(new TriangleShape(x, y));
  }
}

class BaseShape {
  constructor(x, y) {
    this.pos = createVector(x, y);
    this.vel = p5.Vector.random2D();
    this.size = random(10, 20);
    this.rotationSpeed = random(-0.05, 0.05);
    this.rotation = random(TWO_PI);
    this.color = color(random(255), 255, 255, 50);
    this.prevPos = this.pos.copy();
  }

  follow(flowField) {
    let x = floor(this.pos.x / resolution);
    let y = floor(this.pos.y / resolution);
    let index = x + y * cols;
    let force = flowField[index];
    this.vel.add(force);
    // Smoother movement so velocity is limited
    this.vel.limit(2);  
  }

  update() {
    this.pos.add(this.vel);
    this.rotation += this.rotationSpeed;
  }

  display() {
    // Saves the current drawing state
    push();
    // Translates the drawing context to the shape's current position
    translate(this.pos.x, this.pos.y);
    // Rotates the shape's current rotation angle    
    rotate(this.rotation);
    fill(this.color);
    noStroke();
  }

  displayTrail() {
    strokeWeight(1);
    // Creates a semi-transparent color for the trail. It uses the HSB 
    let trailColor = color(hue(this.color), saturation(this.color), brightness(this.color), 20);
    stroke(trailColor);
    // Draws a line from the shape's current position to its previous position
    line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
  }

  finish() {
    this.updatePrev();
    pop();
  }

  updatePrev() {
    this.prevPos.x = this.pos.x;
    this.prevPos.y = this.pos.y;
  }

  particleReset() {
    if (this.pos.x > width) this.pos.x = 0;
    if (this.pos.x < 0) this.pos.x = width;
    if (this.pos.y > height) this.pos.y = 0;
    if (this.pos.y < 0) this.pos.y = height;
    this.updatePrev();
  }
}

class CircleShape extends BaseShape {
  display() {
    super.display();
    ellipse(0, 0, this.size);
    super.finish();
  }
}

class SquareShape extends BaseShape {
  display() {
    super.display();
    square(-this.size / 2, -this.size / 2, this.size);
    super.finish();
  }
}

class TriangleShape extends BaseShape {
  display() {
    super.display();
    triangle(
      -this.size / 2, this.size / 2,
      this.size / 2, this.size / 2,
      0, -this.size / 2
    );
    super.finish();
  }
}

Challenges

I spent a lot of time getting a grasp of noise functions and how to use them to mimic natural movements for my shapes and implement the flow field using Perlin noise. There was considerable time spent adjusting the noise-generating settings to produce a smooth, organic flow that seemed natural.

There was a small challenge to clear the canvas after a certain amount of frames. The logic of the code was fine however the previous shapes were not removed.

Reflections and Improvements

The overall experience was quite helpful. I learned to handle the different functions and classes using object-oriented programming concepts. It made it possible to use a modular. It even helped me to add more features to my code as I was creating my art piece.

I believe that there is one area of development where I could explore various noise offsets and scales to create even more varied flow fields. Playing around with these parameters might result in more complex and eye-catching visual effects.

References

I learned about flow fields through the resources provided to us. I discovered a YouTube channel, “The Coding Train“.

Raya Tabassum: Reading Response 1

Reas navigates through the historical and contemporary landscapes where chance operations have been utilized, underscoring the balance between unpredictability and control, chaos and order.
The concept of employing randomness in art is not new; it traces back to various movements and disciplines, including Dadaism’s use of arbitrary methods to challenge artistic norms and John Cage’s explorations in music that embraced indeterminacy. Reas’ talk prompts one to question: How do these historical instances of chance operations inform and enrich our current understanding of randomness in digital art?
Reas’ emphasis on the symbiosis between order and chaos, particularly in the realm of digital arts, brings to light the nuanced dynamics of control. The artist, through the use of algorithms and computational methods, sets the stage for randomness, yet within predefined constraints. This paradoxical relationship invites reflection on the nature of creativity itself. Is true creativity found in the meticulous planning and execution of an idea, or does it emerge from the serendipitous encounters with the unexpected? The talk challenges one to consider the role of the artist in the digital age: Are they the orchestrators of chaos, the curators of randomness, or simply collaborators with the computational processes they employ?
In conclusion, Casey Reas’ talk on chance operations serves as a profound catalyst for reflection on the intersections between art, technology, and randomness. It compels one to reconsider not just the methodologies of artistic creation but the very essence of creativity and its manifestations in the digital age.

Assignment 2: Ellipses

Loops… I wasn’t really sure how I could use a for, or while loop when the draw() function is itself a loop anyways. My previous experience with programming (which isn’t much) has taught me using for, or while loops in sorting algorithms but I didn’t know where to use loops when drawing an image in p5js. In any case, I looked through the magazines to see if there was anything I felt I could do.

 

When I saw the image above, I immediately began to think about how I could create it in p5js. I knew I could use ellipses to create what, in the image, looks rings around a tube. I also knew  that by making the background black, making the outline of the ellipses white, and removing the fill of the ellipses it could look almost exactly like the image. The only problem was that I didn’t really know how to make the shape without hardcoding all the values. So, instead of hardcoding all the x-coordinate, y-coordinate, width, and height values of all the ellipses I realized I could use a for loop.

When first testing out the idea I made a class and an array and made variables of that class which I put in the array and was just testing to see what worked and what didn’t since I wasn’t familiar with the syntax. In hindsight, I didn’t need to use a class or an array but it was good practice nonetheless. In any case, I ended up with the code below:

for (let i = 0; i < ellipseArray.length; i++) {
    
    
    let something = map(i, 0, ellipseArray.length, -1, 1);

    w = map(tan(frameCount * something * 0.025), -1, 1, 0, 100);

    y = map(i, 0, ellipseArray.length, 10, height);

    ellipseArray[i].make(width / 2 - 100, y, w, 20);

    ellipseArray[i].make(width / 2 + 100, y, w, 20);
    
    
  }

The method of the class which drew the ellipse was called make. Looking at it again I could have just had ellipse() in the place of ellipseArray[i].make … it would be easier to look at but I’ll just call it good practice. Despite that, I am happy with the code I wrote above. I was especially happy with my use of the map() function. At first I wasn’t sure how to use it, I also felt that the p5js references didn’t explain it very well but with a bit of trial and error it became obvious. I was also happy with how I used the frameCount variable to make the image move. I think it might be slightly obvious that I didn’t really know what I was doing throughout all of this as I named one of my variables something, I’m still not sure what to call it but the idea was that depending on where the ellipse was in the array it would have a different value from the tan() function.

At the end, I made the background slightly transparent so that it would leave a shadow of the previous ellipses, which I think makes a similar effect as the slightly fuzzy lines that can be seen in the image I took inspiration from.

 

Reflection

I mentioned this a few times before and it is that I should just use the ellipse() function alone rather than use a class and array to make the code more readable, and maybe even more efficient. I also think I could have added more comments to explain what each line or section did, I left most of it uncommented because I myself wasn’t sure what I was doing and was making changes fairly quickly. I feel with more practice and if I lay out my thought process with comments I can be more efficient when writing my code.

Future Ideas

For the future if I ever choose to come back to this style I could have a design where it uses a trigonometric function as I used it for this assignment but the ellipses are made around the cursor then it would look cool as you move the cursor. Also, I only varied the width of the ellipse, I could also vary both the height and width in the future.

Assignment 2, Loops

When I think of loops the first thing that comes to mind is the DVD screensaver that I used to see as a kid, a never-ending loop that managed to grab my attention until I saw the corner of the logo line up with the edge of a screen. If you still don’t know what I’m referring to, have a look at this iconic scene from the office:

I Tried to recreate the same loop using if statements, randomized the color change whenever the logo hit an edge, and redirected itself in the opposite direction by going into negatives.

I am particularly proud of this part of the code:

if (pos.x >= width – imgPos.width || pos.x < 0) {
speed.x *= -1;
getColorforImage();
}

I was intially overwhelmed by this task, however using the if statement really made it simpler, by making the image speed into the negatives to redirect and change color simultaneosly (repeated the same code for Y variable) I managed to recreate the OG dvd screensaver.

However, I did not use the for or while commands to create this loop so I started experimenting and managed to find a non traditional loop instead:

This was very surprisingly simple, although I wanted to involve more motion to the circles in the back initially, I felt content when I reached this final product. For the future, I would hope to have done something such as a color loop instead, blending or transforming colors into one another in hopes of making this loop more “traditional”, at least visually.



Reflection

Casey Reas’ exploration of chance operations, as presented in his Eyeo Festival talk, provides a fascinating lens through which we can view the intersection of randomness and structured systems within the realm of digital art. 

Reas’ work, which combines the precision of algorithms with the unpredictability of random events, challenges the conventional notion of control in the creative process. This duality of chaos and order, as showcased in his artworks, prompts us to reconsider the role of the artist in the age of digital creation. 

The historical context provided in Reas’ talk, linking back to earlier practices of chance operations in art, enriches our understanding of this concept. This perspective not only bridges the gap between past and present art practices but also illuminates the continuous search for balance between intentionality and serendipity in artistic expression.

In reflecting on Reas’ presentation, it’s clear that the inclusion of chance operations within the realm of digital art opens up new avenues for creativity. It challenges artists to give up a degree of control, allowing randomness to introduce unique, unrepeatable elements into their work. This approach not only enriches the aesthetic and conceptual dimensions of the artwork but also mirrors the complexity and unpredictability of the world around us.

Overall, Casey Reas’ talk at the Eyeo Festival serves as a compelling reminder of the potential that lies at the intersection of technology, art, and randomness. His exploration of chance operations invites us to embrace the unpredictable, seeing it not as a limitation but as a source of endless creative possibilities.

Assignment 2- Shaikha AlKaabi

For this week’s assignment I wanted to create a feather-like magazine design. I got some inspiration from Peacock feathers since they are known for their iridescent colors and striking patterns, featuring an eye-like design.  While working on the code I wanted each “feather” to move whenever the mouse move over it so I used the sin function to scale the flutter effect. 

 

A code that I’m particularly happy about is the one that creates an ombre effect on the “feathers”:

let inter = map(i, 0, featherHeight, 0, 1);

let col = lerpColor(c1, c2, inter);

This code helps the colors to smoothly change from c1 and c2 creating the ombre effect.

let featherWidth = 100;
let featherHeight = 100;
let cols, rows;
let c1, c2;

function setup() {
  createCanvas(400, 400);
  cols = width / featherWidth; 
  rows = height / featherHeight * 2; 

}

function draw() {
  background(255);
  for (let i = 0; i <= cols; i++) {
    for (let j = 0; j <= rows; j++) {
      let x = i * featherWidth;
      let y = j * featherHeight / 2;

      // Adjusting for every other row to create a staggered effect so that the feathers dont overlap
      if (j % 2 === 0) {
        x += featherWidth / 2;
      }

      // Check if the mouse is over the current feather shape
      let mouseOver = dist(mouseX, mouseY, x, y) < featherWidth / 2;

      drawFeather(x, y, mouseOver);
    }
  }
}

function drawFeather(x, y, mouseOver) {
  if (mouseOver) {
    // Generate a gradient of colors for the ombre effect
    c1 = color(random(255), random(255), random(255), 100);
    c2 = color(random(255), random(255), random(255), 100);
  } else {
    c1 = color(0, 100);
    c2 = color(0, 100);
  }

  // Draw and color the feather with a diamond shape using QUAD_STRIP
  noFill();
  strokeWeight(1);
  beginShape(QUAD_STRIP);
  for (let i = 0; i <= featherHeight; i++) {
    let inter = map(i, 0, featherHeight, 0, 1);
    let col = lerpColor(c1, c2, inter);
    stroke(col);
    
    // Introduce fluttery motion when mouse is over
    let flutter = mouseOver ? sin(frameCount / 10 + i / 3) * 2 : 0; // Adjust flutter effect here
    let baseXOffset = sin(map(i, 0, featherHeight, 0, PI)) * featherWidth / 2;
    let xOffset = baseXOffset + flutter; // Apply flutter effect
    vertex(x - xOffset, y + i - featherHeight / 2);
    vertex(x + xOffset, y + i - featherHeight / 2);
  }
  endShape();
}

function mouseMoved() {
  redraw(); 
}

 

Reading Response – Week #2 Redha Al Hammad

The main point from this lecture that stood out to me was the balance between randomness and order which has been central to the development of interactive art over time.

Prior to learning about the technical process behind coding, I never considered that conceptualization and randomness can coexist within the same work. I was vaguely aware of algorithmically generated art, especially with the rise of AI generated images in the past few years, and I had been exposed to contemporary art which puts conceptualization at the forefront. However, the merging of the two is something relatively new to me and definitely an avenue which I would like to explore in the future to expand the scope of my personal work beyond traditional photographic practices.

One of the examples of this presented in the reading was a project by Reas entitled Chronograph in which he algorithmically generated visuals to be projected onto the New World Center in Miami. What stood out to me from this work was the intentionality behind it as the visuals were created using images of the neighborhood surrounding the center and later manipulated and collaged through coding. This defied my preconceived notion of digital, coded art to be nothing more than a display of technique and skill as it offered a very tangible ‘why’ to the decision making process behind the work. I have included it below.

Another point which stood out to me from the lecture was the effectiveness of simplicity. This became apparent to me as Reas did a live demo of a very basic Commodore 64 program. Despite only using two basic symbols, Reas’ introduction of randomness allowed the program to produce an interesting visual. As someone who is inexperienced in coding, I would like to combine the aforementioned intentionality with the effective simplicity of this C64 program in order to get the most out of my work.

Reading Response – Shereena AlNuaimi

In his Eyeo lecture, Casey Reas explores the relationship between art and chance, emphasizing how order and chaos interact in creative expression. He presents the idea of “controlled randomness,” in which artists set guidelines while leaving room for unexpected outcomes, providing a novel viewpoint on the process of creating art. Reas presents the idea of “ordered randomness” to show how artists may retain control while offering unpredictability in response to worries that digital art is stifling artistic creativity. In addition to promoting investigation into digital art and coding, this conversation challenges preconceptions and heightens appreciation for the deliberate use of unpredictability in creative expression. It also improves awareness of the link between order and chaos in art.

Furthermore, he highlights how programming languages become vital to the creation of art, drawing connections between code determinism, creative expression, and controlled unpredictability. This point of view encourages a deeper exploration of the creative possibilities inherent in code by showing how straightforward code may result in patterns that are both visually pleasing and meaningful artistically. These insights provides a new previously untapped avenues for artists to explore the interplay of chance, intention, and order, greatly expanding their artistic canvas.

Week 2 – Reading Reflection: Casey Reas

The implementation of algorithms showcased in the video intrigued me, particularly the simulations where algorithms breathe life into meaningful constructs. Witnessing the utilization of body and tissue geometries to craft clothing was especially striking, demonstrating the fusion of art and technology in multiple ways.

The portrayal of randomness in Reas’s presentation was particularly interesting to me. Each pattern, stemming from a singular algorithm, unfolded into multiple distinct artworks with subtle alterations in speed or character selection. This showed us the ways in which randomness has the capability in generating diverse artistic expressions, raising questions about the nature of creativity in algorithmic art.

However, in a previous course I  attended the debate of when does an algorithm is allowed to be credited for the work it creates popped a lot. Especially when AI can generate images using solely a prompt. Of course, in Reas’s case it is completely different due to the fact that code is being used as a tool, but, what does it mean for artists now when using a prompt?