draw a 3D cube with front and back transparent sides

Hello, I'm new to Processing and would like to draw a box with some sides being transparents. Is there a simplier solution than drawing each rect of the box one by one using beginShape() and vertex() ?

I wonder is there is an API call with 3D rects or quads as rect(startx, starty, startz, endx, endy, endz)

Answers

  • Answer ✓

    It is simple to write your own method that will take indexes to 4 points and draw a quad containing then. So, define all the corners (array of Pvectors?). Then call your method 6 times with different arguments.

  • Ho yeah that make sense ! (I often tend to over complexify ;-)

    Thanks ! I'll give a try and come back here if there something wrong

  • edited March 2018

    There are probably 100 ways to do it

    define all the corners (array of Pvectors?)

    For example instead of defining 8 corners of the cube manually with xyz, it would be enough to define the top left corner in front and width height and depth of the cube.

    Calculate the other 7 points then.

    Call the function then with 4 parameters plus one saying transparentYesNo as a boolean

  • edited March 2018

    Since rect() and quad() are both only 2D (other than point() and line()) in your own method you need to use beginShape() and vertex().

  • 3D operations and vertices usually give me headaches (because I know coding but I very very bad at maths ;-) )

    I did not yet started to code this stuff but I would define a class as

    Cube (float _x, float _y, float _z, float _h, float _w) {
        PShape face;
    
        x = _x;
        y = _y;
        z = _z;
        w = _w;
        h = _h;
        faces = new PShape[6];
        for (int i=0; i<6; i++) {
          faces[i] = createShape();
          faceColors[i] = new RGBA(255, 255, 255, 0);
        }
    
        face = faces[0];
        face.beginShape(); // Front face
        face.vertex(0, 0, 0);
        face.vertex(0, h, 0);
        face.vertex(w, h, 0);
        face.vertex(w, 0, 0);
        face.endShape(CLOSE);
    
        // Draw the 5 other faces
      }
    
      void setFaceColor(int index, RGBA _rgba) {
        // raise exception on wrong index
        faceColors[index] = _rgba;
      }
    
      void draw() {
        pushMatrix();
        translate(x, y, z);
        noStroke();
        for (int i=0; i<6; i++) {
          faces[i].fill(faceColors[i].r, faceColors[i].g, faceColors[i].b, faceColors[i].a);
          shape(faces[i]);
        }
        popMatrix();
      }
    }
    

    Does it seems a kinda 'OK' solution ?

  • edited March 2018

    nobody was speaking abut a class but never mind

    Remark 1

    Cube (float _x, float _y, float _z, float _h, float _w) {

    here float _d for your depth is missing (and d=_d;)

    Remark 2

    the line class Cube { is missing

    Remark 2 a)

    this PShape face; is PShape[] faces; ?

    Remark 3

    not sure what faceColors[i] = new RGBA(255, 255, 255, 0); is - just use color

    Remark 4

    also I was suggesting transparentYesNo as a boolean

    Here you could basically say

    if (faces[i].transparentYesNo) {
    
      faces[i].fill(faceColors[i].r, faceColors[i].g, faceColors[i].b, faceColors[i].a);
    
    } else {
    
    noFill(); 
    
    }
    
  • If I were you, I wouldn't work this way.

    I would start bottom up instead and have always a runnable code. I could run it throughout the process.

    So do setup and draw first. Then add a class with one shape. Test it (that's run it), if it's still running... add next step (otherwise debug it). Test it, if it's still running... and so on.

    If you write something like you do now in theoretical way, when you will run it the first time, there'll be couple of hard to find errors. In my approach, the error is just in the step you last added.

  • Thanks for the hints, I get rid of RGBA and used color instead, and added the depth param.

    The overall demo works great, it could be done better but at least it works ! But there is a last thing (for now) that I don't understand : I can use filled faces with colors, but how can I draw faces as wireframe ? The reason for this is : - most cubes will be wireframe - some cubes will have filled faces, except front and back

    Inside CubeFace.draw() the statements s.setStroke(255); s.setFill(false); produces nothing but black cubes.

    Here is the whole code try, that should run copied/pasted

    Any idea ?

    float cubeProf = 100;
    int CUBES = 50;
    Cube[] cubes;
    float z = 0;
    Alien alien;
    
    public void settings() {
      size(800, 600, P3D);
    }
    
    public void setup() {
      alien = new Alien(width / 2, height / 2, -3000);
      cubes = new Cube[CUBES];
      for (int i=0; i<CUBES; i++) {
        cubes[i] = new Cube(width / 2, height / 2 + random(0, 20  ), -(i * cubeProf), 100, 200, 100);
      }
    }
    
    public void draw() {
      Cube cube;
    
      background(0);
      pushMatrix();
    
      z -= 10;
      lights();
      spotLight(51, 102, 126, 0, 0, 0, 0, 0, -1, PI/2, 2);
      for (int i=0; i<CUBES; i++) {
        cube = cubes[i];
        camera(width/2.0, cube.y, (height/2.0) / tan(PI*30.0 / 180.0)+z, width/2.0, height / 2, z - 1000, 0, 1, 0);
        cube.draw();
        if (z < cube.z - 400) {
          cube.z = cube.z - cubeProf * CUBES;
        }
      }  
      alien.draw();
      popMatrix();
    }
    
    class CubeFace {
      public Boolean visible = true;
      public color c;
      public PShape s;
    
      CubeFace() {
        s = createShape();
        c = color(255, 0, 255, 150);
      }
    
      void begin() {
        s.beginShape();
      }
    
      void vertex(int v1, int v2, int v3) {
        s.vertex(v1, v2, v3);
      }
    
      void end() {
        s.endShape(CLOSE);
      }
    
      void draw() {
        if (visible) {
          s.setStrokeWeight(1);
          s.setStroke(255);
          s.setFill(false);
          //s.setFill(color(255, 0, 0)); //(c.r, c.g, c.b, c.a);      
          shape(s);
        }
      }
    }
    
    class Cube {
    
      static final int FRONT = 0;
      static final int BACK = 1;
      static final int LEFT = 2;
      static final int RIGHT = 3;
      static final int BOTTOM = 4;
      static final int TOP = 5;
    
      public float x, y, z;
      int w, h, d;
      CubeFace[] faces; 
    
      Cube (float _x, float _y, float _z, int _h, int _w, int _d) {
        CubeFace face;
    
        x = _x;
        y = _y;
        z = _z;
        w = _w;
        h = _h;
        d = _d;
    
        faces = new CubeFace[6];
        for (int i=0; i<6; i++) {
          faces[i] = new CubeFace();
        }
    
        face = faces[FRONT];
        face.begin(); // Front face
        face.vertex(0, 0, 0);
        face.vertex(0, h, 0);
        face.vertex(w, h, 0);
        face.vertex(w, 0, 0);
        face.visible = false;
        face.end();
    
        face = faces[BACK];
        face.begin(); // Back face
        face.vertex(0, 0, d);
        face.vertex(0, h, d);
        face.vertex(w, h, d);
        face.vertex(w, 0, d);
        face.visible = false;
        face.end();
    
        face = faces[LEFT];
        face.begin(); // Left face
        face.vertex(0, 0, 0);
        face.vertex(0, h, 0);
        face.vertex(0, h, d);
        face.vertex(0, 0, d);
        face.end();
    
        face = faces[RIGHT];
        face.begin(); // Right face
        face.vertex(w, 0, 0);
        face.vertex(w, h, 0);
        face.vertex(w, h, d);
        face.vertex(w, 0, d);
        face.end();
    
        face = faces[BOTTOM];
        face.begin(); // Bottom face
        face.vertex(0, 0, 0);
        face.vertex(0, 0, d);
        face.vertex(w, 0, d);
        face.vertex(w, 0, 0);
        face.end();
    
        face = faces[TOP];
        face.begin(); // Top face
        face.vertex(0, h, 0);
        face.vertex(0, h, d);
        face.vertex(w, h, d);
        face.vertex(w, h, 0);
        face.end();
      }
    
      void setFaceColor(int index, int r, int g, int b, int a) {
        // should catch exception on wrong index
        faces[index].c = color(r, g, b, a);
      }
    
      void draw() {
        pushMatrix();
        translate(x - w / 2, y - h / 2, z);
        //noStroke();
        for (int i=0; i<6; i++) {
          faces[i].draw();
        }
        popMatrix();
      }
    }
    
    class Alien {
      float x, y, z;
    
      Alien (float _x, float _y, float _z) {
        x = _x;
        y = _y;
        z = _z;
        println("Alien z at " + z);
      }
    
      void draw() {
        pushMatrix();
        translate(x, y, z);
        fill(200);
        noStroke();
        //stroke(255);
        sphere(20);
        popMatrix();
        z += 3;
      }
    }
    
  • edited March 2018

    strokeWeight() can only be called between beginShape() and endShape() stroke() can only be called between beginShape() and endShape()

    visible is saying whether it's filled or wireframe

    I also set s.stroke(255); before vertex class CubeFace

    instead of void vertex better call it void setVertex - too confusing

    also new in class CubeFace, in the constructor

        if (random(100)>40)
          visible = false;
    

    and changes in draw() in class CubeFace

    float cubeProf = 100;
    int CUBES = 50;
    Cube[] cubes;
    
    float z = 0;
    Alien alien;
    
    public void settings() {
      size(800, 600, P3D);
    }
    
    public void setup() {
      alien = new Alien(width / 2, height / 2, -3000);
    
      cubes = new Cube[CUBES];
      for (int i=0; i<CUBES; i++) {
        cubes[i] = new Cube(width / 2, height / 2 + random(0, 0), -(i * cubeProf), 100, 200, 100);
      }
    }
    
    public void draw() {
    
      Cube cube;
    
      background(0);
    
      pushMatrix();
    
      z -= 10;
      lights();
      spotLight(51, 102, 126, 0, 0, 0, 0, 0, -1, PI/2, 2);
    
      for (int i=0; i<CUBES; i++) {
    
        cube = cubes[i];
        camera(width/2.0, cube.y, (height/2.0) / tan(PI*30.0 / 180.0)+z, width/2.0, height / 2, z - 1000, 0, 1, 0);
        cube.draw();
        if (z < cube.z - 400) {
          cube.z = cube.z - cubeProf * CUBES;
        }
      }  
      // alien.draw();
      popMatrix();
    }
    
    class CubeFace {
      public Boolean visible = true;
      public color c;
      public PShape s;
    
      CubeFace() {
        s = createShape();
        c = color(255, 0, 255, 150);
    
        if (random(100)>40)
          visible = false;
      }
    
      void begin() {
        s.beginShape();
      }
    
      void vertex(int v1, int v2, int v3) {
        s.stroke(255);
        s.vertex(v1, v2, v3);
      }
    
      void end() {
        s.endShape(CLOSE);
      }
    
      void draw() {
        if (visible) {
          s.setStrokeWeight(1);
          s.setStroke(255);
          //  s.setFill(false);
          s.setFill(color(255, 0, 0)); //(c.r, c.g, c.b, c.a);      
          shape(s);
        } else {
          //s.strokeWeight(2);
          s.setFill(false);
          s.setStroke(true);
          //s.setStroke(255);
          //s.stroke(true);
          s.stroke(255);
    
          stroke(255);
          shape(s);
        }
      }
      //
    }//class
    
    class Cube {
    
      static final int FRONT = 0;
      static final int BACK = 1;
      static final int LEFT = 2;
      static final int RIGHT = 3;
      static final int BOTTOM = 4;
      static final int TOP = 5;
    
      public float x, y, z;
      int w, h, d;
    
      CubeFace[] faces; 
    
      Cube (float _x, float _y, float _z, 
        int _h, 
        int _w, 
        int _d) {
    
        CubeFace face;
    
        x = _x;
        y = _y;
        z = _z;
    
        w = _w;
        h = _h;
        d = _d;
    
        faces = new CubeFace[6];
        for (int i=0; i<6; i++) {
          faces[i] = new CubeFace();
        }
    
        face = faces[FRONT];
        face.begin(); // Front face
        face.vertex(0, 0, 0);
        face.vertex(0, h, 0);
        face.vertex(w, h, 0);
        face.vertex(w, 0, 0);
        face.visible = false;
        face.end();
    
        face = faces[BACK];
        face.begin(); // Back face
        face.vertex(0, 0, d);
        face.vertex(0, h, d);
        face.vertex(w, h, d);
        face.vertex(w, 0, d);
        face.visible = false;
        face.end();
    
        face = faces[LEFT];
        face.begin(); // Left face
        face.vertex(0, 0, 0);
        face.vertex(0, h, 0);
        face.vertex(0, h, d);
        face.vertex(0, 0, d);
        face.end();
    
        face = faces[RIGHT];
        face.begin(); // Right face
        face.vertex(w, 0, 0);
        face.vertex(w, h, 0);
        face.vertex(w, h, d);
        face.vertex(w, 0, d);
        face.end();
    
        face = faces[BOTTOM];
        face.begin(); // Bottom face
        face.vertex(0, 0, 0);
        face.vertex(0, 0, d);
        face.vertex(w, 0, d);
        face.vertex(w, 0, 0);
        face.end();
    
        face = faces[TOP];
        face.begin(); // Top face
        face.vertex(0, h, 0);
        face.vertex(0, h, d);
        face.vertex(w, h, d);
        face.vertex(w, h, 0);
        face.end();
      }
    
      void setFaceColor(int index, int r, int g, int b, int a) {
        // should catch exception on wrong index
        faces[index].c = color(r, g, b, a);
      }
    
      void draw() {
        pushMatrix();
        translate(x - w / 2, y - h / 2, z);
        //noStroke();
        for (int i=0; i<6; i++) {
          faces[i].draw();
        }
        popMatrix();
      }
    }
    
    class Alien {
      float x, y, z;
    
      Alien (float _x, float _y, float _z) {
        x = _x;
        y = _y;
        z = _z;
        println("Alien z at " + z);
      }
    
      void draw() {
        pushMatrix();
        translate(x, y, z);
        fill(200);
        noStroke();
        //stroke(255);
        sphere(20);
        popMatrix();
        z += 3;
      }
    }//class 
    //
    
  • edited March 2018

    there is flickering right at the bottom of the screen

    it's caused here I think:

        if (z < cube.z - 400) {
             cube.z = cube.z - cubeProf * CUBES;
        }
    

    maybe you can fix that

  • In fact I wanted to have "some" tunnel's cubes colored/filled and I ended with a poor man's solution : fallback to box() when no fill is needed at all.

    And yes, you're right - The flickering is annoying - it might be cause by having too many cubes in the far Z. I'll tweak and see ;-) The result is pretty fun :-)

    I dunno if it's a common/tolerated practice to post revised code in comments but here it is.

    float cubeProf = 100;
    int CUBES = 50;
    Cube[] cubes;
    float z = 0;
    Alien alien;
    
    public void settings() {
      size(800, 600, P3D);
    }
    
    public void setup() {
      alien = new Alien(width / 2, height / 2, -3000);
      cubes = new Cube[CUBES];
      for (int i=0; i<CUBES; i++) {
        cubes[i] = new Cube(width / 2, height / 2 + random(0, 20  ), -(i * cubeProf), 100, 300, 100);
      }
    }
    
    public void draw() {
      Cube cube;
    
      background(0);
      pushMatrix();
    
      z -= 10;
      lights();
      spotLight(51, 102, 126, 0, 0, 0, 0, 0, -1, PI/2, 2);
      for (int i=0; i<CUBES; i++) {
        cube = cubes[i];
        camera(width/2.0, cube.y, (height/2.0) / tan(PI*30.0 / 180.0)+z, width/2.0, height / 2, z - 1000, 0, 1, 0);
        cube.draw();
        if (z < cube.z - 400) {
          cube.z = cube.z - cubeProf * CUBES;
        }
      }  
      alien.draw();
      popMatrix();
    }
    
    class CubeFace {
      public Boolean visible = true;
      public color c;
      public PShape s;
    
      CubeFace(color _c) {
        s = createShape();
        c = _c;
      }
    
      void begin() {
        s.beginShape();
      }
    
      void vertex(int v1, int v2, int v3) {
        s.vertex(v1, v2, v3);
      }
    
      void end() {
        s.endShape(CLOSE);
      }
    
      void draw() {    
        if (visible) {
          s.setStrokeWeight(1);
          s.setStroke(255);
          s.setFill(c);
          shape(s);
        }
      }
    }
    
    class Cube {
    
      static final int FRONT = 0;
      static final int BACK = 1;
      static final int LEFT = 2;
      static final int RIGHT = 3;
      static final int BOTTOM = 4;
      static final int TOP = 5;
    
      public float x, y, z;
      int w, h, d;
      CubeFace[] faces; 
      Boolean isWireFrame;
    
      Cube (float _x, float _y, float _z, int _h, int _w, int _d) {
        x = _x;
        y = _y;
        z = _z;
        w = _w;
        h = _h;
        d = _d;
    
        isWireFrame = random(1) >= 0.2 ? true : false;
        CubeFace face;    
        color c = color(random(255), random(255), random(255), 255);    
        faces = new CubeFace[6];
        for (int i=0; i<6; i++) {
          faces[i] = new CubeFace(c);
        }
    
        face = faces[FRONT];
        face.begin(); // Front face
        face.vertex(0, 0, 0);
        face.vertex(0, h, 0);
        face.vertex(w, h, 0);
        face.vertex(w, 0, 0);
        face.visible = false;
        face.end();
    
        face = faces[BACK];
        face.begin(); // Back face
        face.vertex(0, 0, d);
        face.vertex(0, h, d);
        face.vertex(w, h, d);
        face.vertex(w, 0, d);
        face.visible = false;
        face.end();
    
        face = faces[LEFT];
        face.begin(); // Left face
        face.vertex(0, 0, 0);
        face.vertex(0, h, 0);
        face.vertex(0, h, d);
        face.vertex(0, 0, d);
        face.end();
    
        face = faces[RIGHT];
        face.begin(); // Right face
        face.vertex(w, 0, 0);
        face.vertex(w, h, 0);
        face.vertex(w, h, d);
        face.vertex(w, 0, d);
        face.end();
    
        face = faces[BOTTOM];
        face.begin(); // Bottom face
        face.vertex(0, 0, 0);
        face.vertex(0, 0, d);
        face.vertex(w, 0, d);
        face.vertex(w, 0, 0);
        face.end();
    
        face = faces[TOP];
        face.begin(); // Top face
        face.vertex(0, h, 0);
        face.vertex(0, h, d);
        face.vertex(w, h, d);
        face.vertex(w, h, 0);
        face.end();
      }
    
      void setFaceColor(int index, int r, int g, int b, int a) {
        // should catch exception on wrong index
        faces[index].c = color(r, g, b, a);
      }
    
      void draw() {
        pushMatrix();
        if (isWireFrame) {
          stroke(255);
          noFill();
          translate(x, y, z);
          box(w, h, d);
        } else {
          translate(x - w / 2, y - h / 2, z);
          for (int i=0; i<6; i++) {
            faces[i].draw();
          }
        }
        popMatrix();
      }
    }
    
    class Alien {
      float x, y, z;
    
      Alien (float _x, float _y, float _z) {
        x = _x;
        y = _y;
        z = _z;
        println("Alien z at " + z);
      }
    
      void draw() {
        pushMatrix();
        translate(x, y, z);
        fill(200);
        noStroke();
        sphere(20);
        popMatrix();
        z += 3;
      }
    }
    
  • yeah, but with my solution you have a partial filled, partial non-filled cube. You don't have that

  • @Paganoni

    I dunno if it's a common/tolerated practice to post revised code in comments

    Yes, that is fine. It is often preferred to editing the original code, as then comments and the statement of the problem all still make sense.

Sign In or Register to comment.