Recursive Tree & Conversion into 3D Space?

I’m studying the code below (written by S. Calderon) and we’ve been asked to turn the generated image from 2D to 3D. The code itself is quite complex and as a beginner, I’d appreciate any hints on how I can go about this task??? Any tips on how I get started with this assignment would really be appreciated.

/*
Task: Explore objects and classes by experimenting with object-based graphics that
allow for different instances of the same object within the script.  Next, try to translate 
the geometry into 3-dimensional space.
*/
 
 
//VARIABLES
int branchMax = 3; 
int extentMax = 5;
 
 
//SETUP 
void setup() 
{
  size(800, 400); 
  smooth();
  noLoop();  
  strokeWeight(1);  
}
 
 
//DRAW
void draw() 
{
 background(255);
 Vector node = new Vector(width/2, height, random(20,50), 270);
 fractalise(node, extentMax); 
}
 
void mousePressed()
{    
    draw();
}
 

void fractalise(Vector v, int extent) //the recursive function for tree growth
{
if(extent <= 0 ) //exit condition is when number of extensions less than or equal to zero
{ 
  return; 
} 
 extent--; //decrements value of the integer variable by one
 
 v.Render(); 
 for(int i=0; i<branchMax;i++)
 {
  Vector vGrowth = new Vector(v.getEndPointX(), v.getEndPointY(), //creates new vector
                             random(50,100), random(180, 360));  //angle of growth is random within set parameters
                             
  vGrowth.Render(); //renderise and fractalise recursive                         
  fractalise(vGrowth, extent); 
 }
}
 

class Vector //name of class declared
{
 float x, y, r, theta; //co-ordinates for the class Vector
 float EndX, EndY; //breadth of the class Vector
 
 Vector (float _x, float _y, float _r, float _theta) 
 {
  this.x = _x;
  this.y = _y;
  this.r = _r;
  this.theta = radians(_theta);
  
  EndX = getEndPointX();
  EndY = getEndPointY();
 }
 
 float getEndPointX() {
  return (x + r*cos(theta));  //returns x-coordinate in polar form
 }
 

 float getEndPointY() {
  return (y + r*sin(theta));  //returns y-coordinate in polar form
 }
 
 void Render()  //function dictates branch color and line length
 {  
  stroke(random(200), random(200), random(200));  //lines of the tree are random colors
  line(x,y, getEndPointX(), getEndPointY() );
  noFill();
  ellipse(x,y, 5, 5);
 } 
}

First, I would extend the Vector class from x,y,r,theta (polar coordinates) to x,y,z,r,theta,phi (spherical coordinates. Then add all the various supporting functions like getEndPointZ(). Then when you add a new vGrowth tree branch, generate it within a hemisphere instead of a half circle.

To see it in 3D is rather trickier and, I’m guessing, is beyond the scope of the assignment. A static image won’t really look any different from the 2D version, so you could only see it well if you spun it around. That would require using size(800, 400, P3D); instead and removing the noLoop();. You would generate the tree at the origin, rotate using rotateY(frameCount*TAU/360.); and then translate to be in the middle of the screen. Since you are generating the tree on the fly and not saving any of the data, you’d need to generate the same tree each time you draw it which you can do by re-seeding the random generator each draw loop with a fixed value.

Rather than draw in 3D, you could set the line stroke() based on the z value so that closer branches are brighter than farther ones. That could give you a sense of depth without having to go full 3D.

1 Like

Scudly, thanks so much for the tips. I will give your suggestions a go - yes, the stroke() idea is the way I will approach this exercise. Thanks again :grinning: