4
\$\begingroup\$

UPDATE: I have found that the delays happen when i press a key in the keyboard and move the mouse at the same time, how can i solve it?

I checked it setting a constant speed to the camera(going forward) and disabled the interactions with the keyboard. The lag didnt appear when i was moving forward while rotating the camera, but happened when i pressed keys(with no functions because i disabled them) while i was moving the mouse

I will let here my initial question, but the problem is not because of the code, it is about the keyboard + mouse use. IGNORE WHAT FOLLOWS

=======================================================================

I am running out of ideas of what could be the reason for this, but when i move and rotate the camera an insane lag appers(but it doesnt show of in the FPS, they are always around 120). It doesnt happen when i just rotate the camera or translate it.

Video to show the problem:

https://www.youtube.com/watch?v=3UuXZLzU-As&feature=youtu.be

What could be the reason for this? I tried:

  • To use raw input, but because it didnt solve it i rolled back.
  • Rewrite the camera view calculations.

I am using Vulkan, at the moment on Windows.

Ill include some code:

View update:

void Camera::UpdateView()
{
    glm::mat4 rotate = glm::mat4_cast(GetRotation());
    glm::mat4 translate = glm::mat4(1.0f);
    translate = glm::translate(translate, -GetPosition());

    Matrices.view = rotate*translate;

    glm::mat4 matInverseView = glm::inverse(Matrices.view);
    forward = glm::normalize(glm::vec3(matInverseView[2]));
    right = glm::normalize(glm::vec3(matInverseView[0]));
}

Pitch and yaw update:

void Camera::ActiveMouseUpdate(Input * input, double deltaTime)
{
    if (input->MouseMoved())
    {
        yaw -= MOUSE_SENSIBILITY * input->GetMouseSpeed().x*deltaTime;
        pitch += MOUSE_SENSIBILITY * input->GetMouseSpeed().y*deltaTime;
        pitch = glm::clamp(pitch, glm::radians(-85.0f), glm::radians(85.0f));
        CalculateComponents();
        cameraChanged = true;
    }

}

Rotation update:

void Camera::CalculateComponents()
{
    glm::quat qPitch = glm::angleAxis(pitch, glm::vec3(1, 0, 0));
    glm::quat qYaw = glm::angleAxis(yaw, glm::vec3(0, 1, 0));
    glm::quat qRoll = glm::angleAxis(roll, glm::vec3(0, 0, 1));
    glm::quat orientation = glm::normalize(qPitch * qYaw*qRoll);

    SetRotation(orientation);
}

Movement:

void Camera::PassiveKeyboardUpdate(Input * input, double deltaTime)
{
    cameraChanged = false;

    glm::vec3 pos = GetPosition();

    if (input->isKeyDown(KEY_W))
    {
        pos -= (float)deltaTime*forward*speed;
        cameraChanged = true;
    }
    if (input->isKeyDown(KEY_S))
    {
        pos += (float)deltaTime*forward*speed;
        cameraChanged = true;
    }
    if (input->isKeyDown(KEY_D))
    {
        pos += (float)deltaTime*right*speed;
        cameraChanged = true;
    }
    if (input->isKeyDown(KEY_A))
    {
        pos -= (float)deltaTime*right*speed;
        cameraChanged = true;
    }
}

How my loop works:

void CoreEngine::Loop()
{
    while (renderer->Run())
    {
        UpdateFPS();
        UpdateInput();
        Update();
        Draw();
    }
}

Update input:

void CoreEngine::UpdateInput()
{
    input->Update();
    if(input->KeyboardChanged())
        root->ActiveKeyboardUpdate(input, deltaTime);
    root->PassiveKeyboardUpdate(input, deltaTime);
    if (input->MouseChanged())
        root->ActiveMouseUpdate(input, deltaTime);
}

Update:

void CoreEngine::Update()
{
    root->Update(deltaTime,enlapse);
}

Draw:

void CoreEngine::Draw()
{
    renderer->PrepareFrame();
    renderer->Draw();
    renderer->DrawTextOverlay();
    renderer->PresentDraw();
    renderer->UpdateUniformBuffers(false);
}

Root is the root node of my object tree which call all objects(nodes) attached updates, which nodes also call their own nodes updates.

UPDATE: I found that if i change this:

case WM_MOUSEMOVE:
    if (captureWindow)
    {
        mousePosition.x = LOWORD(lParam);
        mousePosition.y = HIWORD(lParam);
        mouseChangeState = true;
        if (forcedMouseMove)
        {
            lastUpdatePosition = mousePosition;
            forcedMouseMove = false;
        }
        else
            SetCursorCenter();
    }
    break;

For this:

case WM_MOUSEMOVE:
    if (captureWindow)
    {
        mousePosition.x = LOWORD(lParam);
        mousePosition.y = HIWORD(lParam);
        mouseChangeState = true;
        if (forcedMouseMove)
        {
            lastUpdatePosition = mousePosition;
            forcedMouseMove = false;
        }
        else if(glm::abs(mousePosition.x + screen.left - Middle.x ) > 400 || glm::abs(mousePosition.y + screen.top - Middle.y) > 300)
            SetCursorCenter();
    }
    break;

Where:

void Input::SetCursorCenter()
{
    SetCursorPos(Middle.x, Middle.y);
    ForceMove(true);
}
  • Middle: Is the center of the window
  • screen: Is the rectangle that contains the window.

The effect is less appreciable, but still there(i still want to solve this less appreciation). I also interpolated the movement, rotation and forward and right vectors.

\$\endgroup\$
7
  • \$\begingroup\$ Sometimes if your camera is updating out of step with other objects in your world, you can get a "judder" effect that looks like a choppy framerate, even if each part is updating frequently. For instance, if your character's walking and your camera rotation don't always happen in the same order, you might sometimes get two rotation steps between position updates or vice versa. This is especially prone to happen if your character movement is using a fixed timestep and the camera uses a variable timestep without interpolating. Can you show us the translation part & how your loop works? \$\endgroup\$
    – DMGregory
    May 20, 2017 at 14:06
  • \$\begingroup\$ Thank you for reply. I updated the post if you need more information just ask for it. About the character, there is no character attached to the camara, right now it is just a free cam. I dont use interpolation, can it be the cause? \$\endgroup\$
    – Haruko
    May 20, 2017 at 16:16
  • \$\begingroup\$ I interpolated it and it continue happening, i changed: orientation = glm::mix(GetRotation(), orientation, 0.5f); In the UpdateView method. \$\endgroup\$
    – Haruko
    May 20, 2017 at 17:12
  • \$\begingroup\$ @DMGregory i added a video to show you how it looks like. Hope it helps. \$\endgroup\$
    – Haruko
    May 20, 2017 at 18:28
  • 1
    \$\begingroup\$ @IanYoung deltaTime is not the right interpolation weight either. Approaching by 50% each tick is an exponential change, so we can't time correct it the same way we would a linear change. I show a formula for time-correcting an exponential blend in this answer. For maximum correctness we'd want a Slerp here, but the difference should be unnoticeably small for typical camera moves. \$\endgroup\$
    – DMGregory
    May 30, 2017 at 18:56

1 Answer 1

1
\$\begingroup\$

After tons of checks and time, i solved the problem.

Just add

    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

At the beginning of your loop if you have this problem. It will take care of all messages from your inputs before the loop begins solving the problem.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .