assets and etc.
This commit is contained in:
parent
ae5cd2c8b6
commit
ab8cc70785
@ -102,20 +102,25 @@ public partial class Clutch : PowertrainComponent
|
|||||||
// Clutch engagement calculation for automatic clutch
|
// Clutch engagement calculation for automatic clutch
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
// Calculate engagement
|
// Calculate engagement
|
||||||
// Engage the clutch if the input spinning faster than the output, but also if vice versa.
|
// Engage the clutch if the input spinning faster than the output, but also if vice versa.
|
||||||
float throttleInput = Controller.SwappedThrottle;
|
float throttleInput = Controller.SwappedThrottle;
|
||||||
float finalEngagementRPM = EngagementRPM + ThrottleEngagementOffsetRPM * (throttleInput * throttleInput);
|
float finalEngagementRPM = 500 + ThrottleEngagementOffsetRPM * (throttleInput * throttleInput);
|
||||||
float referenceRPM = MathF.Max( InputRPM, OutputRPM );
|
float referenceRPM = MathF.Max( InputRPM, OutputRPM );
|
||||||
|
|
||||||
ClutchInput = (referenceRPM - finalEngagementRPM) / EngagementRange;
|
ClutchInput = (referenceRPM - finalEngagementRPM) / EngagementRange;
|
||||||
ClutchInput = Math.Clamp( ClutchInput, 0f, 1f );
|
ClutchInput = Math.Clamp( ClutchInput, 0f, 1f );
|
||||||
|
|
||||||
// Avoid disconnecting clutch at high speed
|
// Avoid disconnecting clutch at high speed
|
||||||
if ( engine.OutputRPM > engine.IdleRPM * 1.1f && Controller.TotalSpeed > 3f )
|
if ( engine.OutputRPM > engine.IdleRPM * 1.1f && Controller.TotalSpeed > 3f )
|
||||||
{
|
{
|
||||||
ClutchInput = 1f;
|
ClutchInput = 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( Controller.SwappedBrakes > 0 )
|
||||||
|
{
|
||||||
|
ClutchInput = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ( Controller.IsClutching > 0 )
|
if ( Controller.IsClutching > 0 )
|
||||||
{
|
{
|
||||||
@ -175,13 +180,14 @@ public partial class Clutch : PowertrainComponent
|
|||||||
float slipOverflowTorque = -Math.Min( outputTorqueClamp - OutputTorque, 0 );
|
float slipOverflowTorque = -Math.Min( outputTorqueClamp - OutputTorque, 0 );
|
||||||
|
|
||||||
// Apply the creep torque commonly caused by torque converter drag in automatic transmissions
|
// 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
|
// Send the torque downstream
|
||||||
float returnTorque = _output.ForwardStep( OutputTorque, OutputInertia, dt ) * _clutchEngagement;
|
float returnTorque = _output.ForwardStep( OutputTorque, OutputInertia, dt ) * _clutchEngagement;
|
||||||
|
|
||||||
|
|
||||||
// Clamp the return torque to the slip torque of the clutch once again
|
// 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
|
// Torque returned to the input is a combination of torque returned by the powertrain and the torque that
|
||||||
// was possibly never sent downstream
|
// was possibly never sent downstream
|
||||||
|
|||||||
@ -250,7 +250,7 @@ public class Engine : PowertrainComponent, IScenePhysicsEvents
|
|||||||
while ( startTimer <= StartDuration && StarterActive )
|
while ( startTimer <= StartDuration && StarterActive )
|
||||||
{
|
{
|
||||||
startTimer += 0.1f;
|
startTimer += 0.1f;
|
||||||
await GameTask.DelaySeconds( 0.1f );
|
await Task.DelaySeconds( 0.1f );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -341,7 +341,7 @@ public class Engine : PowertrainComponent, IScenePhysicsEvents
|
|||||||
// Calculate/get torque returned from wheels
|
// Calculate/get torque returned from wheels
|
||||||
|
|
||||||
OutputTorque = generatedTorque - reactionTorque;
|
OutputTorque = generatedTorque - reactionTorque;
|
||||||
float returnTorque = -ForwardStep( OutputTorque, 0, dt );
|
float returnTorque = ForwardStep( OutputTorque, 0, dt );
|
||||||
|
|
||||||
float totalTorque = generatedTorque + returnTorque + reactionTorque;
|
float totalTorque = generatedTorque + returnTorque + reactionTorque;
|
||||||
OutputAngularVelocity += totalTorque / inertiaSum * dt;
|
OutputAngularVelocity += totalTorque / inertiaSum * dt;
|
||||||
@ -367,7 +367,7 @@ public class Engine : PowertrainComponent, IScenePhysicsEvents
|
|||||||
|
|
||||||
RevLimiterActive = true;
|
RevLimiterActive = true;
|
||||||
OnRevLimiter?.Invoke();
|
OnRevLimiter?.Invoke();
|
||||||
await GameTask.DelayRealtimeSeconds( RevLimiterCutoffDuration );
|
await Task.DelayRealtimeSeconds( RevLimiterCutoffDuration );
|
||||||
RevLimiterActive = false;
|
RevLimiterActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -548,7 +548,7 @@ public class Transmission : PowertrainComponent
|
|||||||
{
|
{
|
||||||
ShiftProgress = shiftTimer / ShiftDuration;
|
ShiftProgress = shiftTimer / ShiftDuration;
|
||||||
shiftTimer += dt;
|
shiftTimer += dt;
|
||||||
await GameTask.DelayRealtimeSeconds( dt );
|
await Task.DelayRealtimeSeconds( dt );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the shift at the half point of shift duration
|
// Do the shift at the half point of shift duration
|
||||||
@ -566,7 +566,7 @@ public class Transmission : PowertrainComponent
|
|||||||
{
|
{
|
||||||
ShiftProgress = shiftTimer / ShiftDuration;
|
ShiftProgress = shiftTimer / ShiftDuration;
|
||||||
shiftTimer += dt;
|
shiftTimer += dt;
|
||||||
await GameTask.DelayRealtimeSeconds( dt );
|
await Task.DelayRealtimeSeconds( dt );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -583,7 +583,7 @@ public class Transmission : PowertrainComponent
|
|||||||
while ( postShiftBanTimer < PostShiftBan )
|
while ( postShiftBanTimer < PostShiftBan )
|
||||||
{
|
{
|
||||||
postShiftBanTimer += dt;
|
postShiftBanTimer += dt;
|
||||||
await GameTask.DelayRealtimeSeconds( dt );
|
await Task.DelayRealtimeSeconds( dt );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post shift ban has finished
|
// Post shift ban has finished
|
||||||
|
|||||||
@ -15,10 +15,8 @@ public partial class WheelPowertrain : PowertrainComponent
|
|||||||
protected override void OnStart()
|
protected override void OnStart()
|
||||||
{
|
{
|
||||||
_initialRollingResistance = Wheel.RollingResistanceTorque;
|
_initialRollingResistance = Wheel.RollingResistanceTorque;
|
||||||
_initialWheelInertia = Wheel.BaseInertia;
|
|
||||||
}
|
}
|
||||||
private float _initialRollingResistance;
|
private float _initialRollingResistance;
|
||||||
private float _initialWheelInertia;
|
|
||||||
|
|
||||||
public override float QueryAngularVelocity( float angularVelocity, float dt )
|
public override float QueryAngularVelocity( float angularVelocity, float dt )
|
||||||
{
|
{
|
||||||
@ -48,7 +46,7 @@ public partial class WheelPowertrain : PowertrainComponent
|
|||||||
OutputTorque = InputTorque;
|
OutputTorque = InputTorque;
|
||||||
OutputInertia = Wheel.BaseInertia + inertiaSum;
|
OutputInertia = Wheel.BaseInertia + inertiaSum;
|
||||||
|
|
||||||
Wheel.Torque = OutputTorque;
|
Wheel.DriveTorque = OutputTorque;
|
||||||
Wheel.Inertia = OutputInertia;
|
Wheel.Inertia = OutputInertia;
|
||||||
|
|
||||||
Wheel.AutoSimulate = false;
|
Wheel.AutoSimulate = false;
|
||||||
@ -56,4 +54,14 @@ public partial class WheelPowertrain : PowertrainComponent
|
|||||||
|
|
||||||
return Math.Abs( Wheel.CounterTorque );
|
return Math.Abs( Wheel.CounterTorque );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void DrawGizmos()
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( !Gizmo.IsSelected )
|
||||||
|
return;
|
||||||
|
Gizmo.Transform = Wheel.WorldTransform;
|
||||||
|
Wheel?.GizmoDraw();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,8 @@ namespace VeloX;
|
|||||||
|
|
||||||
public abstract partial class VeloXBase
|
public abstract partial class VeloXBase
|
||||||
{
|
{
|
||||||
[Property, Feature( "Input" )] internal InputResolver Input { get; set; } = new();
|
[Feature( "Input" )] internal InputResolver Input { get; set; } = new();
|
||||||
[Property, Feature( "Input" )] public Connection Driver { get => Input.Driver; set => Input.Driver = value; }
|
[Feature( "Input" )] public Connection Driver { get => Input.Driver; set => Input.Driver = value; }
|
||||||
|
|
||||||
|
|
||||||
private bool IsDriverActive => Driver is not null;
|
private bool IsDriverActive => Driver is not null;
|
||||||
|
|||||||
@ -7,7 +7,8 @@ public abstract partial class VeloXBase
|
|||||||
|
|
||||||
private Vector3 linForce;
|
private Vector3 linForce;
|
||||||
private Vector3 angForce;
|
private Vector3 angForce;
|
||||||
|
[Property] float BrakeForce { get; set; } = 1500f;
|
||||||
|
[Property] float HandbrakeForce { get; set; } = 3500f;
|
||||||
private void PhysicsSimulate()
|
private void PhysicsSimulate()
|
||||||
{
|
{
|
||||||
if ( Body.Sleeping && Input.AnalogMove.x == 0 )
|
if ( Body.Sleeping && Input.AnalogMove.x == 0 )
|
||||||
@ -35,9 +36,9 @@ public abstract partial class VeloXBase
|
|||||||
CombinedLoad += v.Fz;
|
CombinedLoad += v.Fz;
|
||||||
foreach ( var v in Wheels )
|
foreach ( var v in Wheels )
|
||||||
{
|
{
|
||||||
v.Brake = SwappedBrakes;
|
v.BrakeTorque = SwappedBrakes * BrakeForce;
|
||||||
if ( !v.IsFront )
|
if ( !v.IsFront )
|
||||||
v.Brake += Handbrake;
|
v.BrakeTorque += Handbrake * HandbrakeForce;
|
||||||
|
|
||||||
v.Update( this, in dt );
|
v.Update( this, in dt );
|
||||||
v.DoPhysics( in dt );
|
v.DoPhysics( in dt );
|
||||||
|
|||||||
@ -34,12 +34,9 @@ public partial class VeloXWheel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float CounterTorque { get; private set; }
|
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, Range( 0, 2 )] public float BrakeMult { get; set; } = 1f;
|
||||||
[Property] public Friction ForwardFriction = new();
|
public Friction ForwardFriction = new();
|
||||||
[Property] public Friction SidewayFriction = new();
|
public Friction SidewayFriction = new();
|
||||||
public Vector3 FrictionForce;
|
public Vector3 FrictionForce;
|
||||||
|
|
||||||
|
|
||||||
@ -102,8 +99,6 @@ public partial class VeloXWheel
|
|||||||
private Vector3 correctiveForce;
|
private Vector3 correctiveForce;
|
||||||
private void UpdateFriction( float dt )
|
private void UpdateFriction( float dt )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
var motorTorque = DriveTorque;
|
var motorTorque = DriveTorque;
|
||||||
var brakeTorque = BrakeTorque * BrakeMult;
|
var brakeTorque = BrakeTorque * BrakeMult;
|
||||||
|
|
||||||
@ -151,7 +146,7 @@ public partial class VeloXWheel
|
|||||||
float absMotorTorque = Math.Abs( motorTorque );
|
float absMotorTorque = Math.Abs( motorTorque );
|
||||||
float absBrakeTorque = Math.Abs( brakeTorque );
|
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;
|
maxForwardForce = absMotorTorque < absBrakeTorque ? maxForwardForce : peakForwardFrictionForce;
|
||||||
ForwardFriction.Force = forwardInputForce > maxForwardForce ? maxForwardForce
|
ForwardFriction.Force = forwardInputForce > maxForwardForce ? maxForwardForce
|
||||||
@ -204,7 +199,7 @@ public partial class VeloXWheel
|
|||||||
ForwardFriction.Slip = (ForwardFriction.Speed - AngularVelocity * mRadius) / clampedAbsForwardSpeed;
|
ForwardFriction.Slip = (ForwardFriction.Speed - AngularVelocity * mRadius) / clampedAbsForwardSpeed;
|
||||||
ForwardFriction.Slip *= slipLoadModifier;
|
ForwardFriction.Slip *= slipLoadModifier;
|
||||||
|
|
||||||
SidewayFriction.Slip = MathF.Atan2( SidewayFriction.Speed, clampedAbsForwardSpeed ).RadianToDegree() * 0.01111f;
|
SidewayFriction.Slip = MathF.Atan2( SidewayFriction.Speed, clampedAbsForwardSpeed );
|
||||||
SidewayFriction.Slip *= slipLoadModifier;
|
SidewayFriction.Slip *= slipLoadModifier;
|
||||||
|
|
||||||
float sideSlipSign = SidewayFriction.Slip > 0 ? 1 : -1;
|
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, hitSidewaysDirection * 10, overlay: true );
|
||||||
//DebugOverlay.Normal( WorldPosition, hitForwardDirection * 10, overlay: true );
|
//DebugOverlay.Normal( WorldPosition, hitForwardDirection * 10, overlay: true );
|
||||||
//DebugOverlay.Normal( WorldPosition, FrictionForce / 100, 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 );
|
//DebugOverlay.Sphere( new( ContactPosition, 4 ), overlay: true );
|
||||||
//Vehicle.Body.ApplyForceAt( ContactPosition, FrictionForce );
|
//Vehicle.Body.ApplyForceAt( ContactPosition, FrictionForce );
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,9 @@ namespace VeloX;
|
|||||||
|
|
||||||
public partial class VeloXWheel : Component
|
public partial class VeloXWheel : Component
|
||||||
{
|
{
|
||||||
protected override void DrawGizmos()
|
protected override void DrawGizmos() => GizmoDraw();
|
||||||
|
|
||||||
|
public void GizmoDraw()
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( !Gizmo.IsSelected )
|
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 );
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,7 @@ public partial class VeloXWheel
|
|||||||
_skidMark.AutoCalculateNormals = false;
|
_skidMark.AutoCalculateNormals = false;
|
||||||
_skidMark.SplineInterpolation = 4;
|
_skidMark.SplineInterpolation = 4;
|
||||||
go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true );
|
go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true );
|
||||||
|
go.Flags = go.Flags.WithFlag( GameObjectFlags.NotNetworked, true );
|
||||||
SkidMarks.Enqueue( _skidMark );
|
SkidMarks.Enqueue( _skidMark );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +85,7 @@ public partial class VeloXWheel
|
|||||||
WorldRotation = Rotation.LookAt( ContactNormal.RotateAround( Vector3.Zero, Rotation.FromRoll( 90 ) ) )
|
WorldRotation = Rotation.LookAt( ContactNormal.RotateAround( Vector3.Zero, Rotation.FromRoll( 90 ) ) )
|
||||||
};
|
};
|
||||||
go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true );
|
go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true );
|
||||||
|
go.Flags = go.Flags.WithFlag( GameObjectFlags.NotNetworked, true );
|
||||||
_skidMark.Points.Add( go );
|
_skidMark.Points.Add( go );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,10 +32,9 @@ public partial class VeloXWheel
|
|||||||
var val = Math.Abs( LateralSlip ) + Math.Abs( LongitudinalSlip );
|
var val = Math.Abs( LateralSlip ) + Math.Abs( LongitudinalSlip );
|
||||||
timeMul = timeMul.LerpTo( val, 0.1f );
|
timeMul = timeMul.LerpTo( val, 0.1f );
|
||||||
|
|
||||||
if ( timeMul > 2 )
|
//if ( timeMul > 2 )
|
||||||
return val;
|
// return val;
|
||||||
|
return val * 5;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
protected override void OnUpdate()
|
protected override void OnUpdate()
|
||||||
{
|
{
|
||||||
@ -78,7 +77,7 @@ public partial class VeloXWheel
|
|||||||
{
|
{
|
||||||
Type = ParticleFloat.ValueType.Curve,
|
Type = ParticleFloat.ValueType.Curve,
|
||||||
Evaluation = ParticleFloat.EvaluationType.Life,
|
Evaluation = ParticleFloat.EvaluationType.Life,
|
||||||
CurveA = new( new List<Curve.Frame>() { new( 0, 10f ), new( 0.8f, 50f ), new( 1f, 160f * sizeMul ) } ),
|
CurveA = new( new List<Curve.Frame>() { new( 0, 10f ), new( 0.8f, 50f ), new( 1f, 160f ) } ),
|
||||||
};
|
};
|
||||||
effect.StartDelay = 0.025f + (1 - smokeMul) * 0.03f;
|
effect.StartDelay = 0.025f + (1 - smokeMul) * 0.03f;
|
||||||
|
|
||||||
@ -98,7 +97,7 @@ public partial class VeloXWheel
|
|||||||
ConstantB = 70,
|
ConstantB = 70,
|
||||||
};
|
};
|
||||||
effect.Force = true;
|
effect.Force = true;
|
||||||
effect.InitialVelocity = hitForwardDirection * LongitudinalSlip * 10f;
|
effect.InitialVelocity = Vehicle.Body.Velocity / 3 + hitForwardDirection * LongitudinalSlip * 10f;
|
||||||
effect.ForceDirection = 0;
|
effect.ForceDirection = 0;
|
||||||
effect.SheetSequence = true;
|
effect.SheetSequence = true;
|
||||||
effect.SequenceSpeed = 0.5f;
|
effect.SequenceSpeed = 0.5f;
|
||||||
|
|||||||
@ -24,15 +24,10 @@ public partial class VeloXWheel : Component
|
|||||||
|
|
||||||
public float BaseInertia => Mass * (Radius * Radius); // kg·m²
|
public float BaseInertia => Mass * (Radius * Radius); // kg·m²
|
||||||
[Property] public float Inertia { get; set; } = 1.5f; // 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 bool IsFront { get; protected set; }
|
||||||
[Property] public float SteerMultiplier { get; set; }
|
[Property] public float SteerMultiplier { get; set; }
|
||||||
|
|
||||||
public float RPM { get => AngularVelocity * 60f / MathF.Tau; set => AngularVelocity = value / (60 / MathF.Tau); }
|
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 Vector3 StartPos { get; set; }
|
||||||
private static Rotation CylinderOffset = Rotation.FromRoll( 90 );
|
private static Rotation CylinderOffset = Rotation.FromRoll( 90 );
|
||||||
@ -40,25 +35,19 @@ public partial class VeloXWheel : Component
|
|||||||
[Sync] public bool IsOnGround { get; private set; }
|
[Sync] public bool IsOnGround { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
[Property] public float DriveTorque => Torque;
|
[Property] public float DriveTorque { get; set; }
|
||||||
[Property] public float BrakeTorque => Brake * 5000f;
|
[Property] public float BrakeTorque { get; set; }
|
||||||
|
|
||||||
public float Compression { get; protected set; } // meters
|
public float Compression { get; protected set; } // meters
|
||||||
public float LastLength { get; protected set; } // meters
|
public float LastLength { get; protected set; } // meters
|
||||||
public float Fz { get; protected set; } // N
|
public float Fz { get; protected set; } // N
|
||||||
public float AngularVelocity { get; protected set; } // rad/s
|
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
|
public float RollAngle { get; protected set; } // degrees
|
||||||
|
|
||||||
|
|
||||||
private VeloXBase Vehicle;
|
private VeloXBase Vehicle;
|
||||||
[Sync] public Vector3 ContactNormal { get; protected set; }
|
[Sync] public Vector3 ContactNormal { get; protected set; }
|
||||||
[Sync] public Vector3 ContactPosition { 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 );
|
Rotation TransformRotationSteer => Vehicle.WorldTransform.RotationToWorld( Vehicle.SteerAngle * SteerMultiplier );
|
||||||
|
|
||||||
protected override void OnAwake()
|
protected override void OnAwake()
|
||||||
@ -96,15 +85,9 @@ public partial class VeloXWheel : Component
|
|||||||
internal void StepPhys( VeloXBase vehicle, in float dt )
|
internal void StepPhys( VeloXBase vehicle, in float dt )
|
||||||
{
|
{
|
||||||
|
|
||||||
var _rigidbody = vehicle.Body;
|
|
||||||
const int numSamples = 3;
|
const int numSamples = 3;
|
||||||
float halfWidth = Width.MeterToInch() * 0.5f;
|
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;
|
int hitCount = 0;
|
||||||
WheelTraceData wheelTraceData = new();
|
WheelTraceData wheelTraceData = new();
|
||||||
for ( int i = 0; i < numSamples; i++ )
|
for ( int i = 0; i < numSamples; i++ )
|
||||||
@ -123,7 +106,6 @@ public partial class VeloXWheel : Component
|
|||||||
|
|
||||||
IsOnGround = true;
|
IsOnGround = true;
|
||||||
|
|
||||||
//// Average all contacts
|
|
||||||
Fz = Math.Max( wheelTraceData.Force / hitCount, 0 );
|
Fz = Math.Max( wheelTraceData.Force / hitCount, 0 );
|
||||||
Compression = wheelTraceData.Compression / hitCount;
|
Compression = wheelTraceData.Compression / hitCount;
|
||||||
ContactNormal = (wheelTraceData.ContactNormal / hitCount).Normal;
|
ContactNormal = (wheelTraceData.ContactNormal / hitCount).Normal;
|
||||||
@ -131,32 +113,7 @@ public partial class VeloXWheel : Component
|
|||||||
//DoSuspensionSounds( vehicle, (RestLength - Compression) * 0.8f);
|
//DoSuspensionSounds( vehicle, (RestLength - Compression) * 0.8f);
|
||||||
LastLength = RestLength - Compression;
|
LastLength = RestLength - Compression;
|
||||||
|
|
||||||
//DebugOverlay.Normal( ContactPosition, ContactNormal * Fz / 1000 );
|
|
||||||
// Apply suspension force
|
|
||||||
//_rigidbody.ApplyForceAt( ContactPosition, ContactNormal * Fz.MeterToInch() );
|
|
||||||
|
|
||||||
UpdateHitVariables();
|
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 );
|
UpdateFriction( dt );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -165,8 +122,6 @@ public partial class VeloXWheel : Component
|
|||||||
// Wheel is off the ground
|
// Wheel is off the ground
|
||||||
Compression = 0f;
|
Compression = 0f;
|
||||||
Fz = 0f;
|
Fz = 0f;
|
||||||
Fx = 0f;
|
|
||||||
Fy = 0f;
|
|
||||||
ContactNormal = Vector3.Up;
|
ContactNormal = Vector3.Up;
|
||||||
ContactPosition = WorldPosition;
|
ContactPosition = WorldPosition;
|
||||||
}
|
}
|
||||||
@ -225,21 +180,19 @@ public partial class VeloXWheel : Component
|
|||||||
{
|
{
|
||||||
if ( IsProxy )
|
if ( IsProxy )
|
||||||
return;
|
return;
|
||||||
StepRotation( Vehicle, dt );
|
|
||||||
if ( AutoSimulate )
|
if ( AutoSimulate )
|
||||||
StepPhys( Vehicle, dt );
|
StepPhys( Vehicle, dt );
|
||||||
|
StepRotation( Vehicle, dt );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StepRotation( VeloXBase vehicle, in float dt )
|
|
||||||
{
|
|
||||||
float inertia = MathF.Max( 1f, Inertia );
|
|
||||||
|
|
||||||
float roadTorque = Fx * Radius;
|
|
||||||
float externalTorque = DriveTorque - roadTorque;
|
|
||||||
float rollingResistanceTorque = Fz * Radius * SurfaceResistance;
|
|
||||||
|
|
||||||
const float HubCoulombNm = 20f;
|
const float HubCoulombNm = 20f;
|
||||||
const float HubViscous = 0.1f;
|
const float HubViscous = 0.1f;
|
||||||
|
private void StepRotation( VeloXBase vehicle, in float dt )
|
||||||
|
{
|
||||||
|
float inertia = MathF.Max( 1f, Inertia );
|
||||||
|
float roadTorque = ForwardFriction.Speed * Radius;
|
||||||
|
float externalTorque = DriveTorque - roadTorque;
|
||||||
|
float rollingResistanceTorque = Fz * Radius * SurfaceResistance;
|
||||||
|
|
||||||
float coulombTorque = BrakeTorque + rollingResistanceTorque + HubCoulombNm;
|
float coulombTorque = BrakeTorque + rollingResistanceTorque + HubCoulombNm;
|
||||||
|
|
||||||
@ -251,11 +204,8 @@ public partial class VeloXWheel : Component
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
// viscous decay
|
|
||||||
if ( HubViscous > 0f ) omega *= MathF.Exp( -(HubViscous / inertia) * dt );
|
if ( HubViscous > 0f ) omega *= MathF.Exp( -(HubViscous / inertia) * dt );
|
||||||
|
|
||||||
// Coulomb drag
|
|
||||||
if ( coulombTorque > 0f && omega != 0f )
|
if ( coulombTorque > 0f && omega != 0f )
|
||||||
{
|
{
|
||||||
float dir = MathF.Sign( omega );
|
float dir = MathF.Sign( omega );
|
||||||
@ -266,7 +216,7 @@ public partial class VeloXWheel : Component
|
|||||||
|
|
||||||
if ( MathF.Abs( omega ) < 0.01f ) omega = 0f;
|
if ( MathF.Abs( omega ) < 0.01f ) omega = 0f;
|
||||||
}
|
}
|
||||||
AngularVelocity = omega; // wider sanity range
|
AngularVelocity = omega;
|
||||||
|
|
||||||
RollAngle += MathX.RadianToDegree( AngularVelocity ) * dt;
|
RollAngle += MathX.RadianToDegree( AngularVelocity ) * dt;
|
||||||
RollAngle = (RollAngle % 360f + 360f) % 360f;
|
RollAngle = (RollAngle % 360f + 360f) % 360f;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ public partial class VeloXCar
|
|||||||
[KeyProperty] public float MaxForce { get; set; }
|
[KeyProperty] public float MaxForce { get; set; }
|
||||||
[KeyProperty] public Vector3 Position { 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 Vector3 Dimensions = new( 2f, 4.5f, 1.5f );
|
||||||
[Property, Feature( "Aerodinamics" )] public float FrontalCd { get; set; } = 0.35f;
|
[Property, Feature( "Aerodinamics" )] public float FrontalCd { get; set; } = 0.35f;
|
||||||
[Property, Feature( "Aerodinamics" )] public float SideCd { get; set; } = 1.05f;
|
[Property, Feature( "Aerodinamics" )] public float SideCd { get; set; } = 1.05f;
|
||||||
@ -52,4 +52,9 @@ public partial class VeloXCar
|
|||||||
foreach ( DownforcePoint dp in DownforcePoints )
|
foreach ( DownforcePoint dp in DownforcePoints )
|
||||||
Body.ApplyForceAt( Transform.World.PointToWorld( dp.Position ), forceCoeff.MeterToInch() * dp.MaxForce.MeterToInch() * -WorldRotation.Up );
|
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 ) );
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user