From 7102c4740d7062c471893d72335bcec4158ec9e4 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Sun, 20 Jun 2021 19:53:09 +0200 Subject: Add optional rotation locking to camera controller --- lbm.org | 68 ++++++++++++++++++++++++++++++++++++---------------- tangle/util/camera.h | 61 +++++++++++++++++++++++++++++++++------------- 2 files changed, 91 insertions(+), 38 deletions(-) diff --git a/lbm.org b/lbm.org index 9e0a7f7..1fe5777 100644 --- a/lbm.org +++ b/lbm.org @@ -4536,9 +4536,13 @@ delta between current and previous mouse location as well as the currently activ manipulation. #+BEGIN_SRC cpp :tangle tangle/util/camera.h -float2 _lastMouse; -bool _dragging; +float2 _mouse; + +bool _rotating; bool _moving; + +bool _restricted_x; +bool _restricted_y; #+END_SRC The =update= function projects the screen space forward, right and up vectors into world space. @@ -4559,38 +4563,51 @@ public: Camera(float3 target, float distance): _distance(distance), _target(target.x, target.y, target.z), - _dragging(false), - _moving(false) { + _rotating(false), + _moving(false), + _restricted_x(false), + _restricted_y(false) { update(); } #+END_SRC -The event handler accepts SFML-provided input events and selects the current manipulation -tool depending on which mouse button is pressed. +The event handler accepts SFML-provided input events to control rotation restrictions +as well as the currently selected tool. #+BEGIN_SRC cpp :tangle tangle/util/camera.h void handle(sf::Event& event) { switch (event.type) { + case sf::Event::KeyPressed: + if (event.key.code == sf::Keyboard::LShift && !_restricted_x && !_restricted_y) { + _restricted_x = true; + _restricted_y = true; + } + break; + case sf::Event::KeyReleased: + if (event.key.code == sf::Keyboard::LShift) { + _restricted_x = false; + _restricted_y = false; + } + break; case sf::Event::MouseButtonPressed: if (event.mouseButton.button == sf::Mouse::Left) { - _dragging = true; - _lastMouse = make_float2(event.mouseButton.x, event.mouseButton.y); + _rotating = true; } else if (event.mouseButton.button == sf::Mouse::Right) { _moving = true; - _lastMouse = make_float2(event.mouseButton.x, event.mouseButton.y); } + _mouse = make_float2(event.mouseButton.x, event.mouseButton.y); break; - case sf::Event::MouseButtonReleased: - if (event.mouseButton.button == sf::Mouse::Left) { - _dragging = false; - } else if (event.mouseButton.button == sf::Mouse::Right) { - _moving = false; - } + case sf::Event::MouseButtonReleased: { + bool restricted = _restricted_x + _restricted_y; + _restricted_x = restricted; + _restricted_y = restricted; + _rotating = false; + _moving = false; break; + } #+END_SRC -Next we change the translation and rotation vectors to zoom when the mouse wheel -is turned… +Next we change the translation and rotation vectors to zoom when the mouse wheel is turned… #+BEGIN_SRC cpp :tangle tangle/util/camera.h case sf::Event::MouseWheelMoved: @@ -4603,8 +4620,17 @@ is turned… #+BEGIN_SRC cpp :tangle tangle/util/camera.h case sf::Event::MouseMoved: float2 mouse = make_float2(event.mouseMove.x, event.mouseMove.y); - if (_dragging) { - float2 delta = 0.005 * (mouse - _lastMouse); + if (_rotating) { + float2 delta = 0.005 * (mouse - _mouse); + if (_restricted_x && _restricted_y) { + if (std::abs(delta.x) > std::abs(delta.y)) { + _restricted_y = false; + } else { + _restricted_x = false; + } + } + if (_restricted_x) { delta.y = 0; } + if (_restricted_y) { delta.x = 0; } glm::quat rotation_z = glm::vec3(0,0,delta.x); glm::quat rotation_x = glm::vec3(delta.y,0,0); _rotation *= glm::cross(rotation_x, rotation_z); @@ -4615,10 +4641,10 @@ is turned… #+BEGIN_SRC cpp :tangle tangle/util/camera.h if (_moving) { - float2 delta = 0.04 * (mouse - _lastMouse); + float2 delta = 0.04 * (mouse - _mouse); _target += _right*delta.x + _up*delta.y; } - _lastMouse = mouse; + _mouse = mouse; break; } update(); diff --git a/tangle/util/camera.h b/tangle/util/camera.h index aa334d9..b54ad86 100644 --- a/tangle/util/camera.h +++ b/tangle/util/camera.h @@ -18,10 +18,14 @@ glm::vec3 _right; glm::vec3 _up; float _distance; -float2 _lastMouse; -bool _dragging; +float2 _mouse; + +bool _rotating; bool _moving; +bool _restricted_x; +bool _restricted_y; + void update() { _position = _target + apply(_rotation, glm::vec3(0, _distance, 0)); _forward = glm::normalize(_target - _position); @@ -33,29 +37,43 @@ public: Camera(float3 target, float distance): _distance(distance), _target(target.x, target.y, target.z), - _dragging(false), - _moving(false) { + _rotating(false), + _moving(false), + _restricted_x(false), + _restricted_y(false) { update(); } void handle(sf::Event& event) { switch (event.type) { + case sf::Event::KeyPressed: + if (event.key.code == sf::Keyboard::LShift && !_restricted_x && !_restricted_y) { + _restricted_x = true; + _restricted_y = true; + } + break; + case sf::Event::KeyReleased: + if (event.key.code == sf::Keyboard::LShift) { + _restricted_x = false; + _restricted_y = false; + } + break; case sf::Event::MouseButtonPressed: if (event.mouseButton.button == sf::Mouse::Left) { - _dragging = true; - _lastMouse = make_float2(event.mouseButton.x, event.mouseButton.y); + _rotating = true; } else if (event.mouseButton.button == sf::Mouse::Right) { _moving = true; - _lastMouse = make_float2(event.mouseButton.x, event.mouseButton.y); } + _mouse = make_float2(event.mouseButton.x, event.mouseButton.y); break; - case sf::Event::MouseButtonReleased: - if (event.mouseButton.button == sf::Mouse::Left) { - _dragging = false; - } else if (event.mouseButton.button == sf::Mouse::Right) { - _moving = false; - } + case sf::Event::MouseButtonReleased: { + bool restricted = _restricted_x + _restricted_y; + _restricted_x = restricted; + _restricted_y = restricted; + _rotating = false; + _moving = false; break; + } case sf::Event::MouseWheelMoved: _distance -= event.mouseWheel.delta * 10; @@ -63,18 +81,27 @@ void handle(sf::Event& event) { case sf::Event::MouseMoved: float2 mouse = make_float2(event.mouseMove.x, event.mouseMove.y); - if (_dragging) { - float2 delta = 0.005 * (mouse - _lastMouse); + if (_rotating) { + float2 delta = 0.005 * (mouse - _mouse); + if (_restricted_x && _restricted_y) { + if (std::abs(delta.x) > std::abs(delta.y)) { + _restricted_y = false; + } else { + _restricted_x = false; + } + } + if (_restricted_x) { delta.y = 0; } + if (_restricted_y) { delta.x = 0; } glm::quat rotation_z = glm::vec3(0,0,delta.x); glm::quat rotation_x = glm::vec3(delta.y,0,0); _rotation *= glm::cross(rotation_x, rotation_z); } if (_moving) { - float2 delta = 0.04 * (mouse - _lastMouse); + float2 delta = 0.04 * (mouse - _mouse); _target += _right*delta.x + _up*delta.y; } - _lastMouse = mouse; + _mouse = mouse; break; } update(); -- cgit v1.2.3