waffledave
waffledave

Reputation: 35

OpenGL Object rotatating at normal speed on PC but extremely fast on Laptop

I have one issue to do with handling input to rotate the object on screen.

I coded everything on my desktop where it rotates as it should and you can manipulate the object in 3D space.

On my laptop however, when I try to rotate the object, it actually rotates so fast you can barely even see it. I'm talking like dozens of rotations per second.

My question is... Why? Why does it rotate at normal speed on my PC but at crazy high speed on my laptop?

The rotation I used for each key press is 0.1... On my PC it rotates fast enough to be able to control or, but on my Laptop (and tablet, I tested it on a tablet as well) it just rotates way too fast! I was able to fix it on my laptop by changing the rotation amount to glm::radians(1.0f) and it rotates at normal speed... But on my PC it is rather slower than I would like.

The only thing I can think of has something to do with delta time and the render speed (which I factored in to my camera controls).

Here is my rotation function for reference...

keyboard callback function (NOTE: I have an global array of Booleans called keys[], which I use to see if a key is being pressed)

// Handle the keyboard input
void keyPressed(GLFWwindow *_window, int key, int scancode, int action, int mods) {

// Close window with escape
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
    glfwSetWindowShouldClose(window, GL_TRUE);
// Change render to show points only with P
if (key == GLFW_KEY_P && action == GLFW_PRESS)
    glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
// Change render to show filled in texture with T
if (key == GLFW_KEY_T && action == GLFW_PRESS)
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Change render to show "wirefram" mesh with W
if (key == GLFW_KEY_W && action == GLFW_PRESS)
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

// Array of keys, if key is being held down, sets index corresponding to appropriate integer related to key to true, and false when key is released
if (key >= 0 && key < 1024)
{
    if (action == GLFW_PRESS)
        keys[key] = true;
    else if (action == GLFW_RELEASE)
        keys[key] = false;
}
return;
}

And the rotation function (NOTE: clicks[0] is another array of Booleans I use to see if left mouse button is being pushed):

// rotate object based on keyboard input
// Left mouse button must not be held down for this to work
// Creates a matrix containing the appriopriate transformation, and this is later multipled to the model matrix
void rotate_object(glm::mat4 &transform)
{
 // Rotate along z axis (left and right, like a barrel roll)
if (!click[0] && keys[GLFW_KEY_LEFT])
    transform = glm::rotate(transform, glm::radians(1.0f), glm::vec3(0.0f, 0.0f, 1.0f));
if (!click[0] && keys[GLFW_KEY_RIGHT])
    transform = glm::rotate(transform, glm::radians(-1.0f), glm::vec3(0.0f, 0.0f, 1.0f));
// Rotate along x axis (up and down, like a flip)
if (!click[0] && keys[GLFW_KEY_UP])
    transform = glm::rotate(transform, glm::radians(1.0f), glm::vec3(1.0f, 0.0f, 0.0f));
if (!click[0] && keys[GLFW_KEY_DOWN])
    transform = glm::rotate(transform, glm::radians(-1.0f), glm::vec3(1.0f, 0.0f, 0.0f));
// Rotate along y axes (make object spin)
if (!click[0] && keys[GLFW_KEY_K])
    transform = glm::rotate(transform, glm::radians(1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
if (!click[0] && keys[GLFW_KEY_L])
    transform = glm::rotate(transform, glm::radians(-1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
}

I appreciate your input!

Thanks,

Upvotes: 1

Views: 1878

Answers (3)

Brett Hale
Brett Hale

Reputation: 22308

You must make use of a timestamp between frames. GLFW has a portable glfwGetTime for this purpose. Your frame delta is current_time - previous_time, which you use to update your (animation) state with. You then set previous_time = current_time prior to your next frame, and repeat the process.

I'd also consider using glfwSwapInterval(1) to wait for vsync - provided your GPU driver honours it. Otherwise, you're just burning cycles doing unnecessary updates.

Upvotes: 2

Andrew Williamson
Andrew Williamson

Reputation: 8696

You are rotating your object using a constant value, with no respect to the amount of time that has passed since the previous rotation. When you run your code on different machines, you will end up with different rotation speeds, based on how fast the machine can process your drawing and update loop.

You need to keep track of time - keep the time of the last update, and the current update, and call the difference 'time delta'. Your rotation needs to be multiplied by 'time delta', so that even if the two machines process the code at different speeds, the object still rotates at the same speed.

Upvotes: 5

user1357959
user1357959

Reputation:

Given that there are no details on hardware or the systems used at all, I assume your significant difference in performance comes from either

  • Different graphics hardware or
  • Different drivers for said graphics hardware (or both)

When the same code runs with different performances on the two systems and your code doesn't seem to be the reason, this is the next best thing.

I assume that your input and draw functions are executed iteratively; so that the next input is only processed when the drawing function returned already. The drawing can take significantly longer on slower graphics hardware/machines. That's where the different you observe can result from.

Try out glxgears on both and see what FPS you get. If your PC is much slower than your laptop (in scales of 10^1 or more), then that's your issue.

Upvotes: 0

Related Questions