diff options
| author | Jordan Woyak <jordan.woyak@gmail.com> | 2019-01-29 14:39:14 -0600 |
|---|---|---|
| committer | Jordan Woyak <jordan.woyak@gmail.com> | 2019-03-03 12:43:25 -0600 |
| commit | 4db4840d7c6ca42dd33c4bfc1e46568622e3a96b (patch) | |
| tree | a26ca3d48ad1b1181a88ac0c06fdb54fc969b416 /Source/Core/InputCommon/ControllerEmu/ControlGroup | |
| parent | 902e407ae5eb39e03b127e9fd58f4a8193cd2ab8 (diff) | |
WiimoteEmu: Reimplement tilt/swing/camera/orientation data using matrix math.
Diffstat (limited to 'Source/Core/InputCommon/ControllerEmu/ControlGroup')
4 files changed, 89 insertions, 63 deletions
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp index c2178ea370..3b3de522a7 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp @@ -4,12 +4,11 @@ #include "InputCommon/ControllerEmu/ControlGroup/Force.h" -#include <cmath> -#include <memory> #include <string> #include "Common/Common.h" -#include "Common/CommonTypes.h" +#include "Common/MathUtil.h" + #include "InputCommon/ControlReference/ControlReference.h" #include "InputCommon/ControllerEmu/Control/Input.h" #include "InputCommon/ControllerEmu/ControllerEmu.h" @@ -17,7 +16,7 @@ namespace ControllerEmu { -Force::Force(const std::string& name_) : ControlGroup(name_, GroupType::Force) +Force::Force(const std::string& name_) : ReshapableInput(name_, name_, GroupType::Force) { controls.emplace_back(std::make_unique<Input>(Translate, _trans("Up"))); controls.emplace_back(std::make_unique<Input>(Translate, _trans("Down"))); @@ -26,26 +25,69 @@ Force::Force(const std::string& name_) : ControlGroup(name_, GroupType::Force) controls.emplace_back(std::make_unique<Input>(Translate, _trans("Forward"))); controls.emplace_back(std::make_unique<Input>(Translate, _trans("Backward"))); - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50)); + // Maximum swing movement (centimeters). + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Distance"), 0.25, 1, 100)); + + // Maximum jerk (m/s^3). + // i18n: "Jerk" as it relates to physics. The time derivative of acceleration. + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Jerk"), 5.0, 1, 1000)); + + // Angle of twist applied at the extremities of the swing (degrees). + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Angle"), 0.45, 0, 180)); } -Force::StateData Force::GetState() +Force::ReshapeData Force::GetReshapableState(bool adjusted) { - StateData state_data; - const ControlState deadzone = numeric_settings[0]->GetValue(); + const ControlState y = controls[0]->control_ref->State() - controls[1]->control_ref->State(); + const ControlState x = controls[3]->control_ref->State() - controls[2]->control_ref->State(); - for (u32 i = 0; i < 6; i += 2) - { - const ControlState state = - controls[i + 1]->control_ref->State() - controls[i]->control_ref->State(); + // Return raw values. (used in UI) + if (!adjusted) + return {x, y}; + + return Reshape(x, y); +} - ControlState tmpf = 0; - if (fabs(state) > deadzone) - tmpf = ((state - (deadzone * sign(state))) / (1 - deadzone)); +Force::StateData Force::GetState(bool adjusted) +{ + const auto state = GetReshapableState(adjusted); + ControlState z = controls[4]->control_ref->State() - controls[5]->control_ref->State(); - state_data[i / 2] = tmpf; + if (adjusted) + { + // Apply deadzone to z. + const ControlState deadzone = numeric_settings[SETTING_DEADZONE]->GetValue(); + z = std::copysign(std::max(0.0, std::abs(z) - deadzone) / (1.0 - deadzone), z); } - return state_data; + return {float(state.x), float(state.y), float(z)}; +} + +ControlState Force::GetGateRadiusAtAngle(double) const +{ + // Just a circle of the configured distance: + return numeric_settings[SETTING_DISTANCE]->GetValue(); +} + +ControlState Force::GetMaxJerk() const +{ + return numeric_settings[SETTING_JERK]->GetValue() * 100; +} + +ControlState Force::GetTwistAngle() const +{ + return numeric_settings[SETTING_ANGLE]->GetValue() * MathUtil::TAU / 3.60; +} + +ControlState Force::GetMaxDistance() const +{ + return numeric_settings[SETTING_DISTANCE]->GetValue(); +} + +ControlState Force::GetDefaultInputRadiusAtAngle(double) const +{ + // Just a circle of radius 1.0. + return 1.0; } + } // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.h index 7b55d3535f..0b4fdcf634 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.h +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.h @@ -6,18 +6,41 @@ #include <array> #include <string> -#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" -#include "InputCommon/ControllerInterface/Device.h" + +#include "Common/Matrix.h" +#include "InputCommon/ControllerEmu/StickGate.h" namespace ControllerEmu { -class Force : public ControlGroup +class Force : public ReshapableInput { public: - using StateData = std::array<ControlState, 3>; + using StateData = Common::Vec3; explicit Force(const std::string& name); - StateData GetState(); + ReshapeData GetReshapableState(bool adjusted) final override; + ControlState GetGateRadiusAtAngle(double ang) const final override; + + ControlState GetDefaultInputRadiusAtAngle(double angle) const final override; + + StateData GetState(bool adjusted = true); + + // Return jerk in m/s^3. + ControlState GetMaxJerk() const; + + // Return twist angle in radians. + ControlState GetTwistAngle() const; + + // Return swing distance in meters. + ControlState GetMaxDistance() const; + +private: + enum + { + SETTING_DISTANCE = ReshapableInput::SETTING_COUNT, + SETTING_JERK, + SETTING_ANGLE, + }; }; } // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp index bacf158be0..8407aa646f 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp @@ -4,13 +4,9 @@ #include "InputCommon/ControllerEmu/ControlGroup/Tilt.h" -#include <algorithm> -#include <cmath> -#include <memory> #include <string> #include "Common/Common.h" -#include "Common/MathUtil.h" #include "InputCommon/ControlReference/ControlReference.h" #include "InputCommon/ControllerEmu/Control/Control.h" @@ -19,8 +15,7 @@ namespace ControllerEmu { -Tilt::Tilt(const std::string& name_) - : ReshapableInput(name_, name_, GroupType::Tilt), m_last_update(Clock::now()) +Tilt::Tilt(const std::string& name_) : ReshapableInput(name_, name_, GroupType::Tilt) { controls.emplace_back(std::make_unique<Input>(Translate, _trans("Forward"))); controls.emplace_back(std::make_unique<Input>(Translate, _trans("Backward"))); @@ -43,33 +38,7 @@ Tilt::ReshapeData Tilt::GetReshapableState(bool adjusted) const ControlState modifier = controls[4]->control_ref->State(); - // Compute desired tilt: - StateData target = Reshape(x, y, modifier); - - // Step the simulation. This is somewhat ugly being here. - // We should be able to GetState without changing state. - // State should be stored outside of this object inside the wiimote, - // and separately inside the UI. - - // We're using system time rather than ticks to step this. - // I don't think that's too horrible as we can consider this part of user input. - // And at least the Mapping UI will behave sanely this way. - // TODO: when state is moved outside of this class have a separate Step() - // function that takes a ms_passed argument - const auto now = Clock::now(); - const auto ms_since_update = - std::chrono::duration_cast<std::chrono::milliseconds>(now - m_last_update).count(); - m_last_update = now; - - const double max_step = MAX_DEG_PER_SEC / 180.0 * ms_since_update / 1000; - - // TODO: Allow wrap around from 1.0 to -1.0 - // (take the fastest route to target) - - m_tilt.x += MathUtil::Clamp(target.x - m_tilt.x, -max_step, max_step); - m_tilt.y += MathUtil::Clamp(target.y - m_tilt.y, -max_step, max_step); - - return m_tilt; + return Reshape(x, y, modifier); } Tilt::StateData Tilt::GetState() diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.h index c18f6dc46d..6a01a575a6 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.h +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.h @@ -4,7 +4,6 @@ #pragma once -#include <chrono> #include <string> #include "InputCommon/ControllerEmu/StickGate.h" @@ -33,12 +32,5 @@ private: { SETTING_MAX_ANGLE = ReshapableInput::SETTING_COUNT, }; - - static constexpr int MAX_DEG_PER_SEC = 360 * 6; - - StateData m_tilt; - - using Clock = std::chrono::steady_clock; - Clock::time_point m_last_update; }; } // namespace ControllerEmu |
