Skip to content

Commit 92c74ef

Browse files
committed
Clean up DecomposeStaticSuperElevation, improve support for unusual track shapes
1 parent 31fd7d2 commit 92c74ef

File tree

1 file changed

+23
-34
lines changed

1 file changed

+23
-34
lines changed

Diff for: Source/RunActivity/Viewer3D/SuperElevation.cs

+23-34
Original file line numberDiff line numberDiff line change
@@ -59,39 +59,34 @@ public static bool DecomposeStaticSuperElevation(Viewer viewer, TrackObj trackOb
5959
// each subsection. The rotation component changes only in heading. The translation
6060
// component steps along the path to reflect the root of each subsection.
6161

62-
TrackShape shape;
63-
6462
bool dontRender = false; // Should this shape be left as a static object?
63+
bool removePhys = false; // Should superelevation physics be removed from this object?
6564
SectionIdx[] SectionIdxs;
6665

67-
try
66+
// Using the track object, determine the track sections
67+
// Most track sections can be recovered directly from a TrackShape object
68+
if (viewer.Simulator.TSectionDat.TrackShapes.TryGetValue(trackObj.SectionIdx, out TrackShape shape))
6869
{
69-
shape = viewer.Simulator.TSectionDat.TrackShapes.Get(trackObj.SectionIdx);
70-
7170
if (shape.RoadShape)
7271
return false; // Roads don't use superelevation, no use in processing them.
7372

7473
// Can't render superelevation on tunnel shapes
7574
dontRender = shape.TunnelShape;
75+
// Can't render superelevation and shouldn't have physics superelevation on junctions and crossovers
76+
dontRender |= removePhys = (shape.NumPaths > 1 && shape.ClearanceDistance != 0);
7677
SectionIdxs = shape.SectionIdxs;
77-
}
78-
catch (Exception)
78+
} // Some route-specific shapes (DynaTrax) won't be populated in the TrackShapes list, check the TrackPaths list
79+
else if (viewer.Simulator.TSectionDat.TSectionIdx.TrackPaths.TryGetValue(trackObj.SectionIdx, out TrackPath path))
7980
{
80-
// Some route-specific shapes (DynaTrax) won't be populated in the TrackShapes list, check the TrackPaths list
81-
if (viewer.Simulator.TSectionDat.TSectionIdx.TrackPaths.TryGetValue(trackObj.SectionIdx, out TrackPath path))
82-
{
83-
// Translate given data into a SectionIdx object that the rest of the method can interpret
84-
// Assumptions: Each piece of DynaTrax is a single section with origin 0, 0, 0 and 0 angle,
85-
// and the entire section of DynaTrax is defined by the track sections given in the track path
86-
SectionIdxs = new SectionIdx[1];
87-
SectionIdxs[0] = new SectionIdx(path);
88-
}
89-
else
90-
return false; // Not enough info, won't be able to render with superelevation
81+
// Translate given data into a SectionIdx object that the rest of the method can interpret
82+
// Assumptions: Each piece of DynaTrax is a single section with origin 0, 0, 0 and 0 angle,
83+
// and the entire section of DynaTrax is defined by the track sections given in the track path
84+
SectionIdxs = new SectionIdx[1];
85+
SectionIdxs[0] = new SectionIdx(path);
9186
}
87+
else
88+
return false; // Can't find section info, won't be able to render with superelevation
9289

93-
// Sometimes junctions get caught here, physics superelevation should be removed for those as well
94-
bool removePhys = false;
9590
// 0 = centered, positive = rotation axis moves to inside of curve, negative = moves to outside of curve
9691
float rollOffsetM = 0.0f;
9792

@@ -135,27 +130,18 @@ public static bool DecomposeStaticSuperElevation(Viewer viewer, TrackObj trackOb
135130
// Iterate through all subsections
136131
foreach (SectionIdx id in SectionIdxs)
137132
{
138-
// If section angle offset is not zero, that means we have a complicated track shape (eg: junction)
139-
// If any sections have identical starting conditions, that means we have a junction
140-
// These should not be rendered using superelevation
141-
if (!dontRender && id.A != 0.0f)
142-
dontRender = true;
143-
if (!dontRender && !removePhys
144-
&& SectionIdxs.Any(idx => idx != id && idx.X == id.X && idx.Y == id.Y && idx.Z == id.Z))
145-
{
146-
dontRender = true;
147-
removePhys = true;
148-
}
149-
150133
// The following vectors represent local positioning relative to root of original section:
151-
Vector3 offset = new Vector3((float)id.X, (float)id.Y, (float)id.Z); // Offset from section origin for this series of sections
134+
Vector3 offset = new Vector3((float)id.X, (float)id.Y, -(float)id.Z); // Offset from section origin for this series of sections
152135
Vector3 localV = Vector3.Zero; // Local position of subsection (in x-z plane)
153136
Vector3 heading = Vector3.Forward; // Local heading (unit vector)
154137

155138
WorldPosition worldMatrix = new WorldPosition(worldMatrixInput); // Copy origin location
156139

157140
worldMatrix.XNAMatrix.Translation = Vector3.Transform(offset, worldMatrix.XNAMatrix);
158141

142+
// If the section is rotated, apply that rotation now so we don't need to in the future
143+
worldMatrix.XNAMatrix = Matrix.CreateRotationY(MathHelper.ToRadians(-(float)id.A)) * worldMatrix.XNAMatrix;
144+
159145
WorldPosition nextRoot = new WorldPosition(worldMatrix); // Will become initial root
160146
Vector3 sectionOrigin = worldMatrix.XNAMatrix.Translation; // Original position for entire section
161147
worldMatrix.XNAMatrix.Translation = Vector3.Zero; // worldMatrix now rotation-only
@@ -235,14 +221,17 @@ public static void ClearJunctionSuperElevation(Viewer viewer, TrackObj trackObj,
235221
foreach (SectionIdx id in SectionIdxs)
236222
{
237223
// The following vectors represent local positioning relative to root of original section:
238-
Vector3 offset = new Vector3((float)id.X, (float)id.Y, (float)id.Z); // Offset from section origin for this series of sections
224+
Vector3 offset = new Vector3((float)id.X, (float)id.Y, -(float)id.Z); // Offset from section origin for this series of sections
239225
Vector3 localV = Vector3.Zero; // Local position of subsection (in x-z plane)
240226
Vector3 heading = Vector3.Forward; // Local heading (unit vector)
241227

242228
WorldPosition worldMatrix = new WorldPosition(worldMatrixInput); // Copy origin location
243229

244230
worldMatrix.XNAMatrix.Translation = Vector3.Transform(offset, worldMatrix.XNAMatrix);
245231

232+
// If the section is rotated, apply that rotation now so we don't need to in the future
233+
worldMatrix.XNAMatrix = Matrix.CreateRotationY(MathHelper.ToRadians(-(float)id.A)) * worldMatrix.XNAMatrix;
234+
246235
WorldPosition nextRoot = new WorldPosition(worldMatrix); // Will become initial root
247236
Vector3 sectionOrigin = worldMatrix.XNAMatrix.Translation; // Original position for entire section
248237
worldMatrix.XNAMatrix.Translation = Vector3.Zero; // worldMatrix now rotation-only

0 commit comments

Comments
 (0)