时间处理精确到微秒

作者在 2007-03-09 18:35:00 发布以下内容

在工业控制中,游戏动画中常常要用到精确延时的功能。
WINDOWS有几个很不错的API函数可以用,不过其精度不高,很难达到要求。精度只能到毫秒。
对于微秒的计时就不能用了。而在工业控制,和游戏中要求时间精度高的时间处理函数就只有自已编写了。
我们就使用最常用的:
QueryPerformanceFrequency();
QueryPerformanceCounter();
以上两个函数来完成这一功能。
以下是一个简单的例子用于计算SLEEP()函数用的时间,可见其精度不高:
void CTxDlg::OnButton2()
{
 // TODO: Add your control notification handler code here
  LARGE_INTEGER tc,tc_bak;
   __int64 t = 0;
   __int64 freq = 0;//freqence unit:Hz
   //Get freq
   QueryPerformanceFrequency(&tc);
   freq=tc.QuadPart;
   //tick start
   QueryPerformanceCounter(&tc_bak);
   //Test code
   ::Sleep(1);
   //tick end
   QueryPerformanceCounter(&tc);
   //time = ticks/freq
   t = ((tc.QuadPart - tc_bak.QuadPart)*1000000)/freq;
   //Report result.
   CString str;
   str.Format("Time used:%I64u uS or %I64u mS+ or about %I64u S+",t,t/1000,t/1000000);
   ::AfxMessageBox(str);
}

为了方便使用可以将这两个函数改成时间处理的类。以下是类代码:
#ifndef __TIMER_H_INCLUDED__
#define __TIMER_H_INCLUDED__
#include <windows.h>
class CHiResTimer
{
public:
  CHiResTimer() {}
  ~CHiResTimer() {}
/*****************************************************************************
 Init()
 If the hi-res timer is present, the tick rate is stored and the function
 returns true. Otherwise, the function returns false, and the timer should
 not be used.
*****************************************************************************/
bool Init()
{
  if (!QueryPerformanceFrequency(&m_ticksPerSecond))
  {
    // system doesn't support hi-res timer
    return false;
  }
  else
  {
    QueryPerformanceCounter(&m_startTime);
    return true;
  }
} // end Init()
float GetElapsedSeconds(unsigned long elapsedFrames = 1)
{
  static LARGE_INTEGER s_lastTime = m_startTime;
  LARGE_INTEGER currentTime;
  QueryPerformanceCounter(&currentTime);
  float seconds =  ((float)currentTime.QuadPart - (float)s_lastTime.QuadPart) / (float)m_ticksPerSecond.QuadPart;
  // reset the timer
  s_lastTime = currentTime;
  return seconds;
} // end GetElapsedSeconds()
/***************************************************************************
 GetFPS()
 Returns the average frames per second over elapsedFrames, which defaults to
 one. If this is not called every frame, the client should track the number
 of frames itself, and reset the value after this is called.
***************************************************************************/
float GetFPS(unsigned long elapsedFrames = 1)
{
  static LARGE_INTEGER s_lastTime = m_startTime;
  LARGE_INTEGER currentTime;
 QueryPerformanceCounter(&currentTime);
  float fps = (float)elapsedFrames * (float)m_ticksPerSecond.QuadPart / ((float)      currentTime.QuadPart - (float)s_lastTime.QuadPart);
  // reset the timer
  s_lastTime = currentTime;
  return fps;
} // end GetFPS
/***************************************************************************
 LockFPS()
 Used to lock the frame rate to a set amount. This will block until enough
 time has passed to ensure that the fps won't go over the requested amount.
 Note that this can only keep the fps from going above the specified level;
 it can still drop below it. It is assumed that if used, this function will
 be called every frame. The val

默认分类 | 阅读 3418 次
文章评论,共0条
游客请输入验证码
浏览61115次
文章分类