Skip to content

Commit 80b81f4

Browse files
committed
Allow manually defining articulation
1 parent df7bf1a commit 80b81f4

File tree

3 files changed

+51
-16
lines changed

3 files changed

+51
-16
lines changed

Source/Documentation/Manual/features-rollingstock.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,35 @@ OR supports tilting trains. A train tilts when its .con file name contains the
403403

404404
.. image:: images/features-tilting.png
405405

406+
Advanced articulation control
407+
-----------------------------
408+
409+
A wide variety of modern rolling stock uses articulation, in which multiple rail vehicles
410+
share a single "Jacobs Bogie". Open Rails offers partial support for such passenger and
411+
freight units by allowing one wagon to include a bogie in its 3D model while the next
412+
wagon removes the bogie from its 3D model. Ideally, OR will then add an invisible bogie
413+
to the end of the wagon without the bogie to emulate "sharing" the bogie with the previous
414+
wagon.
415+
416+
However, this automatic system is limited. OR will check for wheels in the wagon's 3D
417+
model and will assume the wagon is articulated at one end if there are no wheels towards
418+
that end of the 3D model. This approach will only be used on 3D models with 3, 2, or 0 axles
419+
(the 1-axle case is excluded for compatibility reasons) and won't be used on locomotives.
420+
In some cases, this approach will result in false negative or false positive detection
421+
of articulation. Should the automatic articulation method not produce the expected track
422+
following behavior, it is now possible to manually define whether a wagon or engine
423+
should use the articulation behavior.
424+
425+
.. index::
426+
single: ORTSFrontArticulation
427+
single: ORTSRearArticulation
428+
429+
To forcibly enable the articulation behavior at the front of the rail vehicle, use
430+
``ORTSFrontArticulation ( 1 )`` and at the rear use ``ORTSRearArticulation ( 1 )``.
431+
Conversely, use ``ORTSFrontArticulation ( 0 )`` or ``ORTSRearArticulation ( 0 )`` to
432+
force disable articulation behavior. Entering a value of -1 provides the default
433+
automatic behavior.
434+
406435
Freight animations and pickups
407436
==============================
408437

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,8 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
12031203
CarLengthM = stf.ReadFloat(STFReader.UNITS.Distance, null);
12041204
stf.SkipRestOfBlock();
12051205
break;
1206+
case "wagon(ortsfrontarticulation": FrontArticulation = stf.ReadIntBlock(null); break;
1207+
case "wagon(ortsreararticulation": RearArticulation = stf.ReadIntBlock(null); break;
12061208
case "wagon(ortslengthbogiecentre": CarBogieCentreLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
12071209
case "wagon(ortslengthcarbody": CarBodyLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
12081210
case "wagon(ortslengthairhose": CarAirHoseLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;

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

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ public static Interpolator SteamHeatBoilerFuelUsageGalukpH()
187187
public float CarWidthM = 2.5f;
188188
public float CarLengthM = 40; // derived classes must overwrite these defaults
189189
public float CarHeightM = 4; // derived classes must overwrite these defaults
190+
public int FrontArticulation = -1; // -1: Determine front articulation automatically, 0: Force no front articulation, 1: Force front articulation
191+
public int RearArticulation = -1; // -1: Determine rear articulation automatically, 0: Force no rear articulation, 1: Force rear articulation
190192
public float MassKG = 10000; // Mass in KG at runtime; coincides with InitialMassKG if there is no load and no ORTS freight anim
191193
public float InitialMassKG = 10000;
192194
public bool IsDriveable;
@@ -2731,34 +2733,36 @@ public void SetUpWheels()
27312733
// Decided to control what is sent to SetUpWheelsArticulation()by using
27322734
// WheelAxlesLoaded as a flag. This way, wagons that have to be processed are included
27332735
// and the rest left out.
2734-
bool articulatedFront = !WheelAxles.Any(a => a.OffsetM.Z < 0);
2735-
bool articulatedRear = !WheelAxles.Any(a => a.OffsetM.Z > 0);
2736-
var carIndex = Train.Cars.IndexOf(this);
2737-
//Certain locomotives are testing as articulated wagons for some reason.
2738-
if (WagonType != WagonTypes.Engine)
2739-
if (WheelAxles.Count != 1 && (articulatedFront || articulatedRear))
2740-
{
2741-
WheelAxlesLoaded = true;
2742-
SetUpWheelsArticulation(carIndex);
2743-
}
2736+
2737+
// Force articulation if stock is configured as such
2738+
// Otherwise, use default behavior which gives articulation if there are no axles forward/reareward on the mode,
2739+
// disables articulation on engines, and only allows articulation with 3 or fewer axles, but not 1 axle
2740+
bool articulatedFront = (FrontArticulation == 1 ||
2741+
(FrontArticulation == -1 && !WheelAxles.Any(a => a.OffsetM.Z < 0) && WagonType != WagonTypes.Engine && WheelAxles.Count != 1 && WheelAxles.Count <= 3));
2742+
bool articulatedRear = (RearArticulation == 1 ||
2743+
(RearArticulation == -1 && !WheelAxles.Any(a => a.OffsetM.Z > 0) && WagonType != WagonTypes.Engine && WheelAxles.Count != 1 && WheelAxles.Count <= 3));
2744+
2745+
if (articulatedFront || articulatedRear)
2746+
{
2747+
WheelAxlesLoaded = true;
2748+
SetUpWheelsArticulation(articulatedFront, articulatedRear);
2749+
}
27442750
} // end SetUpWheels()
27452751

2746-
protected void SetUpWheelsArticulation(int carIndex)
2752+
protected void SetUpWheelsArticulation(bool front, bool rear)
27472753
{
27482754
// If there are no forward wheels, this car is articulated (joined
27492755
// to the car in front) at the front. Likewise for the rear.
2750-
bool articulatedFront = !WheelAxles.Any(a => a.OffsetM.Z < 0);
2751-
bool articulatedRear = !WheelAxles.Any(a => a.OffsetM.Z > 0);
27522756
// Original process originally used caused too many issues.
27532757
// The original process did include the below process of just using WheelAxles.Add
27542758
// if the initial test did not work. Since the below process is working without issues the
27552759
// original process was stripped down to what is below
2756-
if (articulatedFront || articulatedRear)
2760+
if (front || rear)
27572761
{
2758-
if (articulatedFront && WheelAxles.Count <= 3)
2762+
if (front)
27592763
WheelAxles.Add(new WheelAxle(new Vector3(0.0f, BogiePivotHeightM, -CarLengthM / 2.0f), 0, 0) { Part = Parts[0] });
27602764

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

27642768
WheelAxles.Sort(WheelAxles[0]);

0 commit comments

Comments
 (0)