How to create a 3d cylinder using PShape and vertex (x,y,z)?

edited March 2018 in Library Questions

The code I have is done using a different method I believe, but I am unfamiliar using the PShape and vertex(x,y,z) method. Please help me understand what I need to do to convert.

This is the code I have:

    import peasy.*;
    import peasy.org.apache.commons.math.*;
    import peasy.org.apache.commons.math.geometry.*;

    PeasyCam cam;

    void setup()
    {
        size(600, 600, P3D);  
        lights();
        fill(100, 200, 0);
        cam = new PeasyCam(this, 600);
    }

    void draw()
    {
        background(255);

        pushMatrix();    
        rotateX(PI/4);
        drawCylinder( 30, 100, 300 );
        popMatrix();

    }

    void drawCylinder( int sides, float r, float h)
    {
        float angle = 360 / sides;
        float halfHeight = h / 2;

        // draw top of the tube
        beginShape();
        for (int i = 0; i < sides; i++) {
            float x = cos( radians( i * angle ) ) * r;
            float y = sin( radians( i * angle ) ) * r;
            vertex( x, y, -halfHeight);
        }
        endShape(CLOSE);

        // draw bottom of the tube
        beginShape();
        for (int i = 0; i < sides; i++) {
            float x = cos( radians( i * angle ) ) * r;
            float y = sin( radians( i * angle ) ) * r;
            vertex( x, y, halfHeight);
        }
        endShape(CLOSE);

        // draw sides
        beginShape(TRIANGLE_STRIP);
        for (int i = 0; i < sides + 1; i++) {
            float x = cos( radians( i * angle ) ) * r;
            float y = sin( radians( i * angle ) ) * r;
            vertex( x, y, halfHeight);
            vertex( x, y, -halfHeight);    
        }
        endShape(CLOSE);

    }

Answers

  • Edit post, highlight code, press Ctrl-o to format

  • Answer ✓

    you create the shape at the beginning, using createShape and beginShape. then, in draw(), all you have to do is call shape()

    import peasy.*;
    import peasy.org.apache.commons.math.*;
    import peasy.org.apache.commons.math.geometry.*;
    
    PeasyCam cam;
    PShape cylinder;
    
    void setup() {
      size(600, 600, P3D);  
      lights();
      fill(100, 200, 0);
      cam = new PeasyCam(this, 600);
    
      // create the cylinder (in setup!)
      cylinder = createCylinder(30, 100, 300);
    }
    
    void draw() {
      background(255);
    
      pushMatrix();    
      rotateX(PI/4);
      // draw the shape
      shape(cylinder);
      popMatrix();
    }
    
    // this is mostly the old code, with added shapes
    PShape createCylinder(int sides, float r, float h) {
    
      PShape cylinder = createShape(GROUP);
    
      float angle = 360 / sides;
      float halfHeight = h / 2;
    
      // draw top of the tube
      PShape top = createShape();
      top.beginShape();
      for (int i = 0; i < sides; i++) {
        float x = cos( radians( i * angle ) ) * r;
        float y = sin( radians( i * angle ) ) * r;
        top.vertex( x, y, -halfHeight);
      }
      top.endShape(CLOSE);
      cylinder.addChild(top);
    
      // draw bottom of the tube
      PShape bottom = createShape();
      bottom.beginShape();
      for (int i = 0; i < sides; i++) {
        float x = cos( radians( i * angle ) ) * r;
        float y = sin( radians( i * angle ) ) * r;
        bottom.vertex( x, y, halfHeight);
      }
      bottom.endShape(CLOSE);
      cylinder.addChild(bottom);
    
      // draw sides
      PShape middle = createShape();
      middle.beginShape(TRIANGLE_STRIP);
      for (int i = 0; i < sides + 1; i++) {
        float x = cos( radians( i * angle ) ) * r;
        float y = sin( radians( i * angle ) ) * r;
        middle.vertex( x, y, halfHeight);
        middle.vertex( x, y, -halfHeight);
      }
      middle.endShape(CLOSE);
      cylinder.addChild(middle);
    
      return cylinder;
    }
    

    i haven't checked the winding though, just used the old code with as little change as possible.

  • From https://processing.org/tutorials/pshader/

    Removed the noStroke() so you can see what is is been done.

    Kf

    PShape can;
    float angle;
    PShader colorShader;
    
    void setup() {
      size(640, 360, P3D);
      can = createCan(100, 200, 32);
    }
    
    void draw() {
      background(0);
      translate(width/2, height/2);
      rotateY(angle);
      shape(can);
      angle += 0.01;
    }
    
    PShape createCan(float r, float h, int detail) {
      textureMode(NORMAL);
      PShape sh = createShape();
      sh.beginShape(QUAD_STRIP);
      //sh.noStroke();
      for (int i = 0; i <= detail; i++) {
        float angle = TWO_PI / detail;
        float x = sin(i * angle);
        float z = cos(i * angle);
        float u = float(i) / detail;
        sh.normal(x, 0, z);
        sh.vertex(x * r, -h/2, z * r, u, 0);
        sh.vertex(x * r, +h/2, z * r, u, 1);
      }
      sh.endShape();
      return sh;
    }
    
  • I appreciate the help and the secondary reference! I'm still fairly new to Processing and programming. Your notes helped a bunch. Thanks again!

  • that can has no ends though...

  • my version with lights()

    PShape can;
    float angle;
    PShader colorShader;
    
    void setup() {
      size(640, 360, P3D);
      can = createCan(100, 200, 32);
    }
    
    void draw() {
      background(0);
      lights();
    
      translate(width/2, height/2);
      rotateY(angle);
      rotateX(.7);
      lights();
      shape(can);
    
      angle += 0.01;
    }
    
    //-------------------------------------------------------------------------
    
    PShape createCan(float r, float h, int detail) {
    
      textureMode(NORMAL);
      PShape sh = createShape();
    
      sh.beginShape(QUAD_STRIP);
    
      sh.noStroke();
      sh.fill(255, 0, 0); 
      for (int i = 0; i <= detail; i++) {
        float angle = TWO_PI / detail;
        float x = sin(i * angle);
        float z = cos(i * angle);
        float u = float(i) / detail;
        sh.normal(x, 0, z);
        sh.vertex(x * r, -h/2, z * r, u, 0);
        sh.vertex(x * r, +h/2, z * r, u, 1);
      }
      sh.endShape();
      return sh;
    }
    //
    
  • still no ends...

    and you have texture coordinates but no texture...

  • Is there a way to copy the cylinder made and translate/scale/rotate afterwards?

  • see draw()

  • The usual scale and rotate and translate methods work in draw for my example. And peasycam will let you move the camera, obv.

    Because everything is precalculated you can't really dynamically change the geometry of the object, the number of sides, the length or radius. You could call createCylinder with new parameters every frame but you'd lose a lot of the benefits of PShape (the speed) doing that.

  • Thank You!

  • Is there a way to copy the cylinder made and translate/scale/rotate afterwards?

    Yes. That’s what’s happening in draw(). You can change draw and add scale() or change translate and rotate there. You can also call ghe same with thing in many ways (positions, scales)

  • There is a transformation tutorial in the Processing website.

    Kf

Sign In or Register to comment.