mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-07-03 09:02:30 -05:00
Merge 1b86f22b93 into d8d37fdbc4
This commit is contained in:
commit
4da0610266
|
|
@ -8,15 +8,18 @@
|
|||
#include <cmath>
|
||||
#include <concepts>
|
||||
#include <limits>
|
||||
#include <numbers>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
namespace MathUtil
|
||||
{
|
||||
constexpr double TAU = 6.2831853071795865;
|
||||
constexpr double PI = TAU / 2;
|
||||
template <std::floating_point T>
|
||||
constexpr T TAU_v = std::numbers::pi_v<T> * 2;
|
||||
constexpr double TAU = TAU_v<double>;
|
||||
constexpr double GRAVITY_ACCELERATION = 9.80665;
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -26,9 +29,12 @@ constexpr auto Sign(const T& val) -> decltype((T{} < val) - (val < T{}))
|
|||
}
|
||||
|
||||
template <typename T, typename F>
|
||||
constexpr auto Lerp(const T& x, const T& y, const F& a) -> decltype(x + (y - x) * a)
|
||||
constexpr auto Lerp(const T& x, const T& y, const F& a)
|
||||
{
|
||||
return x + (y - x) * a;
|
||||
if constexpr (std::is_arithmetic_v<T> && std::is_arithmetic_v<F>)
|
||||
return std::lerp(x, y, a);
|
||||
else
|
||||
return x + (y - x) * a;
|
||||
}
|
||||
|
||||
// Casts the specified value to a Dest. The value will be clamped to fit in the destination type.
|
||||
|
|
@ -59,20 +65,18 @@ constexpr Dest SaturatingCast(T value)
|
|||
template <typename T>
|
||||
constexpr bool IsPow2(T imm)
|
||||
{
|
||||
return imm > 0 && (imm & (imm - 1)) == 0;
|
||||
if constexpr (std::is_signed_v<T>)
|
||||
{
|
||||
if (imm <= 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::has_single_bit(static_cast<std::make_unsigned_t<T>>(imm));
|
||||
}
|
||||
|
||||
constexpr u32 NextPowerOf2(u32 value)
|
||||
{
|
||||
--value;
|
||||
value |= value >> 1;
|
||||
value |= value >> 2;
|
||||
value |= value >> 4;
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
++value;
|
||||
|
||||
return value;
|
||||
return std::bit_ceil(value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
|
@ -173,6 +177,20 @@ private:
|
|||
// Rounds down. 0 -> undefined
|
||||
constexpr int IntLog2(u64 val)
|
||||
{
|
||||
return 63 - std::countl_zero(val);
|
||||
DEBUG_ASSERT(val != 0);
|
||||
return std::bit_width(val) - 1;
|
||||
}
|
||||
|
||||
template <std::floating_point T>
|
||||
constexpr T DegToRad(T degrees) noexcept
|
||||
{
|
||||
return degrees * std::numbers::pi_v<T> / T(180);
|
||||
}
|
||||
|
||||
template <std::floating_point T>
|
||||
constexpr T RadToDeg(T radians) noexcept
|
||||
{
|
||||
return radians / std::numbers::pi_v<T> * T(180);
|
||||
}
|
||||
|
||||
} // namespace MathUtil
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ Vec3 FromQuaternionToEuler(const Quaternion& q)
|
|||
|
||||
const float sinp = 2 * (qw * qy - qz * qx);
|
||||
if (std::abs(sinp) >= 1)
|
||||
result.y = std::copysign(MathUtil::PI / 2, sinp); // use 90 degrees if out of range
|
||||
result.y = std::copysign(std::numbers::pi / 2, sinp); // use 90 degrees if out of range
|
||||
else
|
||||
result.y = std::asin(sinp);
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public:
|
|||
// Jordan: I calculate the FOV at 42 degrees horizontally and having a 4:3 aspect ratio.
|
||||
// This is 31.5 degrees vertically.
|
||||
static constexpr float CAMERA_AR = 4.f / 3;
|
||||
static constexpr float CAMERA_FOV_X = 42 * float(MathUtil::TAU) / 360;
|
||||
static constexpr float CAMERA_FOV_X = MathUtil::DegToRad(42.0f);
|
||||
static constexpr float CAMERA_FOV_Y = CAMERA_FOV_X / CAMERA_AR;
|
||||
|
||||
enum : u8
|
||||
|
|
|
|||
|
|
@ -112,8 +112,8 @@ void EmulateTilt(RotationalState* state, ControllerEmu::Tilt* const tilt_group,
|
|||
const auto target = tilt_group->GetState();
|
||||
|
||||
// 180 degrees is currently the max tilt value.
|
||||
const ControlState roll = target.x * MathUtil::PI;
|
||||
const ControlState pitch = target.y * MathUtil::PI;
|
||||
const ControlState roll = target.x * std::numbers::pi;
|
||||
const ControlState pitch = target.y * std::numbers::pi;
|
||||
|
||||
const auto target_angle = Common::Vec3(pitch, -roll, 0);
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ void EmulateTilt(RotationalState* state, ControllerEmu::Tilt* const tilt_group,
|
|||
for (std::size_t i = 0; i != target_angle.data.size(); ++i)
|
||||
{
|
||||
auto& angle = state->angle.data[i];
|
||||
if (std::abs(angle - target_angle.data[i]) > float(MathUtil::PI))
|
||||
if (std::abs(angle - target_angle.data[i]) > std::numbers::pi_v<float>)
|
||||
angle -= std::copysign(MathUtil::TAU, angle);
|
||||
}
|
||||
|
||||
|
|
@ -265,7 +265,7 @@ void EmulatePoint(MotionState* state, ControllerEmu::Cursor* ir_group,
|
|||
// Higher values will be more responsive but increase rate of M+ "desync".
|
||||
// I'd rather not expose this value in the UI if not needed.
|
||||
// At this value, sync is very good and responsiveness still appears instant.
|
||||
constexpr auto MAX_ACCEL = float(MathUtil::TAU * 8);
|
||||
constexpr auto MAX_ACCEL = MathUtil::TAU_v<float> * 8;
|
||||
|
||||
ApproachAngleWithAccel(state, target_angle, MAX_ACCEL, time_elapsed);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ Common::Vec3 MotionPlus::DataFormat::Data::GetAngularVelocity(const CalibrationB
|
|||
const auto sign_fix = Common::Vec3(-1, +1, -1);
|
||||
|
||||
// Adjust deg/s to rad/s.
|
||||
constexpr auto scalar = float(MathUtil::TAU / 360);
|
||||
constexpr auto scalar = MathUtil::DegToRad(1.0f);
|
||||
|
||||
return gyro.GetNormalizedValue(calibration.value) * sign_fix * Common::Vec3(calibration.degrees) *
|
||||
scalar;
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ public:
|
|||
|
||||
static constexpr u16 VALUE_SCALE =
|
||||
(CALIBRATION_SCALE_OFFSET >> (CALIBRATION_BITS - BITS_OF_PRECISION));
|
||||
static constexpr float VALUE_SCALE_DEGREES = VALUE_SCALE / float(MathUtil::TAU) * 360;
|
||||
static constexpr float VALUE_SCALE_DEGREES = MathUtil::RadToDeg(static_cast<float>(VALUE_SCALE));
|
||||
|
||||
static constexpr float SLOW_SCALE = VALUE_SCALE_DEGREES / CALIBRATION_SLOW_SCALE_DEGREES;
|
||||
static constexpr float FAST_SCALE = VALUE_SCALE_DEGREES / CALIBRATION_FAST_SCALE_DEGREES;
|
||||
|
|
|
|||
|
|
@ -231,8 +231,8 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index), m_bt_device_index(i
|
|||
groups.emplace_back(m_swing = new ControllerEmu::Force(_trans("Swing")));
|
||||
|
||||
groups.emplace_back(m_imu_ir = new ControllerEmu::IMUCursor("IMUIR", _trans("Point")));
|
||||
const auto fov_default =
|
||||
Common::DVec2(CameraLogic::CAMERA_FOV_X, CameraLogic::CAMERA_FOV_Y) / MathUtil::TAU * 360;
|
||||
const auto fov_default = Common::DVec2(MathUtil::RadToDeg(CameraLogic::CAMERA_FOV_X),
|
||||
MathUtil::RadToDeg(CameraLogic::CAMERA_FOV_Y));
|
||||
m_imu_ir->AddSetting(&m_fov_x_setting,
|
||||
// i18n: FOV stands for "Field of view".
|
||||
{_trans("Horizontal FOV"),
|
||||
|
|
@ -508,9 +508,8 @@ void Wiimote::BuildDesiredWiimoteState(DesiredWiimoteState* target_state,
|
|||
else if (sensor_bar_state == SensorBarState::Enabled)
|
||||
{
|
||||
target_state->camera_points = CameraLogic::GetCameraPoints(
|
||||
GetTotalTransformation(),
|
||||
Common::Vec2(m_fov_x_setting.GetValue(), m_fov_y_setting.GetValue()) / 360 *
|
||||
float(MathUtil::TAU));
|
||||
GetTotalTransformation(), Common::Vec2(MathUtil::DegToRad(m_fov_x_setting.GetValue()),
|
||||
MathUtil::DegToRad(m_fov_y_setting.GetValue())));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ void DrawVirtualNotches(QPainter& p, ControllerEmu::ReshapableInput& stick, QCol
|
|||
template <typename F>
|
||||
void GenerateFibonacciSphere(int point_count, F&& callback)
|
||||
{
|
||||
const float golden_angle = MathUtil::PI * (3.f - std::sqrt(5.f));
|
||||
const float golden_angle = std::numbers::pi * (3.f - std::sqrt(5.f));
|
||||
|
||||
for (int i = 0; i != point_count; ++i)
|
||||
{
|
||||
|
|
@ -462,7 +462,8 @@ QColor TiltIndicator::GetGateBrushColor() const
|
|||
|
||||
void TiltIndicator::Draw()
|
||||
{
|
||||
auto adj_coord = Common::DVec2{-m_motion_state.angle.y, m_motion_state.angle.x} / MathUtil::PI;
|
||||
auto adj_coord =
|
||||
Common::DVec2{-m_motion_state.angle.y, m_motion_state.angle.x} / std::numbers::pi;
|
||||
|
||||
// Angle values after dividing by pi.
|
||||
constexpr auto norm_180_deg = 1;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ OctagonAnalogStick::OctagonAnalogStick(const char* name_, const char* ui_name_,
|
|||
|
||||
ControlState OctagonAnalogStick::GetVirtualNotchSize() const
|
||||
{
|
||||
return m_virtual_notch_setting.GetValue() * MathUtil::TAU / 360;
|
||||
return MathUtil::DegToRad(m_virtual_notch_setting.GetValue());
|
||||
}
|
||||
|
||||
ControlState OctagonAnalogStick::GetGateRadiusAtAngle(double ang) const
|
||||
|
|
|
|||
|
|
@ -167,12 +167,12 @@ Cursor::StateData Cursor::UpdateState(Cursor::ReshapeData input)
|
|||
|
||||
ControlState Cursor::GetTotalYaw() const
|
||||
{
|
||||
return m_yaw_setting.GetValue() * MathUtil::TAU / 360;
|
||||
return MathUtil::DegToRad(m_yaw_setting.GetValue());
|
||||
}
|
||||
|
||||
ControlState Cursor::GetTotalPitch() const
|
||||
{
|
||||
return m_pitch_setting.GetValue() * MathUtil::TAU / 360;
|
||||
return MathUtil::DegToRad(m_pitch_setting.GetValue());
|
||||
}
|
||||
|
||||
ControlState Cursor::GetVerticalOffset() const
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ ControlState Force::GetReturnSpeed() const
|
|||
|
||||
ControlState Force::GetTwistAngle() const
|
||||
{
|
||||
return m_angle_setting.GetValue() * MathUtil::TAU / 360;
|
||||
return MathUtil::DegToRad(m_angle_setting.GetValue());
|
||||
}
|
||||
|
||||
ControlState Force::GetMaxDistance() const
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ IMUCursor::IMUCursor(std::string name_, std::string ui_name_)
|
|||
|
||||
ControlState IMUCursor::GetTotalYaw() const
|
||||
{
|
||||
return m_yaw_setting.GetValue() * MathUtil::TAU / 360;
|
||||
return MathUtil::DegToRad(m_yaw_setting.GetValue());
|
||||
}
|
||||
|
||||
ControlState IMUCursor::GetAccelWeight() const
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ std::optional<IMUGyroscope::StateData> IMUGyroscope::GetState(bool update)
|
|||
|
||||
ControlState IMUGyroscope::GetDeadzone() const
|
||||
{
|
||||
return m_deadzone_setting.GetValue() / 360 * MathUtil::TAU;
|
||||
return MathUtil::DegToRad(m_deadzone_setting.GetValue());
|
||||
}
|
||||
|
||||
bool IMUGyroscope::IsCalibrating() const
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ ControlState Tilt::GetDefaultInputRadiusAtAngle(double ang) const
|
|||
|
||||
ControlState Tilt::GetMaxRotationalVelocity() const
|
||||
{
|
||||
return m_max_rotational_velocity.GetValue() * MathUtil::TAU;
|
||||
return m_max_rotational_velocity.GetValue() * MathUtil::TAU_v<ControlState>;
|
||||
}
|
||||
|
||||
Control* Tilt::GetModifierInput() const
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ double GetNearestNotch(double angle, double virtual_notch_angle)
|
|||
constexpr auto rounding = MathUtil::TAU / sides;
|
||||
const auto closest_notch = std::round(angle / rounding) * rounding;
|
||||
const auto angle_diff =
|
||||
std::fmod(angle - closest_notch + MathUtil::PI, MathUtil::TAU) - MathUtil::PI;
|
||||
std::fmod(angle - closest_notch + std::numbers::pi, MathUtil::TAU) - std::numbers::pi;
|
||||
return std::abs(angle_diff) < virtual_notch_angle / 2 ? closest_notch : angle;
|
||||
}
|
||||
|
||||
|
|
@ -80,12 +80,12 @@ OctagonStickGate::OctagonStickGate(ControlState radius) : m_radius(radius)
|
|||
ControlState OctagonStickGate::GetRadiusAtAngle(double angle) const
|
||||
{
|
||||
constexpr int sides = 8;
|
||||
constexpr double sum_int_angles = (sides - 2) * MathUtil::PI;
|
||||
constexpr double sum_int_angles = (sides - 2) * std::numbers::pi;
|
||||
constexpr double half_int_angle = sum_int_angles / sides / 2;
|
||||
|
||||
angle = std::fmod(angle, MathUtil::TAU / sides);
|
||||
// Solve ASA triangle using The Law of Sines:
|
||||
return m_radius / std::sin(MathUtil::PI - angle - half_int_angle) * std::sin(half_int_angle);
|
||||
return m_radius / std::sin(std::numbers::pi - angle - half_int_angle) * std::sin(half_int_angle);
|
||||
}
|
||||
|
||||
std::optional<u32> OctagonStickGate::GetIdealCalibrationSampleCount() const
|
||||
|
|
@ -306,7 +306,7 @@ ReshapableInput::ReshapeData ReshapableInput::Reshape(ControlState x, ControlSta
|
|||
// (which depends on the signs of x and y) does not matter here as dist is zero
|
||||
|
||||
// TODO: make the AtAngle functions work with negative angles:
|
||||
ControlState angle = std::atan2(y, x) + MathUtil::TAU;
|
||||
ControlState angle = std::atan2(y, x) + MathUtil::TAU_v<ControlState>;
|
||||
|
||||
const ControlState input_max_dist = GetInputRadiusAtAngle(angle);
|
||||
ControlState gate_max_dist = GetGateRadiusAtAngle(angle);
|
||||
|
|
|
|||
|
|
@ -574,7 +574,7 @@ Device::Device(std::string name, int index, std::string server_address, u16 serv
|
|||
AddInput(new AccelerometerInput("Accel Backward", m_pad_data.accelerometer_z_g, -accel_scale));
|
||||
|
||||
// Convert degrees per second to radians per second
|
||||
constexpr auto gyro_scale = 360.0 / MathUtil::TAU;
|
||||
constexpr auto gyro_scale = MathUtil::RadToDeg(1.0);
|
||||
|
||||
AddInput(new GyroInput("Gyro Pitch Up", m_pad_data.gyro_pitch_deg_s, gyro_scale));
|
||||
AddInput(new GyroInput("Gyro Pitch Down", m_pad_data.gyro_pitch_deg_s, -gyro_scale));
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ bool ReshapableInputMapper::Update()
|
|||
|
||||
float ReshapableInputMapper::GetCurrentAngle() const
|
||||
{
|
||||
constexpr auto quarter_circle = float(MathUtil::TAU) * 0.25f;
|
||||
constexpr auto quarter_circle = MathUtil::TAU_v<float> * 0.25f;
|
||||
return quarter_circle - (float(m_input_detector.GetResults().size()) * quarter_circle);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ Device::Device(hid_device* device) : m_device{device}
|
|||
|
||||
// 16.384 (?) LSBs = 1 deg / s
|
||||
// final output in rads / s
|
||||
constexpr auto gyro_scale = 16.384 * 360.0 / MathUtil::TAU;
|
||||
constexpr auto gyro_scale = MathUtil::RadToDeg(16.384);
|
||||
AddInput(new MotionInput("Gyro Pitch Up", m_latest_input.gyro_pitch, gyro_scale));
|
||||
AddInput(new MotionInput("Gyro Pitch Down", m_latest_input.gyro_pitch, -gyro_scale));
|
||||
AddInput(new MotionInput("Gyro Roll Left", m_latest_input.gyro_roll, -gyro_scale));
|
||||
|
|
|
|||
|
|
@ -1258,7 +1258,7 @@ void Device::UpdateOrientation()
|
|||
m_rotation_inputs =
|
||||
Common::Vec3{WiimoteEmu::GetPitch(m_orientation), WiimoteEmu::GetRoll(m_orientation),
|
||||
WiimoteEmu::GetYaw(m_orientation)} /
|
||||
float(MathUtil::PI);
|
||||
std::numbers::pi_v<float>;
|
||||
}
|
||||
|
||||
void Device::IRState::ProcessData(const DataReportManipulator& manipulator)
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ bool evdevDevice::AddNode(std::string devnode, int fd, libevdev* dev)
|
|||
// evdev resolution is specified in "g"s and deg/s.
|
||||
// Convert these to m/s/s and rad/s.
|
||||
constexpr ControlState accel_scale = MathUtil::GRAVITY_ACCELERATION;
|
||||
constexpr ControlState gyro_scale = MathUtil::TAU / 360;
|
||||
constexpr ControlState gyro_scale = MathUtil::DegToRad(ControlState{1});
|
||||
|
||||
add_motion_inputs(ABS_X, accel_scale);
|
||||
add_motion_inputs(ABS_RX, gyro_scale);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <cstddef>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Common/Matrix.h"
|
||||
|
||||
struct InputVertexData
|
||||
|
|
@ -40,35 +41,27 @@ struct OutputVertexData
|
|||
|
||||
void Lerp(float t, const OutputVertexData* a, const OutputVertexData* b)
|
||||
{
|
||||
#define LINTERP(T, OUT, IN) (OUT) + ((IN - OUT) * T)
|
||||
mvPosition = MathUtil::Lerp(a->mvPosition, b->mvPosition, t);
|
||||
|
||||
#define LINTERP_INT(T, OUT, IN) (OUT) + (((IN - OUT) * T) >> 8)
|
||||
|
||||
mvPosition = LINTERP(t, a->mvPosition, b->mvPosition);
|
||||
|
||||
projectedPosition.x = LINTERP(t, a->projectedPosition.x, b->projectedPosition.x);
|
||||
projectedPosition.y = LINTERP(t, a->projectedPosition.y, b->projectedPosition.y);
|
||||
projectedPosition.z = LINTERP(t, a->projectedPosition.z, b->projectedPosition.z);
|
||||
projectedPosition.w = LINTERP(t, a->projectedPosition.w, b->projectedPosition.w);
|
||||
projectedPosition.x = MathUtil::Lerp(a->projectedPosition.x, b->projectedPosition.x, t);
|
||||
projectedPosition.y = MathUtil::Lerp(a->projectedPosition.y, b->projectedPosition.y, t);
|
||||
projectedPosition.z = MathUtil::Lerp(a->projectedPosition.z, b->projectedPosition.z, t);
|
||||
projectedPosition.w = MathUtil::Lerp(a->projectedPosition.w, b->projectedPosition.w, t);
|
||||
|
||||
for (std::size_t i = 0; i < normal.size(); ++i)
|
||||
{
|
||||
normal[i] = LINTERP(t, a->normal[i], b->normal[i]);
|
||||
normal[i] = MathUtil::Lerp(a->normal[i], b->normal[i], t);
|
||||
}
|
||||
|
||||
const u16 t_int = static_cast<u16>(t * 256);
|
||||
for (std::size_t i = 0; i < color[0].size(); ++i)
|
||||
{
|
||||
color[0][i] = LINTERP_INT(t_int, a->color[0][i], b->color[0][i]);
|
||||
color[1][i] = LINTERP_INT(t_int, a->color[1][i], b->color[1][i]);
|
||||
color[0][i] = static_cast<u8>(MathUtil::Lerp(a->color[0][i], b->color[0][i], t));
|
||||
color[1][i] = static_cast<u8>(MathUtil::Lerp(a->color[1][i], b->color[1][i], t));
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < texCoords.size(); ++i)
|
||||
{
|
||||
texCoords[i] = LINTERP(t, a->texCoords[i], b->texCoords[i]);
|
||||
texCoords[i] = MathUtil::Lerp(a->texCoords[i], b->texCoords[i], t);
|
||||
}
|
||||
|
||||
#undef LINTERP
|
||||
#undef LINTERP_INT
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user