# Explanation for the algorithm behind this generative art piece

**URL:** <https://discourse.processing.org/t/explanation-for-the-algorithm-behind-this-generative-art-piece/21108>\
**Category:** Coding Questions\
**Created:** [May 20, 2020, 7:45pm UTC](https://discourse.processing.org/t/explanation-for-the-algorithm-behind-this-generative-art-piece/21108 "2020-05-20T19:45:39Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![the0ne](https://avatars.discourse-cdn.com/v4/letter/t/47e85d/32.png) [@the0ne](https://discourse.processing.org/u/the0ne)\
**Post date:** [May 20, 2020, 7:45pm UTC](https://discourse.processing.org/t/explanation-for-the-algorithm-behind-this-generative-art-piece/21108/1 "2020-05-20T19:45:39Z")

</div>

I recently came across this beautiful generative art piece, [**’Trunk’ by Kjetil Golid**](https://generated.space/sketch/trunk/) ([source code](https://github.com/kgolid/p5ycho/blob/master/trunk/sketch.js)).

I went through the code and understand what’s being done, yet I’m unable to grasp why the algorithm works the way it does. Can someone explain it to me?

I even ported it to Java from Javascript, in case any of you would like to run it without having to set up an html page. I 've also annotated all the variables that made sense to me.

```auto
int rings = 50; // number of rings
float dim_init = 50; // size of innermost ring
float dim_delta = 4; // distance between two adjacent rings

float chaos_init = 0.2; // noise on innermost ring
float chaos_delta = 0.12; // change in ring noise as you move outwards
int chaos_mag = 20; // magnitude of noise

float ox = random(10000);
float oy = random(10000);
float oz = random(10000);

void setup() {
  size(700, 700);
  frameRate(60);
  smooth();
  
  strokeWeight(1);
  stroke(0);
  noFill();
}

void draw() {
  clear();
  background(255, 255, 255);
  translate(width/2, height/2);
  
  
  //ox += 0.04;
  oy -= 0.02;
  oz += 0.01;
  
  for (int i=0; i<rings; i++) {
    beginShape();
    for(int angle=0; angle<360; angle++){
      float radian = radians(angle);
      //stroke(map(angle, 0, 360, 255, 0), map(i, 0, rings, 255, 0 ), map(angle*i, 0, 360*rings, 255, 0));
      float radius = (chaos_mag*getNoiseWithTime(radian, chaos_delta*i+chaos_init, oz)) + (dim_delta*i+dim_init);
      vertex(radius*cos(radian), radius*sin(radian));
    }
    endShape(CLOSE);
  }
}

float getNoiseWithTime(float radian, float dim, float time) {
  float r = radian % TWO_PI; // r repeats every 360 degrees
  if (r<0) {r += TWO_PI;}
  return noise(ox+cos(r)*dim, oy+sin(r)*dim, oz+time);
}

```

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [May 20, 2020, 7:52pm UTC](https://discourse.processing.org/t/explanation-for-the-algorithm-behind-this-generative-art-piece/21108/2 "2020-05-20T19:52:17Z")

</div>

> [@the0ne](#):
>
> even ported it to Java from Javascript

~~Thanks! Do you have an [editor.p5js.org](http://editor.p5js.org) or [openprocessing.org](http://openprocessing.org) link for that? The forum also accepts direct embeds.~~

**EDIT** : Ah, _to_ Java _from_ JS. Nevermind!

> [@the0ne](#):
>
> I’m unable to grasp why the algorithm works the way it does.

I don’t know which part you don’t understand, so I can’t try to help explain whatever part that is. Can you be more specific about what effect or what operation you are curious about?

---

<div class="post-metadata">

**Author:** ![the0ne](https://avatars.discourse-cdn.com/v4/letter/t/47e85d/32.png) [@the0ne](https://discourse.processing.org/u/the0ne)\
**Post date:** [May 20, 2020, 7:58pm UTC](https://discourse.processing.org/t/explanation-for-the-algorithm-behind-this-generative-art-piece/21108/3 "2020-05-20T19:58:22Z")

</div>

Thank you for responding!

> [@the0ne](#):
>
> ```auto
> float radius = (chaos_mag*getNoiseWithTime(radian, chaos_delta*i+chaos_init, oz)) + (dim_delta*i+dim_init);
> vertex(radius*cos(radian), radius*sin(radian));
> 
> ```

> [@the0ne](#):
>
> ```auto
> float getNoiseWithTime(float radian, float dim, float time) {
> float r = radian % TWO_PI; // r repeats every 360 degrees
> if (r<0) {r += TWO_PI;}
> return noise(ox+cos(r)*dim, oy+sin(r)*dim, oz+time);
> }
> 
> ```

These are the bits I don’t understand - the computation of the radius, noise and vertex. The math is easy to read, but I can’t get an intuitive grasp over how it affects the final output.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [May 20, 2020, 8:00pm UTC](https://discourse.processing.org/t/explanation-for-the-algorithm-behind-this-generative-art-piece/21108/4 "2020-05-20T20:00:59Z")

</div>

Look at this in draw:

```auto
  //ox += 0.04;
  oy -= 0.02;
  oz += 0.01;

```

Try disabling oy, and oz, and both, and rerunning.

Do this in combination with replacing this line:

```auto
return noise(ox+cos(r)*dim, oy+sin(r)*dim, oz+time);

```

with one of these instead:

```auto
  return noise(ox+cos(r)*dim, 0, oz+time);
  return noise(0, oy+sin(r)*dim, oz+time);
  return noise(ox+cos(r)*dim, 0, 0);
  return noise(0, oy+sin(r)*dim, 0);

```

This should help you quickly break down the 5 dimensions involved – x, y, z, and changes in time to y and z.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [May 20, 2020, 8:05pm UTC](https://discourse.processing.org/t/explanation-for-the-algorithm-behind-this-generative-art-piece/21108/5 "2020-05-20T20:05:53Z")

</div>

You can also understand what

```auto
float getNoiseWithTime(float radian, float dim, float time) {

```

is doing by replacing it with `return random(1);` or `(0)` (disabling).

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [May 20, 2020, 8:10pm UTC](https://discourse.processing.org/t/explanation-for-the-algorithm-behind-this-generative-art-piece/21108/6 "2020-05-20T20:10:14Z")

</div>

So, for each vertex in each circle, we want to add a bit of noise. We sample that noise from a corresponding location on 2D slice of a perlin noise field – we can think of those values as like a topological map, locally correlated into mountain ranges and valleys. Now we have rings with perlin wobbles, and the wobbles on the rings line up with the wobbles on the 2D field they were sampled from.

But we want the wobbles to “drip” – so we change oy over time, moving across the perlin surface (slide the mountains) and sampling from a gradually different place.

But we _also_ want the wobbles to change as they drip. Instead of sampling the same slice, we are ~~sinking~~ _bobbing up and down_ in a 3D perlin space like a submarine with oz, and the mountains slowly change their contours.

---

<div class="post-metadata">

**Author:** ![the0ne](https://avatars.discourse-cdn.com/v4/letter/t/47e85d/32.png) [@the0ne](https://discourse.processing.org/u/the0ne)\
**Post date:** [May 26, 2020, 9:11am UTC](https://discourse.processing.org/t/explanation-for-the-algorithm-behind-this-generative-art-piece/21108/7 "2020-05-26T09:11:13Z")

</div>

Hi, sorry for taking a while to reply!

Your suggestions were very helpful, and while tinkering around with the variables I realized that I had no clue how Perlin noise worked. I did my research though, and now that I have the necessary context I can understand the code and the idea behind it.

Thank you for the help. 🙂
