Jumpy FPS

Started by
6 comments, last by doogle 20 years, 6 months ago
My code to work out time between frames almost works... it's fine except for "jumps" every 10 or 20 seconds, where all movement advances about 10 times as quickly as it should (just for one frame) before returning to normal. For example, I'll be walking along and suddenly I'm about 100m ahead of where I should be. Heres the code for it:

LARGE_INTEGER start, end, freq;
 
QueryPerformanceFrequency(&freq);
 
const float dtime() {	
  double t = -(((double)end.QuadPart-(double)start.QuadPart) / (double)freq.QuadPart) * 200000.0f;
  return (float)t;
}
Any ideas as to what could be causing this? My best guess is a rounding error somewhere, so I tried changing the floats to doubles, but it didn't help. [edited by - doogle on October 5, 2003 10:33:20 PM]
Advertisement
poke
Ah yeah, my guess is to perform the subtraction befor you convert to doubles, as the 64 bit number is *HUGE*, and the subtraction will bring the numbers down to a size managable by us mere mortals and floating point representation. The frequency should allready be a nice managably low number, so its allright to convert it straight.

Note: I''m talking out my ass here, as I really don''t know how big a number a double could accuratly represent, I think it would get the magnitude right, but I don''t know if it would have enough significant digits to represent the 64 bit number in full.
hmm my first thought was that its not your code causing this sort of error, i have the same behavior in battlefield (orginal without patches) when i enable tripplebuffer, disabling it by setting the prerender frames to 0 (nvidia driver option) i was able to remove it, but it could be offtopic in your case (i cant see how your code should cause it)


T2k
I remember hearing of an old bug in QueryPerformanceXXX where the counter would jump by several seconds instead of msecs. The solution was to keep a low resolution timer also and if the two differed by too much, assume QueryPerformanceCounter() bugged out.

A quick search revealed this. They claimed it occurs under win2000 sp1 with certain motherboards.

EDIT:
double t = -(((double)end.QuadPart-(double)start.QuadPart) / (double)freq.QuadPart) * 200000.0f; 


What's up with this equation? You seem to be getting times in increments of 5 microseconds, and returning a negative value at that.

Here is some code that measures time in milliseconds:
measuredTime = (unsigned int) ((double) ((curTime.QuadPart - startTime.QuadPart) * 1000) / (double) (freq.QuadPart) + 0.5); 


[edited by - jermz on October 6, 2003 12:35:40 PM]
Thanks for the replies

That equation was negivite as a quick fix for walking backwards instead of forwards... heh

I couldn''t get your equation to work jermz, it just gave 0. And I''m using Win XP, not 2000... hmmm
Heres a basic timer class I''ve used. You start it and then read out the time since then...

#define MIL_FROM_100NAN_CONV 10000/////////////////////////////////////////////////////////////////////// WWSTPTimer - Class used to time events/////////////////////////////////////////////////////////////////////class WWSTPTimer{private:	LARGE_INTEGER	startTime;	LARGE_INTEGER	freq;	unsigned int	measuredTime;	bool		started;	bool		HPT;public:	WWSTPTimer();	void		clearTimer();	void		startTimer();	unsigned int	getTime();};////////////////////////////////////////////////////////////////////// Constructs a timer object, using high precision (~1ms) if// available or more coarse (~10ms) if not////////////////////////////////////////////////////////////////////WWSTPTimer::WWSTPTimer(){	// use high precision timer if available by checking that	// QueryPerformancCounter and QueryPerformanceFrequency are available	HPT = false;	if ( QueryPerformanceCounter( &freq ) )		if ( QueryPerformanceFrequency( &freq) )			HPT = true;	measuredTime	= 0;	started		= false;}////////////////////////////////////////////////////////////////////// Stops a timer and clears measured time.////////////////////////////////////////////////////////////////////void WWSTPTimer::clearTimer(){	measuredTime	= 0;	started		= false;}////////////////////////////////////////////////////////////////////// Starts measuring a time period.////////////////////////////////////////////////////////////////////void WWSTPTimer::startTimer(){	if (HPT)	{		// read in intial counter		QueryPerformanceCounter(&startTime);	}	else	{		// read in initial time		FILETIME fileTime;		GetSystemTimeAsFileTime(&fileTime);		startTime.QuadPart = fileTime.dwHighDateTime;		startTime.QuadPart = startTime.QuadPart << 32;		startTime.QuadPart += fileTime.dwLowDateTime;	}	started	= true;}////////////////////////////////////////////////////////////////////// Calculates the time in the interval since this timer was started.// This can actually be called multiple times since a timer was// started, each call would update the measured time.////////////////////////////////////////////////////////////////////unsigned int WWSTPTimer::getTime(){	LARGE_INTEGER curTime;	if (!started) return 0;	if (HPT)	{		// read in current counter and calc measured time		QueryPerformanceCounter(&curTime);		// this would be ideal formula but integer division always truncates		// measuredTime = (unsigned int) ((curTime.QuadPart - startTime.QuadPart) * 1000 / freq.QuadPart);		// this formula casts to double and adds 0.5 before dividing to overcome truncation		measuredTime = (unsigned int) ((double) ((curTime.QuadPart - startTime.QuadPart) * 1000) / (double) (freq.QuadPart) + 0.5);		// this formula should work solely using integer math, but its 64 bit!		// measuredTime = (unsigned int) ((1000 * (curTime.QuadPart-startTime.QuadPart) + (freq.QuadPart>>1)) / freq.QuadPart);	}	else	{		// read in current time and calculate measured time		FILETIME fileTime;		GetSystemTimeAsFileTime(&fileTime);		curTime.QuadPart = fileTime.dwHighDateTime;		curTime.QuadPart = curTime.QuadPart << 32;		curTime.QuadPart += fileTime.dwLowDateTime;		measuredTime = (unsigned int)((curTime.QuadPart - startTime.QuadPart) / (ULONGLONG) MIL_FROM_100NAN_CONV);	}	return measuredTime;}
Well, I found my problem

//main loopwhile(running) {  QueryPerformanceCounter(&start);  //draw and update  QueryPerformanceCounter(&end);}


Which is why I got a negitive time (and thus the - sign in there), and why I multiplied it by such a big number... hehe... annoying.

It looks way worse now though - time is either 1 or 0 by the looks of it. And my mouselook seems to stop time... crazah, but I'll work it out

EDIT: and just for the record... moving the mouse stopped time because the game isnt updated if win messages need dealling to.. fixed. Doogle out

[edited by - doogle on October 8, 2003 2:07:10 AM]

This topic is closed to new replies.

Advertisement