// update absolute camera internal static void UpdateAbsoluteCamera(double TimeElapsed) { // zoom double zm = World.CameraCurrentAlignment.Zoom; AdjustAlignment(ref World.CameraCurrentAlignment.Zoom, World.CameraAlignmentDirection.Zoom, ref World.CameraAlignmentSpeed.Zoom, TimeElapsed, true); if (zm != World.CameraCurrentAlignment.Zoom) { ApplyZoom(); } if (CameraMode == CameraViewMode.FlyBy | CameraMode == CameraViewMode.FlyByZooming) { // fly-by AdjustAlignment(ref World.CameraCurrentAlignment.Position.X, World.CameraAlignmentDirection.Position.X, ref World.CameraAlignmentSpeed.Position.X, TimeElapsed); AdjustAlignment(ref World.CameraCurrentAlignment.Position.Y, World.CameraAlignmentDirection.Position.Y, ref World.CameraAlignmentSpeed.Position.Y, TimeElapsed); double tr = World.CameraCurrentAlignment.TrackPosition; AdjustAlignment(ref World.CameraCurrentAlignment.TrackPosition, World.CameraAlignmentDirection.TrackPosition, ref World.CameraAlignmentSpeed.TrackPosition, TimeElapsed); if (tr != World.CameraCurrentAlignment.TrackPosition) { World.CameraTrackFollower.Update(World.CameraCurrentAlignment.TrackPosition, true, false); UpdateViewingDistances(); } // camera double px = World.CameraTrackFollower.WorldPosition.X; double py = World.CameraTrackFollower.WorldPosition.Y; double pz = World.CameraTrackFollower.WorldPosition.Z; // position to focus on double tx, ty, tz; double zoomMultiplier; { const double heightFactor = 0.75; TrainManager.Train bestTrain = null; double bestDistanceSquared = double.MaxValue; TrainManager.Train secondBestTrain = null; double secondBestDistanceSquared = double.MaxValue; foreach (TrainManager.Train train in TrainManager.Trains) { if (train.State == TrainState.Available) { double x = 0.5 * (train.Cars[0].FrontAxle.Follower.WorldPosition.X + train.Cars[0].RearAxle.Follower.WorldPosition.X); double y = 0.5 * (train.Cars[0].FrontAxle.Follower.WorldPosition.Y + train.Cars[0].RearAxle.Follower.WorldPosition.Y) + heightFactor * train.Cars[0].Height; double z = 0.5 * (train.Cars[0].FrontAxle.Follower.WorldPosition.Z + train.Cars[0].RearAxle.Follower.WorldPosition.Z); double dx = x - px; double dy = y - py; double dz = z - pz; double d = dx * dx + dy * dy + dz * dz; if (d < bestDistanceSquared) { secondBestTrain = bestTrain; secondBestDistanceSquared = bestDistanceSquared; bestTrain = train; bestDistanceSquared = d; } else if (d < secondBestDistanceSquared) { secondBestTrain = train; secondBestDistanceSquared = d; } } } if (bestTrain != null) { const double maxDistance = 100.0; double bestDistance = Math.Sqrt(bestDistanceSquared); double secondBestDistance = Math.Sqrt(secondBestDistanceSquared); if (secondBestTrain != null && secondBestDistance - bestDistance <= maxDistance) { double x1 = 0.5 * (bestTrain.Cars[0].FrontAxle.Follower.WorldPosition.X + bestTrain.Cars[0].RearAxle.Follower.WorldPosition.X); double y1 = 0.5 * (bestTrain.Cars[0].FrontAxle.Follower.WorldPosition.Y + bestTrain.Cars[0].RearAxle.Follower.WorldPosition.Y) + heightFactor * bestTrain.Cars[0].Height; double z1 = 0.5 * (bestTrain.Cars[0].FrontAxle.Follower.WorldPosition.Z + bestTrain.Cars[0].RearAxle.Follower.WorldPosition.Z); double x2 = 0.5 * (secondBestTrain.Cars[0].FrontAxle.Follower.WorldPosition.X + secondBestTrain.Cars[0].RearAxle.Follower.WorldPosition.X); double y2 = 0.5 * (secondBestTrain.Cars[0].FrontAxle.Follower.WorldPosition.Y + secondBestTrain.Cars[0].RearAxle.Follower.WorldPosition.Y) + heightFactor * secondBestTrain.Cars[0].Height; double z2 = 0.5 * (secondBestTrain.Cars[0].FrontAxle.Follower.WorldPosition.Z + secondBestTrain.Cars[0].RearAxle.Follower.WorldPosition.Z); double t = 0.5 - (secondBestDistance - bestDistance) / (2.0 * maxDistance); if (t < 0.0) { t = 0.0; } t = 2.0 * t * t; /* in order to change the shape of the interpolation curve */ tx = (1.0 - t) * x1 + t * x2; ty = (1.0 - t) * y1 + t * y2; tz = (1.0 - t) * z1 + t * z2; zoomMultiplier = 1.0 - 2.0 * t; } else { tx = 0.5 * (bestTrain.Cars[0].FrontAxle.Follower.WorldPosition.X + bestTrain.Cars[0].RearAxle.Follower.WorldPosition.X); ty = 0.5 * (bestTrain.Cars[0].FrontAxle.Follower.WorldPosition.Y + bestTrain.Cars[0].RearAxle.Follower.WorldPosition.Y) + heightFactor * bestTrain.Cars[0].Height; tz = 0.5 * (bestTrain.Cars[0].FrontAxle.Follower.WorldPosition.Z + bestTrain.Cars[0].RearAxle.Follower.WorldPosition.Z); zoomMultiplier = 1.0; } } else { tx = 0.0; ty = 0.0; tz = 0.0; zoomMultiplier = 1.0; } } // camera { AbsoluteCameraDirection = new Vector3(CameraTrackFollower.WorldDirection); double ox = World.CameraCurrentAlignment.Position.X; double oy = World.CameraCurrentAlignment.Position.Y; double oz = World.CameraCurrentAlignment.Position.Z; double cx = px + CameraTrackFollower.WorldSide.X * ox + CameraTrackFollower.WorldUp.X * oy + AbsoluteCameraDirection.X * oz; double cy = py + CameraTrackFollower.WorldSide.Y * ox + CameraTrackFollower.WorldUp.Y * oy + AbsoluteCameraDirection.Y * oz; double cz = pz + CameraTrackFollower.WorldSide.Z * ox + CameraTrackFollower.WorldUp.Z * oy + AbsoluteCameraDirection.Z * oz; AbsoluteCameraPosition = new Vector3(cx, cy, cz); AbsoluteCameraDirection.X = tx - cx; AbsoluteCameraDirection.Y = ty - cy; AbsoluteCameraDirection.Z = tz - cz; double t = AbsoluteCameraDirection.Norm(); double ti = 1.0 / t; AbsoluteCameraDirection *= ti; AbsoluteCameraSide = new Vector3(AbsoluteCameraDirection.Z, 0.0, -AbsoluteCameraDirection.X); AbsoluteCameraSide.Normalize(); AbsoluteCameraUp = Vector3.Cross(AbsoluteCameraDirection, AbsoluteCameraSide); UpdateViewingDistances(); if (CameraMode == CameraViewMode.FlyByZooming) { // zoom const double fadeOutDistance = 600.0; /* the distance with the highest zoom factor is half the fade-out distance */ const double maxZoomFactor = 7.0; /* the zoom factor at half the fade-out distance */ const double factor = 256.0 / (fadeOutDistance * fadeOutDistance * fadeOutDistance * fadeOutDistance * fadeOutDistance * fadeOutDistance * fadeOutDistance * fadeOutDistance); double zoom; if (t < fadeOutDistance) { double tdist4 = fadeOutDistance - t; tdist4 *= tdist4; tdist4 *= tdist4; double t4 = t * t; t4 *= t4; zoom = 1.0 + factor * zoomMultiplier * (maxZoomFactor - 1.0) * tdist4 * t4; } else { zoom = 1.0; } World.VerticalViewingAngle = World.OriginalVerticalViewingAngle / zoom; Renderer.UpdateViewport(Renderer.ViewPortChangeMode.NoChange); } } } else { // non-fly-by { // current alignment AdjustAlignment(ref World.CameraCurrentAlignment.Position.X, World.CameraAlignmentDirection.Position.X, ref World.CameraAlignmentSpeed.Position.X, TimeElapsed); AdjustAlignment(ref World.CameraCurrentAlignment.Position.Y, World.CameraAlignmentDirection.Position.Y, ref World.CameraAlignmentSpeed.Position.Y, TimeElapsed); AdjustAlignment(ref World.CameraCurrentAlignment.Position.Z, World.CameraAlignmentDirection.Position.Z, ref World.CameraAlignmentSpeed.Position.Z, TimeElapsed); if ((CameraMode == CameraViewMode.Interior | World.CameraMode == CameraViewMode.InteriorLookAhead) & CameraRestriction == Camera.RestrictionMode.On) { if (CameraCurrentAlignment.Position.Z > 0.75) { CameraCurrentAlignment.Position.Z = 0.75; } } bool q = World.CameraAlignmentSpeed.Yaw != 0.0 | World.CameraAlignmentSpeed.Pitch != 0.0 | World.CameraAlignmentSpeed.Roll != 0.0; AdjustAlignment(ref World.CameraCurrentAlignment.Yaw, World.CameraAlignmentDirection.Yaw, ref World.CameraAlignmentSpeed.Yaw, TimeElapsed); AdjustAlignment(ref World.CameraCurrentAlignment.Pitch, World.CameraAlignmentDirection.Pitch, ref World.CameraAlignmentSpeed.Pitch, TimeElapsed); AdjustAlignment(ref World.CameraCurrentAlignment.Roll, World.CameraAlignmentDirection.Roll, ref World.CameraAlignmentSpeed.Roll, TimeElapsed); double tr = World.CameraCurrentAlignment.TrackPosition; AdjustAlignment(ref World.CameraCurrentAlignment.TrackPosition, World.CameraAlignmentDirection.TrackPosition, ref World.CameraAlignmentSpeed.TrackPosition, TimeElapsed); if (tr != World.CameraCurrentAlignment.TrackPosition) { World.CameraTrackFollower.Update(World.CameraCurrentAlignment.TrackPosition, true, false); q = true; } if (q) { UpdateViewingDistances(); } } // camera Vector3 cF = new Vector3(CameraTrackFollower.WorldPosition); Vector3 dF = new Vector3(CameraTrackFollower.WorldDirection); Vector3 uF = new Vector3(CameraTrackFollower.WorldUp); Vector3 sF = new Vector3(CameraTrackFollower.WorldSide); double lookaheadYaw; double lookaheadPitch; if (CameraMode == CameraViewMode.InteriorLookAhead) { // look-ahead double d = 20.0; if (TrainManager.PlayerTrain.Specs.CurrentAverageSpeed > 0.0) { d += 3.0 * (Math.Sqrt(TrainManager.PlayerTrain.Specs.CurrentAverageSpeed * TrainManager.PlayerTrain.Specs.CurrentAverageSpeed + 1.0) - 1.0); } d -= TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].FrontAxle.Position; TrackManager.TrackFollower f = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].FrontAxle.Follower; f.TriggerType = TrackManager.EventTriggerType.None; f.Update(f.TrackPosition + d, true, false); Vector3 r = new Vector3(f.WorldPosition - cF + World.CameraTrackFollower.WorldSide * TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Driver.X + World.CameraTrackFollower.WorldUp * TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Driver.Y + World.CameraTrackFollower.WorldDirection * TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Driver.Z); r.Normalize(); double t = dF.Z * (sF.Y * uF.X - sF.X * uF.Y) + dF.Y * (-sF.Z * uF.X + sF.X * uF.Z) + dF.X * (sF.Z * uF.Y - sF.Y * uF.Z); if (t != 0.0) { t = 1.0 / t; double tx = (r.Z * (-dF.Y * uF.X + dF.X * uF.Y) + r.Y * (dF.Z * uF.X - dF.X * uF.Z) + r.X * (-dF.Z * uF.Y + dF.Y * uF.Z)) * t; double ty = (r.Z * (dF.Y * sF.X - dF.X * sF.Y) + r.Y * (-dF.Z * sF.X + dF.X * sF.Z) + r.X * (dF.Z * sF.Y - dF.Y * sF.Z)) * t; double tz = (r.Z * (sF.Y * uF.X - sF.X * uF.Y) + r.Y * (-sF.Z * uF.X + sF.X * uF.Z) + r.X * (sF.Z * uF.Y - sF.Y * uF.Z)) * t; lookaheadYaw = tx * tz != 0.0 ? Math.Atan2(tx, tz) : 0.0; if (ty < -1.0) { lookaheadPitch = -0.5 * Math.PI; } else if (ty > 1.0) { lookaheadPitch = 0.5 * Math.PI; } else { lookaheadPitch = Math.Asin(ty); } } else { lookaheadYaw = 0.0; lookaheadPitch = 0.0; } } else { lookaheadYaw = 0.0; lookaheadPitch = 0.0; } { // cab pitch and yaw Vector3 d2 = new Vector3(dF); Vector3 u2 = new Vector3(uF); if ((World.CameraMode == CameraViewMode.Interior | World.CameraMode == CameraViewMode.InteriorLookAhead) & TrainManager.PlayerTrain != null) { int c = TrainManager.PlayerTrain.DriverCar; if (c >= 0) { if (TrainManager.PlayerTrain.Cars[c].CarSections.Length == 0 || !TrainManager.PlayerTrain.Cars[c].CarSections[0].Groups[0].Overlay) { double a = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].DriverPitch; double cosa = Math.Cos(-a); double sina = Math.Sin(-a); d2.Rotate(sF, cosa, sina); u2.Rotate(sF, cosa, sina); } } } cF += sF * CameraCurrentAlignment.Position.X + u2 * CameraCurrentAlignment.Position + d2 * CameraCurrentAlignment.Position.Z; } // yaw, pitch, roll double headYaw = World.CameraCurrentAlignment.Yaw + lookaheadYaw; if ((World.CameraMode == CameraViewMode.Interior | World.CameraMode == CameraViewMode.InteriorLookAhead) & TrainManager.PlayerTrain != null) { if (TrainManager.PlayerTrain.DriverCar >= 0) { headYaw += TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].DriverYaw; } } double headPitch = World.CameraCurrentAlignment.Pitch + lookaheadPitch; if ((World.CameraMode == CameraViewMode.Interior | World.CameraMode == CameraViewMode.InteriorLookAhead) & TrainManager.PlayerTrain != null) { if (TrainManager.PlayerTrain.DriverCar >= 0) { headPitch += TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].DriverPitch; } } double bodyPitch = 0.0; double bodyRoll = 0.0; double headRoll = World.CameraCurrentAlignment.Roll; // rotation if (CameraRestriction == Camera.RestrictionMode.NotAvailable & (CameraMode == CameraViewMode.Interior | CameraMode == CameraViewMode.InteriorLookAhead)) { // with body and head bodyPitch += CurrentDriverBody.Pitch; headPitch -= 0.2 * CurrentDriverBody.Pitch; bodyRoll += CurrentDriverBody.Roll; headRoll += 0.2 * CurrentDriverBody.Roll; const double bodyHeight = 0.6; const double headHeight = 0.1; { // body pitch double ry = (Math.Cos(-bodyPitch) - 1.0) * bodyHeight; double rz = Math.Sin(-bodyPitch) * bodyHeight; cF += dF * rz + uF * ry; if (bodyPitch != 0.0) { double cosa = Math.Cos(-bodyPitch); double sina = Math.Sin(-bodyPitch); dF.Rotate(sF, cosa, sina); uF.Rotate(sF, cosa, sina); } } { // body roll double rx = Math.Sin(bodyRoll) * bodyHeight; double ry = (Math.Cos(bodyRoll) - 1.0) * bodyHeight; cF += sF * rx + uF * ry; if (bodyRoll != 0.0) { double cosa = Math.Cos(-bodyRoll); double sina = Math.Sin(-bodyRoll); uF.Rotate(dF, cosa, sina); sF.Rotate(dF, cosa, sina); } } { // head yaw double rx = Math.Sin(headYaw) * headHeight; double rz = (Math.Cos(headYaw) - 1.0) * headHeight; cF += sF * rx + dF * rz; if (headYaw != 0.0) { double cosa = Math.Cos(headYaw); double sina = Math.Sin(headYaw); dF.Rotate(uF, cosa, sina); sF.Rotate(uF, cosa, sina); } } { // head pitch double ry = (Math.Cos(-headPitch) - 1.0) * headHeight; double rz = Math.Sin(-headPitch) * headHeight; cF += dF * rz + uF * ry; if (headPitch != 0.0) { double cosa = Math.Cos(-headPitch); double sina = Math.Sin(-headPitch); dF.Rotate(sF, cosa, sina); uF.Rotate(sF, cosa, sina); } } { // head roll double rx = Math.Sin(headRoll) * headHeight; double ry = (Math.Cos(headRoll) - 1.0) * headHeight; cF += sF * rx + uF * ry; if (headRoll != 0.0) { double cosa = Math.Cos(-headRoll); double sina = Math.Sin(-headRoll); uF.Rotate(dF, cosa, sina); sF.Rotate(dF, cosa, sina); } } } else { // without body or head double totalYaw = headYaw; double totalPitch = headPitch + bodyPitch; double totalRoll = bodyRoll + headRoll; if (totalYaw != 0.0) { double cosa = Math.Cos(totalYaw); double sina = Math.Sin(totalYaw); dF.Rotate(uF, cosa, sina); sF.Rotate(uF, cosa, sina); } if (totalPitch != 0.0) { double cosa = Math.Cos(-totalPitch); double sina = Math.Sin(-totalPitch); dF.Rotate(sF, cosa, sina); uF.Rotate(sF, cosa, sina); } if (totalRoll != 0.0) { double cosa = Math.Cos(-totalRoll); double sina = Math.Sin(-totalRoll); uF.Rotate(dF, cosa, sina); sF.Rotate(dF, cosa, sina); } } // finish AbsoluteCameraPosition = cF; AbsoluteCameraDirection = dF; AbsoluteCameraUp = uF; AbsoluteCameraSide = sF; } }
#pragma warning restore 0649 public override void Update(double TimeElapsed, bool ForceUpdate) { const double extraRadius = 10.0; double z = Object.TranslateZFunction == null ? 0.0 : Object.TranslateZFunction.LastResult; double pa = TrackPosition + z - Radius - extraRadius; double pb = TrackPosition + z + Radius + extraRadius; double ta = World.CameraTrackFollower.TrackPosition + Camera.CurrentAlignment.Position.Z - Backgrounds.BackgroundImageDistance - World.ExtraViewingDistance; double tb = World.CameraTrackFollower.TrackPosition + Camera.CurrentAlignment.Position.Z + Backgrounds.BackgroundImageDistance + World.ExtraViewingDistance; bool visible = pb >= ta & pa <= tb; if (visible | ForceUpdate) { if (Object.SecondsSinceLastUpdate >= Object.RefreshRate | ForceUpdate) { double timeDelta = Object.SecondsSinceLastUpdate + TimeElapsed; Object.SecondsSinceLastUpdate = 0.0; TrainManager.Train train = null; double trainDistance = double.MaxValue; for (int j = 0; j < TrainManager.Trains.Length; j++) { if (TrainManager.Trains[j].State == TrainState.Available) { double distance; if (TrainManager.Trains[j].Cars[0].FrontAxle.Follower.TrackPosition < TrackPosition) { distance = TrackPosition - TrainManager.Trains[j].Cars[0].FrontAxle.Follower.TrackPosition; } else if (TrainManager.Trains[j].Cars[TrainManager.Trains[j].Cars.Length - 1].RearAxle.Follower.TrackPosition > TrackPosition) { distance = TrainManager.Trains[j].Cars[TrainManager.Trains[j].Cars.Length - 1].RearAxle.Follower.TrackPosition - TrackPosition; } else { distance = 0; } if (distance < trainDistance) { train = TrainManager.Trains[j]; trainDistance = distance; } } } if (Visible) { //Calculate the distance travelled double delta = UpdateTrackFollowerScript(false, train, train == null ? 0 : train.DriverCar, SectionIndex, TrackPosition, Position, true, timeDelta); //Update the front and rear axle track followers FrontAxleFollower.Update((TrackPosition + FrontAxlePosition) + delta, true, true); RearAxleFollower.Update((TrackPosition + RearAxlePosition) + delta, true, true); //Update the base object position FrontAxleFollower.UpdateWorldCoordinates(false); RearAxleFollower.UpdateWorldCoordinates(false); UpdateObjectPosition(); } //Update the actual animated object- This must be done last in case the user has used Translation or Rotation Object.Update(false, train, train == null ? 0 : train.DriverCar, SectionIndex, FrontAxleFollower.TrackPosition, FrontAxleFollower.WorldPosition, Direction, Up, Side, false, true, true, timeDelta, true); } else { Object.SecondsSinceLastUpdate += TimeElapsed; } if (!Visible) { Renderer.ShowObject(Object.ObjectIndex, ObjectType.Dynamic); Visible = true; } } else { Object.SecondsSinceLastUpdate += TimeElapsed; if (Visible) { Renderer.HideObject(Object.ObjectIndex); Visible = false; } } }
/// <summary>Renders a graphical visualisation of any events within camera range</summary> /// <param name="Camera">The absolute camera position</param> private static void RenderEvents(Vector3 Camera) { if (Interface.CurrentOptions.ShowEvents == false || TrackManager.Tracks[0].Elements == null) { return; } if (!Initialized) { Init(); Initialized = true; } GL.Enable(EnableCap.CullFace); LibRender.Renderer.CullEnabled = true; GL.Enable(EnableCap.DepthTest); GL.DepthMask(true); if (LibRender.Renderer.LightingEnabled) { GL.Disable(EnableCap.Lighting); LibRender.Renderer.LightingEnabled = false; } if (LibRender.Renderer.AlphaTestEnabled) { GL.Disable(EnableCap.AlphaTest); LibRender.Renderer.AlphaTestEnabled = false; } double da = -World.BackwardViewingDistance - World.ExtraViewingDistance; double db = World.ForwardViewingDistance + World.ExtraViewingDistance; bool[] sta = new bool[CurrentRoute.Stations.Length]; // events for (int i = 0; i < TrackManager.Tracks[0].Elements.Length; i++) { double p = TrackManager.Tracks[0].Elements[i].StartingTrackPosition; double d = p - World.CameraTrackFollower.TrackPosition; if (d >= da & d <= db) { for (int j = 0; j < TrackManager.Tracks[0].Elements[i].Events.Length; j++) { dynamic e = TrackManager.Tracks[0].Elements[i].Events[j]; double dy, dx = 0.0, dz = 0.0; double s; Texture t; if (e is TrackManager.BrightnessChangeEvent) { s = 0.15; dy = 4.0; t = BrightnessChangeTexture; } else if (e is BackgroundChangeEvent) { s = 0.25; dy = 3.5; t = BackgroundChangeTexture; } else if (e is TrackManager.StationStartEvent) { s = 0.25; dy = 1.6; t = StationStartTexture; TrackManager.StationStartEvent f = (TrackManager.StationStartEvent)e; sta[f.StationIndex] = true; } else if (e is TrackManager.StationEndEvent) { s = 0.25; dy = 1.6; t = StationEndTexture; TrackManager.StationEndEvent f = (TrackManager.StationEndEvent)e; sta[f.StationIndex] = true; } else if (e is TrackManager.LimitChangeEvent) { s = 0.2; dy = 1.1; t = LimitTexture; } else if (e is TrackManager.SectionChangeEvent) { s = 0.2; dy = 0.8; t = SectionTexture; } else if (e is TrackManager.TransponderEvent) { s = 0.15; dy = 0.4; t = TransponderTexture; } else if (e is TrackManager.SoundEvent) { TrackManager.SoundEvent f = (TrackManager.SoundEvent)e; s = 0.2; dx = f.Position.X; dy = f.Position.Y < 0.1 ? 0.1 : f.Position.Y; dz = f.Position.Z; t = SoundTexture; } else if (e is TrackManager.PointSoundEvent) { s = 0.2; dx = 0; dy = 0.2; dz = 0; t = PointSoundTexture; } else { s = 0.2; dy = 1.0; t = null; } if (t != null) { TrackManager.TrackFollower f = new TrackManager.TrackFollower(); f.TriggerType = EventTriggerType.None; f.TrackPosition = p; f.Update(p + e.TrackPositionDelta, true, false); f.WorldPosition.X += dx * f.WorldSide.X + dy * f.WorldUp.X + dz * f.WorldDirection.X; f.WorldPosition.Y += dx * f.WorldSide.Y + dy * f.WorldUp.Y + dz * f.WorldDirection.Y; f.WorldPosition.Z += dx * f.WorldSide.Z + dy * f.WorldUp.Z + dz * f.WorldDirection.Z; LibRender.Renderer.DrawCube(f.WorldPosition, f.WorldDirection, f.WorldUp, f.WorldSide, s, Camera, t); } } } } // stops for (int i = 0; i < sta.Length; i++) { if (sta[i]) { for (int j = 0; j < CurrentRoute.Stations[i].Stops.Length; j++) { const double dy = 1.4; const double s = 0.2; double p = CurrentRoute.Stations[i].Stops[j].TrackPosition; TrackManager.TrackFollower f = new TrackManager.TrackFollower(); f.TriggerType = EventTriggerType.None; f.TrackPosition = p; f.Update(p, true, false); f.WorldPosition.X += dy * f.WorldUp.X; f.WorldPosition.Y += dy * f.WorldUp.Y; f.WorldPosition.Z += dy * f.WorldUp.Z; LibRender.Renderer.DrawCube(f.WorldPosition, f.WorldDirection, f.WorldUp, f.WorldSide, s, Camera, StopTexture); } } } // buffers for (int i = 0; i < Game.BufferTrackPositions.Length; i++) { double p = Game.BufferTrackPositions[i]; double d = p - World.CameraTrackFollower.TrackPosition; if (d >= da & d <= db) { const double dy = 2.5; const double s = 0.25; TrackManager.TrackFollower f = new TrackManager.TrackFollower(); f.TriggerType = EventTriggerType.None; f.TrackPosition = p; f.Update(p, true, false); f.WorldPosition.X += dy * f.WorldUp.X; f.WorldPosition.Y += dy * f.WorldUp.Y; f.WorldPosition.Z += dy * f.WorldUp.Z; LibRender.Renderer.DrawCube(f.WorldPosition, f.WorldDirection, f.WorldUp, f.WorldSide, s, Camera, BufferTexture); } } }