How do I display shapes in P3D like on a HUD?

edited October 2017 in How To...

I am trying to make an experimental level editor in Processing, and I want to display a level mini-map using points while playing the level. I can't get it to work, because the points appear in 3D space rather than 2D. How do I make them appear in 2D? I tried the old methods but none of them works (can't clear the zbuffer as it doesn't exist as a variable, etc.)

Answers

  • If you use peasycam, you have available HUD mode. Would that do the trick for you? Google the library and you will see the function calls.

    Kf

  • Peasycam has beginhud endhud iirc

    For an approach without peasy

    Place the hud at the end of draw()

    // start hud

    camera ();

    noLights();

    textMode(.....);

    text(......

  • edited May 2017

    @theliquu69 --

    One method is to create an OpenGL P2D sketch and then draw two images() into the sketch surface -- a PGraphics(P3D) with your 3D sketch content, and a PGraphics(P2D or JAVA2D) with your HUD content.

    Here is a simple example combining JAVA2D, P2D, and P3D graphics buffers into one sketch window composition:

    PGraphics j2, p2, p3;
    
    void setup() {
      size(400, 400, P2D);
      j2 = createGraphics(width/4, width/4, JAVA2D);
      p2 = createGraphics(width, height/4-20, P2D);
      p3 = createGraphics(width-20, 3*height/4, P3D);
    }
    void draw() {
      background(0);
      drawRect(j2);
      drawRandomColor(p2);
      drawSphere(p3);  
      image(p3, 10, 10);
      image(p2, 0, 3*height/4+20);
      image(j2, 20, height-width/4-20);
    }
    
    void drawRandomColor(PGraphics pg) {
      if (random(100) < 2) {
        pg.beginDraw();
        pg.background(color(random(255), random(255), random(255)));
        pg.endDraw();
      }
    }
    
    void drawSphere(PGraphics pg) {
      pg.beginDraw();
      pg.background(128,128);
      pg.translate(pg.width/2,pg.height/2);
      pg.sphere(pg.width*1/4 + pg.width*1/6 * cos( TWO_PI * float(millis() % 4000)/4000 ) );
      pg.endDraw();
    }
    
    void drawRect(PGraphics pg) {
      pg.beginDraw();
      pg.clear();
      pg.stroke(128);
      pg.strokeWeight(10);
      pg.fill(128, 0, 0, 128);
      pg.rect(0, 0, pg.width, pg.height);
      int m = int(millis()/10) % pg.width;
      pg.rect(m/2, m/2, pg.width-m, pg.height-m);
      pg.endDraw();
    }
    

    Layers_Ex8_Simple

    Here the sphere layer (P3D) and color bar (P2D) are arranged next to each other; the HUD rect layer (JAVA2D) is partially transparent and overlays them both. Most of the sketch is defining the layer contents -- the actual layout is just a correct size(), a few createGraphics() calls, and then multiple image() calls in draw().

    If you try to draw 3D content into the main sketch window, on the other hand, this won't work. It works because this is a 2D layout with some of the elements containing 3D content.

  • For an example of drawing a HUD with the peasycam library's beginHUD() / endHUD() -- as mentioned by @kfrajer and @Chrisir -- see:

    The example code looks like this:

      camera.beginHUD(); // start drawing relative to the camera view
      fill(255);
      rect(20, 10, 120, 30);
      fill(0);
      text(str(frameRate), 30, 30);
      camera.endHUD();  // and don't forget to stop/close with this!
    
  • Jeremy, your example is awesome! I simply was not aware that I can use different Renderers in different PGraphics-objects! Thank you very much! Jens

  • edited October 2017

    You are welcome! It is not necessarily clear, as the familiar size() command seems to imply that there is only one renderer for an entire sketch - but that is not true, it is only for the main sketch canvas. You can see documentation about choosing a per-PGraphics renderer on the createGraphics() reference page:

  • Answer ✓

    There is an easier way which allows you to use the P3D directly without having to create off-screen buffers.

    float angle = 0;
    
    void setup() {
      size(400, 400, P3D);
      getGraphics();
    }
    
    void draw() {
      background(64);
      // Start of 3D drawing
      pushMatrix();
      translate(width/2, height/2);
      rotateX(angle);
      rotateY(angle * 1.123);
      angle += 0.01;
      fill(200, 200, 0);
      stroke(0, 64, 0);
      strokeWeight(1);
      sphereDetail(32);
      sphere(150);
      popMatrix();
      // End of 3D start of 2D HUD
      getGraphics().hint(PConstants.DISABLE_DEPTH_TEST);
      fill(255, 160);
      stroke(0);
      strokeWeight(6);
      rect(3, height-100, width-6, 97);
      getGraphics().hint(PConstants.ENABLE_DEPTH_TEST);
    }
    
  • edited October 2017

    Thanks, @quark. Interesting! Is there any documentation that could help explain what is happening here, e.g. with the call in setup? For example, getGraphics() isn't in the reference and the entry in the developer's API seems to be blank:

  • edited October 2017

    AFAIK, it makes no diff. directly invoking hint() or via getGraphics().
    B/c all PApplet methods related to canvas are already routed to variable g, which is the sketch's PGraphics.

  • Yes you can get rid of the getGraphics(). and the PConstants. from lines 23 & 28 because the hint() method in the PApplet class will do this for you. The getGraphics() method returns the PGraphics object used for rendering the sketch so can be used to access any methods not available to PApplet.

    Line 5 is not needed and should be deleted.

  • So the actual working sketch is

    float angle = 0;
    
    void setup() {
      size(400, 400, P3D);
    }
    
    void draw() {
      background(64);
      pushMatrix();
      translate(width/2, height/2);
      rotateX(angle);
      rotateY(angle * 1.123);
      angle += 0.01;
      fill(200, 200, 0);
      stroke(0, 64, 0);
      strokeWeight(1);
      sphereDetail(32);
      sphere(150);
      popMatrix();
      // Start of HUD
      hint(DISABLE_DEPTH_TEST);
      fill(255, 160);
      stroke(0);
      strokeWeight(6);
      rect(3, height-100, width-6, 97);
      hint(ENABLE_DEPTH_TEST);
    }
    
  • edited October 2017

    Got it.

    Is there documentation for hint() somewhere in the javadocs? I've seen it mentioned many times for passing arguments to the renderer, but I wouldn't know where to point someone in teaching them how to use it -- all I have is lore.

    Edit

    Never mind, I was looking in the wrong place. Extensive PGraphics.hint() docs here:

    From the docs:

    hint(DISABLE_DEPTH_TEST) - Disable the zbuffer, allowing you to draw on top of everything at will. When depth testing is disabled, items will be drawn to the screen sequentially, like a painting. This hint is most often used to draw in 3D, then draw in 2D on top of it (for instance, to draw GUI controls in 2D on top of a 3D interface).

Sign In or Register to comment.