diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index f9186d3fe9..f8755042d7 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -41,6 +41,8 @@ const Info GFX_DUMP_EFB_TARGET{{System::GFX, "Settings", "DumpEFBTarget"}, const Info GFX_DUMP_XFB_TARGET{{System::GFX, "Settings", "DumpXFBTarget"}, false}; const Info GFX_DUMP_FRAMES_AS_IMAGES{{System::GFX, "Settings", "DumpFramesAsImages"}, false}; const Info GFX_FREE_LOOK{{System::GFX, "Settings", "FreeLook"}, false}; +const Info GFX_FREE_LOOK_CONTROL_TYPE{ + {System::GFX, "Settings", "FreeLookControlType"}, FreelookControlType::SixAxis}; const Info GFX_USE_FFV1{{System::GFX, "Settings", "UseFFV1"}, false}; const Info GFX_DUMP_FORMAT{{System::GFX, "Settings", "DumpFormat"}, "avi"}; const Info GFX_DUMP_CODEC{{System::GFX, "Settings", "DumpCodec"}, ""}; diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h index c7daedee27..d70831e21b 100644 --- a/Source/Core/Core/Config/GraphicsSettings.h +++ b/Source/Core/Core/Config/GraphicsSettings.h @@ -11,6 +11,7 @@ enum class AspectMode : int; enum class ShaderCompilationMode : int; enum class StereoMode : int; +enum class FreelookControlType : int; namespace Config { @@ -41,6 +42,7 @@ extern const Info GFX_DUMP_EFB_TARGET; extern const Info GFX_DUMP_XFB_TARGET; extern const Info GFX_DUMP_FRAMES_AS_IMAGES; extern const Info GFX_FREE_LOOK; +extern const Info GFX_FREE_LOOK_CONTROL_TYPE; extern const Info GFX_USE_FFV1; extern const Info GFX_DUMP_FORMAT; extern const Info GFX_DUMP_CODEC; diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index f75fec2f9d..93d1530cdb 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -28,7 +28,7 @@ bool IsSettingSaveable(const Config::Location& config_location) return true; } - static constexpr std::array s_setting_saveable = { + static constexpr std::array s_setting_saveable = { // Main.Core &Config::MAIN_DEFAULT_ISO.location, @@ -73,6 +73,7 @@ bool IsSettingSaveable(const Config::Location& config_location) &Config::GFX_DUMP_EFB_TARGET.location, &Config::GFX_DUMP_FRAMES_AS_IMAGES.location, &Config::GFX_FREE_LOOK.location, + &Config::GFX_FREE_LOOK_CONTROL_TYPE.location, &Config::GFX_USE_FFV1.location, &Config::GFX_DUMP_FORMAT.location, &Config::GFX_DUMP_CODEC.location, diff --git a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp index 2496ac5c09..cff45ae767 100644 --- a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp @@ -72,16 +72,27 @@ void AdvancedWidget::CreateWidgets() m_dump_efb_target = new GraphicsBool(tr("Dump EFB Target"), Config::GFX_DUMP_EFB_TARGET); m_disable_vram_copies = new GraphicsBool(tr("Disable EFB VRAM Copies"), Config::GFX_HACK_DISABLE_COPY_TO_VRAM); - m_enable_freelook = new GraphicsBool(tr("Free Look"), Config::GFX_FREE_LOOK); utility_layout->addWidget(m_load_custom_textures, 0, 0); utility_layout->addWidget(m_prefetch_custom_textures, 0, 1); - utility_layout->addWidget(m_enable_freelook, 1, 0); - utility_layout->addWidget(m_disable_vram_copies, 1, 1); + utility_layout->addWidget(m_disable_vram_copies, 1, 0); + utility_layout->addWidget(m_dump_textures, 1, 1); - utility_layout->addWidget(m_dump_textures, 2, 0); - utility_layout->addWidget(m_dump_efb_target, 2, 1); + utility_layout->addWidget(m_dump_efb_target, 2, 0); + + // Freelook + auto* freelook_box = new QGroupBox(tr("Free Look")); + auto* freelook_layout = new QGridLayout(); + freelook_box->setLayout(freelook_layout); + + m_enable_freelook = new GraphicsBool(tr("Enable"), Config::GFX_FREE_LOOK); + m_freelook_control_type = new GraphicsChoice({tr("Six Axis"), tr("First Person"), tr("Orbital")}, + Config::GFX_FREE_LOOK_CONTROL_TYPE); + + freelook_layout->addWidget(m_enable_freelook, 0, 0); + freelook_layout->addWidget(new QLabel(tr("Control Type:")), 1, 0); + freelook_layout->addWidget(m_freelook_control_type, 1, 1); // Frame dumping auto* dump_box = new QGroupBox(tr("Frame Dumping")); @@ -132,6 +143,7 @@ void AdvancedWidget::CreateWidgets() main_layout->addWidget(debugging_box); main_layout->addWidget(utility_box); + main_layout->addWidget(freelook_box); main_layout->addWidget(dump_box); main_layout->addWidget(misc_box); main_layout->addWidget(experimental_box); @@ -145,6 +157,7 @@ void AdvancedWidget::ConnectWidgets() connect(m_load_custom_textures, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings); connect(m_dump_use_ffv1, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings); connect(m_enable_prog_scan, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings); + connect(m_enable_freelook, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings); } void AdvancedWidget::LoadSettings() @@ -153,6 +166,8 @@ void AdvancedWidget::LoadSettings() m_dump_bitrate->setEnabled(!Config::Get(Config::GFX_USE_FFV1)); m_enable_prog_scan->setChecked(Config::Get(Config::SYSCONF_PROGRESSIVE_SCAN)); + + m_freelook_control_type->setEnabled(Config::Get(Config::GFX_FREE_LOOK)); } void AdvancedWidget::SaveSettings() @@ -161,6 +176,8 @@ void AdvancedWidget::SaveSettings() m_dump_bitrate->setEnabled(!Config::Get(Config::GFX_USE_FFV1)); Config::SetBase(Config::SYSCONF_PROGRESSIVE_SCAN, m_enable_prog_scan->isChecked()); + + m_freelook_control_type->setEnabled(Config::Get(Config::GFX_FREE_LOOK)); } void AdvancedWidget::OnBackendChanged() @@ -213,6 +230,14 @@ void AdvancedWidget::AddDescriptions() "to pan or middle button to roll.\n\nUse the WASD keys while holding SHIFT to move the " "camera. Press SHIFT+2 to increase speed or SHIFT+1 to decrease speed. Press SHIFT+R " "to reset the camera or SHIFT+F to reset the speed.\n\nIf unsure, leave this unchecked. "); + static const char TR_FREE_LOOK_CONTROL_TYPE_DESCRIPTION[] = QT_TR_NOOP( + "Changes the in-game camera type during freelook.\n\n Six Axis: Offers full camera control " + "on all axis, akin to moving a spacecraft in zero gravity. This is the most powerful " + "freelook option but is the most challenging to use.\n" + "First Person: cControls the free camera similarly to a first person video game. The camera " + "can rotate and travel, but roll is impossible. Easy to use, but limiting.\nOrbital: Rotates " + "the free camera around the original camera. Has no lateral movement, only rotation and you " + "may zoom up to the camera's origin point."); static const char TR_CROPPING_DESCRIPTION[] = QT_TR_NOOP("Crops the picture from its native aspect ratio to 4:3 or " "16:9.\n\nIf unsure, leave this unchecked."); @@ -254,6 +279,7 @@ void AdvancedWidget::AddDescriptions() AddDescription(m_enable_cropping, TR_CROPPING_DESCRIPTION); AddDescription(m_enable_prog_scan, TR_PROGRESSIVE_SCAN_DESCRIPTION); AddDescription(m_enable_freelook, TR_FREE_LOOK_DESCRIPTION); + AddDescription(m_freelook_control_type, TR_FREE_LOOK_CONTROL_TYPE_DESCRIPTION); AddDescription(m_backend_multithreading, TR_BACKEND_MULTITHREADING_DESCRIPTION); #ifdef _WIN32 AddDescription(m_borderless_fullscreen, TR_BORDERLESS_FULLSCREEN_DESCRIPTION); diff --git a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h index 1c973c58ed..11d33755e2 100644 --- a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h +++ b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h @@ -8,6 +8,7 @@ class GraphicsWindow; class QCheckBox; +class QComboBox; class QSpinBox; class AdvancedWidget final : public GraphicsWidget @@ -39,6 +40,7 @@ private: QCheckBox* m_disable_vram_copies; QCheckBox* m_load_custom_textures; QCheckBox* m_enable_freelook; + QComboBox* m_freelook_control_type; // Frame dumping QCheckBox* m_dump_use_ffv1; diff --git a/Source/Core/DolphinQt/HotkeyScheduler.cpp b/Source/Core/DolphinQt/HotkeyScheduler.cpp index c36c0bc698..e24929f79a 100644 --- a/Source/Core/DolphinQt/HotkeyScheduler.cpp +++ b/Source/Core/DolphinQt/HotkeyScheduler.cpp @@ -30,6 +30,7 @@ #include "InputCommon/ControlReference/ControlReference.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" +#include "VideoCommon/FreeLookCamera.h" #include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/VertexShaderManager.h" @@ -545,25 +546,25 @@ void HotkeyScheduler::Run() fl_speed = 1.0; if (IsHotkey(HK_FREELOOK_UP, true)) - VertexShaderManager::TranslateView(0.0, 0.0, -fl_speed); + g_freelook_camera.MoveVertical(-fl_speed); if (IsHotkey(HK_FREELOOK_DOWN, true)) - VertexShaderManager::TranslateView(0.0, 0.0, fl_speed); + g_freelook_camera.MoveVertical(fl_speed); if (IsHotkey(HK_FREELOOK_LEFT, true)) - VertexShaderManager::TranslateView(fl_speed, 0.0); + g_freelook_camera.MoveHorizontal(fl_speed); if (IsHotkey(HK_FREELOOK_RIGHT, true)) - VertexShaderManager::TranslateView(-fl_speed, 0.0); + g_freelook_camera.MoveHorizontal(-fl_speed); if (IsHotkey(HK_FREELOOK_ZOOM_IN, true)) - VertexShaderManager::TranslateView(0.0, fl_speed); + g_freelook_camera.Zoom(fl_speed); if (IsHotkey(HK_FREELOOK_ZOOM_OUT, true)) - VertexShaderManager::TranslateView(0.0, -fl_speed); + g_freelook_camera.Zoom(-fl_speed); if (IsHotkey(HK_FREELOOK_RESET, true)) - VertexShaderManager::ResetView(); + g_freelook_camera.Reset(); // Savestates for (u32 i = 0; i < State::NUM_STATES; i++) diff --git a/Source/Core/DolphinQt/RenderWidget.cpp b/Source/Core/DolphinQt/RenderWidget.cpp index 14cc33fae7..234eb270cb 100644 --- a/Source/Core/DolphinQt/RenderWidget.cpp +++ b/Source/Core/DolphinQt/RenderWidget.cpp @@ -32,6 +32,7 @@ #include "DolphinQt/Resources.h" #include "DolphinQt/Settings.h" +#include "VideoCommon/FreeLookCamera.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/VertexShaderManager.h" #include "VideoCommon/VideoConfig.h" @@ -238,12 +239,12 @@ void RenderWidget::OnFreeLookMouseMove(QMouseEvent* event) if (event->buttons() & Qt::RightButton) { // Camera Pitch and Yaw: - VertexShaderManager::RotateView(mouse_move.y() / 200.f, mouse_move.x() / 200.f, 0.f); + g_freelook_camera.Rotate(Common::Vec3{mouse_move.y() / 200.f, mouse_move.x() / 200.f, 0.f}); } else if (event->buttons() & Qt::MidButton) { // Camera Roll: - VertexShaderManager::RotateView(0.f, 0.f, mouse_move.x() / 200.f); + g_freelook_camera.Rotate({0.f, 0.f, mouse_move.x() / 200.f}); } } diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index d8993e19d4..8e957f4a8d 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -33,6 +33,8 @@ add_library(videocommon FramebufferManager.h FramebufferShaderGen.cpp FramebufferShaderGen.h + FreeLookCamera.cpp + FreeLookCamera.h GeometryShaderGen.cpp GeometryShaderGen.h GeometryShaderManager.cpp diff --git a/Source/Core/VideoCommon/FreeLookCamera.cpp b/Source/Core/VideoCommon/FreeLookCamera.cpp new file mode 100644 index 0000000000..45ceb775b1 --- /dev/null +++ b/Source/Core/VideoCommon/FreeLookCamera.cpp @@ -0,0 +1,272 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "VideoCommon/FreeLookCamera.h" + +#include +#include + +#include + +#include "Common/MathUtil.h" + +#include "Common/ChunkFile.h" +#include "Core/Config/GraphicsSettings.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "VideoCommon/VideoCommon.h" +#include "VideoCommon/VideoConfig.h" + +FreeLookCamera g_freelook_camera; + +namespace +{ +std::string to_string(FreelookControlType type) +{ + switch (type) + { + case FreelookControlType::SixAxis: + return "Six Axis"; + case FreelookControlType::FPS: + return "First Person"; + case FreelookControlType::Orbital: + return "Orbital"; + } + + return ""; +} + +class SixAxisController : public CameraController +{ +public: + SixAxisController() = default; + + Common::Matrix44 GetView() override { return m_mat; } + + void MoveVertical(float amt) override + { + m_mat = Common::Matrix44::Translate(Common::Vec3{0, amt, 0}) * m_mat; + } + + void MoveHorizontal(float amt) override + { + m_mat = Common::Matrix44::Translate(Common::Vec3{amt, 0, 0}) * m_mat; + } + + void Zoom(float amt) override + { + m_mat = Common::Matrix44::Translate(Common::Vec3{0, 0, amt}) * m_mat; + } + + void Rotate(const Common::Vec3& amt) override + { + using Common::Matrix33; + m_mat = Common::Matrix44::FromMatrix33(Matrix33::RotateX(amt.x) * Matrix33::RotateY(amt.y) * + Matrix33::RotateZ(amt.z)) * + m_mat; + } + + void Reset() override { m_mat = Common::Matrix44::Identity(); } + + void DoState(PointerWrap& p) { p.Do(m_mat); } + +private: + Common::Matrix44 m_mat = Common::Matrix44::Identity(); +}; + +constexpr double HalfPI = MathUtil::PI / 2; + +class FPSController : public CameraController +{ +public: + Common::Matrix44 GetView() override + { + return m_rotate_mat * Common::Matrix44::Translate(m_position); + } + + void MoveVertical(float amt) override + { + Common::Vec3 up{m_rotate_mat.data[4], m_rotate_mat.data[5], m_rotate_mat.data[6]}; + m_position += up * amt; + } + + void MoveHorizontal(float amt) override + { + Common::Vec3 right{m_rotate_mat.data[0], m_rotate_mat.data[1], m_rotate_mat.data[2]}; + m_position += right * amt; + } + + void Zoom(float amt) override + { + Common::Vec3 forward{m_rotate_mat.data[8], m_rotate_mat.data[9], m_rotate_mat.data[10]}; + m_position += forward * amt; + } + + void Rotate(const Common::Vec3& amt) override + { + m_rotation += amt; + + using Common::Matrix33; + using Common::Matrix44; + m_rotate_mat = + Matrix44::FromMatrix33(Matrix33::RotateX(m_rotation.x) * Matrix33::RotateY(m_rotation.y)); + } + + void Reset() override + { + m_position = Common::Vec3{}; + m_rotation = Common::Vec3{}; + m_rotate_mat = Common::Matrix44::Identity(); + } + + void DoState(PointerWrap& p) + { + p.Do(m_rotation); + p.Do(m_rotate_mat); + p.Do(m_position); + } + +private: + Common::Vec3 m_rotation = Common::Vec3{}; + Common::Matrix44 m_rotate_mat = Common::Matrix44::Identity(); + Common::Vec3 m_position = Common::Vec3{}; +}; + +class OrbitalController : public CameraController +{ +public: + Common::Matrix44 GetView() override + { + Common::Matrix44 result = Common::Matrix44::Identity(); + result *= Common::Matrix44::Translate(Common::Vec3{0, 0, -m_distance}); + result *= Common::Matrix44::FromMatrix33(Common::Matrix33::RotateX(m_rotation.x)); + result *= Common::Matrix44::FromMatrix33(Common::Matrix33::RotateY(m_rotation.y)); + + return result; + } + + void MoveVertical(float) override {} + + void MoveHorizontal(float) override {} + + void Zoom(float amt) override + { + m_distance += -1 * amt; + m_distance = std::clamp(m_distance, 0.0f, m_distance); + } + + void Rotate(const Common::Vec3& amt) override { m_rotation += amt; } + + void Reset() override + { + m_rotation = Common::Vec3{}; + m_distance = 0; + } + + void DoState(PointerWrap& p) + { + p.Do(m_rotation); + p.Do(m_distance); + } + +private: + float m_distance = 0; + Common::Vec3 m_rotation = Common::Vec3{}; +}; +} // namespace + +void FreeLookCamera::SetControlType(FreelookControlType type) +{ + if (m_current_type && *m_current_type == type) + { + return; + } + + if (type == FreelookControlType::SixAxis) + { + m_camera_controller = std::make_unique(); + } + else if (type == FreelookControlType::Orbital) + { + m_camera_controller = std::make_unique(); + } + else + { + m_camera_controller = std::make_unique(); + } + + m_current_type = type; +} + +Common::Matrix44 FreeLookCamera::GetView() +{ + return m_camera_controller->GetView(); +} + +void FreeLookCamera::MoveVertical(float amt) +{ + m_camera_controller->MoveVertical(amt); + m_dirty = true; +} + +void FreeLookCamera::MoveHorizontal(float amt) +{ + m_camera_controller->MoveHorizontal(amt); + m_dirty = true; +} + +void FreeLookCamera::Zoom(float amt) +{ + m_camera_controller->Zoom(amt); + m_dirty = true; +} + +void FreeLookCamera::Rotate(const Common::Vec3& amt) +{ + m_camera_controller->Rotate(amt); + m_dirty = true; +} + +void FreeLookCamera::Reset() +{ + m_camera_controller->Reset(); + m_dirty = true; +} + +void FreeLookCamera::DoState(PointerWrap& p) +{ + if (p.mode == PointerWrap::MODE_WRITE || p.mode == PointerWrap::MODE_MEASURE) + { + p.Do(m_current_type); + if (m_camera_controller) + { + m_camera_controller->DoState(p); + } + } + else + { + const auto old_type = m_current_type; + p.Do(m_current_type); + if (old_type == m_current_type) + { + m_camera_controller->DoState(p); + } + else if (p.GetMode() == PointerWrap::MODE_READ) + { + const std::string old_type_name = old_type ? to_string(*old_type) : ""; + const std::string loaded_type_name = m_current_type ? to_string(*m_current_type) : ""; + const std::string message = + fmt::format("State needs same free look camera type. Settings value '{}', loaded value " + "'{}'. Aborting load state", + old_type_name, loaded_type_name); + Core::DisplayMessage(message, 5000); + p.SetMode(PointerWrap::MODE_VERIFY); + } + } +} + +bool FreeLookCamera::IsDirty() const +{ + return m_dirty; +} diff --git a/Source/Core/VideoCommon/FreeLookCamera.h b/Source/Core/VideoCommon/FreeLookCamera.h new file mode 100644 index 0000000000..0fe27d5e58 --- /dev/null +++ b/Source/Core/VideoCommon/FreeLookCamera.h @@ -0,0 +1,66 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "Common/Matrix.h" +#include "VideoCommon/VideoConfig.h" + +class PointerWrap; + +class CameraController +{ +public: + CameraController() = default; + virtual ~CameraController() = default; + + CameraController(const CameraController&) = delete; + CameraController& operator=(const CameraController&) = delete; + + CameraController(CameraController&&) = delete; + CameraController& operator=(CameraController&&) = delete; + + virtual Common::Matrix44 GetView() = 0; + + virtual void MoveVertical(float amt) = 0; + virtual void MoveHorizontal(float amt) = 0; + + virtual void Zoom(float amt) = 0; + + virtual void Rotate(const Common::Vec3& amt) = 0; + + virtual void Reset() = 0; + + virtual void DoState(PointerWrap& p) = 0; +}; + +class FreeLookCamera +{ +public: + void SetControlType(FreelookControlType type); + Common::Matrix44 GetView(); + + void MoveVertical(float amt); + void MoveHorizontal(float amt); + + void Zoom(float amt); + + void Rotate(const Common::Vec3& amt); + + void Reset(); + + void DoState(PointerWrap& p); + + bool IsDirty() const; + +private: + bool m_dirty = false; + std::optional m_current_type; + std::unique_ptr m_camera_controller; +}; + +extern FreeLookCamera g_freelook_camera; diff --git a/Source/Core/VideoCommon/VertexShaderManager.cpp b/Source/Core/VideoCommon/VertexShaderManager.cpp index 59a89be52d..2044de1aff 100644 --- a/Source/Core/VideoCommon/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/VertexShaderManager.cpp @@ -12,13 +12,16 @@ #include "Common/BitSet.h" #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" +#include "Common/Config/Config.h" #include "Common/Logging/Log.h" #include "Common/Matrix.h" +#include "Core/Config/GraphicsSettings.h" #include "Core/ConfigManager.h" #include "Core/Core.h" #include "VideoCommon/BPFunctions.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/CPMemory.h" +#include "VideoCommon/FreeLookCamera.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/VertexManagerBase.h" @@ -42,7 +45,6 @@ static std::array nPostTransformMatricesChanged; // min,max static std::array nLightsChanged; // min,max static Common::Matrix44 s_viewportCorrection; -static Common::Matrix44 s_freelook_matrix; VertexShaderConstants VertexShaderManager::constants; bool VertexShaderManager::dirty; @@ -110,10 +112,10 @@ void VertexShaderManager::Init() bViewportChanged = false; bTexMtxInfoChanged = false; bLightingConfigChanged = false; + g_freelook_camera.SetControlType(Config::Get(Config::GFX_FREE_LOOK_CONTROL_TYPE)); std::memset(static_cast(&xfmem), 0, sizeof(xfmem)); constants = {}; - ResetView(); // TODO: should these go inside ResetView()? s_viewportCorrection = Common::Matrix44::Identity(); @@ -344,7 +346,7 @@ void VertexShaderManager::SetConstants() } } - if (bProjectionChanged) + if (bProjectionChanged || g_freelook_camera.IsDirty()) { bProjectionChanged = false; @@ -413,7 +415,7 @@ void VertexShaderManager::SetConstants() auto corrected_matrix = s_viewportCorrection * Common::Matrix44::FromArray(g_fProjectionMatrix); if (g_ActiveConfig.bFreeLook && xfmem.projection.type == GX_PERSPECTIVE) - corrected_matrix *= s_freelook_matrix; + corrected_matrix *= g_freelook_camera.GetView(); memcpy(constants.projection.data(), corrected_matrix.data.data(), 4 * sizeof(float4)); @@ -445,6 +447,9 @@ void VertexShaderManager::SetConstants() dirty = true; } + + // Handle a potential config change + g_freelook_camera.SetControlType(Config::Get(Config::GFX_FREE_LOOK_CONTROL_TYPE)); } void VertexShaderManager::InvalidateXFRange(int start, int end) @@ -600,31 +605,6 @@ void VertexShaderManager::SetMaterialColorChanged(int index) nMaterialsChanged[index] = true; } -void VertexShaderManager::TranslateView(float x, float y, float z) -{ - s_freelook_matrix = Common::Matrix44::Translate({x, z, y}) * s_freelook_matrix; - - bProjectionChanged = true; -} - -void VertexShaderManager::RotateView(float x, float y, float z) -{ - using Common::Matrix33; - - s_freelook_matrix = Common::Matrix44::FromMatrix33(Matrix33::RotateX(x) * Matrix33::RotateY(y) * - Matrix33::RotateZ(z)) * - s_freelook_matrix; - - bProjectionChanged = true; -} - -void VertexShaderManager::ResetView() -{ - s_freelook_matrix = Common::Matrix44::Identity(); - - bProjectionChanged = true; -} - void VertexShaderManager::SetVertexFormat(u32 components) { if (components != constants.components) @@ -673,7 +653,7 @@ void VertexShaderManager::DoState(PointerWrap& p) { p.DoArray(g_fProjectionMatrix); p.Do(s_viewportCorrection); - p.Do(s_freelook_matrix); + g_freelook_camera.DoState(p); p.DoArray(nTransformMatricesChanged); p.DoArray(nNormalMatricesChanged); diff --git a/Source/Core/VideoCommon/VertexShaderManager.h b/Source/Core/VideoCommon/VertexShaderManager.h index cd13bee4ff..82da504e16 100644 --- a/Source/Core/VideoCommon/VertexShaderManager.h +++ b/Source/Core/VideoCommon/VertexShaderManager.h @@ -29,10 +29,6 @@ public: static void SetProjectionChanged(); static void SetMaterialColorChanged(int index); - static void TranslateView(float x, float y, float z = 0.0f); - static void RotateView(float x, float y, float z); - static void ResetView(); - static void SetVertexFormat(u32 components); static void SetTexMatrixInfoChanged(int index); static void SetLightingConfigChanged(); diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index dec1ffb34b..75c215a3ab 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -63,6 +63,7 @@ + @@ -141,6 +142,7 @@ + diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 3f18f458a0..41dc891e8a 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -51,6 +51,13 @@ enum class ShaderCompilationMode : int AsynchronousSkipRendering }; +enum class FreelookControlType : int +{ + SixAxis, + FPS, + Orbital +}; + // NEVER inherit from this class. struct VideoConfig final { @@ -107,6 +114,7 @@ struct VideoConfig final std::string sDumpPath; bool bInternalResolutionFrameDumps; bool bFreeLook; + FreelookControlType iFreelookControlType; bool bBorderlessFullscreen; bool bEnableGPUTextureDecoding; int iBitrateKbps;