Skip to content

Commit 15b9cc9

Browse files
committed
Allow superelevation on straight track segments, revise 3D superelevation generation, remove influence of secondary motion on camera position, improve handling of extreme gradients
1 parent 62061b8 commit 15b9cc9

File tree

16 files changed

+1177
-1085
lines changed

16 files changed

+1177
-1085
lines changed
Binary file not shown.

Source/Documentation/Manual/news.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ What's been improved
3939
- controls for electric locos
4040
- air brake features for both European and American brake systems
4141
- accurate friction simulation for 4 types of brake shoes
42+
- superelevation system rewritten to be smoother and more configurable
4243

4344

4445
Other changes

Source/ORTS.Common/Coordinates.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public Vector3 Location
138138
/// </summary>
139139
public void Normalize()
140140
{
141-
var TileLocation = XNAMatrix.Translation;
141+
var TileLocation = Location;
142142
int xTileDistance = (int)Math.Round((int)(TileLocation.X / 1024) / 2.0, MidpointRounding.AwayFromZero);
143143
int zTileDistance = (int)Math.Round((int)(TileLocation.Z / 1024) / 2.0, MidpointRounding.AwayFromZero);
144144
if (xTileDistance == 0 && zTileDistance == 0) return;
@@ -148,7 +148,7 @@ public void Normalize()
148148
TileZ += zTileDistance;
149149
TileLocation.X = (float)(TileLocation.X - (xTileDistance * TileSize));
150150
TileLocation.Z = (float)(TileLocation.Z - (zTileDistance * TileSize));
151-
XNAMatrix.Translation = TileLocation;
151+
Location = TileLocation;
152152
}
153153
}
154154

Source/Orts.Formats.Msts/RouteFile.cs

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ public Tr_RouteFile(STFReader stf)
136136
{
137137
// No superelevation standard defined, create the default one
138138
if (SuperElevationHgtpRadiusM != null)
139-
SuperElevation.Add(new SuperElevationStandard(SuperElevationHgtpRadiusM, MilepostUnitsMetric));
139+
SuperElevation.Add(new SuperElevationStandard(SuperElevationHgtpRadiusM, MilepostUnitsMetric, SpeedLimit > 45.0f));
140140
else
141-
SuperElevation.Add(new SuperElevationStandard(MilepostUnitsMetric));
141+
SuperElevation.Add(new SuperElevationStandard(MilepostUnitsMetric, SpeedLimit > 45.0f));
142142
}
143143
}
144144

@@ -248,41 +248,70 @@ public class SuperElevationStandard
248248
public bool UseLegacyCalculation = true; // Should ORTSTrackSuperElevation be used for superelevation calculations?
249249

250250
// Initialize new instance with default values (default metric values)
251-
public SuperElevationStandard(bool metric = true)
251+
public SuperElevationStandard(bool metric = true, bool highSpeed = false)
252252
{
253253
if (metric)
254254
{
255255
// Set underbalance to millimeter values for metric routes
256-
MaxFreightUnderbalanceM = 0.100f; // Default 100 mm
257-
MaxPaxUnderbalanceM = 0.150f; // Default 150 mm
256+
if (highSpeed)
257+
{
258+
RunoffSpeedMpS = 0.080f; // 80 mm / sec for higher speed routes
259+
MaxFreightUnderbalanceM = 0.110f; // 110 mm for higher speed routes
260+
MaxPaxUnderbalanceM = 0.150f; // 150 mm for higher speed routes
261+
}
262+
else
263+
{
264+
MaxFreightUnderbalanceM = 0.100f; // Default 100 mm
265+
MaxPaxUnderbalanceM = 0.130f; // Default 130 mm
266+
}
258267
// Other parameters are already metric by default
268+
259269
}
260270
else
261271
{
262272
// Set values in imperial units
263-
MaxFreightUnderbalanceM = Me.FromIn(2.0f); // Default 2 inches
264-
MaxPaxUnderbalanceM = Me.FromIn(3.0f); // Default 3 inches
265273
MinCantM = Me.FromIn(0.5f);
266274
MaxCantM = Me.FromIn(6.0f);
267275
MinSpeedMpS = MpS.FromMpH(15.0f);
268276
PrecisionM = Me.FromIn(0.25f);
269-
RunoffSpeedMpS = MpS.FromMpH(0.0852f); // 1.5 inches per second
277+
278+
if (highSpeed)
279+
{
280+
RunoffSpeedMpS = MpS.FromMpH(0.1136f); // 2.0 inches for higher speed routes
281+
MaxFreightUnderbalanceM = Me.FromIn(3.0f); // 3 inches for higher speed routes
282+
MaxPaxUnderbalanceM = Me.FromIn(5.0f); // 5 inches for higher speed routes
283+
}
284+
else
285+
{
286+
RunoffSpeedMpS = MpS.FromMpH(0.0852f); // Default 1.5 inches per second
287+
MaxFreightUnderbalanceM = Me.FromIn(2.0f); // Default 2 inches
288+
MaxPaxUnderbalanceM = Me.FromIn(3.0f); // Default 3 inches
289+
}
270290
}
271291
}
272292

273293
// Initialize new instance from superelevation interpolator
274294
// Interpolator X values should be curve radius, Y values amount of superelevation in meters
275-
public SuperElevationStandard(Interpolator elevTable, bool metric = true)
295+
public SuperElevationStandard(Interpolator elevTable, bool metric = true, bool highSpeed = false)
276296
{
277297
MinCantM = elevTable.Y.Min();
278298
MaxCantM = elevTable.Y.Max();
279299

280-
if (!metric)
300+
MinSpeedMpS = 0.0f;
301+
302+
if (metric)
303+
{
304+
if (highSpeed)
305+
RunoffSpeedMpS = 0.080f; // 80 mm / sec of runoff allows for shorter build up on high speed routes
306+
}
307+
else
281308
{
282309
// Some extra data still required, use imperial units if the route uses it
283-
MinSpeedMpS = MpS.FromMpH(15.0f);
284310
PrecisionM = Me.FromIn(0.25f);
285-
RunoffSpeedMpS = MpS.FromMpH(0.0852f); // 1.5 inches per second
311+
if (highSpeed)
312+
RunoffSpeedMpS = MpS.FromMpH(0.1136f); // 2.0 inches per second of runoff allows for shorter build up on high speed routes
313+
else
314+
RunoffSpeedMpS = MpS.FromMpH(0.0852f); // 1.5 inches per second normal
286315
}
287316
}
288317

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,10 @@ public override void InitializeMoving() // TODO
375375
float initialThrottlepercent = InitialThrottlepercent;
376376
MUDynamicBrakePercent = -1;
377377
AITrainBrakePercent = 0;
378-
379-
FirstCar.CurrentElevationPercent = 100f * FirstCar.WorldPosition.XNAMatrix.M32;
378+
// Percent slope = rise / run -> the Y position of the forward vector gives us the 'rise'
379+
// Derive the 'run' by assuming a hypotenuse length of 1, so run = sqrt(1 - rise^2)
380+
float rise = FirstCar.WorldPosition.XNAMatrix.M32;
381+
FirstCar.CurrentElevationPercent = 100f * (rise / (float)Math.Sqrt(1 - rise * rise));
380382
// Give it a bit more gas if it is uphill
381383
if (FirstCar.CurrentElevationPercent < -2.0) initialThrottlepercent = 40f;
382384
// Better block gas if it is downhill

Source/Orts.Simulation/Simulation/Activity.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,9 +629,7 @@ static void ComputeTablePosition(TempSpeedPostItem restrSpeedPost)
629629
var speedPostTablePosition = new Vector3(2.2f, 0, 0);
630630
Vector3.Transform(ref speedPostTablePosition, ref restrSpeedPost.WorldPosition.XNAMatrix, out speedPostTablePosition);
631631
restrSpeedPost.WorldPosition.XNAMatrix.Translation = speedPostTablePosition;
632-
restrSpeedPost.WorldPosition.XNAMatrix.M43 *= -1;
633632
restrSpeedPost.WorldPosition.Normalize();
634-
restrSpeedPost.WorldPosition.XNAMatrix.M43 *= -1;
635633
}
636634

637635

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1860,7 +1860,11 @@ public virtual void InitializeMoving()
18601860
{
18611861
MSTSLocomotive lead = (MSTSLocomotive)Cars[LeadLocomotiveIndex];
18621862
if (lead is MSTSSteamLocomotive) MUReverserPercent = 25;
1863-
lead.CurrentElevationPercent = 100f * lead.WorldPosition.XNAMatrix.M32;
1863+
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));
18641868

18651869
//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.
18661870
// To achieve the same result with other means, without flipping trainset physics, the block should be deleted

0 commit comments

Comments
 (0)