/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "ArcballCameraController.hpp" #include "Scene/Camera.hpp" #include "Input/InputManager.hpp" #include "Input/InputKey.hpp" #include "Base/FrameMetadata.hpp" namespace OpenVulkano { namespace { constexpr float MAX_ZOOM = 40; constexpr float MIN_ZOOM = 7; constexpr float ZOOM_RANGE = MAX_ZOOM - MIN_ZOOM; } void ArcballCameraController::SetupInputActions() { auto input = Input::InputManager::GetInstance(); m_actionForward = input->GetAction("forward"); m_actionSide = input->GetAction("side"); m_actionUp = input->GetAction("up"); m_actionLookUp = input->GetAction("look up"); m_actionLookSide = input->GetAction("look side"); m_actionForwardOrtho = input->GetAction("ArcForwardOrtho"); m_actionSideOrtho = input->GetAction("ArcSideOrtho"); m_actionUpOrtho = input->GetAction("ArcUpOrtho"); m_actionZoomOrtho = input->GetAction("ArcZoomOrtho"); } void ArcballCameraController::HandleRotation() { Input::InputManager* input = Input::InputManager::GetInstance(); float inYaw = (m_lockYaw) ? 0 : input->GetAxis(m_actionLookSide); float inPitch = (m_lockPitch) ? 0 : input->GetAxis(m_actionLookUp); if (inYaw != 0 || inPitch != 0 || m_distUpated) { m_yaw += inYaw; m_pitch = std::min(1.5f, std::max(-1.5f, m_pitch + inPitch)); Math::Matrix4f rotateY = Math::Utils::rotate(m_yaw, Math::Vector3f_SIMD(0, 1, 0)); Math::Vector4f x = rotateY * Math::Vector4f(1, 0, 0, 0); Math::Matrix4f rotateX = Math::Utils::rotate(m_pitch, Math::Vector3f_SIMD(x)); m_framePosition = rotateX * rotateY * Math::Vector4f_SIMD(0, 0, m_frameDistance, 0); m_framePosition += m_pivotPoint; m_frameUpdated = true; m_distUpated = false; } } void ArcballCameraController::HandleMovement() { Input::InputManager* input = Input::InputManager::GetInstance(); Math::Vector3f_SIMD vec(input->GetAxis(m_actionSide), input->GetAxis(m_actionUp), -input->GetAxis(m_actionForward)); if (vec != Math::Vector3f_SIMD (0)) { const float timeScale = CURRENT_FRAME.frameTime; //TODO vec = vec * timeScale * m_movementSpeedModifier; // scale vector vec = GetCamera()->GetRotationMatrix() * Math::Vector3f(vec); const Math::Vector4f_SIMD movement(vec, 0); m_framePosition += movement; m_pivotPoint += movement; m_frameUpdated = true; } } void ArcballCameraController::HandleMovementOrtho() { Input::InputManager* input = Input::InputManager::GetInstance(); Math::Vector4f vec(input->GetAxis(m_actionSideOrtho), input->GetAxis(m_actionUpOrtho), /*-input->GetAxis(m_actionForwardOrtho)*/0, 0); if (vec != Math::Vector4f(0)) { vec /= GetCamera()->GetZoom(); vec /= GetCamera()->GetContentScaleFactor(); m_framePosition += vec; m_pivotPoint += vec; m_frameUpdated = true; } float zoom = Input::InputManager::GetInstance()->GetAxis(m_actionZoomOrtho); if (zoom != 0) { float tmp = sqrt(GetCamera()->GetZoom()) + zoom / std::max(10.0f, (100 - GetCamera()->GetZoom())); tmp = std::max(3.0f, tmp); GetCamera()->SetZoom(tmp * tmp); GetCamera()->UpdateProjectionMatrix(); m_frameUpdated = true; } } void ArcballCameraController::Tick() { if (!GetCamera()) return; m_frameUpdated = false; m_framePosition = GetCamera()->GetPosition(); if (GetCamera()->IsOrtho()) { HandleMovementOrtho(); /*if (GetCamera()->GetZoom() > 50) { float nDist = std::max(((ZOOM_RANGE - sqrt(GetCamera()->GetZoom())) / ZOOM_RANGE) * m_distance, 0.1f); if (nDist != m_frameDistance) { m_distUpated = true; m_frameDistance = nDist; } }*/ } else { HandleMovement(); m_frameDistance = m_distance; } HandleRotation(); if (m_frameUpdated) { // Update the camera view GetCamera()->SetViewMatrix(Math::Utils::lookAt(reinterpret_cast(m_framePosition), reinterpret_cast(m_pivotPoint), Math::Vector3f_SIMD(0, 1, 0))); CURRENT_FRAME.needsRedraw = true; } } void ArcballCameraController::SetActive() { if (!GetCamera()) return; Math::Vector3f viewDir = Math::Utils::normalize(GetCamera()->GetViewDirection()); m_pivotPoint = GetCamera()->GetPosition() + Math::Vector4f(viewDir * m_distance, 0); m_pitch = Math::Utils::asin(viewDir.y); m_yaw = Math::Utils::atan(-viewDir.x, -viewDir.z); } void ArcballCameraController::SetDefaultKeybindings() { m_actionForward->BindKey(Input::InputKey::Controller::AXIS_LEFT_Y); m_actionForward->BindAxisButtons(Input::InputKey::Keyboard::KEY_W, Input::InputKey::Keyboard::KEY_S); m_actionForward->BindKey(Input::InputKey::Touch::AXIS_PINCH, 0.3f); m_actionSide->BindKey(Input::InputKey::Controller::AXIS_LEFT_X); m_actionSide->BindAxisButtons(Input::InputKey::Keyboard::KEY_D, Input::InputKey::Keyboard::KEY_A); m_actionSide->BindKey(Input::InputKey::Touch::AXIS_PAN_TWO_FINGERS_X, -0.05f); m_actionUp->BindAxisButtons(Input::InputKey::Keyboard::KEY_SPACE, Input::InputKey::Keyboard::KEY_LEFT_CONTROL); m_actionUp->BindKey(Input::InputKey::Touch::AXIS_PAN_TWO_FINGERS_Y, 0.05f); m_actionLookUp->BindKey(Input::InputKey::Controller::AXIS_RIGHT_Y); m_actionLookUp->BindAxisButtons(Input::InputKey::Keyboard::KEY_DOWN, Input::InputKey::Keyboard::KEY_UP); m_actionLookUp->BindKey(Input::InputKey::Touch::AXIS_PAN_Y, -0.001f); m_actionLookSide->BindKey(Input::InputKey::Controller::AXIS_RIGHT_X); m_actionLookSide->BindAxisButtons(Input::InputKey::Keyboard::KEY_RIGHT, Input::InputKey::Keyboard::KEY_LEFT); m_actionLookSide->BindKey(Input::InputKey::Touch::AXIS_PAN_X, -0.001f); m_actionLookUp->BindKey(Input::InputKey::Mouse::AXIS_Y); m_actionLookSide->BindKey(Input::InputKey::Mouse::AXIS_X); //m_actionForwardOrtho m_actionSideOrtho->BindKey(Input::InputKey::Touch::AXIS_PAN_TWO_FINGERS_X, -1); m_actionUpOrtho->BindKey(Input::InputKey::Touch::AXIS_PAN_TWO_FINGERS_Y); m_actionZoomOrtho->BindKey(Input::InputKey::Mouse::AXIS_WHEEL_Y, 2); m_actionZoomOrtho->BindKey(Input::InputKey::Touch::AXIS_PINCH, 0.2); } void ArcballCameraController::SetPivotPoint(const Math::Vector4f_SIMD& pivotPoint, bool updateDistance) { m_pivotPoint = pivotPoint; if (updateDistance && GetCamera()) { SetDistance(Math::Utils::length(m_pivotPoint - GetCamera()->GetPosition())); } } }