@@ -59,10 +59,10 @@ public class MSTSWagonViewer : TrainCarViewer
59
59
60
60
// Wheels are rotated by hand instead of in the shape file.
61
61
float WheelRotationR ;
62
- List < int > WheelPartIndexes = new List < int > ( ) ;
62
+ Dictionary < int , List < int > > WheelPartIndexes = new Dictionary < int , List < int > > ( ) ; // List of wheels attached to each axle
63
63
64
64
// Everything else is animated through the shape file.
65
- AnimatedPart RunningGear ;
65
+ Dictionary < int , AnimatedPart > RunningGears ; // List of animated parts linked to every axle
66
66
AnimatedPart Pantograph1 ;
67
67
AnimatedPart Pantograph2 ;
68
68
AnimatedPart Pantograph3 ;
@@ -313,7 +313,12 @@ from data in effect.Value
313
313
if ( car . InteriorShapeFileName != null )
314
314
InteriorShape = new AnimatedShape ( viewer , wagonFolderSlash + car . InteriorShapeFileName + '\0 ' + wagonFolderSlash , car . WorldPosition , ShapeFlags . Interior , 30.0f ) ;
315
315
316
- RunningGear = new AnimatedPart ( TrainCarShape ) ;
316
+ RunningGears = new Dictionary < int , AnimatedPart > ( ) ;
317
+ for ( int i = - 1 ; i < car . LocomotiveAxles . Count ; i ++ )
318
+ {
319
+ RunningGears [ i ] = new AnimatedPart ( TrainCarShape ) ;
320
+ WheelPartIndexes [ i ] = new List < int > ( ) ;
321
+ }
317
322
Pantograph1 = new AnimatedPart ( TrainCarShape ) ;
318
323
Pantograph2 = new AnimatedPart ( TrainCarShape ) ;
319
324
Pantograph3 = new AnimatedPart ( TrainCarShape ) ;
@@ -424,6 +429,15 @@ void MatchMatrixToPart(MSTSWagon car, int matrix, int bogieMatrix)
424
429
var matrixName = TrainCarShape . SharedShape . MatrixNames [ matrix ] . ToUpper ( ) ;
425
430
// Gate all RunningGearPartIndexes on this!
426
431
var matrixAnimated = TrainCarShape . SharedShape . Animations != null && TrainCarShape . SharedShape . Animations . Count > 0 && TrainCarShape . SharedShape . Animations [ 0 ] . anim_nodes . Count > matrix && TrainCarShape . SharedShape . Animations [ 0 ] . anim_nodes [ matrix ] . controllers . Count > 0 ;
432
+ int ? LinkedAxleIndex = null ;
433
+ for ( int i = 0 ; i < car . LocomotiveAxles . Count ; i ++ )
434
+ {
435
+ if ( car . LocomotiveAxles [ i ] . AnimatedParts . Contains ( matrixName ) )
436
+ {
437
+ LinkedAxleIndex = i ;
438
+ break ;
439
+ }
440
+ }
427
441
if ( matrixName . StartsWith ( "WHEELS" ) && ( matrixName . Length == 7 || matrixName . Length == 8 || matrixName . Length == 9 ) )
428
442
{
429
443
// Standard WHEELS length would be 8 to test for WHEELS11. Came across WHEELS tag that used a period(.) between the last 2 numbers, changing max length to 9.
@@ -441,15 +455,15 @@ void MatchMatrixToPart(MSTSWagon car, int matrix, int bogieMatrix)
441
455
if ( matrixName . Length == 8 || matrixName . Length == 9 )
442
456
Int32 . TryParse ( matrixName . Substring ( 6 , 1 ) , out id ) ;
443
457
if ( matrixName . Length == 8 || matrixName . Length == 9 || ! matrixAnimated )
444
- WheelPartIndexes . Add ( matrix ) ;
458
+ WheelPartIndexes [ LinkedAxleIndex ?? - 1 ] . Add ( matrix ) ;
445
459
else
446
- RunningGear . AddMatrix ( matrix ) ;
460
+ RunningGears [ LinkedAxleIndex ?? ( car . LocomotiveAxles . Count > 0 ? 0 : - 1 ) ] . AddMatrix ( matrix ) ;
447
461
var pmatrix = TrainCarShape . SharedShape . GetParentMatrix ( matrix ) ;
448
462
car . AddWheelSet ( m . M43 , id , pmatrix , matrixName . ToString ( ) , bogie1Axles , bogie2Axles ) ;
449
463
}
450
464
// Standard wheels are processed above, but wheels used as animated fans that are greater than 3m are processed here.
451
465
else
452
- RunningGear . AddMatrix ( matrix ) ;
466
+ RunningGears [ LinkedAxleIndex ?? - 1 ] . AddMatrix ( matrix ) ;
453
467
}
454
468
else if ( matrixName . StartsWith ( "BOGIE" ) && matrixName . Length <= 6 ) //BOGIE1 is valid, BOGIE11 is not, it is used by some modelers to indicate this is part of bogie1
455
469
{
@@ -578,7 +592,7 @@ void MatchMatrixToPart(MSTSWagon car, int matrix, int bogieMatrix)
578
592
else
579
593
{
580
594
if ( matrixAnimated && matrix != 0 )
581
- RunningGear . AddMatrix ( matrix ) ;
595
+ RunningGears [ LinkedAxleIndex ?? ( car . LocomotiveAxles . Count > 0 ? 0 : - 1 ) ] . AddMatrix ( matrix ) ;
582
596
583
597
for ( var i = 0 ; i < TrainCarShape . Hierarchy . Length ; i ++ )
584
598
if ( TrainCarShape . Hierarchy [ i ] == matrix )
@@ -709,68 +723,80 @@ private void UpdateAnimation(RenderFrame frame, ElapsedTime elapsedTime)
709
723
{
710
724
711
725
float distanceTravelledM = 0.0f ; // Distance travelled by non-driven wheels
712
- float distanceTravelledDrivenM = 0.0f ; // Distance travelled by driven wheels
713
726
float AnimationWheelRadiusM = MSTSWagon . WheelRadiusM ; // Radius of non driven wheels
714
727
float AnimationDriveWheelRadiusM = MSTSWagon . DriverWheelRadiusM ; // Radius of driven wheels
715
728
716
729
if ( MSTSWagon . IsDriveable && MSTSWagon . Simulator . UseAdvancedAdhesion && ! MSTSWagon . Simulator . Settings . SimpleControlPhysics )
717
730
{
731
+ var loco = MSTSWagon as MSTSLocomotive ;
718
732
//TODO: next code line has been modified to flip trainset physics in order to get viewing direction coincident with loco direction when using rear cab.
719
733
// To achieve the same result with other means, without flipping trainset physics, the line should be changed as follows:
720
734
// distanceTravelledM = MSTSWagon.WheelSpeedMpS * elapsedTime.ClockSeconds;
721
-
722
- distanceTravelledM = ( ( MSTSWagon . Train != null && MSTSWagon . Train . IsPlayerDriven && ( ( MSTSLocomotive ) MSTSWagon ) . UsingRearCab ) ? - 1 : 1 ) * MSTSWagon . WheelSpeedMpS * elapsedTime . ClockSeconds ;
723
- if ( Car . EngineType == Orts . Simulation . RollingStocks . TrainCar . EngineTypes . Steam )
735
+ distanceTravelledM = ( ( MSTSWagon . Train != null && MSTSWagon . Train . IsPlayerDriven && loco . UsingRearCab ) ? - 1 : 1 ) * MSTSWagon . WheelSpeedMpS * elapsedTime . ClockSeconds ;
736
+ if ( Car . BrakeSkid && ! loco . DriveWheelOnlyBrakes ) distanceTravelledM = 0 ;
737
+ foreach ( var kvp in RunningGears )
724
738
{
725
- distanceTravelledDrivenM = ( ( MSTSWagon . Train != null && MSTSWagon . Train . IsPlayerDriven && ( ( MSTSLocomotive ) MSTSWagon ) . UsingRearCab ) ? - 1 : 1 ) * MSTSWagon . WheelSpeedSlipMpS * elapsedTime . ClockSeconds ;
739
+ if ( ! kvp . Value . Empty ( ) )
740
+ {
741
+ var axle = kvp . Key >= 0 && kvp . Key < loco . LocomotiveAxles . Count ? loco . LocomotiveAxles [ kvp . Key ] : null ;
742
+ if ( axle != null )
743
+ //TODO: next code line has been modified to flip trainset physics in order to get viewing direction coincident with loco direction when using rear cab.
744
+ kvp . Value . UpdateLoop ( ( ( MSTSWagon . Train != null && MSTSWagon . Train . IsPlayerDriven && loco . UsingRearCab ) ? - 1 : 1 ) * axle . AxleSpeedMpS * elapsedTime . ClockSeconds / MathHelper . TwoPi / axle . WheelRadiusM ) ;
745
+ else if ( AnimationDriveWheelRadiusM > 0.001 )
746
+ kvp . Value . UpdateLoop ( distanceTravelledM / MathHelper . TwoPi / AnimationDriveWheelRadiusM ) ;
747
+ }
748
+
726
749
}
727
- else // Other driveable rolling stocked.
750
+ foreach ( var kvp in WheelPartIndexes )
728
751
{
729
- distanceTravelledDrivenM = ( ( MSTSWagon . Train != null && MSTSWagon . Train . IsPlayerDriven && ( ( MSTSLocomotive ) MSTSWagon ) . UsingRearCab ) ? - 1 : 1 ) * MSTSWagon . WheelSpeedMpS * elapsedTime . ClockSeconds ;
752
+ var axle = kvp . Key < loco . LocomotiveAxles . Count && kvp . Key >= 0 ? loco . LocomotiveAxles [ kvp . Key ] : ( Car . EngineType == TrainCar . EngineTypes . Steam ? null : loco . LocomotiveAxles [ 0 ] ) ;
753
+ Matrix wheelRotationMatrix ;
754
+ if ( axle != null )
755
+ {
756
+ //TODO: next code line has been modified to flip trainset physics in order to get viewing direction coincident with loco direction when using rear cab.
757
+ wheelRotationMatrix = Matrix . CreateRotationX ( ( ( MSTSWagon . Train != null && MSTSWagon . Train . IsPlayerDriven && loco . UsingRearCab ) ? - 1 : 1 ) * - axle . AxlePositionRad ) ;
758
+ }
759
+ else
760
+ {
761
+ var rotationalDistanceR = distanceTravelledM / AnimationWheelRadiusM ; // in radians
762
+ WheelRotationR = MathHelper . WrapAngle ( WheelRotationR - rotationalDistanceR ) ;
763
+ wheelRotationMatrix = Matrix . CreateRotationX ( WheelRotationR ) ;
764
+ }
765
+ foreach ( var iMatrix in kvp . Value )
766
+ {
767
+ TrainCarShape . XNAMatrices [ iMatrix ] = wheelRotationMatrix * TrainCarShape . SharedShape . Matrices [ iMatrix ] ;
768
+ }
730
769
}
731
770
}
732
771
else // set values for simple adhesion
733
772
{
734
773
distanceTravelledM = ( ( MSTSWagon . IsDriveable && MSTSWagon . Train != null && MSTSWagon . Train . IsPlayerDriven && ( ( MSTSLocomotive ) MSTSWagon ) . UsingRearCab ) ? - 1 : 1 ) * MSTSWagon . SpeedMpS * elapsedTime . ClockSeconds ;
735
- distanceTravelledDrivenM = distanceTravelledM ;
736
- }
737
-
738
- if ( Car . BrakeSkid ) // if car wheels are skidding because of brakes locking wheels up then stop wheels rotating.
739
- {
740
- // Temporary bug fix (CSantucci)
741
- if ( MSTSWagon is MSTSLocomotive loco && loco . DriveWheelOnlyBrakes )
774
+ if ( Car . BrakeSkid ) distanceTravelledM = 0 ;
775
+ foreach ( var kvp in RunningGears )
742
776
{
743
- distanceTravelledDrivenM = 0.0f ;
777
+ if ( ! kvp . Value . Empty ( ) && AnimationDriveWheelRadiusM > 0.001 )
778
+ kvp . Value . UpdateLoop ( distanceTravelledM / MathHelper . TwoPi / AnimationDriveWheelRadiusM ) ;
744
779
}
745
- else
780
+ // Wheel rotation (animation) - for non-drive wheels in steam locomotives and all wheels in other stock
781
+ if ( WheelPartIndexes . Count > 0 )
746
782
{
747
- distanceTravelledM = 0.0f ;
748
- distanceTravelledDrivenM = 0.0f ;
783
+ var rotationalDistanceR = distanceTravelledM / AnimationWheelRadiusM ; // in radians
784
+ WheelRotationR = MathHelper . WrapAngle ( WheelRotationR - rotationalDistanceR ) ;
785
+ var wheelRotationMatrix = Matrix . CreateRotationX ( WheelRotationR ) ;
786
+ foreach ( var kvp in WheelPartIndexes )
787
+ {
788
+ foreach ( var iMatrix in kvp . Value )
789
+ {
790
+ TrainCarShape . XNAMatrices [ iMatrix ] = wheelRotationMatrix * TrainCarShape . SharedShape . Matrices [ iMatrix ] ;
791
+ }
792
+ }
749
793
}
750
794
}
751
795
752
- // Running gear and drive wheel rotation (animation) in steam locomotives
753
- if ( ! RunningGear . Empty ( ) && AnimationDriveWheelRadiusM > 0.001 )
754
- RunningGear . UpdateLoop ( distanceTravelledDrivenM / MathHelper . TwoPi / AnimationDriveWheelRadiusM ) ;
755
-
756
-
757
- // Wheel rotation (animation) - for non-drive wheels in steam locomotives and all wheels in other stock
758
- if ( WheelPartIndexes . Count > 0 )
759
- {
760
- var wheelCircumferenceM = MathHelper . TwoPi * AnimationWheelRadiusM ;
761
- var rotationalDistanceR = MathHelper . TwoPi * distanceTravelledM / wheelCircumferenceM ; // in radians
762
- WheelRotationR = MathHelper . WrapAngle ( WheelRotationR - rotationalDistanceR ) ;
763
- var wheelRotationMatrix = Matrix . CreateRotationX ( WheelRotationR ) ;
764
- foreach ( var iMatrix in WheelPartIndexes )
765
- {
766
- TrainCarShape . XNAMatrices [ iMatrix ] = wheelRotationMatrix * TrainCarShape . SharedShape . Matrices [ iMatrix ] ;
767
- }
768
- }
769
-
770
796
#if DEBUG_WHEEL_ANIMATION
771
797
772
798
Trace . TraceInformation ( "========================== Debug Animation in MSTSWagonViewer.cs ==========================================" ) ;
773
- Trace . TraceInformation ( "Slip speed - Car ID: {0} WheelDistance: {1} SlipWheelDistance: {2} " , Car . CarID , distanceTravelledM , distanceTravelledDrivenM ) ;
799
+ Trace . TraceInformation ( "Slip speed - Car ID: {0} WheelDistance: {1}" , Car . CarID , distanceTravelledM ) ;
774
800
Trace . TraceInformation ( "Wag Speed - Wheelspeed: {0} Slip: {1} Train: {2}" , MSTSWagon . WheelSpeedMpS , MSTSWagon . WheelSpeedSlipMpS , MSTSWagon . SpeedMpS ) ;
775
801
Trace . TraceInformation ( "Wheel Radius - DriveWheel: {0} NonDriveWheel: {1}" , AnimationDriveWheelRadiusM , AnimationWheelRadiusM ) ;
776
802
0 commit comments