Skip to content

Commit dc950d3

Browse files
committed
Automatic merge of T1.6-139-g6b62c2a7d and 12 pull requests
- Pull request #1082 at 8538170: Allow variable water level in glass gauge - Pull request #1156 at f46d5f2: Fix incorrectly disabled options in train operations window - Pull request #1091 at 492795a: Automatic speed control - Pull request #1122 at 73c47b4: Wagon Size and Centering Controls - Pull request #1124 at e241a0d: Built-in PBL2 brake controller - Pull request #1128 at d116396: Particle Emitter Overhaul - Pull request #1157 at 39cd994: Dynamic brake authorization by TCS - Pull request #1159 at 48c9a63: Skip OR warnings about TSRE-specific token Ruler - Pull request #1163 at 2f9e292: Fix: Crash when using Camera 8 and F9. - Pull request #1164 at 1ad9889: Fix: F9 crashes with a front coupled single steam locomotive by Csantucci. - Pull request #1166 at 51e7f7a: Simplify loading of internal and game textures - Pull request #1167 at 2c028a4: Fix: RunActivity slow to terminate because of long sleep in Host Process
14 parents 440f0b7 + 6b62c2a + 8538170 + f46d5f2 + 492795a + 73c47b4 + e241a0d + d116396 + 39cd994 + 48c9a63 + 2f9e292 + 1ad9889 + 51e7f7a + 2c028a4 commit dc950d3

File tree

3 files changed

+59
-22
lines changed

3 files changed

+59
-22
lines changed

Source/Documentation/Manual/features-rollingstock.rst

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,37 @@ types at each end. Only the highest detail LOD of the main shape and freight ani
505505
used, the .sd file is not checked. If the process fails, a warning will be written to the
506506
log and the automatic calculation will be skipped.
507507

508+
Advanced articulation control
509+
-----------------------------
510+
511+
A wide variety of modern rolling stock uses articulation, in which multiple rail vehicles
512+
share a single "Jacobs Bogie". Open Rails offers partial support for such passenger and
513+
freight units by allowing one wagon to include a bogie in its 3D model while the next
514+
wagon removes the bogie from its 3D model. Ideally, OR will then add an invisible bogie
515+
to the end of the wagon without the bogie to emulate "sharing" the bogie with the previous
516+
wagon.
517+
518+
However, this automatic system is limited. OR will check for wheels in the wagon's 3D
519+
model and will assume the wagon is articulated at one end if there are no wheels towards
520+
that end of the 3D model. This approach will only be used on 3D models with 3, 2, or 0 axles
521+
(the 1-axle case is excluded for compatibility reasons) and won't be used on locomotives.
522+
In some cases, this approach will result in false negative or false positive detection
523+
of articulation. Should the automatic articulation method not produce the expected track
524+
following behavior, it is now possible to manually define whether a wagon or engine
525+
should use the articulation behavior.
526+
527+
.. index::
528+
single: ORTSFrontArticulation
529+
single: ORTSRearArticulation
530+
531+
To forcibly enable the articulation behavior at the front of the rail vehicle, use
532+
``ORTSFrontArticulation ( 1 )`` and at the rear use ``ORTSRearArticulation ( 1 )``.
533+
Conversely, use ``ORTSFrontArticulation ( 0 )`` or ``ORTSRearArticulation ( 0 )`` to
534+
force disable articulation behavior. Articulation should generally be enabled on the
535+
'floating' end(s) of a vehicle, where a bogie or wheels are not present in the 3D
536+
model, and disabled on the end(s) that have wheels. Entering a value of -1 provides
537+
the default (automatic) behavior.
538+
508539
Freight animations and pickups
509540
==============================
510541

Source/Orts.Simulation/Simulation/RollingStocks/MSTSWagon.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,6 +1427,8 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
14271427
if (ShapeBoundingLimits.Maxes.Z < ShapeBoundingLimits.Mins.Z)
14281428
(ShapeBoundingLimits.Maxes.Z, ShapeBoundingLimits.Mins.Z) = (ShapeBoundingLimits.Mins.Z, ShapeBoundingLimits.Maxes.Z);
14291429
break;
1430+
case "wagon(ortsfrontarticulation": FrontArticulation = stf.ReadIntBlock(null); break;
1431+
case "wagon(ortsreararticulation": RearArticulation = stf.ReadIntBlock(null); break;
14301432
case "wagon(ortslengthbogiecentre": CarBogieCentreLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
14311433
case "wagon(ortslengthcarbody": CarBodyLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
14321434
case "wagon(ortslengthairhose": CarAirHoseLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
@@ -1454,13 +1456,13 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
14541456
InitialCentreOfGravityM.Y = stf.ReadFloat(STFReader.UNITS.Distance, 0);
14551457
InitialCentreOfGravityM.Z = stf.ReadFloat(STFReader.UNITS.Distance, 0);
14561458

1457-
if (Math.Abs(InitialCentreOfGravityM.Z) > 2)
1458-
{
1459-
STFException.TraceWarning(stf, string.Format("CentreOfGravity Z set to zero because value {0} outside range -2 to +2", InitialCentreOfGravityM.Z));
1460-
InitialCentreOfGravityM.Z = 0;
1461-
}
1459+
if (Math.Abs(InitialCentreOfGravityM.Z) > 2)
1460+
{
1461+
STFException.TraceWarning(stf, string.Format("CentreOfGravity Z set to zero because value {0} outside range -2 to +2", InitialCentreOfGravityM.Z));
1462+
InitialCentreOfGravityM.Z = 0;
1463+
}
14621464

1463-
stf.SkipRestOfBlock();
1465+
stf.SkipRestOfBlock();
14641466
}
14651467
else // User has entered a single value, only set the Y component to this value, leave other components unchanged
14661468
{

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

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ public static Interpolator SteamHeatBoilerFuelUsageGalukpH()
189189
public (Vector3 Mins, Vector3 Maxes) ShapeBoundingLimits;
190190
public bool AutoSize = false; // Are the dimensions of this wagon to be calculated automatically from the shape file?
191191
public Vector3 AutoSizeOffsetM;
192+
public int FrontArticulation = -1; // -1: Determine front articulation automatically, 0: Force no front articulation, 1: Force front articulation
193+
public int RearArticulation = -1; // -1: Determine rear articulation automatically, 0: Force no rear articulation, 1: Force rear articulation
192194
public float MassKG = 10000; // Mass in KG at runtime; coincides with InitialMassKG if there is no load and no ORTS freight anim
193195
public float InitialMassKG = 10000;
194196
public bool IsDriveable;
@@ -2927,34 +2929,36 @@ public void SetUpWheels()
29272929
// Decided to control what is sent to SetUpWheelsArticulation()by using
29282930
// WheelAxlesLoaded as a flag. This way, wagons that have to be processed are included
29292931
// and the rest left out.
2930-
bool articulatedFront = !WheelAxles.Any(a => a.OffsetM.Z < 0);
2931-
bool articulatedRear = !WheelAxles.Any(a => a.OffsetM.Z > 0);
2932-
var carIndex = Train.Cars.IndexOf(this);
2933-
//Certain locomotives are testing as articulated wagons for some reason.
2934-
if (WagonType != WagonTypes.Engine)
2935-
if (WheelAxles.Count != 1 && (articulatedFront || articulatedRear))
2936-
{
2937-
WheelAxlesLoaded = true;
2938-
SetUpWheelsArticulation(carIndex);
2939-
}
2932+
2933+
// Force articulation if stock is configured as such
2934+
// Otherwise, use default behavior which gives articulation if there are no axles forward/reareward on the model,
2935+
// disables articulation on engines, and only allows articulation with 3 or fewer axles, but not 1 axle
2936+
bool articulatedFront = (FrontArticulation == 1 ||
2937+
(FrontArticulation == -1 && !WheelAxles.Any(a => a.OffsetM.Z < 0) && WagonType != WagonTypes.Engine && WheelAxles.Count != 1 && WheelAxles.Count <= 3));
2938+
bool articulatedRear = (RearArticulation == 1 ||
2939+
(RearArticulation == -1 && !WheelAxles.Any(a => a.OffsetM.Z > 0) && WagonType != WagonTypes.Engine && WheelAxles.Count != 1 && WheelAxles.Count <= 3));
2940+
2941+
if (articulatedFront || articulatedRear)
2942+
{
2943+
WheelAxlesLoaded = true;
2944+
SetUpWheelsArticulation(articulatedFront, articulatedRear);
2945+
}
29402946
} // end SetUpWheels()
29412947

2942-
protected void SetUpWheelsArticulation(int carIndex)
2948+
protected void SetUpWheelsArticulation(bool front, bool rear)
29432949
{
29442950
// If there are no forward wheels, this car is articulated (joined
29452951
// to the car in front) at the front. Likewise for the rear.
2946-
bool articulatedFront = !WheelAxles.Any(a => a.OffsetM.Z < 0);
2947-
bool articulatedRear = !WheelAxles.Any(a => a.OffsetM.Z > 0);
29482952
// Original process originally used caused too many issues.
29492953
// The original process did include the below process of just using WheelAxles.Add
29502954
// if the initial test did not work. Since the below process is working without issues the
29512955
// original process was stripped down to what is below
2952-
if (articulatedFront || articulatedRear)
2956+
if (front || rear)
29532957
{
2954-
if (articulatedFront && WheelAxles.Count <= 3)
2958+
if (front)
29552959
WheelAxles.Add(new WheelAxle(new Vector3(0.0f, BogiePivotHeightM, -CarLengthM / 2.0f), 0, 0) { Part = Parts[0] });
29562960

2957-
if (articulatedRear && WheelAxles.Count <= 3)
2961+
if (rear)
29582962
WheelAxles.Add(new WheelAxle(new Vector3(0.0f, BogiePivotHeightM, CarLengthM / 2.0f), 0, 0) { Part = Parts[0] });
29592963

29602964
WheelAxles.Sort(WheelAxles[0]);

0 commit comments

Comments
 (0)