timeGetTime()开始变量大于结束变量
timeGetTime() start variable is bigger than end variable
我使用timeGetTime()
将帧率限制为每秒60帧。我打算这样做的方法是获得渲染60帧所需的时间,然后使用Sleep来等待剩余的时间。但由于某种原因,timeGetTime()
在我第一次调用它时返回的数字比在渲染60帧后调用它时返回的数字要大得多。
代码如下:
头
#ifndef __TesteMapa_h_
#define __TesteMapa_h_
#include "BaseApplication.h"
#include "Mundo.h"
class TesteMapa : public BaseApplication{
public:
TesteMapa()
virtual ~TesteMapa();
protected:
virtual void createScene();
virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);
virtual bool frameEnded(const Ogre::FrameEvent& evt);
virtual bool keyPressed(const OIS::KeyEvent &evt);
virtual bool keyReleased(const OIS::KeyEvent &evt);
private:
Mundo mundo = Mundo(3,3,3);
short altura, largura, passos, balanca, framesNoSegundo=0;
Ogre::SceneNode *noSol, *noSolFilho, *noCamera;
DWORD inicioSegundo = 0, finala;//inicioSegundo is the start variable and finala the ending variable
};
#endif
CPP相关功能
bool TesteMapa::frameEnded(const Ogre::FrameEvent& evt){
framesNoSegundo++;
if (inicioSegundo == 0)
inicioSegundo = timeGetTime();
else{
if (framesNoSegundo == 60){
finala = timeGetTime(); //getting this just to see the value being returned
Sleep(1000UL - (timeGetTime() - inicioSegundo));
inicioSegundo = 0;
framesNoSegundo = 0;
}
}
return true;
}
我在main函数中使用timeBeginPeriod(1)
和timeEndPeriod(1)
甚至不阅读完整的问题,以下:
使用timeGetTime ()将帧率限制为每秒60帧
的剩余时间
…休眠第二个
可以用坚定的"You are doing it wrong"来回答。换句话说,到此为止,采取不同的方法。
timeGetTime
也没有必要的精度(即使你使用timeBeginPeriod(1)
也没有),Sleep
也没有所需的精度,Sleep
也没有提供任何关于最大持续时间的保证,Sleep
的语义也不接近你所期望的,睡眠也不是限制帧率的正确方法。
此外,计算秒的余数将不可避免地引入一个系统误差,该误差将随着时间的推移而累积。
限制帧率的唯一正确方法是使用垂直同步。
如果您需要将模拟限制为特定的速率,则使用可等待计时器是正确的方法。这仍然受制于调度器的精度,但它将避免累积系统错误,并且优先级提升将至少提供事实上的软实时保证。
为了理解为什么你所做的事情(除了精度和累积的错误)在概念上是错误的,考虑两件事:
- 不同的计时器,即使它们在明显相同的频率下运行,也会发散(因此,使用除垂直同步中断之外的任何计时器都是错误的来限制帧速率)。在现实生活中观察红灯时的汽车。总是不同步。
-
Sleep
使当前线程"未准备好"运行,最终,在指定的时间过去一段时间后,使线程再次"准备好"。这并不意味着线程会在那个时候再次运行。事实上,这并不一定意味着线程将在任何有限的时间内运行。 - 分辨率通常在16ms左右(如果你调整调度器的粒度为1ms,这是一个反模式——一些最近的架构通过使用未记录的Nt API支持0.5ms),这对于1/60秒的尺度来说太粗糙了。
如果你使用的是Visual Studio 2013或更早的版本,std::chrono使用64hz的计时器(15.625 ms/tick),这是很慢的。VS 2015应该会解决这个问题。你可以用QueryPerformanceCounter代替。下面的示例代码以固定频率运行,没有漂移,因为延迟是基于计数器的原始读取。dwLateStep是一种调试辅助工具,如果一个或多个步骤花费的时间太长,它会增加。该代码与Windows XP兼容,其中Sleep(1)最多可以占用2毫秒,这就是为什么代码只在有2毫秒或更长时间延迟时才执行Sleep。
typedef unsigned long long UI64; /* unsigned 64 bit int */
#define FREQ 60 /* frequency */
DWORD dwLateStep; /* late step count */
LARGE_INTEGER liPerfFreq; /* 64 bit frequency */
LARGE_INTEGER liPerfTemp; /* used for query */
UI64 uFreq = FREQ; /* thread frequency */
UI64 uOrig; /* original tick */
UI64 uWait; /* tick rate / freq */
UI64 uRem = 0; /* tick rate % freq */
UI64 uPrev; /* previous tick based on original tick */
UI64 uDelta; /* current tick - previous */
UI64 u2ms; /* 2ms of ticks */
UI64 i;
/* ... */ /* wait for some event to start thread */
QueryPerformanceFrequency(&liPerfFreq);
u2ms = ((UI64)(liPerfFreq.QuadPart)+499) / ((UI64)500);
timeBeginPeriod(1); /* set period to 1ms */
Sleep(128); /* wait for it to stabilize */
QueryPerformanceCounter(&liPerfTemp);
uOrig = uPrev = liPerfTemp.QuadPart;
for(i = 0; i < (uFreq*30); i++){
/* update uWait and uRem based on uRem */
uWait = ((UI64)(liPerfFreq.QuadPart) + uRem) / uFreq;
uRem = ((UI64)(liPerfFreq.QuadPart) + uRem) % uFreq;
/* wait for uWait ticks */
while(1){
QueryPerformanceCounter((PLARGE_INTEGER)&liPerfTemp);
uDelta = (UI64)(liPerfTemp.QuadPart - uPrev);
if(uDelta >= uWait)
break;
if((uWait - uDelta) > u2ms)
Sleep(1);
}
if(uDelta >= (uWait*2))
dwLateStep += 1;
uPrev += uWait;
/* fixed frequency code goes here */
/* along with some type of break when done */
}
timeEndPeriod(1); /* restore period */
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 将数组的地址分配给变量并删除
- 为"adjacent"变量赋值时出现问题
- enum是C++中的宏变量还是整数变量
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 用C++中的一个变量定义一个常量
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 你能重载对象变量名本身返回的内容吗
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 尝试通过多个向量访问变量时,向量下标超出范围
- 试图让变量检查数组中的某些内容
- 如果变量数据包含大于 vector 所有元素的整数,则仅在视觉工作室上接收"矢量下标超出范围"?
- 为什么 UInt64 变量不能包含大于 UInt32::Max 的值?
- 我想预先递增变量的赋值(预递增值大于 1)?
- 当运算符尝试输入大于变量可以包含的值>>会发生什么情况?
- C++ 大于堆栈的变量(堆栈溢出)
- 变量的范围大于for循环,为什么它不改变值
- timeGetTime()开始变量大于结束变量