简体   繁体   English

OpenGL3 SFML 2.0rc FPS样式相机-摇晃的鼠标移动

[英]OpenGL3 SFML 2.0rc FPS-style camera - shaky mouse movement

I'm trying to make a first person shooter style camera for my project. 我正在尝试为我的项目制作第一人称射击风格的相机。 Everything looks smooth if I'm moving forward or back, strafing left or right, or going diagonal... The problem is when I look around with the mouse while moving, the movements get really jittery. 如果我向前或向后移动,向左或向右横扫或对角线移动,一切都会看起来很顺畅。问题是当我在移动时用鼠标环顾四周时,动作确实变得抖动。 It is most prominent when I am strafing and turning with the mouse at the same time. 当我同时用鼠标行走和转动时,这是最突出的。

I'm convinced my problem is similar to this: http://en.sfml-dev.org/forums/index.php?topic=4833.msg31550#msg31550 , however I am using Gentoo Linux, not OSX. 我确信我的问题与此类似: http : //en.sfml-dev.org/forums/index.php?topic=4833.msg31550#msg31550 ,但是我使用的是Gentoo Linux,而不是OSX。

It's quite likely that it's not SFML's fault though, and that I did something wrong, so I would like to get some feedback on my event handling code to see if there's a better way to get smooth mouse movements. 不过,这很可能不是SFML的错,而且我做错了事,所以我想从事件处理代码中获得一些反馈,以查看是否有更好的方法来使鼠标平滑移动。

In case you don't want to read through the link I posted, the short of what I think is happening is the mouse movement velocity is being lost every frame when I set the mouse's position back to the center of the screen, which causes a quick visible jerk on screen. 如果您不想通读我发布的链接,那么我认为正在发生的事情是当我将鼠标的位置重新设置到屏幕中央时,每帧鼠标的移动速度都会丢失,这会导致在屏幕上快速可见的混蛋。 This is my going theory as I've tried changing other stuff around for 3 days now and nothing I do makes it less jerky. 这是我的理论,因为我已经尝试了3天左右的时间来更改其他内容,但我所做的任何事情都不会使它变得更加生涩。 So I would like to know if anyone has a better way of handling the mouse movements, or whether you think the problem lies elsewhere. 因此,我想知道是否有人能更好地处理鼠标移动,或者您是否认为问题出在其他地方。

An important note is I have enabled vsync which made a lot of other jitteriness and tearing go away, and I tried using a hard framerate limit like sf::Window::setFramerateLimit(60), but that didn't help at all. 一个重要的注意事项是我启用了vsync,它消除了许多其他的抖动和撕裂感,并且尝试使用像sf :: Window :: setFramerateLimit(60)这样的硬帧速率限制,但这一点都没有帮助。

Here is the event handler (which uses the SFML 2.0 realtime interfaces instead of an event loop), you can probably ignore the part related to jumping: 这是事件处理程序(它使用SFML 2.0实时接口而不是事件循环),您可能会忽略与跳转有关的部分:

void Test_World::handle_events(float& time)
{
    // camera stuff
    _mouse_x_pos = sf::Mouse::getPosition(*_window).x;
    _mouse_y_pos = sf::Mouse::getPosition(*_window).y;

    std::cout << "mouse x: " << _mouse_x_pos << std::endl;
    std::cout << "mouse y: " << _mouse_y_pos << std::endl;

    _horizontal_angle += time * _mouse_speed * float(_resolution_width/2 - _mouse_x_pos);
    _vertical_angle += time * _mouse_speed * float(_resolution_height/2 - _mouse_y_pos);

    // clamp rotation angle between 0 - 2*PI
    if (_horizontal_angle > 3.14f*2) _horizontal_angle = 0;
    if (_horizontal_angle < 0) _horizontal_angle = 3.14f*2;

    // clamp camera up/down values so we can't go upside down
    if (_vertical_angle >= 3.14f/2.0f) _vertical_angle = 3.14f/2.0f;
    if (_vertical_angle <= -3.14f/2.0f) _vertical_angle = -3.14f/2.0f;

    std::cout << "horiz angle: " << _horizontal_angle << std::endl;
    std::cout << "vert angle: " << _vertical_angle << std::endl;

    _direction = glm::vec3( cos(_vertical_angle) * sin(_horizontal_angle),
                            sin(_vertical_angle),
                            cos(_vertical_angle) * cos(_horizontal_angle) );

    _right = glm::vec3( sin(_horizontal_angle - 3.14f/2.0f),
                        0,
                        cos(_horizontal_angle - 3.14f/2.0f) );

    _up = glm::cross( _right, _direction );

    // keyboard: left, right, up, down
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::A))
    {
        if (_jumping)
        {
            _position -= _right * time * _speed * ((_jump_speed/2) + 0.1f);
        }
        else
        {
            _position -= _right * time * _speed;
        }
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right) || sf::Keyboard::isKeyPressed(sf::Keyboard::D))
    {
        if (_jumping)
        {
            _position += _right * time * _speed * ((_jump_speed/2) + 0.1f);
        }
        else
        {
            _position += _right * time * _speed;
        }
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::W))
    {
        glm::vec3 old_direction(_direction);
        _direction.y = 0;

        if (_jumping)
        {
            _position += _direction * time * _speed * ((_jump_speed/2) + 0.1f);
        }
        else
        {
            _position += _direction * time * _speed;
        }

        _direction = old_direction;
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::S))
    {
        glm::vec3 old_direction(_direction);
        _direction.y = 0;

        if (_jumping)
            _position -= _direction * time * _speed * ((_jump_speed/2) + 0.1f);
        else
            _position -= _direction * time * _speed;

        _direction = old_direction;
    }

    // keyboard: jump
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
    {
        // check if standing on something
        if (_standing)
        {
            _standing = false;
            _jumping = true;
        }
    }

    // apply gravity if off the ground
    if (_position.y > _main_character_height && !_jumping)
        _position.y -= time * _speed * _global_gravity;

    // if started jumping
    else if (_position.y < _main_character_height + _jump_height - 3.0f && _jumping)
    {
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
        {
            _position.y += time * _speed * _jump_speed;
        }
        else    // if stopped jumping
        {
            _position += _direction * time * (_speed/(_jump_hang_time*2));
            _jumping = false;
        }
    }

    // if near the highest part of the jump
    else if (_position.y <= _main_character_height + _jump_height && _jumping)
    {
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
        {
            _position.y += time * _speed * (_jump_speed/_jump_hang_time);
        }
        else    // if stopped jumping
        {
            _position += _direction * time * (_speed/(_jump_hang_time*2));
            _jumping = false;
        }
    }

    // if reached the highest part of the jump
    else if (_position.y >= _main_character_height + _jump_height)
    {
        _position += _direction * time * (_speed/_jump_hang_time);
        _jumping = false;
    }
    else if (_position.y <= _main_character_height)
    {
        _standing = true;
    }

    sf::Mouse::setPosition(_middle_of_window, *_window);
}

After the events, I am changing my _view_matrix like this: 事件发生后,我将像这样更改_view_matrix:

_view_matrix = glm::lookAt( _position, _position+_direction, _up );

Then, I recalculate my _modelview_matrix and _modelviewprojection_matrix: 然后,我重新计算_modelview_matrix和_modelviewprojection_matrix:

_modelview_matrix = _view_matrix * _model_matrix;
_modelviewprojection_matrix = _projection_matrix * _modelview_matrix;

After that I finally send the matrices to my shaders and draw the scene. 之后,我最终将矩阵发送到我的着色器并绘制场景。

I am open to any sage wisdom/advice with regards to OpenGL3, SFML 2.0, and/or FPS-style camera handling, and please let me know if it would help to include more code (if you think the problem isn't in the event handling, for example). 对于OpenGL3,SFML 2.0和/或FPS样式的相机处理,我乐于接受任何明智的建议/建议,请告诉我是否有助于添加更多代码(如果您认为问题不在解决之列)。例如事件处理)。 Thanks in advance for the help! 先谢谢您的帮助!

Edit: I still haven't solved this problem, and FYI it doesn't look like the framerate is dropping at all during the shaky movements... 编辑:我仍然没有解决这个问题,仅供参考,在不稳定的移动过程中,帧率似乎根本没有下降...

If I was you I would hide the mouse using this tutorial and then only move the mouseposition when it got to the edge of the screen moving it to the opposite side so it can continue in that direction un-impeded. 如果您是我,则可以使用本教程隐藏鼠标,然后仅在鼠标位置到达屏幕边缘时才将其移动到另一侧,以便它可以不受阻碍地沿该方向继续前进。 May not be the best solution, but I'm pretty sure it'll fix your issue. 可能不是最好的解决方案,但是我敢肯定,它将解决您的问题。

... another idea is to do some remembering and reckoning as to what they are doing and not use the position data itself, but simply use the position data to guide the reckoning (ie use physics to control it instead of the raw data). ...另一个想法是对他们正在做的事情做一些记忆和估算,而不是使用位置数据本身,而只是使用位置数据来指导估算(即使用物理学代替原始数据来控制它)。

Just my thoughts, hope they help^^ 只是我的想法,希望对他们有帮助^^

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM