Having a slight problem moving my camera based on time passed using GLUT/OpenGL

814 views Asked by At

Before anyone asks, this is for a university project and I have to use GLUT. I'm not tagging this as homework because this is not a requirement, nor will I have extra points for this.

With GLUT, for people unaware, you have:

  • glutIdleFunc(func): registers the render function and this means that when GLUT is not doing anything else, it will call this function. In other words, it will keep rendering as fast as possible.
  • glutTimerFunc(msecs, func, val): registers a function that will be called in msecs and the registering the same function recursively would allow for a fixed time based movement.

Now, I'm trying to avoid these functions for this purpose and most discussions/articles I found about GLUT, use them for time based movement. So I have come here once again... But if I'm not using any of those functions, how are the frames rendered? I just call glutPostRedisplay and a single frame will be rendered.

I have managed to implement time based movement in GLUT in a simple manner. May not be the best implementation, but it's not overly complex and works. Well, there's only a slight problem, that's why I'm here.

My camera movement is based on Newton's Second Law of Motion, where I calculate the displacement movement like this:

Vector3D displacement = (CurrentVelocity * elapsedTime) +
    (Acceleration * 0.5f * elapsedTime * elapsedTime);

The elapsedTime comes from my timer implementation and I think that's where the problem lies. The problem is that displacement should be positive or negative depending on the movement direction but if CurrentVelocity is a really low value (ie: -0.1f), the displacement will be positive when it should be negative. The rest of the code will accelerate or deacelerate the camera, so the problem only happens when accelerating because that's when CurrentVelocity will be small and what happens is that the camera moves slightly to the right (positive) and then to the left (negative) when it gains enough momentum to give a negative displacement value.

Now, when there's no movement in the scene, nothing is being rendered at all. When I press on of the movement keys, I do this:

CameraDirection.z = CAMERA_WALK_BACKWARD;
SceneTimer.PostRedisplayWindow();

That also comes from my timer class, I do that instead of calling glutPostRedisplay and the reason for that is this:

void Timer::PostRedisplayWindow(void) {
    currentTime = glutGet(GLUT_ELAPSED_TIME);
    glutPostRedisplay();
}

I need to get the currentTime (which will become the previousTime when I need to calculate the elapsed time) and then I call glutPostRedisplay. A single frame will be rendered, which means the renderScene will be called:

void renderScene(void) {
    (...)

    glLoadIdentity();

    elapsedTime = SceneTimer.GetElapsedTimeInSeconds();

    SceneCamera.Move(CameraDirection, elapsedTime);
    SceneCamera.LookAt();

    drawCompleteScene();

    glutSwapBuffers();

    checkAnimationRedisplay();
}

As you can see, the elapsed time is calculated and the camera is moved on that. Everything in the scene is drawn, swap buffers and then I have this extra function which will check if something needs to be animated, in this case, the camera needs:

void checkAnimationRedisplay(void) {
    if(SceneCamera.IsCameraMoving()) {
        glutPostRedisplay();
        return;
    }
}

It will keep calling glutPostRedisplay until the camera has stopped moving. Meaning, renderScene will be called every time, the elapsed time is calculated and the camera is moved based on time, everything's working; besides, of course, the little glitch already mentioned, little but the one that made me create this long question (sorry about that).

All that's missing is the most important function of this question, the one that calculates the elapsed time, simple as this:

float Timer::GetElapsedTimeInSeconds(void) { static int previousTime = 0; static int elapsedTime = 0;

previousTime = currentTime;
currentTime = glutGet(GLUT_ELAPSED_TIME);
elapsedTime = currentTime - previousTime;

return elapsedTime / 1000.0f;

}

There's probably something wrong with my timer code right? I mean, moving forward or right (positive values), there's no problems. The movement is smooth and time based. For instance, if I set a movement speed of 5m/s, it will actually take 5 seconds to move 25meters (I'm assuming 1m = 1.0f).

So, what I'm doing wrong with the timer so that the negative values start moving to the right for a split-second and only then to the left as it should?

1

There are 1 answers

0
rfgamaral On BEST ANSWER