Open Sound Control Message Lisener instead of draw loop?!

edited August 2015 in Library Questions

Hi,

in my current project, i have some timing problems when rendering in realtime. As many of you might have experienced, the draw loop is not always a relieable timer. In my experience, it is better to have objects that render dependent on millis() instead of relying on a stable framerate. But still, this is not very smooth in more complex cases. (Strange, it is not a performance problem. It also happens to be unsmooth when the CPU is happy with 30%)

I am thinking about to trigger the drawing action from outside the Processing sketch, lets say a plain Java-application which just contains one thread which sends an Open Sound Control Message to the sketch every xxx milliseconds. And the sketch will render one Frame when it receives one of these messages.

Something like:

public void oscEvent(OscMessage theOscMessage)
  anObjectWhichDoesRendering.draw(playHead);
  playHead += playHeadStep;
}

Question to those who know more about Java, OSC and Threading than me: Is this approach worth a try?

Thanks in advance

nossekk

Answers

  • Thank you GoToLoop!

    But how do i trigger redraw precisely?

    From the perspective of my project, the question is actually not which method does the rendering but how to trigger those methods with a precise regularity.

    I wrote my own methods drawing into a PGraphics-Object, and i'm using the draw loop only to trigger those methods.

  • edited August 2015

    But how do I trigger redraw() precisely?

    AFAIK, when noLoop() is active, redraw() "calls" draw() ASAP.
    Actually, redraw() merely assigns true to field redraw.
    Dunno exactly the rate Processing polls that field. But I believe it's fast enough.
    For extra faster reaction time, set field redraw directly: redraw = true;.
    Doing so avoids synchronized slowdown trap from redraw()! :P

  • edited August 2015

    Okay thanks i will give it a try. So it sounds like i could solve my problem without external trigger, right! Will check back to tell how it works... Thanks nossekk

    EDIT: No, wait, i still didn't get it. Who or what will call redraw?!

  • edited August 2015

    Who or what will call redraw()?!

    W/ noLoop() active, we call redraw() when we wanna update the canvas.
    Only you can decide when that moment is right!

  • Hm, sorry if i just don't understand you but now it still looks to me that my problem is not which method does the drawing, but to find a way that this method will be called in a really precise pace. How would you do that? In a second thread?

  • Gotta confess I can't pinpoint at which context you're asking about it. X_X
    So it's not related to request sketch's canvas to be rendered after all? :-??
    You should provide a more clear sample what's in your mind, I'm afraid...

  • edited August 2015

    ok i will give a stripped down example today or tomorrow... Thanks anyway for taking your time GoToLoop!

  • Now, here's a stripped down example of how i do the rendering in my project. I don't render directly into the sketch's canvas, but into a PGraphics Object, which, of course, finally will be displayed in the canvas with image(). (The reason why i do so is that i do multichannel video editing. So, each PGraphics Object represents one frame at one videoscreen. So i can place views on the different videochannels in the canvas)

    class StupidEllipse{
      void render(PGraphics renderTarget){
        renderTarget.beginDraw();
        renderTarget.ellipse(random(0, renderTarget.width), random(0, renderTarget.height), 20, 20);
        renderTarget.endDraw();
      } 
    }
    
    void setup(){
      size(500, 500);
      stupid = new StupidEllipse();
    }
    
    void draw(){
      PGraphics renderTarget = createGraphics(width, height);
      stupid.render(renderTarget);
      background(0);
      image(renderTarget, 0, 0);
    }
    

    But i think this all is not really essential for my problem.

    The problem is: the loop which calls the draw() method has an unstable timing. You cannot rely on that it will have a precise pace. I am looking for something else that will trigger drawing action as precise as possible, every x milliseconds.

    I did some experiments with a Thread, which basically looks like this:

    class RenderClock extends Thread {
      int framesPerSecond;
      RenderClock(int framesPerSecond) {
        this.framesPerSecond = framesPerSecond;
      }
    
      void run() {
        while (true) {
          try {
            sleep((long)(1000.0 / framesPerSecond));
          }
          catch(InterruptedException e) {
          }
          //calls a method which will do the drawing action...
        }
      }
    }
    

    I could start the Thread, but it weren't able to trigger drawing action yet. Will post more examples later.

    have a nice day nossekk

  • starting from the redraw() example in the reference, i wrote the following test where the drawing is triggered by a thread.

    Next step will be to check out if this really improves the stability of the drawing-pace. Well, i'm really not sure :) If not, i'd put the clocker into a second java-application and send the clocker-"bangs" via OSC. Will let you know how it works...

    RenderClock clock;  
    
    float x = 0;
    
    void setup() {
      size(200, 200);
      noLoop();
      clock = new RenderClock(10);
      //This detour seems to be neccessary because a direct call of
      // clock.run(); will have the effect that the canvas will not be drawn at all.
      thread("startClock");
    }
    
    void startClock() {
      clock.run();
    }
    
    // does nothing but has to be there.
    void draw() {
    }
    
    void render() {
      x += 1;
      background(204);
      line(x, 0, x, height); 
      redraw();
    }
    
    class RenderClock extends Thread {
      int framesPerSecond;
      RenderClock(int framesPerSecond) {
        this.framesPerSecond = framesPerSecond;
      }
    
      void run() {
        while (true) {
          try {
            sleep((long)(1000 / framesPerSecond));
            render();
          }
          catch(InterruptedException e) {
          }
        }
      }
    }
    
  • edited August 2015

    Maybe you should check out how to use thread() + delay(), or even TimerTask here:
    http://forum.Processing.org/two/discussion/9432/having-an-event-occur-every-n-milliseconds

  • aaah, this looks really very interesting, thanks!

Sign In or Register to comment.