diff --git a/openVulkanoCpp/Controller/ArcballCameraController.cpp b/openVulkanoCpp/Controller/ArcballCameraController.cpp new file mode 100644 index 0000000..a4dcecd --- /dev/null +++ b/openVulkanoCpp/Controller/ArcballCameraController.cpp @@ -0,0 +1,90 @@ +/* + * 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 +{ + 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"); + } + + void ArcballCameraController::Tick() + { + if (!GetCamera()) return; + auto input = Input::InputManager::GetInstance(); + Math::Vector4f_SIMD position = GetCamera()->GetPosition(); + float yaw = input->GetAxis(m_actionLookSide); + float pitch = input->GetAxis(m_actionLookUp); + + // Handle issue with camera direction being the same as the up vector + float cosAngle = dot(Math::Vector3f_SIMD(GetCamera()->GetViewDirection()), m_upVector); + if (cosAngle * Math::Utils::sign(pitch) > 0.99f) pitch = 0; + + // Rotate the camera around the pivot point + Math::Matrix4f rotationMatrixX = Math::Utils::rotate(yaw, m_upVector); + position = (rotationMatrixX * (position - m_pivotPoint)) + m_pivotPoint; + m_rightVector = Math::Vector3f_SIMD(rotationMatrixX * Math::Vector4f(m_rightVector, 0)); + Math::Matrix4f rotationMatrixY = Math::Utils::rotate(pitch, m_rightVector); + position = (rotationMatrixY * (position - m_pivotPoint)) + m_pivotPoint; + + // Move the camera and the pivot point + Math::Vector3f_SIMD vec(input->GetAxis(m_actionSide), input->GetAxis(m_actionUp), -input->GetAxis(m_actionForward)); + if (vec != Math::Vector3f_SIMD (0)) + { + if (Math::Utils::length2(vec) > 1.0f) + { + vec = Math::Utils::normalize(vec); + } + const float timeScale = CURRENT_FRAME.frameTime; //TODO + vec = vec * timeScale * 3.0f; // scale vector + vec = GetCamera()->GetRotationMatrix() * Math::Vector3f(vec); + const Math::Vector4f_SIMD movement(vec, 0); + position += movement; + m_pivotPoint += movement; + } + + // Update the camera view + GetCamera()->SetViewMatrix(Math::Utils::lookAt(reinterpret_cast(position), + reinterpret_cast(m_pivotPoint), + m_upVector)); + } + + void ArcballCameraController::SetActive() + { + m_pivotPoint = GetCamera()->GetPosition() + Math::Vector4f(GetCamera()->GetViewDirection() * 3.0f, 0); + } + + 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.2f); + 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.03f); + 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.03f); + 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); + } +} diff --git a/openVulkanoCpp/Controller/ArcballCameraController.hpp b/openVulkanoCpp/Controller/ArcballCameraController.hpp new file mode 100644 index 0000000..6d80263 --- /dev/null +++ b/openVulkanoCpp/Controller/ArcballCameraController.hpp @@ -0,0 +1,49 @@ +/* + * 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/. + */ + +#pragma once + +#include "CameraController.hpp" +#include "Math/Math.hpp" + +namespace OpenVulkano +{ + namespace Input + { + class InputAction; + } + + class ArcballCameraController final : public CameraController + { + Math::Vector3f_SIMD m_upVector{ 0, 1, 0 }, m_rightVector{ 1, 0, 0 }; + Math::Vector4f_SIMD m_pivotPoint{ 0, 0, 0, 1 }; + + Input::InputAction* m_actionForward = nullptr; + Input::InputAction* m_actionSide = nullptr; + Input::InputAction* m_actionUp = nullptr; + Input::InputAction* m_actionLookUp = nullptr; + Input::InputAction* m_actionLookSide = nullptr; + + void SetupInputActions(); + + public: + ArcballCameraController() { SetupInputActions(); } + + ArcballCameraController(Scene::Camera* camera) : CameraController(camera) { SetupInputActions(); SetActive(); } + + void Tick() override; + + [[nodiscard]] const Math::Vector4f_SIMD& GetPivotPoint() const { return m_pivotPoint; } + + void SetPivotPoint(const Math::Vector4f_SIMD& pivotPoint) { m_pivotPoint = pivotPoint; } + + void SetActive(); + + void SetDefaultKeybindings(); + + void Init(Scene::Camera *camera) override { CameraController::SetCamera(camera); SetActive(); } + }; +}