new powertrain смерть чуркам

This commit is contained in:
Valera
2025-06-13 21:16:20 +07:00
parent ba9afba4d1
commit 964b46e1c5
15 changed files with 868 additions and 416 deletions

View File

@@ -4,7 +4,7 @@ namespace VeloX;
[GameResource( "Wheel Friction", "whfric", "Wheel Friction", Category = "VeloX", Icon = "radio_button_checked" )]
public class WheelFriction : GameResource
public class TirePreset : GameResource
{
public FrictionPreset Longitudinal { get; set; }
public FrictionPreset Lateral { get; set; }

View File

@@ -1,11 +1,6 @@
using Sandbox;
using Sandbox.UI;
using System;
using System.Buffers.Text;
using System.Numerics;
using System.Runtime.Intrinsics.Arm;
using System.Text.RegularExpressions;
using System.Threading;
namespace VeloX;
@@ -23,13 +18,10 @@ public partial class VeloXWheel : Component
public FrictionPreset LateralFrictionPreset => WheelFriction.Lateral;
public FrictionPreset AligningFrictionPreset => WheelFriction.Aligning;
[Property] public WheelFriction WheelFriction { get; set; }
[Property] public TirePreset WheelFriction { get; set; }
[Property] public float Width { get; set; } = 6;
[Sync] public float SideSlip { get; private set; }
[Sync] public float ForwardSlip { get; private set; }
[Sync, Range( 0, 1 )] public float BrakePower { get; set; }
[Sync] public float Torque { get; set; }
[Sync, Range( 0, 1 )] public float Brake { get; set; }
[Property] float BrakePowerMax { get; set; } = 3000;
@@ -43,9 +35,13 @@ public partial class VeloXWheel : Component
[Property, Group( "Suspension" )] float SpringStrength { get; set; } = 800;
[Property, Group( "Suspension" )] float SpringDamper { get; set; } = 3000;
[Property] public bool AutoPhysics { get; set; } = true;
public float Spin { get; private set; }
public float RPM { get => angularVelocity * 60f / MathF.Tau; set => angularVelocity = value / (60 / MathF.Tau); }
public float AngularVelocity => angularVelocity;
internal float DistributionFactor { get; set; }
private Vector3 StartPos { get; set; }
@@ -69,9 +65,11 @@ public partial class VeloXWheel : Component
private Friction forwardFriction;
private Friction sideFriction;
private Vector3 force;
public float CounterTorque { get; private set; }
private float BaseInertia => 0.5f * Mass * MathF.Pow( Radius.InchToMeter(), 2 );
private float Inertia => BaseInertia;
public float Inertia => BaseInertia;
protected override void OnAwake()
{
@@ -118,7 +116,7 @@ public partial class VeloXWheel : Component
}
private (float, float, float, float) StepLongitudinal( float Vx, float Lc, float kFx, float kSx, float dt )
private (float, float, float, float) StepLongitudinal( float Vx, float Lc, float kFx, float kSx)
{
float Tm = Torque;
float Tb = Brake * BrakePowerMax + RollingResistance;
@@ -138,35 +136,35 @@ public partial class VeloXWheel : Component
Sx = Math.Clamp( Sx * kSx, -1, 1 );
W += Tm / I * dt;
W += Tm / I * Time.Delta;
Tb *= W > 0 ? -1 : 1;
float TbCap = MathF.Abs( W ) * I / dt;
float TbCap = MathF.Abs( W ) * I / Time.Delta;
float Tbr = MathF.Abs( Tb ) - MathF.Abs( TbCap );
Tbr = MathF.Max( Tbr, 0 );
Tb = Math.Clamp( Tb, -TbCap, TbCap );
W += Tb / I * dt;
W += Tb / I * Time.Delta;
float maxTorque = LongitudinalFrictionPreset.Evaluate( Sx ) * Lc * kFx;
float errorTorque = (W - Vx / R) * I / dt;
float errorTorque = (W - Vx / R) * I / Time.Delta;
float surfaceTorque = MathX.Clamp( errorTorque, -maxTorque, maxTorque );
W -= surfaceTorque / I * dt;
W -= surfaceTorque / I * Time.Delta;
float Fx = surfaceTorque / R;
Tbr *= W > 0 ? -1 : 1;
float TbCap2 = MathF.Abs( W ) * I / dt;
float TbCap2 = MathF.Abs( W ) * I / Time.Delta;
float Tb2 = Math.Clamp( Tbr, -TbCap2, TbCap2 );
W += Tb2 / I * dt;
W += Tb2 / I * Time.Delta;
float deltaOmegaTorque = (W - Winit) * I / dt;
float deltaOmegaTorque = (W - Winit) * I / Time.Delta;
float Tcnt = -surfaceTorque + Tb + Tb2 - deltaOmegaTorque;
if ( Lc < 0.001f )
@@ -175,7 +173,7 @@ public partial class VeloXWheel : Component
return (W, Sx, Fx, Tcnt);
}
private (float, float) StepLateral( float Vx, float Vy, float Lc, float kFy, float kSy, float dt )
private (float, float) StepLateral( float Vx, float Vy, float Lc, float kFy, float kSy)
{
float VxAbs = MathF.Abs( Vx );
float Sy;
@@ -183,7 +181,7 @@ public partial class VeloXWheel : Component
if ( VxAbs > 0.1f )
Sy = MathF.Atan( Vy / VxAbs ).RadianToDegree() * 0.01111f;
else
Sy = Vy * (0.003f / dt);
Sy = Vy * (0.003f / Time.Delta);
Sy *= kSy * 0.95f;
@@ -224,7 +222,7 @@ public partial class VeloXWheel : Component
private static float GetLongitudinalLoadCoefficient( float load ) => 11000 * (1 - MathF.Exp( -0.00014f * load ));
private static float GetLateralLoadCoefficient( float load ) => 18000 * (1 - MathF.Exp( -0.0001f * load ));
public void DoPhysics( VeloXBase vehicle, in float dt )
public void DoPhysics( VeloXBase vehicle )
{
var pos = vehicle.WorldTransform.PointToWorld( StartPos );
@@ -274,7 +272,7 @@ public partial class VeloXWheel : Component
var springForce = (offset * SpringStrength);
var damperForce = (lastSpringOffset - offset) * SpringDamper;
lastSpringOffset = offset;
force = (springForce - damperForce) * MathF.Max( 0, up.Dot( normal ) ) * normal / dt;
force = (springForce - damperForce) * MathF.Max( 0, up.Dot( normal ) ) * normal / Time.Delta;
// Vector3.CalculateVelocityOffset is broken (need fix)
//var velU = normal.Dot( vel ).MeterToInch();
@@ -301,13 +299,11 @@ public partial class VeloXWheel : Component
forwardSpeed = vel.Dot( forward );
sideSpeed = vel.Dot( right );
}
(float W, float Sx, float Fx, float _) = StepLongitudinal(
(float W, float Sx, float Fx, float Tcnt) = StepLongitudinal(
forwardSpeed,
longitudinalLoadCoefficient,
0.95f,
0.9f,
dt
0.9f
);
(float Sy, float Fy) = StepLateral(
@@ -315,12 +311,13 @@ public partial class VeloXWheel : Component
sideSpeed,
lateralLoadCoefficient,
0.95f,
0.9f,
dt
0.9f
);
SlipCircle( Sx, Sy, Fx, ref Fy );
angularVelocity = W;
CounterTorque = Tcnt;
forwardFriction = new Friction()
{