For those who don't know about framerate..a little demo

Note: as per Arturo’s correction in post below i made a one line mod to the code to use a more accurate frame timing

Hi Folks, as i was just wandering through a piece of code tidying up i starting to take out my framerate dependencies (of course this should be done as the code is being built!). Most folks here maybe know this, but some won’t Whenever you play a console game the coders have always taken out framerate dependencies to accomplish a standard rate of movement for objects. In a racing game we want our car in our racing game to drive at 110km/h irrespective of framerate.

For those who are new to this but just want some code, here is a quick little Hare and Tortoise codelet, that just needs dropping into an OF emptyExample…

  
#include "testApp.h"  
  
  
float framerateMult;  
  
  
  
  
//--------------------------------------------------------------  
void testApp::setup(){  
  
    framerateMult = 1.0f;  
      
    ofSetFrameRate(60);   
  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
  
      
    framerateMult = 60.0f/(1.0f/ofGetLastFrameTime());  // changed as per Arturo correction..thanks  
      
    if(ofGetElapsedTimef()< 10.0f) ofSetFrameRate(120);  
    else if(ofGetElapsedTimef()< 20.0f) ofSetFrameRate(60);  
    else if(ofGetElapsedTimef()< 30.0f) ofSetFrameRate(30);  
    else if(ofGetElapsedTimef()< 40.0f) ofSetFrameRate(10);  
      
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
  
      
    int startLine = 30;  
    static float harePos = 0.0f;  
    static float tortoisePos = 0.0f;  
    float blightersSpeed = 0.3f;  
  
      
    string info = "fps: " + ofToString(ofGetFrameRate(),2)   
    + "\nframerateMult: " + ofToString(framerateMult,2) ;  
    ofDrawBitmapString(info, 10, ofGetHeight()-40);  
      
    //Draw the timeline  
      
    int littleStep = 10;  
    int bigStep = 100;  
      
    ofSetColor(255, 255, 255, 255);  
    for(int x = startLine; x<ofGetWidth()-100; x+=littleStep)  
        {  
          
        if(x%bigStep == 0)  
            ofRect(x,ofGetHeight()/2-20, 2, 80);  
        else  
            ofRect(x,ofGetHeight()/2, 1, 40);  
          
        }  
      
    //Move the hare  
    harePos += blightersSpeed;  
    //Draw the hare  
    ofSetColor(128, 0, 0, 255);  
    ofRect(startLine+harePos,ofGetHeight()/2-40, 20, 20);  
    info = "hare\nSpeed " + ofToString(blightersSpeed * ofGetFrameRate(), 2) + " km/h";  
    ofDrawBitmapString(info, startLine+harePos,ofGetHeight()/2-70);  
      
    //Move the tortoise  
    tortoisePos += blightersSpeed*framerateMult;  
    //Draw the tortoise  
    ofSetColor(0, 0, 128, 255);  
    ofRect(startLine+tortoisePos,ofGetHeight()/2+60, 20, 20);  
   info = "tortoise\nSpeed " + ofToString(blightersSpeed*framerateMult * ofGetFrameRate(), 2) + " km/h";  
    ofDrawBitmapString(info, startLine+tortoisePos,ofGetHeight()/2+100);  
  
     
      
    ofSetColor(255, 255, 255, 255);  
     
  
}  

You typically pick a base framerate (one you expect your app to hopefully run at), usually in games it is 30FPS or 60FPS. In this codelet i picked 60FPS as my base. You see that the Hare goes crazy at first as the framerate is above 60FPS, then as i force the framerate lower and lower the Hare gets slower and slower. Meanwhile the Tortoise keeps a constant speed.

As the framerate gets to 10FPS you will see the graphics flickering…achieving framerate independence does not make the underlying graphics update smoother, if FPS is below 30 you will see the screen update.

In a real app as you pile on your graphics and CPU load, the framerate obviously drops, and if your car movement isn’t framerate independent then it would look like it was going slower, also if the framerate increased ridiculously the car would seem to be going faster. It can also dramatically affects user input, in particular i would expect those playing with ofxKinect and multiple human inputs to be having issues related to this.

PS… there is another way to achieve this. Lets say for moving our car we have a function called movethecar() that is called from the OF update() function. You can simply call you movethecar() routine more than once a frame. If you chose your base framerate to be 60FPS then you call the movethecar() once per frame, if the framerate drops to say 44FPS then you would force it down to 30FPS and call movethecar() twice per frame, if the framerate drops to 21FPS then you would force it to 20FPS and call movethecar() three times per frame. Of course you can only use dividers that produce whole numbers, and that is a disadvantage of that method.

That’s it…

mmh, so that’s not totally right.

ofSetFramerate, makes the app sleep for a while if the calculated fps is higher that what you set, but it’s not perfectly accurate cause just measuring time takes some time which you cannot account for, and also asking a thread to sleep for some time doesn’t necessarily mean that it will sleep for exactly that time. so it’s impossible to have a perfectly accurate fps measure/clamping.

For animation indeed you should be using ofSetVerticalSync(true) so you don’t have artifacts.

Also ofGetFramerate is actually calculating an average of the fps during the last frames so using it for animation can be problematic if for example one frame takes longer than the rest your position updating for that frame will be wrong.

What you should be using instead is ofGetLastFrameTime, which gives you the time in seconds that has passed since the last frame. So for example if you want to move something in the screen at 10 pixels per second you would do something like:

  
  
update(){  
posX += ofGetLastFrameTime() * 10;  
}  
  
draw(){  
ofCircle(posX,posY,10);  
}  
  

even with that there’s some cases where you need to divide the update of the position in little steps in each cycle of the update/draw loop, but for simple cases this is ok

3 Likes

Thanks Arturo, i wasn’t aware that ofGetFrameRate() was building an average, as the documentation states

ofGetFrameRate() returns float
returns the current framerate, as a floating point number.

I guess i should have looked at the implementation.

So yes i am wrong to think that this codelet would perfectly solve the animation issue.

Here’s a great article showing several different variations of framerate independent animation:
http://gafferongames.com/game-physics/fix-your-timestep/

One thing I’ve noticed when using time-corrected integration…dragging the application window around while it’s running freezes frame updates, but not time-elapsed updates, creating an abnormally huge time gap between frames and completely screwing up all animation.

Hi all,

I’m somewhat new to openframeworks (1 mo) and I LOVE IT! So nice.

One question:
Is there any way I can set the draw() and update() framerates different from say the onNewMessage() frame rate used by ofxSimpleSerial.

Reason for it is this:
I’m creating an interactive installation that measures/logs/uploads viewer’s heartbeats and has some picture taking and midiout sound stuff - http://produceconsumerobot.com/emergence/

I’m getting serial signals that tell me a heartbeat occurred and I would like that measurement to be as accurate as possible. 250bpm = 24ms, even a 250 framerate gives me ~1 per 4ms, which amounts to a 15% error (at best, at worst graphics lag that) that is captured both in my logs and audible in the beat timing at even ~170bpm. I really only need a 30fps for the graphics and some of the sounds, but I would love it if I could take the simple serial reads up to a much faster rate (even 1000Hz would be awesome).

I tried a couple of ill-posed hacks and poked around in the code and couldn’t find anything obvious.

Any thoughts?

I’m taking the piece to ISEA Istanbul tomorrow :slight_smile:
http://isea2011.sabanciuniv.edu/

Cheers,
Sean

BTW, I’m using of 0.6.2 - too scared to upgrade before the show :slight_smile:

haven’t looked at ofxSimpleSerial but i guess it’s using a listener to the update event to query the serial port.

You’ll need to change that to use a thread instead so it can query as fast as it can, take a look at the threadExample to see how to do it. mainly anything in your update function in ofxSimpleSerial should be moved or called from a loop in threadedFunction with a small sleep at the end

AWESOME!
You da man Arturo!

On question:
What happens if I don’t call TO.stop before I stop the application?
Is it stopped for me or will I rack up a bunch of orphan threads?

no, all threads are killed when the process (the application) ends

hi.

i am also trying to get a smooth movement.
i made this little app to see the performance better. i’m either doing something wrong or my computer is just too slow. (mac book pro core i7 2.6 ghz 8gb)

the app stores as many vertical lines as the stage is wide.
these lines are drawn in to an FBO and also outside on the regular stage.
the “play head” moves from left to right at a specific speed. only those lines are made visible where the play head actually is.

if the computer would perform constant the line pattern should be even but it is not.

screen shot -> http://lozano-hemmer.com/ss/pTest.png

any ideas why this happens?

  
  
#define stageWidth 1920  
  
bool linePos[stageWidth];  
int beltPos = 0;  
unsigned long lastUpdateTime;  
  
ofFbo mainFBO;  
int fboHeight = 700;  
  
//--------------------------------------------------------------  
void testApp::setup(){  
      
    ofSetVerticalSync(true);  
      
    mainFBO.allocate(stageWidth,fboHeight,GL_RGBA);  
  
      
    ofBackground(255, 255, 0);  
   // ofSetBackgroundAuto(false);  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
      
  
//   unsigned long updateDT = ofGetElapsedTimeMillis() - lastUpdateTime;  
//    lastUpdateTime = ofGetElapsedTimeMillis();  
//    beltPos = beltPos + (beltSpeed * updateDT);  
     
      
    //beltPos = (ofGetElapsedTimeMillis()/6) % stageWidth;  
    beltPos +=   ofGetLastFrameTime()*200;  
      
    if(beltPos > stageWidth) beltPos = 0;  
      
    if(beltPos == 0){  
        for(int i=0; i<stageWidth; i++){  
            linePos[i] = false;  
        }  
    }  
    linePos[int(beltPos)] = true;  
  
      
    mainFBO.begin();  
    ofClear(255, 255, 255);  
      
    ofFill();  
    ofSetColor(255);  
    ofRect(0, 0, stageWidth, fboHeight);  
      
    ofSetColor(0, 0, 255);  
    for(int i=0; i<stageWidth; i++){  
        if(linePos[i] == true) ofLine(i,fboHeight/2,i,fboHeight);  
          
    }  
  
    mainFBO.end();  
  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
      
      
    ofSetColor(255);  
    mainFBO.draw(0,200,stageWidth,400);  
      
    ofSetColor(255, 0, 0);  
      
    for(int i=0; i<stageWidth; i++){  
        if(linePos[i] == true) ofLine(i,0,i,250);  
    }  
      
    ofSetColor(255, 0, 0);  
    ofFill();  
    ofCircle(beltPos, 300, 50);  
      
    ofCircle(mouseX,mouseY, 20, 20);  
}  
  
  

The idea behind time based animation is that the framerate is not constant, even when synchronized with the vertical refresh there can be small differences between time. So instead of moving by a constant disatance every frame you calculate how much time has passed between frames and move by the corresponding distance depending on a velocity or acceleration.

So if you draw the steps every frame it’s normal that they are not equal but the speed of the ball is constant in time

i think this what i did, move depending on time past? beltPos += ofGetLastFrameTime()*200;
or are you suggesting an other method? not sure if i understand.

the problem is that i see the ball movement being jittery.

in my setup i need the projected image to move at the same speed as a real moving object.

what i say is that the lines that you are drawing don’t necessarily need to be constant since the time between frames is going to be different but the movement of the ball shouldn’t be jittery. the logic seems correct to me though.

let me give it a try

i think the problem is that beltPos is an int so you are loosing the decimal positions which makes the movement jittery, if i change that to a float or a double then the movement is perfectly stable. The lines won’t be evenly separated though but as i said that’s normal

just tired float and double for beltPos but it still jitters. i will try to make a screen movie.

here is a screen movie of what i see
http://lozano-hemmer.com/ss/pTest.mov

and i think the lines not being even happens at the same rate as the sphere jitter.

it’s very strange.

that’s in osx?

if it is can you try to change the following functions in ofUtils?

  
  
  
unsigned long long ofGetSystemTime( ) {  
#ifdef TARGET_LINUX  
	struct timespec now;  
	clock_gettime(CLOCK_MONOTONIC, &now);  
	return  
		(unsigned long long) now.tv_nsec/1000000. +  
		(unsigned long long) now.tv_sec*1000;  
	#elif TARGET_OSX  
		return mach_absolute_time()/1000000.;  
	#elif !defined( TARGET_WIN32 )  
		struct timeval now;  
		gettimeofday( &now, NULL );  
		return  
			(unsigned long long) now.tv_usec/1000 +  
			(unsigned long long) now.tv_sec*1000;  
	#else  
		#if defined(_WIN32_WCE)  
			return GetTickCount();  
		#else  
			return timeGetTime();  
		#endif  
	#endif  
}  
  
unsigned long long ofGetSystemTimeMicros( ) {  
	#ifdef TARGET_LINUX  
		struct timespec now;  
		clock_gettime(CLOCK_MONOTONIC, &now);  
		return   
			(unsigned long long) now.tv_nsec/1000. +  
			(unsigned long long) now.tv_sec*1000000;  
	#elif TARGET_OSX  
		return mach_absolute_time()/1000.;  
	#elif !defined( TARGET_WIN32 )  
		struct timeval now;  
		gettimeofday( &now, NULL );  
		return  
			(unsigned long long) now.tv_usec +  
			(unsigned long long) now.tv_sec*1000000;  
	#else  
		#if defined(_WIN32_WCE)  
			return ((unsigned long long)GetTickCount()) * 1000;  
		#else  
			return ((unsigned long long)timeGetTime()) * 1000;  
		#endif  
	#endif  
}  
  

you’ll need to include <mach/mach_time.h>

that’s using a more precise timer but even with the current version of that code it works ok for me in linux and osx

ok i replace it with your code. i only left all osx related things.

still jitters.
see here:http://lozano-hemmer.com/ss/pTest2.mov

my new code also has a blue sphere that moves 3.3 pixels ever time update is called.
just to compare.

i am also noticing i am not able to compile any app for release just debug.
saw the same thing on a mac mini at work.
it’s probably not related though.

unsigned long long ofGetSystemTime( ) {

return mach_absolute_time()/1000000.;

}

unsigned long long ofGetSystemTimeMicros( ) {

return mach_absolute_time()/1000.;

}

could it be that there’s some other process running in your computer that it’s stopping the app from time to time? i get some jitter at the beginning but then it’s completely smooth. perhaps try to cout the times to see if there’s any frame that takes much longer than the others, which it seems from the pattern in the lines.

also try using a ofGlutWindow instead of glfw