уже лучше
This commit is contained in:
parent
4912d0ae1a
commit
f0f89ff947
@ -1,5 +1,56 @@
|
||||
{
|
||||
"Pacejka": {},
|
||||
"Pacejka": {
|
||||
"Lateral": {
|
||||
"a0": 1.4,
|
||||
"a1": -0,
|
||||
"a2": 1688,
|
||||
"a3": 2400,
|
||||
"a4": 6.026,
|
||||
"a5": 0,
|
||||
"a6": -0.359,
|
||||
"a7": 1,
|
||||
"a8": 0,
|
||||
"a9": 0,
|
||||
"a10": 0,
|
||||
"a111": 0,
|
||||
"a112": 0,
|
||||
"a12": 0,
|
||||
"a13": 0
|
||||
},
|
||||
"Longitudinal": {
|
||||
"b0": 1.65,
|
||||
"b1": 0,
|
||||
"b2": 1690,
|
||||
"b3": 0,
|
||||
"b4": 229,
|
||||
"b5": 0,
|
||||
"b6": 0,
|
||||
"b7": 0,
|
||||
"b8": -10,
|
||||
"b9": 0,
|
||||
"b10": 0
|
||||
},
|
||||
"Aligning": {
|
||||
"c0": 2,
|
||||
"c1": -3.8,
|
||||
"c2": -3.14,
|
||||
"c3": -1.16,
|
||||
"c4": -7.2,
|
||||
"c5": 0,
|
||||
"c6": 0,
|
||||
"c7": 0.044,
|
||||
"c8": -0.58,
|
||||
"c9": 0.18,
|
||||
"c10": 0,
|
||||
"c11": 0,
|
||||
"c12": 0,
|
||||
"c13": 0,
|
||||
"c14": 0.14,
|
||||
"c15": -1.029,
|
||||
"c16": 0,
|
||||
"c17": 0
|
||||
}
|
||||
},
|
||||
"RollResistanceLin": 0.001,
|
||||
"RollResistanceQuad": 1E-06,
|
||||
"__references": [],
|
||||
|
||||
@ -87,7 +87,7 @@ public class Engine : PowertrainComponent
|
||||
angularVelocity += finalTorque / inertiaSum * Time.Delta;
|
||||
angularVelocity = Math.Max( angularVelocity, 0 );
|
||||
|
||||
//UpdateStream();
|
||||
UpdateStream();
|
||||
|
||||
return finalTorque;
|
||||
}
|
||||
|
||||
@ -7,7 +7,11 @@ public class PowerWheel : PowertrainComponent
|
||||
{
|
||||
[Property] public VeloXWheel Wheel { get; set; }
|
||||
|
||||
public override float QueryInertia() => Wheel.Inertia;
|
||||
public override float QueryInertia()
|
||||
{
|
||||
float dtScale = Math.Clamp( Time.Delta, 0.01f, 0.05f ) / 0.005f;
|
||||
return Wheel.BaseInertia * dtScale;
|
||||
}
|
||||
|
||||
public override float QueryAngularVelocity( float angularVelocity )
|
||||
{
|
||||
@ -19,7 +23,8 @@ public class PowerWheel : PowertrainComponent
|
||||
Wheel.AutoPhysics = false;
|
||||
Wheel.Torque = torque;
|
||||
Wheel.Brake = Vehicle.Brake;
|
||||
|
||||
Inertia = Wheel.BaseInertia + inertia;
|
||||
Wheel.Inertia = inertia;
|
||||
Wheel.DoPhysics( Vehicle );
|
||||
|
||||
angularVelocity = Wheel.AngularVelocity;
|
||||
|
||||
@ -167,7 +167,7 @@ public class Pacejka
|
||||
|
||||
|
||||
/// pacejka magic formula for longitudinal force
|
||||
public float PacejkaFx( float sigma, float Fz, float friction_coeff )
|
||||
public float PacejkaFx( float sigma, float Fz, float friction_coeff, out float maxforce_output )
|
||||
{
|
||||
var b = Longitudinal;
|
||||
|
||||
@ -198,6 +198,7 @@ public class Pacejka
|
||||
|
||||
// scale by surface friction
|
||||
Fx *= friction_coeff;
|
||||
maxforce_output = D;
|
||||
|
||||
return Fx;
|
||||
}
|
||||
|
||||
@ -24,12 +24,24 @@ public class TirePreset : GameResource
|
||||
return resistance;
|
||||
}
|
||||
|
||||
public void ComputeSlip( float vlon, float vlat, float vrot, out float slip_ratio, out float slip_angle )
|
||||
public static void ComputeSlip( float lon_velocity, float lat_velocity, float rot_velocity, float wheel_radius, out float slip_ratio, out float slip_angle )
|
||||
{
|
||||
float rvlon = 1 / MathF.Max( MathF.Abs( vlon ), 1E-3f );
|
||||
float vslip = vrot - vlon;
|
||||
slip_ratio = vslip * rvlon;
|
||||
slip_angle = -MathF.Atan( vlat * rvlon );
|
||||
var abs_lon = Math.Max( MathF.Abs( lon_velocity ), 1e-3f );
|
||||
|
||||
slip_ratio = lon_velocity - rot_velocity * wheel_radius;
|
||||
|
||||
if ( abs_lon >= 0.005f )
|
||||
slip_ratio /= abs_lon;
|
||||
else
|
||||
slip_ratio *= abs_lon;
|
||||
|
||||
if ( abs_lon >= 0.5f )
|
||||
slip_angle = MathF.Atan2( -lat_velocity, abs_lon ).RadianToDegree() / 50f;
|
||||
else
|
||||
slip_angle = -lat_velocity * (0.01f / Time.Delta);
|
||||
|
||||
slip_ratio = Math.Clamp( slip_ratio, -1, 1 );
|
||||
slip_angle = Math.Clamp( slip_angle, -1, 1 );
|
||||
|
||||
}
|
||||
|
||||
@ -40,104 +52,6 @@ public class TirePreset : GameResource
|
||||
return ((1 / 6.0f) * (sc * sc) + 1) * sc;
|
||||
}
|
||||
|
||||
public struct TireState()
|
||||
{
|
||||
/// <summary>
|
||||
/// surface friction coefficient
|
||||
/// </summary>
|
||||
public float friction = 0;
|
||||
|
||||
/// <summary>
|
||||
/// tire camber angle relative to track surface
|
||||
/// </summary>
|
||||
public float camber = 0;
|
||||
|
||||
/// <summary>
|
||||
/// camber thrust induced lateral slip velocity
|
||||
/// </summary>
|
||||
public float vcam = 0;
|
||||
|
||||
/// <summary>
|
||||
/// ratio of tire contact patch speed to road speed
|
||||
/// </summary>
|
||||
public float slip = 0;
|
||||
|
||||
/// <summary>
|
||||
/// the angle between the wheel heading and the wheel velocity
|
||||
/// </summary>
|
||||
public float slip_angle = 0;
|
||||
|
||||
/// <summary>
|
||||
/// peak force slip ratio
|
||||
/// </summary>
|
||||
public float ideal_slip = 0;
|
||||
|
||||
/// <summary>
|
||||
/// peak force slip angle
|
||||
/// </summary>
|
||||
public float ideal_slip_angle = 0;
|
||||
|
||||
/// <summary>
|
||||
/// positive during traction
|
||||
/// </summary>
|
||||
public float fx = 0;
|
||||
|
||||
/// <summary>
|
||||
/// positive during traction in a right turn
|
||||
/// </summary>
|
||||
public float fy = 0;
|
||||
|
||||
/// <summary>
|
||||
/// positive during traction in a left turn
|
||||
/// </summary>
|
||||
public float mz = 0;
|
||||
};
|
||||
|
||||
public void ComputeState(
|
||||
float normal_force,
|
||||
float rot_velocity,
|
||||
float lon_velocity,
|
||||
float lat_velocity,
|
||||
float camber_angle,
|
||||
out TireState s
|
||||
)
|
||||
{
|
||||
s = new TireState
|
||||
{
|
||||
camber = camber_angle,
|
||||
friction = 1.0f
|
||||
};
|
||||
|
||||
if ( normal_force * s.friction < 1E-6f )
|
||||
{
|
||||
s.slip = s.slip_angle = 0;
|
||||
s.fx = s.fy = s.mz = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
float Fz = MathF.Min( normal_force * 0.001f, 30f );
|
||||
|
||||
ComputeSlip( lon_velocity, lat_velocity, rot_velocity, out float slip, out float slip_angle );
|
||||
float sigma = slip;
|
||||
float alpha = slip_angle.RadianToDegree();
|
||||
float gamma = s.camber.RadianToDegree();
|
||||
|
||||
float Fx0 = Pacejka.PacejkaFx( sigma, Fz, s.friction );
|
||||
float Fy0 = Pacejka.PacejkaFy( alpha, Fz, gamma, s.friction, out float camber_alpha );
|
||||
|
||||
// combined slip
|
||||
float Gx = Pacejka.PacejkaGx( slip, slip_angle );
|
||||
float Gy = Pacejka.PacejkaGy( slip, slip_angle );
|
||||
float Fx = Gx * Fx0;
|
||||
float Fy = Gy * Fy0;
|
||||
|
||||
s.vcam = ComputeCamberVelocity( camber_alpha.DegreeToRadian(), lon_velocity );
|
||||
s.slip = slip;
|
||||
s.slip_angle = slip_angle;
|
||||
s.fx = Fx;
|
||||
s.fy = Fy;
|
||||
}
|
||||
|
||||
public static float ComputeCamberVelocity( float sa, float vx )
|
||||
{
|
||||
float tansa = (1 / 3.0f * (sa * sa) + 1) * sa;
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
using Sandbox;
|
||||
using Sandbox.Rendering;
|
||||
using Sandbox.Services;
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Numerics;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using static Sandbox.CameraComponent;
|
||||
using static Sandbox.Package;
|
||||
using static Sandbox.SkinnedModelRenderer;
|
||||
|
||||
namespace VeloX;
|
||||
|
||||
@ -40,7 +44,7 @@ public partial class VeloXWheel : Component
|
||||
public float Spin { get; private set; }
|
||||
|
||||
public float RPM { get => angularVelocity * 30f / MathF.PI; set => angularVelocity = value / (30f / MathF.PI); }
|
||||
public float AngularVelocity => angularVelocity;
|
||||
public float AngularVelocity { get => angularVelocity; set => angularVelocity = value; }
|
||||
|
||||
internal float DistributionFactor { get; set; }
|
||||
|
||||
@ -65,8 +69,12 @@ public partial class VeloXWheel : Component
|
||||
private Vector3 force;
|
||||
public float CounterTorque { get; private set; }
|
||||
|
||||
private float BaseInertia => Mass * MathF.Pow( Radius.InchToMeter(), 2 );
|
||||
public float Inertia => BaseInertia;
|
||||
internal float BaseInertia => 0.5f * Mass * MathF.Pow( Radius.InchToMeter(), 2 );
|
||||
public float Inertia
|
||||
{
|
||||
get => BaseInertia + inertia;
|
||||
set => inertia = value;
|
||||
}
|
||||
|
||||
|
||||
protected override void OnAwake()
|
||||
@ -83,12 +91,8 @@ public partial class VeloXWheel : Component
|
||||
|
||||
private void UpdateVisuals( VeloXBase vehicle, in float dt )
|
||||
{
|
||||
var entityAngles = vehicle.WorldRotation;
|
||||
|
||||
Spin -= angularVelocity.MeterToInch() * dt;
|
||||
|
||||
Spin -= angularVelocity.RadianToDegree() * dt;
|
||||
WorldRotation = vehicle.WorldTransform.RotationToWorld( GetSteer( vehicle.SteerAngle.yaw ) ) * Rotation.FromAxis( Vector3.Right, Spin );
|
||||
|
||||
}
|
||||
|
||||
private Rotation GetSteer( float steer )
|
||||
@ -108,16 +112,14 @@ 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 ));
|
||||
float lastload;
|
||||
private float inertia;
|
||||
|
||||
public void DoPhysics( VeloXBase vehicle )
|
||||
{
|
||||
var pos = vehicle.WorldTransform.PointToWorld( StartPos );
|
||||
|
||||
var ang = vehicle.WorldTransform.RotationToWorld( GetSteer( vehicle.SteerAngle.yaw ) );
|
||||
|
||||
forward = ang.Forward;
|
||||
right = ang.Right;
|
||||
up = ang.Up;
|
||||
|
||||
var maxLen = SuspensionLength;
|
||||
|
||||
var endPos = pos + ang.Down * maxLen;
|
||||
@ -129,6 +131,12 @@ public partial class VeloXWheel : Component
|
||||
.UseHitPosition( false )
|
||||
.WithoutTags( vehicle.WheelIgnoredTags )
|
||||
.Run();
|
||||
//forward = ang.Forward;
|
||||
//right = ang.Right;
|
||||
up = ang.Up;
|
||||
|
||||
forward = Vector3.VectorPlaneProject( ang.Forward, Trace.Normal ).Normal;
|
||||
right = Vector3.VectorPlaneProject( ang.Right, Trace.Normal ).Normal;
|
||||
|
||||
var fraction = Trace.Fraction;
|
||||
|
||||
@ -141,7 +149,9 @@ public partial class VeloXWheel : Component
|
||||
|
||||
var normal = Trace.Normal;
|
||||
|
||||
var vel = vehicle.Body.GetVelocityAtPoint( pos );
|
||||
var vel = vehicle.Body.GetVelocityAtPoint( contactPos );
|
||||
|
||||
//var vel = vehicle.Body.GetVelocityAtPoint( pos );
|
||||
|
||||
if ( !IsOnGround )
|
||||
{
|
||||
@ -191,76 +201,105 @@ public partial class VeloXWheel : Component
|
||||
|
||||
float camber_rad = CamberAngle.DegreeToRadian();
|
||||
float R = Radius.InchToMeter();
|
||||
TirePreset.ComputeState(
|
||||
2500,
|
||||
angularVelocity * R,
|
||||
forwardSpeed,
|
||||
sideSpeed,
|
||||
camber_rad,
|
||||
out var tireState
|
||||
);
|
||||
|
||||
//TirePreset.ComputeState(
|
||||
// load,
|
||||
// angularVelocity,
|
||||
// forwardSpeed,
|
||||
// sideSpeed,
|
||||
// camber_rad,
|
||||
// R,
|
||||
// Inertia,
|
||||
// out var tireState
|
||||
//);
|
||||
|
||||
float linearSpeed = angularVelocity * Radius.InchToMeter();
|
||||
float F_roll = TirePreset.GetRollingResistance( linearSpeed, 1.0f );
|
||||
F_roll = -MathF.Sign( forwardSpeed ) * F_roll;
|
||||
F_roll *= -Math.Clamp( linearSpeed * 0.25f, -1, 1 );
|
||||
|
||||
float Fx_total = tireState.fx + F_roll;
|
||||
//float Fx_total = tireState.fx + F_roll;
|
||||
|
||||
float T_brake = Brake * BrakePowerMax;
|
||||
|
||||
if ( angularVelocity > 0 ) T_brake = -T_brake;
|
||||
else T_brake = angularVelocity < 0 ? T_brake : -MathF.Sign( Torque ) * T_brake;
|
||||
float totalTorque = Torque + T_brake - Fx_total * R;
|
||||
//float totalTorque = Torque + tireState.fx;
|
||||
|
||||
// not work
|
||||
Vector3 c = pos.Cross( forward );
|
||||
Vector3 v = (c * vehicle.Body.PhysicsBody.Inertia).Cross( pos );
|
||||
var m = 1 / (1 / vehicle.Body.Mass + forward.Dot( v ));
|
||||
m *= Inertia / (m * R * R + Inertia);
|
||||
float ve = forward.Dot( vel ).InchToMeter() - angularVelocity;
|
||||
angularVelocity += Torque / Inertia * Time.Delta;
|
||||
angularVelocity += T_brake / Inertia * Time.Delta;
|
||||
angularVelocity += F_roll * 9.80665f / Inertia * Time.Delta;
|
||||
TirePreset.ComputeSlip( forwardSpeed, sideSpeed, angularVelocity, R, out var slip, out var slip_ang );
|
||||
var fx = TirePreset.Pacejka.PacejkaFx( slip, load, 1, out var maxTorque );
|
||||
var fy = TirePreset.Pacejka.PacejkaFy( slip_ang * load, load, camber_rad, 1, out var _ );
|
||||
|
||||
angularVelocity += ve * m * Radius * (1 / Inertia);// totalTorque * (1 / Inertia) * Time.Delta;
|
||||
maxTorque *= R;
|
||||
var errorTorque = (angularVelocity - forwardSpeed / R) * Inertia / Time.Delta;
|
||||
|
||||
var surfaceTorque = Math.Clamp( errorTorque, -maxTorque, maxTorque );
|
||||
|
||||
angularVelocity -= surfaceTorque / Inertia * Time.Delta;
|
||||
|
||||
forwardFriction = new Friction()
|
||||
{
|
||||
Slip = tireState.slip,
|
||||
Force = Fx_total,
|
||||
Slip = slip,
|
||||
Force = -fx,
|
||||
Speed = forwardSpeed
|
||||
};
|
||||
|
||||
sideFriction = new Friction()
|
||||
{
|
||||
Slip = tireState.slip_angle,
|
||||
Force = tireState.fy,
|
||||
Slip = slip_ang,
|
||||
Force = fy,
|
||||
Speed = sideSpeed
|
||||
};
|
||||
|
||||
Vector3 frictionForce = forward * forwardFriction.Force + right * sideFriction.Force;
|
||||
vehicle.Body.ApplyForceAt( contactPos, (force + frictionForce) / Time.Delta );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Колесо в воздухе: сбрасываем силы
|
||||
forwardFriction = new Friction();
|
||||
sideFriction = new Friction();
|
||||
vehicle.Body.ApplyForceAt( pos, force / Time.Delta * ProjectSettings.Physics.SubSteps );
|
||||
vehicle.Body.ApplyForceAt( pos, frictionForce * ProjectSettings.Physics.SubSteps );
|
||||
|
||||
// Обновление угловой скорости только от мотора/тормозов
|
||||
float T_brake = Brake * BrakePowerMax;
|
||||
|
||||
if ( angularVelocity > 0 ) T_brake = -T_brake;
|
||||
else T_brake = angularVelocity < 0 ? T_brake : -MathF.Sign( Torque ) * T_brake;
|
||||
angularVelocity += (Torque + T_brake) / Inertia * Time.Delta;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//todo
|
||||
protected (float Mass, float Inertia) CalcMassAndInertia()
|
||||
{
|
||||
// section width in millimeters, measured from sidewall to sidewall
|
||||
// ratio of sidewall height to section width in percent
|
||||
// diameter of the wheel in inches
|
||||
var tire_size = new Vector3( 215, 45, 17 );
|
||||
|
||||
float tire_width = tire_size[0] * 0.001f;
|
||||
float tire_aspect_ratio = tire_size[1] * 0.01f;
|
||||
float tire_radius = tire_size[2] * 0.5f * 0.0254f + tire_width * tire_aspect_ratio;
|
||||
float tire_thickness = 0.02f;
|
||||
float tire_density = 1000; // rubber
|
||||
|
||||
float rim_radius = tire_radius - tire_width * tire_aspect_ratio;
|
||||
float rim_width = tire_width;
|
||||
float rim_thickness = 0.01f;
|
||||
float rim_density = 2700; // aluminium
|
||||
|
||||
float tire_volume = float.Pi * tire_width * tire_thickness * (2 * tire_radius - tire_thickness);
|
||||
float rim_volume = float.Pi * rim_width * rim_thickness * (2 * rim_radius - rim_thickness);
|
||||
float tire_mass = tire_density * tire_volume;
|
||||
float rim_mass = rim_density * rim_volume;
|
||||
float tire_inertia = tire_mass * tire_radius * tire_radius;
|
||||
float rim_inertia = rim_mass * rim_radius * rim_radius;
|
||||
|
||||
float mass = tire_mass + rim_mass;
|
||||
float inertia = tire_inertia + rim_inertia;
|
||||
|
||||
return (mass, inertia);
|
||||
}
|
||||
|
||||
// debug
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
DebugOverlay.Normal( contactPos, forward * forwardFriction.Force / 100f, Color.Red, overlay: true );
|
||||
DebugOverlay.Normal( contactPos, right * sideFriction.Force / 100f, Color.Green, overlay: true );
|
||||
DebugOverlay.Normal( contactPos, forward * forwardFriction.Force / 1000f, Color.Red, overlay: true );
|
||||
DebugOverlay.Normal( contactPos, right * sideFriction.Force / 1000f, Color.Green, overlay: true );
|
||||
DebugOverlay.Normal( contactPos, up * force / 1000f, Color.Blue, overlay: true );
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,33 +14,40 @@ public partial class VeloXCar
|
||||
[Property, Feature( "Steer" )] public float MaxSteerAngle { get; set; } = 35f;
|
||||
|
||||
[Sync] public float Steering { get; private set; }
|
||||
private float jTurnMultiplier;
|
||||
|
||||
private float inputSteer;
|
||||
|
||||
public static float SignedAngle( Vector3 from, Vector3 to, Vector3 axis )
|
||||
{
|
||||
float unsignedAngle = Vector3.GetAngle( from, to );
|
||||
|
||||
float cross_x = from.y * to.z - from.z * to.y;
|
||||
float cross_y = from.z * to.x - from.x * to.z;
|
||||
float cross_z = from.x * to.y - from.y * to.x;
|
||||
float sign = MathF.Sign( axis.x * cross_x + axis.y * cross_y + axis.z * cross_z );
|
||||
return unsignedAngle * sign;
|
||||
}
|
||||
public float VelocityAngle { get; private set; }
|
||||
public int CarDirection { get { return ForwardSpeed.InchToMeter() < 5 ? 0 : (VelocityAngle < 90 && VelocityAngle > -90 ? 1 : -1); } }
|
||||
private void UpdateSteering( float dt )
|
||||
{
|
||||
var inputSteer = Input.AnalogMove.y;
|
||||
var absInputSteer = Math.Abs( inputSteer );
|
||||
|
||||
var sideSlip = Math.Clamp( avgSideSlip, -1, 1 );
|
||||
|
||||
VelocityAngle = -SignedAngle( Body.Velocity, WorldRotation.Forward, WorldRotation.Up );
|
||||
|
||||
var steerConeFactor = Math.Clamp( TotalSpeed / SteerConeMaxSpeed, 0, 1 );
|
||||
var steerCone = 1 - steerConeFactor * (1 - SteerConeMaxAngle);
|
||||
|
||||
steerCone = Math.Clamp( steerCone, Math.Abs( sideSlip ), 1 );
|
||||
|
||||
inputSteer = ExpDecay( this.inputSteer, inputSteer * steerCone, SteerConeChangeRate, dt );
|
||||
this.inputSteer = inputSteer;
|
||||
var counterSteer = sideSlip * steerConeFactor * (1 - absInputSteer);
|
||||
counterSteer = Math.Clamp( counterSteer, -1, 1 ) * CounterSteer;
|
||||
|
||||
inputSteer = Math.Clamp( inputSteer + counterSteer, -1, 1 );
|
||||
float target = -inputSteer * MaxSteerAngle;
|
||||
if ( CarDirection > 0 )
|
||||
target -= VelocityAngle * CounterSteer;
|
||||
|
||||
inputSteer = Math.Clamp( inputSteer, -1, 1 );
|
||||
Steering = inputSteer;
|
||||
SteerAngle = new( 0, -inputSteer * MaxSteerAngle, 0 );
|
||||
|
||||
if ( ForwardSpeed < -100 )
|
||||
jTurnMultiplier = 0.5f;
|
||||
else
|
||||
jTurnMultiplier = ExpDecay( jTurnMultiplier, 1, 2, dt );
|
||||
SteerAngle = new( 0, target, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,27 +2,9 @@
|
||||
|
||||
public partial class VeloXCar
|
||||
{
|
||||
private float avgSideSlip;
|
||||
private float avgPoweredRPM;
|
||||
private float avgForwardSlip;
|
||||
private void WheelThink( in float dt )
|
||||
{
|
||||
float avgRPM = 0, totalSideSlip = 0, totalForwardSlip = 0;
|
||||
|
||||
foreach ( var w in Wheels )
|
||||
{
|
||||
w.Update( this, dt );
|
||||
|
||||
totalSideSlip += w.SideSlip;
|
||||
totalForwardSlip += w.ForwardSlip;
|
||||
var rpm = w.RPM;
|
||||
|
||||
avgRPM += rpm * w.DistributionFactor;
|
||||
}
|
||||
|
||||
avgPoweredRPM = avgRPM;
|
||||
avgSideSlip = totalSideSlip / Wheels.Count;
|
||||
avgForwardSlip = totalForwardSlip / Wheels.Count;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,32 +7,6 @@ namespace VeloX;
|
||||
[Title( "VeloX - Car" )]
|
||||
public partial class VeloXCar : VeloXBase
|
||||
{
|
||||
protected override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
//StreamPlayer = new( Stream );
|
||||
//if ( IsDriver )
|
||||
//{
|
||||
// UpdateGearList();
|
||||
// UpdatePowerDistribution();
|
||||
//}
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
base.OnUpdate();
|
||||
//if ( StreamPlayer is not null )
|
||||
//{
|
||||
|
||||
// StreamPlayer.Throttle = Throttle;
|
||||
// StreamPlayer.RPMPercent = RPMPercent;
|
||||
// StreamPlayer.EngineState = EngineState;
|
||||
// StreamPlayer.IsRedlining = IsRedlining;
|
||||
|
||||
// StreamPlayer.Update( Time.Delta, WorldPosition );
|
||||
//}
|
||||
|
||||
}
|
||||
protected override void OnFixedUpdate()
|
||||
{
|
||||
if ( !IsDriver )
|
||||
|
||||
@ -17,7 +17,7 @@ public class PacejkaWidget : ControlObjectWidget
|
||||
Layout = Layout.Column();
|
||||
Layout.Margin = 8f;
|
||||
Layout.Spacing = 8;
|
||||
foreach ( var item in TypeLibrary.GetType<Pacejka.LateralForce>().Fields )
|
||||
foreach ( var item in TypeLibrary.GetType<Pacejka.LateralForce>().Properties )
|
||||
{
|
||||
var row = Layout.AddRow();
|
||||
row.Spacing = 8;
|
||||
@ -36,7 +36,7 @@ public class PacejkaWidget : ControlObjectWidget
|
||||
Layout = Layout.Column();
|
||||
Layout.Margin = 8f;
|
||||
Layout.Spacing = 8;
|
||||
foreach ( var item in TypeLibrary.GetType<Pacejka.LongitudinalForce>().Fields )
|
||||
foreach ( var item in TypeLibrary.GetType<Pacejka.LongitudinalForce>().Properties )
|
||||
{
|
||||
var row = Layout.AddRow();
|
||||
row.Spacing = 8;
|
||||
@ -55,7 +55,7 @@ public class PacejkaWidget : ControlObjectWidget
|
||||
Layout = Layout.Column();
|
||||
Layout.Margin = 8f;
|
||||
Layout.Spacing = 8;
|
||||
foreach ( var item in TypeLibrary.GetType<Pacejka.AligningMoment>().Fields )
|
||||
foreach ( var item in TypeLibrary.GetType<Pacejka.AligningMoment>().Properties )
|
||||
{
|
||||
var row = Layout.AddRow();
|
||||
row.Spacing = 8;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
using Editor;
|
||||
using Editor.Assets;
|
||||
using Editor.Inspectors;
|
||||
using Editor.ShaderGraph.Nodes;
|
||||
using Sandbox;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -68,16 +67,13 @@ class TirePresetPreview( Asset asset ) : PixmapAssetPreview( asset )
|
||||
for ( float x = x0; x <= xn; x += (xn - x0) / points )
|
||||
{
|
||||
|
||||
float yval = tire.PacejkaFy( x, load, Camber, 1.0f, out float maxforce ) / load;
|
||||
float yval = tire.PacejkaFy( x, load, Camber, 1.0f, out float _ ) / load;
|
||||
float xval = width * (x - x0) / (xn - x0);
|
||||
yval /= ymax - ymin;
|
||||
yval = (yval + 1.0f) * 0.5f;
|
||||
yval = 1.0f - yval;
|
||||
yval *= height;
|
||||
if ( x == x0 )
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
else
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
}
|
||||
|
||||
Paint.DrawLine( pointCache );
|
||||
@ -86,6 +82,29 @@ class TirePresetPreview( Asset asset ) : PixmapAssetPreview( asset )
|
||||
{ // draw longitudinal line
|
||||
pointCache.Clear();
|
||||
|
||||
Paint.SetPen( Color.Green, 1 );
|
||||
float x0 = -zoom * 0.5f;
|
||||
float xn = zoom * 0.5f;
|
||||
float ymin = -1000.0f;
|
||||
float ymax = 1000.0f;
|
||||
int points = 500;
|
||||
|
||||
for ( float x = x0; x <= xn; x += (xn - x0) / points )
|
||||
{
|
||||
float yval = tire.PacejkaFx( x, load, 1.0f, out var _ ) / load;
|
||||
float xval = width * (x - x0) / (xn - x0);
|
||||
yval /= ymax - ymin;
|
||||
yval = (yval + 1.0f) * 0.5f;
|
||||
yval = 1.0f - yval;
|
||||
yval *= height;
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
}
|
||||
Paint.DrawLine( pointCache );
|
||||
}
|
||||
|
||||
{ // draw aligning line
|
||||
pointCache.Clear();
|
||||
|
||||
Paint.SetPen( Color.Blue, 1 );
|
||||
float x0 = -zoom * 0.5f * 10.0f;
|
||||
float xn = zoom * 0.5f * 10.0f;
|
||||
@ -101,36 +120,7 @@ class TirePresetPreview( Asset asset ) : PixmapAssetPreview( asset )
|
||||
yval = (yval + 1.0f) * 0.5f;
|
||||
yval = 1.0f - yval;
|
||||
yval *= height;
|
||||
if ( x == x0 )
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
else
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
}
|
||||
Paint.DrawLine( pointCache );
|
||||
}
|
||||
|
||||
{ // draw aligning line
|
||||
pointCache.Clear();
|
||||
|
||||
Paint.SetPen( Color.Green, 1 );
|
||||
float x0 = -zoom * 0.5f;
|
||||
float xn = zoom * 0.5f;
|
||||
float ymin = -1000.0f;
|
||||
float ymax = 1000.0f;
|
||||
int points = 500;
|
||||
|
||||
for ( float x = x0; x <= xn; x += (xn - x0) / points )
|
||||
{
|
||||
float yval = tire.PacejkaFx( x, load, 1.0f ) / load;
|
||||
float xval = width * (x - x0) / (xn - x0);
|
||||
yval /= ymax - ymin;
|
||||
yval = (yval + 1.0f) * 0.5f;
|
||||
yval = 1.0f - yval;
|
||||
yval *= height;
|
||||
if ( x == x0 )
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
else
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
}
|
||||
Paint.DrawLine( pointCache );
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user