PDA

View Full Version : Archieving smooth animation



Xarragon
08-29-2004, 01:42 PM
Hello, I'm having some problems with a a little project I'm working on. The problem is that my animations are oscillating slightly. I'm using a timer (implemented in win32 by QueryPerformanceCounter), that returns a float value, representing the time slice for the frame in seconds. When I replace the time with a fixed value for the timeslice, the animation runs perfect.

Here is the timer implementation:

bool WinTimer::initialize (void)
{
if (!QueryPerformanceFrequency((LARGE_INTEGER *) &itsFrequency))
return false;

if (!QueryPerformanceCounter((LARGE_INTEGER *) &itsLastValue))
return false;

return true;
}

float WinTimer::getTimeSinceLastCall (void)
{
__int64 tmp = itsLastValue;

QueryPerformanceCounter((LARGE_INTEGER *) &itsLastValue);

tmp = (itsLastValue - tmp); // TODO: check if ok

return (float) ((double) tmp / (double) itsFrequency);
} The returned value is sent to the "update" methods as an argument. I have a wintimer set up, sending WM_PAINT messages to the window every 1/85th second.

How can I improve this? Should I use a lower-precision timer, lower the forced framerate, or apply a simple filter on the output from my timer?

Thank you in advance!
Martin Persson

ZbuffeR
08-29-2004, 03:06 PM
Such irregularities may be related to vsync on or off, try to toggle it. I would say 'on' is better, specially if you have a high framerate.
Maybe return a double, to get more precision ?

For vsync, you can try to set it through the driver control panel, or use wglSwapInterval(1)

EDIT: well, if using a constant value smoothes the animation, then vsync is not the issue. Try to log what values are returned, both as original integer and after transformation to double.

08-29-2004, 04:50 PM
also, i wouldn't send paint messages. just draw directly.

common main loop in windows:

[CODE]
MSG msg;
bool done = false;
while( !done )
{
while( PeekMessage(&msg,NULL,0,0,PM_REMOVE) )
{
if( msg.message == WM_QUIT )
{
done = true;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if( done )
break;

// drive animation with idle time
animate();
}
[CODE]

08-29-2004, 04:54 PM
hopefully you can read this (they dont call me bonehead for nothin)


MSG msg;
bool done = false;
while( !done )
{
while( PeekMessage(&msg,NULL,0,0,PM_REMOVE) )
{
if( msg.message == WM_QUIT )
{
done = true;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if( done )
break;

// drive animation with idle time
animate();
}

Xarragon
08-31-2004, 10:28 AM
Thanks for your replies. I'll try logging the output of the timer as suggested, and study it. The obvious solution, as pointed out, would be to use a double instead, but I'll do some peeking around first as to acertain wether it really is the issue or not.

The reason that I perform game update with WM_PAINT messages are really comes from a framework we were handed by the course admin, where they implemented it this way. It has it's advantages, as game updates are done during this message, so it doesn't eat up all CPU. I'll probably change it to the way you suggested, now that I have a pause function halts the game whenever the window loses focus anyway.

Thanks again guys, I'll post any findings or progress I make.
Martin