#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# How to extrude a 2D custom shape into 3D

edited January 2018

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:

• 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
//
``````