在有人问之前,这是一个大学项目,我必须使用 GLUT。我没有将此标记为作业,因为这不是必需的,我也不会为此加分。
使用 GLUT,对于不知情的人,您可以:
glutIdleFunc(func)
: 注册渲染函数,这意味着当 GLUT 没有做任何其他事情时,它会调用这个函数。换句话说,它将尽可能快地保持渲染。glutTimerFunc(msecs, func, val)
: 注册一个将被调用的函数,msecs
并且递归地注册相同的函数将允许基于固定时间的移动。
现在,为了这个目的,我试图避免使用这些功能,并且我发现的关于 GLUT 的大多数讨论/文章都将它们用于基于时间的移动。所以我又来了……但是如果我不使用这些功能中的任何一个,帧是如何渲染的?我只是打电话glutPostRedisplay
,一个单一的帧将被渲染。
我设法以一种简单的方式在 GLUT 中实现了基于时间的运动。可能不是最好的实现,但它并不过分复杂且有效。好吧,只有一个小问题,这就是我在这里的原因。
我的相机运动基于牛顿第二运动定律,我计算位移运动如下:
Vector3D displacement = (CurrentVelocity * elapsedTime) +
(Acceleration * 0.5f * elapsedTime * elapsedTime);
elapsedTime
来自我的计时器实现,我认为这就是问题所在。问题是它displacement
应该是正数还是负数取决于运动方向,但如果CurrentVelocity
是一个非常低的值(即:-0.1f),那么displacement
当它应该是负数时它将是正数。其余代码将加速或减速相机,因此问题仅在加速时发生,因为那时CurrentVelocity
会很小,发生的情况是相机略微向右(正)移动,然后向左(负)移动获得足够的动量以给出负值displacement
。
现在,当场景中没有运动时,根本没有渲染任何内容。当我按下移动键时,我会这样做:
CameraDirection.z = CAMERA_WALK_BACKWARD;
SceneTimer.PostRedisplayWindow();
这也来自我的计时器类,我这样做而不是调用glutPostRedisplay
,原因是:
void Timer::PostRedisplayWindow(void) {
currentTime = glutGet(GLUT_ELAPSED_TIME);
glutPostRedisplay();
}
我需要得到currentTime
(这将成为previousTime
我需要计算经过时间的时间),然后我打电话给glutPostRedisplay
. 将呈现单个帧,这意味着renderScene
将调用:
void renderScene(void) {
(...)
glLoadIdentity();
elapsedTime = SceneTimer.GetElapsedTimeInSeconds();
SceneCamera.Move(CameraDirection, elapsedTime);
SceneCamera.LookAt();
drawCompleteScene();
glutSwapBuffers();
checkAnimationRedisplay();
}
如您所见,计算了经过的时间,并在其上移动了相机。场景中的所有内容都被绘制,交换缓冲区,然后我有这个额外的功能,它将检查是否需要动画,在这种情况下,相机需要:
void checkAnimationRedisplay(void) {
if(SceneCamera.IsCameraMoving()) {
glutPostRedisplay();
return;
}
}
它会一直调用glutPostRedisplay
,直到相机停止移动。意思是,renderScene
每次都会调用,计算经过的时间并根据时间移动相机,一切正常;此外,当然,还有已经提到的小故障,只是让我提出这个长问题的小故障(对此感到抱歉)。
缺少的只是这个问题最重要的功能,即计算经过时间的功能,简单如下:
float Timer::GetElapsedTimeInSeconds(void) { static int previousTime = 0; 静态int elapsedTime = 0;
previousTime = currentTime;
currentTime = glutGet(GLUT_ELAPSED_TIME);
elapsedTime = currentTime - previousTime;
return elapsedTime / 1000.0f;
}
我的计时器代码可能有问题,对吗?我的意思是,向前或向右(正值),没有问题。运动平稳且基于时间。例如,如果我将移动速度设置为 5m/s,实际上移动 25 米需要 5 秒(我假设 1m = 1.0f)。
那么,我在计时器上做错了什么,以至于负值开始向右移动一秒钟,然后才向左移动?