InputCommon: Add types to ControllerEmu that represent raw controller inputs and calibration data to calculate normalized input values.
This commit is contained in:
parent
259a7191d2
commit
8343dadd58
|
@ -300,6 +300,12 @@ void SetBit(T& value, size_t bit_number, bool bit_value)
|
|||
value &= ~(T{1} << bit_number);
|
||||
}
|
||||
|
||||
template <size_t bit_number, typename T>
|
||||
void SetBit(T& value, bool bit_value)
|
||||
{
|
||||
SetBit(value, bit_number, bit_value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class FlagBit
|
||||
{
|
||||
|
@ -340,4 +346,15 @@ public:
|
|||
std::underlying_type_t<T> m_hex = 0;
|
||||
};
|
||||
|
||||
// Left-shift a value and set new LSBs to that of the supplied LSB.
|
||||
// Converts a value from a N-bit range to an (N+X)-bit range. e.g. 0x101 -> 0x10111
|
||||
template <typename T>
|
||||
T ExpandValue(T value, size_t left_shift_amount)
|
||||
{
|
||||
static_assert(std::is_unsigned<T>(), "ExpandValue is only sane on unsigned types.");
|
||||
|
||||
return (value << left_shift_amount) |
|
||||
(T(-ExtractBit<0>(value)) >> (BitSize<T>() - left_shift_amount));
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/BitUtils.h"
|
||||
#include "Common/Common.h"
|
||||
#include "Common/IniFile.h"
|
||||
#include "InputCommon/ControlReference/ExpressionParser.h"
|
||||
|
@ -27,6 +28,106 @@ namespace ControllerEmu
|
|||
{
|
||||
class ControlGroup;
|
||||
|
||||
// Represents calibration data found on Wii Remotes + extensions with a zero and a max value.
|
||||
// (e.g. accelerometer data)
|
||||
// Bits of precision specified to handle common situation of differing precision in the actual data.
|
||||
template <typename T, size_t Bits>
|
||||
struct TwoPointCalibration
|
||||
{
|
||||
TwoPointCalibration() = default;
|
||||
TwoPointCalibration(const T& zero_, const T& max_) : zero{zero_}, max{max_} {}
|
||||
|
||||
static constexpr size_t BITS_OF_PRECISION = Bits;
|
||||
|
||||
T zero;
|
||||
T max;
|
||||
};
|
||||
|
||||
// Represents calibration data with a min, zero, and max value. (e.g. joystick data)
|
||||
template <typename T, size_t Bits>
|
||||
struct ThreePointCalibration
|
||||
{
|
||||
ThreePointCalibration() = default;
|
||||
ThreePointCalibration(const T& min_, const T& zero_, const T& max_)
|
||||
: min{min_}, zero{zero_}, max{max_}
|
||||
{
|
||||
}
|
||||
|
||||
static constexpr size_t BITS_OF_PRECISION = Bits;
|
||||
|
||||
T min;
|
||||
T zero;
|
||||
T max;
|
||||
};
|
||||
|
||||
// Represents a raw/uncalibrated N-dimensional value of input data. (e.g. Joystick X and Y)
|
||||
// A normalized value can be calculated with a provided {Two,Three}PointCalibration.
|
||||
// Values are adjusted with mismatched bits of precision.
|
||||
// Underlying type may be an unsigned type or a a Common::TVecN<> of an unsigned type.
|
||||
template <typename T, size_t Bits>
|
||||
struct RawValue
|
||||
{
|
||||
RawValue() = default;
|
||||
explicit RawValue(const T& value_) : value{value_} {}
|
||||
|
||||
static constexpr size_t BITS_OF_PRECISION = Bits;
|
||||
|
||||
T value;
|
||||
|
||||
template <typename OtherT, size_t OtherBits>
|
||||
auto GetNormalizedValue(const TwoPointCalibration<OtherT, OtherBits>& calibration) const
|
||||
{
|
||||
const auto value_expansion =
|
||||
std::max(0, int(calibration.BITS_OF_PRECISION) - int(BITS_OF_PRECISION));
|
||||
|
||||
const auto calibration_expansion =
|
||||
std::max(0, int(BITS_OF_PRECISION) - int(calibration.BITS_OF_PRECISION));
|
||||
|
||||
const auto calibration_zero = ExpandValue(calibration.zero, calibration_expansion) * 1.f;
|
||||
const auto calibration_max = ExpandValue(calibration.max, calibration_expansion) * 1.f;
|
||||
|
||||
// Multiplication by 1.f to floatify either a scalar or a Vec.
|
||||
return (ExpandValue(value, value_expansion) * 1.f - calibration_zero) /
|
||||
(calibration_max - calibration_zero);
|
||||
}
|
||||
|
||||
template <typename OtherT, size_t OtherBits>
|
||||
auto GetNormalizedValue(const ThreePointCalibration<OtherT, OtherBits>& calibration) const
|
||||
{
|
||||
const auto value_expansion =
|
||||
std::max(0, int(calibration.BITS_OF_PRECISION) - int(BITS_OF_PRECISION));
|
||||
|
||||
const auto calibration_expansion =
|
||||
std::max(0, int(BITS_OF_PRECISION) - int(calibration.BITS_OF_PRECISION));
|
||||
|
||||
const auto calibration_min = ExpandValue(calibration.min, calibration_expansion) * 1.f;
|
||||
const auto calibration_zero = ExpandValue(calibration.zero, calibration_expansion) * 1.f;
|
||||
const auto calibration_max = ExpandValue(calibration.max, calibration_expansion) * 1.f;
|
||||
|
||||
const auto use_max = calibration.zero < value;
|
||||
|
||||
// Multiplication by 1.f to floatify either a scalar or a Vec.
|
||||
return (ExpandValue(value, value_expansion) * 1.f - calibration_zero) /
|
||||
(use_max * 1.f * (calibration_max - calibration_zero) +
|
||||
!use_max * 1.f * (calibration_zero - calibration_min));
|
||||
}
|
||||
|
||||
template <typename OtherT>
|
||||
static OtherT ExpandValue(OtherT value, size_t bits)
|
||||
{
|
||||
if constexpr (std::is_arithmetic_v<OtherT>)
|
||||
{
|
||||
return Common::ExpandValue(value, bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i != std::size(value.data); ++i)
|
||||
value.data[i] = Common::ExpandValue(value.data[i], bits);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class EmulatedController
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue