P3D working slow?
  • Hello everyone.

    I've wrote this little piece of code, trying to recreate a hit-box-like scenario, where when I hover over a 3D object/model, it will trigger an if statement.

    Here:

    void setup() {
      size(500, 500, P3D);
    }
    
    void draw() {
      rotateX(radians(-20));
      rotateY(radians(20));
      drawHitBox();
      checkHit();
      background(100);
      drawBox();
      println(frameRate);
    }
    
    void drawHitBox() {
      fill(255, 0, 0);
      translate(width/2, height/2, 0);
      box(100, 30, 50);
    }
    
    void checkHit() {
      if(get(mouseX, mouseY) == color(255, 0, 0)) {
        fill(255, 0, 0);
      } else {
        fill(255);
      }
    }
    
    void drawBox() {
      box(100, 30, 50);
    }
    

    The problem is: This code is WAY too slow, and will be even slower, considering I'll be loading an enormous model into the scene. frameRate states the the frame rate of the program is at about 5fps. I remember seeing that there are ways of loading the objects into an off-screen buffer, but I might be mistaken. Is there any way of speeding up this code, so that it will also be object weight-proof?

    -- MenteCode

  • Funny... when I run this same sketch, I can get up to 250 FPS (calling frameRate() in draw()). Perhaps it has to do with your hardware?

  • PhiLhoPhiLho
    Accepted Answer

    Calling frameRate(1000); in setup() gets me some 160-190 FPS on my not-so-fast computer.

  • Weird. I even tried frameRate(1000) and that didn't get me to a higher frame rate. It stayed at 5. This code, though, runs at a fairly normal speed (my computer doesn't want to exceed 60fps).

    float i = 0;
    
    void setup() {
      size(500, 500, P3D);
      frameRate(10000);
    }
    
    void draw() {
      translate(width/2, height/2);
      rotateX(radians(-20));
      rotateY(radians(i));
      background(100);
      drawBox();
      println(frameRate); 
      i+=0.5;
    }
    
    void drawBox() {
      box(100, 30, 50);
    }
    

    One thing that might be the problem is that I haven't installed the newer version of processing, or the fact that I don't have a graphics card (I do, but it's a CPU internal one). Do any of you have 1 of the 2, that show a better frame rate than me?

    -- MenteCode

  • calsigncalsign
    Accepted Answer

    I have tested the sketch in both Processing 2.1.1 and 1.5.1 with the same performance. I do have a graphics card, however... this is obviously the crucial difference.

    Calling frameRate() is more like setting the target FPS, but it won't change anything if you can't get 60 FPS to begin with.

  • What I would like to know is why the sketch in my last reply run 20x faster then the first one.

    I've just attempted to "debug" the code, and the one function that is making me slower than without, is the checkHit() function. It has the get() function within it, and after removing it, my sketch runs at normal speed. I've changed get() to a different test -- if(mouseX > width/2) -- and it runs perfectly.

    Why?

  • codeanticodecodeanticode
    Accepted Answer

    When you call get() with the OpenGL-based renderers (P2D/P3D), Processing has to read the current contents of the screen (stored in GPU memory) into the CPU memory (and because the renderer doesn't know how many times you are going to call get() during the duration of the current frame, it simply reads the entire screen buffer after the first get(), just in case).

    These GPU-CPU transfers are costly, specially on older hardware. Some contributed libraries implement better techniques to do object picking in 3D, for example you could use ProScene (it is available in the Library manager), in particular take a look at the Basics/MouseGrabbers example.

  • I was trying to make a 3D block selection method, and get() seemed like a good way. Apparently not :P

    Anyway, thanks all who replied.

  • Perhaps you can use this custom method instead of get():

    color getPixel(int x, int y) {
      loadPixels();
      return pixels[x + y * width];
    }
    
  • That shouldn't make a big difference, since calling get(x, y) for the first time triggers a loadPixels(), so the entire framebuffer is loaded into the pixels array. Subsequent calls to get() (as long as they happen within the same frame) don't invoke loadPixels.