diff --git a/Source/Core/Common/MathUtil.h b/Source/Core/Common/MathUtil.h index 47440f2239..cb8e6d4e56 100644 --- a/Source/Core/Common/MathUtil.h +++ b/Source/Core/Common/MathUtil.h @@ -8,15 +8,18 @@ #include #include #include +#include #include #include +#include "Common/Assert.h" #include "Common/CommonTypes.h" namespace MathUtil { -constexpr double TAU = 6.2831853071795865; -constexpr double PI = TAU / 2; +template +constexpr T TAU_v = std::numbers::pi_v * 2; +constexpr double TAU = TAU_v; constexpr double GRAVITY_ACCELERATION = 9.80665; template @@ -26,9 +29,12 @@ constexpr auto Sign(const T& val) -> decltype((T{} < val) - (val < T{})) } template -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 && std::is_arithmetic_v) + 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 constexpr bool IsPow2(T imm) { - return imm > 0 && (imm & (imm - 1)) == 0; + if constexpr (std::is_signed_v) + { + if (imm <= 0) + return false; + } + + return std::has_single_bit(static_cast>(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 @@ -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 +constexpr T DegToRad(T degrees) noexcept +{ + return degrees * std::numbers::pi_v / T(180); +} + +template +constexpr T RadToDeg(T radians) noexcept +{ + return radians / std::numbers::pi_v * T(180); +} + } // namespace MathUtil diff --git a/Source/Core/Common/Matrix.cpp b/Source/Core/Common/Matrix.cpp index 9c75487111..f97f53f46e 100644 --- a/Source/Core/Common/Matrix.cpp +++ b/Source/Core/Common/Matrix.cpp @@ -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); diff --git a/Source/Core/Core/HW/WiimoteEmu/Camera.h b/Source/Core/Core/HW/WiimoteEmu/Camera.h index 5f02034358..d0f0f4dea1 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Camera.h +++ b/Source/Core/Core/HW/WiimoteEmu/Camera.h @@ -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 diff --git a/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp b/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp index ebf24f735c..9c5866fd05 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp @@ -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) 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 * 8; ApproachAngleWithAccel(state, target_angle, MAX_ACCEL, time_elapsed); } diff --git a/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp b/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp index c7acf7d0cd..ea1fb8a418 100644 --- a/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp @@ -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; diff --git a/Source/Core/Core/HW/WiimoteEmu/MotionPlus.h b/Source/Core/Core/HW/WiimoteEmu/MotionPlus.h index 02ddfb7ec2..09320ecb00 100644 --- a/Source/Core/Core/HW/WiimoteEmu/MotionPlus.h +++ b/Source/Core/Core/HW/WiimoteEmu/MotionPlus.h @@ -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(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; diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index bbbea66e37..f97781dcb7 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -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 { diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp index b0ebaacca1..3e8f83408a 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp @@ -275,7 +275,7 @@ void DrawVirtualNotches(QPainter& p, ControllerEmu::ReshapableInput& stick, QCol template 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; diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp index 9ff06d4056..9533915c30 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp @@ -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 diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp index 169846c947..5d584b90ba 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp @@ -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 diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp index d74c4df5eb..65464e824e 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp @@ -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 diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/IMUCursor.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/IMUCursor.cpp index f9a2b0fba0..0f3fc8d449 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/IMUCursor.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/IMUCursor.cpp @@ -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 diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/IMUGyroscope.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/IMUGyroscope.cpp index 316ed45f84..29aef3f50f 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/IMUGyroscope.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/IMUGyroscope.cpp @@ -163,7 +163,7 @@ std::optional 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 diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp index 5c604ef3d1..82b6eccb73 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp @@ -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; } Control* Tilt::GetModifierInput() const diff --git a/Source/Core/InputCommon/ControllerEmu/StickGate.cpp b/Source/Core/InputCommon/ControllerEmu/StickGate.cpp index 660ee939be..6ba1ccdc31 100644 --- a/Source/Core/InputCommon/ControllerEmu/StickGate.cpp +++ b/Source/Core/InputCommon/ControllerEmu/StickGate.cpp @@ -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 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; const ControlState input_max_dist = GetInputRadiusAtAngle(angle); ControlState gate_max_dist = GetGateRadiusAtAngle(angle); diff --git a/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp b/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp index b22ace19f2..17660622c5 100644 --- a/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp +++ b/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp @@ -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)); diff --git a/Source/Core/InputCommon/ControllerInterface/MappingCommon.cpp b/Source/Core/InputCommon/ControllerInterface/MappingCommon.cpp index 8b8a22e400..6b29a95b2c 100644 --- a/Source/Core/InputCommon/ControllerInterface/MappingCommon.cpp +++ b/Source/Core/InputCommon/ControllerInterface/MappingCommon.cpp @@ -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 * 0.25f; return quarter_circle - (float(m_input_detector.GetResults().size()) * quarter_circle); } diff --git a/Source/Core/InputCommon/ControllerInterface/SteamDeck/SteamDeck.cpp b/Source/Core/InputCommon/ControllerInterface/SteamDeck/SteamDeck.cpp index b78c56afc6..d45c5401a6 100644 --- a/Source/Core/InputCommon/ControllerInterface/SteamDeck/SteamDeck.cpp +++ b/Source/Core/InputCommon/ControllerInterface/SteamDeck/SteamDeck.cpp @@ -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)); diff --git a/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.cpp b/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.cpp index e7724c1840..8cd0d94d07 100644 --- a/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.cpp @@ -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; } void Device::IRState::ProcessData(const DataReportManipulator& manipulator) diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp index bb51d0026e..5e072140ec 100644 --- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp +++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp @@ -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); diff --git a/Source/Core/VideoBackends/Software/NativeVertexFormat.h b/Source/Core/VideoBackends/Software/NativeVertexFormat.h index f8fc455c50..64a733659e 100644 --- a/Source/Core/VideoBackends/Software/NativeVertexFormat.h +++ b/Source/Core/VideoBackends/Software/NativeVertexFormat.h @@ -7,6 +7,7 @@ #include #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(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(MathUtil::Lerp(a->color[0][i], b->color[0][i], t)); + color[1][i] = static_cast(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 } };