0

我正在尝试为 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 计算移动到我的渲染函数的底部,因为我认为空闲回调可能被调用太频繁,但这并没有解决问题。有什么想法我在这里做错了吗?

4

3 回答 3

2

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

于 2014-01-07T15:33:52.157 回答
0

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

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

  glutPostRedisplay();
}

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

于 2014-01-07T15:14:23.157 回答
0

我现在对 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中更新的位置是 PhysX 的最后一次更新时间,以及您分配给每次更新的毫秒数 - 16 或 17 毫秒(60 fps)timeGetTimelastUpdateTimemsPerUpdate

如果你想支持浮点更新因子(推荐用于物理应用程序),然后float timeMultiplier像这样定义和更新每一帧:timeMultiplier = (float)frameRate / desiredFrameRate;- 如果你想以 60 fps 的速度更新物理,这里frameRate是不言自明的,desiredFramerate是 60.0f。为此,您必须更新UpdatePhysX为将float所有更新因子乘以的参数。

于 2014-01-07T17:08:10.837 回答