Skip to content

Commit b970aa2

Browse files
committed
Automatic merge of T1.5.1-1204-g8bc1d82939 and 17 pull requests
- Pull request #799 at dfc715e: Consolidated wind simulation - Pull request #839 at d00beb9: First phase of https://blueprints.launchpad.net/or/+spec/additional-cruise-control-parameters - Pull request #885 at 8f473ce: feat: Add notifications to Menu - Pull request #891 at 9a1d6b2: Auto save - Pull request #892 at 1f5ba4c: Signal Function OPP_SIG_ID_TRAINPATH - Pull request #952 at 8347095: Investigation - Pulsing graphics - Pull request #953 at a519452: Fix Lights Crash on Corrupt Shapes - Pull request #954 at 62061b8: Multiple Track Profiles & Superelevation Improvements - Pull request #962 at 46d0472: Fix pantographs on unpowered cars - Pull request #972 at e90a2aa: On Map window color changed switch or signal is not changed - Pull request #980 at a7406de: Downloading route content (Github, zip) second part - Pull request #981 at 10d297f: Multiple type trainset lightglows - Pull request #982 at efcf19c: WEB based Switch Panel enhancement: Alerter - Pull request #983 at 202316e: WEB based Switch Panel bug: DPU window - Pull request #984 at 0f8122e: Player train switching for timetable mode - Pull request #900 at c27f32d: DMI updates - Pull request #876 at f92de76: docs: add source for documents previously on website to source Documentation folder
19 parents 0f402c4 + 8bc1d82 + dfc715e + d00beb9 + 8f473ce + 9a1d6b2 + 1f5ba4c + 8347095 + a519452 + 62061b8 + 46d0472 + e90a2aa + a7406de + 10d297f + efcf19c + 202316e + 0f8122e + c27f32d + f92de76 commit b970aa2

File tree

5 files changed

+122
-109
lines changed

5 files changed

+122
-109
lines changed

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,7 +1952,11 @@ public virtual void UpdateCurveSpeedLimit(float elapsedClockSeconds)
19521952
// If speed exceeds the overturning speed, then indicated that an error condition has been reached.
19531953
if (s > CriticalMaxSpeedMpS)
19541954
{
1955-
if (!IsCriticalMaxSpeed)
1955+
// Consider a tolerance so error isn't immediately thrown, should reduce overkill notifications on routes with jerky track laying
1956+
// Will be reduced faster if simultaneously above the max safe speed
1957+
ComfortTolerance -= 0.25f * (s / MaxSafeCurveSpeedMps - 1.0f) * elapsedClockSeconds;
1958+
1959+
if (!IsCriticalMaxSpeed && ComfortTolerance <= 0.0f)
19561960
{
19571961
IsCriticalMaxSpeed = true; // set flag for IsCriticalSpeed reached
19581962

@@ -2896,7 +2900,10 @@ public void UpdateCurvePhys(Traveller traveller, float[] offsets)
28962900
// Set superelevation angle used by physics system
28972901
SuperElevationAngleRad = (float)Math.Asin(SuperelevationM / TrackGaugeM);
28982902

2899-
CurrentCurveRadiusM = curveRadii.Min();
2903+
CurrentCurveRadiusM = curveRadii.Average();
2904+
// Straight track has a "radius" of infinity, but rest of code expects straight to have a "radius" of 0
2905+
if (CurrentCurveRadiusM == float.PositiveInfinity)
2906+
CurrentCurveRadiusM = 0;
29002907
}
29012908
#endregion
29022909

Source/Orts.Simulation/Simulation/SuperElevation.cs

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -162,63 +162,64 @@ void MarkSections(Simulator simulator, List<TrVectorSection> SectionList, float
162162
if (standard == null)
163163
{
164164
foreach (TrVectorSection s in SectionList)
165-
s.NomElevM = 0;
166-
return; // No superelevation needed, stop processing here
165+
s.NomElevM = 0; // No superelevation needed
167166
}
168-
if ((standard.MinCantM / effectiveRunoffSlope) * 2.0f > totLen * 0.75f)
167+
else if ((standard.MinCantM / effectiveRunoffSlope) * 2.0f > totLen * 0.75f)
169168
{
170169
foreach (TrVectorSection s in SectionList)
171-
s.NomElevM = 0;
172-
return; // Curve is so short that no meaningful superelevation can be applied
170+
s.NomElevM = 0; // Curve is so short that no meaningful superelevation can be applied
173171
}
174-
175-
// Determine proper level of superelevation for every section
176-
for (int i = 0; i < SectionList.Count; i++)
172+
else
177173
{
178-
// Superelevation has not been calculated for this section yet
179-
if (SectionList[i].NomElevM < 0.0f)
174+
// Superelevation can be applied, run calculations
175+
foreach (TrVectorSection s in SectionList)
180176
{
181-
var sectionData = simulator.TSectionDat.TrackSections.Get(SectionList[i].SectionIndex);
182-
183-
if (sectionData == null || sectionData.SectionCurve == null)
177+
// Superelevation has not been calculated for this section yet
178+
// FUTURE: Superelevation NomElevM may be specified externally, eg: by a route editor
179+
if (s.NomElevM < 0.0f)
184180
{
185-
SectionList[i].NomElevM = 0.0f;
186-
continue;
187-
}
188-
else
189-
{
190-
float superElevation;
181+
var sectionData = simulator.TSectionDat.TrackSections.Get(s.SectionIndex);
191182

192-
// Support for old system with superelevation set directly in Route (TRK) file
193-
if (standard.UseLegacyCalculation && simulator.TRK.Tr_RouteFile.SuperElevationHgtpRadiusM != null)
183+
if (sectionData == null || sectionData.SectionCurve == null)
194184
{
195-
superElevation = simulator.TRK.Tr_RouteFile.SuperElevationHgtpRadiusM[sectionData.SectionCurve.Radius];
185+
s.NomElevM = 0.0f;
186+
continue;
196187
}
197-
else // Newer standard for calculating superelevation
188+
else
198189
{
199-
if (standard != null)
200-
{
201-
float paxSpeed = SectionList[i].PassSpeedMpS;
202-
float freightSpeed = SectionList[i].FreightSpeedMpS;
203-
204-
// Approximate ideal level of superelevation determined using E = (G*V^2) / (g*R), then subtract off cant deficiency
205-
// For different speeds on the same curve, we can factor out speed and get a constant c = G / (g*R)
206-
float elevationFactor = simulator.SuperElevationGauge / (9.81f * sectionData.SectionCurve.Radius);
207-
// Calculate required superelevation for passenger and freight separately
208-
float paxElevation = elevationFactor * (paxSpeed * paxSpeed) - standard.MaxPaxUnderbalanceM;
209-
float freightElevation = elevationFactor * (freightSpeed * freightSpeed) - standard.MaxFreightUnderbalanceM;
190+
float superElevation;
210191

211-
superElevation = Math.Max(paxElevation, freightElevation); // Choose the highest required superelevation
192+
// Support for old system with superelevation set directly in Route (TRK) file
193+
if (standard.UseLegacyCalculation && simulator.TRK.Tr_RouteFile.SuperElevationHgtpRadiusM != null)
194+
{
195+
superElevation = simulator.TRK.Tr_RouteFile.SuperElevationHgtpRadiusM[sectionData.SectionCurve.Radius];
212196
}
213-
else // No superelevation needed (shouldn't reach this point, this is a failsafe)
214-
superElevation = 0.0f;
215-
}
216-
superElevation = (float)Math.Round(superElevation / standard.PrecisionM, MidpointRounding.AwayFromZero)
217-
* standard.PrecisionM; // Round superelevation amount to next higher increment of precision
197+
else // Newer standard for calculating superelevation
198+
{
199+
if (standard != null)
200+
{
201+
float paxSpeed = s.PassSpeedMpS;
202+
float freightSpeed = s.FreightSpeedMpS;
203+
204+
// Approximate ideal level of superelevation determined using E = (G*V^2) / (g*R), then subtract off cant deficiency
205+
// For different speeds on the same curve, we can factor out speed and get a constant c = G / (g*R)
206+
float elevationFactor = simulator.SuperElevationGauge / (9.81f * sectionData.SectionCurve.Radius);
207+
// Calculate required superelevation for passenger and freight separately
208+
float paxElevation = elevationFactor * (paxSpeed * paxSpeed) - standard.MaxPaxUnderbalanceM;
209+
float freightElevation = elevationFactor * (freightSpeed * freightSpeed) - standard.MaxFreightUnderbalanceM;
210+
211+
superElevation = Math.Max(paxElevation, freightElevation); // Choose the highest required superelevation
212+
}
213+
else // No superelevation needed (shouldn't reach this point, this is a failsafe)
214+
superElevation = 0.0f;
215+
}
216+
superElevation = (float)Math.Round(superElevation / standard.PrecisionM, MidpointRounding.AwayFromZero)
217+
* standard.PrecisionM; // Round superelevation amount to next higher increment of precision
218218

219-
superElevation = MathHelper.Clamp(superElevation, standard.MinCantM, maxElev);
219+
superElevation = MathHelper.Clamp(superElevation, standard.MinCantM, maxElev);
220220

221-
SectionList[i].NomElevM = superElevation;
221+
s.NomElevM = superElevation;
222+
}
222223
}
223224
}
224225
}

Source/Orts.Simulation/Simulation/Traveller.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ public float GetCurvature()
980980
public void GetCurveData(out float physicsElev, out float curveRadius)
981981
{
982982
physicsElev = 0;
983-
curveRadius = 0;
983+
curveRadius = float.PositiveInfinity;
984984

985985
if (trackSection == null || trackVectorSection == null)
986986
return;

Source/RunActivity/Viewer3D/Scenery.cs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -376,20 +376,22 @@ public WorldFile(Viewer viewer, int tileX, int tileZ, bool visible)
376376
// We might not have found the junction node; if so, fall back to the static track shape.
377377
if (trJunctionNode != null)
378378
{
379+
// Handle superelevation on junctions (usually this means disabling it)
379380
if (viewer.Simulator.UseSuperElevation)
380-
SuperElevationManager.DecomposeStaticSuperElevation(viewer, dTrackList, trackObj, worldMatrix, TileX, TileZ, shapeFilePath);
381+
SuperElevationManager.PrepareStaticSuperElevation(viewer, trackObj, TileX, TileZ, shapeFilePath);
381382
sceneryObjects.Add(new SwitchTrackShape(viewer, shapeFilePath, worldMatrix, trJunctionNode));
382383
}
383384
else
384385
{
385-
//if want to use super elevation, we will generate tracks using dynamic tracks
386+
// See if superelevation should be used on this piece of track
386387
if (viewer.Simulator.UseSuperElevation
387-
&& SuperElevationManager.DecomposeStaticSuperElevation(viewer, dTrackList, trackObj, worldMatrix, TileX, TileZ, shapeFilePath))
388+
&& SuperElevationManager.PrepareStaticSuperElevation(viewer, trackObj, TileX, TileZ, shapeFilePath))
388389
{
389-
// No need to add shapes for this segment of track
390+
// Don't add scenery for this section of track, dynamic superelevated track will be created instead
390391
}
391-
//otherwise, use shapes
392-
else if (!containsMovingTable) sceneryObjects.Add(new StaticTrackShape(viewer, shapeFilePath, worldMatrix));
392+
// No superelevation, use shapes
393+
else if (!containsMovingTable)
394+
sceneryObjects.Add(new StaticTrackShape(viewer, shapeFilePath, worldMatrix));
393395
else
394396
{
395397
var found = false;
@@ -429,22 +431,24 @@ public WorldFile(Viewer viewer, int tileX, int tileZ, bool visible)
429431
}
430432
else if (worldObject.GetType() == typeof(DyntrackObj))
431433
{
434+
// Dynamic track will require track profiles, set up track profiles if not yet set
432435
if (viewer.TRPs == null)
433436
{
434-
// First to need a track profile creates it
435437
Trace.Write(" TRP");
436-
// Creates profile and loads materials into SceneryMaterials
438+
// Creates profile(s) and loads materials into SceneryMaterials
437439
TRPFile.CreateTrackProfile(viewer, viewer.Simulator.RoutePath, out viewer.TRPs);
438440
}
439441

440442
if (viewer.Simulator.Settings.Wire == true && viewer.Simulator.TRK.Tr_RouteFile.Electrified == true)
441443
Wire.DecomposeDynamicWire(viewer, dTrackList, (DyntrackObj)worldObject, worldMatrix);
442444
// Add DyntrackDrawers for individual subsections
443-
if (viewer.Simulator.UseSuperElevation && SuperElevationManager.UseSuperElevationDyn(viewer, dTrackList, (DyntrackObj)worldObject, worldMatrix))
445+
if (viewer.Simulator.UseSuperElevation && SuperElevationManager.UseSuperElevationDyn((DyntrackObj)worldObject))
444446
SuperElevationManager.DecomposeDynamicSuperElevation(viewer, dTrackList, (DyntrackObj)worldObject, worldMatrix);
445-
else DynamicTrack.Decompose(viewer, dTrackList, (DyntrackObj)worldObject, worldMatrix);
447+
else
448+
DynamicTrack.Decompose(viewer, dTrackList, (DyntrackObj)worldObject, worldMatrix);
446449

447-
} // end else if DyntrackObj
450+
}
451+
// Objects other than tracks
448452
else if (worldObject.GetType() == typeof(ForestObj))
449453
{
450454
if (!(worldObject as ForestObj).IsYard)
@@ -593,8 +597,9 @@ public WorldFile(Viewer viewer, int tileX, int tileZ, bool visible)
593597
}
594598
}
595599

596-
if (viewer.Simulator.UseSuperElevation) SuperElevationManager.DecomposeStaticSuperElevation(Viewer, dTrackList, TileX, TileZ);
597-
if (Viewer.World.Sounds != null) Viewer.World.Sounds.AddByTile(TileX, TileZ);
600+
if (viewer.Simulator.UseSuperElevation)
601+
SuperElevationManager.DecomposeTileSuperElevation(Viewer, dTrackList, TileX, TileZ);
602+
Viewer.World.Sounds?.AddByTile(TileX, TileZ);
598603
}
599604

600605
/// <summary>

0 commit comments

Comments
 (0)