Skip to content

Commit da57f73

Browse files
authored
Merge pull request #1029 from SteelFill/multi_track_profiles
Superelevation Follow Up Fixes
2 parents 44e5919 + 248b8d5 commit da57f73

File tree

7 files changed

+114
-90
lines changed

7 files changed

+114
-90
lines changed

Source/Orts.Formats.Msts/TrackSectionsFile.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,18 @@ public SectionIdx(STFReader stf)
182182
STFException.TraceWarning(stf, "Invalid track section " + token);
183183
}
184184
stf.SkipRestOfBlock();
185-
}
186-
public uint NoSections;
185+
}
186+
public SectionIdx(TrackPath path)
187+
{
188+
X = 0;
189+
Y = 0;
190+
Z = 0;
191+
A = 0;
192+
NoSections = path.NoSections;
193+
TrackSections = path.TrackSections;
194+
}
195+
196+
public uint NoSections;
187197
public double X,Y,Z; // Offset
188198
public double A; // Angular offset
189199
public uint[] TrackSections;

Source/Orts.Simulation/Simulation/AIs/AITrain.cs

+2-4
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,8 @@ public override void InitializeMoving() // TODO
378378
float initialThrottlepercent = InitialThrottlepercent;
379379
MUDynamicBrakePercent = -1;
380380
AITrainBrakePercent = 0;
381-
// Percent slope = rise / run -> the Y position of the forward vector gives us the 'rise'
382-
// Derive the 'run' by assuming a hypotenuse length of 1, so run = sqrt(1 - rise^2)
383-
float rise = FirstCar.WorldPosition.XNAMatrix.M32;
384-
FirstCar.CurrentElevationPercent = 100f * (rise / (float)Math.Sqrt(1 - rise * rise));
381+
// Force calculate gradient at the front of the train
382+
FirstCar.UpdateGravity();
385383
// Give it a bit more gas if it is uphill
386384
if (FirstCar.CurrentElevationPercent < -2.0) initialThrottlepercent = 40f;
387385
// Better block gas if it is downhill

Source/Orts.Simulation/Simulation/Physics/Train.cs

+11-27
Original file line numberDiff line numberDiff line change
@@ -1861,18 +1861,8 @@ public virtual void InitializeMoving()
18611861
MSTSLocomotive lead = (MSTSLocomotive)Cars[LeadLocomotiveIndex];
18621862
if (lead is MSTSSteamLocomotive) MUReverserPercent = 25;
18631863

1864-
// Percent slope = rise / run -> the Y position of the forward vector gives us the 'rise'
1865-
// Derive the 'run' by assuming a hypotenuse length of 1, so run = sqrt(1 - rise^2)
1866-
float rise = lead.WorldPosition.XNAMatrix.M32;
1867-
lead.CurrentElevationPercent = 100f * (rise / (float)Math.Sqrt(1 - rise * rise));
1868-
1869-
//TODO: next if block has been inserted to flip trainset physics in order to get viewing direction coincident with loco direction when using rear cab.
1870-
// To achieve the same result with other means, without flipping trainset physics, the block should be deleted
1871-
//
1872-
if (lead.IsDriveable && (lead as MSTSLocomotive).UsingRearCab)
1873-
{
1874-
lead.CurrentElevationPercent = -lead.CurrentElevationPercent;
1875-
}
1864+
// Force calculate gradient at the lead locomotive
1865+
lead.UpdateGravity();
18761866
// give it a bit more gas if it is uphill
18771867
if (lead.CurrentElevationPercent < -2.0) initialThrottlepercent = 40f;
18781868
// better block gas if it is downhill
@@ -4512,9 +4502,9 @@ public void RepositionRearTraveller()
45124502

45134503
// Update car's curve radius and superelevation based on bogie position and move traveller to front bogie
45144504
// Also determine roll angle for superelevation by averaging both bogies
4515-
float roll = traveller.GetVisualElevation();
4505+
float roll = traveller.GetVisualElevation(Simulator.Settings.UseSuperElevation);
45164506
car.UpdateCurvePhys(traveller, new[] { 0, car.CarBogieCentreLengthM });
4517-
roll = (roll + traveller.GetVisualElevation()) / 2.0f;
4507+
roll = (roll + traveller.GetVisualElevation(Simulator.Settings.UseSuperElevation)) / 2.0f;
45184508

45194509
// Normalize across tile boundaries
45204510
x += 2048 * (tileX - traveller.TileX);
@@ -4532,9 +4522,7 @@ public void RepositionRearTraveller()
45324522
car.WorldPosition.XNAMatrix *= Simulator.XNAMatrixFromMSTSCoordinates(traveller.X, traveller.Y, traveller.Z, x, y, z);
45334523

45344524
// Update gravity force when position is updated, but before any secondary motion is added
4535-
Vector3 fwd = car.WorldPosition.XNAMatrix.Backward;
4536-
car.GravityForceN = car.MassKG * TrainCar.GravitationalAccelerationMpS2 * fwd.Y;
4537-
car.CurrentElevationPercent = 100f * (fwd.Y / (float)Math.Sqrt(1 - fwd.Y * fwd.Y));
4525+
car.UpdateGravity();
45384526

45394527
// Apply superelevation to car
45404528
car.WorldPosition.XNAMatrix = Matrix.CreateRotationZ((car.Flipped ? -1.0f : 1.0f) * roll) * car.WorldPosition.XNAMatrix;
@@ -4633,9 +4621,9 @@ public void CalculatePositionOfCars(float elapsedTime, float distance)
46334621

46344622
// Update car's curve radius and superelevation based on bogie position and move traveller to front bogie
46354623
// Outputs rotation angle for superelevation, used below
4636-
float roll = traveller.GetVisualElevation();
4624+
float roll = traveller.GetVisualElevation(Simulator.Settings.UseSuperElevation);
46374625
car.UpdateCurvePhys(traveller, new[] { 0, car.CarBogieCentreLengthM });
4638-
roll = (roll + traveller.GetVisualElevation()) / 2.0f;
4626+
roll = (roll + traveller.GetVisualElevation(Simulator.Settings.UseSuperElevation)) / 2.0f;
46394627

46404628
// Normalize across tile boundaries
46414629
x += 2048 * (tileX - traveller.TileX);
@@ -4653,9 +4641,7 @@ public void CalculatePositionOfCars(float elapsedTime, float distance)
46534641
car.WorldPosition.XNAMatrix *= Simulator.XNAMatrixFromMSTSCoordinates(traveller.X, traveller.Y, traveller.Z, x, y, z);
46544642

46554643
// Update gravity force when position is updated, but before any secondary motion is added
4656-
Vector3 fwd = car.WorldPosition.XNAMatrix.Backward;
4657-
car.GravityForceN = car.MassKG * TrainCar.GravitationalAccelerationMpS2 * fwd.Y;
4658-
car.CurrentElevationPercent = 100f * (fwd.Y / (float)Math.Sqrt(1 - fwd.Y * fwd.Y));
4644+
car.UpdateGravity();
46594645

46604646
// Apply superelevation to car
46614647
car.WorldPosition.XNAMatrix = Matrix.CreateRotationZ((car.Flipped ? -1.0f : 1.0f) * roll) * car.WorldPosition.XNAMatrix;
@@ -4714,9 +4700,9 @@ public void CalculatePositionOfEOT()
47144700

47154701
// Update car's curve radius and superelevation based on bogie position and move traveller to front bogie
47164702
// Outputs rotation angle for superelevation, used below
4717-
float roll = traveller.GetVisualElevation();
4703+
float roll = traveller.GetVisualElevation(Simulator.Settings.UseSuperElevation);
47184704
car.UpdateCurvePhys(traveller, new[] { 0, car.CarBogieCentreLengthM });
4719-
roll = (roll + traveller.GetVisualElevation()) / 2.0f;
4705+
roll = (roll + traveller.GetVisualElevation(Simulator.Settings.UseSuperElevation)) / 2.0f;
47204706

47214707
// Normalize across tile boundaries
47224708
x += 2048 * (tileX - traveller.TileX);
@@ -4734,9 +4720,7 @@ public void CalculatePositionOfEOT()
47344720
car.WorldPosition.XNAMatrix *= Simulator.XNAMatrixFromMSTSCoordinates(traveller.X, traveller.Y, traveller.Z, x, y, z);
47354721

47364722
// Update gravity force when position is updated, but before any secondary motion is added
4737-
Vector3 fwd = car.WorldPosition.XNAMatrix.Backward;
4738-
car.GravityForceN = car.MassKG * TrainCar.GravitationalAccelerationMpS2 * fwd.Y;
4739-
car.CurrentElevationPercent = 100f * (fwd.Y / (float)Math.Sqrt(1 - fwd.Y * fwd.Y));
4723+
car.UpdateGravity();
47404724

47414725
// Apply superelevation to car
47424726
car.WorldPosition.XNAMatrix = Matrix.CreateRotationZ((car.Flipped ? -1.0f : 1.0f) * roll) * car.WorldPosition.XNAMatrix;

Source/Orts.Simulation/Simulation/RollingStocks/TrainCar.cs

+31-11
Original file line numberDiff line numberDiff line change
@@ -985,15 +985,6 @@ public virtual void Update(float elapsedClockSeconds)
985985

986986
AbsSpeedMpS = Math.Abs(_SpeedMpS);
987987

988-
//TODO: next if block has been inserted to flip trainset physics in order to get viewing direction coincident with loco direction when using rear cab.
989-
// To achieve the same result with other means, without flipping trainset physics, the block should be deleted
990-
//
991-
if (IsDriveable && Train != null & Train.IsPlayerDriven && (this as MSTSLocomotive).UsingRearCab)
992-
{
993-
GravityForceN = -GravityForceN;
994-
CurrentElevationPercent = -CurrentElevationPercent;
995-
}
996-
997988
UpdateCurveSpeedLimit(elapsedClockSeconds);
998989
UpdateCurveForce(elapsedClockSeconds);
999990
UpdateTunnelForce();
@@ -2835,8 +2826,7 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
28352826
m.Backward = fwd;
28362827

28372828
// Update gravity force when position is updated, but before any secondary motion is added
2838-
GravityForceN = MassKG * GravitationalAccelerationMpS2 * fwd.Y;
2839-
CurrentElevationPercent = 100f * (fwd.Y / (float)Math.Sqrt(1 - fwd.Y * fwd.Y));
2829+
UpdateGravity(m);
28402830

28412831
// Consider body roll from superelevation and from tilting.
28422832
UpdateTilting(traveler, elapsedTimeS, speed, direction);
@@ -3468,6 +3458,36 @@ public LatLonDirection GetLatLonDirection()
34683458

34693459
return new LatLonDirection(latLon, directionDeg); ;
34703460
}
3461+
3462+
/// <summary>
3463+
/// Update the gravity force and % gradient of this train car at the current position
3464+
/// </summary>
3465+
public void UpdateGravity()
3466+
{
3467+
UpdateGravity(WorldPosition.XNAMatrix);
3468+
}
3469+
3470+
/// <summary>
3471+
/// Update the gravity force and % gradient of this train car at an arbitrary position
3472+
/// </summary>
3473+
/// <param name="orientation">Matrix giving the train car orientation used to determine gravity.</param>
3474+
public void UpdateGravity(Matrix orientation)
3475+
{
3476+
// Percent slope = 100 * rise / run -> the Y component of the forward vector gives us the 'rise'
3477+
// Derive the 'run' by assuming a hypotenuse length of 1, so per Pythagoras run = sqrt(1 - rise^2)
3478+
float rise = orientation.Backward.Y;
3479+
3480+
GravityForceN = MassKG * GravitationalAccelerationMpS2 * rise;
3481+
CurrentElevationPercent = 100f * (rise / (float)Math.Sqrt(1 - rise * rise));
3482+
3483+
// Reverse gravity force and % gradient on locomotives operated from the rear cab
3484+
// FUTURE: Change rear cabs to not require such forbidden manipulations of physics
3485+
if (IsDriveable && Train != null & Train.IsPlayerDriven && (this as MSTSLocomotive).UsingRearCab)
3486+
{
3487+
GravityForceN = -GravityForceN;
3488+
CurrentElevationPercent = -CurrentElevationPercent;
3489+
}
3490+
}
34713491
}
34723492

34733493
public class WheelAxle : IComparer<WheelAxle>

Source/RunActivity/Viewer3D/DynamicTrack.cs

+3
Original file line numberDiff line numberDiff line change
@@ -1503,6 +1503,9 @@ public virtual void CircArcGen()
15031503
}
15041504
break;
15051505
}
1506+
// Limit the number of sections to prevent overflowing the number of triangles
1507+
if (NumSections > 250)
1508+
NumSections = 250;
15061509
// Ensure an even number of sections
15071510
if (NumSections % 2 == 1)
15081511
NumSections++;

Source/RunActivity/Viewer3D/RollingStock/MSTSWagonViewer.cs

+22-17
Original file line numberDiff line numberDiff line change
@@ -882,33 +882,38 @@ private void UpdateAnimation(RenderFrame frame, ElapsedTime elapsedTime)
882882

883883
#endif
884884

885-
// truck angle animation
885+
// Bogie angle animation
886886
Matrix inverseLocation = Matrix.Invert(Car.WorldPosition.XNAMatrix);
887887

888888
foreach (var p in Car.Parts)
889889
{
890890
if (p.iMatrix <= 0)
891891
continue;
892892

893-
// Determine orientation of bogie in absolute space
894893
Matrix m = Matrix.Identity;
895-
Vector3 fwd = new Vector3(p.Dir[0], p.Dir[1], -p.Dir[2]);
896-
// Only do this calculation if the bogie position has been calculated
897-
if (!(fwd.X == 0 && fwd.Y == 0 && fwd.Z == 0))
894+
895+
// Bogie rotation calculation doesn't work on turntables
896+
// Assume bogies aren't rotated when on a turntable
897+
if (Car.Train?.ControlMode != Train.TRAIN_CONTROL.TURNTABLE)
898898
{
899-
fwd.Normalize();
900-
Vector3 side = Vector3.Cross(Vector3.Up, fwd);
901-
if (!(side.X == 0 && side.Y == 0 && side.Z == 0))
902-
side.Normalize();
903-
Vector3 up = Vector3.Cross(fwd, side);
904-
m.Right = side;
905-
m.Up = up;
906-
m.Backward = fwd;
907-
908-
// Convert absolute rotation into rotation relative to train car
909-
m = Matrix.CreateRotationZ(p.Roll) * m * inverseLocation;
899+
// Determine orientation of bogie in absolute space
900+
Vector3 fwd = new Vector3(p.Dir[0], p.Dir[1], -p.Dir[2]);
901+
// Only do this calculation if the bogie position has been calculated
902+
if (!(fwd.X == 0 && fwd.Y == 0 && fwd.Z == 0))
903+
{
904+
fwd.Normalize();
905+
Vector3 side = Vector3.Cross(Vector3.Up, fwd);
906+
if (!(side.X == 0 && side.Y == 0 && side.Z == 0))
907+
side.Normalize();
908+
Vector3 up = Vector3.Cross(fwd, side);
909+
m.Right = side;
910+
m.Up = up;
911+
m.Backward = fwd;
912+
913+
// Convert absolute rotation into rotation relative to train car
914+
m = Matrix.CreateRotationZ(p.Roll) * m * inverseLocation;
915+
}
910916
}
911-
912917
// Insert correct translation (previous step likely introduced garbage data)
913918
m.Translation = TrainCarShape.SharedShape.Matrices[p.iMatrix].Translation;
914919

0 commit comments

Comments
 (0)