Skip to content

Commit 1bef191

Browse files
committed
Automatic merge of T1.5.1-957-g4fd63a327 and 18 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 #876 at f92de76: docs: add source for documents previously on website to source Documentation folder - Pull request #882 at 3ca0eb1: Blueprint/train car operations UI window - Pull request #891 at 9a1d6b2: Auto save - Pull request #892 at 1f5ba4c: Signal Function OPP_SIG_ID_TRAINPATH - Pull request #896 at 5866028: First implementation of https://blueprints.launchpad.net/or/+spec/specific-sounds-for-ai-trains - Pull request #900 at c27f32d: DMI updates - Pull request #903 at 7af1f91: Downloading route content (Github, zip) - Pull request #912 at 56abfa2: New Triple Valve Features Vol. 2 - Pull request #919 at 26cc6a8: Added mouse wheel support for controls which can be moved by pressing t… - Pull request #922 at abe2e52: Autopilot for timetable mode - Pull request #923 at 4c27204: Add curve squeal to route - Pull request #929 at a406a69: Add support for common circuit breaker variants - Pull request #939 at 6c8095a: Add KM/HOUR/MIN to Cabview Units - Pull request #940 at f8b5b15: Browser HUD column alignment improvements - Pull request #941 at 50378f6: AI Penalty Lights Fix - Pull request #942 at 3a9c6ca: Fix wrong case in filename
20 parents b65fa14 + 4fd63a3 + dfc715e + d00beb9 + f92de76 + 3ca0eb1 + 9a1d6b2 + 1f5ba4c + 5866028 + c27f32d + 7af1f91 + 56abfa2 + 26cc6a8 + abe2e52 + 4c27204 + a406a69 + 6c8095a + f8b5b15 + 50378f6 + 3a9c6ca commit 1bef191

File tree

8 files changed

+114
-4
lines changed

8 files changed

+114
-4
lines changed

Source/Documentation/Manual/features-rollingstock.rst

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,6 +1487,53 @@ to the oscillation from center point to an oscillation end point. The file shoul
14871487
one cue point at its beginning and one after the time interval of a complete bell swing
14881488
forward and backward, and should have a final fadeoff for best result.
14891489

1490+
Brake Equipment Animations
1491+
==========================
1492+
1493+
Open Rails now supports animation of brake rigging components driven by the brake system
1494+
simulation.
1495+
1496+
Brake Cylinder Animation
1497+
------------------------
1498+
1499+
On engines and wagons with :ref:`advanced brake cylinder parameters <physics-braking-parameters>`
1500+
`ORTSBrakeCylinderDiameter` and `ORTSBrakeCylinderPistonTravel` defined, Open Rails will
1501+
simulate the motion of the brake cylinders and brake rigging. This simulation can be used
1502+
to drive animations of brake cylinders using animation matricies with names that
1503+
start with `ORTSBRAKECYLINDER`. This animation type should NOT be used for any brake equipment
1504+
that can be actuated by the brake cylinder and the handbrakes. See the section on brake rigging
1505+
animation for details.
1506+
1507+
Unlike other animation types, the keyframes for brake cylinders do not represent time.
1508+
Instead, the key value represents the level of brake cylinder extension. A value of 0.8
1509+
represents the state where the brake cylinder has taken up the slack in the brake rigging,
1510+
1.0 represents the level of brake cylinder extension at 50 psi/3.5 bar, and the maximum
1511+
value of cylinder extension is 1.6, which should not be possible in normal operation.
1512+
These values are the same regardless of the settings used in the engine or wagon file.
1513+
1514+
Note that the advanced brake cylinder calculations are only run on air brake systems on the
1515+
player train to save computing power. As such, brake cylinder animations on AI trains
1516+
or brake systems other than air brakes behave in a simplified manner.
1517+
1518+
Handbrake Animation
1519+
-------------------
1520+
1521+
Handbrake wheels and levers can also be animated using the same process as two-state animations
1522+
such as mirrors. The matrix name for animated handbrakes must begin with `ORTSHANDBRAKE`.
1523+
1524+
Brake Rigging and Brake Shoe Animation
1525+
--------------------------------------
1526+
1527+
For any brake equipment that is actuated by both the handbrake and the brake cylinders (typically,
1528+
this includes brake rigging and brake shoes, but sometimes also includes brake cylinders themselves),
1529+
use animations with a matrix name starting with `ORTSBRAKERIGGING`. For this type of animation, the
1530+
animation state will respond to the brake cylinder travel or the handbrake, whichever input is greater.
1531+
1532+
The same keyframe rules as brake cylinder animations apply here. The 0.8 key should represent the state
1533+
where the brake shoes have made contact with the friction surface, and no further motion of brake shoes
1534+
should occur after 0.8. Applying the handbrake will drive the animation to the 1.0 state, the same
1535+
as a 50 psi/3.5 bar application of the brakes.
1536+
14901537
Coupler and Airhose Animation
14911538
=============================
14921539

Source/Documentation/Manual/physics.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3143,6 +3143,8 @@ notch of the train brake controller, where 0 means no dynamic brake and 1 means
31433143
Native Open Rails Braking Parameters
31443144
------------------------------------
31453145

3146+
.. _physics-braking-parameters:
3147+
31463148
Open Rails has implemented additional specific braking parameters to
31473149
deliver realism in braking performance in the simulation.
31483150

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/BrakeSystem.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public abstract class BrakeSystem
8282
public abstract float GetCylPressurePSI();
8383
public abstract float GetCylVolumeM3();
8484
public abstract float GetTotalCylVolumeM3();
85+
public abstract float GetNormalizedCylTravel();
8586
public abstract float GetVacResPressurePSI();
8687
public abstract float GetVacResVolume();
8788
public abstract float GetVacBrakeCylNumber();

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/MSTS/AirSinglePipe.cs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,11 @@ public override float GetTotalCylVolumeM3()
300300
return TotalCylVolumeM3;
301301
}
302302

303+
public override float GetNormalizedCylTravel()
304+
{
305+
return CurrentCylTravelM / CylStrokeM;
306+
}
307+
303308
public float GetFullServPressurePSI()
304309
{
305310
return FullServPressurePSI;
@@ -655,8 +660,8 @@ public override void Initialize()
655660
// Other assumptions:
656661
// Brake cylinder travel remains at 0 until reaching half the spring counter-pressure
657662
// Brake cylinder travel is linear w.r.t. total air in the cylinder line, not entirely accurate but greatly simplifies code
658-
float[] airPV = new float[5];
659-
float[] cylTravel = new float[5];
663+
float[] airPV = new float[7];
664+
float[] cylTravel = new float[7];
660665

661666
float nomPSI = 50.0f;
662667

@@ -685,6 +690,12 @@ public override void Initialize()
685690

686691
cylTravel[4] = (strokePerPsi * (Math.Max(nomPSI, ReferencePressurePSI) - 50.0f)) + CylStrokeM;
687692
airPV[4] = AdvancedBrakeCylinderAir(Math.Max(nomPSI, ReferencePressurePSI), true);
693+
// Absolute maximum cylinder travel limited to 160% of nominal
694+
cylTravel[5] = CylStrokeM * 1.6f;
695+
airPV[5] = AdvancedBrakeCylinderAir((cylTravel[5] - cylTravel[2]) / strokePerPsi);
696+
697+
cylTravel[6] = cylTravel[5];
698+
airPV[6] = airPV[5] * 2.0f;
688699

689700
CylTravelTab = new Interpolator(airPV, cylTravel);
690701

@@ -813,7 +824,6 @@ public float CalculateBrakeCylinderPressure(ref float airPV, float dp, float tar
813824
}
814825
else if (dp < 0)
815826
{
816-
recalculate = true;
817827
if (pressurePSI < 0)
818828
{
819829
currentAir = 0;
@@ -1409,6 +1419,8 @@ public override void Update(float elapsedClockSeconds)
14091419
dp = QuickServiceLimitPSI - AutoCylPressurePSI;
14101420
if (QuickServiceBulbPressurePSI - (dp * volumeRatio) < AutoCylPressurePSI + dp)
14111421
dp = (QuickServiceBulbPressurePSI - AutoCylPressurePSI) / (1 + volumeRatio);
1422+
if (dp < 0)
1423+
dp = 0;
14121424
if (CylSource == 0)
14131425
AutoCylPressurePSI = CalculateBrakeCylinderPressure(ref AutoCylAirPV, dp, QuickServiceLimitPSI);
14141426
else
@@ -1739,7 +1751,7 @@ public override void Update(float elapsedClockSeconds)
17391751
if (CylDiameterM > 0 && Car.Train.IsPlayerDriven)
17401752
CurrentCylTravelM = CylTravelTab[CylAirPV];
17411753
else
1742-
CurrentCylTravelM = 0;
1754+
CurrentCylTravelM = CylPressurePSI > BrakeCylinderSpringPressurePSI ? CylStrokeM : 0.0f;
17431755

17441756
// During braking wheelslide control is effected throughout the train by additional equipment on each vehicle. In the piping to each pair of brake cylinders are fitted electrically operated
17451757
// dump valves. When axle rotations which are sensed electrically, differ by a predetermined speed the dump valves are operated releasing brake cylinder pressure to both axles of the affected

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/MSTS/ManualBraking.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,11 @@ public override float GetTotalCylVolumeM3()
356356
return 0;
357357
}
358358

359+
public override float GetNormalizedCylTravel()
360+
{
361+
return ManualBrakingCurrentFraction;
362+
}
363+
359364
public override float GetVacResVolume()
360365
{
361366
return 0;

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/MSTS/VacuumSinglePipe.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,11 @@ public override float GetTotalCylVolumeM3()
216216
return TotalCylVolumeM3;
217217
}
218218

219+
public override float GetNormalizedCylTravel()
220+
{
221+
return CylPressurePSIA > VacResPressureAdjPSIA() ? 1.0f : 0.0f;
222+
}
223+
219224
public override float GetVacResVolume()
220225
{
221226
return VacResVolM3;

Source/RunActivity/Viewer3D/AnimatedPart.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,20 @@ public void SetFrameClamp(float frame)
103103
SetFrame(frame);
104104
}
105105

106+
/// <summary>
107+
/// Smoothly changes the animation to a particular frame whilst clamping it to the frame count range.
108+
/// </summary>
109+
public void UpdateFrameClamp(float frame, ElapsedTime elapsedTime)
110+
{
111+
float newState;
112+
if (Math.Abs(frame - AnimationKey) > 1.0f * elapsedTime.ClockSeconds)
113+
newState = AnimationKey + Math.Sign(frame - AnimationKey) * elapsedTime.ClockSeconds;
114+
else
115+
newState = frame;
116+
117+
SetFrameClamp(newState);
118+
}
119+
106120
/// <summary>
107121
/// Sets the animation to a particular frame whilst cycling back to the start as input goes beyond the last frame.
108122
/// </summary>

Source/RunActivity/Viewer3D/RollingStock/MSTSWagonViewer.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ public class MSTSWagonViewer : TrainCarViewer
8080
protected AnimatedPart Item2Continuous;
8181
protected AnimatedPart Item1TwoState;
8282
protected AnimatedPart Item2TwoState;
83+
protected AnimatedPart BrakeCylinders;
84+
protected AnimatedPart Handbrakes;
85+
protected AnimatedPart BrakeRigging;
8386
AnimatedPart UnloadingParts;
8487

8588
public Dictionary<string, List<ParticleEmitterViewer>> ParticleDrawers = new Dictionary<string, List<ParticleEmitterViewer>>();
@@ -341,6 +344,9 @@ from data in effect.Value
341344
Item2Continuous = new AnimatedPart(TrainCarShape);
342345
Item1TwoState = new AnimatedPart(TrainCarShape);
343346
Item2TwoState = new AnimatedPart(TrainCarShape);
347+
BrakeCylinders = new AnimatedPart(TrainCarShape);
348+
Handbrakes = new AnimatedPart(TrainCarShape);
349+
BrakeRigging = new AnimatedPart(TrainCarShape);
344350

345351
if (car.FreightAnimations != null)
346352
FreightAnimations = new FreightAnimationsViewer(viewer, car, wagonFolderSlash);
@@ -431,6 +437,9 @@ from data in effect.Value
431437
RightWindowRear.SetState(MSTSWagon.WindowStates[MSTSWagon.RightWindowRearIndex] >= MSTSWagon.WindowState.Opening);
432438
Item1TwoState.SetState(MSTSWagon.GenericItem1);
433439
Item2TwoState.SetState(MSTSWagon.GenericItem2);
440+
BrakeCylinders.SetFrameClamp(MSTSWagon.BrakeSystem.GetNormalizedCylTravel());
441+
Handbrakes.SetState(MSTSWagon.GetTrainHandbrakeStatus());
442+
BrakeRigging.SetFrameClamp(Math.Max(MSTSWagon.BrakeSystem.GetNormalizedCylTravel(), MSTSWagon.GetTrainHandbrakeStatus() ? 1.0f : 0.0f));
434443
UnloadingParts.SetState(MSTSWagon.UnloadingPartsOpen);
435444

436445
InitializeUserInputCommands();
@@ -617,6 +626,18 @@ void MatchMatrixToPart(MSTSWagon car, int matrix, int bogieMatrix)
617626
{
618627
Item2TwoState.AddMatrix(matrix);
619628
}
629+
else if (matrixName.StartsWith("ORTSBRAKECYLINDER")) // brake cylinder animation
630+
{
631+
BrakeCylinders.AddMatrix(matrix);
632+
}
633+
else if (matrixName.StartsWith("ORTSHANDBRAKE")) // handbrake wheel animation
634+
{
635+
Handbrakes.AddMatrix(matrix);
636+
}
637+
else if (matrixName.StartsWith("ORTSBRAKERIGGING")) // brake rigging/brake shoes animation
638+
{
639+
BrakeRigging.AddMatrix(matrix);
640+
}
620641
else
621642
{
622643
if (matrixAnimated && matrix != 0)
@@ -669,6 +690,9 @@ public override void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime)
669690
UnloadingParts.UpdateState(MSTSWagon.UnloadingPartsOpen, elapsedTime);
670691
Item1TwoState.UpdateState(MSTSWagon.GenericItem1, elapsedTime);
671692
Item2TwoState.UpdateState(MSTSWagon.GenericItem2, elapsedTime);
693+
BrakeCylinders.UpdateFrameClamp(MSTSWagon.BrakeSystem.GetNormalizedCylTravel(), elapsedTime);
694+
Handbrakes.UpdateState(MSTSWagon.GetTrainHandbrakeStatus(), elapsedTime);
695+
BrakeRigging.UpdateFrameClamp(Math.Max(MSTSWagon.BrakeSystem.GetNormalizedCylTravel(), MSTSWagon.GetTrainHandbrakeStatus() ? 1.0f : 0.0f), elapsedTime);
672696
UpdateAnimation(frame, elapsedTime);
673697

674698
var car = Car as MSTSWagon;

0 commit comments

Comments
 (0)