How can I create a sphere (or other shape) with cubes? (3D)

Hi everyone I am new generally in coding ( not only in Processing) so I need your help if you can. What I want to do is to design 10 types of cubes with different color shades ( from white to totally black) without having the same dimension and with those cubes to fill (create) a 3D shape for instance a sphere or a cone. I have seen some tutorials on Youtube and I found the below simple code in which I tried to change in order to do what I want, but guess what, I did nothing

size(400,300);
background(0);
strokeWeight(2);
stroke(255);
fill(127);

for (int y = 0; y < height; y = y+20) {
for (int x = 0; x < width; x = x+20){
fill(random(255));

rect(x, y, 20, 20);

}
}

You need a 3D Sketch when I understand you correctly.

read P3D \ Processing.org

I’ll be back in a second with an example.

Hey, and welcome to the forum!

Great to have you here!

Warm regards,

Chrisir


Sketch

Click mouse to enter a new cube. You can move the last cube in 3D with cursor keys and p and “l” (“L”). You need to add a size changer (e.g. + and - ) and add automatic color from white to black.
You could save the cube position on Hard Drive (hard to do) or make a screen shot (command save() associated with key ‘s’ for example).

  • So you can make a sphere or a cone from cubes. I wouldn’t know how to do this automatically. Well, we could try.
// constants
final color BLACK  = color(0); 
final color WHITE  = color(255);

final color RED    = color(255, 0, 0); 
final color GREEN  = color(0, 255, 0);
final color BLUE   = color(0, 0, 255);

final color YELLOW = (#FFF80A); 

// the cubes 
ArrayList<Cube> cubes = new ArrayList();

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

void setup() {
  size( 1200, 900, P3D ); // 3D Mode 

  //text 
  textMode(SHAPE);

  // add one cube - delete this
  Cube newCube = new Cube(); 
  newCube.pos=new PVector(60, 310, -60);
  newCube.colorForCube = color ( RED ) ;   
  cubes.add(newCube); 
  //
}//func

void draw() {

  background(0);

  // 3D part ---
  lights();

  for (Cube currentCube : cubes) {
    currentCube.display();
  }

  // 2D part --- 
  showMessages();
}//func 

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

void showMessages() {
  // 2D part --- 

  // prepare for 2D
  hint(DISABLE_DEPTH_TEST);
  camera();
  noLights();

  // 2D code 
  fill(255); 
  text("Place cubes with Mouse. Move last cube in Z with Cursor up and down (and left/right and p/l)", 17, 17);
  if (cubes.size()>0) {
    text("Last cube x,y,z: "
      +cubes.get(cubes.size()-1).pos.x
      +","
      +cubes.get(cubes.size()-1).pos.y
      +","
      +cubes.get(cubes.size()-1).pos.z, 17, 35);
  }

  // reset for 3D again 
  hint(ENABLE_DEPTH_TEST);
}

// ------------------------------------------------------------------------
// Inputs 

void mousePressed() {
  // add cube at mouse pos with z = 0.
  addCube(new PVector(mouseX, mouseY, 0));
}

void keyPressed() {

  if (key==CODED) {

    // CODED

    switch(keyCode) {
    case UP:
      cubes.get(cubes.size()-1).pos.z-=10; 
      break; 

    case DOWN:
      cubes.get(cubes.size()-1).pos.z += 10; 
      break;

    case LEFT:
      cubes.get(cubes.size()-1).pos.x-=10; 
      break; 

    case RIGHT:
      cubes.get(cubes.size()-1).pos.x += 10; 
      break;
    }//switch 1
  } 
  //-------

  else {

    // not CODED

    switch(key) {
    case 'p':
      cubes.get(cubes.size()-1).pos.y-=10; 
      break; 

    case 'l':
      cubes.get(cubes.size()-1).pos.y += 10; 
      break;
    }//switch 2
  } // else
}//func 

// ------------------------------------------------------------------------
// Tools

void addCube(PVector pos_) {

  Cube newCube = new Cube(); 
  newCube.pos=pos_.copy();
  newCube.colorForCube = color ( RED ) ;   

  cubes.add(newCube); 
  //
} // func

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

class Cube {

  // one cube

  PVector pos; 
  color colorForCube; 

  void display() {
    pushMatrix();
    stroke(111);
    fill(colorForCube);
    translate(pos.x, pos.y, pos.z);
    box(60);
    popMatrix();
  }  
  //
}//class
//

You can use Pythagoras to test whether a 3d position is inside a 3d field. I think there is no definition for dist (x,y,z,x2,y2,z2) but you can apply pythagoras twice:

boolean insideSphere(
    float cx,  float cy, float cz,   /*center*/
    float radius,                           /*radius*/
    float px, float py, float pz   /*test point*/
      )
{
    float x=px-cx;
    float y=py-cy;
    float cz=pz-cz;
    float R=radius*radius;
    if (R<(x*x+y*y+z*z)){
        return TRUE;
    }
    return FALSE;
}

Please note I left maths when I was 15 years old. So maybe there is an easier way.

thanks!

A few minor typos, check this:

boolean insideSphere(
  float cx, float cy, float cz, /*center*/
  float radius, /*radius*/
  float px, float py, float pz   /*test point*/
  )
{
  float x=px-cx;
  float y=py-cy;
  float z=pz-cz;
  float R=radius*radius;
  if ((x*x+y*y+z*z) < R) {
    return true;
  }
  return false;
}

can be shortened to

boolean insideSphere (
  float cx, float cy, float cz, // center
  float radius, // radius
  float px, float py, float pz    // test point
  ) {
  PVector center = new PVector(cx, cy, cz);
  PVector testPoint = new PVector(px, py, pz);
  return center.dist(testPoint) < radius;
}

Full code with peasy cam (and some PVector stuff):





import peasy.*;

PeasyCam peasyCam;

PVector center;  // center 
PVector testPoint=new PVector();  // test point

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

void setup() {
  size(1400, 940, P3D);
  peasyCam = new PeasyCam(this, 1000);
  center = new PVector(0, 0, 0);
}

void draw() {
  background(255);
  lights();
  fill(255, 0, 0);

  int radiusSphere=200; 
  for (int x=-radiusSphere; x<radiusSphere; x+=22) {
    for (int y=-radiusSphere; y<radiusSphere; y+=22) {
      for (int z=-radiusSphere; z<radiusSphere; z+=22) {

        if (insideSphere(radiusSphere/2, 
          x, y, z)) {
          pushMatrix();
          translate(x, y, z); 
          box(22-1); 
          popMatrix();
        }
      }
    }
  }

  peasyCam.beginHUD();
  noLights();
  fill(0);
  text("Use PeasyCam by dragging the mouse, pan etc. ", 12, 12); 
  peasyCam.endHUD();
}

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

boolean insideSphere ( float radius, // radius
  float px, float py, float pz    // test point
  ) {
  testPoint.set(px, py, pz);
  return 
    center.dist(testPoint) < radius;
}
//

Hi! I detected my typo but I was too lazy to make a last edit to my post.

Thank you for the example with peasycam. I find wery frustrating the control of the camera. PeasyCam makes it easier!

But still, the cubes are all the same in my example (and far too many)

That’s not really the idea

When the initial cubes have a fixed and individual size (and color) we need an array (or ArrayList) and a class Cube and some kind of optimization algorithm to pack them in a good way (when you want to do it automatically by an algorithm) - hard !

It’s unclear whether you mean

  • cubes (all six faces have the same size) of different sizes or
  • also cuboids (six faces of 3 different sizes) of different sizes.

Do you want to arrange the cubes or cuboids with or without overlapping? Is it really in 3D? Do you want to make the arrangement

  • automatically or
  • by user input, with mouse or keyboard?

Chrisir

P.S.

here is a similar example

A cube of 3x3x3 has to be filled with pieces