Midterm Project Concept – Nature

Concept:

For my midterm project, I will be producing NFT generative nature-related artwork. This involves acrylic-paint tinted landscapes, (potentially 3D) recursive components, sin-waves, and particles, with the user being able to customize them. Through a GUI, the user will be prompted to choose the season, the weather, the time, and the components. I was mainly inspired by the course’s name “decoding nature”, and instead of having infinitely running animations, static artwork would be more convenient.

Libraires and Algorithms:

For now, I’ll be using the following:
Acrylic paint
Perlin noise
Sin-wave
Three.js
Recursion
Particle system (attraction, repulsion)

Progress:
// Noise wave
beginShape();
for (let i = 0; i < width; i += 2) {
  vertex(i, baseline + offset + amplitude * noise(i * 0.01));
}
endShape();

View post on imgur.com

View post on imgur.com

View post on imgur.com

GUI:

The page will be divided into two sections divided as the following (75%-25%). The larger area will showcase the artwork whereas the smaller one will allow the user to play around with the settings (weather, time, recursive components, particles, perlin noise, waves, …)

Potential challenges:

Potential challenges could involve setting the right parameters for recursion to avoid a high computational power need. Finding the most optimal values for noise and particles could be tricky as well, but that could be solved through a trial-and-error process. As for adding a third dimension, it would be time-consuming for the short amount of time we have, but I’ll definitely try to implement a simpler version.

Coding Assignment 4 – Network

Concept:

For this week’s assignment, I was inspired by the mystique of celestial bodies and quantum mechanics to create a network of dynamically connected particles gravitating around the mouse coordinates. It involves particle interaction, attraction, acceleration, and velocity. The number of particles starts low and gradually increases to reach 350, alongside their opacity and size. Upon mouse movement, the particles follow slowly the coordinates with some noise introduced implicitly.

Code: https://editor.p5js.org/bdr/sketches/ekie7vlHu

Code Walkthrough:

Particle Class:

Constructor: each particle is initialized with a random position, velocity, and an initial distance vector.

Update(): It is responsible for updating the particle’s position based on its velocity and applying boundaries to ensure particles stay within the canvas. It also calculates the acceleration pointing towards the mouse cursor and adds it to the particle’s velocity, creating an attraction effect.

update() {
        if (this.position.x > width / 2 || this.position.x < -width / 2 || this.position.y > height / 2 || this.position.y < -height / 2) {
            this.position = createVector(random(-150, 150), random(-150, 150));
            this.velocity = createVector(random(-0.5, 1), random(-0.5, 1));
        }
        let m = createVector(mouseX - width/2, mouseY - height/2);
        let acceleration = p5.Vector.sub(m, this.position);

        acceleration.setMag(0.5);
        this.velocity.add(acceleration);
        this.position.add(this.velocity);
}

Display(): Mainly to display the particles. It calculates the distance vector to track proximity to other particles to later draw the connecting line.

As the network grows bigger, the transparency of the connecting line decreases. The particles – filled circles – are replaced with larger non-filled ellipses.

stroke(255, 0, 0, this.distance.x + this.distance.y);

Draw Function:

Translate(): translates the coordinate system to the center of the canvas to make it easier to work with particle positions.

To gradually create multiple instances of particles, I’m adding one particle at every iteration.

The line is drawn using the following:

for (i=0; i<particles.length; i++) {
        particles[i].display();
        for (j=0; j<particles.length; j++) {
            if (i!=j){
                if (particles[i].position.x <= particles[j].position.x + 28 && particles[i].position.x >= particles[j].position.x - 28) {
                    if (particles[i].position.y <= particles[j].position.y + 28 && particles[i].position.y >= particles[j].position.y - 28) {
                        stroke(255, 0, 0, particles[i].distance.x + particles[i].distance.y);
                        line(particles[i].position.x, particles[i].position.y, particles[j].position.x, particles[j].position.y);
                    }
                }
            }
        }
    }
Challenges:

One of the challenges that I have faced is certainly the computational power.  Having ore particles means needing more power and therefore sacrificing speed. Hence keeping the max to 350.

Improvements:

Repulsion force: Add repulsion forces alongside attraction
Wind force using mouse movement/click: Upon using the mouse, the particles will move away following the wind movement and power.

Coding Assignment 3 – Gravity

Concept:

This week’s sketch is a simulation that explores the fundamental force of gravity allowing users to observe how objects interact with each other in response to gravitational attraction and repulsion. It involves two types of entities: movers and attractors, and relies on acceleration, velocity, g-force and mass to move them.

Inspiration:

It is inspired by how gravitational power influences the motion and behavior of celestial bodies.

Code: https://editor.p5js.org/bdr/sketches/rtPleK4cp

Code Walkthrough:
Initialization and Setup:

At first, two arrays are defined ‘movers’ and ‘attractors’ to store instances of the Mover class. The setup function creates a canvas and initializes the simulation with one attractor at the center and four randomly positioned movers with random velocities. Each mover is given a random mass.

Mover Class:

The Mover class represents the moving objects in the simulation. Each mover has a position, velocity, acceleration, and mass which determines the strength of its gravitational attraction. The class includes methods for applying forces, attracting other objects, updating their position and velocity, and displaying itself on the canvas.

AddAttractor():

Users can add attractors to the simulation by double-clicking anywhere on the canvas.

Draw():

The draw function is the core of the simulation. It continuously updates and displays the state of the movers and attractors.
Translate(): It translates the coordinate system to the center of the canvas, making calculations and rendering centered around this point.
Mover-mover interaction: It iterates through each pair of movers to calculate gravitational forces between them. this creates a network of interconnected motions among the movers. Connecting lines are drawn between the movers to visualize these interactions.

Challenges:

One of the challenges I have faced is balancing the strength of gravitational forces to ensure that the simulation is visually appealing and not too chaotic. It took some experimentation and trial and error before finding the right values.

Improvements:

Collision detection: Implement collision detection and response for the movers when they come into close proximity to each other or with the canvas boundaries.

Trail effects: Add trail effects to the movers to visualize their path over time.

Gravitational bodies: Instead of circles, represent movers and attractors as more complex shapes or even images for a more realistic and visually appealing representation.

Assignment Week #2

Concept:

This week’s assignment represents water droplets falling on the ground. They are visually represented as ellipses and they exhibit natural falling and splashing behavior.

It is inspired by the following slow-motion video:

Demo:

Code: https://editor.p5js.org/bdr/sketches/YS6DBtNOH

Process:

https://imgur.com/WlcV5ZmCode Walkthrough:

Drop Class:

Constructor: The constructor initializes a new water drop object with the following properties:
– Position: A 2D vector representing the initial position of the raindrop on the canvas. It is set to a random location within the boundaries.
– Velocity: A 2D vector representing the initial velocity of the raindrop. It starts with no horizontal velocity and a downward velocity of 5 pixels per frame.
– Acceleration: A 2D vector representing the acceleration of the raindrop. It starts with no horizontal acceleration and a vertical acceleration of 0.2 pixels per frame.
– Length: The length of the water drop, which is a random value between 10 and  20 pixels.
r: Control the size of the splash.
Opacity: Set a smooth transition for the splash.
Landed: A boolean variable to indicate whether the water drop landed on the ground.

Methods:
Update(): Update the water drop’s position based on the velocity and acceleration. It also limits the raindrop to a certain velocity.
Display(): Draw the drop on the canvas as an ellipse. The color is white with an opacity of 120. When landed, its length is gradually reduced to create a disappearing effect.
Land(): Display a landing effect. It is a shrinking ellipse with decreasing opacity.

Setup(): Create the canvas 640×640, and initialize an array of water drops (40 droplets).

Draw(): Call the object’s methods, and replace the drops that have landed with a new one creating a continuous simulation.

Challenges:

One of the challenges is certainly creating the perfect splashing effect, it took some trial and error before landing on the ideal parameters.

Improvements:

– Add water splash sound.
– Allow the user to control where the drops are originating from using mouseX and mouseY.

Assignment Week#1

Code: https://editor.p5js.org/bdr/sketches/Vnv5bkHdK

Concept:

Connections combines two concepts: Levy flight motion and dynamic bezier curve connections between particles. Levy flight is a type of random walk where the step length follows a heavy-tailed probability distribution, resulting in a long erratic movement. It represents a dynamic system of particles moving within the canvas, with real-time changing edges connecting them. My sketch draws inspiration from concepts in computational art to explore the interplay between randomness and controlled forms in a dynamic particle system.

Steps:

Code Walkthrough:

A ‘Particle’ class encapsulates the behavior and properties of individual particles. Each particle is initialized with a random position (x,y) within the canvas and a random color with alpha transparency. The particles move according to Levy flight motion and can change direction when they come into close proximity to each other.

Particle Movement – Levy Flight:

Using the update() function, a random length and direction is calculated and is reflected on the particle’s movement. Since stepDirection is a random angle, cos(stepDirection) and  sin(stepDirection) generate random values between -1 and 1. These values are then multiplied by stepLength, which is a random value as well. The use of cosine and sinus ensures that the particle can move in any direction as stepDirection can take any value between 0 and 2π.

// Levy flight movement
update() {
  let stepLength = random(3);
  let stepDirection = random(TWO_PI);
  this.x += cos(stepDirection) * stepLength;
  this.y += sin(stepDirection) * stepLength;

  // Keep particles within bounds
  this.x = (this.x + width) % width;
  this.y = (this.y + height) % height;
}

Particle Appearance:

The display() method draws each particle as a white ellipse with random alpha to create a glowing effect.

Particle Interaction:

As the particles come too close to each other, they both change their respective directions. It is handled by the changeDirection() function.

Particle Connection – Lerp:

If two particles come within a certain distance, a bezier curve is drawn between them. Linear interpolation is used twice for each pair of connected particles: once to determine the position of the first control point (x1,y1) and again for the second control point (x2,y2). It allows for fine-tuning the curvature of the bezier curve between them.

// Control points for bezier
let control1X = lerp(particles[i].x, particles[j].x, 0.1);
let control1Y = lerp(particles[i].y, particles[j].y, 0.4);
let control2X = lerp(particles[i].x, particles[j].x, 0.9);
let control2Y = lerp(particles[i].y, particles[j].y, 0.9);

// Combines the colors of the particles it connects
stroke(lerpColor(particles[i].color, particles[j].color, 0.5));
bezier(particles[i].x, particles[i].y, control1X, control1Y, control2X, control2Y, particles[j].x, particles[j].y);

The color of each bezier curve is a combination of the colors of the two connected particles, creating a smooth color transition along the curve (using Lerp again).

Challenges:

Achieving a balance between randomness and control in the particle movement can be tricky as an excess in randomness can result in chaos and unpredictable behavior. I was able to do that by fine-tuning these parameters and following a trial and error process.

Possible improvements:

  • Particle attraction: add forces of attraction
  • User Interaction: let the user interact through clicks or mouse movement

Reading Response – Week#1

Computational Beauty of Nature presents a nuanced perspective on the concept of reductionism and its relevance in scientific research, sparking reflection on the nature of our understanding of complex systems. It underscores the balance between recognizing the benefits of reductionism and acknowledging its limitations. In Biology, reductionism has proven successful in studying life forms at various organizational levels, from whole organisms down to tiny molecules. Yet, while valuable, reductionism may not always give us the full picture. Understanding how things interact and the emergent properties that arise is as crucial in scientific exploration as tracing them back to the quantum level.

It is worth noting the author’s subtle inclination towards favoring a more holistic perspective on understanding complex systems as he continuously hints at possible limitations in the reductionist approach. Despite the bias, the reading encourages a deeper appreciation for the different natures of scientific investigation and suggests that embracing various perspectives can enrich our comprehension of the world’s intricacies. As for personal beliefs, the reading didn’t necessarily change them but prompted some introspection. I believe that combining both methodologies will result in a much richer understanding of the world around us. However, it did leave me with thought-provoking questions regarding how incompatible or complementary reductionism and holism are together, and if a balance is realistic.