HW3: Generative Art Using OOPs and Perlin Noise

Inspiration

This code is inspired by a video from “The Coding Train” channel on YouTube. The video shows how to create a flow field simulation using particles that follow the flow of a vector field.  It uses Object-Oriented Programming, arrays, and Perlin noise to create flow field particles that look very aesthetically pleasing.

Concept

The concept behind the flow field simulation is that particles move according to a vector field, which defines the direction and magnitude of the flow. The vector field is generated using noise, so that the flow is not predictable and creates a natural, organic look. The particles follow the flow field by calculating the angle of the vector at their current position, and adjusting their velocity and position accordingly.

Implementation

The implementation of the code involves creating a Particle class to represent each particle in the system. This class contains a number of methods to control the particle’s motion. The update() method updates the velocity and position of the particle based on its acceleration. The follow() method uses the particle’s current position to find the corresponding vector in the flow field and apply it as a force to the particle. The display() method draws a line from the particle’s current position to its previous position, and the updatePrev() method updates the previous position to be the current position. The resetParticles() method checks if the particle has gone out of bounds and wraps it back to the other side of the canvas if it has.

The main setup function generates the flow field and creates the particles. The flow field is generated by dividing the canvas into a grid of cells, and then generating a random vector for each cell. The number of columns and rows in the grid is calculated based on the size of the canvas and the scale factor, s. The setup() function also creates the particles by creating new instances of the Particle class and adding them to the particles array.

The draw() function updates the flow field and the particles. First, it updates the noise offset to create a smoothly changing flow field. Then, it loops through the grid and calculates a new angle for each cell based on the noise function. This angle is converted into a vector, which is stored in the flowfield array. Next, the function loops through the particles, and for each particle, it calls the follow() method to apply the corresponding flow field vector to the particle. Then, the update() method is called to update the particle’s velocity and position based on its acceleration. Finally, the display() method is called to draw the particle and the resetParticles() method is called to wrap the particle back to the other side of the canvas if it has gone out of bounds.

// Class for a particle that moves based on a perlin noise flow field
class Particle {
  constructor() {
    // Initial position of the particle at a random point on the canvas
    this.pos = createVector(random(width), random(height));
    // Initial velocity set to (0, 0)
    this.vel = createVector(0, 0);
    // Initial acceleration set to (0, 0)
    this.accel = createVector(0, 0);
    // Maximum speed that the particle can move
    this.maxV = 4;
    // Store the previous position of the particle
    this.prevPos = this.pos.copy();
  }

  // Follow the flow field vectors
  follow(vectors) {
    // Calculate the grid position of the particle
    let x = floor(this.pos.x / s);
    let y = floor(this.pos.y / s);
    let index = x + y * cols;
    // Get the force vector at that grid position
    let force = vectors[index];
    // Apply a force to the particle's acceleration
    this.accel.add(force);
  }
  
  // Update the position of the particle based on its velocity and acceleration
  update() {
    // Add the acceleration to the velocity
    this.vel.add(this.accel);
    // Limit the velocity to the maxV
    this.vel.limit(this.maxV);
    // Add the velocity to the position
    this.pos.add(this.vel);
    // Reset the acceleration to (0, 0)
    this.accel.mult(0);
  }

  // Display the particle as a line connecting its current and previous position
  display() {
    stroke(220);
    strokeWeight(1);
    line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
    this.updatePrev();
  }

  // Update the previous position of the particle
  updatePrev() {
    this.prevPos.x = this.pos.x;
    this.prevPos.y = this.pos.y;
  }

  // Check if the particle has gone outside the canvas and wrap it around if necessary
  particleReset() {
    if (this.pos.x > width) {
      this.pos.x = 0;
      this.updatePrev();
    }
    if (this.pos.x < 0) {
      this.pos.x = width;
      this.updatePrev();
    }
    if (this.pos.y > height) {
      this.pos.y = 0;
      this.updatePrev();
    }
    if (this.pos.y < 0) {
      this.pos.y = height;
      this.updatePrev();
    }
  }
}

Challenges

One of the challenges in this project was figuring out how to create a smooth flow field that changes over time. This was achieved by using the noise function to generate random values for each cell in the grid. By updating the noise offset in the draw() function, the flow field smoothly changes over time, creating a dynamic and interesting visual.

Another challenge was figuring out how to apply the flow field vectors to the particles in a way that creates a believable and visually appealing motion. This was achieved by dividing the canvas into a grid of cells and using the particle’s position to find the corresponding flow field vector. The particle’s velocity is then updated based on this vector, creating a believable motion that follows the flow of the flow field.

Reflection

This project was a fun and interesting exploration of particle systems and flow fields. By creating a simple system of particles that follow a flow field, it is possible to create a wide variety of dynamic and visually appealing patterns. The use of the noise function to generate the flow field allows for a high degree of control over the motion of the particles and the overall visual appearance of the system. This project was a valuable learning experience, and it has given me a deeper appreciation for the potential of particle systems and flow fields for creating dynamic, organic and engaging visuals using object-oriented programming, arrays, and Perlin noise.

Reference

Sketch Link: https://editor.p5js.org/swostikpati/full/-KXM2Ag3s

Leave a Reply