【问题标题】:Time Step in PhysXPhysX 中的时间步长
【发布时间】:2014-01-07 15:04:10
【问题描述】:

我正在尝试在 PhysX 应用程序中为物理模拟定义一个时间步长,以便物理在所有机器上以相同的速度运行。我希望物理以 60FPS 的速度更新,所以每次更新的增量时间应该是 1/60 秒。

我的应用程序必须使用 GLUT。目前,我的循环设置如下。

空闲函数:

void GLUTGame::Idle()
{
    newElapsedTime = glutGet(GLUT_ELAPSED_TIME);
    deltaTime = newElapsedTime - lastElapsedTime;
    lastElapsedTime = newElapsedTime;

    glutPostRedisplay();
}

在这种情况下,帧速率并不重要 - 只有我的物理更新速度才是真正重要的。

我的渲染函数包含以下内容:

void GLUTGame::Render()
{
    // Rendering Code

    simTimer += deltaTime;

    if (simTimer > m_fps)
    {
        m_scene->UpdatePhys(m_fps);
        simTimer = 0;
    }
}

地点:

Fl32 m_fps = 1.f/60.f

但是,这会导致一些非常缓慢的更新,因为 deltaTime 在大多数循环中似乎等于 0(这实际上是不可能的......)我已经尝试将我的 deltaTime 计算移动到底部我的渲染函数,因为我认为空闲回调可能被调用得太频繁,但这并没有解决问题。有什么想法我在这里做错了吗?

【问题讨论】:

    标签: c++ time game-loop physx


    【解决方案1】:

    OpenGL website 中,我们发现glutGet(GLUT_ELAPSED_TIME)int 形式返回经过的毫秒数。因此,如果您每秒调用 void GLUTGame::Idle() 方法大约 2000 次,那么在一次这样的调用之后经过的时间大约是 1000 * 1/2000 = 0.5 毫秒。因此,每秒超过 2000 次调用 void GLUTGame::Idle() 会导致 glutGet(GLUT_ELAPSED_TIME) 由于整数舍入而返回 0

    【讨论】:

    • 接受这个答案,因为它引导我找到解决方案。由于 glutGet 不够准确,我改用了time.h 中的clock()clock_t,这似乎解决了这个问题。
    【解决方案2】:

    您可能会将非常小的数字添加到较大的数字中,并且会出现舍入错误。 试试这个:

    void GLUTGame::Idle()
    {
      newElapsedTime = glutGet(GLUT_ELAPSED_TIME);
      timeDelta = newElapsedTime - lastElapsedTime;
      if (timeDelta <  m_fps) return;
      lastElapsedTime = newElapsedTime;
    
      glutPostRedisplay();
    }
    

    如果你愿意,你可以在其他方法中做类似的事情。

    【讨论】:

    • 我已经尝试过了,但它似乎没有任何区别。 newElapstedTimedeltaTimelastElapsedTime 都是双打。尽管glutGetint 的形式返回毫秒,但我看不出有任何准确性问题的理由。
    【解决方案3】:

    我现在对 GLUT 或 PhysX 一无所知,但无论游戏运行多快,以下是如何以相同的速率(使用整数)执行某些东西:

    if (currentTime - lastUpdateTime > msPerUpdate)
    {
        DWORD msPassed = currentTime - lastUpdateTime;
        int updatesPassed = msPassed / msPerUpdate;
        for (int i=0; i<updatesPassed; i++)
            UpdatePhysX(); //or whatever function you use
        lastUpdateTime = currentTime - msPassed + (updatesPassed * msPerUpdate);
    }
    

    其中currentTime 更新为timeGetTime 每次运行通过游戏循环,lastUpdateTime 是最后一次更新 PhysX,msPerUpdate 是您分配给每次更新的毫秒数 - 16 或 17 毫秒60帧

    如果你想支持浮点更新因子(推荐用于物理应用程序),那么定义 float timeMultiplier 并像这样每帧更新它:timeMultiplier = (float)frameRate / desiredFrameRate; - 其中frameRate 是不言自明的,@ 987654329@ 是 60.0f 如果你想以 60 fps 更新物理。为此,您必须将 UpdatePhysX 更新为采用 float 参数,它将所有更新因子乘以。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 2019-02-19
      • 1970-01-01
      • 1970-01-01
      • 2021-01-16
      • 2020-03-06
      相关资源
      最近更新 更多