Help with a exercise (making circle packing 3d)

Hello! I need help turning

this 2d code into 3d. I have recently started using processing, so 3d processing is a bit of a stretch for me. I am basically just trying to turn the circles into spheres, nothing more extreme, but I have no idea what I should do

The initial code is this

Box [] boxes;
int minSize = 20;
int maxSize = 50;
boolean collide = false;
void setup()
{
size(500, 500);
rectMode(CENTER);
ellipseMode(CENTER);
boxes = new Box[120];
for (int i = 0; i < boxes.length; i++)
{
boxes[i] = new Box(random(maxSize, width-maxSize), random(maxSize, height-maxSize), random(minSize, maxSize), color(0, random(10, 255), random(10, 255)));
}
}
void draw()
{
//background(200);
fill(200, 10);
rect(width/2, height/2, width+2, height+2);
for (int i = 0; i < boxes.length; i++)
{
boxes[i].draw();
}
//check distances between all the other boxes and attracts and collide!
for (int j = 0; j < boxes.length; j++)
{
for (int k = 0; k < boxes.length; k++)
{
if (j != k)
{
boxes[j].collide(boxes[k]);
boxes[j].attract(boxes[k]);
}
}
}
}
void mousePressed()
{
for (int i = 0; i < boxes.length; i++)
{
boxes[i].jiggle();
}
}

and the box class:

class Box
{
// step 1 = variables declaration
int frame = 0;
float posX;
float posY;
float velX;
float velY;
float side;
color c;
// step 2 = constructor, initializes the class
Box(float _posX, float _posY, float _side, color _c)
{
posX = _posX;
posY = _posY;
velX = random(-0.8, 0.8);
velY = random(-0.8, 0.8);
side = _side;
c = _c;
}
// step 3 = functions, functionality of the class
void draw()
{
posX += velX;
posY += velY;
pushMatrix();
translate(posX, posY);
fill©;
ellipse(0, 0, side, side);
popMatrix();
//don’t let the boxes run away from the frame!
if ((posX < side || posX >= width-side)||(posY < side || posY >= height-side))
{
velX = -0.99velX;
velY = -0.99
velY;
}
//slow circles down over time
velX = .98velX;
velY = .98
velY;
}
void attract(Box b)
{
float d = dist(posX, posY, b.posX, b.posY); // calculate dist between boxes
float diffX = b.posX - posX; // difference of position in X
float diffY = b.posY - posY; // difference of position in Y
velX += 0.08*(diffX / (sq(d))); // change velocity by a ratio between dist and pos difference
velY += 0.08*(diffY / (sq(d)));
}
void collide(Box b)
{
float dis = dist(posX, posY, b.posX, b.posY);
//if (dis <= (sqrt(sq(side) + sq(side/2)) + sqrt(sq(b.side/2) + sq(b.side/2)))) // for boxes
float overlap = (side/2 + b.side/2) - dis;
if (overlap>0)
{
float diffX = b.posX - posX; // difference of position in X
float diffY = b.posY - posY; // difference of position in Y
float unitX = diffX/dis;
float unitY = diffY/dis;
velX -= 0.1unitXoverlap;
velY -= 0.1unitYoverlap;
}
}
void jiggle()
{
velX = random(-1, 1);
velY = random(-1, 1);
}
}

Thank you!

so im a beginner too but I know that you can call P3D to work in 3d.

you need to call it within size: size(500,500,P3D)

1 Like

hi! thanks for answering!
yes, indeed, but that won’t turn the circles into spheres, it just changes the ‘world’ they live in.

I have tried few things, but I keep encountering an error saying posZ can not be float

here is a runable version of your code

Apologies, you posted in a way that some code was not correct anymore



Box [] boxes;
int minSize = 20;
int maxSize = 50;
boolean collide = false;

// ----------------------------------------------------------------------
void setup() {
  size(500, 500);
  rectMode(CENTER);
  ellipseMode(CENTER);
  boxes = new Box[120];
  for (int i = 0; i < boxes.length; i++)
  {
    boxes[i] = new Box(
      random(maxSize, width-maxSize), random(maxSize, height-maxSize), 
      random(minSize, maxSize), 
      color(0, random(10, 255), random(10, 255)));
  }
}

// ----

void draw() {
  //background(200);
  fill(200, 10);
  rect(width/2, height/2, width+2, height+2);
  for (int i = 0; i < boxes.length; i++)
  {
    boxes[i].draw();
  }
  //check distances between all the other boxes and attracts and collide!
  for (int j = 0; j < boxes.length; j++)
  {
    for (int k = 0; k < boxes.length; k++)
    {
      if (j != k)
      {
        boxes[j].collide(boxes[k]);
        boxes[j].attract(boxes[k]);
      }
    }
  }
}

// -----------------------------------------------------------------------------

void mousePressed()
{
  for (int i = 0; i < boxes.length; i++)
  {
    boxes[i].jiggle();
  }
}

//===========================================================================

class Box
{
  // step 1 = variables declaration
  int frame = 0;
  float posX;
  float posY;
  float velX;
  float velY;
  float side;
  color c;

  // step 2 = constructor, initializes the class
  Box(float _posX, float _posY, 
    float _side, 
    color _c)
  {
    posX = _posX;
    posY = _posY;
    velX = random(-0.8, 0.8);
    velY = random(-0.8, 0.8);
    side = _side;
    c = _c;
  }

  // -------

  // step 3 = functions, functionality of the class
  void draw()
  {
    posX += velX;
    posY += velY;
    pushMatrix();
    translate(posX, posY);
    fill(c);
    ellipse(0, 0, side, side);
    popMatrix();
    //don’t let the boxes run away from the frame!
    if ((posX < side || posX >= width-side)||(posY < side || posY >= height-side))
    {
      velX = -0.99*velX;
      velY = -0.99*velY;
    }
    //slow circles down over time
    velX = .98*velX;
    velY = .98*velY;
  }
  void attract(Box b)
  {
    float d = dist(posX, posY, b.posX, b.posY); // calculate dist between boxes
    float diffX = b.posX - posX; // difference of position in X
    float diffY = b.posY - posY; // difference of position in Y
    velX += 0.08*(diffX / (sq(d))); // change velocity by a ratio between dist and pos difference
    velY += 0.08*(diffY / (sq(d)));
  }
  void collide(Box b)
  {
    float dis = dist(posX, posY, b.posX, b.posY);
    //if (dis <= (sqrt(sq(side) + sq(side/2)) + sqrt(sq(b.side/2) + sq(b.side/2)))) // for boxes
    float overlap = (side/2 + b.side/2) - dis;
    if (overlap>0)
    {
      float diffX = b.posX - posX; // difference of position in X
      float diffY = b.posY - posY; // difference of position in Y
      float unitX = diffX/dis;
      float unitY = diffY/dis;
      velX -= 0.1*unitX*overlap;
      velY -= 0.1*unitY*overlap;
    }
  }
  void jiggle()
  {
    velX = random(-1, 1);
    velY = random(-1, 1);
  }
}//class
//

Chrisir

oh, thank you!
do you have any idea how I could change it to 3d?

1 Like

here is a VERY quick change to 3D.

You have to make all collide and attract etc. stuff to 3D too…

Have you read the 3D tutorial: https://www.processing.org/tutorials/p3d/

Hey, and welcome to the forum!

Great to have you here!

Chrisir



Box [] boxes;
int minSize = 20;
int maxSize = 50;
boolean collide = false;

// ----------------------------------------------------------------------
void setup() {
  size(500, 500, P3D);
  rectMode(CENTER);
  ellipseMode(CENTER);
  boxes = new Box[120];
  for (int i = 0; i < boxes.length; i++)
  {
    boxes[i] = new Box(
      random(maxSize, width-maxSize), random(maxSize, height-maxSize), random(maxSize, height-maxSize), 
      random(minSize, maxSize), 
      color(0, random(10, 255), random(10, 255)));
  }
}

// ----

void draw() {
  background(200);
  lights(); 

  fill(200, 10);
  rect(width/2, height/2, width+2, height+2);

  for (int i = 0; i < boxes.length; i++) {
    boxes[i].draw();
  }

  //check distances between all the other boxes and attracts and collide!
  for (int j = 0; j < boxes.length-1; j++)
  {
    for (int k = j+1; k < boxes.length; k++)
    {
      if (j != k)
      {
        boxes[j].collide(boxes[k]);
        boxes[j].attract(boxes[k]);
      }
    }
  }
}

// -----------------------------------------------------------------------------

void mousePressed()
{
  for (int i = 0; i < boxes.length; i++)
  {
    boxes[i].jiggle();
  }
}

//===========================================================================

class Box
{
  // step 1 = variables declaration
  int frame = 0;
  float posX;
  float posY;
  float posZ;

  float velX;
  float velY;
  float side;
  color c;

  // step 2 = constructor, initializes the class
  Box(float _posX, float _posY, float _posZ, 
    float _side, 
    color _c)
  {
    posX = _posX;
    posY = _posY;
    posZ= _posZ; 
    velX = random(-0.8, 0.8);
    velY = random(-0.8, 0.8);
    side = _side;
    c = _c;
  }

  // -------

  // step 3 = functions, functionality of the class
  void draw()
  {
    posX += velX;
    posY += velY;
    pushMatrix();
    translate(posX, posY, posZ);
    noStroke(); 
    fill(c);
    // ellipse(0, 0, side, side);
    sphere(side); 
    popMatrix();
    //don’t let the boxes run away from the frame!
    if ((posX < side || posX >= width-side)||(posY < side || posY >= height-side))
    {
      velX = -0.99*velX;
      velY = -0.99*velY;
    }
    //slow circles down over time
    velX = .98*velX;
    velY = .98*velY;
  }
  void attract(Box b)
  {
    float d = dist(posX, posY, b.posX, b.posY); // calculate dist between boxes
    float diffX = b.posX - posX; // difference of position in X
    float diffY = b.posY - posY; // difference of position in Y
    velX += 0.08*(diffX / (sq(d))); // change velocity by a ratio between dist and pos difference
    velY += 0.08*(diffY / (sq(d)));
  }
  void collide(Box b)
  {
    float dis = dist(posX, posY, b.posX, b.posY);
    //if (dis <= (sqrt(sq(side) + sq(side/2)) + sqrt(sq(b.side/2) + sq(b.side/2)))) // for boxes
    float overlap = (side/2 + b.side/2) - dis;
    if (overlap>0)
    {
      float diffX = b.posX - posX; // difference of position in X
      float diffY = b.posY - posY; // difference of position in Y
      float unitX = diffX/dis;
      float unitY = diffY/dis;
      velX -= 0.1*unitX*overlap;
      velY -= 0.1*unitY*overlap;
    }
  }
  void jiggle()
  {
    velX = random(-1, 1);
    velY = random(-1, 1);
  }
}//class
//

1 Like

oh, that’s amazing! I see now where and what I was doing wrong!
Thank you for the help

1 Like

Yeah, especially you need to make the dist() check 3D

and add velZ to your code

also in jiggle and in the draw function (the one in the class) where it says:

//don’t let the boxes run away from the frame!

you need to make adjustments…

Remark

in draw() (the one outside the class) I changed

    for (int k = j+1; k < boxes.length; k++)

but I am not sure!!!

It looks very nice though!

Chrisir

1 Like

thank you! this was very helpful! I don’t know why, I was trying to change the class first, and being a beginner I did not know wheater the issues were logical or just bad writing

thank you a lot for your help

1 Like

why is it

 //check distances between all the other boxes and attracts and collide!
  for (int j = 0; j < boxes.length-1; j++)

I’m referring to the ‘-1’ bit.
Thank you

1 Like

that’s because of the for-loop with k (see above)

but I was wrong anyway, please change back to your :

//check distances between all the other boxes and attracts and collide!
for (int j = 0; j < boxes.length; j++)
{
for (int k = 0; k < boxes.length; k++)
{

Chrisir

Hey, thank you again for your help! I did change it to have all the z values, but it seems like the camera is cutting through the spheres. is there any way I can fix that? It seems like it is not bouncing back to what would it be the ‘front’
I have attached the code below

Box [] boxes;
int minSize = 20;
int maxSize = 50;
boolean collide = false;

// ----------------------------------------------------------------------
void setup() {
  size(500, 500, P3D);
  rectMode(CENTER);
  ellipseMode(CENTER);
  boxes = new Box[120];
  for (int i = 0; i < boxes.length; i++)
  {
    boxes[i] = new Box(
      random(maxSize, width-maxSize), random(maxSize, height-maxSize), random(maxSize, height-maxSize), 
      random(minSize, maxSize), 
      color(0, random(10, 255), random(10, 255)));
  }
}

// ----

void draw() {
  background(200);
  lights(); 

  fill(200, 10);
  rect(width/2, height/2, width+2, height+2);

  for (int i = 0; i < boxes.length; i++) {
    boxes[i].draw();
  }

  //check distances between all the other boxes and attracts and collide!
  for (int j = 0; j < boxes.length; j++)
  {
    for (int k = 0; k < boxes.length; k++)
    {
      if (j != k)
      {
        boxes[j].collide(boxes[k]);
        boxes[j].attract(boxes[k]);
      }
    }
  }
}

// -----------------------------------------------------------------------------

void mousePressed()
{
  for (int i = 0; i < boxes.length; i++)
  {
    boxes[i].jiggle();
  }
}

box class

class Box
{
  // step 1 = variables declaration
  int frame = 0;
  float posX;
  float posY;
  float posZ;

  float velX;
  float velY;
  float velZ; 
  float side;
  color c;

  // step 2 = constructor, initializes the class
  Box(float _posX, float _posY, float _posZ, 
    float _side, 
    color _c)
  {
    posX = _posX;
    posY = _posY;
    posZ= _posZ; 
    velX = random(-0.8, 0.8);
    velY = random(-0.8, 0.8);
    velZ = random(-0.8, 0.8);
    side = _side;
    c = _c;
  }

  // -------

  // step 3 = functions, functionality of the class
  void draw()
  {
    posX += velX;
    posY += velY;
    posZ += velZ;
    pushMatrix();
    translate(posX, posY, posZ);
    noStroke(); 
    fill(c);
    // ellipse(0, 0, side, side);
    sphere(side); 
    popMatrix();
    //don’t let the boxes run away from the frame!
    if ((posX < side || posX >= width-side)||(posY < side || posY >= height-side) || (posZ < side || posZ >=  width + height - side))
    {
      velX = -0.99*velX;
      velY = -0.99*velY;
      velZ = -0.99*velZ;
    }
    //slow circles down over time
    velX = .98*velX;
    velY = .98*velY;
    velZ = .98*velZ;
  }
  void attract(Box b)
  {
    float d = dist(posX, posY, posZ, b.posX, b.posY, b.posZ); // calculate dist between boxes
    float diffX = b.posX - posX; // difference of position in X
    float diffY = b.posY - posY; // difference of position in Y
    float diffZ = b.posZ - posZ; // difference of position in Z
    velX += 0.08*(diffX / (sq(d))); // change velocity by a ratio between dist and pos difference
    velY += 0.08*(diffY / (sq(d)));
    velZ += 0.08*(diffZ / (sq(d)));
  }
  void collide(Box b)
  {
    float dis = dist(posX, posY, posZ,  b.posX, b.posY, b.posZ);
    //if (dis <= (sqrt(sq(side) + sq(side/2)) + sqrt(sq(b.side/2) + sq(b.side/2)))) // for boxes
    float overlap = (side/2 + b.side/2) - dis;
    if (overlap>0)
    {
      float diffX = b.posX - posX; // difference of position in X
      float diffY = b.posY - posY; // difference of possition in Y
      float diffZ = b.posZ - posZ; // difference of position in Z
      float unitX = diffX/dis;
      float unitY = diffY/dis;
      float unitZ = diffZ/dis; 
      velX -= 0.1*unitX*overlap;
      velY -= 0.1*unitY*overlap;
      velZ -= 0.1*unitZ*overlap;
    }
  }
  void jiggle()
  {
    velX = random(-1, 1);
    velY = random(-1, 1);
    velZ = random(-1, 1);
  }
}

Thank you for all your help! It made 3d processing a lot more clearer! I just needed a bit of guidance

please this in setup()

  // avoid clipping (at camera): 
  // https : // 
  // forum.processing.org/two/discussion/4128/quick-q-how-close-is-too-close-why-when-do-3d-objects-disappear
  perspective(PI/3.0, (float) width/height, 1, 1000000);

aaah, amazing, thank you!

1 Like