Animated conveyor belt

Hi all,

so i have searched the net and cant find an example anywhere and a bit lost as where to start.

I want to loop through an array and each time create a bar plot.

each new bar (3d rect/box) is brought to the front of the screen whilst the previous bars stay on the screen, but will be behind the new one. i can rotate the visualization so that i will be able to see all bars. essentially it will be like having the 3d bars on a conveyor belt.

sorry i cant provide any code or example. Any help is much appreciated.

thanks

Start with a blank 3D sketch that does nothing.

void setup(){
  size(600,400,P3D);
}

void draw(){
  background(0);
}

This is, of course, very boring. But it works! If we add or change something to this and it stops working, we’ll know where the problem is.

Next, let’s add a box. Because we want the box to be in the middle of the screen, let’s move the origin to the middle and then draw out box.

void setup(){
  size(600,400,P3D);
}

void draw(){
  background(0);
  translate(width/2,height/2);
  box(10);
}

Great, we can see the box. But is it a box or a rect? Let’s use the mouse to move it about a bit, throw in some lights, and make the box bigger.

void setup(){
  size(600,400,P3D);
  noStroke();
}

void draw(){
  background(0);
  translate(width/2,height/2);
  lights();
  rotateY(map(mouseX, 0, width, -PI,PI));
  rotateX(map(mouseY, 0, height, -PI,PI));
  box(60);
}

So we can do 3D boxes. Great. Now we know we’re going to need more than one box, right? So it makes sense to turn our one box example into a one box example that uses a class.

So the next step is to write a class for a single object.

class SingleBar {
  float px, py, pz;
  float sx, sy, sz;
  color c;
  SingleBar(float ipx, float ipy, float ipz, float h) {
    px = ipx;
    py = ipy;
    pz = ipz;
    sx = sy = sz = 60;
    c = color( random(255), random(255), random(255) );
  } 
  void draw() {
    pushMatrix();
    translate(px, py, pz);
    fill(c);
    box(sx, sy, sz);
    popMatrix();
  }
}

SingleBar sb0 = new SingleBar(0, 0, 0, 100);

void setup() {
  size(600, 400, P3D);
  noStroke();
}

void draw() {
  background(0);
  translate(width/2, height/2);
  lights();
  rotateY(map(mouseX, 0, width, -PI, PI));
  rotateX(map(mouseY, 0, height, -PI, PI));
  sb0.draw();
}

Looks basically the same, right? Good!

1 Like

The point of writing a class is so that we can easily have many boxes. Like so:

class SingleBar {
  float px, py, pz;
  float sx, sy, sz;
  color c;
  SingleBar(float ipx, float ipy, float ipz, float h) {
    px = ipx;
    py = ipy;
    pz = ipz;
    sx = sy = sz = 60;
    c = color( random(255), random(255), random(255) );
  } 
  void draw() {
    pushMatrix();
    translate(px, py, pz);
    fill(c);
    box(sx, sy, sz);
    popMatrix();
  }
}

SingleBar[] sbs = new SingleBar[10];

void setup() {
  size(600, 400, P3D);
  noStroke();
  for( int i = 0; i< sbs.length; i++){
    sbs[i] = new SingleBar(0, 0, -60*i, 30*i);
  }
}

void draw() {
  background(0);
  translate(width/2, height/2);
  lights();
  rotateY(map(mouseX, 0, width, -PI, PI));
  //rotateX(map(mouseY, 0, height, -PI, PI));
  for( int i = 0; i< sbs.length; i++){
    sbs[i].draw();
  }
}
1 Like

A few more tweeks now. Change to using an ArrayList so we can push new objects easier. Remove the initial objects. Add a mousePressed function that puts in a new bar when the mouse is clicked. Adjust a few values for rotations and positions. Look! It’s almost like they’re scrolling now!

class SingleBar {
  float px, py, pz;
  float sx, sy, sz;
  color c;
  SingleBar(float ipx, float ipy, float ipz, float h) {
    px = ipx;
    py = ipy;
    pz = ipz;
    sx = sz = 60;
    sy = h;
    c = color( random(255), random(255), random(255) );
  } 
  void draw() {
    pushMatrix();
    translate(px, py, pz);
    translate(0,-sy/2,0);
    fill(c);
    box(sx, sy, sz);
    popMatrix();
  }
}

ArrayList<SingleBar> sbs = new ArrayList();//SingleBar[10];

void setup() {
  size(600, 400, P3D);
  noStroke();
}

void draw() {
  background(0);
  translate(width/2, height/2);
  lights();
  rotateY(-map(mouseX, 0, width, -HALF_PI, HALF_PI));
  //rotateX(map(mouseY, 0, height, -PI, PI));
  for( int i = 0; i< sbs.size(); i++){
    sbs.get(i).draw();
    translate(0,0,-60);
  }
}

void mousePressed(){
  sbs.add( 0, new SingleBar(0, 170, 0, random(60,300)) );
}
1 Like

More tweeks! Add an offset that is the amount that the boxes have shifted down by. If that offset is enough for a new box, add one and adjust the offset. Remove boxes if there are too many.

class SingleBar {
  float px, py, pz;
  float sx, sy, sz;
  color c;
  SingleBar(float ipx, float ipy, float ipz, float h) {
    px = ipx;
    py = ipy;
    pz = ipz;
    sx = sz = 60;
    sy = h;
    c = color( random(255), random(255), random(255) );
  } 
  void draw() {
    pushMatrix();
    translate(px, py, pz);
    translate(0,-sy/2,0);
    fill(c);
    box(sx, sy, sz);
    popMatrix();
  }
}

ArrayList<SingleBar> sbs = new ArrayList();//SingleBar[10];
int offset = 0;
final int OFFSET_SPEED = 6;
final int MAX_BARS = 300;

void setup() {
  size(600, 400, P3D);
  noStroke();
}

void draw() {
  if( sbs.size() > MAX_BARS ){
    sbs.remove(sbs.size()-1);
  }
  background(0);
  translate(width/2, height/2);
  lights();
  rotateY(-map(mouseX, 0, width, -HALF_PI, HALF_PI));
  //rotateX(map(mouseY, 0, height, -PI, PI));
  translate(0,0,-offset);
  for( int i = 0; i< sbs.size(); i++){
    sbs.get(i).draw();
    translate(0,0,-60);
  }
  if( offset > 60 ){
    offset %= 60;
    sbs.add( 0, new SingleBar(0, 170, 0, random(60,300)) );
  }
  offset+=OFFSET_SPEED;
}

Thank you - huge help and thanks for explaining the steps.

further to the above -i wanted to add a second column of bars, to highlight i did this by changing the code such that:

for( int i = 0; i< sbs2.size(); i++){
sbs2.get(i).draw();
pushMatrix();
translate(-100,0,0);
sbs2.get(i).draw();
popMatrix();
translate(0,0,-60);
}

if( offset > 60 ){
offset %= 60;
sbs2.add( 0, new SingleBar(0, 170, 0, random(60,300)) );
}
offset+=OFFSET_SPEED;
}…

However, i need the height of the second row of bars to be different to the other. ive tried numerous ways but think the code gets stuck in the loop when generating the first row.

do i have to crate a second variable, sbs2? if so how do i then add data to this?

Thanks again.

Jared

Alright, you got me. I cheated you a bit. While each of my bars has a full (x,y,z) position, it isn’t making use of it at all. The bars move because of a translate in the loop that is drawing them. This is not ideal. So the first thing to fix would be to have each bar store and use a real position in 3D space. I got that working, then I just made it so that more than one bar are added at once.

class SingleBar {
  float px, py, pz;
  float sx, sy, sz;
  color c;
  SingleBar(float ipx, float ipy, float ipz, float h) {
    px = ipx;
    py = ipy;
    pz = ipz;
    sx = sz = 60;
    sy = h;
    c = color( random(255), random(255), random(255) );
  } 
  void draw() {
    pushMatrix();
    translate(px, py, pz);
    translate(0,-sy/2,0);
    fill(c);
    box(sx, sy, sz);
    popMatrix();
  }
}

ArrayList<SingleBar> sbs = new ArrayList();//SingleBar[10];
int offset = 0;
final int OFFSET_SPEED = 6;
final int MAX_BARS = 300;
float atX = 0;
float atZ = 0;

void setup() {
  size(600, 400, P3D);
  noStroke();
}

void draw() {
  if( sbs.size() > MAX_BARS ){
    sbs.remove(sbs.size()-1);
  }
  background(0);
  translate(width/2, height/2);
  lights();
  rotateY(-map(mouseX, 0, width, -HALF_PI, HALF_PI));
  //rotateX(map(mouseY, 0, height, -PI, PI));
  translate(0,0,atZ-offset);
  for( int i = 0; i< sbs.size(); i++){
    sbs.get(i).draw();
  }
  if( offset > 60 ){
    atZ -= 60;
    offset %= 60;
    for( int i = -1; i < 2; i+=2){
      sbs.add( 0, new SingleBar(30*i, 170, -atZ, random(60,300)) );
    }
  }
  offset+=OFFSET_SPEED;
}

Hey - Thanks again - your help is much appreciated. i under estimated the time it would take me to pick this up.

I have slightly modified the code - i wanted to create a few more bar plots. In doing so, im not exactly sure what to call it, but the red image is not as clear as the blue, im not sure what is causing this. Also, the height of sbs3 is not as random as sbs2/1. Any ideas would be great - but again, thanks for all the help you have provided.

class SingleBar {
float px, py, pz;
float sx, sy, sz;
color c;
SingleBar(float ipx, float ipy, float ipz, float h) {
px = ipx;
py = ipy;
pz = ipz;
sx = sz = 60;
sy = h;
c = color( 0,0,255,20);
}
void draw() {
pushMatrix();
translate(px, py, pz);
translate(0,-sy/2,0);
fill©;
box(sx, sy, sz);
popMatrix();
}
}

class SingleBar2 {
float px, py, pz;
float sx, sy, sz;
color c;
SingleBar2(float ipx, float ipy, float ipz, float h) {
px = ipx;
py = ipy;
pz = ipz;
sx = sz = 60;
sy = h;
c = color( 255,0,0,20);
}
void draw() {
pushMatrix();
translate(px, py, pz);
translate(0,-sy/2,0);
fill©;
box(sx, sy, sz);
popMatrix();
}
}

class SingleBar3 {
float px, py, pz;
float sx, sy, sz;
color c;
SingleBar3(float ipx, float ipy, float ipz, float h) {
px = ipx;
py = ipy;
pz = ipz;
sx = sz = 30;
sy = h;
c = color( 255,255,255,200);
}
void draw() {
pushMatrix();
translate(px, py, pz);
translate(0,-sy/2,0);
fill©;
box(sx, sy, sz);
popMatrix();
}
}

ArrayList sbs = new ArrayList();//SingleBar[10];
ArrayList sbs2 = new ArrayList();//SingleBar[10];
ArrayList sbs3 = new ArrayList();//SingleBar[10];
int offset = 0;
final int OFFSET_SPEED = 6;
final int MAX_BARS = 300;
float atX = 0;
float atZ = 0;

void setup() {
size(1000, 1000, P3D);
noStroke();
}

void draw() {
background(0);

translate(width/2, height/2);
lights();
rotateY(-map(mouseX, 0, width, -HALF_PI, HALF_PI));
rotateX(map(mouseY, 0, height, -PI, PI));
translate(0,0,atZ-offset);

for( int i = 0; i< sbs.size(); i++){
sbs.get(i).draw();
}

pushMatrix();
translate(-200,0,0);
for( int j = 0; j< sbs2.size(); j++){
sbs2.get(j).draw();
}
popMatrix();

pushMatrix();
translate(-75,0,0);
for( int k = 0; k< sbs3.size(); k++){
sbs3.get(k).draw();
}
popMatrix();

if( offset > 60 ){
atZ -= 60;
offset %= 60;
for( int i = 1; i < 10; i+=2){
sbs.add( 0, new SingleBar(30*i, 170, -atZ, random(60,300)) );

 for( int j = 1; j < 10; j+=2){
  sbs2.add( 0, new SingleBar2(-30*j, 170, -atZ, random(60,300)) );
  
  for( int k = 1; k < 2; k+=2){
  sbs3.add( 0, new SingleBar3(-15*k, 170, -atZ, random(0,75)) );
 
  }
}
  } }

offset+=OFFSET_SPEED;
}

also re the above - everything has to be in that first if statement - anything past that does not run, if i take the offset% out it works, but then the visualisations obviously doesn’t run as smooth and isn’t aligned. im not sure why this is happening? Thanks in advance.

if( offset > 60 ){
atZ -= 60;
offset %= 60;
for( int i = 1; i < 10; i+=2){
sbs.add( 0, new SingleBar(30*i, 170, -atZ, random(60,300)) );

Please edit your posts, select your code, and hit the format button, which looks like this: </>

The beauty of a class is that you can use one class for all sort of similar objects. You don’t need a seperate class for white bars and blue bars and red bars. You just need one class for bars, and then that class can remember which type of bar it is. There is no need for three copies of basically the same class.

The beauty of having a dynamic data structure such as an ArrayList is that is can hold all the objects you’re working with. There is no need for three copies of the same data structure.

The beauty of formatted code is that it allows you to see what level of depth your loops are taking place in. There is no need to put a loop in a loop in a loop in this instance.

Consider this code, which is basically the same but runs smoothly (because there is a lot less looping), and vastly simplier (because there has been a 66% reduction in number of classes and ArrayLists):

color[] colors = { 
  color(0, 0, 255, 200), 
  color(255, 0, 0, 200), 
  color(255, 255, 255, 200) 
}; 
int[] bases = {
  60, 
  60, 
  30
};

class SingleBar {
  float px, py, pz;
  float sx, sy, sz;
  color c;
  SingleBar(float ipx, float ipy, float ipz, float h, int type) {
    px = ipx;
    py = ipy;
    pz = ipz;
    sx = sz = bases[type];
    sy = h;
    c = colors[type];
  }
  void draw() {
    pushMatrix();
    translate(px, py, pz);
    translate(0, -sy/2, 0);
    fill(c);
    box(sx, sy, sz);
    popMatrix();
  }
}

ArrayList<SingleBar> sbs = new ArrayList();

int offset = 0;
final int OFFSET_SPEED = 6;
final int MAX_BARS = 300;
float atX = 0;
float atZ = 0;

void setup() {
  size(1000, 1000, P3D);
  noStroke();
}

void draw() {
  background(0);

  translate(width/2, height/2);
  lights();
  rotateY(-map(mouseX, 0, width, -HALF_PI, HALF_PI));
  rotateX(map(mouseY, 0, height, -PI, PI));
  translate(0, 0, atZ-offset);
  
  for ( int i = 0; i< sbs.size(); i++) {
    sbs.get(i).draw();
  }
  
  if ( offset > 60 ) {
    atZ -= 60;
    offset %= 60;
    for ( int i = 0; i < 5; i++) {
      sbs.add( 0, new SingleBar(60*i+140, height/3, -atZ, random(60, 300), 0) );
      sbs.add( 0, new SingleBar(-60*i-140, height/3, -atZ, random(60, 300), 1) );
    }
    sbs.add( 0, new SingleBar(0, height/3, -atZ, random(0, 75), 2) );
  }
  offset+=OFFSET_SPEED;
}

I also had to brighten up the red and blue bar colors because they were driving me crazy being as dark as they were. I also re-centered things.

1 Like

Thank you very much… This was very helpful.

The bars are now running from left to right but i can adjust them with the arrows - so all good.

thanks again