diff --git a/Code/Base/Powertrain/Clutch.cs b/Code/Base/Powertrain/Clutch.cs index 5da8529..497abb2 100644 --- a/Code/Base/Powertrain/Clutch.cs +++ b/Code/Base/Powertrain/Clutch.cs @@ -102,20 +102,25 @@ public partial class Clutch : PowertrainComponent // Clutch engagement calculation for automatic clutch else { + // Calculate engagement // Engage the clutch if the input spinning faster than the output, but also if vice versa. float throttleInput = Controller.SwappedThrottle; - float finalEngagementRPM = EngagementRPM + ThrottleEngagementOffsetRPM * (throttleInput * throttleInput); + float finalEngagementRPM = 500 + ThrottleEngagementOffsetRPM * (throttleInput * throttleInput); float referenceRPM = MathF.Max( InputRPM, OutputRPM ); ClutchInput = (referenceRPM - finalEngagementRPM) / EngagementRange; ClutchInput = Math.Clamp( ClutchInput, 0f, 1f ); - // Avoid disconnecting clutch at high speed if ( engine.OutputRPM > engine.IdleRPM * 1.1f && Controller.TotalSpeed > 3f ) { ClutchInput = 1f; } + + if ( Controller.SwappedBrakes > 0 ) + { + ClutchInput = 0; + } } if ( Controller.IsClutching > 0 ) { @@ -175,13 +180,14 @@ public partial class Clutch : PowertrainComponent float slipOverflowTorque = -Math.Min( outputTorqueClamp - OutputTorque, 0 ); // Apply the creep torque commonly caused by torque converter drag in automatic transmissions - ApplyCreepTorque( ref OutputTorque, CreepTorque ); + //ApplyCreepTorque( ref OutputTorque, CreepTorque ); // Send the torque downstream float returnTorque = _output.ForwardStep( OutputTorque, OutputInertia, dt ) * _clutchEngagement; + // Clamp the return torque to the slip torque of the clutch once again - returnTorque = Math.Clamp( returnTorque, -SlipTorque, SlipTorque ); + //returnTorque = Math.Clamp( returnTorque, -SlipTorque, SlipTorque ); // Torque returned to the input is a combination of torque returned by the powertrain and the torque that // was possibly never sent downstream diff --git a/Code/Base/Powertrain/Engine.cs b/Code/Base/Powertrain/Engine.cs index 9163578..d2b14b1 100644 --- a/Code/Base/Powertrain/Engine.cs +++ b/Code/Base/Powertrain/Engine.cs @@ -250,7 +250,7 @@ public class Engine : PowertrainComponent, IScenePhysicsEvents while ( startTimer <= StartDuration && StarterActive ) { startTimer += 0.1f; - await GameTask.DelaySeconds( 0.1f ); + await Task.DelaySeconds( 0.1f ); } } finally @@ -341,7 +341,7 @@ public class Engine : PowertrainComponent, IScenePhysicsEvents // Calculate/get torque returned from wheels OutputTorque = generatedTorque - reactionTorque; - float returnTorque = -ForwardStep( OutputTorque, 0, dt ); + float returnTorque = ForwardStep( OutputTorque, 0, dt ); float totalTorque = generatedTorque + returnTorque + reactionTorque; OutputAngularVelocity += totalTorque / inertiaSum * dt; @@ -367,7 +367,7 @@ public class Engine : PowertrainComponent, IScenePhysicsEvents RevLimiterActive = true; OnRevLimiter?.Invoke(); - await GameTask.DelayRealtimeSeconds( RevLimiterCutoffDuration ); + await Task.DelayRealtimeSeconds( RevLimiterCutoffDuration ); RevLimiterActive = false; } @@ -408,7 +408,7 @@ public class Engine : PowertrainComponent, IScenePhysicsEvents // Apply idle throttle correction to keep the engine running else ApplyICEIdleCorrection(); - + // Trigger rev limiter if needed if ( angularVelocity >= _revLimiterAngularVelocity && !RevLimiterActive ) RevLimiter(); diff --git a/Code/Base/Powertrain/Transmission.cs b/Code/Base/Powertrain/Transmission.cs index 9f72d25..a60888f 100644 --- a/Code/Base/Powertrain/Transmission.cs +++ b/Code/Base/Powertrain/Transmission.cs @@ -548,7 +548,7 @@ public class Transmission : PowertrainComponent { ShiftProgress = shiftTimer / ShiftDuration; shiftTimer += dt; - await GameTask.DelayRealtimeSeconds( dt ); + await Task.DelayRealtimeSeconds( dt ); } // Do the shift at the half point of shift duration @@ -566,7 +566,7 @@ public class Transmission : PowertrainComponent { ShiftProgress = shiftTimer / ShiftDuration; shiftTimer += dt; - await GameTask.DelayRealtimeSeconds( dt ); + await Task.DelayRealtimeSeconds( dt ); } @@ -583,7 +583,7 @@ public class Transmission : PowertrainComponent while ( postShiftBanTimer < PostShiftBan ) { postShiftBanTimer += dt; - await GameTask.DelayRealtimeSeconds( dt ); + await Task.DelayRealtimeSeconds( dt ); } // Post shift ban has finished diff --git a/Code/Base/Powertrain/WheelPowertrain.cs b/Code/Base/Powertrain/WheelPowertrain.cs index 7ab7325..ce17662 100644 --- a/Code/Base/Powertrain/WheelPowertrain.cs +++ b/Code/Base/Powertrain/WheelPowertrain.cs @@ -15,10 +15,8 @@ public partial class WheelPowertrain : PowertrainComponent protected override void OnStart() { _initialRollingResistance = Wheel.RollingResistanceTorque; - _initialWheelInertia = Wheel.BaseInertia; } private float _initialRollingResistance; - private float _initialWheelInertia; public override float QueryAngularVelocity( float angularVelocity, float dt ) { @@ -48,7 +46,7 @@ public partial class WheelPowertrain : PowertrainComponent OutputTorque = InputTorque; OutputInertia = Wheel.BaseInertia + inertiaSum; - Wheel.Torque = OutputTorque; + Wheel.DriveTorque = OutputTorque; Wheel.Inertia = OutputInertia; Wheel.AutoSimulate = false; @@ -56,4 +54,14 @@ public partial class WheelPowertrain : PowertrainComponent return Math.Abs( Wheel.CounterTorque ); } + + protected override void DrawGizmos() + { + + if ( !Gizmo.IsSelected ) + return; + Gizmo.Transform = Wheel.WorldTransform; + Wheel?.GizmoDraw(); + + } } diff --git a/Code/Base/VeloXBase.Input.cs b/Code/Base/VeloXBase.Input.cs index ac2507e..602f507 100644 --- a/Code/Base/VeloXBase.Input.cs +++ b/Code/Base/VeloXBase.Input.cs @@ -4,8 +4,8 @@ namespace VeloX; public abstract partial class VeloXBase { - [Property, Feature( "Input" )] internal InputResolver Input { get; set; } = new(); - [Property, Feature( "Input" )] public Connection Driver { get => Input.Driver; set => Input.Driver = value; } + [Feature( "Input" )] internal InputResolver Input { get; set; } = new(); + [Feature( "Input" )] public Connection Driver { get => Input.Driver; set => Input.Driver = value; } private bool IsDriverActive => Driver is not null; diff --git a/Code/Base/VeloXBase.Phys.cs b/Code/Base/VeloXBase.Phys.cs index d3b44bb..2f85862 100644 --- a/Code/Base/VeloXBase.Phys.cs +++ b/Code/Base/VeloXBase.Phys.cs @@ -7,7 +7,8 @@ public abstract partial class VeloXBase private Vector3 linForce; private Vector3 angForce; - + [Property] float BrakeForce { get; set; } = 1500f; + [Property] float HandbrakeForce { get; set; } = 3500f; private void PhysicsSimulate() { if ( Body.Sleeping && Input.AnalogMove.x == 0 ) @@ -35,9 +36,9 @@ public abstract partial class VeloXBase CombinedLoad += v.Fz; foreach ( var v in Wheels ) { - v.Brake = SwappedBrakes; + v.BrakeTorque = SwappedBrakes * BrakeForce; if ( !v.IsFront ) - v.Brake += Handbrake; + v.BrakeTorque += Handbrake * HandbrakeForce; v.Update( this, in dt ); v.DoPhysics( in dt ); diff --git a/Code/Base/Wheel/VeloXWheel.Friction.cs b/Code/Base/Wheel/VeloXWheel.Friction.cs index 21db5e1..2dd02e3 100644 --- a/Code/Base/Wheel/VeloXWheel.Friction.cs +++ b/Code/Base/Wheel/VeloXWheel.Friction.cs @@ -34,12 +34,9 @@ public partial class VeloXWheel /// public float CounterTorque { get; private set; } - [Property, Sync] public bool AutoSetFriction { get; set; } = true; - [Property, Sync] public bool UseGroundVelocity { get; set; } = true; - [Property, Range( 0, 2 )] public float BrakeMult { get; set; } = 1f; - [Property] public Friction ForwardFriction = new(); - [Property] public Friction SidewayFriction = new(); + public Friction ForwardFriction = new(); + public Friction SidewayFriction = new(); public Vector3 FrictionForce; @@ -102,8 +99,6 @@ public partial class VeloXWheel private Vector3 correctiveForce; private void UpdateFriction( float dt ) { - - var motorTorque = DriveTorque; var brakeTorque = BrakeTorque * BrakeMult; @@ -151,7 +146,7 @@ public partial class VeloXWheel float absMotorTorque = Math.Abs( motorTorque ); float absBrakeTorque = Math.Abs( brakeTorque ); - float maxForwardForce = Tire.Evaluate( Math.Abs( ForwardFriction.Slip ) ) * Math.Min( peakForwardFrictionForce, forwardForceClamp ); + float maxForwardForce = Math.Min( peakForwardFrictionForce, forwardForceClamp ); maxForwardForce = absMotorTorque < absBrakeTorque ? maxForwardForce : peakForwardFrictionForce; ForwardFriction.Force = forwardInputForce > maxForwardForce ? maxForwardForce @@ -204,7 +199,7 @@ public partial class VeloXWheel ForwardFriction.Slip = (ForwardFriction.Speed - AngularVelocity * mRadius) / clampedAbsForwardSpeed; ForwardFriction.Slip *= slipLoadModifier; - SidewayFriction.Slip = MathF.Atan2( SidewayFriction.Speed, clampedAbsForwardSpeed ).RadianToDegree() * 0.01111f; + SidewayFriction.Slip = MathF.Atan2( SidewayFriction.Speed, clampedAbsForwardSpeed ); SidewayFriction.Slip *= slipLoadModifier; float sideSlipSign = SidewayFriction.Slip > 0 ? 1 : -1; @@ -288,7 +283,8 @@ public partial class VeloXWheel //DebugOverlay.Normal( WorldPosition, hitSidewaysDirection * 10, overlay: true ); //DebugOverlay.Normal( WorldPosition, hitForwardDirection * 10, overlay: true ); //DebugOverlay.Normal( WorldPosition, FrictionForce / 100, overlay: true ); - //DebugOverlay.Normal( ContactPosition, ContactNormal * 10, overlay: true ); + //DebugOverlay.Normal( ContactPosition, Vector3.Up * AngularVelocity, overlay: true ); + //DebugOverlay.Sphere( new( ContactPosition, 4 ), overlay: true ); //Vehicle.Body.ApplyForceAt( ContactPosition, FrictionForce ); diff --git a/Code/Base/Wheel/VeloXWheel.Gizmo.cs b/Code/Base/Wheel/VeloXWheel.Gizmo.cs index d73d8a8..da3a8f3 100644 --- a/Code/Base/Wheel/VeloXWheel.Gizmo.cs +++ b/Code/Base/Wheel/VeloXWheel.Gizmo.cs @@ -5,7 +5,9 @@ namespace VeloX; public partial class VeloXWheel : Component { - protected override void DrawGizmos() + protected override void DrawGizmos() => GizmoDraw(); + + public void GizmoDraw() { if ( !Gizmo.IsSelected ) @@ -60,15 +62,5 @@ public partial class VeloXWheel : Component } } - //// - //// Forward direction - //// - //{ - // var arrowStart = Vector3.Forward * Radius.MeterToInch(); - // var arrowEnd = arrowStart + Vector3.Forward * 8f; - - // Gizmo.Draw.Color = Color.Red; - // Gizmo.Draw.Arrow( arrowStart, arrowEnd, 4, 1 ); - //} } } diff --git a/Code/Base/Wheel/VeloXWheel.Skid.cs b/Code/Base/Wheel/VeloXWheel.Skid.cs index 2f8ca27..f5d5277 100644 --- a/Code/Base/Wheel/VeloXWheel.Skid.cs +++ b/Code/Base/Wheel/VeloXWheel.Skid.cs @@ -47,6 +47,7 @@ public partial class VeloXWheel _skidMark.AutoCalculateNormals = false; _skidMark.SplineInterpolation = 4; go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true ); + go.Flags = go.Flags.WithFlag( GameObjectFlags.NotNetworked, true ); SkidMarks.Enqueue( _skidMark ); } @@ -84,6 +85,7 @@ public partial class VeloXWheel WorldRotation = Rotation.LookAt( ContactNormal.RotateAround( Vector3.Zero, Rotation.FromRoll( 90 ) ) ) }; go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true ); + go.Flags = go.Flags.WithFlag( GameObjectFlags.NotNetworked, true ); _skidMark.Points.Add( go ); } } diff --git a/Code/Base/Wheel/VeloXWheel.Smoke.cs b/Code/Base/Wheel/VeloXWheel.Smoke.cs index 3c214b6..99de3d8 100644 --- a/Code/Base/Wheel/VeloXWheel.Smoke.cs +++ b/Code/Base/Wheel/VeloXWheel.Smoke.cs @@ -32,10 +32,9 @@ public partial class VeloXWheel var val = Math.Abs( LateralSlip ) + Math.Abs( LongitudinalSlip ); timeMul = timeMul.LerpTo( val, 0.1f ); - if ( timeMul > 2 ) - return val; - - return 0; + //if ( timeMul > 2 ) + // return val; + return val * 5; } protected override void OnUpdate() { @@ -78,7 +77,7 @@ public partial class VeloXWheel { Type = ParticleFloat.ValueType.Curve, Evaluation = ParticleFloat.EvaluationType.Life, - CurveA = new( new List() { new( 0, 10f ), new( 0.8f, 50f ), new( 1f, 160f * sizeMul ) } ), + CurveA = new( new List() { new( 0, 10f ), new( 0.8f, 50f ), new( 1f, 160f ) } ), }; effect.StartDelay = 0.025f + (1 - smokeMul) * 0.03f; @@ -98,7 +97,7 @@ public partial class VeloXWheel ConstantB = 70, }; effect.Force = true; - effect.InitialVelocity = hitForwardDirection * LongitudinalSlip * 10f; + effect.InitialVelocity = Vehicle.Body.Velocity / 3 + hitForwardDirection * LongitudinalSlip * 10f; effect.ForceDirection = 0; effect.SheetSequence = true; effect.SequenceSpeed = 0.5f; diff --git a/Code/Base/Wheel/VeloXWheel.cs b/Code/Base/Wheel/VeloXWheel.cs index 6624584..caac34b 100644 --- a/Code/Base/Wheel/VeloXWheel.cs +++ b/Code/Base/Wheel/VeloXWheel.cs @@ -24,15 +24,10 @@ public partial class VeloXWheel : Component public float BaseInertia => Mass * (Radius * Radius); // kg·m² [Property] public float Inertia { get; set; } = 1.5f; // kg·m² - public float SideSlip => SlipAngle; - public float ForwardSlip => DynamicSlipRatio; - [Sync] public float Torque { get; set; } - [Sync, Range( 0, 1 )] public float Brake { get; set; } [Property] public bool IsFront { get; protected set; } [Property] public float SteerMultiplier { get; set; } public float RPM { get => AngularVelocity * 60f / MathF.Tau; set => AngularVelocity = value / (60 / MathF.Tau); } - [Sync] internal float DistributionFactor { get; set; } private Vector3 StartPos { get; set; } private static Rotation CylinderOffset = Rotation.FromRoll( 90 ); @@ -40,25 +35,19 @@ public partial class VeloXWheel : Component [Sync] public bool IsOnGround { get; private set; } - [Property] public float DriveTorque => Torque; - [Property] public float BrakeTorque => Brake * 5000f; + [Property] public float DriveTorque { get; set; } + [Property] public float BrakeTorque { get; set; } public float Compression { get; protected set; } // meters public float LastLength { get; protected set; } // meters public float Fz { get; protected set; } // N public float AngularVelocity { get; protected set; } // rad/s - public float Fx { get; protected set; } // N - public float Fy { get; protected set; } // N public float RollAngle { get; protected set; } // degrees private VeloXBase Vehicle; [Sync] public Vector3 ContactNormal { get; protected set; } [Sync] public Vector3 ContactPosition { get; protected set; } - public float SlipRatio { get; protected set; } - public float SlipAngle { get; protected set; } - public float DynamicSlipRatio { get; protected set; } - public float DynamicSlipAngle { get; protected set; } Rotation TransformRotationSteer => Vehicle.WorldTransform.RotationToWorld( Vehicle.SteerAngle * SteerMultiplier ); protected override void OnAwake() @@ -96,15 +85,9 @@ public partial class VeloXWheel : Component internal void StepPhys( VeloXBase vehicle, in float dt ) { - var _rigidbody = vehicle.Body; const int numSamples = 3; float halfWidth = Width.MeterToInch() * 0.5f; - var ang = vehicle.WorldTransform.RotationToWorld( vehicle.SteerAngle * SteerMultiplier ); - - Vector3 right = Vector3.VectorPlaneProject( ang.Right, Vector3.Up ).Normal; - - int hitCount = 0; WheelTraceData wheelTraceData = new(); for ( int i = 0; i < numSamples; i++ ) @@ -123,7 +106,6 @@ public partial class VeloXWheel : Component IsOnGround = true; - //// Average all contacts Fz = Math.Max( wheelTraceData.Force / hitCount, 0 ); Compression = wheelTraceData.Compression / hitCount; ContactNormal = (wheelTraceData.ContactNormal / hitCount).Normal; @@ -131,32 +113,7 @@ public partial class VeloXWheel : Component //DoSuspensionSounds( vehicle, (RestLength - Compression) * 0.8f); LastLength = RestLength - Compression; - //DebugOverlay.Normal( ContactPosition, ContactNormal * Fz / 1000 ); - // Apply suspension force - //_rigidbody.ApplyForceAt( ContactPosition, ContactNormal * Fz.MeterToInch() ); - UpdateHitVariables(); - // Friction - - Vector3 forward = ContactNormal.Cross( right ).Normal; - right = Rotation.FromAxis( ContactNormal, 90f ) * forward; - - var velAtContact = _rigidbody.GetVelocityAtPoint( ContactPosition + vehicle.Body.MassCenter ) * 0.0254f; - float vx = Vector3.Dot( velAtContact, forward ); - float vy = Vector3.Dot( velAtContact, right ); - float wheelLinearVel = AngularVelocity * Radius; - - float creepVel = 0.5f; - SlipRatio = (wheelLinearVel - vx) / (MathF.Abs( vx ) + creepVel); - SlipAngle = MathX.RadianToDegree( MathF.Atan2( vy, MathF.Abs( vx ) + creepVel ) ); - - float latCoeff = 1.0f - MathF.Exp( -MathF.Max( MathF.Abs( vx ), 1f ) * dt / 0.01f ); - float longCoeff = 1.0f - MathF.Exp( -MathF.Max( MathF.Abs( vx ), 1f ) * dt / 0.01f ); - - DynamicSlipAngle += (SlipAngle - DynamicSlipAngle) * latCoeff; - DynamicSlipRatio += (SlipRatio - DynamicSlipRatio) * longCoeff; - - UpdateFriction( dt ); } else @@ -165,8 +122,6 @@ public partial class VeloXWheel : Component // Wheel is off the ground Compression = 0f; Fz = 0f; - Fx = 0f; - Fy = 0f; ContactNormal = Vector3.Up; ContactPosition = WorldPosition; } @@ -225,22 +180,20 @@ public partial class VeloXWheel : Component { if ( IsProxy ) return; - StepRotation( Vehicle, dt ); if ( AutoSimulate ) StepPhys( Vehicle, dt ); + StepRotation( Vehicle, dt ); } + const float HubCoulombNm = 20f; + const float HubViscous = 0.1f; private void StepRotation( VeloXBase vehicle, in float dt ) { float inertia = MathF.Max( 1f, Inertia ); - - float roadTorque = Fx * Radius; + float roadTorque = ForwardFriction.Speed * Radius; float externalTorque = DriveTorque - roadTorque; float rollingResistanceTorque = Fz * Radius * SurfaceResistance; - const float HubCoulombNm = 20f; - const float HubViscous = 0.1f; - float coulombTorque = BrakeTorque + rollingResistanceTorque + HubCoulombNm; float omega = AngularVelocity; @@ -251,11 +204,8 @@ public partial class VeloXWheel : Component } else { - - // viscous decay if ( HubViscous > 0f ) omega *= MathF.Exp( -(HubViscous / inertia) * dt ); - // Coulomb drag if ( coulombTorque > 0f && omega != 0f ) { float dir = MathF.Sign( omega ); @@ -266,7 +216,7 @@ public partial class VeloXWheel : Component if ( MathF.Abs( omega ) < 0.01f ) omega = 0f; } - AngularVelocity = omega; // wider sanity range + AngularVelocity = omega; RollAngle += MathX.RadianToDegree( AngularVelocity ) * dt; RollAngle = (RollAngle % 360f + 360f) % 360f; diff --git a/Code/Car/VeloXCar.Aerodinamics.cs b/Code/Car/VeloXCar.Aerodinamics.cs index 3b50183..0467dd4 100644 --- a/Code/Car/VeloXCar.Aerodinamics.cs +++ b/Code/Car/VeloXCar.Aerodinamics.cs @@ -12,7 +12,7 @@ public partial class VeloXCar [KeyProperty] public float MaxForce { get; set; } [KeyProperty] public Vector3 Position { get; set; } } - public const float RHO = 10.225f; + public const float RHO = 1.225f; [Property, Feature( "Aerodinamics" )] public Vector3 Dimensions = new( 2f, 4.5f, 1.5f ); [Property, Feature( "Aerodinamics" )] public float FrontalCd { get; set; } = 0.35f; [Property, Feature( "Aerodinamics" )] public float SideCd { get; set; } = 1.05f; @@ -52,4 +52,9 @@ public partial class VeloXCar foreach ( DownforcePoint dp in DownforcePoints ) Body.ApplyForceAt( Transform.World.PointToWorld( dp.Position ), forceCoeff.MeterToInch() * dp.MaxForce.MeterToInch() * -WorldRotation.Up ); } + + //protected override void DrawGizmos() + //{ + // Gizmo.Draw.LineBBox( new BBox( -Dimensions / 2 * 39.37f, Dimensions / 2 * 39.37f ) ); + //} }