From: "Szymon M. Rusinkiewicz" Newsgroups: su.class.cs248 Subject: Re: smooth animation Date: 6 Nov 1999 23:01:47 GMT Kyle Kuznetz writes: >I am having trouble getting smooth animation using the glutIdleFunc(). >Is there a way to somehow interpolate movement from point a to b in a >nice, smooth way? I realize I can go from a to c to d and finally to b, >but splitting up the translations into a bunch of small translations is >too slow, and not fun... The right way to do smooth animation is to have some desired velocity in mind for the object that's moving, then update the position by that velocity times the actual time elapsed since the last update. In other words, in your idle function you should keep track of the last time idle was called. Each time idle is called, you find out the current time, subtract to find the elapsed time, and multiply that elapsed time by the object's velocity to find out how much to change position. For a really trivial example of this, see ~smr/OpenGLAnim. This just has a square moving around the window, but it illustrates in principle what needs to be done. (Windows users might need to replace the call to gettimeofday() with the Windows equivalent, whatever that is...) There are other ways of doing animation, but this one has the advantage that the velocity of moving objects appears constant no matter how loaded your system gets. If your process happens to pause for a bit because of a hiccup in the scheduler, your game will still look reasonable. In addition, it doesn't depend on the exact frequency at which you get calls to the idle function, so it should not care if you switch back and forth between really slow and really fast machines. You'll get a higher frame rate on the fast machines, but the speed of objects moving around in your game will not change drastically. For these reasons, I'd really encourage people to do something like this instead of trying to move your objects by a fixed amount each time you go through the idle loop. - Szymon -------- From: mtsmith@leland.Stanford.EDU (Michelle Chung-Ming Tam) Newsgroups: su.class.cs248 Subject: Re: smooth animation Date: 9 Nov 1999 00:09:10 GMT the following GLUT command: glutGet(GLUT_ELAPSED_TIME); returns an int equal to the number of milliseconds since glutInit() was called. It can be used by Windows (& Unix) people instead of gettimeofday(). I've tried it out with mixed success- it seems to be equivalent to the ANSI clock() command. On my PC, both seem to have rather poor resultion, but I think that may be just on my PC. I'm actually sort of wondering how it works out for other people. (I'm getting behavior where it returns the number of millisecons, but the return value only seems to change after 50 or so milliseonds have passed. It will return the same value for a number of calls, and then jump to a higher value). -Matt -------- From: bacook@stanford.edu (Bryan Cook) Newsgroups: su.class.cs248 Subject: Re: smooth animation Date: Tue, 09 Nov 1999 04:06:27 GMT smr@cs.stanford.edu wrote: >According to the GLUT source, that seems to do gettimeofday on Unix boxes and >ftime under Windows. The 50-millisecond thing sounds like the frequency of >timer interrupts under Windows (and DOS, for that matter). Any Windows hackers >out there know of a higher-resolution way of getting time than ftime? > > - Szymon For pentium and higher CPU's, you can use the high performance counter. Here is a simple little timer class I made to interface with the high performance counter. I hope this helps. -Bryan Cook bacook@stanford.edu ----------------------------------------------------------------------- #include #include #include class cTimer { public: cTimer() { LARGE_INTEGER Frequency; int Status = QueryPerformanceFrequency(&Frequency); assert(Status); //This will be 0 if the CPU doesn't support this CountPerSec = Frequency.LowPart; } void StartTimer() { QueryPerformanceCounter(&start); } void StopTimer() { QueryPerformanceCounter(&finish); } double GetTime() { return (((finish.HighPart - start.HighPart) * (double)UINT_MAX + (finish.LowPart - start.LowPart)) / (double)CountPerSec); } private: unsigned long CountPerSec; LARGE_INTEGER start, finish; };