I noticed something disturbing about sf::Window animation with OpenGL: any call to SetFramerateLimit(), even with an absurdly high argument such as:
//App.SetFramerateLimit(30);
//App.SetFramerateLimit(60);
//App.SetFramerateLimit(120);
App.SetFramerateLimit(360);
will introduce irregularities & small pauses into the animation! The rotation of even *a single quad* (2 triangles, no texturing) stutters very noticeably, approximately once every second on Windows 7 64-bit.
It was very surprising to find this line was the root cause of the problem. My first suspect was UseVerticalSync(), and it's true that also introduces a little bit of stutter -- but far, far less than SetFramerateLimit().
So, take heed everyone -- take a look at your project and see if you are using this line, see what happens if you play with the parameter or take this call out of your code altogether.
Laurent has mentioned before that it's simply relying on the OS's sleep() method under the hood, and I'm guessing my flavour of Windows just likes to take a nice long nap ~ once per second! : )
A complete & minimal example code:
#include <SFML/Window.hpp>
static void resize(int w, int h);
static void renderLoop(sf::Window & App);
static void drawSquare();
static const float ROTATE_DEGREES_PER_SEC = 45.0f;
int main()
{
const int initialWidth = 1024;
const int initialHeight = 768;
sf::Window App(sf::VideoMode(initialWidth, initialHeight, 32), "SFML");
// Try uncommenting *any* of these to cause the animation to
// stutter on Win7:
//// App.SetFramerateLimit(30);
//// App.SetFramerateLimit(60);
//// App.SetFramerateLimit(120);
//// App.SetFramerateLimit(360);
//// App.UseVerticalSync(true);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glShadeModel(GL_SMOOTH);
resize(initialWidth, initialHeight);
renderLoop(App);
return EXIT_SUCCESS;
}
static void resize(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(
45.0f, // fov
float(w) / float(h), // aspect ratio
1.0f, // near clip
500.0f); // far clip
glMatrixMode(GL_MODELVIEW);
}
static void renderLoop(sf::Window & App)
{
sf::Event Event;
sf::Clock Clock;
while (App.IsOpened())
{
while (App.GetEvent(Event))
{
if((Event.Type == sf::Event::Closed) ||
(Event.Type == sf::Event::KeyPressed))
App.Close();
if (Event.Type == sf::Event::Resized)
resize(Event.Size.Width, Event.Size.Height);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -3.0f);
glRotatef(Clock.GetElapsedTime() * ROTATE_DEGREES_PER_SEC,
0.0f, 0.0f, 1.0f);
drawSquare();
App.Display();
}
}
static void drawSquare()
{
glBegin(GL_QUADS);
glColor3ub(255, 255, 0); glVertex3f(-0.5f, -0.5f, 0.5f);
glColor3ub(255, 0, 0); glVertex3f( 0.5f, -0.5f, 0.5f);
glColor3ub(255, 0, 0); glVertex3f( 0.5f, 0.5f, 0.5f);
glColor3ub(0, 255, 255); glVertex3f(-0.5f, 0.5f, 0.5f);
glEnd();
}
I hope the documentation can be updated to warn the user about the potential irregularities introduced by the timers used by SetFramerateLimit(). I see in another post that Laurent has decided to altogether remove GetFrameTime() from 2.0 anyway, for the same reasons.
Laurent: thanks for all your work on SFML; it is great, and inspiring (even from the clean top-level design, not to mention all the gnarly OS-specific work going on underneath...), and I look forward to v2.0. My only chore with it was to transfer the VS2008 project to VS2010 Express, download the Win7 SDK and figure out how to compile SFML against it, as the binaries did not work for me in Win7 as-is. A sample Visual Studio 2010 project at least would be cool -- I can provide one for the community if you like.
-----------------------
Completely off topic, also: could we add a very simple:
bool sf::Window::IsFullscreen() const;
predicate? I'm having to keeping track of that state myself, in order to "toggle" fullscreen mode on/off, which seems kind of silly. (since we cannot get access to the sf::Style after the window is created...)