Final Project – 3D Procedural Creature Generator

https://editor.p5js.org/oae233/full/lk6Id6oVL

Concept / Idea

In my midterm, I recreated the visual components of the body using & coding logic and used them as the “paint” to create my artwork, in an attempt to explore the concept of the body. For my final I wanted to focus on the aspect of recreating bodies in 3D space, trying to replicate the biological logic behind how they are assembled. I broke down different parts of the body that are shared among a variety of creatures and thought about how to recreate them, with varying attributes that produce both familiar and wildly new forms.

I hope that my project can leave users with a sense of connectedness with different life forms no matter how physically different we might be.

Implementation:

For this project, I implemented my knowledge gained from the course about using randomness, noise, oscillation/waves, class handling, and trigonometry logic.

I start by generating points in 3D space and then draw lines to connect them. this creates the skeleton or base of my creature. Then I use points on these lines to place different 3D primitives, orienting them based on the lines’ direction.

I only implemented this idea to the spine (which creates the main body) and arms and legs.

Some code I want to highlight:

ThreeD(i) {
    // push();
    // this.radius2 = this.radius1/(i+1);
    this.length = p5.Vector.sub(this.startPoint, this.endPoint);
    this.nextlength = p5.Vector.sub(this.nextstartPoint, this.nextendPoint);

    this.distance = p5.Vector.dist(this.startPoint, this.endPoint);
    this.division = this.distance / 2;
    this.lengthStep = p5.Vector.div(this.length, this.division);
    this.facing = this.length.heading();
    this.nextfacing = this.nextlength.heading();

    this.anglediff = this.facing - this.nextfacing;

    this.anglediff /= this.division;
    // this.counter+=0.5;

    for (let w = 0; w <= this.division; w++) {
      this.sinwav = map(i, 0, this.bodyparts, 0, 90);
      this.counter += 0.04;
      // this.radius2 = this.radius1/this.counter;
      this.radius2 =
        (this.radius1 / this.counter) *
          this.Rmax *
          cos(this.shift + this.sinwav * this.stretch) +
        this.Rmin;
      this.radius2 = constrain(this.radius2, 2, 100);
      push();
      noStroke();
      translate(
        this.startPoint.x - this.lengthStep.x * w,
        this.startPoint.y - this.lengthStep.y * w,
        this.startPoint.z - this.lengthStep.z * w
      );
      rotate(90);
      rotate(this.facing);
      cylinder(this.radius2, 5);
      pop();
      if (w > this.division - 1) {
        for (let z = 0; z < this.division; z++) {
          push();
          // print(z);
          noStroke();
          translate(
            this.startPoint.x - this.lengthStep.x * w,
            this.startPoint.y - this.lengthStep.y * w,
            this.startPoint.z - this.lengthStep.z * w
          );
          rotate(90);

          rotate(this.facing - this.anglediff * z);
          cylinder(this.radius2, 5);
          pop();
        }
      }
    }
  }
}

This is the function that turns the line skeletons into 3D shapes. As u can see I use the length of the line (this.distance) to distribute the shapes at constant density across all lines.

I also modulate the radius using various waves to create variation.

Happy Accidents:

Tip: use your mouse to move around this shape!

 

IM Showcase:

Future work:

For future work I’d love to complete the project, adding support for heads, and individual facial features like mouth and eyes, that can generate vastly different forms from beaks and simple eyes, to toothful jaws and compound eyes. This was what I had hoped to do in the beginning but unfortunately I was unable to complete it on time.

Leave a Reply

Your email address will not be published. Required fields are marked *