Шаг по времени в PhysX

Я пытаюсь определить временной шаг для симуляции физики в приложении 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 в конец моей функции рендеринга , поскольку я думал, что, возможно, обратный вызов в режиме ожидания вызывался слишком часто, но это не решило проблему. Есть идеи, что я здесь делаю не так?

0

Решение

От Сайт OpenGL, мы находим, что glutGet(GLUT_ELAPSED_TIME) возвращает количество пройденных миллисекунд в виде ИНТ. Итак, если вы позвоните void GLUTGame::Idle() метод около 2000 раз в секунду, затем время, прошедшее после одного такого вызова, составляет около 1000 * 1/2000 = 0,5 мс. Таким образом, более 2000 вызовов в секунду, чтобы аннулировать GLUTGame::Idle() результаты в glutGet(GLUT_ELAPSED_TIME) возврате 0 из-за целочисленного округления.

2

Другие решения

Скорее всего, вы добавляете очень маленькие числа к более крупным, и вы получаете ошибки округления.
Попробуй это:

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

glutPostRedisplay();
}

Вы можете сделать что-то подобное в другом методе, если хотите.

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 обновляется до timeGetTime каждый проход по игровому циклу, lastUpdateTime последний раз обновляется PhysX, и msPerUpdate количество миллисекунд, которое вы назначаете каждому обновлению — 16 или 17 мс для 60 кадров в секунду

Если вы хотите поддерживать коэффициенты обновления с плавающей запятой (что рекомендуется для физических приложений), тогда определите float timeMultiplier и обновлять его каждый кадр так: timeMultiplier = (float)frameRate / desiredFrameRate; — где frameRate говорит само за себя и desiredFramerate равно 60.0f, если вы хотите обновить физику со скоростью 60 кадров в секунду. Для этого нужно обновить UpdatePhysX как принимая float параметр, на который он умножает все коэффициенты обновления.

0
По вопросам рекламы [email protected]