How to draw Shapes3D objects on PGraphics

edited October 2017 in Library Questions

I have recently installed the Shapes3D library and I'm so much enjoying it :) I'm wondering how to draw 3D objects on a PGraphics object not directly on the screen. In the following code, I want to draw the box object on 'canvas'. Please teach me how to do it. Thanks!

import shapes3d.*;

Box box;
PGraphics canvas;

public void setup() {
  size(720, 720, P3D);

  box = new Box(this, 60, 60, 100);
  box.fill(color(32, 32, 200));
  box.stroke(color(200, 200, 200));
  box.strokeWeight(1.2f);
  box.moveTo(0, 0, 0);
  box.drawMode(Shape3D.WIRE);
  box.tag = "box";

  canvas = createGraphics(720, 720, P3D);
}

public void draw() {

  background(0);

  pushStyle();
  pushMatrix();

  box.rotateBy(radians(4.0f), radians(4.0f), radians(4.0f));
  camera(0, -190, 350, 0, 0, 0, 0, 1, 0);
  box.draw();    // How to make this drawn onto the 'canvas' object?

  popMatrix();
  popStyle();
}
Tagged:

Answers

  • @quark is the one to ask, but I think that Shapes3D targets a PApplet, and that draw methods like box.draw() all draw on the canvas of that applet.

    https://sourceforge.net/p/shapes3d/code/ci/master/tree/Shapes 3D/src/shapes3d/Box.java#l132

    https://sourceforge.net/p/shapes3d/code/ci/master/tree/Shapes 3D/src/shapes3d/Box.java#l569

  • Answer ✓

    @jeremeydouglas is correct that a Shape3D shape is associated to a PApplet object when it is created so in the line

    box = new Box(this, 60, 60, 100);

    box is associated with the PApplet object this which is the main sketch window where the box is too be drawn.

    Having said that I tried it anyway. I had limited success because I couldn't get the box in the middle of the PGraphics. I don't recommend doing this , it is an experiment, it is a hack and the results cannot be guaranteed.

    import shapes3d.*;

    Box box;
    PGraphics canvas;
    
    public void setup() {
      size(720, 720, P3D);
    
      box = new Box(this, 60, 60, 100);
      box.fill(color(32, 32, 200));
      box.stroke(color(200, 200, 200));
      box.strokeWeight(1.2f);
      box.moveTo(0, 0, 0);
      box.drawMode(Shape3D.WIRE | Shape3D.SOLID);
      box.tag = "box";
    
      canvas = createGraphics(720, 720, P3D);
      // I wouldn't do this inside the draw method unless you want 
      // to repart it 60 times a second :-(
      canvas.beginDraw();
      canvas.background(0);
      canvas.translate(canvas.width/2, canvas.height/2);
      canvas.camera(0, -190, 350, 0, 0, 0, 0, 1, 0);
      box.draw();
      canvas.endDraw();
      canvas.save("test.png");
    }
    
    public void draw() {
      background(0);
      camera(0, -190, 350, 0, 0, 0, 0, 1, 0);
      box.rotateBy(radians(4.0f), radians(4.0f), radians(4.0f));
      box.draw();    // How to make this drawn onto the 'canvas' object?
    }
    

    BTW you don't need to use push/popStyle and push/popMatrix to isolate changes made when drawing the box (or any other Shapes3D shape) since Shapes3D does it for you.

  • Thanks @quark and @jeremydouglas!

    So, there's no official way to draw Shapes3D objects on a PGraphics object. Right? Hm... too bad :(

  • Why do you want to draw them to a PGraphics object? There maybe an alternative way to achieve the same thing.

  • Hi @quark,

    I'm making an application which is supposed to have multiple layers (PGraphics). Some of them must have 3D presentation while others are just for 2D primitives.

    In this case, is there a good way you recommend me to use?

    Thanks!

  • Unfortunately I can't see a simple alternative without making changes to the Shapes3D library and I would need to do some investigation how much work would be involved, so no promises. If you are still interested you could post it as a feature request ticket on Sourceforge.

  • T_DT_D
    edited October 2017 Answer ✓

    Here is a little trick for doing what you want. However, there could be possible side-effects that are hard to track down.

    
    import shapes3d.*;
     
    Box box;
    PGraphics canvas;
     
    public void setup() {
      size(720, 720, P2D);
     
      box = new Box(this, 60, 60, 100);
      box.fill(color(32, 32, 200));
      box.stroke(color(200, 200, 200));
      box.strokeWeight(1.2f);
      box.moveTo(0, 0, 0);
      box.drawMode(Shape3D.WIRE);
      box.tag = "box";
     
      canvas = createGraphics(720, 720, P3D);
    }
     
    public void draw() {
      beginDraw(canvas);
      canvas.background(0);
      canvas.pushStyle();
      canvas.pushMatrix();
      box.rotateBy(radians(4.0f), radians(4.0f), radians(4.0f));
      canvas.camera(0, -190, 350, 0, 0, 0, 0, 1, 0);
      box.draw(); // shapes3d doesnt know we swapped g
      canvas.popMatrix();
      canvas.popStyle();
      endDraw(canvas);
    
      image(canvas, 0, 0);
    }
    
    
    PGraphics this_g;
    public void beginDraw(PGraphics pg){
      pg.beginDraw();
      this_g = g;  // backup g
      this.g = pg; // replace g
    }
    
    void endDraw(PGraphics pg){
      this.g = this_g; // restore g
      pg.endDraw();
    }
    
    
    
    
  • edited October 2017

    Neat.

    I've seen PGraphics pg; pg.beginDraw(), but that is a novel way of creating a top-level "beginDraw" -- I wasn't even aware that PGraphics swapping could be done with the main sketch canvas. (Edited once I took a closer look at what was going on)

  • Wow! Thanks @T_D! It's really cool and looks sufficient to be used as a temporary solution. Maybe later, as @quark suggested, I may need to post a feature request.

    Thank you all!

Sign In or Register to comment.