From 8d92d57fb1949d288b12d940267629b43beb25f4 Mon Sep 17 00:00:00 2001 From: kamih Date: Sat, 25 Jan 2025 12:30:28 -0700 Subject: [PATCH 01/20] added first test of new HUD that sends trigger effects to dualsense controller via simple dll instead of dsx --- .../DualSense/DualSenseConfiguration.cs | 86 +++++++++++++++++++ .../Driving/DualSense/DualSenseJob.cs | 19 ++++ .../Driving/DualSense/DualSenseOverlay.cs | 49 +++++++++++ .../Overlays/Driving/DualSense/Resources.cs | 27 ++++++ .../Driving/DualSense/TriggerHaptics.cs | 77 +++++++++++++++++ 5 files changed, 258 insertions(+) create mode 100644 Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs create mode 100644 Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs create mode 100644 Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs create mode 100644 Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs create mode 100644 Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs new file mode 100644 index 000000000..1f13af5ed --- /dev/null +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs @@ -0,0 +1,86 @@ +using RaceElement.HUD.Overlay.Configuration; + +namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; + +internal sealed class DualSenseConfiguration : OverlayConfiguration +{ + public DualSenseConfiguration() + { + GenericConfiguration.AlwaysOnTop = false; + GenericConfiguration.Window = false; + GenericConfiguration.Opacity = 1.0f; + GenericConfiguration.AllowRescale = false; + } + + + [ConfigGrouping("Brake Slip", "Adjust the slip effect whilst applying the brakes.")] + public BrakeSlipHaptics BrakeSlip { get; init; } = new(); + public sealed class BrakeSlipHaptics + { + /// + /// The brake in percentage (divide by 100f if you want 0-1 value) + /// + [ToolTip("The minimum brake percentage before any effects are applied. See this like a deadzone.")] + [FloatRange(0.1f, 99f, 0.1f, 1)] + public float BrakeThreshold { get; init; } = 3f; + + [FloatRange(0.05f, 6f, 0.002f, 3)] + public float FrontSlipThreshold { get; init; } = 0.25f; + + [FloatRange(0.05f, 6f, 0.002f, 3)] + public float RearSlipThreshold { get; init; } = 0.25f; + + [ToolTip("Higher is stronger dynamic feedback.")] + [IntRange(5, 8, 1)] + public int FeedbackStrength { get; init; } = 7; + + [ToolTip("Sets the min frequency of the vibration effect in the trigger.")] + [IntRange(1, 10, 1)] + public int MinFrequency { get; init; } = 10; + + [ToolTip("Sets the max frequency of the vibration effect in the trigger.")] + [IntRange(20, 150, 1)] + public int MaxFrequency { get; init; } = 100; + + [ToolTip("Change the amplitude(strength) of the vibration effect in the trigger.")] + [IntRange(1, 8, 1)] + public int Amplitude { get; init; } = 1; + } + + [ConfigGrouping("Throttle Slip", "Adjust the slip effect whilst applying the throttle.\nModify the threshold to increase or decrease sensitivity in different situations.")] + public ThrottleSlipHaptics ThrottleSlip { get; init; } = new(); + public sealed class ThrottleSlipHaptics + { + /// + /// The throttle in percentage (divide by 100f if you want 0-1 value) + /// + [ToolTip("The minimum throttle percentage before any effects are applied. See this like a deadzone.")] + [FloatRange(0.1f, 99f, 0.1f, 1)] + public float ThrottleThreshold { get; init; } = 3f; + + [ToolTip("Decrease this treshold to increase the sensitivity when the front wheels slip (understeer).")] + [FloatRange(0.05f, 6f, 0.002f, 3)] + public float FrontSlipThreshold { get; init; } = 0.35f; + + [ToolTip("Decrease this treshold to increase the sensitivity when the rear wheels slip (oversteer).")] + [FloatRange(0.05f, 10f, 0.002f, 3)] + public float RearSlipThreshold { get; init; } = 0.25f; + + [ToolTip("Higher is stronger dynamic feedback.")] + [IntRange(5, 8, 1)] + public int FeedbackStrength { get; init; } = 8; + + [ToolTip("Sets the min frequency of the vibration effect in the trigger.")] + [IntRange(1, 10, 1)] + public int MinFrequency { get; init; } = 10; + + [ToolTip("Sets the max frequency of the vibration effect in the trigger.")] + [IntRange(20, 150, 1)] + public int MaxFrequency { get; init; } = 100; + + [ToolTip("Change the amplitude(strength) of the vibration effect in the trigger.")] + [IntRange(1, 8, 1)] + public int Amplitude { get; init; } = 1; + } + +} diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs new file mode 100644 index 000000000..1240795af --- /dev/null +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs @@ -0,0 +1,19 @@ +using RaceElement.Core.Jobs.Loop; +using static RaceElement.HUD.Common.Overlays.Driving.DualSense.Resources; + +namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; + +internal sealed class DualSenseJob(DualSenseOverlay overlay) : AbstractLoopJob +{ + public sealed override void RunAction() + { + //if (!overlay.ShouldRender()) + // return; + + TriggerHaptics.HandleAcceleration(overlay._config); + TriggerHaptics.HandleBraking(overlay._config); + } + public override void AfterCancel() + { + } +} diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs new file mode 100644 index 000000000..4c806616c --- /dev/null +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs @@ -0,0 +1,49 @@ +using RaceElement.Data.Games; +using RaceElement.HUD.Overlay.Internal; +using System.Diagnostics; +using System.Drawing; +using System.Text; + +using static RaceElement.HUD.Common.Overlays.Driving.DualSense.Resources; + +namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; + +[Overlay(Name = "DualSense", + Description = "Adds trigger effects to the DualSense Controller.\n See Guide in the Discord of Race Element for instructions.", + OverlayCategory = OverlayCategory.Inputs, + OverlayType = OverlayType.Drive, + Game = Game.RaceRoom | Game.AssettoCorsa1 | Game.AssettoCorsaEvo, + Authors = ["Reinier Klarenberg", "Guillaume Stordeur"] +)] +internal sealed class DualSenseOverlay : CommonAbstractOverlay +{ + internal readonly DualSenseConfiguration _config = new(); + private DualSenseJob _DualSenseJob; + + public DualSenseOverlay(Rectangle rectangle) : base(rectangle, "DualSense") + { + Width = 1; Height = 1; + RefreshRateHz = 1; + AllowReposition = false; + } + + public sealed override void BeforeStart() + { + if (IsPreviewing) return; + ds5w_init(); + _DualSenseJob = new DualSenseJob(this) { IntervalMillis = 1000 / 200 }; + _DualSenseJob.Run(); + } + public sealed override void BeforeStop() + { + if (IsPreviewing) return; + + _DualSenseJob?.CancelJoin(); + ds5w_shutdown(); + } + + public sealed override bool ShouldRender() => DefaultShouldRender() && !IsPreviewing; + + public sealed override void Render(Graphics g) { } + +} diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs new file mode 100644 index 000000000..f56a188ae --- /dev/null +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs @@ -0,0 +1,27 @@ +using System.Net; +using System.Runtime.InteropServices; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; + +internal static class Resources +{ + /* + DS5W_CAPI int ds5w_init(void); + DS5W_CAPI void ds5w_shutdown(void); + DS5W_CAPI int ds5w_set_trigger_effect_off(int left); + DS5W_CAPI int ds5w_set_trigger_effect_vibration(int left, int pos, int amp, int freq); + */ + [DllImport("ds5w_x64.dll", SetLastError = true)] + public static extern int ds5w_init(); + + [DllImport("ds5w_x64.dll", SetLastError = true)] + public static extern void ds5w_shutdown(); + + [DllImport("ds5w_x64.dll", SetLastError = true)] + public static extern int ds5w_set_trigger_effect_off(int left); + + [DllImport("ds5w_x64.dll", SetLastError = true)] + public static extern int ds5w_set_trigger_effect_vibration(int left, int pos, int amp, int freq); +} diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs new file mode 100644 index 000000000..b1200d03e --- /dev/null +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs @@ -0,0 +1,77 @@ +using RaceElement.Data.Common; +using RaceElement.Util.SystemExtensions; +using static RaceElement.HUD.Common.Overlays.Driving.DualSense.Resources; + +namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; + +internal static class TriggerHaptics +{ + public static void HandleBraking(DualSenseConfiguration config) + { + // TODO: add either an option to threshold it on brake input or based on some curve? + if (SimDataProvider.LocalCar.Inputs.Brake <= config.BrakeSlip.BrakeThreshold / 100f) + return; + float[] slipRatios = SimDataProvider.LocalCar.Tyres.SlipRatio; + if (slipRatios.Length != 4) + return; + + float slipRatioFront = Math.Max(slipRatios[0], slipRatios[1]); + float slipRatioRear = Math.Max(slipRatios[2], slipRatios[3]); + + // TODO: add option for front and rear ratio threshold. + if (slipRatioFront > config.BrakeSlip.FrontSlipThreshold || slipRatioRear > config.BrakeSlip.RearSlipThreshold) + { + float frontslipCoefecient = slipRatioFront * 4f; + frontslipCoefecient.ClipMax(10); + + float rearSlipCoefecient = slipRatioFront * 2f; + rearSlipCoefecient.ClipMax(7.5f); + + float magicValue = frontslipCoefecient + rearSlipCoefecient; + float percentage = magicValue * 1.0f / 17.5f; + //if (percentage >= 0.05f) + // p.AddAdaptiveTriggerToPacket(controllerIndex, Trigger.Left, TriggerMode.FEEDBACK, [1, (int)(config.BrakeSlip.FeedbackStrength * percentage)]); + + int freq = (int)(config.BrakeSlip.MaxFrequency * percentage); + freq.ClipMin(config.BrakeSlip.MinFrequency); + ds5w_set_trigger_effect_vibration(1, 0, config.BrakeSlip.Amplitude, freq); + } + else + { + ds5w_set_trigger_effect_off(1); + } + } + + public static void HandleAcceleration(DualSenseConfiguration config) + { + if (SimDataProvider.LocalCar.Inputs.Throttle <= config.ThrottleSlip.ThrottleThreshold / 100f) + return; + float[] slipRatios = SimDataProvider.LocalCar.Tyres.SlipRatio; + if (slipRatios.Length != 4) + return; + + float slipRatioFront = Math.Max(slipRatios[0], slipRatios[1]); + float slipRatioRear = Math.Max(slipRatios[2], slipRatios[3]); + + if (slipRatioFront > config.ThrottleSlip.FrontSlipThreshold || slipRatioRear > config.ThrottleSlip.RearSlipThreshold) + { + float frontslipCoefecient = slipRatioFront * 3f; + frontslipCoefecient.ClipMax(5); + float rearSlipCoefecient = slipRatioFront * 5f; + rearSlipCoefecient.ClipMax(7.5f); + + float magicValue = frontslipCoefecient + rearSlipCoefecient; + float percentage = magicValue * 1.0f / 12.5f; + //if (percentage >= 0.05f) + // p.AddAdaptiveTriggerToPacket(controllerIndex, Trigger.Right, TriggerMode.FEEDBACK, [1, (int)(config.ThrottleSlip.FeedbackStrength * percentage)]); + + int freq = (int)(config.ThrottleSlip.MaxFrequency * percentage); + freq.ClipMin(config.ThrottleSlip.MinFrequency); + ds5w_set_trigger_effect_vibration(0, 0, config.ThrottleSlip.Amplitude, freq); + } + else + { + ds5w_set_trigger_effect_off(0); + } + } +} From 7f69c46f849fbf1722dc99dccda4ea53a2acf515 Mon Sep 17 00:00:00 2001 From: Reinier Klarenberg Date: Sat, 25 Jan 2025 22:19:19 +0100 Subject: [PATCH 02/20] embed ds5w_x64.dll - will require version checking to auto-update the extracted file - auto extracts the embedded dll at first usage --- .../Driving/DualSense/DualSenseOverlay.cs | 29 ++++++++++++++++++ .../Overlays/Driving/DualSense/Resources.cs | 23 ++++++-------- .../Overlays/Driving/DualSense/ds5w_x64.dll | Bin 0 -> 19968 bytes .../Race Element.HUD.Common.csproj | 9 ++++-- 4 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 Race Element.HUD.Common/Overlays/Driving/DualSense/ds5w_x64.dll diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs index 4c806616c..df3f5e486 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs @@ -2,6 +2,7 @@ using RaceElement.HUD.Overlay.Internal; using System.Diagnostics; using System.Drawing; +using System.Reflection; using System.Text; using static RaceElement.HUD.Common.Overlays.Driving.DualSense.Resources; @@ -30,6 +31,9 @@ public DualSenseOverlay(Rectangle rectangle) : base(rectangle, "DualSense") public sealed override void BeforeStart() { if (IsPreviewing) return; + + ExtractDs5ApiDll(); + ds5w_init(); _DualSenseJob = new DualSenseJob(this) { IntervalMillis = 1000 / 200 }; _DualSenseJob.Run(); @@ -42,6 +46,31 @@ public sealed override void BeforeStop() ds5w_shutdown(); } + /// + /// Extracts the embbed dll in this namespace folder, to the executing assembly folder. + /// only extracts if it does not exists. Does not check for version!!! + /// + private static void ExtractDs5ApiDll() + { + string dllPath = Path.Combine(AppContext.BaseDirectory, Path.GetFileName("ds5w_x64.dll")); + FileInfo dllFile = new FileInfo(dllPath); + if (dllFile.Exists) return; + + string resourceName = "RaceElement.HUD.Common.Overlays.Driving.DualSense.ds5w_x64.dll"; + var assembly = Assembly.GetExecutingAssembly(); + using (var stream = assembly.GetManifestResourceStream(resourceName)) + { + if (stream == null) + throw new FileNotFoundException($"Could not find resource: {resourceName}"); + + dllFile.Create(); + using (var fileStream = dllFile.Open(FileMode.Create, FileAccess.Write)) + { + stream.CopyTo(fileStream); + } + } + } + public sealed override bool ShouldRender() => DefaultShouldRender() && !IsPreviewing; public sealed override void Render(Graphics g) { } diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs index f56a188ae..7cc8ef70b 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs @@ -1,11 +1,8 @@ -using System.Net; -using System.Runtime.InteropServices; -using System.Text.Json; -using System.Text.Json.Serialization; +using System.Runtime.InteropServices; namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; -internal static class Resources +internal static partial class Resources { /* DS5W_CAPI int ds5w_init(void); @@ -13,15 +10,15 @@ internal static class Resources DS5W_CAPI int ds5w_set_trigger_effect_off(int left); DS5W_CAPI int ds5w_set_trigger_effect_vibration(int left, int pos, int amp, int freq); */ - [DllImport("ds5w_x64.dll", SetLastError = true)] - public static extern int ds5w_init(); + [LibraryImport("ds5w_x64.dll", SetLastError = true)] + public static partial int ds5w_init(); - [DllImport("ds5w_x64.dll", SetLastError = true)] - public static extern void ds5w_shutdown(); + [LibraryImport("ds5w_x64.dll", SetLastError = true)] + public static partial void ds5w_shutdown(); - [DllImport("ds5w_x64.dll", SetLastError = true)] - public static extern int ds5w_set_trigger_effect_off(int left); + [LibraryImport("ds5w_x64.dll", SetLastError = true)] + public static partial int ds5w_set_trigger_effect_off(int left); - [DllImport("ds5w_x64.dll", SetLastError = true)] - public static extern int ds5w_set_trigger_effect_vibration(int left, int pos, int amp, int freq); + [LibraryImport("ds5w_x64.dll", SetLastError = true)] + public static partial int ds5w_set_trigger_effect_vibration(int left, int pos, int amp, int freq); } diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/ds5w_x64.dll b/Race Element.HUD.Common/Overlays/Driving/DualSense/ds5w_x64.dll new file mode 100644 index 0000000000000000000000000000000000000000..fb56309a0d2ebb059fec63be5eb2e907cf85c96c GIT binary patch literal 19968 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 True + + + + + + @@ -36,7 +42,6 @@ - + - From 1615691f7e5b5b83b5ce6467f2fa2ba965d71a54 Mon Sep 17 00:00:00 2001 From: Reinier Klarenberg Date: Sat, 25 Jan 2025 22:22:42 +0100 Subject: [PATCH 03/20] Update DualSenseJob.cs disable effects after cancelling the dualsense job --- .../Overlays/Driving/DualSense/DualSenseJob.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs index 1240795af..1a016b10b 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs @@ -15,5 +15,7 @@ public sealed override void RunAction() } public override void AfterCancel() { + ds5w_set_trigger_effect_off(0); + ds5w_set_trigger_effect_off(1); } } From 09c796c23886f90af9cf648449031c6d77b9bbf6 Mon Sep 17 00:00:00 2001 From: Reinier Klarenberg Date: Sat, 25 Jan 2025 23:24:33 +0100 Subject: [PATCH 04/20] Update DualSenseOverlay.cs fix creation of file --- .../Overlays/Driving/DualSense/DualSenseOverlay.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs index df3f5e486..a810f0a75 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs @@ -53,7 +53,7 @@ public sealed override void BeforeStop() private static void ExtractDs5ApiDll() { string dllPath = Path.Combine(AppContext.BaseDirectory, Path.GetFileName("ds5w_x64.dll")); - FileInfo dllFile = new FileInfo(dllPath); + FileInfo dllFile = new(dllPath); if (dllFile.Exists) return; string resourceName = "RaceElement.HUD.Common.Overlays.Driving.DualSense.ds5w_x64.dll"; @@ -63,11 +63,10 @@ private static void ExtractDs5ApiDll() if (stream == null) throw new FileNotFoundException($"Could not find resource: {resourceName}"); - dllFile.Create(); - using (var fileStream = dllFile.Open(FileMode.Create, FileAccess.Write)) - { - stream.CopyTo(fileStream); - } + using var fileStream = dllFile.Open(FileMode.Create, FileAccess.Write); + stream.CopyTo(fileStream); + stream.Close(); + fileStream.Close(); } } From ad4f4c81deaeb1fa27fb694a698eb2124a0c5727 Mon Sep 17 00:00:00 2001 From: Reinier Klarenberg Date: Sat, 25 Jan 2025 23:38:13 +0100 Subject: [PATCH 05/20] Update TriggerHaptics.cs disable effects at all times (can be improved in the future to remember this state) --- .../Overlays/Driving/DualSense/TriggerHaptics.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs index b1200d03e..692a439c4 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs @@ -10,10 +10,16 @@ public static void HandleBraking(DualSenseConfiguration config) { // TODO: add either an option to threshold it on brake input or based on some curve? if (SimDataProvider.LocalCar.Inputs.Brake <= config.BrakeSlip.BrakeThreshold / 100f) + { + ds5w_set_trigger_effect_off(1); return; + } float[] slipRatios = SimDataProvider.LocalCar.Tyres.SlipRatio; if (slipRatios.Length != 4) + { + ds5w_set_trigger_effect_off(1); return; + } float slipRatioFront = Math.Max(slipRatios[0], slipRatios[1]); float slipRatioRear = Math.Max(slipRatios[2], slipRatios[3]); @@ -45,10 +51,16 @@ public static void HandleBraking(DualSenseConfiguration config) public static void HandleAcceleration(DualSenseConfiguration config) { if (SimDataProvider.LocalCar.Inputs.Throttle <= config.ThrottleSlip.ThrottleThreshold / 100f) + { + ds5w_set_trigger_effect_off(0); return; + } float[] slipRatios = SimDataProvider.LocalCar.Tyres.SlipRatio; if (slipRatios.Length != 4) + { + ds5w_set_trigger_effect_off(0); return; + } float slipRatioFront = Math.Max(slipRatios[0], slipRatios[1]); float slipRatioRear = Math.Max(slipRatios[2], slipRatios[3]); From 3615968f738e2d9e5d699c2855de68cb88034c14 Mon Sep 17 00:00:00 2001 From: Reinier Klarenberg Date: Sat, 25 Jan 2025 23:40:45 +0100 Subject: [PATCH 06/20] Update DualSenseConfiguration.cs update default settings, feels better after the previous commit, you can turn down amplitude ofc! --- .../Overlays/Driving/DualSense/DualSenseConfiguration.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs index 1f13af5ed..43edd1974 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs @@ -36,7 +36,7 @@ public sealed class BrakeSlipHaptics [ToolTip("Sets the min frequency of the vibration effect in the trigger.")] [IntRange(1, 10, 1)] - public int MinFrequency { get; init; } = 10; + public int MinFrequency { get; init; } = 3; [ToolTip("Sets the max frequency of the vibration effect in the trigger.")] [IntRange(20, 150, 1)] @@ -44,7 +44,7 @@ public sealed class BrakeSlipHaptics [ToolTip("Change the amplitude(strength) of the vibration effect in the trigger.")] [IntRange(1, 8, 1)] - public int Amplitude { get; init; } = 1; + public int Amplitude { get; init; } = 8; } [ConfigGrouping("Throttle Slip", "Adjust the slip effect whilst applying the throttle.\nModify the threshold to increase or decrease sensitivity in different situations.")] @@ -72,7 +72,7 @@ public sealed class ThrottleSlipHaptics [ToolTip("Sets the min frequency of the vibration effect in the trigger.")] [IntRange(1, 10, 1)] - public int MinFrequency { get; init; } = 10; + public int MinFrequency { get; init; } = 6; [ToolTip("Sets the max frequency of the vibration effect in the trigger.")] [IntRange(20, 150, 1)] @@ -80,7 +80,7 @@ public sealed class ThrottleSlipHaptics [ToolTip("Change the amplitude(strength) of the vibration effect in the trigger.")] [IntRange(1, 8, 1)] - public int Amplitude { get; init; } = 1; + public int Amplitude { get; init; } = 7; } } From 7231cafe61bc58616cc83a784aaa4bf5439c83d9 Mon Sep 17 00:00:00 2001 From: Reinier Klarenberg Date: Sat, 25 Jan 2025 23:49:29 +0100 Subject: [PATCH 07/20] Update TriggerHaptics.cs add feedback as 0 frequency --- .../Overlays/Driving/DualSense/TriggerHaptics.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs index 692a439c4..0ad5c10ed 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs @@ -35,8 +35,8 @@ public static void HandleBraking(DualSenseConfiguration config) float magicValue = frontslipCoefecient + rearSlipCoefecient; float percentage = magicValue * 1.0f / 17.5f; - //if (percentage >= 0.05f) - // p.AddAdaptiveTriggerToPacket(controllerIndex, Trigger.Left, TriggerMode.FEEDBACK, [1, (int)(config.BrakeSlip.FeedbackStrength * percentage)]); + if (percentage >= 0.05f) + ds5w_set_trigger_effect_vibration(1, 0, (int)(config.ThrottleSlip.FeedbackStrength * percentage), 0); int freq = (int)(config.BrakeSlip.MaxFrequency * percentage); freq.ClipMin(config.BrakeSlip.MinFrequency); @@ -74,8 +74,8 @@ public static void HandleAcceleration(DualSenseConfiguration config) float magicValue = frontslipCoefecient + rearSlipCoefecient; float percentage = magicValue * 1.0f / 12.5f; - //if (percentage >= 0.05f) - // p.AddAdaptiveTriggerToPacket(controllerIndex, Trigger.Right, TriggerMode.FEEDBACK, [1, (int)(config.ThrottleSlip.FeedbackStrength * percentage)]); + if (percentage >= 0.05f) + ds5w_set_trigger_effect_vibration(0, 0, (int)(config.ThrottleSlip.FeedbackStrength * percentage), 0); int freq = (int)(config.ThrottleSlip.MaxFrequency * percentage); freq.ClipMin(config.ThrottleSlip.MinFrequency); From 23b6b8f45321747e55b7ba7063e1df3d2fb7a471 Mon Sep 17 00:00:00 2001 From: Reinier Klarenberg Date: Sat, 25 Jan 2025 23:57:19 +0100 Subject: [PATCH 08/20] Update TriggerHaptics.cs - fix ffb str to brake setting instead of throttle for brake slip feedback --- .../Overlays/Driving/DualSense/TriggerHaptics.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs index 0ad5c10ed..99a505b11 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs @@ -35,8 +35,9 @@ public static void HandleBraking(DualSenseConfiguration config) float magicValue = frontslipCoefecient + rearSlipCoefecient; float percentage = magicValue * 1.0f / 17.5f; + if (percentage >= 0.05f) - ds5w_set_trigger_effect_vibration(1, 0, (int)(config.ThrottleSlip.FeedbackStrength * percentage), 0); + ds5w_set_trigger_effect_vibration(1, 0, (int)(config.BrakeSlip.FeedbackStrength * percentage), 0); int freq = (int)(config.BrakeSlip.MaxFrequency * percentage); freq.ClipMin(config.BrakeSlip.MinFrequency); From d7ad4add6fc30d1bebe8ad00e27ae996e3fdb3be Mon Sep 17 00:00:00 2001 From: Reinier Klarenberg Date: Sun, 26 Jan 2025 00:10:31 +0100 Subject: [PATCH 09/20] revert tripperhaptics to vibration only --- .../Overlays/Driving/DualSense/TriggerHaptics.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs index 99a505b11..12eb22e9b 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs @@ -36,8 +36,8 @@ public static void HandleBraking(DualSenseConfiguration config) float magicValue = frontslipCoefecient + rearSlipCoefecient; float percentage = magicValue * 1.0f / 17.5f; - if (percentage >= 0.05f) - ds5w_set_trigger_effect_vibration(1, 0, (int)(config.BrakeSlip.FeedbackStrength * percentage), 0); + //if (percentage >= 0.05f) + // ds5w_set_trigger_effect_vibration(1, 0, (int)(config.BrakeSlip.FeedbackStrength * percentage), 90); int freq = (int)(config.BrakeSlip.MaxFrequency * percentage); freq.ClipMin(config.BrakeSlip.MinFrequency); @@ -75,8 +75,8 @@ public static void HandleAcceleration(DualSenseConfiguration config) float magicValue = frontslipCoefecient + rearSlipCoefecient; float percentage = magicValue * 1.0f / 12.5f; - if (percentage >= 0.05f) - ds5w_set_trigger_effect_vibration(0, 0, (int)(config.ThrottleSlip.FeedbackStrength * percentage), 0); + //if (percentage >= 0.05f) + // ds5w_set_trigger_effect_vibration(0, 0, (int)(config.ThrottleSlip.FeedbackStrength * percentage), 0); int freq = (int)(config.ThrottleSlip.MaxFrequency * percentage); freq.ClipMin(config.ThrottleSlip.MinFrequency); From 135b34da6eb16d5798595f953e6dbfb5d35b58ae Mon Sep 17 00:00:00 2001 From: kamih Date: Sat, 25 Jan 2025 16:28:49 -0700 Subject: [PATCH 10/20] added ds5w_set_trigger_effect_feedback and ds5w_set_trigger_effect_weapon to DualSense API Resources --- .../Overlays/Driving/DualSense/Resources.cs | 12 ++++++------ .../Overlays/Driving/DualSense/ds5w_x64.dll | Bin 19968 -> 19968 bytes 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs index 7cc8ef70b..bb8a16a15 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs @@ -4,12 +4,6 @@ namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; internal static partial class Resources { - /* - DS5W_CAPI int ds5w_init(void); - DS5W_CAPI void ds5w_shutdown(void); - DS5W_CAPI int ds5w_set_trigger_effect_off(int left); - DS5W_CAPI int ds5w_set_trigger_effect_vibration(int left, int pos, int amp, int freq); - */ [LibraryImport("ds5w_x64.dll", SetLastError = true)] public static partial int ds5w_init(); @@ -21,4 +15,10 @@ internal static partial class Resources [LibraryImport("ds5w_x64.dll", SetLastError = true)] public static partial int ds5w_set_trigger_effect_vibration(int left, int pos, int amp, int freq); + + [LibraryImport("ds5w_x64.dll", SetLastError = true)] + public static partial int ds5w_set_trigger_effect_feedback(int left, int pos, int strength); + + [LibraryImport("ds5w_x64.dll", SetLastError = true)] + public static partial int ds5w_set_trigger_effect_weapon(int left, int start, int end, int strength); } diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/ds5w_x64.dll b/Race Element.HUD.Common/Overlays/Driving/DualSense/ds5w_x64.dll index fb56309a0d2ebb059fec63be5eb2e907cf85c96c..a6e93968e85f47519d796ea711d552ad8db81a0a 100644 GIT binary patch delta 5382 zcmeHLdwf&n8U9Y%(}tEby`>k@v}v2rR-sf_7l9!ZIvokoHM1`76AcufC{s0q6NHEnNsTX?0L^QQDEEO`)B9(d(ZQ{ zm+$>9=lkAs65kfVw?$~n5Td@jV-q(E7NLz#5EjH_L^D=c$A2sQLTKcT$+0#)C1xjQwGE155%p$7U{`E6cLl zzwy30aP@7jC*#rMbFpVIZcEPorN_ZXzm^(HAa zEusGfzC>SAdEh$6`tOdy`rKnHVV+4+$h4*wSwe;#ZE)X55mZrVmh#9a#!>2 z4(tN9Q;!?c{{p@SW92T)Vjj_eSWPKH;`IcoW8zHaW!+3XS&KpJ-RrBE4By2GU6G8V zDUAy)t3xIu@qjo~qofp}Rl(6xBcQtzFygVhTbw#~ixhS88;nSK2)>Gs;JPrsmoe8X z+K~6bOC5AphYWut9uPMJFy^fQbkM1G&sl8cqBRX;H&V$bzuj{ADO^XI3p97 zK|CN%Gy~B=CE%wS*r9bZJ1>q))Af(xSH=|!9lR;7HhR$*Y+pRVaGeN>D@xUCw`2unSU2wm~n12V?C8lE5;**uC1>M?sElY*|eCK4<9d-^E-zx z6w>(N;a3Qc@-#z{?wgU^Wylid@|z8fwsi$cqr$4-e%U09WDF;wP6|#hltP<)NGO{= zw)0a4r+d4dvEZ6$B`yYWau4?Nz`YZW9b+u8Cb}s`Ha!iq6smN(gZryPVyCjf+%~H= zCfRg3UzSj;8?^H$6VgUA3T~D?QSLy2tNf@r?C;Z^&c@hf(+PB?Y_QV_ivAZnKb}x6 zJjjcUtAq#m)5daPG5@=9wC=rpo}9QO+qX$PP$t#^XHP>$>Z~s15_dfgL)lJ zqGDt6WMK_=CV!Oh`59U6s2csjDLneG^7!bKJ9Nv=@Ya+ZVJQ!%jL^-uav?dBf0J^J zu$sG5w;6>>tb?)nP279LuiX4xYOZ6Wm8NR&1NsvTN@qp=(?w~_3U6?|JZ-NX~qM`mtQ9cp|cyurhYH=EB$UuJtc z3(bOiWYYs6vZ+;3dv^|tW?|F{>(372^#+6g1>S$}kE1>q(M~sM^#GlQ`GS4tmPwj(9=#X)`sBYFvv?3L}FJrtg zo~LKp1s|`-v|OrFVk;A+K;?jJT0a6OA}n1-e1pnE(=$}Pg*RtTO#FTV<(^}!kHtE9}~f5$&4{MYi7s$6nH3gMKmrlSA3)1n*Li+ecg_ zwD6@P-WNvltIXrT*O)5=7k||}VTm3ahXvnny2XD^Sh=`gh*2IyVe^MgHYEHSOW8k8 zu{9+^A0pkZ#uSeYpLR4DZx`Rpq#^anXN+F4Q+*t70Z1jpMBW8-i%;>r&N|8enblYEIt*3cisjt+S^!+HK4|wpQf%bBk0Q>@s6Kd z^FafaM*f2Ja&HOv_C9~FzDKlx;smpRXa;kA+iCUO(zFU<0HswC3+)pX@qsqNox%d8?eH)*f_m!}o&&+q} zK1gbRIDeGRy9}Q~bj{JQTEkKeM`)p76;teYMV77`jO^?&?YR!JLhU>NVk7@Xn zie9!|Gkl>1u8K6!utrPxjHY*MxJ9$C({QndkpcesT9s|nutmc|8a68Ejf6Ayi8he8 zHH^7l^|f7;c)VsW)-aOcsHQK`aGi!XYFMqIQ^Pk1@g2#Y(F~D9c^B!+FJ(SD5D{z} zqv{7P!btlE+7A|-5zFz5;ubQ|3AzjNu>`@#4P6l*UYaZwGN%fHZy~zqmxw$%Q~gC! zyrzDJjj=tDKFC8O8KV!7TZ$OF@e;`iXAFWo#!Uo2k0$-1uhmdff1Xnq=X%6 ze`3r^p^APR6)##i&ohsHBdPg|ZzbI}mYTi@8_h|x;fyoZ3tKDJP_v;%G1ka$y6o5X z<4Gva(-_Nzr4{@q9qWcT#l~~TUYh1Z(hy`)wHmGJeE!(Hisxxrkv=mkn#BnzENZ!~ zgls;Tb5o*O%EDx(pOwMt@m6Ywtk+T~I`15tBC72Dv15u_EsXsQ@((2jgYf9tg*FU| zV)$i_{Gv8|N_-6|n@)qG=wa+a8&h?@#*v>}k1^49D8y_Zh0tT6YY1G-gU&l0<|!0~ zHD;4xxf$}g7F7yF*Z~?>vyASvzqy@YcH~^uQAdJaFy@g#5Y=ImACu~DWvRwnL z2l*T_3(5c)@t#`+PIwlw5PT4LtDUhW;7foRcnA8x3CkhWStHP|@wLF$G#=*XrkcH_ z_zQrd2&*(+4SXK*A~F#k)$D`=8YjF2b&}eS0=^8P(RBc8P&?Oy6M7(ICwxNVZNNdi zp?j~vLncy+e+y{05aMe>;U3@>#i&teOz*7S5bA6%uwV>h|AgHMd;p?H3B}h3+YT9k t9bX{IJ7f@?-X-*==*9XH(p!Q!;fNA!H&W;wK-In)4G0_ClPbT|{|mE=Ax8iJ delta 5297 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 Date: Sun, 26 Jan 2025 00:38:27 +0100 Subject: [PATCH 11/20] Update TriggerHaptics.cs add feedback effect --- .../Overlays/Driving/DualSense/TriggerHaptics.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs index 12eb22e9b..4e5a51d1e 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs @@ -36,8 +36,11 @@ public static void HandleBraking(DualSenseConfiguration config) float magicValue = frontslipCoefecient + rearSlipCoefecient; float percentage = magicValue * 1.0f / 17.5f; - //if (percentage >= 0.05f) - // ds5w_set_trigger_effect_vibration(1, 0, (int)(config.BrakeSlip.FeedbackStrength * percentage), 90); + if (percentage >= 0.05f) + { + ds5w_set_trigger_effect_feedback(1, 0, (int)(config.BrakeSlip.FeedbackStrength * percentage)); + ds5w_set_trigger_effect_off(1); + } int freq = (int)(config.BrakeSlip.MaxFrequency * percentage); freq.ClipMin(config.BrakeSlip.MinFrequency); @@ -75,8 +78,11 @@ public static void HandleAcceleration(DualSenseConfiguration config) float magicValue = frontslipCoefecient + rearSlipCoefecient; float percentage = magicValue * 1.0f / 12.5f; - //if (percentage >= 0.05f) - // ds5w_set_trigger_effect_vibration(0, 0, (int)(config.ThrottleSlip.FeedbackStrength * percentage), 0); + if (percentage >= 0.05f) + { + ds5w_set_trigger_effect_feedback(0, 0, (int)(config.ThrottleSlip.FeedbackStrength * percentage)); + ds5w_set_trigger_effect_off(0); + } int freq = (int)(config.ThrottleSlip.MaxFrequency * percentage); freq.ClipMin(config.ThrottleSlip.MinFrequency); From a660d5d88fd54ea00a54503ab13391a107339eef Mon Sep 17 00:00:00 2001 From: kamih Date: Sun, 26 Jan 2025 16:00:47 -0700 Subject: [PATCH 12/20] added new math utility functions to FloatExtensions, different trigger effect logic with new parameters --- .../DualSense/DualSenseConfiguration.cs | 62 +++++++-------- .../Driving/DualSense/DualSenseJob.cs | 6 +- .../Driving/DualSense/DualSenseOverlay.cs | 2 +- .../Overlays/Driving/DualSense/Resources.cs | 15 +++- .../Driving/DualSense/TriggerHaptics.cs | 77 ++++++++++++++++--- .../SystemExtensions/FloatExtensions.cs | 21 ++++- 6 files changed, 129 insertions(+), 54 deletions(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs index 43edd1974..b4b5a2bc0 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs @@ -24,27 +24,23 @@ public sealed class BrakeSlipHaptics [FloatRange(0.1f, 99f, 0.1f, 1)] public float BrakeThreshold { get; init; } = 3f; - [FloatRange(0.05f, 6f, 0.002f, 3)] - public float FrontSlipThreshold { get; init; } = 0.25f; + [FloatRange(0.0f, 1.0f, 0.002f, 3)] + public float MinSlipRatio { get; init; } = 0.5f; - [FloatRange(0.05f, 6f, 0.002f, 3)] - public float RearSlipThreshold { get; init; } = 0.25f; + [FloatRange(1.0f, 10.0f, 0.002f, 3)] + public float MaxSlipRatio { get; init; } = 2.5f; - [ToolTip("Higher is stronger dynamic feedback.")] - [IntRange(5, 8, 1)] - public int FeedbackStrength { get; init; } = 7; + [ToolTip("Sets the frequency of the trigger vibration effect at the MinSlipRatio value.")] + [FloatRange(10.0f, 255.0f, 0.5f, 2)] + public float FreqAtMinSlipRatio { get; init; } = 255.0f; - [ToolTip("Sets the min frequency of the vibration effect in the trigger.")] - [IntRange(1, 10, 1)] - public int MinFrequency { get; init; } = 3; + [ToolTip("Sets the frequency of the trigger vibration effect at the MaxSlipRatio value.")] + [FloatRange(10.0f, 255.0f, 0.5f, 2)] + public float FreqAtMaxSlipRatio { get; init; } = 20.0f; - [ToolTip("Sets the max frequency of the vibration effect in the trigger.")] - [IntRange(20, 150, 1)] - public int MaxFrequency { get; init; } = 100; - - [ToolTip("Change the amplitude(strength) of the vibration effect in the trigger.")] - [IntRange(1, 8, 1)] - public int Amplitude { get; init; } = 8; + [ToolTip("Gain for the effect amplitude as SlipRatio increases.")] + [FloatRange(1.0f, 10.0f, 0.1f, 1)] + public float AmpGain { get; init; } = 2.5f; } [ConfigGrouping("Throttle Slip", "Adjust the slip effect whilst applying the throttle.\nModify the threshold to increase or decrease sensitivity in different situations.")] @@ -58,29 +54,23 @@ public sealed class ThrottleSlipHaptics [FloatRange(0.1f, 99f, 0.1f, 1)] public float ThrottleThreshold { get; init; } = 3f; - [ToolTip("Decrease this treshold to increase the sensitivity when the front wheels slip (understeer).")] - [FloatRange(0.05f, 6f, 0.002f, 3)] - public float FrontSlipThreshold { get; init; } = 0.35f; - - [ToolTip("Decrease this treshold to increase the sensitivity when the rear wheels slip (oversteer).")] - [FloatRange(0.05f, 10f, 0.002f, 3)] - public float RearSlipThreshold { get; init; } = 0.25f; + [FloatRange(0.0f, 1.0f, 0.002f, 3)] + public float MinSlipRatio { get; init; } = 0.5f; - [ToolTip("Higher is stronger dynamic feedback.")] - [IntRange(5, 8, 1)] - public int FeedbackStrength { get; init; } = 8; + [FloatRange(1.0f, 10.0f, 0.002f, 3)] + public float MaxSlipRatio { get; init; } = 2.5f; - [ToolTip("Sets the min frequency of the vibration effect in the trigger.")] - [IntRange(1, 10, 1)] - public int MinFrequency { get; init; } = 6; + [ToolTip("Sets the frequency of the trigger vibration effect at the MinSlipRatio value.")] + [FloatRange(10.0f, 255.0f, 0.5f, 2)] + public float FreqAtMinSlipRatio { get; init; } = 255.0f; - [ToolTip("Sets the max frequency of the vibration effect in the trigger.")] - [IntRange(20, 150, 1)] - public int MaxFrequency { get; init; } = 100; + [ToolTip("Sets the frequency of the trigger vibration effect at the MaxSlipRatio value.")] + [FloatRange(10.0f, 255.0f, 0.5f, 2)] + public float FreqAtMaxSlipRatio { get; init; } = 20.0f; - [ToolTip("Change the amplitude(strength) of the vibration effect in the trigger.")] - [IntRange(1, 8, 1)] - public int Amplitude { get; init; } = 7; + [ToolTip("Gain for the effect amplitude as SlipRatio increases.")] + [FloatRange(1.0f, 10.0f, 0.1f, 1)] + public float AmpGain { get; init; } = 2.5f; } } diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs index 1a016b10b..fb9cd7f88 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs @@ -1,5 +1,5 @@ using RaceElement.Core.Jobs.Loop; -using static RaceElement.HUD.Common.Overlays.Driving.DualSense.Resources; +using static RaceElement.HUD.Common.Overlays.Driving.DualSense.DS5W; namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; @@ -10,8 +10,8 @@ public sealed override void RunAction() //if (!overlay.ShouldRender()) // return; - TriggerHaptics.HandleAcceleration(overlay._config); - TriggerHaptics.HandleBraking(overlay._config); + TriggerHaptics.HandleAcceleration(overlay._config.ThrottleSlip); + TriggerHaptics.HandleBraking(overlay._config.BrakeSlip); } public override void AfterCancel() { diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs index a810f0a75..89e935688 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseOverlay.cs @@ -5,7 +5,7 @@ using System.Reflection; using System.Text; -using static RaceElement.HUD.Common.Overlays.Driving.DualSense.Resources; +using static RaceElement.HUD.Common.Overlays.Driving.DualSense.DS5W; namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs index bb8a16a15..8b462ef93 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs @@ -1,8 +1,19 @@ -using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Runtime.InteropServices; namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; -internal static partial class Resources +internal class Util +{ + public static void DebugOut(string msg) + { + StackTrace st = new StackTrace(false); + string caller = st.GetFrame(1).GetMethod().Name; + Debug.WriteLine(caller + ": " + msg); + } +} + +internal static partial class DS5W { [LibraryImport("ds5w_x64.dll", SetLastError = true)] public static partial int ds5w_init(); diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs index 4e5a51d1e..8a69ffd1b 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs @@ -1,11 +1,67 @@ using RaceElement.Data.Common; using RaceElement.Util.SystemExtensions; -using static RaceElement.HUD.Common.Overlays.Driving.DualSense.Resources; +using static RaceElement.Util.SystemExtensions.FloatExtensions; +using static RaceElement.HUD.Common.Overlays.Driving.DualSense.DS5W; +using static RaceElement.HUD.Common.Overlays.Driving.DualSense.Util; +using static RaceElement.HUD.Common.Overlays.Driving.DualSense.DualSenseConfiguration; namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; internal static class TriggerHaptics { + public static void HandleAcceleration(ThrottleSlipHaptics config) + { + float[] slipRatios = SimDataProvider.LocalCar.Tyres.SlipRatio; + if (SimDataProvider.LocalCar.Inputs.Throttle <= config.ThrottleThreshold / 100f || + slipRatios.Length != 4) + { + ds5w_set_trigger_effect_off(0); + return; + } + //DebugOut("Slip Ratios: " + slipRatios[0] + ", " + slipRatios[1] + ", " + slipRatios[2] + ", " + slipRatios[3]); + float slipRatioFront = 0.5f * (slipRatios[0] + slipRatios[1]); + if (slipRatioFront < config.MinSlipRatio) + { + ds5w_set_trigger_effect_off(0); + return; + } + // Calculate frequency from slipRatio + float srWeight = SmoothStep(slipRatioFront, config.MinSlipRatio, config.MaxSlipRatio); + float freqf = Lerp(srWeight, config.FreqAtMinSlipRatio, config.FreqAtMaxSlipRatio); + int freq = (int)Math.Round(Clip(freqf, 0.0f, 255.0f)); + // Calculate amplitude from slipRatio + int amp = 1 + (int)Math.Round(Math.Sqrt(slipRatioFront - config.MinSlipRatio ) * config.AmpGain); + amp.ClipMax(8); + DebugOut("slipRatioFront: " + slipRatioFront + ", freq: " + freq + ", amp: " + amp); + ds5w_set_trigger_effect_vibration(0, 0, amp, freq); + } + public static void HandleBraking(BrakeSlipHaptics config) + { + float[] slipRatios = SimDataProvider.LocalCar.Tyres.SlipRatio; + if (SimDataProvider.LocalCar.Inputs.Brake <= config.BrakeThreshold / 100f || + slipRatios.Length != 4) + { + ds5w_set_trigger_effect_off(1); + return; + } + //DebugOut("Slip Ratios: " + slipRatios[0] + ", " + slipRatios[1] + ", " + slipRatios[2] + ", " + slipRatios[3]); + float slipRatioBack = 0.5f * (slipRatios[2] + slipRatios[3]); + if (slipRatioBack < config.MinSlipRatio) + { + ds5w_set_trigger_effect_off(1); + return; + } + // Calculate frequency from slipRatio + float srWeight = SmoothStep(slipRatioBack, config.MinSlipRatio, config.MaxSlipRatio); + float freqf = Lerp(srWeight, config.FreqAtMinSlipRatio, config.FreqAtMaxSlipRatio); + int freq = (int)Math.Round(Clip(freqf, 0.0f, 255.0f)); + // Calculate amplitude from slipRatio + int amp = 1 + (int)Math.Round(Math.Sqrt(slipRatioBack - config.MinSlipRatio) * config.AmpGain); + amp.ClipMax(8); + DebugOut("slipRatioBack: " + slipRatioBack + ", freq: " + freq + ", amp: " + amp); + ds5w_set_trigger_effect_vibration(1, 0, amp, freq); + } +#if false public static void HandleBraking(DualSenseConfiguration config) { // TODO: add either an option to threshold it on brake input or based on some curve? @@ -35,23 +91,21 @@ public static void HandleBraking(DualSenseConfiguration config) float magicValue = frontslipCoefecient + rearSlipCoefecient; float percentage = magicValue * 1.0f / 17.5f; - - if (percentage >= 0.05f) - { - ds5w_set_trigger_effect_feedback(1, 0, (int)(config.BrakeSlip.FeedbackStrength * percentage)); - ds5w_set_trigger_effect_off(1); + int strength = (int)(config.BrakeSlip.FeedbackStrength * percentage); + if (strength >= 1) { + ds5w_set_trigger_effect_feedback(1, 0, strength); + //ds5w_set_trigger_effect_off(1); } - int freq = (int)(config.BrakeSlip.MaxFrequency * percentage); + /*int freq = (int)(config.BrakeSlip.MaxFrequency * percentage); freq.ClipMin(config.BrakeSlip.MinFrequency); - ds5w_set_trigger_effect_vibration(1, 0, config.BrakeSlip.Amplitude, freq); + ds5w_set_trigger_effect_vibration(1, 0, config.BrakeSlip.Amplitude, freq);*/ } else { ds5w_set_trigger_effect_off(1); } } - public static void HandleAcceleration(DualSenseConfiguration config) { if (SimDataProvider.LocalCar.Inputs.Throttle <= config.ThrottleSlip.ThrottleThreshold / 100f) @@ -78,11 +132,11 @@ public static void HandleAcceleration(DualSenseConfiguration config) float magicValue = frontslipCoefecient + rearSlipCoefecient; float percentage = magicValue * 1.0f / 12.5f; - if (percentage >= 0.05f) + /*if (percentage >= 0.05f) { ds5w_set_trigger_effect_feedback(0, 0, (int)(config.ThrottleSlip.FeedbackStrength * percentage)); ds5w_set_trigger_effect_off(0); - } + }*/ int freq = (int)(config.ThrottleSlip.MaxFrequency * percentage); freq.ClipMin(config.ThrottleSlip.MinFrequency); @@ -93,4 +147,5 @@ public static void HandleAcceleration(DualSenseConfiguration config) ds5w_set_trigger_effect_off(0); } } +#endif } diff --git a/Race_Element.Util/SystemExtensions/FloatExtensions.cs b/Race_Element.Util/SystemExtensions/FloatExtensions.cs index 80a62ce4d..068689fe6 100644 --- a/Race_Element.Util/SystemExtensions/FloatExtensions.cs +++ b/Race_Element.Util/SystemExtensions/FloatExtensions.cs @@ -18,6 +18,10 @@ public static float Clip(ref this float value, float min, float max) if (value > max) value = max; return value; } + public static float Clip(float value, float min, float max) + { + return Math.Min(max, Math.Max(min, value)); + } /// /// Sets this value or returns it, clipped by max (inclusive) @@ -45,7 +49,22 @@ public static float ClipMin(ref this float value, float min) return value; } - + public static float Cubic(float x) + { + return x * x * (3.0f - 2.0f * x); + } + public static float SmoothStep(float x, float edge0, float edge1) + { + // Scale, bias and clamp x to 0..1 range + x = (x - edge0) / (edge1 - edge0); + x = Math.Min(1.0f, Math.Max(0.0f, x)); + // Evaluate polynomial + return Cubic(x); + } + public static float Lerp(float weight, float a, float b) + { + return a * (1.0f - weight) + b * weight; + } public static string ToString(this float[] values, int decimals) { From 721282da892f023ebe78599d8083ed2afc0e7278 Mon Sep 17 00:00:00 2001 From: kamih Date: Mon, 27 Jan 2025 02:32:54 -0700 Subject: [PATCH 13/20] added ds5w_batch_begin, ds5w_batch_end, and ds5w_set_rumble API functions to ds5w DLL --- .../Overlays/Driving/DualSense/Resources.cs | 21 +++++++++++++----- .../Overlays/Driving/DualSense/ds5w_x64.dll | Bin 19968 -> 20992 bytes 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs index 8b462ef93..b7bc387d0 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/Resources.cs @@ -15,21 +15,30 @@ public static void DebugOut(string msg) internal static partial class DS5W { - [LibraryImport("ds5w_x64.dll", SetLastError = true)] + [LibraryImport("ds5w_x64.dll")] public static partial int ds5w_init(); - [LibraryImport("ds5w_x64.dll", SetLastError = true)] + [LibraryImport("ds5w_x64.dll")] public static partial void ds5w_shutdown(); - [LibraryImport("ds5w_x64.dll", SetLastError = true)] + [LibraryImport("ds5w_x64.dll")] + public static partial void ds5w_batch_begin(); + + [LibraryImport("ds5w_x64.dll")] + public static partial int ds5w_batch_end(); + + [LibraryImport("ds5w_x64.dll")] + public static partial int ds5w_set_rumble(int left, int strength); + + [LibraryImport("ds5w_x64.dll")] public static partial int ds5w_set_trigger_effect_off(int left); - [LibraryImport("ds5w_x64.dll", SetLastError = true)] + [LibraryImport("ds5w_x64.dll")] public static partial int ds5w_set_trigger_effect_vibration(int left, int pos, int amp, int freq); - [LibraryImport("ds5w_x64.dll", SetLastError = true)] + [LibraryImport("ds5w_x64.dll")] public static partial int ds5w_set_trigger_effect_feedback(int left, int pos, int strength); - [LibraryImport("ds5w_x64.dll", SetLastError = true)] + [LibraryImport("ds5w_x64.dll")] public static partial int ds5w_set_trigger_effect_weapon(int left, int start, int end, int strength); } diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/ds5w_x64.dll b/Race Element.HUD.Common/Overlays/Driving/DualSense/ds5w_x64.dll index a6e93968e85f47519d796ea711d552ad8db81a0a..fb6435a87c418de24fec2fd8c3f7fe597f59fa3e 100644 GIT binary patch delta 5835 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 From 8d831939a504e28574df114281fe391bbc523dd3 Mon Sep 17 00:00:00 2001 From: kamih Date: Mon, 27 Jan 2025 02:35:15 -0700 Subject: [PATCH 14/20] added suspensionTravel and kerb/slip/g/abs vibration telemetry data to LocalCarData --- .../Common/SimulatorData/LocalCar/LocalCarData.cs | 15 +++++++++++++++ .../AssettoCorsaEvo/DataMapper/LocalCarMapper.cs | 7 ++++++- .../SharedMemory/AcEvoSharedMemory.cs | 8 ++++---- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/Race Element.Data/Common/SimulatorData/LocalCar/LocalCarData.cs b/Race Element.Data/Common/SimulatorData/LocalCar/LocalCarData.cs index 440b6b383..bbf5a36d0 100644 --- a/Race Element.Data/Common/SimulatorData/LocalCar/LocalCarData.cs +++ b/Race Element.Data/Common/SimulatorData/LocalCar/LocalCarData.cs @@ -143,6 +143,21 @@ public sealed record PhysicsData /// The speed of the car in kilometers per hour. /// public float Velocity { get; internal set; } + + /// Wheel suspension travel. + public float[] SuspensionTravel { get; internal set; } = new float[4]; + + /// Vibrations generated from driving on curbs and off track. + public float KerbVibration; + + /// Vibrations generated from tire slip. + public float SlipVibrations; + + /// Vibrations generated from g-forces. + public float Gvibrations; + + /// Vibrations generated from brake ABS. + public float AbsVibrations; } public sealed record InputsData { diff --git a/Race Element.Data/Games/AssettoCorsaEvo/DataMapper/LocalCarMapper.cs b/Race Element.Data/Games/AssettoCorsaEvo/DataMapper/LocalCarMapper.cs index 8491e726f..30c24b33a 100644 --- a/Race Element.Data/Games/AssettoCorsaEvo/DataMapper/LocalCarMapper.cs +++ b/Race Element.Data/Games/AssettoCorsaEvo/DataMapper/LocalCarMapper.cs @@ -11,11 +11,16 @@ internal static partial class LocalCarMapper { internal static void AddPhysics(ref SPageFilePhysics pagePhysics, ref LocalCarData commonData, ref SessionData sessionData) { + commonData.Physics.SuspensionTravel = pagePhysics.SuspensionTravel; + commonData.Physics.KerbVibration = pagePhysics.KerbVibration; + commonData.Physics.SlipVibrations = pagePhysics.SlipVibrations; + commonData.Physics.Gvibrations = pagePhysics.Gvibrations; + commonData.Physics.AbsVibrations = pagePhysics.AbsVibrations; commonData.Physics.Acceleration = new(pagePhysics.AccG[0], pagePhysics.AccG[1], pagePhysics.AccG[2]); + commonData.Engine.IsPitLimiterOn = pagePhysics.PitLimiterOn; commonData.Engine.MaxRpm = pagePhysics.CurrentMaxRpm; commonData.Engine.Rpm = pagePhysics.Rpms; - commonData.Engine.IsRunning = commonData.Engine.Rpm > 0; commonData.Inputs.Steering = pagePhysics.SteerAngle; diff --git a/Race Element.Data/Games/AssettoCorsaEvo/SharedMemory/AcEvoSharedMemory.cs b/Race Element.Data/Games/AssettoCorsaEvo/SharedMemory/AcEvoSharedMemory.cs index cc9859065..8aaa0f7a2 100644 --- a/Race Element.Data/Games/AssettoCorsaEvo/SharedMemory/AcEvoSharedMemory.cs +++ b/Race Element.Data/Games/AssettoCorsaEvo/SharedMemory/AcEvoSharedMemory.cs @@ -691,16 +691,16 @@ public sealed class SPageFilePhysics /// Engine running? [MarshalAs(UnmanagedType.Bool)] public bool IsEngineRunning; - /// Vibrations sent to the FFB, could be used for motion rigs + /// Vibrations generated from driving on curbs and off track. public float KerbVibration; - /// Vibrations sent to the FFB, could be used for motion rigs + /// Vibrations generated from tire slip. public float SlipVibrations; - /// Vibrations sent to the FFB, could be used for motion rigs + /// Vibrations generated from g-forces. public float Gvibrations; - /// Vibrations sent to the FFB, could be used for motion rigs + /// Vibrations generated from brake ABS. public float AbsVibrations; public static readonly int Size = Marshal.SizeOf(typeof(SPageFilePhysics)); From 457dcd7e6f69af2cc74fd07278d4c11f65240e95 Mon Sep 17 00:00:00 2001 From: kamih Date: Mon, 27 Jan 2025 02:36:40 -0700 Subject: [PATCH 15/20] added rumble settings to DualSense tab, set left rumble from curb vibration telemetry, and right rumble from abs --- .../DualSense/DualSenseConfiguration.cs | 28 +++++- .../Driving/DualSense/DualSenseJob.cs | 8 +- .../Driving/DualSense/TriggerHaptics.cs | 98 +++---------------- 3 files changed, 39 insertions(+), 95 deletions(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs index b4b5a2bc0..d4b0c6a6f 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs @@ -12,6 +12,24 @@ public DualSenseConfiguration() GenericConfiguration.AllowRescale = false; } + [ConfigGrouping("Rumble", "Adjust the rumble effects.")] + public RumbleParams Rumble { get; init; } = new(); + public sealed class RumbleParams + { + /// + /// Kerb vibration coef + /// + [ToolTip("Kerb vibration coef.")] + [FloatRange(0.0f, 2.0f, 0.01f, 2)] + public float KerbCoef { get; init; } = 1.2f; + + /// + /// ABS vibration coef + /// + [ToolTip("ABS vibration coef.")] + [FloatRange(0.0f, 2.0f, 0.01f, 2)] + public float ABSCoef { get; init; } = 1f; + } [ConfigGrouping("Brake Slip", "Adjust the slip effect whilst applying the brakes.")] public BrakeSlipHaptics BrakeSlip { get; init; } = new(); @@ -25,14 +43,14 @@ public sealed class BrakeSlipHaptics public float BrakeThreshold { get; init; } = 3f; [FloatRange(0.0f, 1.0f, 0.002f, 3)] - public float MinSlipRatio { get; init; } = 0.5f; + public float MinSlipRatio { get; init; } = 0.240f; [FloatRange(1.0f, 10.0f, 0.002f, 3)] - public float MaxSlipRatio { get; init; } = 2.5f; + public float MaxSlipRatio { get; init; } = 2.0f; [ToolTip("Sets the frequency of the trigger vibration effect at the MinSlipRatio value.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] - public float FreqAtMinSlipRatio { get; init; } = 255.0f; + public float FreqAtMinSlipRatio { get; init; } = 150.0f; [ToolTip("Sets the frequency of the trigger vibration effect at the MaxSlipRatio value.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] @@ -40,7 +58,7 @@ public sealed class BrakeSlipHaptics [ToolTip("Gain for the effect amplitude as SlipRatio increases.")] [FloatRange(1.0f, 10.0f, 0.1f, 1)] - public float AmpGain { get; init; } = 2.5f; + public float AmpGain { get; init; } = 2.8f; } [ConfigGrouping("Throttle Slip", "Adjust the slip effect whilst applying the throttle.\nModify the threshold to increase or decrease sensitivity in different situations.")] @@ -62,7 +80,7 @@ public sealed class ThrottleSlipHaptics [ToolTip("Sets the frequency of the trigger vibration effect at the MinSlipRatio value.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] - public float FreqAtMinSlipRatio { get; init; } = 255.0f; + public float FreqAtMinSlipRatio { get; init; } = 165.0f; [ToolTip("Sets the frequency of the trigger vibration effect at the MaxSlipRatio value.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs index fb9cd7f88..6f53d6628 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs @@ -1,5 +1,7 @@ using RaceElement.Core.Jobs.Loop; +using RaceElement.Data.Common; using static RaceElement.HUD.Common.Overlays.Driving.DualSense.DS5W; +using static RaceElement.HUD.Common.Overlays.Driving.DualSense.Util; namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; @@ -9,13 +11,13 @@ public sealed override void RunAction() { //if (!overlay.ShouldRender()) // return; - + ds5w_batch_begin(); TriggerHaptics.HandleAcceleration(overlay._config.ThrottleSlip); TriggerHaptics.HandleBraking(overlay._config.BrakeSlip); + TriggerHaptics.HandleRumble(overlay._config.Rumble); + ds5w_batch_end(); } public override void AfterCancel() { - ds5w_set_trigger_effect_off(0); - ds5w_set_trigger_effect_off(1); } } diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs index 8a69ffd1b..6346dc7fc 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs @@ -9,6 +9,17 @@ namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; internal static class TriggerHaptics { + public static void HandleRumble(RumbleParams config) + { + float kerb = Math.Max(0.0f, SimDataProvider.LocalCar.Physics.KerbVibration) * config.KerbCoef; + float abs = Math.Abs(SimDataProvider.LocalCar.Physics.AbsVibrations) * config.ABSCoef; + int lRumble = (int)Math.Round(Clip(kerb * 255.0f, 0.0f, 255.0f)); + int rRumble = (int)Math.Round(Clip(abs * 255.0f, 0.0f, 255.0f)); + //DebugOut("kerb: " + SimDataProvider.LocalCar.Physics.KerbVibration + ", lRumble: " + lRumble); + //DebugOut("abs: " + SimDataProvider.LocalCar.Physics.AbsVibrations + ", rRumble: " + rRumble); + ds5w_set_rumble(1, lRumble); + ds5w_set_rumble(0, rRumble); + } public static void HandleAcceleration(ThrottleSlipHaptics config) { float[] slipRatios = SimDataProvider.LocalCar.Tyres.SlipRatio; @@ -61,91 +72,4 @@ public static void HandleBraking(BrakeSlipHaptics config) DebugOut("slipRatioBack: " + slipRatioBack + ", freq: " + freq + ", amp: " + amp); ds5w_set_trigger_effect_vibration(1, 0, amp, freq); } -#if false - public static void HandleBraking(DualSenseConfiguration config) - { - // TODO: add either an option to threshold it on brake input or based on some curve? - if (SimDataProvider.LocalCar.Inputs.Brake <= config.BrakeSlip.BrakeThreshold / 100f) - { - ds5w_set_trigger_effect_off(1); - return; - } - float[] slipRatios = SimDataProvider.LocalCar.Tyres.SlipRatio; - if (slipRatios.Length != 4) - { - ds5w_set_trigger_effect_off(1); - return; - } - - float slipRatioFront = Math.Max(slipRatios[0], slipRatios[1]); - float slipRatioRear = Math.Max(slipRatios[2], slipRatios[3]); - - // TODO: add option for front and rear ratio threshold. - if (slipRatioFront > config.BrakeSlip.FrontSlipThreshold || slipRatioRear > config.BrakeSlip.RearSlipThreshold) - { - float frontslipCoefecient = slipRatioFront * 4f; - frontslipCoefecient.ClipMax(10); - - float rearSlipCoefecient = slipRatioFront * 2f; - rearSlipCoefecient.ClipMax(7.5f); - - float magicValue = frontslipCoefecient + rearSlipCoefecient; - float percentage = magicValue * 1.0f / 17.5f; - int strength = (int)(config.BrakeSlip.FeedbackStrength * percentage); - if (strength >= 1) { - ds5w_set_trigger_effect_feedback(1, 0, strength); - //ds5w_set_trigger_effect_off(1); - } - - /*int freq = (int)(config.BrakeSlip.MaxFrequency * percentage); - freq.ClipMin(config.BrakeSlip.MinFrequency); - ds5w_set_trigger_effect_vibration(1, 0, config.BrakeSlip.Amplitude, freq);*/ - } - else - { - ds5w_set_trigger_effect_off(1); - } - } - public static void HandleAcceleration(DualSenseConfiguration config) - { - if (SimDataProvider.LocalCar.Inputs.Throttle <= config.ThrottleSlip.ThrottleThreshold / 100f) - { - ds5w_set_trigger_effect_off(0); - return; - } - float[] slipRatios = SimDataProvider.LocalCar.Tyres.SlipRatio; - if (slipRatios.Length != 4) - { - ds5w_set_trigger_effect_off(0); - return; - } - - float slipRatioFront = Math.Max(slipRatios[0], slipRatios[1]); - float slipRatioRear = Math.Max(slipRatios[2], slipRatios[3]); - - if (slipRatioFront > config.ThrottleSlip.FrontSlipThreshold || slipRatioRear > config.ThrottleSlip.RearSlipThreshold) - { - float frontslipCoefecient = slipRatioFront * 3f; - frontslipCoefecient.ClipMax(5); - float rearSlipCoefecient = slipRatioFront * 5f; - rearSlipCoefecient.ClipMax(7.5f); - - float magicValue = frontslipCoefecient + rearSlipCoefecient; - float percentage = magicValue * 1.0f / 12.5f; - /*if (percentage >= 0.05f) - { - ds5w_set_trigger_effect_feedback(0, 0, (int)(config.ThrottleSlip.FeedbackStrength * percentage)); - ds5w_set_trigger_effect_off(0); - }*/ - - int freq = (int)(config.ThrottleSlip.MaxFrequency * percentage); - freq.ClipMin(config.ThrottleSlip.MinFrequency); - ds5w_set_trigger_effect_vibration(0, 0, config.ThrottleSlip.Amplitude, freq); - } - else - { - ds5w_set_trigger_effect_off(0); - } - } -#endif } From 861bfb22cf941fba9c53005ffc1b9f8021cc53d6 Mon Sep 17 00:00:00 2001 From: kamih Date: Mon, 27 Jan 2025 13:43:30 -0700 Subject: [PATCH 16/20] hide Rumble config group for RaceRoom and AC1 --- .../Overlays/Driving/DualSense/DualSenseConfiguration.cs | 1 + .../Overlays/Driving/DualSense/DualSenseJob.cs | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs index d4b0c6a6f..5c17b4e47 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs @@ -12,6 +12,7 @@ public DualSenseConfiguration() GenericConfiguration.AllowRescale = false; } + [HideForGame(Game.RaceRoom | Game.AssettoCorsa1)] [ConfigGrouping("Rumble", "Adjust the rumble effects.")] public RumbleParams Rumble { get; init; } = new(); public sealed class RumbleParams diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs index 6f53d6628..03cf89a5f 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs @@ -1,5 +1,7 @@ using RaceElement.Core.Jobs.Loop; using RaceElement.Data.Common; +using RaceElement.Data.Games; + using static RaceElement.HUD.Common.Overlays.Driving.DualSense.DS5W; using static RaceElement.HUD.Common.Overlays.Driving.DualSense.Util; @@ -14,7 +16,9 @@ public sealed override void RunAction() ds5w_batch_begin(); TriggerHaptics.HandleAcceleration(overlay._config.ThrottleSlip); TriggerHaptics.HandleBraking(overlay._config.BrakeSlip); - TriggerHaptics.HandleRumble(overlay._config.Rumble); + if (!GameManager.CurrentGame.HasFlag(Game.RaceRoom) && + !GameManager.CurrentGame.HasFlag(Game.AssettoCorsa1)) + TriggerHaptics.HandleRumble(overlay._config.Rumble); ds5w_batch_end(); } public override void AfterCancel() From 1c1fe67a0a6611415db6ad2e7b7fd7bc10c484e2 Mon Sep 17 00:00:00 2001 From: kamih Date: Mon, 27 Jan 2025 13:44:27 -0700 Subject: [PATCH 17/20] rename: FreqAtMinSlipRatio -> LowSlipFrequency, FreqAtMaxSlipRatio -> HighSlipFrequency --- .../Driving/DualSense/DualSenseConfiguration.cs | 17 +++++++++-------- .../Driving/DualSense/TriggerHaptics.cs | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs index 5c17b4e47..aea132bdc 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs @@ -1,4 +1,5 @@ using RaceElement.HUD.Overlay.Configuration; +using RaceElement.Data.Games; namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; @@ -49,13 +50,13 @@ public sealed class BrakeSlipHaptics [FloatRange(1.0f, 10.0f, 0.002f, 3)] public float MaxSlipRatio { get; init; } = 2.0f; - [ToolTip("Sets the frequency of the trigger vibration effect at the MinSlipRatio value.")] + [ToolTip("Sets the frequency of the trigger vibration effect when slip ratio is <= MinSlipRatio.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] - public float FreqAtMinSlipRatio { get; init; } = 150.0f; + public float LowSlipFrequency { get; init; } = 150.0f; - [ToolTip("Sets the frequency of the trigger vibration effect at the MaxSlipRatio value.")] + [ToolTip("Sets the frequency of the trigger vibration effect when slip ratio is >= MaxSlipRatio.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] - public float FreqAtMaxSlipRatio { get; init; } = 20.0f; + public float HighSlipFrequency { get; init; } = 20.0f; [ToolTip("Gain for the effect amplitude as SlipRatio increases.")] [FloatRange(1.0f, 10.0f, 0.1f, 1)] @@ -79,13 +80,13 @@ public sealed class ThrottleSlipHaptics [FloatRange(1.0f, 10.0f, 0.002f, 3)] public float MaxSlipRatio { get; init; } = 2.5f; - [ToolTip("Sets the frequency of the trigger vibration effect at the MinSlipRatio value.")] + [ToolTip("Sets the frequency of the trigger vibration effect when slip ratio is <= MinSlipRatio.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] - public float FreqAtMinSlipRatio { get; init; } = 165.0f; + public float LowSlipFrequency { get; init; } = 165.0f; - [ToolTip("Sets the frequency of the trigger vibration effect at the MaxSlipRatio value.")] + [ToolTip("Sets the frequency of the trigger vibration effect when slip ratio is >= MaxSlipRatio.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] - public float FreqAtMaxSlipRatio { get; init; } = 20.0f; + public float HighSlipFrequency { get; init; } = 20.0f; [ToolTip("Gain for the effect amplitude as SlipRatio increases.")] [FloatRange(1.0f, 10.0f, 0.1f, 1)] diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs index 6346dc7fc..33f8b3053 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs @@ -38,7 +38,7 @@ public static void HandleAcceleration(ThrottleSlipHaptics config) } // Calculate frequency from slipRatio float srWeight = SmoothStep(slipRatioFront, config.MinSlipRatio, config.MaxSlipRatio); - float freqf = Lerp(srWeight, config.FreqAtMinSlipRatio, config.FreqAtMaxSlipRatio); + float freqf = Lerp(srWeight, config.LowSlipFrequency, config.HighSlipFrequency); int freq = (int)Math.Round(Clip(freqf, 0.0f, 255.0f)); // Calculate amplitude from slipRatio int amp = 1 + (int)Math.Round(Math.Sqrt(slipRatioFront - config.MinSlipRatio ) * config.AmpGain); @@ -64,7 +64,7 @@ public static void HandleBraking(BrakeSlipHaptics config) } // Calculate frequency from slipRatio float srWeight = SmoothStep(slipRatioBack, config.MinSlipRatio, config.MaxSlipRatio); - float freqf = Lerp(srWeight, config.FreqAtMinSlipRatio, config.FreqAtMaxSlipRatio); + float freqf = Lerp(srWeight, config.LowSlipFrequency, config.HighSlipFrequency); int freq = (int)Math.Round(Clip(freqf, 0.0f, 255.0f)); // Calculate amplitude from slipRatio int amp = 1 + (int)Math.Round(Math.Sqrt(slipRatioBack - config.MinSlipRatio) * config.AmpGain); From e986f44f08c29373ac24137eefeb52f217251d15 Mon Sep 17 00:00:00 2001 From: kamih Date: Tue, 28 Jan 2025 23:40:31 -0700 Subject: [PATCH 18/20] update lastPhysicsPacketId in AssettoCorsaEvoDataProvider::Update --- .../Games/AssettoCorsaEvo/AssettoCorsaEvoDataProvider.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Race Element.Data/Games/AssettoCorsaEvo/AssettoCorsaEvoDataProvider.cs b/Race Element.Data/Games/AssettoCorsaEvo/AssettoCorsaEvoDataProvider.cs index c74e23b33..1abbe8db9 100644 --- a/Race Element.Data/Games/AssettoCorsaEvo/AssettoCorsaEvoDataProvider.cs +++ b/Race Element.Data/Games/AssettoCorsaEvo/AssettoCorsaEvoDataProvider.cs @@ -22,16 +22,13 @@ internal sealed class AssettoCorsaEvoDataProvider : AbstractSimDataProvider public sealed override void Update(ref LocalCarData localCar, ref SessionData sessionData, ref GameData gameData) { var physicsPage = AcEvoSharedMemory.Instance.ReadPhysicsPageFile(); - if (lastPhysicsPacketId == physicsPage.PacketId) // no need to remap the physics page if packet is the same + // no need to remap the physics page if packet is the same + if (lastPhysicsPacketId == physicsPage.PacketId) { SimDataProvider.GameData.IsGamePaused = true; return; } - else - { SimDataProvider.GameData.IsGamePaused = false; - } - LocalCarMapper.AddPhysics(ref physicsPage, ref localCar, ref sessionData); gameData.Name = GameName; @@ -46,6 +43,7 @@ public sealed override void Update(ref LocalCarData localCar, ref SessionData se //SessionData.Instance.PlayerCarIndex = graphicsPage.PlayerCarID; //SimDataProvider.LocalCar.CarModel.CarClass = dummyCarClass; + lastPhysicsPacketId = physicsPage.PacketId; } public override List GetCarClasses() From b4b2bcf4d20660b422cf5c43c7dc15a09a068b03 Mon Sep 17 00:00:00 2001 From: kamih Date: Tue, 28 Jan 2025 23:59:32 -0700 Subject: [PATCH 19/20] added SlipRatioBias to ThrottleSlipHaptics and BrakeSlipHaptics --- .../DualSense/DualSenseConfiguration.cs | 24 ++++++++++++----- .../Driving/DualSense/TriggerHaptics.cs | 26 +++++++++++-------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs index aea132bdc..0b6ab3ec6 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs @@ -44,19 +44,25 @@ public sealed class BrakeSlipHaptics [FloatRange(0.1f, 99f, 0.1f, 1)] public float BrakeThreshold { get; init; } = 3f; + [ToolTip("Front/back slip ratio balance to feed into effect. Front[0..1]Back")] + [FloatRange(0.0f, 1.0f, 0.002f, 3)] + public float SlipRatioBias { get; init; } = 0.5f; + + [ToolTip("Minimum slip ratio at which the effect will start.")] [FloatRange(0.0f, 1.0f, 0.002f, 3)] public float MinSlipRatio { get; init; } = 0.240f; + [ToolTip("Maximum slip ratio after which frequency of effect will be clamped.")] [FloatRange(1.0f, 10.0f, 0.002f, 3)] public float MaxSlipRatio { get; init; } = 2.0f; [ToolTip("Sets the frequency of the trigger vibration effect when slip ratio is <= MinSlipRatio.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] - public float LowSlipFrequency { get; init; } = 150.0f; + public float MinSlipFrequency { get; init; } = 150.0f; [ToolTip("Sets the frequency of the trigger vibration effect when slip ratio is >= MaxSlipRatio.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] - public float HighSlipFrequency { get; init; } = 20.0f; + public float MaxSlipFrequency { get; init; } = 20.0f; [ToolTip("Gain for the effect amplitude as SlipRatio increases.")] [FloatRange(1.0f, 10.0f, 0.1f, 1)] @@ -74,19 +80,25 @@ public sealed class ThrottleSlipHaptics [FloatRange(0.1f, 99f, 0.1f, 1)] public float ThrottleThreshold { get; init; } = 3f; + [ToolTip("Front/back slip ratio balance to feed into effect. Front[0..1]Back")] + [FloatRange(0.0f, 1.0f, 0.002f, 3)] + public float SlipRatioBias { get; init; } = 0.5f; + + [ToolTip("Minimum slip ratio at which the effect will start.")] [FloatRange(0.0f, 1.0f, 0.002f, 3)] public float MinSlipRatio { get; init; } = 0.5f; + [ToolTip("Maximum slip ratio after which frequency of effect will be clamped.")] [FloatRange(1.0f, 10.0f, 0.002f, 3)] public float MaxSlipRatio { get; init; } = 2.5f; - [ToolTip("Sets the frequency of the trigger vibration effect when slip ratio is <= MinSlipRatio.")] + [ToolTip("Sets the frequency of the trigger vibration effect when slip ratio is <= MinSlip.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] - public float LowSlipFrequency { get; init; } = 165.0f; + public float MinSlipFrequency { get; init; } = 165.0f; - [ToolTip("Sets the frequency of the trigger vibration effect when slip ratio is >= MaxSlipRatio.")] + [ToolTip("Sets the frequency of the trigger vibration effect when slip ratio is >= MaxSlip.")] [FloatRange(10.0f, 255.0f, 0.5f, 2)] - public float HighSlipFrequency { get; init; } = 20.0f; + public float MaxSlipFrequency { get; init; } = 20.0f; [ToolTip("Gain for the effect amplitude as SlipRatio increases.")] [FloatRange(1.0f, 10.0f, 0.1f, 1)] diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs index 33f8b3053..8b913ff49 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs @@ -31,19 +31,21 @@ public static void HandleAcceleration(ThrottleSlipHaptics config) } //DebugOut("Slip Ratios: " + slipRatios[0] + ", " + slipRatios[1] + ", " + slipRatios[2] + ", " + slipRatios[3]); float slipRatioFront = 0.5f * (slipRatios[0] + slipRatios[1]); - if (slipRatioFront < config.MinSlipRatio) + float slipRatioBack = 0.5f * (slipRatios[2] + slipRatios[3]); + float slipRatio = Lerp(config.SlipRatioBias, slipRatioFront, slipRatioBack); + if (slipRatio < config.MinSlipRatio) { ds5w_set_trigger_effect_off(0); return; } // Calculate frequency from slipRatio - float srWeight = SmoothStep(slipRatioFront, config.MinSlipRatio, config.MaxSlipRatio); - float freqf = Lerp(srWeight, config.LowSlipFrequency, config.HighSlipFrequency); + float srWeight = SmoothStep(slipRatio, config.MinSlipRatio, config.MaxSlipRatio); + float freqf = Lerp(srWeight, config.MinSlipFrequency, config.MaxSlipFrequency); int freq = (int)Math.Round(Clip(freqf, 0.0f, 255.0f)); // Calculate amplitude from slipRatio - int amp = 1 + (int)Math.Round(Math.Sqrt(slipRatioFront - config.MinSlipRatio ) * config.AmpGain); + int amp = 1 + (int)Math.Round(Math.Sqrt(slipRatio - config.MinSlipRatio) * config.AmpGain); amp.ClipMax(8); - DebugOut("slipRatioFront: " + slipRatioFront + ", freq: " + freq + ", amp: " + amp); + DebugOut("slipRatio: " + slipRatio + ", freq: " + freq + ", amp: " + amp); ds5w_set_trigger_effect_vibration(0, 0, amp, freq); } public static void HandleBraking(BrakeSlipHaptics config) @@ -56,20 +58,22 @@ public static void HandleBraking(BrakeSlipHaptics config) return; } //DebugOut("Slip Ratios: " + slipRatios[0] + ", " + slipRatios[1] + ", " + slipRatios[2] + ", " + slipRatios[3]); + float slipRatioFront = 0.5f * (slipRatios[0] + slipRatios[1]); float slipRatioBack = 0.5f * (slipRatios[2] + slipRatios[3]); - if (slipRatioBack < config.MinSlipRatio) + float slipRatio = Lerp(config.SlipRatioBias, slipRatioFront, slipRatioBack); + if (slipRatio < config.MinSlipRatio) { ds5w_set_trigger_effect_off(1); return; } // Calculate frequency from slipRatio - float srWeight = SmoothStep(slipRatioBack, config.MinSlipRatio, config.MaxSlipRatio); - float freqf = Lerp(srWeight, config.LowSlipFrequency, config.HighSlipFrequency); + float srWeight = SmoothStep(slipRatio, config.MinSlipRatio, config.MaxSlipRatio); + float freqf = Lerp(srWeight, config.MinSlipFrequency, config.MaxSlipFrequency); int freq = (int)Math.Round(Clip(freqf, 0.0f, 255.0f)); - // Calculate amplitude from slipRatio - int amp = 1 + (int)Math.Round(Math.Sqrt(slipRatioBack - config.MinSlipRatio) * config.AmpGain); + // Calculate amplitude from slip + int amp = 1 + (int)Math.Round(Math.Sqrt(slipRatio - config.MinSlipRatio) * config.AmpGain); amp.ClipMax(8); - DebugOut("slipRatioBack: " + slipRatioBack + ", freq: " + freq + ", amp: " + amp); + DebugOut("slipRatio: " + slipRatio + ", freq: " + freq + ", amp: " + amp); ds5w_set_trigger_effect_vibration(1, 0, amp, freq); } } From 9d0532f4fee77a1f50625e470c0500a2f837f3ea Mon Sep 17 00:00:00 2001 From: kamih Date: Mon, 3 Feb 2025 15:47:42 -0700 Subject: [PATCH 20/20] added damage, abs, gear shift -> left rumble motor, rpm -> right rumble motor, maxAmp param for trigger effect --- .../SimulatorData/LocalCar/LocalCarData.cs | 3 + .../DataMapper/LocalCarMapper.cs | 1 + .../DualSense/DualSenseConfiguration.cs | 51 +++++++++++++-- .../Driving/DualSense/DualSenseJob.cs | 7 ++- .../Driving/DualSense/TriggerHaptics.cs | 62 ++++++++++++++----- .../SystemExtensions/FloatExtensions.cs | 4 -- 6 files changed, 101 insertions(+), 27 deletions(-) diff --git a/Race Element.Data/Common/SimulatorData/LocalCar/LocalCarData.cs b/Race Element.Data/Common/SimulatorData/LocalCar/LocalCarData.cs index bbf5a36d0..a3e7eee27 100644 --- a/Race Element.Data/Common/SimulatorData/LocalCar/LocalCarData.cs +++ b/Race Element.Data/Common/SimulatorData/LocalCar/LocalCarData.cs @@ -147,6 +147,9 @@ public sealed record PhysicsData /// Wheel suspension travel. public float[] SuspensionTravel { get; internal set; } = new float[4]; + /// Damage to each side. + public float[] Damage { get; internal set; } = new float[5]; + /// Vibrations generated from driving on curbs and off track. public float KerbVibration; diff --git a/Race Element.Data/Games/AssettoCorsaEvo/DataMapper/LocalCarMapper.cs b/Race Element.Data/Games/AssettoCorsaEvo/DataMapper/LocalCarMapper.cs index 30c24b33a..38d08e438 100644 --- a/Race Element.Data/Games/AssettoCorsaEvo/DataMapper/LocalCarMapper.cs +++ b/Race Element.Data/Games/AssettoCorsaEvo/DataMapper/LocalCarMapper.cs @@ -17,6 +17,7 @@ internal static void AddPhysics(ref SPageFilePhysics pagePhysics, ref LocalCarDa commonData.Physics.Gvibrations = pagePhysics.Gvibrations; commonData.Physics.AbsVibrations = pagePhysics.AbsVibrations; commonData.Physics.Acceleration = new(pagePhysics.AccG[0], pagePhysics.AccG[1], pagePhysics.AccG[2]); + commonData.Physics.Damage = pagePhysics.CarDamage; commonData.Engine.IsPitLimiterOn = pagePhysics.PitLimiterOn; commonData.Engine.MaxRpm = pagePhysics.CurrentMaxRpm; diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs index 0b6ab3ec6..ab03098c6 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseConfiguration.cs @@ -19,18 +19,53 @@ public DualSenseConfiguration() public sealed class RumbleParams { /// - /// Kerb vibration coef + /// Kerb rumble coef /// - [ToolTip("Kerb vibration coef.")] + [ToolTip("Kerb rumble coef.")] [FloatRange(0.0f, 2.0f, 0.01f, 2)] public float KerbCoef { get; init; } = 1.2f; /// - /// ABS vibration coef + /// ABS rumble coef /// - [ToolTip("ABS vibration coef.")] + [ToolTip("ABS rumble coef.")] [FloatRange(0.0f, 2.0f, 0.01f, 2)] public float ABSCoef { get; init; } = 1f; + + /// + /// Damage rumble coef + /// + [ToolTip("Damage rumble coef.")] + [FloatRange(0.0f, 100.0f, 0.01f, 2)] + public float DamageCoef { get; init; } = 60f; + + /// + /// Gear shift rumble coef + /// + [ToolTip("Gear shift rumble coef.")] + [FloatRange(0.0f, 100.0f, 0.01f, 2)] + public float GearCoef { get; init; } = 32f; + + /// + /// How slowly rumble accum decays (low = fast) + /// + [ToolTip("How fast rumble accum decays. (low = fast)")] + [FloatRange(0.5f, 0.9f, 0.01f, 2)] + public float AccumDecay { get; init; } = 0.7f; + + /// + /// RPM % at which rumble will start + /// + [ToolTip("RPM % at which right rumble will start.")] + [FloatRange(0.0f, 1.0f, 0.01f, 2)] + public float RPMStart { get; init; } = 0.9f; + + /// + /// RPM right rumble coef + /// + [ToolTip("RPM right rumble coef.")] + [FloatRange(0.0f, 1.0f, 0.01f, 2)] + public float RPMCoef { get; init; } = 0.5f; } [ConfigGrouping("Brake Slip", "Adjust the slip effect whilst applying the brakes.")] @@ -67,6 +102,10 @@ public sealed class BrakeSlipHaptics [ToolTip("Gain for the effect amplitude as SlipRatio increases.")] [FloatRange(1.0f, 10.0f, 0.1f, 1)] public float AmpGain { get; init; } = 2.8f; + + [ToolTip("Maximum effect amplitude.")] + [IntRange(1, 8, 1)] + public int MaxAmp { get; init; } = 3; } [ConfigGrouping("Throttle Slip", "Adjust the slip effect whilst applying the throttle.\nModify the threshold to increase or decrease sensitivity in different situations.")] @@ -103,6 +142,10 @@ public sealed class ThrottleSlipHaptics [ToolTip("Gain for the effect amplitude as SlipRatio increases.")] [FloatRange(1.0f, 10.0f, 0.1f, 1)] public float AmpGain { get; init; } = 2.5f; + + [ToolTip("Maximum effect amplitude.")] + [IntRange(1, 8, 1)] + public int MaxAmp { get; init; } = 3; } } diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs index 03cf89a5f..0a129a52a 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/DualSenseJob.cs @@ -9,16 +9,17 @@ namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; internal sealed class DualSenseJob(DualSenseOverlay overlay) : AbstractLoopJob { + private TriggerHaptics _triggerHaptics = new(); public sealed override void RunAction() { //if (!overlay.ShouldRender()) // return; ds5w_batch_begin(); - TriggerHaptics.HandleAcceleration(overlay._config.ThrottleSlip); - TriggerHaptics.HandleBraking(overlay._config.BrakeSlip); + _triggerHaptics.HandleAcceleration(overlay._config.ThrottleSlip); + _triggerHaptics.HandleBraking(overlay._config.BrakeSlip); if (!GameManager.CurrentGame.HasFlag(Game.RaceRoom) && !GameManager.CurrentGame.HasFlag(Game.AssettoCorsa1)) - TriggerHaptics.HandleRumble(overlay._config.Rumble); + _triggerHaptics.HandleRumble(overlay._config.Rumble); ds5w_batch_end(); } public override void AfterCancel() diff --git a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs index 8b913ff49..f5643faa1 100644 --- a/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs +++ b/Race Element.HUD.Common/Overlays/Driving/DualSense/TriggerHaptics.cs @@ -7,20 +7,50 @@ namespace RaceElement.HUD.Common.Overlays.Driving.DualSense; -internal static class TriggerHaptics +internal class TriggerHaptics { - public static void HandleRumble(RumbleParams config) + private float mLeftAccum; + private int mGear; + private float[] mDamage; + + public TriggerHaptics() + { + mGear = 0; + mLeftAccum = 0.0f; + mDamage = new float[5]; + } + private float UpdateDamage(float[] damage) + { + float newDamage = 0.0f; + for (int i = 0; i < 5; ++i) + { + if (damage[i] > mDamage[i]) + { + newDamage += damage[i] - mDamage[i]; + } + mDamage[i] = damage[i]; + } + return newDamage; + } + + public void HandleRumble(RumbleParams config) { - float kerb = Math.Max(0.0f, SimDataProvider.LocalCar.Physics.KerbVibration) * config.KerbCoef; - float abs = Math.Abs(SimDataProvider.LocalCar.Physics.AbsVibrations) * config.ABSCoef; - int lRumble = (int)Math.Round(Clip(kerb * 255.0f, 0.0f, 255.0f)); - int rRumble = (int)Math.Round(Clip(abs * 255.0f, 0.0f, 255.0f)); - //DebugOut("kerb: " + SimDataProvider.LocalCar.Physics.KerbVibration + ", lRumble: " + lRumble); - //DebugOut("abs: " + SimDataProvider.LocalCar.Physics.AbsVibrations + ", rRumble: " + rRumble); + // Combine values for left (strong) motor rumble + float damage = UpdateDamage(SimDataProvider.LocalCar.Physics.Damage) * config.DamageCoef; + float gear = (SimDataProvider.LocalCar.Inputs.Gear != mGear) ? config.GearCoef : 0.0f; + mGear = SimDataProvider.LocalCar.Inputs.Gear; + mLeftAccum = (mLeftAccum * config.AccumDecay) + damage + gear; + float kerb = Math.Max(0.0f, SimDataProvider.LocalCar.Physics.KerbVibration) * config.KerbCoef * 255.0f; + float abs = Math.Abs(SimDataProvider.LocalCar.Physics.AbsVibrations) * config.ABSCoef * 255.0f; + int lRumble = Math.Clamp((int)Math.Round(kerb + abs + mLeftAccum), 0, 255); + // Combine values for right (weak) motor rumble + float rpm = (float)SimDataProvider.LocalCar.Engine.Rpm / (float)SimDataProvider.LocalCar.Engine.MaxRpm; + int rRumble = rpm > config.RPMStart ? (int)Math.Round(config.RPMCoef * 255.0f): 0; + DebugOut("lRumble: " + lRumble + ", rRumble: " + rRumble); ds5w_set_rumble(1, lRumble); ds5w_set_rumble(0, rRumble); } - public static void HandleAcceleration(ThrottleSlipHaptics config) + public void HandleAcceleration(ThrottleSlipHaptics config) { float[] slipRatios = SimDataProvider.LocalCar.Tyres.SlipRatio; if (SimDataProvider.LocalCar.Inputs.Throttle <= config.ThrottleThreshold / 100f || @@ -41,14 +71,14 @@ public static void HandleAcceleration(ThrottleSlipHaptics config) // Calculate frequency from slipRatio float srWeight = SmoothStep(slipRatio, config.MinSlipRatio, config.MaxSlipRatio); float freqf = Lerp(srWeight, config.MinSlipFrequency, config.MaxSlipFrequency); - int freq = (int)Math.Round(Clip(freqf, 0.0f, 255.0f)); + int freq = Math.Clamp((int)Math.Round(freqf), 0, 255); // Calculate amplitude from slipRatio int amp = 1 + (int)Math.Round(Math.Sqrt(slipRatio - config.MinSlipRatio) * config.AmpGain); - amp.ClipMax(8); - DebugOut("slipRatio: " + slipRatio + ", freq: " + freq + ", amp: " + amp); + amp.ClipMax(config.MaxAmp); + //DebugOut("slipRatio: " + slipRatio + ", freq: " + freq + ", amp: " + amp); ds5w_set_trigger_effect_vibration(0, 0, amp, freq); } - public static void HandleBraking(BrakeSlipHaptics config) + public void HandleBraking(BrakeSlipHaptics config) { float[] slipRatios = SimDataProvider.LocalCar.Tyres.SlipRatio; if (SimDataProvider.LocalCar.Inputs.Brake <= config.BrakeThreshold / 100f || @@ -69,11 +99,11 @@ public static void HandleBraking(BrakeSlipHaptics config) // Calculate frequency from slipRatio float srWeight = SmoothStep(slipRatio, config.MinSlipRatio, config.MaxSlipRatio); float freqf = Lerp(srWeight, config.MinSlipFrequency, config.MaxSlipFrequency); - int freq = (int)Math.Round(Clip(freqf, 0.0f, 255.0f)); + int freq = Math.Clamp((int)Math.Round(freqf), 0, 255); // Calculate amplitude from slip int amp = 1 + (int)Math.Round(Math.Sqrt(slipRatio - config.MinSlipRatio) * config.AmpGain); - amp.ClipMax(8); - DebugOut("slipRatio: " + slipRatio + ", freq: " + freq + ", amp: " + amp); + amp.ClipMax(config.MaxAmp); + //DebugOut("slipRatio: " + slipRatio + ", freq: " + freq + ", amp: " + amp); ds5w_set_trigger_effect_vibration(1, 0, amp, freq); } } diff --git a/Race_Element.Util/SystemExtensions/FloatExtensions.cs b/Race_Element.Util/SystemExtensions/FloatExtensions.cs index 068689fe6..301bb6053 100644 --- a/Race_Element.Util/SystemExtensions/FloatExtensions.cs +++ b/Race_Element.Util/SystemExtensions/FloatExtensions.cs @@ -18,10 +18,6 @@ public static float Clip(ref this float value, float min, float max) if (value > max) value = max; return value; } - public static float Clip(float value, float min, float max) - { - return Math.Min(max, Math.Max(min, value)); - } /// /// Sets this value or returns it, clipped by max (inclusive)