c++ - timeGetTime() 开始变量大于结束变量

标签 c++ windows ogre

我正在使用 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;
}

我在主函数中使用了 timeBeginPeriod(1)timeEndPeriod(1)

最佳答案

甚至没有阅读完整的问题,以下内容:

using timeGetTime() t limit the framerate to 60 frames per second
...
Sleep for the remainder of the second

可以坚定地回答“你做错了”。换句话说,就此打住,并采取不同的方法。

timeGetTime 也没有所需的精度(即使您使用 timeBeginPeriod(1)),Sleep 也没有所需的精度,Sleep 也不保证最大持续时间,Sleep 的语义甚至与您期望的相差甚远, sleep 也不能正确地限制帧速率方法。
此外,计算秒的余数将不可避免地引入系统误差,该误差会随着时间的推移而累积。

限制帧率的唯一正确方法是使用垂直同步。

如果您需要以其他方式将模拟限制为特定速率,使用可等待计时器是正确的方法。这仍然会受到调度程序精度的影响,但它会避免累积系统错误,并且优先级提升将至少提供事实上的软实时保证。

为了理解为什么您正在做的事情(除了精度和累积错误)在概念上是错误的,请考虑两件事:

  1. 不同的计时器,即使它们以明显相同的频率运行,也会有所不同(因此,使用除垂直同步中断之外的任何计时器来限制帧速率都是错误的)。观看红色交通信号灯处的汽车,以进行现实类比。他们的信号灯将总是不同步。
  2. Sleep 使当前线程“未准备好”运行,并最终在指定时间过后的某个时间再次使线程“准备好”。这并不意味着该线程将在那个时间再次运行。事实上,这并不一定意味着线程会在任何有限的时间内运行。
  3. 分辨率通常在 16 毫秒左右(如果您调整调度程序的粒度,则为 1 毫秒,这是一种反模式——一些最近的架构通过使用未记录的 Nt API 支持 0.5 毫秒),这对于 1/60 秒的东西来说太粗糙了规模。

关于c++ - timeGetTime() 开始变量大于结束变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32670373/

相关文章:

windows - 在 Windows 上使用 Youtube-dl 提取 MP3 的问题

linux - 将 .bat 转换为 .sh

c++ - 将 ogre3d 与全息透镜集成

c++ - 头文件中类的私有(private)成员的链接器错误

windows - 一家考虑使用Azure的小型开发公司

c++ - 动态分配 float 组并将其设置为零

c++ - 访问网格的顶点

c++ - 制作对象的多个版本

Android C++ framebuffer ioctl,只有 root?

c++ - 最简单的代码上的“imspossible”错误