How to extrude a 2D custom shape into 3D

Hi everyone,

I am new to processing and I am trying to extrude a 2D shape into 3D. The figure that I want to draw is made up of curves, beziers, and ellipses.

Is there any method, technique or library that I can use to extrude my custom 2D shape into 3D. I want to be able to give my 2D shape some depth and turn it into 3D.

The figure that I am trying to extrude into 3D is similar to this one.

void setup() {

  size(600, 450, P3D);

  background(255);

}

void draw() {

  stroke(0);
  strokeWeight(1.5);
  noFill();

  int x = 300;
  int y = 220;

  bezier(x + 50, y - 50, x + 30, y - 30, x + 30, y + 30, x + 50, y + 50);
  bezier(x + 40, y - 40, x + 20, y - 20, x + 20, y + 20, x + 40, y + 40);

  bezier(x - 50, y - 50, x - 30, y - 30, x - 30, y + 30, x - 50, y + 50);
  bezier(x - 40, y - 40, x - 20, y - 20, x - 20, y + 20, x - 40, y + 40);

  bezier(x - 50, y - 50, x - 30, y - 30, x + 30, y - 30, x + 50, y - 50);
  bezier(x - 40, y - 40, x - 20, y - 20, x + 20, y - 20, x + 40, y - 40);

  bezier(x - 50, y + 50, x - 30, y + 30, x + 30, y + 30, x + 50, y + 50);
  bezier(x - 40, y + 40, x - 20, y + 20, x + 20, y + 20, x + 40, y + 40);


}
Tagged:

Answers

  • If you want to do your own extrusion, in general, you want:

    1. a base layer of points
    2. an identical extruded layer of points, separated by a z-offset
    3. a set of connections between each point in the extruded layer and each point in the base.

    So for a list of points:

    (ax, ay, 0) (bx, by, 0) (cx, cy, 0) etc.

    You also want to draw everything again and add a z:

    (ax, ay, az) (bx, by, bz) (cx, cy, cz) etc.

    ...and then connect the two:

    (ax, ay, 0) -> (ax, ay, az)
    (bx, by, 0) -> (bx, by, bz)

  • // see https : // forum.processing.org/two/discussion/26185/how-to-extrude-a-2d-custom-shape-into-3d#latest
    
    import peasy.*;
    import peasy.org.apache.commons.math.*;
    import peasy.org.apache.commons.math.geometry.*;
    
    PeasyCam cam;
    
    // distance between two layers / levels 
    float differenceInZ = 25.0;
    
    void setup() {
    
      size(600, 450, P3D);
    
      background(255);
    
      cam = new PeasyCam(this, 300);
    }
    
    void draw() {
      background(255);
      lights();
    
      strokeWeight(1.5);
      noFill();
    
      float x = 300.0;
      float y = 220.0;
      float z = 200.0; 
    
      // to move into camera center 
      translate(-300, -220);
    
      // 1. standard level   *******************************************
    
      // red
      stroke(255, 0, 0);
    
      bezier(x + 50, y - 50, z, x + 30, y - 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
      bezier(x + 40, y - 40, z, x + 20, y - 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
    
      bezier(x - 50, y - 50, z, x - 30, y - 30, z, x - 30, y + 30, z, x - 50, y + 50, z);
      bezier(x - 40, y - 40, z, x - 20, y - 20, z, x - 20, y + 20, z, x - 40, y + 40, z);
    
      bezier(x - 50, y - 50, z, x - 30, y - 30, z, x + 30, y - 30, z, x + 50, y - 50, z);
      bezier(x - 40, y - 40, z, x - 20, y - 20, z, x + 20, y - 20, z, x + 40, y - 40, z);
    
      bezier(x - 50, y + 50, z, x - 30, y + 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
      bezier(x - 40, y + 40, z, x - 20, y + 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
    
      // ----------------------
    
      if (true) {
    
        // 2. connecting standard level and next level   *******************************************
    
        // green 
        stroke(0, 255, 0);
    
        connectAnchorPoints(x + 50, y - 50, z, x + 30, y - 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
        connectAnchorPoints(x + 40, y - 40, z, x + 20, y - 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
    
        connectAnchorPoints(x - 50, y - 50, z, x - 30, y - 30, z, x - 30, y + 30, z, x - 50, y + 50, z);
        connectAnchorPoints(x - 40, y - 40, z, x - 20, y - 20, z, x - 20, y + 20, z, x - 40, y + 40, z);
    
        connectAnchorPoints(x - 50, y - 50, z, x - 30, y - 30, z, x + 30, y - 30, z, x + 50, y - 50, z);
        connectAnchorPoints(x - 40, y - 40, z, x - 20, y - 20, z, x + 20, y - 20, z, x + 40, y - 40, z);
    
        connectAnchorPoints(x - 50, y + 50, z, x - 30, y + 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
        connectAnchorPoints(x - 40, y + 40, z, x - 20, y + 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
      }
      // ----------------------
    
      // 3. next level  *******************************************
    
      z+=differenceInZ; // !!!!!!
      // blue 
      stroke(0, 0, 255);
    
      bezier(x + 50, y - 50, z, x + 30, y - 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
      bezier(x + 40, y - 40, z, x + 20, y - 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
    
      bezier(x - 50, y - 50, z, x - 30, y - 30, z, x - 30, y + 30, z, x - 50, y + 50, z);
      bezier(x - 40, y - 40, z, x - 20, y - 20, z, x - 20, y + 20, z, x - 40, y + 40, z);
    
      bezier(x - 50, y - 50, z, x - 30, y - 30, z, x + 30, y - 30, z, x + 50, y - 50, z);
      bezier(x - 40, y - 40, z, x - 20, y - 20, z, x + 20, y - 20, z, x + 40, y - 40, z);
    
      bezier(x - 50, y + 50, z, x - 30, y + 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
      bezier(x - 40, y + 40, z, x - 20, y + 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
    
      // show text upper left corner 
      cam.beginHUD();
      noLights();
      fill(255, 0, 0); // red 
      text("Use mouse to rotate: Click, hold and move mouse; drag with center button (PeasyCam)", 17, 17);
      cam.endHUD();
    }
    
    void connectAnchorPoints(  float... arrayOfParameters ) {
    
      // using optional variables in a function: arrayOfParameters
    
      // see https : // forum.processing.org/two/discussion/11222/how-to-define-optional-variables-in-a-function
    
      // connect two layers with straight 3D lines of length differenceInZ
    
      // (takes all points (like bezier) but uses only the first and last three, see reference for bezier)
    
      int i=0;
      // using the 3D version of line here 
      line(arrayOfParameters[i], arrayOfParameters[i+1], arrayOfParameters[i+2], 
        arrayOfParameters[i], arrayOfParameters[i+1], arrayOfParameters[i+2]+differenceInZ);
    
      i=9;
      // using the 3D version of line here 
      line(arrayOfParameters[i], arrayOfParameters[i+1], arrayOfParameters[i+2], 
        arrayOfParameters[i], arrayOfParameters[i+1], arrayOfParameters[i+2]+differenceInZ);
    }//func
    // 
    
  • edited February 2018

    To move from @Chrisir's concrete example to a more general extrude solution:

    1. You can draw your 2D layer as a PShape. This could be anything made out of a vertex list.

    2. Actually, because copying PShapes can be complex / impossible, create a constructor to build your PShape, and have it take a z argument.

    3. Now the general part. You can add multiple child PShapes to a PShape (GROUP) -- so create a group PShape, call your constructor twice and add two children (base layer and extruded layer) to your GROUP shape. You code is written so that anything could go in here -- a stop sign, Pacman, whatever. Put it in and you get two of them, separated by Z height.
    4. Create a third child Pshape to wrap the extruded sides. Loop through the vertices of the two shapes (which are identical length lists, so just iterate up to the length of either), use the index to look up a point in each, and draw a line between those points. If you want to get fancy, this could be a QUAD_STRIP. Your assumption about whether the layers are OPEN or CLOSED matters to what you do at the end of the strip.
  • edited February 2018

    i tried to work further on this but it's very confusing

    I tried using bezierVertex() together with beginShape() but then the points must be in a certain order and apparently they were not

    It was a mess

  • at least I have done one side wall filled in red

    here is the mess (my mistake, not yours!)

    But I think, bezierVertex() is so complicate to work with, one should write a class to be a wrapper for it basically. There is now so much repetition in my code

    // see https : // forum.processing.org/two/discussion/26185/how-to-extrude-a-2d-custom-shape-into-3d#latest
    
    import peasy.*;
    import peasy.org.apache.commons.math.*;
    import peasy.org.apache.commons.math.geometry.*;
    
    PeasyCam cam;
    
    // distance between two layers / levels 
    float differenceInZ = 25.0;
    
    void setup() {
    
      size(600, 450, P3D);
    
      background(255);
    
      cam = new PeasyCam(this, 300);
    }
    
    void draw() {
      background(255);
      lights();
    
      strokeWeight(1.5);
      noFill();
    
      float x = 300.0;
      float y = 220.0;
      float z = 200.0; 
    
      // to move into camera center 
      translate(-300, -220);
    
      //  standard level   *******************************************
    
      if (true) {
        beginShape();
    
        vertex(x + 50, y - 50, z); 
        bezierVertex( x + 30, y - 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
        bezier2(x + 40, y - 40, z, x + 20, y - 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
    
        bezier2(x - 50, y - 50, z, x - 30, y - 30, z, x - 30, y + 30, z, x - 50, y + 50, z);
        bezier2(x - 40, y - 40, z, x - 20, y - 20, z, x - 20, y + 20, z, x - 40, y + 40, z);
    
        bezier2(x - 50, y - 50, z, x - 30, y - 30, z, x + 30, y - 30, z, x + 50, y - 50, z);
        bezier2(x - 40, y - 40, z, x - 20, y - 20, z, x + 20, y - 20, z, x + 40, y - 40, z);
    
        bezier2(x - 50, y + 50, z, x - 30, y + 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
        bezier2(x - 40, y + 40, z, x - 20, y + 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
    
    
        endShape();
      }
    
      // side RED  *******************************************
    
      // red
      stroke(255, 0, 0);
      fill(255, 0, 0);
    
      beginShape();
    
      // The first time bezierVertex() is used within a beginShape() call, it must be prefaced with a call to vertex() to set the first anchor point.
      vertex(x + 50, y - 50, z);
    
      // bezierVertex requires: 3 coords control, 3 coords control, 3 coords anchor 
      bezierVertex( x + 30, y - 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
    
      z+=differenceInZ; // !!!!!!
    
      vertex( x + 50, y + 50, z);
    
      bezierVertex( x + 30, y - 30, z, x + 30, y + 30, z, x + 50, y - 50, z);
    
      z-=differenceInZ; // !!!!!!
    
      endShape(OPEN);
    
      // ----------------------
    
      if (true) {
    
        // connecting standard level and next level   *******************************************
    
        // green 
        stroke(0, 255, 0);
    
        connectAnchorPoints(x + 50, y - 50, z, x + 30, y - 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
        connectAnchorPoints(x + 40, y - 40, z, x + 20, y - 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
    
        connectAnchorPoints(x - 50, y - 50, z, x - 30, y - 30, z, x - 30, y + 30, z, x - 50, y + 50, z);
        connectAnchorPoints(x - 40, y - 40, z, x - 20, y - 20, z, x - 20, y + 20, z, x - 40, y + 40, z);
    
        connectAnchorPoints(x - 50, y - 50, z, x - 30, y - 30, z, x + 30, y - 30, z, x + 50, y - 50, z);
        connectAnchorPoints(x - 40, y - 40, z, x - 20, y - 20, z, x + 20, y - 20, z, x + 40, y - 40, z);
    
        connectAnchorPoints(x - 50, y + 50, z, x - 30, y + 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
        connectAnchorPoints(x - 40, y + 40, z, x - 20, y + 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
      }
      // ----------------------
    
      // next level  *******************************************
    
      z+=differenceInZ; // !!!!!!
      stroke(0, 0, 255);
      noFill();
    
      if (true) {
        beginShape();
    
        vertex(x + 50, y - 50, z); 
        bezierVertex( x + 30, y - 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
        bezier2(x + 40, y - 40, z, x + 20, y - 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
    
        bezier2(x - 50, y - 50, z, x - 30, y - 30, z, x - 30, y + 30, z, x - 50, y + 50, z);
        bezier2(x - 40, y - 40, z, x - 20, y - 20, z, x - 20, y + 20, z, x - 40, y + 40, z);
    
        bezier2(x - 50, y - 50, z, x - 30, y - 30, z, x + 30, y - 30, z, x + 50, y - 50, z);
        bezier2(x - 40, y - 40, z, x - 20, y - 20, z, x + 20, y - 20, z, x + 40, y - 40, z);
    
        bezier2(x - 50, y + 50, z, x - 30, y + 30, z, x + 30, y + 30, z, x + 50, y + 50, z);
        bezier2(x - 40, y + 40, z, x - 20, y + 20, z, x + 20, y + 20, z, x + 40, y + 40, z);
    
    
        endShape();
      }
    
    
      // show text upper left corner 
      cam.beginHUD();
      noLights();
      fill(255, 0, 0); // red 
      text("Use mouse to rotate: Click, hold and move mouse; drag with center button (PeasyCam)", 17, 17);
      cam.endHUD();
    }
    
    void bezier2(  float... arrayOfParameters ) {
      // bezier2 expects all points like bezier (anchor control control anchor (each 3 coords in P3D)) but uses them as bezierVertex;
      // bezierVertex requires: 3 coords control, 3 coords control, 3 coords anchor 
    
      int i=0; // for anchor points
      int c1=3; // for control points
      int c2=6; // for control points
      bezierVertex(  arrayOfParameters[c1], arrayOfParameters[c1+1], arrayOfParameters[c1+2], 
        arrayOfParameters[c2], arrayOfParameters[c2+1], arrayOfParameters[c2+2], 
        arrayOfParameters[i], arrayOfParameters[i+1], arrayOfParameters[i+2] ) ;
      i=9;
      bezierVertex  ( arrayOfParameters[c1], arrayOfParameters[c1+1], arrayOfParameters[c1+2], 
        arrayOfParameters[c2], arrayOfParameters[c2+1], arrayOfParameters[c2+2], 
        arrayOfParameters[i], arrayOfParameters[i+1], arrayOfParameters[i+2] ) ;
    }
    
    void connectAnchorPoints(  float... arrayOfParameters ) {
    
      // using optional variables in a function: arrayOfParameters
    
      // see https : // forum.processing.org/two/discussion/11222/how-to-define-optional-variables-in-a-function
    
      // connect two layers with straight 3D lines of length differenceInZ
    
      // (takes all points (like bezier) but uses only the first and last three points, which are the 2 anchor points see reference for bezier)
    
      int i=0;
      // using the 3D version of line here 
      line(arrayOfParameters[i], arrayOfParameters[i+1], arrayOfParameters[i+2], 
        arrayOfParameters[i], arrayOfParameters[i+1], arrayOfParameters[i+2]+differenceInZ);
    
      i=9;
      // using the 3D version of line here 
      line(arrayOfParameters[i], arrayOfParameters[i+1], arrayOfParameters[i+2], 
        arrayOfParameters[i], arrayOfParameters[i+1], arrayOfParameters[i+2]+differenceInZ);
    }//func
    // 
    
Sign In or Register to comment.