@@ -458,91 +458,66 @@ public virtual void LoadFromWagFile(string wagFilePath)
458458 // But my hubris has decided we can use for the shape for things other than graphics - Phillip
459459 ShapeFile wagShape = new ShapeFile ( wagonFolderSlash + MainShapeFileName , true ) ;
460460
461- Vector3 mins = new Vector3 ( float . PositiveInfinity ) ;
462- Vector3 maxes = new Vector3 ( float . NegativeInfinity ) ;
461+ ( Vector3 mainMins , Vector3 mainMaxes ) = wagShape . GetBoundingLimits ( ) ;
463462
464- // Determine size specifically for LOD0's (nearest LOD) sub objects
465- foreach ( sub_object subObj in wagShape . shape . lod_controls [ 0 ] . distance_levels [ 0 ] . sub_objects )
463+ // Repeat for MSTS freight animation bounds
464+ if ( ! string . IsNullOrEmpty ( FreightShapeFileName ) )
466465 {
467- // Use vertex sets in the sub object to determine which vertices to check
468- foreach ( vertex_set vSet in subObj . vertex_sets )
469- {
470- // Use the vertex state used by this vertex set to determine the matrix used
471- vtx_state vState = wagShape . shape . vtx_states [ vSet . VtxStateIdx ] ;
466+ ShapeFile freightShape = new ShapeFile ( wagonFolderSlash + FreightShapeFileName , true ) ;
472467
473- // The index of the matrix used by this vertex state
474- int mIndex = vState . imatrix ;
468+ ( Vector3 freightMins , Vector3 freightMaxes ) = freightShape . GetBoundingLimits ( ) ;
475469
476- // The 'actual' XNA matrix used to determine the vertex transformation
477- Matrix mat = Matrix . Identity ;
470+ // MSTS freight animations don't have offsets, so can be simply compared
471+ mainMins = Vector3 . Min ( mainMins , freightMins ) ;
472+ mainMaxes = Vector3 . Max ( mainMaxes , freightMaxes ) ;
473+ }
478474
479- // Determine the overall transformation matrix from the root to the current matrix by following the hierarchy
480- do
475+ // And also repeat for ORTS freight animations
476+ if ( FreightAnimations != null )
477+ {
478+ foreach ( var freightAnim in FreightAnimations . Animations )
479+ {
480+ // We will ignore freight animations not attached to the main shape object for simplicity
481+ if ( ! string . IsNullOrEmpty ( freightAnim . ShapeFileName ) && freightAnim . ShapeIndex <= 0 && string . IsNullOrEmpty ( freightAnim . ShapeHierarchy ) )
481482 {
482- matrix m = wagShape . shape . matrices [ mIndex ] ;
483+ ShapeFile ortsFreightShape = new ShapeFile ( wagonFolderSlash + freightAnim . ShapeFileName , true ) ;
484+
485+ ( Vector3 ortsFreightMins , Vector3 ortsFreightMaxes ) = ortsFreightShape . GetBoundingLimits ( ) ;
483486
484- // Convert the shape file matrix to an XNA matrix
485- Matrix matTransform = new Matrix
487+ // Account for flipped freight animation by inverting x and z components
488+ if ( freightAnim . Flipped )
486489 {
487- M11 = m . AX ,
488- M12 = m . AY ,
489- M13 = m . AZ , //
490- M14 = 0 ,
491- M21 = m . BX ,
492- M22 = m . BY ,
493- M23 = m . BZ , //
494- M24 = 0 ,
495- M31 = m . CX , //
496- M32 = m . CY , //
497- M33 = m . CZ ,
498- M34 = 0 ,
499- M41 = m . DX ,
500- M42 = m . DY ,
501- M43 = m . DZ , //
502- M44 = 1.0f
503- } ;
504-
505- // Add the effect of this transformation to the overall transformation
506- mat = mat * matTransform ;
507-
508- // Determine the index of the next highest matrix in the hierarchy
509- mIndex = wagShape . shape . lod_controls [ 0 ] . distance_levels [ 0 ] . distance_level_header . hierarchy [ mIndex ] ;
510- } // Keep calculating until we have calculated the root, or until a loop is encountered
511- while ( mIndex > - 1 && mIndex != vState . imatrix && mIndex < wagShape . shape . matrices . Count ) ;
512-
513- // Determine position of every vertex in this set from point position and tranformed by the matrix
514- for ( int i = vSet . StartVtxIdx ; i < vSet . StartVtxIdx + vSet . VtxCount ; i ++ )
515- {
516- // Determine vertex position from vertex index and point index
517- point p = wagShape . shape . points [ subObj . vertices [ i ] . ipoint ] ;
518- Vector3 pPos = new Vector3 ( p . X , p . Y , p . Z ) ;
519-
520- pPos = Vector3 . Transform ( pPos , mat ) ;
521-
522- if ( pPos . X < mins . X )
523- mins . X = pPos . X ;
524- if ( pPos . X > maxes . X )
525- maxes . X = pPos . X ;
526-
527- if ( pPos . Y < mins . Y )
528- mins . Y = pPos . Y ;
529- if ( pPos . Y > maxes . Y )
530- maxes . Y = pPos . Y ;
531-
532- if ( pPos . Z < mins . Z )
533- mins . Z = pPos . Z ;
534- if ( pPos . Z > maxes . Z )
535- maxes . Z = pPos . Z ;
490+ Vector3 temp = ortsFreightMins ;
491+ temp . X *= - 1 ;
492+ temp . Y = ortsFreightMaxes . Y ;
493+ temp . Z *= - 1 ;
494+
495+ ortsFreightMaxes . X *= - 1 ;
496+ ortsFreightMaxes . Y = ortsFreightMins . Y ;
497+ ortsFreightMaxes . Z *= - 1 ;
498+
499+ ortsFreightMins = ortsFreightMaxes ;
500+ ortsFreightMaxes = temp ;
501+ }
502+
503+ // Account for offsets
504+ // Z-axis offset is inverted to match MSTS coordinate system
505+ Vector3 modOffset = new Vector3 ( freightAnim . Offset . X , freightAnim . Offset . Y , - freightAnim . Offset . Z ) ;
506+ ortsFreightMins += modOffset ;
507+ ortsFreightMaxes += modOffset ;
508+
509+ mainMins = Vector3 . Min ( mainMins , ortsFreightMins ) ;
510+ mainMaxes = Vector3 . Max ( mainMaxes , ortsFreightMaxes ) ;
536511 }
537512 }
538513 }
539514
540515 // Set dimensions of wagon if configured as such
541516 if ( AutoSize )
542517 {
543- CarWidthM = Math . Max ( ( maxes . X - mins . X ) + AutoWidthOffsetM , 0.1f ) ;
544- CarHeightM = Math . Max ( ( maxes . Y - mins . Y ) + AutoHeightOffsetM , 0.1f ) ;
545- CarLengthM = Math . Max ( ( maxes . Z - mins . Z ) + AutoLengthOffsetM , 0.1f ) ;
518+ CarWidthM = Math . Max ( ( mainMaxes . X - mainMins . X ) + AutoWidthOffsetM , 0.1f ) ;
519+ CarHeightM = Math . Max ( ( mainMaxes . Y - mainMins . Y ) + AutoHeightOffsetM , 0.1f ) ;
520+ CarLengthM = Math . Max ( ( mainMaxes . Z - mainMins . Z ) + AutoLengthOffsetM , 0.1f ) ;
546521
547522 if ( Simulator . Settings . VerboseConfigurationMessages )
548523 {
@@ -552,9 +527,9 @@ public virtual void LoadFromWagFile(string wagFilePath)
552527 FormatStrings . FormatVeryShortDistanceDisplay ( AutoLengthOffsetM , IsMetric ) ) ;
553528 Trace . TraceInformation ( "Main shape file {0} calculated to be {1} wide, {2} tall, and {3} long. " +
554529 "Resulting Size ( ) is {4} wide, {5} tall, and {6} long.\n " , MainShapeFileName ,
555- FormatStrings . FormatVeryShortDistanceDisplay ( ( maxes . X - mins . X ) , IsMetric ) ,
556- FormatStrings . FormatVeryShortDistanceDisplay ( ( maxes . Y - mins . Y ) , IsMetric ) ,
557- FormatStrings . FormatVeryShortDistanceDisplay ( ( maxes . Z - mins . Z ) , IsMetric ) ,
530+ FormatStrings . FormatVeryShortDistanceDisplay ( ( mainMaxes . X - mainMins . X ) , IsMetric ) ,
531+ FormatStrings . FormatVeryShortDistanceDisplay ( ( mainMaxes . Y - mainMins . Y ) , IsMetric ) ,
532+ FormatStrings . FormatVeryShortDistanceDisplay ( ( mainMaxes . Z - mainMins . Z ) , IsMetric ) ,
558533 FormatStrings . FormatVeryShortDistanceDisplay ( CarWidthM , IsMetric ) ,
559534 FormatStrings . FormatVeryShortDistanceDisplay ( CarHeightM , IsMetric ) ,
560535 FormatStrings . FormatVeryShortDistanceDisplay ( CarLengthM , IsMetric ) ) ;
@@ -564,21 +539,21 @@ public virtual void LoadFromWagFile(string wagFilePath)
564539 // Automatically determine the center of gravity offset required to perfectly center the shape (lengthwise)
565540 if ( AutoCenter )
566541 {
567- InitialCentreOfGravityM . Z = ( maxes . Z + mins . Z ) / 2.0f ;
542+ InitialCentreOfGravityM . Z = ( mainMaxes . Z + mainMins . Z ) / 2.0f ;
568543
569544 if ( Simulator . Settings . VerboseConfigurationMessages )
570545 {
571546 Trace . TraceInformation ( "Rolling stock {0} CoG z-value automatically calculated using ORTSAutoCenter." , shortPath ) ;
572547 if ( Math . Abs ( InitialCentreOfGravityM . Z ) < 0.0001f )
573548 Trace . TraceInformation ( "Main shape file {0} bounds calculated to be {1} to {2}. Shape is already centered, CoG offset reset to zero.\n " ,
574549 MainShapeFileName ,
575- FormatStrings . FormatVeryShortDistanceDisplay ( mins . Z , IsMetric ) ,
576- FormatStrings . FormatVeryShortDistanceDisplay ( maxes . Z , IsMetric ) ) ;
550+ FormatStrings . FormatVeryShortDistanceDisplay ( mainMins . Z , IsMetric ) ,
551+ FormatStrings . FormatVeryShortDistanceDisplay ( mainMaxes . Z , IsMetric ) ) ;
577552 else
578553 Trace . TraceInformation ( "Main shape file {0} bounds calculated to be {1} to {2}. CoG offset used to center shape is {0}.\n " ,
579554 MainShapeFileName ,
580- FormatStrings . FormatVeryShortDistanceDisplay ( mins . Z , IsMetric ) ,
581- FormatStrings . FormatVeryShortDistanceDisplay ( maxes . Z , IsMetric ) ,
555+ FormatStrings . FormatVeryShortDistanceDisplay ( mainMins . Z , IsMetric ) ,
556+ FormatStrings . FormatVeryShortDistanceDisplay ( mainMaxes . Z , IsMetric ) ,
582557 FormatStrings . FormatVeryShortDistanceDisplay ( InitialCentreOfGravityM . Z , IsMetric ) ) ;
583558 }
584559 }
@@ -1393,7 +1368,7 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
13931368 case "wagon(ortscenterofgravity_z" :
13941369 case "wagon(ortscentreofgravity_z" : InitialCentreOfGravityM . Z = stf . ReadFloatBlock ( STFReader . UNITS . Distance , null ) ; break ;
13951370 case "wagon(ortsautocentre" :
1396- case "wagon(ortsautocenter" : AutoCenter = stf . ReadBoolBlock ( false ) ; break ;
1371+ case "wagon(ortsautocenter" : AutoCenter = stf . ReadBoolBlock ( true ) ; break ;
13971372 case "wagon(ortsunbalancedsuperelevation" : MaxUnbalancedSuperElevationM = stf . ReadFloatBlock ( STFReader . UNITS . Distance , null ) ; break ;
13981373 case "wagon(ortsrigidwheelbase" :
13991374 stf . MustMatch ( "(" ) ;
0 commit comments