Represents a 3D vector of System.Double coordinates.
 internal SoundEvent(double TrackPositionDelta, int SoundIndex, bool PlayerTrainOnly, bool Once, bool Dynamic, World.Vector3D Position, double Speed)
 {
     this.TrackPositionDelta = TrackPositionDelta;
     this.DontTriggerAnymore = false;
     this.SoundIndex         = SoundIndex;
     this.PlayerTrainOnly    = PlayerTrainOnly;
     this.Once     = Once;
     this.Dynamic  = Dynamic;
     this.Position = Position;
     this.Speed    = Speed;
 }
Example #2
0
 internal TrackElement(double StartingTrackPosition)
 {
     this.StartingTrackPosition = StartingTrackPosition;
     this.CurveRadius           = 0.0;
     this.CurveCant             = 0.0;
     this.CurveCantTangent      = 0.0;
     this.AdhesionMultiplier    = 1.0;
     this.CsvRwAccuracyLevel    = 2.0;
     this.WorldPosition         = new World.Vector3D(0.0, 0.0, 0.0);
     this.WorldDirection        = new World.Vector3D(0.0, 0.0, 1.0);
     this.WorldUp   = new World.Vector3D(0.0, 1.0, 0.0);
     this.WorldSide = new World.Vector3D(1.0, 0.0, 0.0);
     this.Events    = new GeneralEvent[] { };
 }
Example #3
0
 internal Transformation(Transformation BaseTransformation, Transformation AuxTransformation)
 {
     World.Vector3D x = BaseTransformation.X;
     World.Vector3D y = BaseTransformation.Y;
     World.Vector3D z = BaseTransformation.Z;
     World.Vector3D s = AuxTransformation.X;
     World.Vector3D u = AuxTransformation.Y;
     World.Vector3D d = AuxTransformation.Z;
     Rotate(ref x.X, ref x.Y, ref x.Z, d.X, d.Y, d.Z, u.X, u.Y, u.Z, s.X, s.Y, s.Z);
     Rotate(ref y.X, ref y.Y, ref y.Z, d.X, d.Y, d.Z, u.X, u.Y, u.Z, s.X, s.Y, s.Z);
     Rotate(ref z.X, ref z.Y, ref z.Z, d.X, d.Y, d.Z, u.X, u.Y, u.Z, s.X, s.Y, s.Z);
     this.X = x;
     this.Y = y;
     this.Z = z;
 }
Example #4
0
 internal static void MouseEvent(object sender, MouseButtonEventArgs e)
 {
     MouseCameraPosition  = World.AbsoluteCameraPosition;
     MouseCameraDirection = World.AbsoluteCameraDirection;
     MouseCameraUp        = World.AbsoluteCameraUp;
     MouseCameraSide      = World.AbsoluteCameraSide;
     if (e.Button == OpenTK.Input.MouseButton.Left)
     {
         MouseButton = e.Mouse.LeftButton == ButtonState.Pressed ? 1 : 0;
     }
     if (e.Button == OpenTK.Input.MouseButton.Right)
     {
         MouseButton = e.Mouse.RightButton == ButtonState.Pressed ? 2 : 0;
     }
     if (e.Button == OpenTK.Input.MouseButton.Middle)
     {
         MouseButton = e.Mouse.RightButton == ButtonState.Pressed ? 3 : 0;
     }
     previousMouseState = Mouse.GetState();
 }
Example #5
0
		internal static void UpdateTrackFollower(ref TrackFollower Follower, double NewTrackPosition, bool UpdateWorldCoordinates, bool AddTrackInaccurary) {
			if (CurrentTrack.Elements.Length == 0) return;
			int i = Follower.LastTrackElement;
			while (i >= 0 && NewTrackPosition < CurrentTrack.Elements[i].StartingTrackPosition) {
				double ta = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
				double tb = -0.01;
				CheckEvents(ref Follower, i, -1, ta, tb);
				i--;
			}
			if (i >= 0) {
				while (i < CurrentTrack.Elements.Length - 1) {
					if (NewTrackPosition < CurrentTrack.Elements[i + 1].StartingTrackPosition) break;
					double ta = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
					double tb = CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition + 0.01;
					CheckEvents(ref Follower, i, 1, ta, tb);
					i++;
				}
			} else {
				i = 0;
			}
			double da = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
			double db = NewTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
			// track
			if (UpdateWorldCoordinates) {
				if (db != 0.0) {
					if (CurrentTrack.Elements[i].CurveRadius != 0.0) {
						// curve
						double r = CurrentTrack.Elements[i].CurveRadius;
						double p = CurrentTrack.Elements[i].WorldDirection.Y / Math.Sqrt(CurrentTrack.Elements[i].WorldDirection.X * CurrentTrack.Elements[i].WorldDirection.X + CurrentTrack.Elements[i].WorldDirection.Z * CurrentTrack.Elements[i].WorldDirection.Z);
						double s = db / Math.Sqrt(1.0 + p * p);
						double h = s * p;
						double b = s / Math.Abs(r);
						double f = 2.0 * r * r * (1.0 - Math.Cos(b));
						double c = (double)Math.Sign(db) * Math.Sqrt(f >= 0.0 ? f : 0.0);
						double a = 0.5 * (double)Math.Sign(r) * b;
						World.Vector3D D = new World.Vector3D(CurrentTrack.Elements[i].WorldDirection.X, 0.0, CurrentTrack.Elements[i].WorldDirection.Z);
						World.Normalize(ref D.X, ref D.Y, ref D.Z);
						double cosa = Math.Cos(a);
						double sina = Math.Sin(a);
						World.Rotate(ref D.X, ref D.Y, ref D.Z, 0.0, 1.0, 0.0, cosa, sina);
						Follower.WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + c * D.X;
						Follower.WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + h;
						Follower.WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + c * D.Z;
						World.Rotate(ref D.X, ref D.Y, ref D.Z, 0.0, 1.0, 0.0, cosa, sina);
						Follower.WorldDirection.X = D.X;
						Follower.WorldDirection.Y = p;
						Follower.WorldDirection.Z = D.Z;
						World.Normalize(ref Follower.WorldDirection.X, ref Follower.WorldDirection.Y, ref Follower.WorldDirection.Z);
						double cos2a = Math.Cos(2.0 * a);
						double sin2a = Math.Sin(2.0 * a);
						Follower.WorldSide = CurrentTrack.Elements[i].WorldSide;
						World.Rotate(ref Follower.WorldSide.X, ref Follower.WorldSide.Y, ref Follower.WorldSide.Z, 0.0, 1.0, 0.0, cos2a, sin2a);
						World.Cross(Follower.WorldDirection.X, Follower.WorldDirection.Y, Follower.WorldDirection.Z, Follower.WorldSide.X, Follower.WorldSide.Y, Follower.WorldSide.Z, out Follower.WorldUp.X, out Follower.WorldUp.Y, out Follower.WorldUp.Z);
						Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
					} else {
						// straight
						Follower.WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + db * CurrentTrack.Elements[i].WorldDirection.X;
						Follower.WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + db * CurrentTrack.Elements[i].WorldDirection.Y;
						Follower.WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + db * CurrentTrack.Elements[i].WorldDirection.Z;
						Follower.WorldDirection = CurrentTrack.Elements[i].WorldDirection;
						Follower.WorldUp = CurrentTrack.Elements[i].WorldUp;
						Follower.WorldSide = CurrentTrack.Elements[i].WorldSide;
						Follower.CurveRadius = 0.0;
					}
					// cant
					if (i < CurrentTrack.Elements.Length - 1) {
						double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
						if (t < 0.0) {
							t = 0.0;
						} else if (t > 1.0) {
							t = 1.0;
						}
						double t2 = t * t;
						double t3 = t2 * t;
						Follower.CurveCant =
							(2.0 * t3 - 3.0 * t2 + 1.0) * CurrentTrack.Elements[i].CurveCant +
							(t3 - 2.0 * t2 + t) * CurrentTrack.Elements[i].CurveCantTangent +
							(-2.0 * t3 + 3.0 * t2) * CurrentTrack.Elements[i + 1].CurveCant +
							(t3 - t2) * CurrentTrack.Elements[i + 1].CurveCantTangent;
					} else {
						Follower.CurveCant = CurrentTrack.Elements[i].CurveCant;
					}
				} else {
					Follower.WorldPosition = CurrentTrack.Elements[i].WorldPosition;
					Follower.WorldDirection = CurrentTrack.Elements[i].WorldDirection;
					Follower.WorldUp = CurrentTrack.Elements[i].WorldUp;
					Follower.WorldSide = CurrentTrack.Elements[i].WorldSide;
					Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
					Follower.CurveCant = CurrentTrack.Elements[i].CurveCant;
				}
			} else {
				if (db != 0.0) {
					if (CurrentTrack.Elements[i].CurveRadius != 0.0) {
						Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
					} else {
						Follower.CurveRadius = 0.0;
					}
					if (i < CurrentTrack.Elements.Length - 1) {
						double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
						if (t < 0.0) {
							t = 0.0;
						} else if (t > 1.0) {
							t = 1.0;
						}
						double t2 = t * t;
						double t3 = t2 * t;
						Follower.CurveCant =
							(2.0 * t3 - 3.0 * t2 + 1.0) * CurrentTrack.Elements[i].CurveCant +
							(t3 - 2.0 * t2 + t) * CurrentTrack.Elements[i].CurveCantTangent +
							(-2.0 * t3 + 3.0 * t2) * CurrentTrack.Elements[i + 1].CurveCant +
							(t3 - t2) * CurrentTrack.Elements[i + 1].CurveCantTangent;
					} else {
						Follower.CurveCant = CurrentTrack.Elements[i].CurveCant;
					}
				} else {
					Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
					Follower.CurveCant = CurrentTrack.Elements[i].CurveCant;
				}
			}
			Follower.AdhesionMultiplier = CurrentTrack.Elements[i].AdhesionMultiplier;
			// inaccuracy
			if (AddTrackInaccurary) {
				double x, y, c;
				if (i < CurrentTrack.Elements.Length - 1) {
					double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
					if (t < 0.0) {
						t = 0.0;
					} else if (t > 1.0) {
						t = 1.0;
					}
					double x1, y1, c1;
					double x2, y2, c2;
					GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i].CsvRwAccuracyLevel, out x1, out y1, out c1);
					GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i + 1].CsvRwAccuracyLevel, out x2, out y2, out c2);
					x = (1.0 - t) * x1 + t * x2;
					y = (1.0 - t) * y1 + t * y2;
					c = (1.0 - t) * c1 + t * c2;
				} else {
					GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i].CsvRwAccuracyLevel, out x, out y, out c);
				}
				Follower.WorldPosition.X += x * Follower.WorldSide.X + y * Follower.WorldUp.X;
				Follower.WorldPosition.Y += x * Follower.WorldSide.Y + y * Follower.WorldUp.Y;
				Follower.WorldPosition.Z += x * Follower.WorldSide.Z + y * Follower.WorldUp.Z;
				Follower.CurveCant += c;
				Follower.CantDueToInaccuracy = c;
			} else {
				Follower.CantDueToInaccuracy = 0.0;
			}
			// events
			CheckEvents(ref Follower, i, Math.Sign(db - da), da, db);
			// finish
			Follower.TrackPosition = NewTrackPosition;
			Follower.LastTrackElement = i;
		}
Example #6
0
 // render cube
 private static void RenderBox(World.Vector3D Position, World.Vector3D Direction, World.Vector3D Up, World.Vector3D Side, World.Vector3D Size, double CameraX, double CameraY, double CameraZ)
 {
     if (TexturingEnabled)
     {
         GL.Disable(EnableCap.Texture2D);
         TexturingEnabled = false;
     }
     World.Vector3D[] v = new World.Vector3D[8];
     v[0] = new World.Vector3D(Size.X, Size.Y, -Size.Z);
     v[1] = new World.Vector3D(Size.X, -Size.Y, -Size.Z);
     v[2] = new World.Vector3D(-Size.X, -Size.Y, -Size.Z);
     v[3] = new World.Vector3D(-Size.X, Size.Y, -Size.Z);
     v[4] = new World.Vector3D(Size.X, Size.Y, Size.Z);
     v[5] = new World.Vector3D(Size.X, -Size.Y, Size.Z);
     v[6] = new World.Vector3D(-Size.X, -Size.Y, Size.Z);
     v[7] = new World.Vector3D(-Size.X, Size.Y, Size.Z);
     for (int i = 0; i < 8; i++)
     {
         World.Rotate(ref v[i].X, ref v[i].Y, ref v[i].Z, Direction.X, Direction.Y, Direction.Z, Up.X, Up.Y, Up.Z, Side.X, Side.Y, Side.Z);
         v[i].X += Position.X - CameraX;
         v[i].Y += Position.Y - CameraY;
         v[i].Z += Position.Z - CameraZ;
     }
     int[][] Faces = new int[6][];
     Faces[0] = new int[] { 0, 1, 2, 3 };
     Faces[1] = new int[] { 0, 4, 5, 1 };
     Faces[2] = new int[] { 0, 3, 7, 4 };
     Faces[3] = new int[] { 6, 5, 4, 7 };
     Faces[4] = new int[] { 6, 7, 3, 2 };
     Faces[5] = new int[] { 6, 2, 1, 5 };
     for (int i = 0; i < 6; i++)
     {
         GL.Begin(PrimitiveType.Quads);
         for (int j = 0; j < 4; j++)
         {
             GL.Vertex3(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z);
         }
         GL.End();
     }
 }
Example #7
0
 private static void PlaySound(ref int SoundSourceIndex, bool ReturnHandle, int SoundBufferIndex, TrainManager.Train Train, int CarIndex, World.Vector3D Position, Importance Important, bool Looped, double Pitch, double Gain)
 {
     if (OpenAlContext != IntPtr.Zero)
     {
         if (Game.MinimalisticSimulation & Important == Importance.DontCare | SoundBufferIndex == -1)
         {
             return;
         }
         if (SoundSourceIndex >= 0)
         {
             StopSound(ref SoundSourceIndex);
         }
         int i;
         for (i = 0; i < SoundSources.Length; i++)
         {
             if (SoundSources[i] == null)
             {
                 break;
             }
         }
         if (i >= SoundSources.Length)
         {
             Array.Resize <SoundSource>(ref SoundSources, SoundSources.Length << 1);
         }
         SoundSources[i]                   = new SoundSourceX();
         SoundSources[i].Position          = Position;
         SoundSources[i].OpenAlPosition    = new float[] { 0.0f, 0.0f, 0.0f };
         SoundSources[i].OpenAlVelocity    = new float[] { 0.0f, 0.0f, 0.0f };
         SoundSources[i].SoundBufferIndex  = SoundBufferIndex;
         SoundSources[i].Radius            = SoundBuffers[SoundBufferIndex].Radius;
         SoundSources[i].Pitch             = (float)Pitch;
         SoundSources[i].Gain              = (float)Gain;
         SoundSources[i].Looped            = Looped;
         SoundSources[i].Suppressed        = true;
         SoundSources[i].FinishedPlaying   = false;
         SoundSources[i].Train             = Train;
         SoundSources[i].CarIndex          = CarIndex;
         SoundSources[i].OpenAlSourceIndex = new OpenAlIndex(0, false);
         SoundSources[i].HasHandle         = ReturnHandle;
         SoundSourceIndex                  = i;
     }
 }
Example #8
0
 internal static void PlaySound(ref int SoundSourceIndex, int SoundBufferIndex, TrainManager.Train Train, int CarIndex, World.Vector3D Position, Importance Important, bool Looped, double Pitch, double Gain)
 {
     PlaySound(ref SoundSourceIndex, true, SoundBufferIndex, Train, CarIndex, Position, Important, Looped, Pitch, Gain);
 }
 internal TrackElement(double StartingTrackPosition)
 {
     this.StartingTrackPosition = StartingTrackPosition;
     this.CurveRadius = 0.0;
     this.CurveCant = 0.0;
     this.CurveCantInterpolation = CantInterpolationMode.Linear;
     this.Inaccuracy = 0.0;
     this.AdhesionMultiplier = 1.0;
     this.WorldPosition = new World.Vector3D(0.0, 0.0, 0.0);
     this.WorldDirection = new World.Vector3D(0.0, 0.0, 1.0);
     this.WorldUp = new World.Vector3D(0.0, 1.0, 0.0);
     this.WorldSide = new World.Vector3D(1.0, 0.0, 0.0);
     this.Events = new GeneralEvent[] { };
 }
Example #10
0
        // 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, World.CameraAlignmentSpeed.Zoom != 0.0);
            if (zm != World.CameraCurrentAlignment.Zoom)
            {
                ApplyZoom();
            }
            // 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);
            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)
            {
                TrackManager.UpdateTrackFollower(ref World.CameraTrackFollower, World.CameraCurrentAlignment.TrackPosition, true, false);
                q = true;
            }
            if (q)
            {
                UpdateViewingDistances();
            }
            double dx = World.CameraTrackFollower.WorldDirection.X;
            double dy = World.CameraTrackFollower.WorldDirection.Y;
            double dz = World.CameraTrackFollower.WorldDirection.Z;
            double ux = World.CameraTrackFollower.WorldUp.X;
            double uy = World.CameraTrackFollower.WorldUp.Y;
            double uz = World.CameraTrackFollower.WorldUp.Z;
            double sx = World.CameraTrackFollower.WorldSide.X;
            double sy = World.CameraTrackFollower.WorldSide.Y;
            double sz = World.CameraTrackFollower.WorldSide.Z;
            double tx = World.CameraCurrentAlignment.Position.X;
            double ty = World.CameraCurrentAlignment.Position.Y;
            double tz = World.CameraCurrentAlignment.Position.Z;
            double dx2 = dx, dy2 = dy, dz2 = dz;
            double ux2 = ux, uy2 = uy, uz2 = uz;
            double cx = World.CameraTrackFollower.WorldPosition.X + sx * tx + ux2 * ty + dx2 * tz;
            double cy = World.CameraTrackFollower.WorldPosition.Y + sy * tx + uy2 * ty + dy2 * tz;
            double cz = World.CameraTrackFollower.WorldPosition.Z + sz * tx + uz2 * ty + dz2 * tz;

            if (World.CameraCurrentAlignment.Yaw != 0.0)
            {
                double cosa = Math.Cos(World.CameraCurrentAlignment.Yaw);
                double sina = Math.Sin(World.CameraCurrentAlignment.Yaw);
                World.Rotate(ref dx, ref dy, ref dz, ux, uy, uz, cosa, sina);
                World.Rotate(ref sx, ref sy, ref sz, ux, uy, uz, cosa, sina);
            }
            double p = World.CameraCurrentAlignment.Pitch;

            if (p != 0.0)
            {
                double cosa = Math.Cos(-p);
                double sina = Math.Sin(-p);
                World.Rotate(ref dx, ref dy, ref dz, sx, sy, sz, cosa, sina);
                World.Rotate(ref ux, ref uy, ref uz, sx, sy, sz, cosa, sina);
            }
            if (World.CameraCurrentAlignment.Roll != 0.0)
            {
                double cosa = Math.Cos(-World.CameraCurrentAlignment.Roll);
                double sina = Math.Sin(-World.CameraCurrentAlignment.Roll);
                World.Rotate(ref ux, ref uy, ref uz, dx, dy, dz, cosa, sina);
                World.Rotate(ref sx, ref sy, ref sz, dx, dy, dz, cosa, sina);
            }
            AbsoluteCameraPosition  = new Vector3D(cx, cy, cz);
            AbsoluteCameraDirection = new Vector3D(dx, dy, dz);
            AbsoluteCameraUp        = new Vector3D(ux, uy, uz);
            AbsoluteCameraSide      = new Vector3D(sx, sy, sz);
        }
Example #11
0
		// process events
		private static void ProcessEvents() {
			SDL.SDL_Event Event;
			while (SDL.SDL_PollEvent(out Event) != 0) {
				switch (Event.type) {
						// quit
					case SDL.SDL_EventType.SDL_QUIT:
						Quit = true;
						return;
						// resize
					case SDL.SDL_EventType.SDL_WINDOWEVENT:
						if (Event.window.windowEvent == SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESIZED) {
							Renderer.ScreenWidth = Event.window.data1;
							Renderer.ScreenHeight = Event.window.data2;
							UpdateViewport();
						}
						break;
						// mouse
					case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN:
						MouseCenterX = (short)Event.button.x;
						MouseCenterY = (short)Event.button.y;
						MouseCameraPosition = World.AbsoluteCameraPosition;
						MouseCameraDirection = World.AbsoluteCameraDirection;
						MouseCameraUp = World.AbsoluteCameraUp;
						MouseCameraSide = World.AbsoluteCameraSide;
						MouseButton = Event.button.button;
						break;
					case SDL.SDL_EventType.SDL_MOUSEBUTTONUP:
						MouseButton = 0;
						break;
					case SDL.SDL_EventType.SDL_MOUSEMOTION:
						if (MouseButton == SDL.SDL_BUTTON_LEFT) {
							World.AbsoluteCameraDirection = MouseCameraDirection;
							World.AbsoluteCameraUp = MouseCameraUp;
							World.AbsoluteCameraSide = MouseCameraSide;
							{
								double dx = 0.0025 * (double)(MouseCenterX - Event.motion.x);
								double cosa = Math.Cos(dx);
								double sina = Math.Sin(dx);
								World.Rotate(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z, 0.0, 1.0, 0.0, cosa, sina);
								World.Rotate(ref World.AbsoluteCameraUp.X, ref World.AbsoluteCameraUp.Y, ref World.AbsoluteCameraUp.Z, 0.0, 1.0, 0.0, cosa, sina);
								World.Rotate(ref World.AbsoluteCameraSide.X, ref World.AbsoluteCameraSide.Y, ref World.AbsoluteCameraSide.Z, 0.0, 1.0, 0.0, cosa, sina);
							}
							{
								double dy = 0.0025 * (double)(MouseCenterY - Event.motion.y);
								double cosa = Math.Cos(dy);
								double sina = Math.Sin(dy);
								World.Rotate(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z, World.AbsoluteCameraSide.X, World.AbsoluteCameraSide.Y, World.AbsoluteCameraSide.Z, cosa, sina);
								World.Rotate(ref World.AbsoluteCameraUp.X, ref World.AbsoluteCameraUp.Y, ref World.AbsoluteCameraUp.Z, World.AbsoluteCameraSide.X, World.AbsoluteCameraSide.Y, World.AbsoluteCameraSide.Z, cosa, sina);
							}
							ReducedMode = false;
						} else if (MouseButton == SDL.SDL_BUTTON_RIGHT) {
							World.AbsoluteCameraPosition = MouseCameraPosition;
							double dx = -0.025 * (double)(Event.motion.x - MouseCenterX);
							World.AbsoluteCameraPosition.X += dx * World.AbsoluteCameraSide.X;
							World.AbsoluteCameraPosition.Y += dx * World.AbsoluteCameraSide.Y;
							World.AbsoluteCameraPosition.Z += dx * World.AbsoluteCameraSide.Z;
							double dy = 0.025 * (double)(Event.motion.y - MouseCenterY);
							World.AbsoluteCameraPosition.X += dy * World.AbsoluteCameraUp.X;
							World.AbsoluteCameraPosition.Y += dy * World.AbsoluteCameraUp.Y;
							World.AbsoluteCameraPosition.Z += dy * World.AbsoluteCameraUp.Z;
							ReducedMode = false;
						} else if (MouseButton == SDL.SDL_BUTTON_MIDDLE) {
							World.AbsoluteCameraPosition = MouseCameraPosition;
							double dx = -0.025 * (double)(Event.motion.x - MouseCenterX);
							World.AbsoluteCameraPosition.X += dx * World.AbsoluteCameraSide.X;
							World.AbsoluteCameraPosition.Y += dx * World.AbsoluteCameraSide.Y;
							World.AbsoluteCameraPosition.Z += dx * World.AbsoluteCameraSide.Z;
							double dz = -0.025 * (double)(Event.motion.y - MouseCenterY);
							World.AbsoluteCameraPosition.X += dz * World.AbsoluteCameraDirection.X;
							World.AbsoluteCameraPosition.Y += dz * World.AbsoluteCameraDirection.Y;
							World.AbsoluteCameraPosition.Z += dz * World.AbsoluteCameraDirection.Z;
							ReducedMode = false;
						}
						break;
						// key down
					case SDL.SDL_EventType.SDL_KEYDOWN:
						switch (Event.key.keysym.sym) {
							case SDL.SDL_Keycode.SDLK_LSHIFT:
							case SDL.SDL_Keycode.SDLK_RSHIFT:
								ShiftPressed = true;
								break;
							case SDL.SDL_Keycode.SDLK_F5:
								// reset
								ReducedMode = false;
								LightingRelative = -1.0;
								Game.Reset();
								TextureManager.UnuseAllTextures();
								Fonts.Initialize();
								Interface.ClearMessages();
								for (int i = 0; i < Files.Length; i++) {
									#if !DEBUG
									try {
										#endif
										ObjectManager.UnifiedObject o = ObjectManager.LoadObject(Files[i], System.Text.Encoding.UTF8, ObjectManager.ObjectLoadMode.Normal, false, false, false);
										ObjectManager.CreateObject(o, new World.Vector3D(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0);
										#if !DEBUG
									} catch (Exception ex) {
										Interface.AddMessage(Interface.MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Files[i] + ".");
									}
									#endif
								}
								ObjectManager.InitializeVisibility();
								ObjectManager.UpdateVisibility(0.0, true);
								ObjectManager.UpdateAnimatedWorldObjects(0.01, true);
								break;
							case SDL.SDL_Keycode.SDLK_F7:
								{
									OpenFileDialog Dialog = new OpenFileDialog();
									Dialog.CheckFileExists = true;
									Dialog.Multiselect = true;
									Dialog.Filter = "CSV/B3D/X/ANIMATED files|*.csv;*.b3d;*.x;*.animated|All files|*";
									if (Dialog.ShowDialog() == DialogResult.OK) {
										string[] f = Dialog.FileNames;
										int n = Files.Length;
										Array.Resize<string>(ref Files, n + f.Length);
										for (int i = 0; i < f.Length; i++) {
											Files[n + i] = f[i];
										}
										// reset
										ReducedMode = false;
										LightingRelative = -1.0;
										Game.Reset();
										TextureManager.UnuseAllTextures();
										Fonts.Initialize();
										Interface.ClearMessages();
										for (int i = 0; i < Files.Length; i++) {
											#if !DEBUG
											try {
												#endif
												ObjectManager.UnifiedObject o = ObjectManager.LoadObject(Files[i], System.Text.Encoding.UTF8, ObjectManager.ObjectLoadMode.Normal, false, false, false);
												ObjectManager.CreateObject(o, new World.Vector3D(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0);
												#if !DEBUG
											} catch (Exception ex) {
												Interface.AddMessage(Interface.MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Files[i] + ".");
											}
											#endif
										}
										ObjectManager.InitializeVisibility();
										ObjectManager.FinishCreatingObjects();
										ObjectManager.UpdateVisibility(0.0, true);
										ObjectManager.UpdateAnimatedWorldObjects(0.01, true);
									}
								} break;
							case SDL.SDL_Keycode.SDLK_F9:
								if (Interface.MessageCount != 0) {
									formMessages.ShowMessages();
								}
								break;
							case SDL.SDL_Keycode.SDLK_DELETE:
								ReducedMode = false;
								LightingRelative = -1.0;
								Game.Reset();
								TextureManager.UnuseAllTextures();
								Fonts.Initialize();
								Interface.ClearMessages();
								Files = new string[] { };
								UpdateCaption();
								break;
							case SDL.SDL_Keycode.SDLK_LEFT:
								RotateX = -1;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_RIGHT:
								RotateX = 1;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_UP:
								RotateY = -1;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_DOWN:
								RotateY = 1;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_a:
							case SDL.SDL_Keycode.SDLK_KP_4:
								MoveX = -1;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_d:
							case SDL.SDL_Keycode.SDLK_KP_6:
								MoveX = 1;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_KP_8:
								MoveY = 1;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_KP_2:
								MoveY = -1;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_w:
							case SDL.SDL_Keycode.SDLK_KP_9:
								MoveZ = 1;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_s:
							case SDL.SDL_Keycode.SDLK_KP_3:
								MoveZ = -1;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_KP_5:
								ResetCamera();
								break;
							case SDL.SDL_Keycode.SDLK_f:
							case SDL.SDL_Keycode.SDLK_F1:
								Renderer.OptionWireframe = !Renderer.OptionWireframe;
								if (Renderer.OptionWireframe) {
									GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
								} else {
									GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
								} break;
							case SDL.SDL_Keycode.SDLK_n:
							case SDL.SDL_Keycode.SDLK_F2:
								Renderer.OptionNormals = !Renderer.OptionNormals;
								break;
							case SDL.SDL_Keycode.SDLK_l:
							case SDL.SDL_Keycode.SDLK_F3:
								LightingTarget = 1 - LightingTarget;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_i:
							case SDL.SDL_Keycode.SDLK_F4:
								Renderer.OptionInterface = !Renderer.OptionInterface;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_g:
							case SDL.SDL_Keycode.SDLK_c:
								Renderer.OptionCoordinateSystem = !Renderer.OptionCoordinateSystem;
								ReducedMode = false;
								break;
							case SDL.SDL_Keycode.SDLK_b:
								if (ShiftPressed) {
									ColorDialog dialog = new ColorDialog();
									dialog.FullOpen = true;
									if (dialog.ShowDialog() == DialogResult.OK) {
										Renderer.BackgroundColor = -1;
										Renderer.ApplyBackgroundColor(dialog.Color.R, dialog.Color.G, dialog.Color.B);
									}
								} else {
									Renderer.BackgroundColor++;
									if (Renderer.BackgroundColor >= Renderer.MaxBackgroundColor) {
										Renderer.BackgroundColor = 0;
									}
									Renderer.ApplyBackgroundColor();
								}
								ReducedMode = false;
								break;
						} break;
						// key up
					case SDL.SDL_EventType.SDL_KEYUP:
						switch (Event.key.keysym.sym) {
							case SDL.SDL_Keycode.SDLK_LSHIFT:
							case SDL.SDL_Keycode.SDLK_RSHIFT:
								ShiftPressed = false;
								break;
							case SDL.SDL_Keycode.SDLK_LEFT:
							case SDL.SDL_Keycode.SDLK_RIGHT:
								RotateX = 0;
								break;
							case SDL.SDL_Keycode.SDLK_UP:
							case SDL.SDL_Keycode.SDLK_DOWN:
								RotateY = 0;
								break;
							case SDL.SDL_Keycode.SDLK_a:
							case SDL.SDL_Keycode.SDLK_d:
							case SDL.SDL_Keycode.SDLK_KP_4:
							case SDL.SDL_Keycode.SDLK_KP_6:
								MoveX = 0;
								break;
							case SDL.SDL_Keycode.SDLK_KP_8:
							case SDL.SDL_Keycode.SDLK_KP_2:
								MoveY = 0;
								break;
							case SDL.SDL_Keycode.SDLK_w:
							case SDL.SDL_Keycode.SDLK_s:
							case SDL.SDL_Keycode.SDLK_KP_9:
							case SDL.SDL_Keycode.SDLK_KP_3:
								MoveZ = 0;
								break;
						} break;
				}
			}
		}
Example #12
0
		// apply route data
		private static void ApplyRouteData(string FileName, System.Text.Encoding Encoding, ref RouteData Data, bool PreviewOnly) {
			string SignalPath, LimitPath, LimitGraphicsPath, TransponderPath;
			ObjectManager.StaticObject SignalPost, LimitPostStraight, LimitPostLeft, LimitPostRight, LimitPostInfinite;
			ObjectManager.StaticObject LimitOneDigit, LimitTwoDigits, LimitThreeDigits, StopPost;
			ObjectManager.StaticObject TransponderS, TransponderSN, TransponderFalseStart, TransponderPOrigin, TransponderPStop;
			if (!PreviewOnly) {
				string CompatibilityFolder = Program.FileSystem.GetDataFolder("Compatibility");
				// load compatibility objects
				SignalPath = OpenBveApi.Path.CombineDirectory(CompatibilityFolder, "Signals");
				SignalPost = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalPath, "signal_post.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				LimitPath = OpenBveApi.Path.CombineDirectory(CompatibilityFolder, "Limits");
				LimitGraphicsPath = OpenBveApi.Path.CombineDirectory(LimitPath, "Graphics");
				LimitPostStraight = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_straight.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				LimitPostLeft = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_left.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				LimitPostRight = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_right.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				LimitPostInfinite = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_infinite.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				LimitOneDigit = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_1_digit.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				LimitTwoDigits = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_2_digits.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				LimitThreeDigits = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_3_digits.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				StopPost = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(CompatibilityFolder, "stop.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				TransponderPath = OpenBveApi.Path.CombineDirectory(CompatibilityFolder, "Transponders");
				TransponderS = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "s.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				TransponderSN = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "sn.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				TransponderFalseStart = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "falsestart.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				TransponderPOrigin = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "porigin.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
				TransponderPStop = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "pstop.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
			} else {
				SignalPath = null;
				LimitPath = null;
				LimitGraphicsPath = null;
				TransponderPath = null;
				SignalPost = null;
				LimitPostStraight = null;
				LimitPostLeft = null;
				LimitPostRight = null;
				LimitPostInfinite = null;
				LimitOneDigit = null;
				LimitTwoDigits = null;
				LimitThreeDigits = null;
				StopPost = null;
				TransponderS = null;
				TransponderSN = null;
				TransponderFalseStart = null;
				TransponderPOrigin = null;
				TransponderPStop = null;
			}
			// initialize
			System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
			int LastBlock = (int)Math.Floor((Data.TrackPosition + 600.0) / Data.BlockInterval + 0.001) + 1;
			int BlocksUsed = Data.Blocks.Length;
			CreateMissingBlocks(ref Data, ref BlocksUsed, LastBlock, PreviewOnly);
			Array.Resize<Block>(ref Data.Blocks, BlocksUsed);
			// interpolate height
			if (!PreviewOnly) {
				int z = 0;
				for (int i = 0; i < Data.Blocks.Length; i++) {
					if (!double.IsNaN(Data.Blocks[i].Height)) {
						for (int j = i - 1; j >= 0; j--) {
							if (!double.IsNaN(Data.Blocks[j].Height)) {
								double a = Data.Blocks[j].Height;
								double b = Data.Blocks[i].Height;
								double d = (b - a) / (double)(i - j);
								for (int k = j + 1; k < i; k++) {
									a += d;
									Data.Blocks[k].Height = a;
								}
								break;
							}
						}
						z = i;
					}
				}
				for (int i = z + 1; i < Data.Blocks.Length; i++) {
					Data.Blocks[i].Height = Data.Blocks[z].Height;
				}
			}
			// background
			if (!PreviewOnly) {
				if (Data.Blocks[0].Background >= 0 & Data.Blocks[0].Background < Data.Backgrounds.Length) {
					World.CurrentBackground = Data.Backgrounds[Data.Blocks[0].Background];
				} else {
					World.CurrentBackground = new World.Background(-1, 6, false);
				}
				World.TargetBackground = World.CurrentBackground;
			}
			// brightness
			int CurrentBrightnessElement = -1;
			int CurrentBrightnessEvent = -1;
			float CurrentBrightnessValue = 1.0f;
			double CurrentBrightnessTrackPosition = (double)Data.FirstUsedBlock * Data.BlockInterval;
			if (!PreviewOnly) {
				for (int i = Data.FirstUsedBlock; i < Data.Blocks.Length; i++) {
					if (Data.Blocks[i].Brightness != null && Data.Blocks[i].Brightness.Length != 0) {
						CurrentBrightnessValue = Data.Blocks[i].Brightness[0].Value;
						CurrentBrightnessTrackPosition = Data.Blocks[i].Brightness[0].Value;
						break;
					}
				}
			}
			// create objects and track
			World.Vector3D Position = new World.Vector3D(0.0, 0.0, 0.0);
			World.Vector2D Direction = new World.Vector2D(0.0, 1.0);
			TrackManager.CurrentTrack = new TrackManager.Track();
			TrackManager.CurrentTrack.Elements = new TrackManager.TrackElement[] { };
			double CurrentSpeedLimit = double.PositiveInfinity;
			int CurrentRunIndex = 0;
			int CurrentFlangeIndex = 0;
			if (Data.FirstUsedBlock < 0) Data.FirstUsedBlock = 0;
			TrackManager.CurrentTrack.Elements = new TrackManager.TrackElement[256];
			int CurrentTrackLength = 0;
			int PreviousFogElement = -1;
			int PreviousFogEvent = -1;
			Game.Fog PreviousFog = new Game.Fog(Game.NoFogStart, Game.NoFogEnd, new World.ColorRGB(128, 128, 128), -Data.BlockInterval);
			Game.Fog CurrentFog = new Game.Fog(Game.NoFogStart, Game.NoFogEnd, new World.ColorRGB(128, 128, 128), 0.0);
			// process blocks
			double progressFactor = Data.Blocks.Length - Data.FirstUsedBlock == 0 ? 0.5 : 0.5 / (double)(Data.Blocks.Length - Data.FirstUsedBlock);
			for (int i = Data.FirstUsedBlock; i < Data.Blocks.Length; i++) {
				Loading.RouteProgress = 0.6667 + (double)(i - Data.FirstUsedBlock) * progressFactor;
				if ((i & 15) == 0) {
					System.Threading.Thread.Sleep(1);
					if (Loading.Cancel) return;
				}
				double StartingDistance = (double)i * Data.BlockInterval;
				double EndingDistance = StartingDistance + Data.BlockInterval;
				// normalize
				World.Normalize(ref Direction.X, ref Direction.Y);
				// track
				if (!PreviewOnly) {
					if (Data.Blocks[i].Cycle.Length == 1 && Data.Blocks[i].Cycle[0] == -1) {
						if (Data.Structure.Cycle.Length == 0 || Data.Structure.Cycle[0] == null) {
							Data.Blocks[i].Cycle = new int[] { 0 };
						} else {
							Data.Blocks[i].Cycle = Data.Structure.Cycle[0];
						}
					}
				}
				TrackManager.TrackElement WorldTrackElement = Data.Blocks[i].CurrentTrackState;
				int n = CurrentTrackLength;
				if (n >= TrackManager.CurrentTrack.Elements.Length) {
					Array.Resize<TrackManager.TrackElement>(ref TrackManager.CurrentTrack.Elements, TrackManager.CurrentTrack.Elements.Length << 1);
				}
				CurrentTrackLength++;
				TrackManager.CurrentTrack.Elements[n] = WorldTrackElement;
				TrackManager.CurrentTrack.Elements[n].WorldPosition = Position;
				TrackManager.CurrentTrack.Elements[n].WorldDirection = new World.Vector3D(Direction, Data.Blocks[i].Pitch);
				TrackManager.CurrentTrack.Elements[n].WorldSide = new World.Vector3D(Direction.Y, 0.0, -Direction.X);
				World.Cross(TrackManager.CurrentTrack.Elements[n].WorldDirection.X, TrackManager.CurrentTrack.Elements[n].WorldDirection.Y, TrackManager.CurrentTrack.Elements[n].WorldDirection.Z, TrackManager.CurrentTrack.Elements[n].WorldSide.X, TrackManager.CurrentTrack.Elements[n].WorldSide.Y, TrackManager.CurrentTrack.Elements[n].WorldSide.Z, out TrackManager.CurrentTrack.Elements[n].WorldUp.X, out TrackManager.CurrentTrack.Elements[n].WorldUp.Y, out TrackManager.CurrentTrack.Elements[n].WorldUp.Z);
				TrackManager.CurrentTrack.Elements[n].StartingTrackPosition = StartingDistance;
				TrackManager.CurrentTrack.Elements[n].Events = new TrackManager.GeneralEvent[] { };
				TrackManager.CurrentTrack.Elements[n].AdhesionMultiplier = Data.Blocks[i].AdhesionMultiplier;
				TrackManager.CurrentTrack.Elements[n].CsvRwAccuracyLevel = Data.Blocks[i].Accuracy;
				// background
				if (!PreviewOnly) {
					if (Data.Blocks[i].Background >= 0) {
						int typ;
						if (i == Data.FirstUsedBlock) {
							typ = Data.Blocks[i].Background;
						} else {
							typ = Data.Backgrounds.Length > 0 ? 0 : -1;
							for (int j = i - 1; j >= Data.FirstUsedBlock; j--) {
								if (Data.Blocks[j].Background >= 0) {
									typ = Data.Blocks[j].Background;
									break;
								}
							}
						}
						if (typ >= 0 & typ < Data.Backgrounds.Length) {
							int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
							Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
							TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.BackgroundChangeEvent(0.0, Data.Backgrounds[typ], Data.Backgrounds[Data.Blocks[i].Background]);
						}
					}
				}
				// brightness
				if (!PreviewOnly) {
					for (int j = 0; j < Data.Blocks[i].Brightness.Length; j++) {
						int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
						Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
						double d = Data.Blocks[i].Brightness[j].TrackPosition - StartingDistance;
						TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.BrightnessChangeEvent(d, Data.Blocks[i].Brightness[j].Value, CurrentBrightnessValue, Data.Blocks[i].Brightness[j].TrackPosition - CurrentBrightnessTrackPosition, Data.Blocks[i].Brightness[j].Value, 0.0);
						if (CurrentBrightnessElement >= 0 & CurrentBrightnessEvent >= 0) {
							TrackManager.BrightnessChangeEvent bce = (TrackManager.BrightnessChangeEvent)TrackManager.CurrentTrack.Elements[CurrentBrightnessElement].Events[CurrentBrightnessEvent];
							bce.NextBrightness = Data.Blocks[i].Brightness[j].Value;
							bce.NextDistance = Data.Blocks[i].Brightness[j].TrackPosition - CurrentBrightnessTrackPosition;
						}
						CurrentBrightnessElement = n;
						CurrentBrightnessEvent = m;
						CurrentBrightnessValue = Data.Blocks[i].Brightness[j].Value;
						CurrentBrightnessTrackPosition = Data.Blocks[i].Brightness[j].TrackPosition;
					}
				}
				// fog
				if (!PreviewOnly) {
					if (Data.FogTransitionMode) {
						if (Data.Blocks[i].FogDefined) {
							Data.Blocks[i].Fog.TrackPosition = StartingDistance;
							int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
							Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
							TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.FogChangeEvent(0.0, PreviousFog, Data.Blocks[i].Fog, Data.Blocks[i].Fog);
							if (PreviousFogElement >= 0 & PreviousFogEvent >= 0) {
								TrackManager.FogChangeEvent e = (TrackManager.FogChangeEvent)TrackManager.CurrentTrack.Elements[PreviousFogElement].Events[PreviousFogEvent];
								e.NextFog = Data.Blocks[i].Fog;
							} else {
								Game.PreviousFog = PreviousFog;
								Game.CurrentFog = PreviousFog;
								Game.NextFog = Data.Blocks[i].Fog;
							}
							PreviousFog = Data.Blocks[i].Fog;
							PreviousFogElement = n;
							PreviousFogEvent = m;
						}
					} else {
						Data.Blocks[i].Fog.TrackPosition = StartingDistance + Data.BlockInterval;
						int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
						Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
						TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.FogChangeEvent(0.0, PreviousFog, CurrentFog, Data.Blocks[i].Fog);
						PreviousFog = CurrentFog;
						CurrentFog = Data.Blocks[i].Fog;
					}
				}
				// rail sounds
				if (!PreviewOnly) {
					int j = Data.Blocks[i].RailType[0];
					int r = j < Data.Structure.Run.Length ? Data.Structure.Run[j] : 0;
					int f = j < Data.Structure.Flange.Length ? Data.Structure.Flange[j] : 0;
					int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
					Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
					TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.RailSoundsChangeEvent(0.0, CurrentRunIndex, CurrentFlangeIndex, r, f);
					CurrentRunIndex = r;
					CurrentFlangeIndex = f;
				}
				// point sound
				if (!PreviewOnly) {
					if (i < Data.Blocks.Length - 1) {
						bool q = false;
						for (int j = 0; j < Data.Blocks[i].Rail.Length; j++) {
							if (Data.Blocks[i].Rail[j].RailStart & Data.Blocks[i + 1].Rail.Length > j) {
								bool qx = Math.Sign(Data.Blocks[i].Rail[j].RailStartX) != Math.Sign(Data.Blocks[i + 1].Rail[j].RailEndX);
								bool qy = Data.Blocks[i].Rail[j].RailStartY * Data.Blocks[i + 1].Rail[j].RailEndY <= 0.0;
								if (qx & qy) {
									q = true;
									break;
								}
							}
						}
						if (q) {
							int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
							Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
							TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.SoundEvent(0.0, TrackManager.SoundEvent.SoundIndexTrainPoint, false, false, true, new World.Vector3D(0.0, 0.0, 0.0), 12.5);
						}
					}
				}
				// station
				if (Data.Blocks[i].Station >= 0) {
					// station
					int s = Data.Blocks[i].Station;
					int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
					Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
					TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.StationStartEvent(0.0, s);
					double dx, dy = 3.0;
					if (Game.Stations[s].OpenLeftDoors & !Game.Stations[s].OpenRightDoors) {
						dx = -5.0;
					} else if (!Game.Stations[s].OpenLeftDoors & Game.Stations[s].OpenRightDoors) {
						dx = 5.0;
					} else {
						dx = 0.0;
					}
					Game.Stations[s].SoundOrigin.X = Position.X + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.X + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.X;
					Game.Stations[s].SoundOrigin.Y = Position.Y + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.Y + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.Y;
					Game.Stations[s].SoundOrigin.Z = Position.Z + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.Z + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.Z;
					// passalarm
					if (!PreviewOnly) {
						if (Data.Blocks[i].StationPassAlarm) {
							int b = i - 6;
							if (b >= 0) {
								int j = b - Data.FirstUsedBlock;
								if (j >= 0) {
									m = TrackManager.CurrentTrack.Elements[j].Events.Length;
									Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[j].Events, m + 1);
									TrackManager.CurrentTrack.Elements[j].Events[m] = new TrackManager.StationPassAlarmEvent(0.0);
								}
							}
						}
					}
				}
				// stop
				for (int j = 0; j < Data.Blocks[i].Stop.Length; j++) {
					int s = Data.Blocks[i].Stop[j].Station;
					int t = Game.Stations[s].Stops.Length;
					Array.Resize<Game.StationStop>(ref Game.Stations[s].Stops, t + 1);
					Game.Stations[s].Stops[t].TrackPosition = Data.Blocks[i].Stop[j].TrackPosition;
					Game.Stations[s].Stops[t].ForwardTolerance = Data.Blocks[i].Stop[j].ForwardTolerance;
					Game.Stations[s].Stops[t].BackwardTolerance = Data.Blocks[i].Stop[j].BackwardTolerance;
					Game.Stations[s].Stops[t].Cars = Data.Blocks[i].Stop[j].Cars;
					double dx, dy = 2.0;
					if (Game.Stations[s].OpenLeftDoors & !Game.Stations[s].OpenRightDoors) {
						dx = -5.0;
					} else if (!Game.Stations[s].OpenLeftDoors & Game.Stations[s].OpenRightDoors) {
						dx = 5.0;
					} else {
						dx = 0.0;
					}
					Game.Stations[s].SoundOrigin.X = Position.X + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.X + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.X;
					Game.Stations[s].SoundOrigin.Y = Position.Y + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.Y + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.Y;
					Game.Stations[s].SoundOrigin.Z = Position.Z + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.Z + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.Z;
				}
				// limit
				for (int j = 0; j < Data.Blocks[i].Limit.Length; j++) {
					int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
					Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
					double d = Data.Blocks[i].Limit[j].TrackPosition - StartingDistance;
					TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.LimitChangeEvent(d, CurrentSpeedLimit, Data.Blocks[i].Limit[j].Speed);
					CurrentSpeedLimit = Data.Blocks[i].Limit[j].Speed;
				}
				// marker
				if (!PreviewOnly) {
					for (int j = 0; j < Data.Markers.Length; j++) {
						if (Data.Markers[j].StartingPosition >= StartingDistance & Data.Markers[j].StartingPosition < EndingDistance) {
							int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
							Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
							double d = Data.Markers[j].StartingPosition - StartingDistance;
							int t = Data.Markers[j].Texture;
							TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.MarkerStartEvent(d, t);
						}
						if (Data.Markers[j].EndingPosition >= StartingDistance & Data.Markers[j].EndingPosition < EndingDistance) {
							int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
							Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
							double d = Data.Markers[j].EndingPosition - StartingDistance;
							int t = Data.Markers[j].Texture;
							TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.MarkerEndEvent(d, t);
						}
					}
				}
				// sound
				if (!PreviewOnly) {
					for (int j = 0; j < Data.Blocks[i].Sound.Length; j++) {
						if (Data.Blocks[i].Sound[j].Type == SoundType.TrainStatic | Data.Blocks[i].Sound[j].Type == SoundType.TrainDynamic) {
							int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
							Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
							double d = Data.Blocks[i].Sound[j].TrackPosition - StartingDistance;
							switch (Data.Blocks[i].Sound[j].Type) {
								case SoundType.TrainStatic:
									TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.SoundEvent(d, Data.Blocks[i].Sound[j].SoundIndex, true, true, false, new World.Vector3D(0.0, 0.0, 0.0), 0.0);
									break;
								case SoundType.TrainDynamic:
									TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.SoundEvent(d, Data.Blocks[i].Sound[j].SoundIndex, false, false, true, new World.Vector3D(0.0, 0.0, 0.0), Data.Blocks[i].Sound[j].Speed);
									break;
							}
						}
					}
				}
				// turn
				if (Data.Blocks[i].Turn != 0.0) {
					double ag = -Math.Atan(Data.Blocks[i].Turn);
					double cosag = Math.Cos(ag);
					double sinag = Math.Sin(ag);
					World.Rotate(ref Direction, cosag, sinag);
					World.RotatePlane(ref TrackManager.CurrentTrack.Elements[n].WorldDirection, cosag, sinag);
					World.RotatePlane(ref TrackManager.CurrentTrack.Elements[n].WorldSide, cosag, sinag);
					World.Cross(TrackManager.CurrentTrack.Elements[n].WorldDirection.X, TrackManager.CurrentTrack.Elements[n].WorldDirection.Y, TrackManager.CurrentTrack.Elements[n].WorldDirection.Z, TrackManager.CurrentTrack.Elements[n].WorldSide.X, TrackManager.CurrentTrack.Elements[n].WorldSide.Y, TrackManager.CurrentTrack.Elements[n].WorldSide.Z, out TrackManager.CurrentTrack.Elements[n].WorldUp.X, out TrackManager.CurrentTrack.Elements[n].WorldUp.Y, out TrackManager.CurrentTrack.Elements[n].WorldUp.Z);
				}
				// curves
				double a = 0.0;
				double c = Data.BlockInterval;
				double h = 0.0;
				if (WorldTrackElement.CurveRadius != 0.0 & Data.Blocks[i].Pitch != 0.0) {
					double d = Data.BlockInterval;
					double p = Data.Blocks[i].Pitch;
					double r = WorldTrackElement.CurveRadius;
					double s = d / Math.Sqrt(1.0 + p * p);
					h = s * p;
					double b = s / Math.Abs(r);
					c = Math.Sqrt(2.0 * r * r * (1.0 - Math.Cos(b)));
					a = 0.5 * (double)Math.Sign(r) * b;
					World.Rotate(ref Direction, Math.Cos(-a), Math.Sin(-a));
				} else if (WorldTrackElement.CurveRadius != 0.0) {
					double d = Data.BlockInterval;
					double r = WorldTrackElement.CurveRadius;
					double b = d / Math.Abs(r);
					c = Math.Sqrt(2.0 * r * r * (1.0 - Math.Cos(b)));
					a = 0.5 * (double)Math.Sign(r) * b;
					World.Rotate(ref Direction, Math.Cos(-a), Math.Sin(-a));
				} else if (Data.Blocks[i].Pitch != 0.0) {
					double p = Data.Blocks[i].Pitch;
					double d = Data.BlockInterval;
					c = d / Math.Sqrt(1.0 + p * p);
					h = c * p;
				}
				double TrackYaw = Math.Atan2(Direction.X, Direction.Y);
				double TrackPitch = Math.Atan(Data.Blocks[i].Pitch);
				World.Transformation GroundTransformation = new World.Transformation(TrackYaw, 0.0, 0.0);
				World.Transformation TrackTransformation = new World.Transformation(TrackYaw, TrackPitch, 0.0);
				World.Transformation NullTransformation = new World.Transformation(0.0, 0.0, 0.0);
				// ground
				if (!PreviewOnly) {
					int cb = (int)Math.Floor((double)i + 0.001);
					int ci = (cb % Data.Blocks[i].Cycle.Length + Data.Blocks[i].Cycle.Length) % Data.Blocks[i].Cycle.Length;
					int gi = Data.Blocks[i].Cycle[ci];
					if (gi >= 0 & gi < Data.Structure.Ground.Length) {
						if (Data.Structure.Ground[gi] != null) {
							ObjectManager.CreateObject(Data.Structure.Ground[Data.Blocks[i].Cycle[ci]], World.Vector3D.Add(Position, new World.Vector3D(0.0, -Data.Blocks[i].Height, 0.0)), GroundTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
						}
					}
				}
				// ground-aligned free objects
				if (!PreviewOnly) {
					for (int j = 0; j < Data.Blocks[i].GroundFreeObj.Length; j++) {
						int sttype = Data.Blocks[i].GroundFreeObj[j].Type;
						double d = Data.Blocks[i].GroundFreeObj[j].TrackPosition - StartingDistance;
						double dx = Data.Blocks[i].GroundFreeObj[j].X;
						double dy = Data.Blocks[i].GroundFreeObj[j].Y;
						World.Vector3D wpos = World.Vector3D.Add(Position, new World.Vector3D(Direction.X * d + Direction.Y * dx, dy - Data.Blocks[i].Height, Direction.Y * d - Direction.X * dx));
						double tpos = Data.Blocks[i].GroundFreeObj[j].TrackPosition;
						ObjectManager.CreateObject(Data.Structure.FreeObj[sttype], wpos, GroundTransformation, new World.Transformation(Data.Blocks[i].GroundFreeObj[j].Yaw, Data.Blocks[i].GroundFreeObj[j].Pitch, Data.Blocks[i].GroundFreeObj[j].Roll), Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos);
					}
				}
				// rail-aligned objects
				if (!PreviewOnly) {
					for (int j = 0; j < Data.Blocks[i].Rail.Length; j++) {
						if (j > 0 && !Data.Blocks[i].Rail[j].RailStart) continue;
						// rail
						World.Vector3D pos;
						World.Transformation RailTransformation;
						double planar, updown;
						if (j == 0) {
							// rail 0
							pos = Position;
							planar = 0.0;
							updown = 0.0;
							RailTransformation = new World.Transformation(TrackTransformation, planar, updown, 0.0);
							pos = Position;
						} else {
							// rails 1-infinity
							double x = Data.Blocks[i].Rail[j].RailStartX;
							double y = Data.Blocks[i].Rail[j].RailStartY;
							World.Vector3D offset = new World.Vector3D(Direction.Y * x, y, -Direction.X * x);
							pos = World.Vector3D.Add(Position, offset);
							double dh;
							if (i < Data.Blocks.Length - 1 && Data.Blocks[i + 1].Rail.Length > j) {
								// take orientation of upcoming block into account
								World.Vector2D Direction2 = Direction;
								World.Vector3D Position2 = Position;
								Position2.X += Direction.X * c;
								Position2.Y += h;
								Position2.Z += Direction.Y * c;
								if (a != 0.0) {
									World.Rotate(ref Direction2, Math.Cos(-a), Math.Sin(-a));
								}
								if (Data.Blocks[i + 1].Turn != 0.0) {
									double ag = -Math.Atan(Data.Blocks[i + 1].Turn);
									double cosag = Math.Cos(ag);
									double sinag = Math.Sin(ag);
									World.Rotate(ref Direction2, cosag, sinag);
								}
								double a2 = 0.0;
								double c2 = Data.BlockInterval;
								double h2 = 0.0;
								if (Data.Blocks[i + 1].CurrentTrackState.CurveRadius != 0.0 & Data.Blocks[i + 1].Pitch != 0.0) {
									double d2 = Data.BlockInterval;
									double p2 = Data.Blocks[i + 1].Pitch;
									double r2 = Data.Blocks[i + 1].CurrentTrackState.CurveRadius;
									double s2 = d2 / Math.Sqrt(1.0 + p2 * p2);
									h2 = s2 * p2;
									double b2 = s2 / Math.Abs(r2);
									c2 = Math.Sqrt(2.0 * r2 * r2 * (1.0 - Math.Cos(b2)));
									a2 = 0.5 * (double)Math.Sign(r2) * b2;
									World.Rotate(ref Direction2, Math.Cos(-a2), Math.Sin(-a2));
								} else if (Data.Blocks[i + 1].CurrentTrackState.CurveRadius != 0.0) {
									double d2 = Data.BlockInterval;
									double r2 = Data.Blocks[i + 1].CurrentTrackState.CurveRadius;
									double b2 = d2 / Math.Abs(r2);
									c2 = Math.Sqrt(2.0 * r2 * r2 * (1.0 - Math.Cos(b2)));
									a2 = 0.5 * (double)Math.Sign(r2) * b2;
									World.Rotate(ref Direction2, Math.Cos(-a2), Math.Sin(-a2));
								} else if (Data.Blocks[i + 1].Pitch != 0.0) {
									double p2 = Data.Blocks[i + 1].Pitch;
									double d2 = Data.BlockInterval;
									c2 = d2 / Math.Sqrt(1.0 + p2 * p2);
									h2 = c2 * p2;
								}
								double TrackYaw2 = Math.Atan2(Direction2.X, Direction2.Y);
								double TrackPitch2 = Math.Atan(Data.Blocks[i + 1].Pitch);
								World.Transformation GroundTransformation2 = new World.Transformation(TrackYaw2, 0.0, 0.0);
								World.Transformation TrackTransformation2 = new World.Transformation(TrackYaw2, TrackPitch2, 0.0);
								double x2 = Data.Blocks[i + 1].Rail[j].RailEndX;
								double y2 = Data.Blocks[i + 1].Rail[j].RailEndY;
								World.Vector3D offset2 = new World.Vector3D(Direction2.Y * x2, y2, -Direction2.X * x2);
								World.Vector3D pos2 = World.Vector3D.Add(Position2, offset2);
								double rx = pos2.X - pos.X;
								double ry = pos2.Y - pos.Y;
								double rz = pos2.Z - pos.Z;
								World.Normalize(ref rx, ref ry, ref rz);
								RailTransformation.Z = new World.Vector3D(rx, ry, rz);
								RailTransformation.X = new World.Vector3D(rz, 0.0, -rx);
								World.Normalize(ref RailTransformation.X.X, ref RailTransformation.X.Z);
								RailTransformation.Y = World.Cross(RailTransformation.Z, RailTransformation.X);
								double dx = Data.Blocks[i + 1].Rail[j].RailEndX - Data.Blocks[i].Rail[j].RailStartX;
								double dy = Data.Blocks[i + 1].Rail[j].RailEndY - Data.Blocks[i].Rail[j].RailStartY;
								planar = Math.Atan(dx / c);
								dh = dy / c;
								updown = Math.Atan(dh);
							} else {
								planar = 0.0;
								dh = 0.0;
								updown = 0.0;
								RailTransformation = new World.Transformation(TrackTransformation, 0.0, 0.0, 0.0);
							}
						}
						if (Data.Blocks[i].RailType[j] < Data.Structure.Rail.Length) {
							if (Data.Structure.Rail[Data.Blocks[i].RailType[j]] != null) {
								ObjectManager.CreateObject(Data.Structure.Rail[Data.Blocks[i].RailType[j]], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
							}
						}
						// points of interest
						for (int k = 0; k < Data.Blocks[i].PointsOfInterest.Length; k++) {
							if (Data.Blocks[i].PointsOfInterest[k].RailIndex == j) {
								double d = Data.Blocks[i].PointsOfInterest[k].TrackPosition - StartingDistance;
								double x = Data.Blocks[i].PointsOfInterest[k].X;
								double y = Data.Blocks[i].PointsOfInterest[k].Y;
								int m = Game.PointsOfInterest.Length;
								Array.Resize<Game.PointOfInterest>(ref Game.PointsOfInterest, m + 1);
								Game.PointsOfInterest[m].TrackPosition = Data.Blocks[i].PointsOfInterest[k].TrackPosition;
								if (i < Data.Blocks.Length - 1 && Data.Blocks[i + 1].Rail.Length > j) {
									double dx = Data.Blocks[i + 1].Rail[j].RailEndX - Data.Blocks[i].Rail[j].RailStartX;
									double dy = Data.Blocks[i + 1].Rail[j].RailEndY - Data.Blocks[i].Rail[j].RailStartY;
									dx = Data.Blocks[i].Rail[j].RailStartX + d / Data.BlockInterval * dx;
									dy = Data.Blocks[i].Rail[j].RailStartY + d / Data.BlockInterval * dy;
									Game.PointsOfInterest[m].TrackOffset = new World.Vector3D(x + dx, y + dy, 0.0);
								} else {
									double dx = Data.Blocks[i].Rail[j].RailStartX;
									double dy = Data.Blocks[i].Rail[j].RailStartY;
									Game.PointsOfInterest[m].TrackOffset = new World.Vector3D(x + dx, y + dy, 0.0);
								}
								Game.PointsOfInterest[m].TrackYaw = Data.Blocks[i].PointsOfInterest[k].Yaw + planar;
								Game.PointsOfInterest[m].TrackPitch = Data.Blocks[i].PointsOfInterest[k].Pitch + updown;
								Game.PointsOfInterest[m].TrackRoll = Data.Blocks[i].PointsOfInterest[k].Roll;
								Game.PointsOfInterest[m].Text = Data.Blocks[i].PointsOfInterest[k].Text;
							}
						}
						// poles
						if (Data.Blocks[i].RailPole.Length > j && Data.Blocks[i].RailPole[j].Exists) {
							double dz = StartingDistance / Data.Blocks[i].RailPole[j].Interval;
							dz -= Math.Floor(dz + 0.5);
							if (dz >= -0.01 & dz <= 0.01) {
								if (Data.Blocks[i].RailPole[j].Mode == 0) {
									if (Data.Blocks[i].RailPole[j].Location <= 0.0) {
										ObjectManager.CreateObject(Data.Structure.Poles[0][Data.Blocks[i].RailPole[j].Type], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
									} else {
										ObjectManager.UnifiedObject Pole = GetMirroredObject(Data.Structure.Poles[0][Data.Blocks[i].RailPole[j].Type]);
										ObjectManager.CreateObject(Pole, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
									}
								} else {
									int m = Data.Blocks[i].RailPole[j].Mode;
									double dx = -Data.Blocks[i].RailPole[j].Location * 3.8;
									double wa = Math.Atan2(Direction.Y, Direction.X) - planar;
									double wx = Math.Cos(wa);
									double wy = Math.Tan(updown);
									double wz = Math.Sin(wa);
									World.Normalize(ref wx, ref wy, ref wz);
									double sx = Direction.Y;
									double sy = 0.0;
									double sz = -Direction.X;
									World.Vector3D wpos = World.Vector3D.Add(pos, new World.Vector3D(sx * dx + wx * dz, sy * dx + wy * dz, sz * dx + wz * dz));
									int type = Data.Blocks[i].RailPole[j].Type;
									ObjectManager.CreateObject(Data.Structure.Poles[m][type], wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
								}
							}
						}
						// walls
						if (Data.Blocks[i].RailWall.Length > j && Data.Blocks[i].RailWall[j].Exists) {
							if (Data.Blocks[i].RailWall[j].Direction <= 0) {
								ObjectManager.CreateObject(Data.Structure.WallL[Data.Blocks[i].RailWall[j].Type], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
							}
							if (Data.Blocks[i].RailWall[j].Direction >= 0) {
								ObjectManager.CreateObject(Data.Structure.WallR[Data.Blocks[i].RailWall[j].Type], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
							}
						}
						// dikes
						if (Data.Blocks[i].RailDike.Length > j && Data.Blocks[i].RailDike[j].Exists) {
							if (Data.Blocks[i].RailDike[j].Direction <= 0) {
								ObjectManager.CreateObject(Data.Structure.DikeL[Data.Blocks[i].RailDike[j].Type], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
							}
							if (Data.Blocks[i].RailDike[j].Direction >= 0) {
								ObjectManager.CreateObject(Data.Structure.DikeR[Data.Blocks[i].RailDike[j].Type], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
							}
						}
						// sounds
						if (j == 0) {
							for (int k = 0; k < Data.Blocks[i].Sound.Length; k++) {
								if (Data.Blocks[i].Sound[k].Type == SoundType.World) {
									if (Data.Blocks[i].Sound[k].SoundIndex >= 0) {
										double d = Data.Blocks[i].Sound[k].TrackPosition - StartingDistance;
										double dx = Data.Blocks[i].Sound[k].X;
										double dy = Data.Blocks[i].Sound[k].Y;
										double wa = Math.Atan2(Direction.Y, Direction.X) - planar;
										double wx = Math.Cos(wa);
										double wy = Math.Tan(updown);
										double wz = Math.Sin(wa);
										World.Normalize(ref wx, ref wy, ref wz);
										double sx = Direction.Y;
										double sy = 0.0;
										double sz = -Direction.X;
										double ux, uy, uz;
										World.Cross(wx, wy, wz, sx, sy, sz, out ux, out uy, out uz);
										World.Vector3D wpos = World.Vector3D.Add(pos, new World.Vector3D(sx * dx + ux * dy + wx * d, sy * dx + uy * dy + wy * d, sz * dx + uz * dy + wz * d));
										SoundManager.PlaySound(Data.Blocks[i].Sound[k].SoundIndex, null, -1, wpos, SoundManager.Importance.AlwaysPlay, true, 1.0, 1.0);
									}
								}
							}
						}
						// forms
						for (int k = 0; k < Data.Blocks[i].Form.Length; k++) {
							// primary rail
							if (Data.Blocks[i].Form[k].PrimaryRail == j) {
								if (Data.Blocks[i].Form[k].SecondaryRail == Form.SecondaryRailStub) {
									if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormL.Length || Data.Structure.FormL[Data.Blocks[i].Form[k].FormType] == null) {
										Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
									} else {
										ObjectManager.CreateObject(Data.Structure.FormL[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
										if (Data.Blocks[i].Form[k].RoofType > 0) {
											if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofL.Length || Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType] == null) {
												Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
											} else {
												ObjectManager.CreateObject(Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
											}
										}
									}
								} else if (Data.Blocks[i].Form[k].SecondaryRail == Form.SecondaryRailL) {
									if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormL.Length || Data.Structure.FormL[Data.Blocks[i].Form[k].FormType] == null) {
										Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
									} else {
										ObjectManager.CreateObject(Data.Structure.FormL[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
									}
									if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormCL.Length || Data.Structure.FormCL[Data.Blocks[i].Form[k].FormType] == null) {
										Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
									} else {
										ObjectManager.CreateStaticObject(Data.Structure.FormCL[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
									}
									if (Data.Blocks[i].Form[k].RoofType > 0) {
										if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofL.Length || Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType] == null) {
											Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
										} else {
											ObjectManager.CreateObject(Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
										}
										if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofCL.Length || Data.Structure.RoofCL[Data.Blocks[i].Form[k].RoofType] == null) {
											Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
										} else {
											ObjectManager.CreateStaticObject(Data.Structure.RoofCL[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
										}
									}
								} else if (Data.Blocks[i].Form[k].SecondaryRail == Form.SecondaryRailR) {
									if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormR.Length || Data.Structure.FormR[Data.Blocks[i].Form[k].FormType] == null) {
										Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
									} else {
										ObjectManager.CreateObject(Data.Structure.FormR[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
									}
									if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormCR.Length || Data.Structure.FormCR[Data.Blocks[i].Form[k].FormType] == null) {
										Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
									} else {
										ObjectManager.CreateStaticObject(Data.Structure.FormCR[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
									}
									if (Data.Blocks[i].Form[k].RoofType > 0) {
										if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofR.Length || Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType] == null) {
											Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
										} else {
											ObjectManager.CreateObject(Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
										}
										if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofCR.Length || Data.Structure.RoofCR[Data.Blocks[i].Form[k].RoofType] == null) {
											Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
										} else {
											ObjectManager.CreateStaticObject(Data.Structure.RoofCR[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
										}
									}
								} else if (Data.Blocks[i].Form[k].SecondaryRail > 0) {
									int p = Data.Blocks[i].Form[k].PrimaryRail;
									double px0 = p > 0 ? Data.Blocks[i].Rail[p].RailStartX : 0.0;
									double px1 = p > 0 ? Data.Blocks[i + 1].Rail[p].RailEndX : 0.0;
									int s = Data.Blocks[i].Form[k].SecondaryRail;
									if (s < 0 || s >= Data.Blocks[i].Rail.Length || !Data.Blocks[i].Rail[s].RailStart) {
										Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is out of range in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName);
									} else {
										double sx0 = Data.Blocks[i].Rail[s].RailStartX;
										double sx1 = Data.Blocks[i + 1].Rail[s].RailEndX;
										double d0 = sx0 - px0;
										double d1 = sx1 - px1;
										if (d0 < 0.0) {
											if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormL.Length || Data.Structure.FormL[Data.Blocks[i].Form[k].FormType] == null) {
												Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
											} else {
												ObjectManager.CreateObject(Data.Structure.FormL[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
											}
											if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormCL.Length || Data.Structure.FormCL[Data.Blocks[i].Form[k].FormType] == null) {
												Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
											} else {
												ObjectManager.StaticObject FormC = GetTransformedStaticObject(Data.Structure.FormCL[Data.Blocks[i].Form[k].FormType], d0, d1);
												ObjectManager.CreateStaticObject(FormC, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
											}
											if (Data.Blocks[i].Form[k].RoofType > 0) {
												if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofL.Length || Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType] == null) {
													Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
												} else {
													ObjectManager.CreateObject(Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
												}
												if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofCL.Length || Data.Structure.RoofCL[Data.Blocks[i].Form[k].RoofType] == null) {
													Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
												} else {
													ObjectManager.StaticObject RoofC = GetTransformedStaticObject(Data.Structure.RoofCL[Data.Blocks[i].Form[k].RoofType], d0, d1);
													ObjectManager.CreateStaticObject(RoofC, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
												}
											}
										} else if (d0 > 0.0) {
											if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormR.Length || Data.Structure.FormR[Data.Blocks[i].Form[k].FormType] == null) {
												Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
											} else {
												ObjectManager.CreateObject(Data.Structure.FormR[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
											}
											if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormCR.Length || Data.Structure.FormCR[Data.Blocks[i].Form[k].FormType] == null) {
												Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
											} else {
												ObjectManager.StaticObject FormC = GetTransformedStaticObject(Data.Structure.FormCR[Data.Blocks[i].Form[k].FormType], d0, d1);
												ObjectManager.CreateStaticObject(FormC, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
											}
											if (Data.Blocks[i].Form[k].RoofType > 0) {
												if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofR.Length || Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType] == null) {
													Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
												} else {
													ObjectManager.CreateObject(Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
												}
												if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofCR.Length || Data.Structure.RoofCR[Data.Blocks[i].Form[k].RoofType] == null) {
													Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
												} else {
													ObjectManager.StaticObject RoofC = GetTransformedStaticObject(Data.Structure.RoofCR[Data.Blocks[i].Form[k].RoofType], d0, d1);
													ObjectManager.CreateStaticObject(RoofC, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
												}
											}
										}
									}
								}
							}
							// secondary rail
							if (Data.Blocks[i].Form[k].SecondaryRail == j) {
								int p = Data.Blocks[i].Form[k].PrimaryRail;
								double px = p > 0 ? Data.Blocks[i].Rail[p].RailStartX : 0.0;
								int s = Data.Blocks[i].Form[k].SecondaryRail;
								double sx = Data.Blocks[i].Rail[s].RailStartX;
								double d = px - sx;
								if (d < 0.0) {
									if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormL.Length || Data.Structure.FormL[Data.Blocks[i].Form[k].FormType] == null) {
										Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
									} else {
										ObjectManager.CreateObject(Data.Structure.FormL[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
									}
									if (Data.Blocks[i].Form[k].RoofType > 0) {
										if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofL.Length || Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType] == null) {
											Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
										} else {
											ObjectManager.CreateObject(Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
										}
									}
								} else {
									if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormR.Length || Data.Structure.FormR[Data.Blocks[i].Form[k].FormType] == null) {
										Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
									} else {
										ObjectManager.CreateObject(Data.Structure.FormR[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
									}
									if (Data.Blocks[i].Form[k].RoofType > 0) {
										if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofR.Length || Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType] == null) {
											Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
										} else {
											ObjectManager.CreateObject(Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
										}
									}
								}
							}
						}
						// cracks
						for (int k = 0; k < Data.Blocks[i].Crack.Length; k++) {
							if (Data.Blocks[i].Crack[k].PrimaryRail == j) {
								int p = Data.Blocks[i].Crack[k].PrimaryRail;
								double px0 = p > 0 ? Data.Blocks[i].Rail[p].RailStartX : 0.0;
								double px1 = p > 0 ? Data.Blocks[i + 1].Rail[p].RailEndX : 0.0;
								int s = Data.Blocks[i].Crack[k].SecondaryRail;
								if (s < 0 || s >= Data.Blocks[i].Rail.Length || !Data.Blocks[i].Rail[s].RailStart) {
									Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is out of range in Track.Crack at track position " + StartingDistance.ToString(Culture) + " in file " + FileName);
								} else {
									double sx0 = Data.Blocks[i].Rail[s].RailStartX;
									double sx1 = Data.Blocks[i + 1].Rail[s].RailEndX;
									double d0 = sx0 - px0;
									double d1 = sx1 - px1;
									if (d0 < 0.0) {
										if (Data.Blocks[i].Crack[k].Type >= Data.Structure.CrackL.Length || Data.Structure.CrackL[Data.Blocks[i].Crack[k].Type] == null) {
											Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex references a CrackL not loaded in Track.Crack at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
										} else {
											ObjectManager.StaticObject Crack = GetTransformedStaticObject(Data.Structure.CrackL[Data.Blocks[i].Crack[k].Type], d0, d1);
											ObjectManager.CreateStaticObject(Crack, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
										}
									} else if (d0 > 0.0) {
										if (Data.Blocks[i].Crack[k].Type >= Data.Structure.CrackR.Length || Data.Structure.CrackR[Data.Blocks[i].Crack[k].Type] == null) {
											Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex references a CrackR not loaded in Track.Crack at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
										} else {
											ObjectManager.StaticObject Crack = GetTransformedStaticObject(Data.Structure.CrackR[Data.Blocks[i].Crack[k].Type], d0, d1);
											ObjectManager.CreateStaticObject(Crack, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
										}
									}
								}
							}
						}
						// free objects
						if (Data.Blocks[i].RailFreeObj.Length > j && Data.Blocks[i].RailFreeObj[j] != null) {
							for (int k = 0; k < Data.Blocks[i].RailFreeObj[j].Length; k++) {
								int sttype = Data.Blocks[i].RailFreeObj[j][k].Type;
								double dx = Data.Blocks[i].RailFreeObj[j][k].X;
								double dy = Data.Blocks[i].RailFreeObj[j][k].Y;
								double dz = Data.Blocks[i].RailFreeObj[j][k].TrackPosition - StartingDistance;
								World.Vector3D wpos = pos;
								wpos.X += dx * RailTransformation.X.X + dy * RailTransformation.Y.X + dz * RailTransformation.Z.X;
								wpos.Y += dx * RailTransformation.X.Y + dy * RailTransformation.Y.Y + dz * RailTransformation.Z.Y;
								wpos.Z += dx * RailTransformation.X.Z + dy * RailTransformation.Y.Z + dz * RailTransformation.Z.Z;
								double tpos = Data.Blocks[i].RailFreeObj[j][k].TrackPosition;
								ObjectManager.CreateObject(Data.Structure.FreeObj[sttype], wpos, RailTransformation, new World.Transformation(Data.Blocks[i].RailFreeObj[j][k].Yaw, Data.Blocks[i].RailFreeObj[j][k].Pitch, Data.Blocks[i].RailFreeObj[j][k].Roll), -1, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos, 1.0, false);
							}
						}
						// transponder objects
						if (j == 0) {
							for (int k = 0; k < Data.Blocks[i].Transponder.Length; k++) {
								ObjectManager.UnifiedObject obj = null;
								if (Data.Blocks[i].Transponder[k].ShowDefaultObject) {
									switch (Data.Blocks[i].Transponder[k].Type) {
											case TrackManager.TransponderType.SLong: obj = TransponderS; break;
											case TrackManager.TransponderType.SN: obj = TransponderSN; break;
											case TrackManager.TransponderType.AccidentalDeparture: obj = TransponderFalseStart; break;
											case TrackManager.TransponderType.AtsPPatternOrigin: obj = TransponderPOrigin; break;
											case TrackManager.TransponderType.AtsPImmediateStop: obj = TransponderPStop; break;
									}
								} else {
									int b = Data.Blocks[i].Transponder[k].BeaconStructureIndex;
									if (b >= 0 & b < Data.Structure.Beacon.Length) {
										obj = Data.Structure.Beacon[b];
									}
								}
								if (obj != null) {
									double dx = Data.Blocks[i].Transponder[k].X;
									double dy = Data.Blocks[i].Transponder[k].Y;
									double dz = Data.Blocks[i].Transponder[k].TrackPosition - StartingDistance;
									World.Vector3D wpos = pos;
									wpos.X += dx * RailTransformation.X.X + dy * RailTransformation.Y.X + dz * RailTransformation.Z.X;
									wpos.Y += dx * RailTransformation.X.Y + dy * RailTransformation.Y.Y + dz * RailTransformation.Z.Y;
									wpos.Z += dx * RailTransformation.X.Z + dy * RailTransformation.Y.Z + dz * RailTransformation.Z.Z;
									double tpos = Data.Blocks[i].Transponder[k].TrackPosition;
									if (Data.Blocks[i].Transponder[k].ShowDefaultObject) {
										double b = 0.25 + 0.75 * GetBrightness(ref Data, tpos);
										ObjectManager.CreateObject(obj, wpos, RailTransformation, new World.Transformation(Data.Blocks[i].Transponder[k].Yaw, Data.Blocks[i].Transponder[k].Pitch, Data.Blocks[i].Transponder[k].Roll), -1, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
									} else {
										ObjectManager.CreateObject(obj, wpos, RailTransformation, new World.Transformation(Data.Blocks[i].Transponder[k].Yaw, Data.Blocks[i].Transponder[k].Pitch, Data.Blocks[i].Transponder[k].Roll), Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos);
									}
								}
							}
						}
						// sections/signals/transponders
						if (j == 0) {
							// signals
							for (int k = 0; k < Data.Blocks[i].Signal.Length; k++) {
								SignalData sd;
								if (Data.Blocks[i].Signal[k].SignalCompatibilityObjectIndex >= 0) {
									sd = Data.CompatibilitySignalData[Data.Blocks[i].Signal[k].SignalCompatibilityObjectIndex];
								} else {
									sd = Data.SignalData[Data.Blocks[i].Signal[k].SignalObjectIndex];
								}
								// objects
								double dz = Data.Blocks[i].Signal[k].TrackPosition - StartingDistance;
								if (Data.Blocks[i].Signal[k].ShowPost) {
									// post
									double dx = Data.Blocks[i].Signal[k].X;
									World.Vector3D wpos = pos;
									wpos.X += dx * RailTransformation.X.X + dz * RailTransformation.Z.X;
									wpos.Y += dx * RailTransformation.X.Y + dz * RailTransformation.Z.Y;
									wpos.Z += dx * RailTransformation.X.Z + dz * RailTransformation.Z.Z;
									double tpos = Data.Blocks[i].Signal[k].TrackPosition;
									double b = 0.25 + 0.75 * GetBrightness(ref Data, tpos);
									ObjectManager.CreateStaticObject(SignalPost, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
								}
								if (Data.Blocks[i].Signal[k].ShowObject) {
									// signal object
									double dx = Data.Blocks[i].Signal[k].X;
									double dy = Data.Blocks[i].Signal[k].Y;
									World.Vector3D wpos = pos;
									wpos.X += dx * RailTransformation.X.X + dy * RailTransformation.Y.X + dz * RailTransformation.Z.X;
									wpos.Y += dx * RailTransformation.X.Y + dy * RailTransformation.Y.Y + dz * RailTransformation.Z.Y;
									wpos.Z += dx * RailTransformation.X.Z + dy * RailTransformation.Y.Z + dz * RailTransformation.Z.Z;
									double tpos = Data.Blocks[i].Signal[k].TrackPosition;
									if (sd is AnimatedObjectSignalData) {
										AnimatedObjectSignalData aosd = (AnimatedObjectSignalData)sd;
										ObjectManager.CreateObject(aosd.Objects, wpos, RailTransformation, new World.Transformation(Data.Blocks[i].Signal[k].Yaw, Data.Blocks[i].Signal[k].Pitch, Data.Blocks[i].Signal[k].Roll), Data.Blocks[i].Signal[k].Section, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos, 1.0, false);
									} else if (sd is CompatibilitySignalData) {
										CompatibilitySignalData csd = (CompatibilitySignalData)sd;
										if (csd.Numbers.Length != 0) {
											double brightness = 0.25 + 0.75 * GetBrightness(ref Data, tpos);
											ObjectManager.AnimatedObjectCollection aoc = new ObjectManager.AnimatedObjectCollection();
											aoc.Objects = new ObjectManager.AnimatedObject[1];
											aoc.Objects[0] = new ObjectManager.AnimatedObject();
											aoc.Objects[0].States = new ObjectManager.AnimatedObjectState[csd.Numbers.Length];
											for (int l = 0; l < csd.Numbers.Length; l++) {
												aoc.Objects[0].States[l].Object = ObjectManager.CloneObject(csd.Objects[l]);
											}
											string expr = "";
											for (int l = 0; l < csd.Numbers.Length - 1; l++) {
												expr += "section " + csd.Numbers[l].ToString(Culture) + " <= " + l.ToString(Culture) + " ";
											}
											expr += (csd.Numbers.Length - 1).ToString(Culture);
											for (int l = 0; l < csd.Numbers.Length - 1; l++) {
												expr += " ?";
											}
											aoc.Objects[0].StateFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(expr);
											aoc.Objects[0].RefreshRate = 1.0 + 0.01 * Game.Generator.NextDouble();
											ObjectManager.CreateObject(aoc, wpos, RailTransformation, new World.Transformation(Data.Blocks[i].Signal[k].Yaw, Data.Blocks[i].Signal[k].Pitch, Data.Blocks[i].Signal[k].Roll), Data.Blocks[i].Signal[k].Section, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos, brightness, false);
										}
									} else if (sd is Bve4SignalData) {
										Bve4SignalData b4sd = (Bve4SignalData)sd;
										if (b4sd.SignalTextures.Length != 0) {
											int m = Math.Max(b4sd.SignalTextures.Length, b4sd.GlowTextures.Length);
											int zn = 0;
											for (int l = 0; l < m; l++) {
												if (l < b4sd.SignalTextures.Length && b4sd.SignalTextures[l] >= 0 || l < b4sd.GlowTextures.Length && b4sd.GlowTextures[l] >= 0) {
													zn++;
												}
											}
											ObjectManager.AnimatedObjectCollection aoc = new ObjectManager.AnimatedObjectCollection();
											aoc.Objects = new ObjectManager.AnimatedObject[1];
											aoc.Objects[0] = new ObjectManager.AnimatedObject();
											aoc.Objects[0].States = new ObjectManager.AnimatedObjectState[zn];
											int zi = 0;
											string expr = "";
											for (int l = 0; l < m; l++) {
												bool qs = l < b4sd.SignalTextures.Length && b4sd.SignalTextures[l] >= 0;
												bool qg = l < b4sd.GlowTextures.Length && b4sd.GlowTextures[l] >= 0;
												if (qs & qg) {
													ObjectManager.StaticObject so = ObjectManager.CloneObject(b4sd.BaseObject, b4sd.SignalTextures[l], -1);
													ObjectManager.StaticObject go = ObjectManager.CloneObject(b4sd.GlowObject, b4sd.GlowTextures[l], -1);
													ObjectManager.JoinObjects(ref so, go);
													aoc.Objects[0].States[zi].Object = so;
												} else if (qs) {
													ObjectManager.StaticObject so = ObjectManager.CloneObject(b4sd.BaseObject, b4sd.SignalTextures[l], -1);
													aoc.Objects[0].States[zi].Object = so;
												} else if (qg) {
													ObjectManager.StaticObject go = ObjectManager.CloneObject(b4sd.GlowObject, b4sd.GlowTextures[l], -1);
													aoc.Objects[0].States[zi].Object = go;
												}
												if (qs | qg) {
													if (zi < zn - 1) {
														expr += "section " + l.ToString(Culture) + " <= " + zi.ToString(Culture) + " ";
													} else {
														expr += zi.ToString(Culture);
													}
													zi++;
												}
											}
											for (int l = 0; l < zn - 1; l++) {
												expr += " ?";
											}
											aoc.Objects[0].StateFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(expr);
											aoc.Objects[0].RefreshRate = 1.0 + 0.01 * Game.Generator.NextDouble();
											ObjectManager.CreateObject(aoc, wpos, RailTransformation, new World.Transformation(Data.Blocks[i].Signal[k].Yaw, Data.Blocks[i].Signal[k].Pitch, Data.Blocks[i].Signal[k].Roll), Data.Blocks[i].Signal[k].Section, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos, 1.0, false);
										}
									}
								}
							}
							// sections
							for (int k = 0; k < Data.Blocks[i].Section.Length; k++) {
								int m = Game.Sections.Length;
								Array.Resize<Game.Section>(ref Game.Sections, m + 1);
								Game.Sections[m].SignalIndices = new int[] { };
								// create associated transponders
								for (int g = 0; g <= i; g++) {
									for (int l = 0; l < Data.Blocks[g].Transponder.Length; l++) {
										if (Data.Blocks[g].Transponder[l].Type != TrackManager.TransponderType.None & Data.Blocks[g].Transponder[l].Section == m) {
											int o = TrackManager.CurrentTrack.Elements[n - i + g].Events.Length;
											Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n - i + g].Events, o + 1);
											double dt = Data.Blocks[g].Transponder[l].TrackPosition - StartingDistance + (double)(i - g) * Data.BlockInterval;
											TrackManager.CurrentTrack.Elements[n - i + g].Events[o] = new TrackManager.TransponderEvent(dt, Data.Blocks[g].Transponder[l].Type, Data.Blocks[g].Transponder[l].SwitchSubsystem, Data.Blocks[g].Transponder[l].OptionalInteger, Data.Blocks[g].Transponder[l].OptionalFloat, m);
											Data.Blocks[g].Transponder[l].Type = TrackManager.TransponderType.None;
										}
									}
								}
								// create section
								Game.Sections[m].TrackPosition = Data.Blocks[i].Section[k].TrackPosition;
								Game.Sections[m].Aspects = new Game.SectionAspect[Data.Blocks[i].Section[k].Aspects.Length];
								for (int l = 0; l < Data.Blocks[i].Section[k].Aspects.Length; l++) {
									Game.Sections[m].Aspects[l].Number = Data.Blocks[i].Section[k].Aspects[l];
									if (Data.Blocks[i].Section[k].Aspects[l] >= 0 & Data.Blocks[i].Section[k].Aspects[l] < Data.SignalSpeeds.Length) {
										Game.Sections[m].Aspects[l].Speed = Data.SignalSpeeds[Data.Blocks[i].Section[k].Aspects[l]];
									} else {
										Game.Sections[m].Aspects[l].Speed = double.PositiveInfinity;
									}
								}
								Game.Sections[m].Type = Data.Blocks[i].Section[k].Type;
								Game.Sections[m].CurrentAspect = -1;
								if (m > 0) {
									Game.Sections[m].PreviousSection = m - 1;
									Game.Sections[m - 1].NextSection = m;
								} else {
									Game.Sections[m].PreviousSection = -1;
								}
								Game.Sections[m].NextSection = -1;
								Game.Sections[m].StationIndex = Data.Blocks[i].Section[k].DepartureStationIndex;
								Game.Sections[m].Invisible = Data.Blocks[i].Section[k].Invisible;
								Game.Sections[m].Trains = new TrainManager.Train[] { };
								// create section change event
								double d = Data.Blocks[i].Section[k].TrackPosition - StartingDistance;
								int p = TrackManager.CurrentTrack.Elements[n].Events.Length;
								Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, p + 1);
								TrackManager.CurrentTrack.Elements[n].Events[p] = new TrackManager.SectionChangeEvent(d, m - 1, m);
							}
							// transponders introduced after corresponding sections
							for (int l = 0; l < Data.Blocks[i].Transponder.Length; l++) {
								if (Data.Blocks[i].Transponder[l].Type != TrackManager.TransponderType.None) {
									int t = Data.Blocks[i].Transponder[l].Section;
									if (t >= 0 & t < Game.Sections.Length) {
										int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
										Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
										double dt = Data.Blocks[i].Transponder[l].TrackPosition - StartingDistance;
										TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.TransponderEvent(dt, Data.Blocks[i].Transponder[l].Type, Data.Blocks[i].Transponder[l].SwitchSubsystem, Data.Blocks[i].Transponder[l].OptionalInteger, Data.Blocks[i].Transponder[l].OptionalFloat, t);
										Data.Blocks[i].Transponder[l].Type = TrackManager.TransponderType.None;
									}
								}
							}
						}
						// limit
						if (j == 0) {
							for (int k = 0; k < Data.Blocks[i].Limit.Length; k++) {
								if (Data.Blocks[i].Limit[k].Direction != 0) {
									double dx = 2.2 * (double)Data.Blocks[i].Limit[k].Direction;
									double dz = Data.Blocks[i].Limit[k].TrackPosition - StartingDistance;
									World.Vector3D wpos = pos;
									wpos.X += dx * RailTransformation.X.X + dz * RailTransformation.Z.X;
									wpos.Y += dx * RailTransformation.X.Y + dz * RailTransformation.Z.Y;
									wpos.Z += dx * RailTransformation.X.Z + dz * RailTransformation.Z.Z;
									double tpos = Data.Blocks[i].Limit[k].TrackPosition;
									double b = 0.25 + 0.75 * GetBrightness(ref Data, tpos);
									if (Data.Blocks[i].Limit[k].Speed <= 0.0 | Data.Blocks[i].Limit[k].Speed >= 1000.0) {
										ObjectManager.CreateStaticObject(LimitPostInfinite, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
									} else {
										if (Data.Blocks[i].Limit[k].Cource < 0) {
											ObjectManager.CreateStaticObject(LimitPostLeft, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
										} else if (Data.Blocks[i].Limit[k].Cource > 0) {
											ObjectManager.CreateStaticObject(LimitPostRight, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
										} else {
											ObjectManager.CreateStaticObject(LimitPostStraight, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
										}
										double lim = Data.Blocks[i].Limit[k].Speed / Data.UnitOfSpeed;
										if (lim < 10.0) {
											int d0 = (int)Math.Round(lim);
											int o = ObjectManager.CreateStaticObject(LimitOneDigit, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, true);
											if (ObjectManager.Objects[o].Mesh.Materials.Length >= 1) {
												ObjectManager.Objects[o].Mesh.Materials[0].DaytimeTextureIndex = TextureManager.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d0 + ".png"), new World.ColorRGB(0, 0, 0), 0, TextureManager.TextureWrapMode.ClampToEdge, TextureManager.TextureWrapMode.ClampToEdge, false);
											}
										} else if (lim < 100.0) {
											int d1 = (int)Math.Round(lim);
											int d0 = d1 % 10;
											d1 /= 10;
											int o = ObjectManager.CreateStaticObject(LimitTwoDigits, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, true);
											if (ObjectManager.Objects[o].Mesh.Materials.Length >= 1) {
												ObjectManager.Objects[o].Mesh.Materials[0].DaytimeTextureIndex = TextureManager.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d1 + ".png"), new World.ColorRGB(0, 0, 0), 0, TextureManager.TextureWrapMode.ClampToEdge, TextureManager.TextureWrapMode.ClampToEdge, false);
											}
											if (ObjectManager.Objects[o].Mesh.Materials.Length >= 2) {
												ObjectManager.Objects[o].Mesh.Materials[1].DaytimeTextureIndex = TextureManager.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d0 + ".png"), new World.ColorRGB(0, 0, 0), 0, TextureManager.TextureWrapMode.ClampToEdge, TextureManager.TextureWrapMode.ClampToEdge, false);
											}
										} else {
											int d2 = (int)Math.Round(lim);
											int d0 = d2 % 10;
											int d1 = (d2 / 10) % 10;
											d2 /= 100;
											int o = ObjectManager.CreateStaticObject(LimitThreeDigits, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, true);
											if (ObjectManager.Objects[o].Mesh.Materials.Length >= 1) {
												ObjectManager.Objects[o].Mesh.Materials[0].DaytimeTextureIndex = TextureManager.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d2 + ".png"), new World.ColorRGB(0, 0, 0), 0, TextureManager.TextureWrapMode.ClampToEdge, TextureManager.TextureWrapMode.ClampToEdge, false);
											}
											if (ObjectManager.Objects[o].Mesh.Materials.Length >= 2) {
												ObjectManager.Objects[o].Mesh.Materials[1].DaytimeTextureIndex = TextureManager.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d1 + ".png"), new World.ColorRGB(0, 0, 0), 0, TextureManager.TextureWrapMode.ClampToEdge, TextureManager.TextureWrapMode.ClampToEdge, false);
											}
											if (ObjectManager.Objects[o].Mesh.Materials.Length >= 3) {
												ObjectManager.Objects[o].Mesh.Materials[2].DaytimeTextureIndex = TextureManager.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d0 + ".png"), new World.ColorRGB(0, 0, 0), 0, TextureManager.TextureWrapMode.ClampToEdge, TextureManager.TextureWrapMode.ClampToEdge, false);
											}
										}
									}
								}
							}
						}
						// stop
						if (j == 0) {
							for (int k = 0; k < Data.Blocks[i].Stop.Length; k++) {
								if (Data.Blocks[i].Stop[k].Direction != 0) {
									double dx = 1.8 * (double)Data.Blocks[i].Stop[k].Direction;
									double dz = Data.Blocks[i].Stop[k].TrackPosition - StartingDistance;
									World.Vector3D wpos = pos;
									wpos.X += dx * RailTransformation.X.X + dz * RailTransformation.Z.X;
									wpos.Y += dx * RailTransformation.X.Y + dz * RailTransformation.Z.Y;
									wpos.Z += dx * RailTransformation.X.Z + dz * RailTransformation.Z.Z;
									double tpos = Data.Blocks[i].Stop[k].TrackPosition;
									double b = 0.25 + 0.75 * GetBrightness(ref Data, tpos);
									ObjectManager.CreateStaticObject(StopPost, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
								}
							}
						}
					}
				}
				// finalize block
				Position.X += Direction.X * c;
				Position.Y += h;
				Position.Z += Direction.Y * c;
				if (a != 0.0) {
					World.Rotate(ref Direction, Math.Cos(-a), Math.Sin(-a));
				}
			}
			// orphaned transponders
			if (!PreviewOnly) {
				for (int i = Data.FirstUsedBlock; i < Data.Blocks.Length; i++) {
					for (int j = 0; j < Data.Blocks[i].Transponder.Length; j++) {
						if (Data.Blocks[i].Transponder[j].Type != TrackManager.TransponderType.None) {
							int n = i - Data.FirstUsedBlock;
							int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
							Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
							double d = Data.Blocks[i].Transponder[j].TrackPosition - TrackManager.CurrentTrack.Elements[n].StartingTrackPosition;
							int s = Data.Blocks[i].Transponder[j].Section;
							if (s >= 0) s = -1;
							TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.TransponderEvent(d, Data.Blocks[i].Transponder[j].Type, Data.Blocks[i].Transponder[j].SwitchSubsystem, Data.Blocks[i].Transponder[j].OptionalInteger, Data.Blocks[i].Transponder[j].OptionalFloat, s);
							Data.Blocks[i].Transponder[j].Type = TrackManager.TransponderType.None;
						}
					}
				}
			}
			// insert station end events
			for (int i = 0; i < Game.Stations.Length; i++) {
				int j = Game.Stations[i].Stops.Length - 1;
				if (j >= 0) {
					double p = Game.Stations[i].Stops[j].TrackPosition + Game.Stations[i].Stops[j].ForwardTolerance + Data.BlockInterval;
					int k = (int)Math.Floor(p / (double)Data.BlockInterval) - Data.FirstUsedBlock;
					if (k >= 0 & k < Data.Blocks.Length) {
						double d = p - (double)(k + Data.FirstUsedBlock) * (double)Data.BlockInterval;
						int m = TrackManager.CurrentTrack.Elements[k].Events.Length;
						Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[k].Events, m + 1);
						TrackManager.CurrentTrack.Elements[k].Events[m] = new TrackManager.StationEndEvent(d, i);
					}
				}
			}
			// create default point of interests
			if (Game.PointsOfInterest.Length == 0) {
				Game.PointsOfInterest = new OpenBve.Game.PointOfInterest[Game.Stations.Length];
				int n = 0;
				for (int i = 0; i < Game.Stations.Length; i++) {
					if (Game.Stations[i].Stops.Length != 0) {
						Game.PointsOfInterest[n].Text = Game.Stations[i].Name;
						Game.PointsOfInterest[n].TrackPosition = Game.Stations[i].Stops[0].TrackPosition;
						Game.PointsOfInterest[n].TrackOffset = new OpenBve.World.Vector3D(0.0, 2.8, 0.0);
						if (Game.Stations[i].OpenLeftDoors & !Game.Stations[i].OpenRightDoors) {
							Game.PointsOfInterest[n].TrackOffset.X = -2.5;
						} else if (!Game.Stations[i].OpenLeftDoors & Game.Stations[i].OpenRightDoors) {
							Game.PointsOfInterest[n].TrackOffset.X = 2.5;
						}
						n++;
					}
				}
				Array.Resize<Game.PointOfInterest>(ref Game.PointsOfInterest, n);
			}
			// convert block-based cant into point-based cant
			for (int i = CurrentTrackLength - 1; i >= 1; i--) {
				if (TrackManager.CurrentTrack.Elements[i].CurveCant == 0.0) {
					TrackManager.CurrentTrack.Elements[i].CurveCant = TrackManager.CurrentTrack.Elements[i - 1].CurveCant;
				} else if (TrackManager.CurrentTrack.Elements[i - 1].CurveCant != 0.0) {
					if (Math.Sign(TrackManager.CurrentTrack.Elements[i - 1].CurveCant) == Math.Sign(TrackManager.CurrentTrack.Elements[i].CurveCant)) {
						if (Math.Abs(TrackManager.CurrentTrack.Elements[i - 1].CurveCant) > Math.Abs(TrackManager.CurrentTrack.Elements[i].CurveCant)) {
							TrackManager.CurrentTrack.Elements[i].CurveCant = TrackManager.CurrentTrack.Elements[i - 1].CurveCant;
						}
					} else {
						TrackManager.CurrentTrack.Elements[i].CurveCant = 0.5 * (TrackManager.CurrentTrack.Elements[i].CurveCant + TrackManager.CurrentTrack.Elements[i - 1].CurveCant);
					}
				}
			}
			// finalize
			Array.Resize<TrackManager.TrackElement>(ref TrackManager.CurrentTrack.Elements, CurrentTrackLength);
			for (int i = 0; i < Game.Stations.Length; i++) {
				if (Game.Stations[i].Stops.Length == 0 & Game.Stations[i].StopMode != Game.StationStopMode.AllPass) {
					Interface.AddMessage(Interface.MessageType.Warning, false, "Station " + Game.Stations[i].Name + " expects trains to stop but does not define stop points at track position " + Game.Stations[i].DefaultTrackPosition.ToString(Culture) + " in file " + FileName);
					Game.Stations[i].StopMode = Game.StationStopMode.AllPass;
				}
				if (Game.Stations[i].StationType == Game.StationType.ChangeEnds) {
					if (i < Game.Stations.Length - 1) {
						if (Game.Stations[i + 1].StopMode != Game.StationStopMode.AllStop) {
							Interface.AddMessage(Interface.MessageType.Warning, false, "Station " + Game.Stations[i].Name + " is marked as \"change ends\" but the subsequent station does not expect all trains to stop in file " + FileName);
							Game.Stations[i + 1].StopMode = Game.StationStopMode.AllStop;
						}
					} else {
						Interface.AddMessage(Interface.MessageType.Warning, false, "Station " + Game.Stations[i].Name + " is marked as \"change ends\" but there is no subsequent station defined in file " + FileName);
						Game.Stations[i].StationType = Game.StationType.Terminal;
					}
				}
			}
			if (Game.Stations.Length != 0) {
				Game.Stations[Game.Stations.Length - 1].StationType = Game.StationType.Terminal;
			}
			if (TrackManager.CurrentTrack.Elements.Length != 0) {
				int n = TrackManager.CurrentTrack.Elements.Length - 1;
				int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
				Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
				TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.TrackEndEvent(Data.BlockInterval);
			}
			if (!PreviewOnly) {
				ComputeCantTangents();
				int subdivisions = (int)Math.Floor(Data.BlockInterval / 5.0);
				if (subdivisions >= 2) {
					SmoothenOutTurns(subdivisions);
					ComputeCantTangents();
				}
			}
		}
Example #13
0
		// 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, World.CameraAlignmentSpeed.Zoom != 0.0);
			if (zm != World.CameraCurrentAlignment.Zoom) {
				ApplyZoom();
			}
			// 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);
			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) {
				TrackManager.UpdateTrackFollower(ref World.CameraTrackFollower, World.CameraCurrentAlignment.TrackPosition, true, false);
				q = true;
			}
			if (q) {
				UpdateViewingDistances();
			}
			double dx = World.CameraTrackFollower.WorldDirection.X;
			double dy = World.CameraTrackFollower.WorldDirection.Y;
			double dz = World.CameraTrackFollower.WorldDirection.Z;
			double ux = World.CameraTrackFollower.WorldUp.X;
			double uy = World.CameraTrackFollower.WorldUp.Y;
			double uz = World.CameraTrackFollower.WorldUp.Z;
			double sx = World.CameraTrackFollower.WorldSide.X;
			double sy = World.CameraTrackFollower.WorldSide.Y;
			double sz = World.CameraTrackFollower.WorldSide.Z;
			double tx = World.CameraCurrentAlignment.Position.X;
			double ty = World.CameraCurrentAlignment.Position.Y;
			double tz = World.CameraCurrentAlignment.Position.Z;
			double dx2 = dx, dy2 = dy, dz2 = dz;
			double ux2 = ux, uy2 = uy, uz2 = uz;
			double cx = World.CameraTrackFollower.WorldPosition.X + sx * tx + ux2 * ty + dx2 * tz;
			double cy = World.CameraTrackFollower.WorldPosition.Y + sy * tx + uy2 * ty + dy2 * tz;
			double cz = World.CameraTrackFollower.WorldPosition.Z + sz * tx + uz2 * ty + dz2 * tz;
			if (World.CameraCurrentAlignment.Yaw != 0.0) {
				double cosa = Math.Cos(World.CameraCurrentAlignment.Yaw);
				double sina = Math.Sin(World.CameraCurrentAlignment.Yaw);
				World.Rotate(ref dx, ref dy, ref dz, ux, uy, uz, cosa, sina);
				World.Rotate(ref sx, ref sy, ref sz, ux, uy, uz, cosa, sina);
			}
			double p = World.CameraCurrentAlignment.Pitch;
			if (p != 0.0) {
				double cosa = Math.Cos(-p);
				double sina = Math.Sin(-p);
				World.Rotate(ref dx, ref dy, ref dz, sx, sy, sz, cosa, sina);
				World.Rotate(ref ux, ref uy, ref uz, sx, sy, sz, cosa, sina);
			}
			if (World.CameraCurrentAlignment.Roll != 0.0) {
				double cosa = Math.Cos(-World.CameraCurrentAlignment.Roll);
				double sina = Math.Sin(-World.CameraCurrentAlignment.Roll);
				World.Rotate(ref ux, ref uy, ref uz, dx, dy, dz, cosa, sina);
				World.Rotate(ref sx, ref sy, ref sz, dx, dy, dz, cosa, sina);
			}
			AbsoluteCameraPosition = new Vector3D(cx, cy, cz);
			AbsoluteCameraDirection = new Vector3D(dx, dy, dz);
			AbsoluteCameraUp = new Vector3D(ux, uy, uz);
			AbsoluteCameraSide = new Vector3D(sx, sy, sz);
		}
Example #14
0
			internal TrackElement(double StartingTrackPosition) {
				this.StartingTrackPosition = StartingTrackPosition;
				this.CurveRadius = 0.0;
				this.CurveCant = 0.0;
				this.CurveCantTangent = 0.0;
				this.AdhesionMultiplier = 1.0;
				this.CsvRwAccuracyLevel = 2.0;
				this.WorldPosition = new World.Vector3D(0.0, 0.0, 0.0);
				this.WorldDirection = new World.Vector3D(0.0, 0.0, 1.0);
				this.WorldUp = new World.Vector3D(0.0, 1.0, 0.0);
				this.WorldSide = new World.Vector3D(1.0, 0.0, 0.0);
				this.Events = new GeneralEvent[] { };
			}
Example #15
0
 internal SoundEvent(double TrackPositionDelta, int SoundIndex, bool PlayerTrainOnly, bool Once, bool Dynamic, World.Vector3D Position, double Speed) {
     this.TrackPositionDelta = TrackPositionDelta;
     this.DontTriggerAnymore = false;
     this.SoundIndex = SoundIndex;
     this.PlayerTrainOnly = PlayerTrainOnly;
     this.Once = Once;
     this.Dynamic = Dynamic;
     this.Position = Position;
     this.Speed = Speed;
 }
        internal static void UpdateTrackFollower(ref TrackFollower Follower, double NewTrackPosition, bool UpdateWorldCoordinates, bool AddTrackInaccurary)
        {
            if (CurrentTrack.Elements.Length == 0)
            {
                return;
            }
            int i = Follower.LastTrackElement;

            while (i >= 0 && NewTrackPosition < CurrentTrack.Elements[i].StartingTrackPosition)
            {
                double ta = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
                double tb = -0.01;
                CheckEvents(ref Follower, i, -1, ta, tb);
                i--;
            }
            if (i >= 0)
            {
                while (i < CurrentTrack.Elements.Length - 1)
                {
                    if (NewTrackPosition < CurrentTrack.Elements[i + 1].StartingTrackPosition)
                    {
                        break;
                    }
                    double ta = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
                    double tb = CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition + 0.01;
                    CheckEvents(ref Follower, i, 1, ta, tb);
                    i++;
                }
            }
            else
            {
                i = 0;
            }
            double da = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
            double db = NewTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;

            // track
            if (UpdateWorldCoordinates)
            {
                if (db != 0.0)
                {
                    if (CurrentTrack.Elements[i].CurveRadius != 0.0)
                    {
                        // curve
                        double         r = CurrentTrack.Elements[i].CurveRadius;
                        double         p = CurrentTrack.Elements[i].WorldDirection.Y / Math.Sqrt(CurrentTrack.Elements[i].WorldDirection.X * CurrentTrack.Elements[i].WorldDirection.X + CurrentTrack.Elements[i].WorldDirection.Z * CurrentTrack.Elements[i].WorldDirection.Z);
                        double         s = db / Math.Sqrt(1.0 + p * p);
                        double         h = s * p;
                        double         b = s / Math.Abs(r);
                        double         f = 2.0 * r * r * (1.0 - Math.Cos(b));
                        double         c = (double)Math.Sign(db) * Math.Sqrt(f >= 0.0 ? f : 0.0);
                        double         a = 0.5 * (double)Math.Sign(r) * b;
                        World.Vector3D D = new World.Vector3D(CurrentTrack.Elements[i].WorldDirection.X, 0.0, CurrentTrack.Elements[i].WorldDirection.Z);
                        World.Normalize(ref D.X, ref D.Y, ref D.Z);
                        double cosa = Math.Cos(a);
                        double sina = Math.Sin(a);
                        World.Rotate(ref D.X, ref D.Y, ref D.Z, 0.0, 1.0, 0.0, cosa, sina);
                        Follower.WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + c * D.X;
                        Follower.WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + h;
                        Follower.WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + c * D.Z;
                        World.Rotate(ref D.X, ref D.Y, ref D.Z, 0.0, 1.0, 0.0, cosa, sina);
                        Follower.WorldDirection.X = D.X;
                        Follower.WorldDirection.Y = p;
                        Follower.WorldDirection.Z = D.Z;
                        World.Normalize(ref Follower.WorldDirection.X, ref Follower.WorldDirection.Y, ref Follower.WorldDirection.Z);
                        double cos2a = Math.Cos(2.0 * a);
                        double sin2a = Math.Sin(2.0 * a);
                        Follower.WorldSide = CurrentTrack.Elements[i].WorldSide;
                        World.Rotate(ref Follower.WorldSide.X, ref Follower.WorldSide.Y, ref Follower.WorldSide.Z, 0.0, 1.0, 0.0, cos2a, sin2a);
                        World.Cross(Follower.WorldDirection.X, Follower.WorldDirection.Y, Follower.WorldDirection.Z, Follower.WorldSide.X, Follower.WorldSide.Y, Follower.WorldSide.Z, out Follower.WorldUp.X, out Follower.WorldUp.Y, out Follower.WorldUp.Z);
                        Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
                    }
                    else
                    {
                        // straight
                        Follower.WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + db * CurrentTrack.Elements[i].WorldDirection.X;
                        Follower.WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + db * CurrentTrack.Elements[i].WorldDirection.Y;
                        Follower.WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + db * CurrentTrack.Elements[i].WorldDirection.Z;
                        Follower.WorldDirection  = CurrentTrack.Elements[i].WorldDirection;
                        Follower.WorldUp         = CurrentTrack.Elements[i].WorldUp;
                        Follower.WorldSide       = CurrentTrack.Elements[i].WorldSide;
                        Follower.CurveRadius     = 0.0;
                    }
                    // cant
                    if (i < CurrentTrack.Elements.Length - 1)
                    {
                        double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
                        if (t < 0.0)
                        {
                            t = 0.0;
                        }
                        else if (t > 1.0)
                        {
                            t = 1.0;
                        }
                        double t2 = t * t;
                        double t3 = t2 * t;
                        Follower.CurveCant =
                            (2.0 * t3 - 3.0 * t2 + 1.0) * CurrentTrack.Elements[i].CurveCant +
                            (t3 - 2.0 * t2 + t) * CurrentTrack.Elements[i].CurveCantTangent +
                            (-2.0 * t3 + 3.0 * t2) * CurrentTrack.Elements[i + 1].CurveCant +
                            (t3 - t2) * CurrentTrack.Elements[i + 1].CurveCantTangent;
                    }
                    else
                    {
                        Follower.CurveCant = CurrentTrack.Elements[i].CurveCant;
                    }
                }
                else
                {
                    Follower.WorldPosition  = CurrentTrack.Elements[i].WorldPosition;
                    Follower.WorldDirection = CurrentTrack.Elements[i].WorldDirection;
                    Follower.WorldUp        = CurrentTrack.Elements[i].WorldUp;
                    Follower.WorldSide      = CurrentTrack.Elements[i].WorldSide;
                    Follower.CurveRadius    = CurrentTrack.Elements[i].CurveRadius;
                    Follower.CurveCant      = CurrentTrack.Elements[i].CurveCant;
                }
            }
            else
            {
                if (db != 0.0)
                {
                    if (CurrentTrack.Elements[i].CurveRadius != 0.0)
                    {
                        Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
                    }
                    else
                    {
                        Follower.CurveRadius = 0.0;
                    }
                    if (i < CurrentTrack.Elements.Length - 1)
                    {
                        double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
                        if (t < 0.0)
                        {
                            t = 0.0;
                        }
                        else if (t > 1.0)
                        {
                            t = 1.0;
                        }
                        double t2 = t * t;
                        double t3 = t2 * t;
                        Follower.CurveCant =
                            (2.0 * t3 - 3.0 * t2 + 1.0) * CurrentTrack.Elements[i].CurveCant +
                            (t3 - 2.0 * t2 + t) * CurrentTrack.Elements[i].CurveCantTangent +
                            (-2.0 * t3 + 3.0 * t2) * CurrentTrack.Elements[i + 1].CurveCant +
                            (t3 - t2) * CurrentTrack.Elements[i + 1].CurveCantTangent;
                    }
                    else
                    {
                        Follower.CurveCant = CurrentTrack.Elements[i].CurveCant;
                    }
                }
                else
                {
                    Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
                    Follower.CurveCant   = CurrentTrack.Elements[i].CurveCant;
                }
            }
            Follower.AdhesionMultiplier = CurrentTrack.Elements[i].AdhesionMultiplier;
            // inaccuracy
            if (AddTrackInaccurary)
            {
                double x, y, c;
                if (i < CurrentTrack.Elements.Length - 1)
                {
                    double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
                    if (t < 0.0)
                    {
                        t = 0.0;
                    }
                    else if (t > 1.0)
                    {
                        t = 1.0;
                    }
                    double x1, y1, c1;
                    double x2, y2, c2;
                    GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i].CsvRwAccuracyLevel, out x1, out y1, out c1);
                    GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i + 1].CsvRwAccuracyLevel, out x2, out y2, out c2);
                    x = (1.0 - t) * x1 + t * x2;
                    y = (1.0 - t) * y1 + t * y2;
                    c = (1.0 - t) * c1 + t * c2;
                }
                else
                {
                    GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i].CsvRwAccuracyLevel, out x, out y, out c);
                }
                Follower.WorldPosition.X    += x * Follower.WorldSide.X + y * Follower.WorldUp.X;
                Follower.WorldPosition.Y    += x * Follower.WorldSide.Y + y * Follower.WorldUp.Y;
                Follower.WorldPosition.Z    += x * Follower.WorldSide.Z + y * Follower.WorldUp.Z;
                Follower.CurveCant          += c;
                Follower.CantDueToInaccuracy = c;
            }
            else
            {
                Follower.CantDueToInaccuracy = 0.0;
            }
            // events
            CheckEvents(ref Follower, i, Math.Sign(db - da), da, db);
            // finish
            Follower.TrackPosition    = NewTrackPosition;
            Follower.LastTrackElement = i;
        }
 internal static void UpdateTrackFollower(ref TrackFollower Follower, double NewTrackPosition, bool UpdateWorldCoordinates, bool AddTrackInaccurary)
 {
     if (CurrentTrack.Elements == null) return;
     if (CurrentTrack.Elements.Length == 0) return;
     int i = Follower.LastTrackElement;
     while (i >= 0 && NewTrackPosition < CurrentTrack.Elements[i].StartingTrackPosition) {
         double ta = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
         double tb = -0.01;
         CheckEvents(ref Follower, i, -1, ta, tb);
         i--;
     }
     if (i >= 0) {
         while (i < CurrentTrack.Elements.Length - 1) {
             if (NewTrackPosition < CurrentTrack.Elements[i + 1].StartingTrackPosition) break;
             double ta = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
             double tb = CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition + 0.01;
             CheckEvents(ref Follower, i, 1, ta, tb);
             i++;
         }
     } else i = 0;
     double da = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
     double db = NewTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
     // track
     if (UpdateWorldCoordinates) {
         if (db != 0.0) {
             if (CurrentTrack.Elements[i].CurveRadius != 0.0) {
                 // side curve
                 double r = CurrentTrack.Elements[i].CurveRadius;
                 double p = CurrentTrack.Elements[i].WorldDirection.Y / Math.Sqrt(CurrentTrack.Elements[i].WorldDirection.X * CurrentTrack.Elements[i].WorldDirection.X + CurrentTrack.Elements[i].WorldDirection.Z * CurrentTrack.Elements[i].WorldDirection.Z);
                 double s = db / Math.Sqrt(1.0 + p * p);
                 double h = s * p;
                 double b = s / Math.Abs(r);
                 double f = 2.0 * r * r * (1.0 - Math.Cos(b));
                 double c = (double)Math.Sign(db) * Math.Sqrt(f >= 0.0 ? f : 0.0);
                 double a = 0.5 * (double)Math.Sign(r) * b;
                 World.Vector3D D = new World.Vector3D(CurrentTrack.Elements[i].WorldDirection.X, 0.0, CurrentTrack.Elements[i].WorldDirection.Z);
                 World.Normalize(ref D.X, ref D.Y, ref D.Z);
                 double cosa = Math.Cos(a);
                 double sina = Math.Sin(a);
                 World.Rotate(ref D.X, ref D.Y, ref D.Z, 0.0, 1.0, 0.0, cosa, sina);
                 Follower.WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + c * D.X;
                 Follower.WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + h;
                 Follower.WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + c * D.Z;
                 World.Rotate(ref D.X, ref D.Y, ref D.Z, 0.0, 1.0, 0.0, cosa, sina);
                 Follower.WorldDirection.X = D.X;
                 Follower.WorldDirection.Y = p;
                 Follower.WorldDirection.Z = D.Z;
                 World.Normalize(ref Follower.WorldDirection.X, ref Follower.WorldDirection.Y, ref Follower.WorldDirection.Z);
                 double cos2a = Math.Cos(2.0 * a);
                 double sin2a = Math.Sin(2.0 * a);
                 Follower.WorldSide = CurrentTrack.Elements[i].WorldSide;
                 World.Rotate(ref Follower.WorldSide.X, ref Follower.WorldSide.Y, ref Follower.WorldSide.Z, 0.0, 1.0, 0.0, cos2a, sin2a);
                 World.Cross(Follower.WorldDirection.X, Follower.WorldDirection.Y, Follower.WorldDirection.Z, Follower.WorldSide.X, Follower.WorldSide.Y, Follower.WorldSide.Z, out Follower.WorldUp.X, out Follower.WorldUp.Y, out Follower.WorldUp.Z);
                 Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
             } else {
                 // straight
                 Follower.WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + db * CurrentTrack.Elements[i].WorldDirection.X;
                 Follower.WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + db * CurrentTrack.Elements[i].WorldDirection.Y;
                 Follower.WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + db * CurrentTrack.Elements[i].WorldDirection.Z;
                 Follower.WorldDirection = CurrentTrack.Elements[i].WorldDirection;
                 Follower.WorldUp = CurrentTrack.Elements[i].WorldUp;
                 Follower.WorldSide = CurrentTrack.Elements[i].WorldSide;
                 Follower.CurveRadius = 0.0;
             }
             // cant
             if (i < CurrentTrack.Elements.Length - 1) {
                 double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
                 switch (CurrentTrack.Elements[i].CurveCantInterpolation) {
                     case CantInterpolationMode.BiasForward:
                         t *= t;
                         t = 1.0 - t * t;
                         t = 1.0 - t * t;
                         break;
                     case CantInterpolationMode.BiasBackward:
                         t = 1.0 - t;
                         t *= t;
                         t = 1.0 - t * t;
                         t *= t;
                         break;
                 }
                 Follower.CurveCant = (1.0 - t) * CurrentTrack.Elements[i].CurveCant + t * CurrentTrack.Elements[i + 1].CurveCant;
             } else {
                 Follower.CurveCant = CurrentTrack.Elements[i].CurveCant;
             }
         } else {
             Follower.WorldPosition = CurrentTrack.Elements[i].WorldPosition;
             Follower.WorldDirection = CurrentTrack.Elements[i].WorldDirection;
             Follower.WorldUp = CurrentTrack.Elements[i].WorldUp;
             Follower.WorldSide = CurrentTrack.Elements[i].WorldSide;
             Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
             Follower.CurveCant = CurrentTrack.Elements[i].CurveCant;
         }
     }
     Follower.AdhesionMultiplier = CurrentTrack.Elements[i].AdhesionMultiplier;
     if (AddTrackInaccurary) {
         double f = NewTrackPosition;
         f = 0.3121 * Math.Sin(0.9843 * f) + 1.1217 * Math.Sin(0.1874 * f) + 1.6421 * Math.Sin(0.1126 * f) + 1.8421 * Math.Sin(0.2546 * f);
         f *= 0.15 * CurrentTrack.Elements[i].Inaccuracy;
         double g = NewTrackPosition;
         g = 0.3495 * Math.Sin(0.8272 * g) + 1.6321 * Math.Sin(0.2356 * g);
         g *= 0.15 * CurrentTrack.Elements[i].Inaccuracy;
         Follower.WorldPosition.X += f * Follower.WorldSide.X + g * Follower.WorldUp.X;
         Follower.WorldPosition.Y += f * Follower.WorldSide.Y + g * Follower.WorldUp.Y;
         Follower.WorldPosition.Z += f * Follower.WorldSide.Z + g * Follower.WorldUp.Z;
     }
     // events
     CheckEvents(ref Follower, i, Math.Sign(db - da), da, db);
     // finish
     Follower.TrackPosition = NewTrackPosition;
     Follower.LastTrackElement = i;
 }
Example #18
0
		private static void RenderCube(World.Vector3D Position, World.Vector3D Direction, World.Vector3D Up, World.Vector3D Side, double Size, double CameraX, double CameraY, double CameraZ, int TextureIndex) {
			int OpenGlTextureIndex = TextureManager.UseTexture(TextureIndex, TextureManager.UseMode.LoadImmediately);
			if (OpenGlTextureIndex > 0) {
				if (!TexturingEnabled) {
					Gl.glEnable(Gl.GL_TEXTURE_2D);
					TexturingEnabled = false;
				}
				Gl.glBindTexture(Gl.GL_TEXTURE_2D, OpenGlTextureIndex);
			} else {
				if (TexturingEnabled) {
					Gl.glDisable(Gl.GL_TEXTURE_2D);
					TexturingEnabled = false;
				}
			}
			World.Vector3D[] v = new World.Vector3D[8];
			v[0] = new World.Vector3D(Size, Size, -Size);
			v[1] = new World.Vector3D(Size, -Size, -Size);
			v[2] = new World.Vector3D(-Size, -Size, -Size);
			v[3] = new World.Vector3D(-Size, Size, -Size);
			v[4] = new World.Vector3D(Size, Size, Size);
			v[5] = new World.Vector3D(Size, -Size, Size);
			v[6] = new World.Vector3D(-Size, -Size, Size);
			v[7] = new World.Vector3D(-Size, Size, Size);
			for (int i = 0; i < 8; i++) {
				World.Rotate(ref v[i].X, ref v[i].Y, ref v[i].Z, Direction.X, Direction.Y, Direction.Z, Up.X, Up.Y, Up.Z, Side.X, Side.Y, Side.Z);
				v[i].X += Position.X - CameraX;
				v[i].Y += Position.Y - CameraY;
				v[i].Z += Position.Z - CameraZ;
			}
			int[][] Faces = new int[6][];
			Faces[0] = new int[] { 0, 1, 2, 3 };
			Faces[1] = new int[] { 0, 4, 5, 1 };
			Faces[2] = new int[] { 0, 3, 7, 4 };
			Faces[3] = new int[] { 6, 5, 4, 7 };
			Faces[4] = new int[] { 6, 7, 3, 2 };
			Faces[5] = new int[] { 6, 2, 1, 5 };
			if (OpenGlTextureIndex != 0) {
				World.Vector2D[][] t = new World.Vector2D[6][];
				t[0] = new World.Vector2D[] { new World.Vector2D(1.0, 0.0), new World.Vector2D(1.0, 1.0), new World.Vector2D(0.0, 1.0), new World.Vector2D(0.0, 0.0) };
				t[1] = new World.Vector2D[] { new World.Vector2D(0.0, 0.0), new World.Vector2D(1.0, 0.0), new World.Vector2D(1.0, 1.0), new World.Vector2D(0.0, 1.0) };
				t[2] = new World.Vector2D[] { new World.Vector2D(1.0, 1.0), new World.Vector2D(0.0, 1.0), new World.Vector2D(0.0, 0.0), new World.Vector2D(1.0, 0.0) };
				t[3] = new World.Vector2D[] { new World.Vector2D(1.0, 1.0), new World.Vector2D(0.0, 1.0), new World.Vector2D(0.0, 0.0), new World.Vector2D(1.0, 0.0) };
				t[4] = new World.Vector2D[] { new World.Vector2D(0.0, 1.0), new World.Vector2D(0.0, 0.0), new World.Vector2D(1.0, 0.0), new World.Vector2D(1.0, 1.0) };
				t[5] = new World.Vector2D[] { new World.Vector2D(0.0, 1.0), new World.Vector2D(0.0, 0.0), new World.Vector2D(1.0, 0.0), new World.Vector2D(1.0, 1.0) };
				for (int i = 0; i < 6; i++) {
					Gl.glBegin(Gl.GL_QUADS);
					Gl.glColor3d(1.0, 1.0, 1.0);
					for (int j = 0; j < 4; j++) {
						Gl.glTexCoord2d(t[i][j].X, t[i][j].Y);
						Gl.glVertex3d(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z);
					}
					Gl.glEnd();
				}
			} else {
				for (int i = 0; i < 6; i++) {
					Gl.glBegin(Gl.GL_QUADS);
					Gl.glColor3d(1.0, 1.0, 1.0);
					for (int j = 0; j < 4; j++) {
						Gl.glVertex3d(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z);
					}
					Gl.glEnd();
				}
			}
		}
Example #19
0
        // parse animated object config
        /// <summary>Loads a collection of animated objects from a file.</summary>
        /// <param name="FileName">The text file to load the animated object from. Must be an absolute file name.</param>
        /// <param name="Encoding">The encoding the file is saved in. If the file uses a byte order mark, the encoding indicated by the byte order mark is used and the Encoding parameter is ignored.</param>
        /// <param name="LoadMode">The texture load mode.</param>
        /// <returns>The collection of animated objects.</returns>
        internal static ObjectManager.AnimatedObjectCollection ReadObject(string FileName, System.Text.Encoding Encoding, ObjectManager.ObjectLoadMode LoadMode)
        {
            System.Globalization.CultureInfo       Culture = System.Globalization.CultureInfo.InvariantCulture;
            ObjectManager.AnimatedObjectCollection Result  = new ObjectManager.AnimatedObjectCollection();
            Result.Objects = new ObjectManager.AnimatedObject[4];
            int ObjectCount = 0;

            // load file
            string[] Lines   = System.IO.File.ReadAllLines(FileName, Encoding);
            bool     rpnUsed = false;

            for (int i = 0; i < Lines.Length; i++)
            {
                int j = Lines[i].IndexOf(';');
                if (j >= 0)
                {
                    Lines[i] = Lines[i].Substring(0, j).Trim();
                }
                else
                {
                    Lines[i] = Lines[i].Trim();
                }
                if (Lines[i].IndexOf("functionrpn", StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    rpnUsed = true;
                }
            }
            if (rpnUsed)
            {
                Interface.AddMessage(Interface.MessageType.Error, false, "An animated object file contains RPN functions. These were never meant to be used directly, only for debugging. They won't be supported indefinately. Please get rid of them in file " + FileName);
            }
            for (int i = 0; i < Lines.Length; i++)
            {
                if (Lines[i].Length != 0)
                {
                    switch (Lines[i].ToLowerInvariant())
                    {
                    case "[include]":
                    {
                        i++;
                        World.Vector3D position           = new World.Vector3D(0.0, 0.0, 0.0);
                        ObjectManager.UnifiedObject[] obj = new OpenBve.ObjectManager.UnifiedObject[4];
                        int objCount = 0;
                        while (i < Lines.Length && !(Lines[i].StartsWith("[", StringComparison.Ordinal) & Lines[i].EndsWith("]", StringComparison.Ordinal)))
                        {
                            if (Lines[i].Length != 0)
                            {
                                int j = Lines[i].IndexOf("=", StringComparison.Ordinal);
                                if (j > 0)
                                {
                                    string a = Lines[i].Substring(0, j).TrimEnd();
                                    string b = Lines[i].Substring(j + 1).TrimStart();
                                    switch (a.ToLowerInvariant())
                                    {
                                    case "position":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 3)
                                        {
                                            double x, y, z;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                position = new World.Vector3D(x, y, z);
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    default:
                                        Interface.AddMessage(Interface.MessageType.Error, false, "The attribute " + a + " is not supported at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        break;
                                    }
                                }
                                else
                                {
                                    string Folder = System.IO.Path.GetDirectoryName(FileName);
                                    if (Path.ContainsInvalidChars(Lines[i]))
                                    {
                                        Interface.AddMessage(Interface.MessageType.Error, false, Lines[i] + " contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                    }
                                    else
                                    {
                                        string file = OpenBveApi.Path.CombineFile(Folder, Lines[i]);
                                        if (System.IO.File.Exists(file))
                                        {
                                            if (obj.Length == objCount)
                                            {
                                                Array.Resize <ObjectManager.UnifiedObject>(ref obj, obj.Length << 1);
                                            }
                                            obj[objCount] = ObjectManager.LoadObject(file, Encoding, LoadMode, false, false, false);
                                            objCount++;
                                        }
                                        else
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, true, "File " + file + " not found at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    }
                                }
                            }
                            i++;
                        }
                        i--;
                        for (int j = 0; j < objCount; j++)
                        {
                            if (obj[j] != null)
                            {
                                if (obj[j] is ObjectManager.StaticObject)
                                {
                                    ObjectManager.StaticObject s = (ObjectManager.StaticObject)obj[j];
                                    s.Dynamic = true;
                                    if (ObjectCount >= Result.Objects.Length)
                                    {
                                        Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length << 1);
                                    }
                                    ObjectManager.AnimatedObject      a   = new ObjectManager.AnimatedObject();
                                    ObjectManager.AnimatedObjectState aos = new ObjectManager.AnimatedObjectState();
                                    aos.Object   = s;
                                    aos.Position = position;
                                    a.States     = new ObjectManager.AnimatedObjectState[] { aos };
                                    Result.Objects[ObjectCount] = a;
                                    ObjectCount++;
                                }
                                else if (obj[j] is ObjectManager.AnimatedObjectCollection)
                                {
                                    ObjectManager.AnimatedObjectCollection a = (ObjectManager.AnimatedObjectCollection)obj[j];
                                    for (int k = 0; k < a.Objects.Length; k++)
                                    {
                                        if (ObjectCount >= Result.Objects.Length)
                                        {
                                            Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length << 1);
                                        }
                                        for (int h = 0; h < a.Objects[k].States.Length; h++)
                                        {
                                            a.Objects[k].States[h].Position.X += position.X;
                                            a.Objects[k].States[h].Position.Y += position.Y;
                                            a.Objects[k].States[h].Position.Z += position.Z;
                                        }
                                        Result.Objects[ObjectCount] = a.Objects[k];
                                        ObjectCount++;
                                    }
                                }
                            }
                        }
                    }
                    break;

                    case "[object]":
                    {
                        i++;
                        if (Result.Objects.Length == ObjectCount)
                        {
                            Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length << 1);
                        }
                        Result.Objects[ObjectCount]                        = new ObjectManager.AnimatedObject();
                        Result.Objects[ObjectCount].States                 = new ObjectManager.AnimatedObjectState[] { };
                        Result.Objects[ObjectCount].CurrentState           = -1;
                        Result.Objects[ObjectCount].TranslateXDirection    = new World.Vector3D(1.0, 0.0, 0.0);
                        Result.Objects[ObjectCount].TranslateYDirection    = new World.Vector3D(0.0, 1.0, 0.0);
                        Result.Objects[ObjectCount].TranslateZDirection    = new World.Vector3D(0.0, 0.0, 1.0);
                        Result.Objects[ObjectCount].RotateXDirection       = new World.Vector3D(1.0, 0.0, 0.0);
                        Result.Objects[ObjectCount].RotateYDirection       = new World.Vector3D(0.0, 1.0, 0.0);
                        Result.Objects[ObjectCount].RotateZDirection       = new World.Vector3D(0.0, 0.0, 1.0);
                        Result.Objects[ObjectCount].TextureShiftXDirection = new World.Vector2D(1.0, 0.0);
                        Result.Objects[ObjectCount].TextureShiftYDirection = new World.Vector2D(0.0, 1.0);
                        Result.Objects[ObjectCount].RefreshRate            = 0.0;
                        Result.Objects[ObjectCount].ObjectIndex            = -1;
                        World.Vector3D Position          = new World.Vector3D(0.0, 0.0, 0.0);
                        bool           timetableUsed     = false;
                        string[]       StateFiles        = null;
                        string         StateFunctionRpn  = null;
                        int            StateFunctionLine = -1;
                        while (i < Lines.Length && !(Lines[i].StartsWith("[", StringComparison.Ordinal) & Lines[i].EndsWith("]", StringComparison.Ordinal)))
                        {
                            if (Lines[i].Length != 0)
                            {
                                int j = Lines[i].IndexOf("=", StringComparison.Ordinal);
                                if (j > 0)
                                {
                                    string a = Lines[i].Substring(0, j).TrimEnd();
                                    string b = Lines[i].Substring(j + 1).TrimStart();
                                    switch (a.ToLowerInvariant())
                                    {
                                    case "position":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 3)
                                        {
                                            double x, y, z;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                Position = new World.Vector3D(x, y, z);
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    case "states":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length >= 1)
                                        {
                                            string Folder = System.IO.Path.GetDirectoryName(FileName);
                                            StateFiles = new string[s.Length];
                                            bool NullObject = true;
                                            for (int k = 0; k < s.Length; k++)
                                            {
                                                s[k] = s[k].Trim();
                                                if (s[k].Length == 0)
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "File" + k.ToString(Culture) + " is an empty string - did you mean something else? - in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                    StateFiles[k] = null;
                                                }
                                                else if (Path.ContainsInvalidChars(s[k]))
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "File" + k.ToString(Culture) + " contains illegal characters in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                    StateFiles[k] = null;
                                                }
                                                else
                                                {
                                                    StateFiles[k] = OpenBveApi.Path.CombineFile(Folder, s[k]);
                                                    if (!System.IO.File.Exists(StateFiles[k]))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, true, "File " + StateFiles[k] + " not found in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                        StateFiles[k] = null;
                                                    }
                                                }
                                                if (StateFiles[k] != null)
                                                {
                                                    NullObject = false;
                                                }
                                            }
                                            if (NullObject == true)
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "No statefiles were found in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                return(null);
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "At least one argument is expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            return(null);
                                        }
                                    } break;

                                    case "statefunction":
                                        try {
                                            StateFunctionLine = i;
                                            StateFunctionRpn  = FunctionScripts.GetPostfixNotationFromInfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "statefunctionrpn":
                                    {
                                        StateFunctionLine = i;
                                        StateFunctionRpn  = b;
                                    } break;

                                    case "translatexdirection":
                                    case "translateydirection":
                                    case "translatezdirection":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 3)
                                        {
                                            double x, y, z;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                switch (a.ToLowerInvariant())
                                                {
                                                case "translatexdirection":
                                                    Result.Objects[ObjectCount].TranslateXDirection = new World.Vector3D(x, y, z);
                                                    break;

                                                case "translateydirection":
                                                    Result.Objects[ObjectCount].TranslateYDirection = new World.Vector3D(x, y, z);
                                                    break;

                                                case "translatezdirection":
                                                    Result.Objects[ObjectCount].TranslateZDirection = new World.Vector3D(x, y, z);
                                                    break;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    case "translatexfunction":
                                        try {
                                            Result.Objects[ObjectCount].TranslateXFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "translateyfunction":
                                        try {
                                            Result.Objects[ObjectCount].TranslateYFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "translatezfunction":
                                        try {
                                            Result.Objects[ObjectCount].TranslateZFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "translatexfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].TranslateXFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "translateyfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].TranslateYFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "translatezfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].TranslateZFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotatexdirection":
                                    case "rotateydirection":
                                    case "rotatezdirection":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 3)
                                        {
                                            double x, y, z;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (x == 0.0 & y == 0.0 & z == 0.0)
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "The direction indicated by X, Y and Z is expected to be non-zero in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                switch (a.ToLowerInvariant())
                                                {
                                                case "rotatexdirection":
                                                    Result.Objects[ObjectCount].RotateXDirection = new World.Vector3D(x, y, z);
                                                    break;

                                                case "rotateydirection":
                                                    Result.Objects[ObjectCount].RotateYDirection = new World.Vector3D(x, y, z);
                                                    break;

                                                case "rotatezdirection":
                                                    Result.Objects[ObjectCount].RotateZDirection = new World.Vector3D(x, y, z);
                                                    break;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    case "rotatexfunction":
                                        try {
                                            Result.Objects[ObjectCount].RotateXFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotateyfunction":
                                        try {
                                            Result.Objects[ObjectCount].RotateYFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotatezfunction":
                                        try {
                                            Result.Objects[ObjectCount].RotateZFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotatexfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].RotateXFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotateyfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].RotateYFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotatezfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].RotateZFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "rotatexdamping":
                                    case "rotateydamping":
                                    case "rotatezdamping":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 2)
                                        {
                                            double nf, dr;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out nf))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "NaturalFrequency is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out dr))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "DampingRatio is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (nf <= 0.0)
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "NaturalFrequency is expected to be positive in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (dr <= 0.0)
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "DampingRatio is expected to be positive in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                switch (a.ToLowerInvariant())
                                                {
                                                case "rotatexdamping":
                                                    Result.Objects[ObjectCount].RotateXDamping = new ObjectManager.Damping(nf, dr);
                                                    break;

                                                case "rotateydamping":
                                                    Result.Objects[ObjectCount].RotateYDamping = new ObjectManager.Damping(nf, dr);
                                                    break;

                                                case "rotatezdamping":
                                                    Result.Objects[ObjectCount].RotateZDamping = new ObjectManager.Damping(nf, dr);
                                                    break;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 2 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    case "textureshiftxdirection":
                                    case "textureshiftydirection":
                                    {
                                        string[] s = b.Split(',');
                                        if (s.Length == 2)
                                        {
                                            double x, y;
                                            if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            }
                                            else
                                            {
                                                switch (a.ToLowerInvariant())
                                                {
                                                case "textureshiftxdirection":
                                                    Result.Objects[ObjectCount].TextureShiftXDirection = new World.Vector2D(x, y);
                                                    break;

                                                case "textureshiftydirection":
                                                    Result.Objects[ObjectCount].TextureShiftYDirection = new World.Vector2D(x, y);
                                                    break;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 2 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                    } break;

                                    case "textureshiftxfunction":
                                        try {
                                            Result.Objects[ObjectCount].TextureShiftXFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "textureshiftyfunction":
                                        try {
                                            Result.Objects[ObjectCount].TextureShiftYFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "textureshiftxfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].TextureShiftXFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "textureshiftyfunctionrpn":
                                        try {
                                            Result.Objects[ObjectCount].TextureShiftYFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                        } catch (Exception ex) {
                                            Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        } break;

                                    case "textureoverride":
                                        switch (b.ToLowerInvariant())
                                        {
                                        case "none":
                                            break;

                                        case "timetable":
                                            if (!timetableUsed)
                                            {
                                                Timetable.AddObjectForCustomTimetable(Result.Objects[ObjectCount]);
                                                timetableUsed = true;
                                            }
                                            break;

                                        default:
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Unrecognized value in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                            break;
                                        }
                                        break;

                                    case "refreshrate":
                                    {
                                        double r;
                                        if (!double.TryParse(b, System.Globalization.NumberStyles.Float, Culture, out r))
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Value is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                        else if (r < 0.0)
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Value is expected to be non-negative in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        }
                                        else
                                        {
                                            Result.Objects[ObjectCount].RefreshRate = r;
                                        }
                                    } break;

                                    default:
                                        Interface.AddMessage(Interface.MessageType.Error, false, "The attribute " + a + " is not supported at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                        break;
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(Interface.MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                    return(null);
                                }
                            }
                            i++;
                        }
                        i--;
                        if (StateFiles != null)
                        {
                            // create the object
                            if (timetableUsed)
                            {
                                if (StateFunctionRpn != null)
                                {
                                    StateFunctionRpn = "timetable 0 == " + StateFunctionRpn + " -1 ?";
                                }
                                else
                                {
                                    StateFunctionRpn = "timetable";
                                }
                            }
                            if (StateFunctionRpn != null)
                            {
                                try {
                                    Result.Objects[ObjectCount].StateFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(StateFunctionRpn);
                                } catch (Exception ex) {
                                    Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in StateFunction at line " + (StateFunctionLine + 1).ToString(Culture) + " in file " + FileName);
                                }
                            }
                            Result.Objects[ObjectCount].States = new ObjectManager.AnimatedObjectState[StateFiles.Length];
                            bool ForceTextureRepeatX = Result.Objects[ObjectCount].TextureShiftXFunction != null & Result.Objects[ObjectCount].TextureShiftXDirection.X != 0.0 |
                                                       Result.Objects[ObjectCount].TextureShiftYFunction != null & Result.Objects[ObjectCount].TextureShiftYDirection.Y != 0.0;
                            bool ForceTextureRepeatY = Result.Objects[ObjectCount].TextureShiftXFunction != null & Result.Objects[ObjectCount].TextureShiftXDirection.X != 0.0 |
                                                       Result.Objects[ObjectCount].TextureShiftYFunction != null & Result.Objects[ObjectCount].TextureShiftYDirection.Y != 0.0;
                            for (int k = 0; k < StateFiles.Length; k++)
                            {
                                Result.Objects[ObjectCount].States[k].Position = new World.Vector3D(0.0, 0.0, 0.0);
                                if (StateFiles[k] != null)
                                {
                                    Result.Objects[ObjectCount].States[k].Object = ObjectManager.LoadStaticObject(StateFiles[k], Encoding, LoadMode, false, ForceTextureRepeatX, ForceTextureRepeatY);
                                    if (Result.Objects[ObjectCount].States[k].Object != null)
                                    {
                                        Result.Objects[ObjectCount].States[k].Object.Dynamic = true;
                                    }
                                }
                                else
                                {
                                    Result.Objects[ObjectCount].States[k].Object = null;
                                }
                                for (int j = 0; j < Result.Objects[ObjectCount].States.Length; j++)
                                {
                                    Result.Objects[ObjectCount].States[j].Position = Position;
                                }
                            }
                        }
                        else
                        {
                            Result.Objects[ObjectCount].States = new ObjectManager.AnimatedObjectState[] { };
                        }
                        ObjectCount++;
                    }
                    break;

                    default:
                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                        return(null);
                    }
                }
            }
            Array.Resize <ObjectManager.AnimatedObject>(ref Result.Objects, ObjectCount);
            return(Result);
        }
Example #20
0
        // process events
        private static void ProcessEvents()
        {
            SDL.SDL_Event Event;
            while (SDL.SDL_PollEvent(out Event) != 0)
            {
                switch (Event.type)
                {
                // quit
                case SDL.SDL_EventType.SDL_QUIT:
                    Quit = true;
                    return;

                // resize
                case SDL.SDL_EventType.SDL_WINDOWEVENT:
                    if (Event.window.windowEvent == SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESIZED)
                    {
                        Renderer.ScreenWidth  = Event.window.data1;
                        Renderer.ScreenHeight = Event.window.data2;
                        UpdateViewport();
                    }
                    break;

                // mouse
                case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN:
                    MouseCenterX         = (short)Event.button.x;
                    MouseCenterY         = (short)Event.button.y;
                    MouseCameraPosition  = World.AbsoluteCameraPosition;
                    MouseCameraDirection = World.AbsoluteCameraDirection;
                    MouseCameraUp        = World.AbsoluteCameraUp;
                    MouseCameraSide      = World.AbsoluteCameraSide;
                    MouseButton          = Event.button.button;
                    break;

                case SDL.SDL_EventType.SDL_MOUSEBUTTONUP:
                    MouseButton = 0;
                    break;

                case SDL.SDL_EventType.SDL_MOUSEMOTION:
                    if (MouseButton == SDL.SDL_BUTTON_LEFT)
                    {
                        World.AbsoluteCameraDirection = MouseCameraDirection;
                        World.AbsoluteCameraUp        = MouseCameraUp;
                        World.AbsoluteCameraSide      = MouseCameraSide;
                        {
                            double dx   = 0.0025 * (double)(MouseCenterX - Event.motion.x);
                            double cosa = Math.Cos(dx);
                            double sina = Math.Sin(dx);
                            World.Rotate(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z, 0.0, 1.0, 0.0, cosa, sina);
                            World.Rotate(ref World.AbsoluteCameraUp.X, ref World.AbsoluteCameraUp.Y, ref World.AbsoluteCameraUp.Z, 0.0, 1.0, 0.0, cosa, sina);
                            World.Rotate(ref World.AbsoluteCameraSide.X, ref World.AbsoluteCameraSide.Y, ref World.AbsoluteCameraSide.Z, 0.0, 1.0, 0.0, cosa, sina);
                        }
                        {
                            double dy   = 0.0025 * (double)(MouseCenterY - Event.motion.y);
                            double cosa = Math.Cos(dy);
                            double sina = Math.Sin(dy);
                            World.Rotate(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z, World.AbsoluteCameraSide.X, World.AbsoluteCameraSide.Y, World.AbsoluteCameraSide.Z, cosa, sina);
                            World.Rotate(ref World.AbsoluteCameraUp.X, ref World.AbsoluteCameraUp.Y, ref World.AbsoluteCameraUp.Z, World.AbsoluteCameraSide.X, World.AbsoluteCameraSide.Y, World.AbsoluteCameraSide.Z, cosa, sina);
                        }
                        ReducedMode = false;
                    }
                    else if (MouseButton == SDL.SDL_BUTTON_RIGHT)
                    {
                        World.AbsoluteCameraPosition = MouseCameraPosition;
                        double dx = -0.025 * (double)(Event.motion.x - MouseCenterX);
                        World.AbsoluteCameraPosition.X += dx * World.AbsoluteCameraSide.X;
                        World.AbsoluteCameraPosition.Y += dx * World.AbsoluteCameraSide.Y;
                        World.AbsoluteCameraPosition.Z += dx * World.AbsoluteCameraSide.Z;
                        double dy = 0.025 * (double)(Event.motion.y - MouseCenterY);
                        World.AbsoluteCameraPosition.X += dy * World.AbsoluteCameraUp.X;
                        World.AbsoluteCameraPosition.Y += dy * World.AbsoluteCameraUp.Y;
                        World.AbsoluteCameraPosition.Z += dy * World.AbsoluteCameraUp.Z;
                        ReducedMode = false;
                    }
                    else if (MouseButton == SDL.SDL_BUTTON_MIDDLE)
                    {
                        World.AbsoluteCameraPosition = MouseCameraPosition;
                        double dx = -0.025 * (double)(Event.motion.x - MouseCenterX);
                        World.AbsoluteCameraPosition.X += dx * World.AbsoluteCameraSide.X;
                        World.AbsoluteCameraPosition.Y += dx * World.AbsoluteCameraSide.Y;
                        World.AbsoluteCameraPosition.Z += dx * World.AbsoluteCameraSide.Z;
                        double dz = -0.025 * (double)(Event.motion.y - MouseCenterY);
                        World.AbsoluteCameraPosition.X += dz * World.AbsoluteCameraDirection.X;
                        World.AbsoluteCameraPosition.Y += dz * World.AbsoluteCameraDirection.Y;
                        World.AbsoluteCameraPosition.Z += dz * World.AbsoluteCameraDirection.Z;
                        ReducedMode = false;
                    }
                    break;

                // key down
                case SDL.SDL_EventType.SDL_KEYDOWN:
                    switch (Event.key.keysym.sym)
                    {
                    case SDL.SDL_Keycode.SDLK_LSHIFT:
                    case SDL.SDL_Keycode.SDLK_RSHIFT:
                        ShiftPressed = true;
                        break;

                    case SDL.SDL_Keycode.SDLK_F5:
                        // reset
                        ReducedMode      = false;
                        LightingRelative = -1.0;
                        Game.Reset();
                        TextureManager.UnuseAllTextures();
                        Fonts.Initialize();
                        Interface.ClearMessages();
                        for (int i = 0; i < Files.Length; i++)
                        {
                                                                        #if !DEBUG
                            try {
                                                                                #endif
                            ObjectManager.UnifiedObject o = ObjectManager.LoadObject(Files[i], System.Text.Encoding.UTF8, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                            ObjectManager.CreateObject(o, new World.Vector3D(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0);
                                                                                #if !DEBUG
                        }
                        catch (Exception ex) {
                            Interface.AddMessage(Interface.MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Files[i] + ".");
                        }
                                                                        #endif
                        }
                        ObjectManager.InitializeVisibility();
                        ObjectManager.UpdateVisibility(0.0, true);
                        ObjectManager.UpdateAnimatedWorldObjects(0.01, true);
                        break;

                    case SDL.SDL_Keycode.SDLK_F7:
                    {
                        OpenFileDialog Dialog = new OpenFileDialog();
                        Dialog.CheckFileExists = true;
                        Dialog.Multiselect     = true;
                        Dialog.Filter          = "CSV/B3D/X/ANIMATED files|*.csv;*.b3d;*.x;*.animated|All files|*";
                        if (Dialog.ShowDialog() == DialogResult.OK)
                        {
                            string[] f = Dialog.FileNames;
                            int      n = Files.Length;
                            Array.Resize <string>(ref Files, n + f.Length);
                            for (int i = 0; i < f.Length; i++)
                            {
                                Files[n + i] = f[i];
                            }
                            // reset
                            ReducedMode      = false;
                            LightingRelative = -1.0;
                            Game.Reset();
                            TextureManager.UnuseAllTextures();
                            Fonts.Initialize();
                            Interface.ClearMessages();
                            for (int i = 0; i < Files.Length; i++)
                            {
                                                                                        #if !DEBUG
                                try {
                                                                                                #endif
                                ObjectManager.UnifiedObject o = ObjectManager.LoadObject(Files[i], System.Text.Encoding.UTF8, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                ObjectManager.CreateObject(o, new World.Vector3D(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0);
                                                                                                #if !DEBUG
                            }
                            catch (Exception ex) {
                                Interface.AddMessage(Interface.MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + Files[i] + ".");
                            }
                                                                                        #endif
                            }
                            ObjectManager.InitializeVisibility();
                            ObjectManager.FinishCreatingObjects();
                            ObjectManager.UpdateVisibility(0.0, true);
                            ObjectManager.UpdateAnimatedWorldObjects(0.01, true);
                        }
                    } break;

                    case SDL.SDL_Keycode.SDLK_F9:
                        if (Interface.MessageCount != 0)
                        {
                            formMessages.ShowMessages();
                        }
                        break;

                    case SDL.SDL_Keycode.SDLK_DELETE:
                        ReducedMode      = false;
                        LightingRelative = -1.0;
                        Game.Reset();
                        TextureManager.UnuseAllTextures();
                        Fonts.Initialize();
                        Interface.ClearMessages();
                        Files = new string[] { };
                        UpdateCaption();
                        break;

                    case SDL.SDL_Keycode.SDLK_LEFT:
                        RotateX     = -1;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_RIGHT:
                        RotateX     = 1;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_UP:
                        RotateY     = -1;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_DOWN:
                        RotateY     = 1;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_a:
                    case SDL.SDL_Keycode.SDLK_KP_4:
                        MoveX       = -1;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_d:
                    case SDL.SDL_Keycode.SDLK_KP_6:
                        MoveX       = 1;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_KP_8:
                        MoveY       = 1;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_KP_2:
                        MoveY       = -1;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_w:
                    case SDL.SDL_Keycode.SDLK_KP_9:
                        MoveZ       = 1;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_s:
                    case SDL.SDL_Keycode.SDLK_KP_3:
                        MoveZ       = -1;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_KP_5:
                        ResetCamera();
                        break;

                    case SDL.SDL_Keycode.SDLK_f:
                    case SDL.SDL_Keycode.SDLK_F1:
                        Renderer.OptionWireframe = !Renderer.OptionWireframe;
                        if (Renderer.OptionWireframe)
                        {
                            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
                        }
                        else
                        {
                            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
                        } break;

                    case SDL.SDL_Keycode.SDLK_n:
                    case SDL.SDL_Keycode.SDLK_F2:
                        Renderer.OptionNormals = !Renderer.OptionNormals;
                        break;

                    case SDL.SDL_Keycode.SDLK_l:
                    case SDL.SDL_Keycode.SDLK_F3:
                        LightingTarget = 1 - LightingTarget;
                        ReducedMode    = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_i:
                    case SDL.SDL_Keycode.SDLK_F4:
                        Renderer.OptionInterface = !Renderer.OptionInterface;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_g:
                    case SDL.SDL_Keycode.SDLK_c:
                        Renderer.OptionCoordinateSystem = !Renderer.OptionCoordinateSystem;
                        ReducedMode = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_b:
                        if (ShiftPressed)
                        {
                            ColorDialog dialog = new ColorDialog();
                            dialog.FullOpen = true;
                            if (dialog.ShowDialog() == DialogResult.OK)
                            {
                                Renderer.BackgroundColor = -1;
                                Renderer.ApplyBackgroundColor(dialog.Color.R, dialog.Color.G, dialog.Color.B);
                            }
                        }
                        else
                        {
                            Renderer.BackgroundColor++;
                            if (Renderer.BackgroundColor >= Renderer.MaxBackgroundColor)
                            {
                                Renderer.BackgroundColor = 0;
                            }
                            Renderer.ApplyBackgroundColor();
                        }
                        ReducedMode = false;
                        break;
                    }
                    break;

                // key up
                case SDL.SDL_EventType.SDL_KEYUP:
                    switch (Event.key.keysym.sym)
                    {
                    case SDL.SDL_Keycode.SDLK_LSHIFT:
                    case SDL.SDL_Keycode.SDLK_RSHIFT:
                        ShiftPressed = false;
                        break;

                    case SDL.SDL_Keycode.SDLK_LEFT:
                    case SDL.SDL_Keycode.SDLK_RIGHT:
                        RotateX = 0;
                        break;

                    case SDL.SDL_Keycode.SDLK_UP:
                    case SDL.SDL_Keycode.SDLK_DOWN:
                        RotateY = 0;
                        break;

                    case SDL.SDL_Keycode.SDLK_a:
                    case SDL.SDL_Keycode.SDLK_d:
                    case SDL.SDL_Keycode.SDLK_KP_4:
                    case SDL.SDL_Keycode.SDLK_KP_6:
                        MoveX = 0;
                        break;

                    case SDL.SDL_Keycode.SDLK_KP_8:
                    case SDL.SDL_Keycode.SDLK_KP_2:
                        MoveY = 0;
                        break;

                    case SDL.SDL_Keycode.SDLK_w:
                    case SDL.SDL_Keycode.SDLK_s:
                    case SDL.SDL_Keycode.SDLK_KP_9:
                    case SDL.SDL_Keycode.SDLK_KP_3:
                        MoveZ = 0;
                        break;
                    }
                    break;
                }
            }
        }
Example #21
0
		// ------------------
		
		
		// smoothen out turns
		private static void SmoothenOutTurns(int subdivisions) {
			if (subdivisions < 2) {
				throw new InvalidOperationException();
			}
			// subdivide track
			int length = TrackManager.CurrentTrack.Elements.Length;
			int newLength = (length - 1) * subdivisions + 1;
			double[] midpointsTrackPositions = new double[newLength];
			World.Vector3D[] midpointsWorldPositions = new World.Vector3D[newLength];
			World.Vector3D[] midpointsWorldDirections = new World.Vector3D[newLength];
			World.Vector3D[] midpointsWorldUps = new World.Vector3D[newLength];
			World.Vector3D[] midpointsWorldSides = new World.Vector3D[newLength];
			double[] midpointsCant = new double[newLength];
			for (int i = 0; i < newLength; i++) {
				int m = i % subdivisions;
				if (m != 0) {
					int q = i / subdivisions;
					TrackManager.TrackFollower follower = new TrackManager.TrackFollower();
					double r = (double)m / (double)subdivisions;
					double p = (1.0 - r) * TrackManager.CurrentTrack.Elements[q].StartingTrackPosition + r * TrackManager.CurrentTrack.Elements[q + 1].StartingTrackPosition;
					TrackManager.UpdateTrackFollower(ref follower, -1.0, true, false);
					TrackManager.UpdateTrackFollower(ref follower, p, true, false);
					midpointsTrackPositions[i] = p;
					midpointsWorldPositions[i] = follower.WorldPosition;
					midpointsWorldDirections[i] = follower.WorldDirection;
					midpointsWorldUps[i] = follower.WorldUp;
					midpointsWorldSides[i] = follower.WorldSide;
					midpointsCant[i] = follower.CurveCant;
				}
			}
			Array.Resize<TrackManager.TrackElement>(ref TrackManager.CurrentTrack.Elements, newLength);
			for (int i = length - 1; i >= 1; i--) {
				TrackManager.CurrentTrack.Elements[subdivisions * i] = TrackManager.CurrentTrack.Elements[i];
			}
			for (int i = 0; i < TrackManager.CurrentTrack.Elements.Length; i++) {
				int m = i % subdivisions;
				if (m != 0) {
					int q = i / subdivisions;
					int j = q * subdivisions;
					TrackManager.CurrentTrack.Elements[i] = TrackManager.CurrentTrack.Elements[j];
					TrackManager.CurrentTrack.Elements[i].Events = new TrackManager.GeneralEvent[] { };
					TrackManager.CurrentTrack.Elements[i].StartingTrackPosition = midpointsTrackPositions[i];
					TrackManager.CurrentTrack.Elements[i].WorldPosition = midpointsWorldPositions[i];
					TrackManager.CurrentTrack.Elements[i].WorldDirection = midpointsWorldDirections[i];
					TrackManager.CurrentTrack.Elements[i].WorldUp = midpointsWorldUps[i];
					TrackManager.CurrentTrack.Elements[i].WorldSide = midpointsWorldSides[i];
					TrackManager.CurrentTrack.Elements[i].CurveCant = midpointsCant[i];
					TrackManager.CurrentTrack.Elements[i].CurveCantTangent = 0.0;
				}
			}
			// find turns
			bool[] isTurn = new bool[TrackManager.CurrentTrack.Elements.Length];
			{
				TrackManager.TrackFollower follower = new TrackManager.TrackFollower();
				for (int i = 1; i < TrackManager.CurrentTrack.Elements.Length - 1; i++) {
					int m = i % subdivisions;
					if (m == 0) {
						double p = 0.00000001 * TrackManager.CurrentTrack.Elements[i - 1].StartingTrackPosition + 0.99999999 * TrackManager.CurrentTrack.Elements[i].StartingTrackPosition;
						TrackManager.UpdateTrackFollower(ref follower, p, true, false);
						World.Vector3D d1 = TrackManager.CurrentTrack.Elements[i].WorldDirection;
						World.Vector3D d2 = follower.WorldDirection;
						World.Vector3D d = World.Vector3D.Subtract(d1, d2);
						double t = d.X * d.X + d.Z * d.Z;
						const double e = 0.0001;
						if (t > e) {
							isTurn[i] = true;
						}
					}
				}
			}
			// replace turns by curves
			double totalShortage = 0.0;
			for (int i = 0; i < TrackManager.CurrentTrack.Elements.Length; i++) {
				if (isTurn[i]) {
					// estimate radius
					World.Vector3D AP = TrackManager.CurrentTrack.Elements[i - 1].WorldPosition;
					World.Vector3D AS = TrackManager.CurrentTrack.Elements[i - 1].WorldSide;
					World.Vector3D BP = TrackManager.CurrentTrack.Elements[i + 1].WorldPosition;
					World.Vector3D BS = TrackManager.CurrentTrack.Elements[i + 1].WorldSide;
					World.Vector3D S = World.Vector3D.Subtract(AS, BS);
					double rx;
					if (S.X * S.X > 0.000001) {
						rx = (BP.X - AP.X) / S.X;
					} else {
						rx = 0.0;
					}
					double rz;
					if (S.Z * S.Z > 0.000001) {
						rz = (BP.Z - AP.Z) / S.Z;
					} else {
						rz = 0.0;
					}
					if (rx != 0.0 | rz != 0.0) {
						double r;
						if (rx != 0.0 & rz != 0.0) {
							if (Math.Sign(rx) == Math.Sign(rz)) {
								double f = rx / rz;
								if (f > -1.1 & f < -0.9 | f > 0.9 & f < 1.1) {
									r = Math.Sqrt(Math.Abs(rx * rz)) * Math.Sign(rx);
								} else {
									r = 0.0;
								}
							} else {
								r = 0.0;
							}
						} else if (rx != 0.0) {
							r = rx;
						} else {
							r = rz;
						}
						if (r * r > 1.0) {
							// apply radius
							TrackManager.TrackFollower follower = new TrackManager.TrackFollower();
							TrackManager.CurrentTrack.Elements[i - 1].CurveRadius = r;
							double p = 0.00000001 * TrackManager.CurrentTrack.Elements[i - 1].StartingTrackPosition + 0.99999999 * TrackManager.CurrentTrack.Elements[i].StartingTrackPosition;
							TrackManager.UpdateTrackFollower(ref follower, p - 1.0, true, false);
							TrackManager.UpdateTrackFollower(ref follower, p, true, false);
							TrackManager.CurrentTrack.Elements[i].CurveRadius = r;
							//TrackManager.CurrentTrack.Elements[i].CurveCant = TrackManager.CurrentTrack.Elements[i].CurveCant;
							//TrackManager.CurrentTrack.Elements[i].CurveCantInterpolation = TrackManager.CurrentTrack.Elements[i].CurveCantInterpolation;
							TrackManager.CurrentTrack.Elements[i].WorldPosition = follower.WorldPosition;
							TrackManager.CurrentTrack.Elements[i].WorldDirection = follower.WorldDirection;
							TrackManager.CurrentTrack.Elements[i].WorldUp = follower.WorldUp;
							TrackManager.CurrentTrack.Elements[i].WorldSide = follower.WorldSide;
							// iterate to shorten track element length
							p = 0.00000001 * TrackManager.CurrentTrack.Elements[i].StartingTrackPosition + 0.99999999 * TrackManager.CurrentTrack.Elements[i + 1].StartingTrackPosition;
							TrackManager.UpdateTrackFollower(ref follower, p - 1.0, true, false);
							TrackManager.UpdateTrackFollower(ref follower, p, true, false);
							World.Vector3D d = World.Vector3D.Subtract(TrackManager.CurrentTrack.Elements[i + 1].WorldPosition, follower.WorldPosition);
							double bestT = d.X * d.X + d.Y * d.Y + d.Z * d.Z;
							int bestJ = 0;
							int n = 1000;
							double a = 1.0 / (double)n * (TrackManager.CurrentTrack.Elements[i + 1].StartingTrackPosition - TrackManager.CurrentTrack.Elements[i].StartingTrackPosition);
							for (int j = 1; j < n - 1; j++) {
								TrackManager.UpdateTrackFollower(ref follower, TrackManager.CurrentTrack.Elements[i + 1].StartingTrackPosition - (double)j * a, true, false);
								d = World.Vector3D.Subtract(TrackManager.CurrentTrack.Elements[i + 1].WorldPosition, follower.WorldPosition);
								double t = d.X * d.X + d.Y * d.Y + d.Z * d.Z;
								if (t < bestT) {
									bestT = t;
									bestJ = j;
								} else {
									break;
								}
							}
							double s = (double)bestJ * a;
							for (int j = i + 1; j < TrackManager.CurrentTrack.Elements.Length; j++) {
								TrackManager.CurrentTrack.Elements[j].StartingTrackPosition -= s;
							}
							totalShortage += s;
							// introduce turn to compensate for curve
							p = 0.00000001 * TrackManager.CurrentTrack.Elements[i].StartingTrackPosition + 0.99999999 * TrackManager.CurrentTrack.Elements[i + 1].StartingTrackPosition;
							TrackManager.UpdateTrackFollower(ref follower, p - 1.0, true, false);
							TrackManager.UpdateTrackFollower(ref follower, p, true, false);
							World.Vector3D AB = World.Vector3D.Subtract(TrackManager.CurrentTrack.Elements[i + 1].WorldPosition, follower.WorldPosition);
							World.Vector3D AC = World.Vector3D.Subtract(TrackManager.CurrentTrack.Elements[i + 1].WorldPosition, TrackManager.CurrentTrack.Elements[i].WorldPosition);
							World.Vector3D BC = World.Vector3D.Subtract(follower.WorldPosition, TrackManager.CurrentTrack.Elements[i].WorldPosition);
							double sa = Math.Sqrt(BC.X * BC.X + BC.Z * BC.Z);
							double sb = Math.Sqrt(AC.X * AC.X + AC.Z * AC.Z);
							double sc = Math.Sqrt(AB.X * AB.X + AB.Z * AB.Z);
							double denominator = 2.0 * sa * sb;
							if (denominator != 0.0) {
								double originalAngle;
								{
									double value = (sa * sa + sb * sb - sc * sc) / denominator;
									if (value < -1.0) {
										originalAngle = Math.PI;
									} else if (value > 1.0) {
										originalAngle = 0;
									} else {
										originalAngle = Math.Acos(value);
									}
								}
								TrackManager.TrackElement originalTrackElement = TrackManager.CurrentTrack.Elements[i];
								bestT = double.MaxValue;
								bestJ = 0;
								for (int j = -1; j <= 1; j++) {
									double g = (double)j * originalAngle;
									double cosg = Math.Cos(g);
									double sing = Math.Sin(g);
									TrackManager.CurrentTrack.Elements[i] = originalTrackElement;
									World.Rotate(ref TrackManager.CurrentTrack.Elements[i].WorldDirection.X, ref TrackManager.CurrentTrack.Elements[i].WorldDirection.Y, ref TrackManager.CurrentTrack.Elements[i].WorldDirection.Z, 0.0, 1.0, 0.0, cosg, sing);
									World.Rotate(ref TrackManager.CurrentTrack.Elements[i].WorldUp.X, ref TrackManager.CurrentTrack.Elements[i].WorldUp.Y, ref TrackManager.CurrentTrack.Elements[i].WorldUp.Z, 0.0, 1.0, 0.0, cosg, sing);
									World.Rotate(ref TrackManager.CurrentTrack.Elements[i].WorldSide.X, ref TrackManager.CurrentTrack.Elements[i].WorldSide.Y, ref TrackManager.CurrentTrack.Elements[i].WorldSide.Z, 0.0, 1.0, 0.0, cosg, sing);
									p = 0.00000001 * TrackManager.CurrentTrack.Elements[i].StartingTrackPosition + 0.99999999 * TrackManager.CurrentTrack.Elements[i + 1].StartingTrackPosition;
									TrackManager.UpdateTrackFollower(ref follower, p - 1.0, true, false);
									TrackManager.UpdateTrackFollower(ref follower, p, true, false);
									d = World.Vector3D.Subtract(TrackManager.CurrentTrack.Elements[i + 1].WorldPosition, follower.WorldPosition);
									double t = d.X * d.X + d.Y * d.Y + d.Z * d.Z;
									if (t < bestT) {
										bestT = t;
										bestJ = j;
									}
								}
								{
									double newAngle = (double)bestJ * originalAngle;
									double cosg = Math.Cos(newAngle);
									double sing = Math.Sin(newAngle);
									TrackManager.CurrentTrack.Elements[i] = originalTrackElement;
									World.Rotate(ref TrackManager.CurrentTrack.Elements[i].WorldDirection.X, ref TrackManager.CurrentTrack.Elements[i].WorldDirection.Y, ref TrackManager.CurrentTrack.Elements[i].WorldDirection.Z, 0.0, 1.0, 0.0, cosg, sing);
									World.Rotate(ref TrackManager.CurrentTrack.Elements[i].WorldUp.X, ref TrackManager.CurrentTrack.Elements[i].WorldUp.Y, ref TrackManager.CurrentTrack.Elements[i].WorldUp.Z, 0.0, 1.0, 0.0, cosg, sing);
									World.Rotate(ref TrackManager.CurrentTrack.Elements[i].WorldSide.X, ref TrackManager.CurrentTrack.Elements[i].WorldSide.Y, ref TrackManager.CurrentTrack.Elements[i].WorldSide.Z, 0.0, 1.0, 0.0, cosg, sing);
								}
								// iterate again to further shorten track element length
								p = 0.00000001 * TrackManager.CurrentTrack.Elements[i].StartingTrackPosition + 0.99999999 * TrackManager.CurrentTrack.Elements[i + 1].StartingTrackPosition;
								TrackManager.UpdateTrackFollower(ref follower, p - 1.0, true, false);
								TrackManager.UpdateTrackFollower(ref follower, p, true, false);
								d = World.Vector3D.Subtract(TrackManager.CurrentTrack.Elements[i + 1].WorldPosition, follower.WorldPosition);
								bestT = d.X * d.X + d.Y * d.Y + d.Z * d.Z;
								bestJ = 0;
								n = 1000;
								a = 1.0 / (double)n * (TrackManager.CurrentTrack.Elements[i + 1].StartingTrackPosition - TrackManager.CurrentTrack.Elements[i].StartingTrackPosition);
								for (int j = 1; j < n - 1; j++) {
									TrackManager.UpdateTrackFollower(ref follower, TrackManager.CurrentTrack.Elements[i + 1].StartingTrackPosition - (double)j * a, true, false);
									d = World.Vector3D.Subtract(TrackManager.CurrentTrack.Elements[i + 1].WorldPosition, follower.WorldPosition);
									double t = d.X * d.X + d.Y * d.Y + d.Z * d.Z;
									if (t < bestT) {
										bestT = t;
										bestJ = j;
									} else {
										break;
									}
								}
								s = (double)bestJ * a;
								for (int j = i + 1; j < TrackManager.CurrentTrack.Elements.Length; j++) {
									TrackManager.CurrentTrack.Elements[j].StartingTrackPosition -= s;
								}
								totalShortage += s;
							}
							// compensate for height difference
							p = 0.00000001 * TrackManager.CurrentTrack.Elements[i].StartingTrackPosition + 0.99999999 * TrackManager.CurrentTrack.Elements[i + 1].StartingTrackPosition;
							TrackManager.UpdateTrackFollower(ref follower, p - 1.0, true, false);
							TrackManager.UpdateTrackFollower(ref follower, p, true, false);
							World.Vector3D d1 = World.Vector3D.Subtract(TrackManager.CurrentTrack.Elements[i + 1].WorldPosition, TrackManager.CurrentTrack.Elements[i].WorldPosition);
							double a1 = Math.Atan(d1.Y / Math.Sqrt(d1.X * d1.X + d1.Z * d1.Z));
							World.Vector3D d2 = World.Vector3D.Subtract(follower.WorldPosition, TrackManager.CurrentTrack.Elements[i].WorldPosition);
							double a2 = Math.Atan(d2.Y / Math.Sqrt(d2.X * d2.X + d2.Z * d2.Z));
							double b = a2 - a1;
							if (b * b > 0.00000001) {
								double cosa = Math.Cos(b);
								double sina = Math.Sin(b);
								World.Rotate(ref TrackManager.CurrentTrack.Elements[i].WorldDirection.X, ref TrackManager.CurrentTrack.Elements[i].WorldDirection.Y, ref TrackManager.CurrentTrack.Elements[i].WorldDirection.Z, TrackManager.CurrentTrack.Elements[i].WorldSide.X, TrackManager.CurrentTrack.Elements[i].WorldSide.Y, TrackManager.CurrentTrack.Elements[i].WorldSide.Z, cosa, sina);
								World.Rotate(ref TrackManager.CurrentTrack.Elements[i].WorldUp.X, ref TrackManager.CurrentTrack.Elements[i].WorldUp.Y, ref TrackManager.CurrentTrack.Elements[i].WorldUp.Z, TrackManager.CurrentTrack.Elements[i].WorldSide.X, TrackManager.CurrentTrack.Elements[i].WorldSide.Y, TrackManager.CurrentTrack.Elements[i].WorldSide.Z, cosa, sina);
							}
						}
					}
				}
			}
			// correct events
			for (int i = 0; i < TrackManager.CurrentTrack.Elements.Length - 1; i++) {
				double startingTrackPosition = TrackManager.CurrentTrack.Elements[i].StartingTrackPosition;
				double endingTrackPosition = TrackManager.CurrentTrack.Elements[i + 1].StartingTrackPosition;
				for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++) {
					double p = startingTrackPosition + TrackManager.CurrentTrack.Elements[i].Events[j].TrackPositionDelta;
					if (p >= endingTrackPosition) {
						int len = TrackManager.CurrentTrack.Elements[i + 1].Events.Length;
						Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[i + 1].Events, len + 1);
						TrackManager.CurrentTrack.Elements[i + 1].Events[len] = TrackManager.CurrentTrack.Elements[i].Events[j];
						TrackManager.CurrentTrack.Elements[i + 1].Events[len].TrackPositionDelta += startingTrackPosition - endingTrackPosition;
						for (int k = j; k < TrackManager.CurrentTrack.Elements[i].Events.Length - 1; k++) {
							TrackManager.CurrentTrack.Elements[i].Events[k] = TrackManager.CurrentTrack.Elements[i].Events[k + 1];
						}
						len = TrackManager.CurrentTrack.Elements[i].Events.Length;
						Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[i].Events, len - 1);
						j--;
					}
				}
			}
		}
Example #22
0
 internal static void PlaySound(ref int SoundSourceIndex, int SoundBufferIndex, World.Vector3D Position, Importance Important, bool Looped)
 {
     PlaySound(ref SoundSourceIndex, true, SoundBufferIndex, null, -1, Position, Important, Looped, 1.0, 1.0);
 }
 // parse animated object config
 /// <summary>Loads a collection of animated objects from a file.</summary>
 /// <param name="FileName">The text file to load the animated object from. Must be an absolute file name.</param>
 /// <param name="Encoding">The encoding the file is saved in. If the file uses a byte order mark, the encoding indicated by the byte order mark is used and the Encoding parameter is ignored.</param>
 /// <param name="LoadMode">The texture load mode.</param>
 /// <returns>The collection of animated objects.</returns>
 internal static ObjectManager.AnimatedObjectCollection ReadObject(string FileName, System.Text.Encoding Encoding, ObjectManager.ObjectLoadMode LoadMode)
 {
     System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
     ObjectManager.AnimatedObjectCollection Result = new ObjectManager.AnimatedObjectCollection();
     Result.Objects = new ObjectManager.AnimatedObject[4];
     int ObjectCount = 0;
     // load file
     string[] Lines = System.IO.File.ReadAllLines(FileName, Encoding);
     bool rpnUsed = false;
     for (int i = 0; i < Lines.Length; i++) {
         int j = Lines[i].IndexOf(';');
         if (j >= 0) {
             Lines[i] = Lines[i].Substring(0, j).Trim();
         } else {
             Lines[i] = Lines[i].Trim();
         }
         if (Program.CurrentProgramType == Program.ProgramType.ObjectViewer | Program.CurrentProgramType == Program.ProgramType.RouteViewer) {
             if (Lines[i].IndexOf("functionrpn", StringComparison.OrdinalIgnoreCase) >= 0) {
                 rpnUsed = true;
             }
         }
     }
     if (rpnUsed) {
         Interface.AddMessage(Interface.MessageType.Warning, false, "An animated object file contains non-official RPN functions. Please get rid of them in file " + FileName);
     }
     for (int i = 0; i < Lines.Length; i++) {
         if (Lines[i].Length != 0) {
             switch (Lines[i].ToLowerInvariant()) {
                 case "[include]":
                     {
                         i++;
                         World.Vector3D position = new World.Vector3D(0.0, 0.0, 0.0);
                         ObjectManager.UnifiedObject[] obj = new OpenBve.ObjectManager.UnifiedObject[4];
                         int objCount = 0;
                         while (i < Lines.Length && !(Lines[i].StartsWith("[", StringComparison.Ordinal) & Lines[i].EndsWith("]", StringComparison.Ordinal))) {
                             if (Lines[i].Length != 0) {
                                 int j = Lines[i].IndexOf("=", StringComparison.Ordinal);
                                 if (j > 0) {
                                     string a = Lines[i].Substring(0, j).TrimEnd();
                                     string b = Lines[i].Substring(j + 1).TrimStart();
                                     switch (a.ToLowerInvariant()) {
                                         case "position":
                                             {
                                                 string[] s = b.Split(',');
                                                 if (s.Length == 3) {
                                                     double x, y, z;
                                                     if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else {
                                                         position = new World.Vector3D(x, y, z);
                                                     }
                                                 } else {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                 }
                                             } break;
                                         default:
                                             Interface.AddMessage(Interface.MessageType.Error, false, "The attribute " + a + " is not supported at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             break;
                                     }
                                 } else {
                                     string Folder = System.IO.Path.GetDirectoryName(FileName);
                                     if (Interface.ContainsInvalidPathChars(Lines[i])) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Lines[i] + " contains illegal characters at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                     } else {
                                         string file = Interface.GetCombinedFileName(Folder, Lines[i]);
                                         if (System.IO.File.Exists(file)) {
                                             if (obj.Length == objCount) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref obj, obj.Length << 1);
                                             }
                                             obj[objCount] = ObjectManager.LoadObject(file, Encoding, LoadMode, false, false, false);
                                             objCount++;
                                         } else {
                                             Interface.AddMessage(Interface.MessageType.Error, true, "File " + file + " not found at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                         }
                                     }
                                 }
                             }
                             i++;
                         }
                         i--;
                         for (int j = 0; j < objCount; j++) {
                             if (obj[j] != null) {
                                 if (obj[j] is ObjectManager.StaticObject) {
                                     ObjectManager.StaticObject s = (ObjectManager.StaticObject)obj[j];
                                     s.Dynamic = 1;
                                     if (ObjectCount >= Result.Objects.Length) {
                                         Array.Resize<ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length << 1);
                                     }
                                     ObjectManager.AnimatedObject a = new ObjectManager.AnimatedObject();
                                     ObjectManager.AnimatedObjectState aos = new ObjectManager.AnimatedObjectState();
                                     aos.Object = s;
                                     aos.Position = position;
                                     a.States = new ObjectManager.AnimatedObjectState[] { aos };
                                     Result.Objects[ObjectCount] = a;
                                     ObjectCount++;
                                 } else if (obj[j] is ObjectManager.AnimatedObjectCollection) {
                                     ObjectManager.AnimatedObjectCollection a = (ObjectManager.AnimatedObjectCollection)obj[j];
                                     for (int k = 0; k < a.Objects.Length; k++) {
                                         if (ObjectCount >= Result.Objects.Length) {
                                             Array.Resize<ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length << 1);
                                         }
                                         for (int h = 0; h < a.Objects[k].States.Length; h++) {
                                             a.Objects[k].States[h].Position.X += position.X;
                                             a.Objects[k].States[h].Position.Y += position.Y;
                                             a.Objects[k].States[h].Position.Z += position.Z;
                                         }
                                         Result.Objects[ObjectCount] = a.Objects[k];
                                         ObjectCount++;
                                     }
                                 }
                             }
                         }
                     }
                     break;
                 case "[object]":
                     {
                         i++;
                         if (Result.Objects.Length == ObjectCount) {
                             Array.Resize<ObjectManager.AnimatedObject>(ref Result.Objects, Result.Objects.Length << 1);
                         }
                         Result.Objects[ObjectCount] = new ObjectManager.AnimatedObject();
                         Result.Objects[ObjectCount].States = new ObjectManager.AnimatedObjectState[] { };
                         Result.Objects[ObjectCount].CurrentState = -1;
                         Result.Objects[ObjectCount].TranslateXDirection = new World.Vector3D(1.0, 0.0, 0.0);
                         Result.Objects[ObjectCount].TranslateYDirection = new World.Vector3D(0.0, 1.0, 0.0);
                         Result.Objects[ObjectCount].TranslateZDirection = new World.Vector3D(0.0, 0.0, 1.0);
                         Result.Objects[ObjectCount].RotateXDirection = new World.Vector3D(1.0, 0.0, 0.0);
                         Result.Objects[ObjectCount].RotateYDirection = new World.Vector3D(0.0, 1.0, 0.0);
                         Result.Objects[ObjectCount].RotateZDirection = new World.Vector3D(0.0, 0.0, 1.0);
                         Result.Objects[ObjectCount].TextureShiftXDirection = new World.Vector2D(1.0, 0.0);
                         Result.Objects[ObjectCount].TextureShiftYDirection = new World.Vector2D(0.0, 1.0);
                         Result.Objects[ObjectCount].RefreshRate = 0.0;
                         Result.Objects[ObjectCount].ObjectIndex = -1;
                         World.Vector3D Position = new World.Vector3D(0.0, 0.0, 0.0);
                         string[] StateFiles = null;
                         while (i < Lines.Length && !(Lines[i].StartsWith("[", StringComparison.Ordinal) & Lines[i].EndsWith("]", StringComparison.Ordinal))) {
                             if (Lines[i].Length != 0) {
                                 int j = Lines[i].IndexOf("=", StringComparison.Ordinal);
                                 if (j > 0) {
                                     string a = Lines[i].Substring(0, j).TrimEnd();
                                     string b = Lines[i].Substring(j + 1).TrimStart();
                                     switch (a.ToLowerInvariant()) {
                                         case "position":
                                             {
                                                 string[] s = b.Split(',');
                                                 if (s.Length == 3) {
                                                     double x, y, z;
                                                     if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else {
                                                         Position = new World.Vector3D(x, y, z);
                                                     }
                                                 } else {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                 }
                                             } break;
                                         case "states":
                                             {
                                                 string[] s = b.Split(',');
                                                 if (s.Length >= 1) {
                                                     string Folder = System.IO.Path.GetDirectoryName(FileName);
                                                     StateFiles = new string[s.Length];
                                                     for (int k = 0; k < s.Length; k++) {
                                                         s[k] = s[k].Trim();
                                                         if (Interface.ContainsInvalidPathChars(s[k])) {
                                                             Interface.AddMessage(Interface.MessageType.Error, false, "File" + k.ToString(Culture) + " contains illegal characters in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                             StateFiles[k] = null;
                                                         } else {
                                                             StateFiles[k] = Interface.GetCombinedFileName(Folder, s[k]);
                                                             if (!System.IO.File.Exists(StateFiles[k])) {
                                                                 Interface.AddMessage(Interface.MessageType.Error, true, "File " + StateFiles[k] + " not found in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                                 StateFiles[k] = null;
                                                             }
                                                         }
                                                     }
                                                 } else {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "At least one argument is expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     return null;
                                                 }
                                             } break;
                                         case "statefunction":
                                             try {
                                                 Result.Objects[ObjectCount].StateFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "statefunctionrpn":
                                             try {
                                                 Result.Objects[ObjectCount].StateFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "translatexdirection":
                                         case "translateydirection":
                                         case "translatezdirection":
                                             {
                                                 string[] s = b.Split(',');
                                                 if (s.Length == 3) {
                                                     double x, y, z;
                                                     if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else {
                                                         switch (a.ToLowerInvariant()) {
                                                             case "translatexdirection":
                                                                 Result.Objects[ObjectCount].TranslateXDirection = new World.Vector3D(x, y, z);
                                                                 break;
                                                             case "translateydirection":
                                                                 Result.Objects[ObjectCount].TranslateYDirection = new World.Vector3D(x, y, z);
                                                                 break;
                                                             case "translatezdirection":
                                                                 Result.Objects[ObjectCount].TranslateZDirection = new World.Vector3D(x, y, z);
                                                                 break;
                                                         }
                                                     }
                                                 } else {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                 }
                                             } break;
                                         case "translatexfunction":
                                             try {
                                                 Result.Objects[ObjectCount].TranslateXFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "translateyfunction":
                                             try {
                                                 Result.Objects[ObjectCount].TranslateYFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "translatezfunction":
                                             try {
                                                 Result.Objects[ObjectCount].TranslateZFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "translatexfunctionrpn":
                                             try {
                                                 Result.Objects[ObjectCount].TranslateXFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "translateyfunctionrpn":
                                             try {
                                                 Result.Objects[ObjectCount].TranslateYFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "translatezfunctionrpn":
                                             try {
                                                 Result.Objects[ObjectCount].TranslateZFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "rotatexdirection":
                                         case "rotateydirection":
                                         case "rotatezdirection":
                                             {
                                                 string[] s = b.Split(',');
                                                 if (s.Length == 3) {
                                                     double x, y, z;
                                                     if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (!double.TryParse(s[2], System.Globalization.NumberStyles.Float, Culture, out z)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "Z is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (x == 0.0 & y == 0.0 & z == 0.0) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "The direction indicated by X, Y and Z is expected to be non-zero in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else {
                                                         switch (a.ToLowerInvariant()) {
                                                             case "rotatexdirection":
                                                                 Result.Objects[ObjectCount].RotateXDirection = new World.Vector3D(x, y, z);
                                                                 break;
                                                             case "rotateydirection":
                                                                 Result.Objects[ObjectCount].RotateYDirection = new World.Vector3D(x, y, z);
                                                                 break;
                                                             case "rotatezdirection":
                                                                 Result.Objects[ObjectCount].RotateZDirection = new World.Vector3D(x, y, z);
                                                                 break;
                                                         }
                                                     }
                                                 } else {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 3 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                 }
                                             } break;
                                         case "rotatexfunction":
                                             try {
                                                 Result.Objects[ObjectCount].RotateXFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "rotateyfunction":
                                             try {
                                                 Result.Objects[ObjectCount].RotateYFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "rotatezfunction":
                                             try {
                                                 Result.Objects[ObjectCount].RotateZFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "rotatexfunctionrpn":
                                             try {
                                                 Result.Objects[ObjectCount].RotateXFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "rotateyfunctionrpn":
                                             try {
                                                 Result.Objects[ObjectCount].RotateYFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "rotatezfunctionrpn":
                                             try {
                                                 Result.Objects[ObjectCount].RotateZFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "rotatexdamping":
                                         case "rotateydamping":
                                         case "rotatezdamping":
                                             {
                                                 string[] s = b.Split(',');
                                                 if (s.Length == 2) {
                                                     double nf, dr;
                                                     if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out nf)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "NaturalFrequency is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out dr)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "DampingRatio is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (nf <= 0.0) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "NaturalFrequency is expected to be positive in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (dr <= 0.0) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "DampingRatio is expected to be positive in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else {
                                                         switch (a.ToLowerInvariant()) {
                                                             case "rotatexdamping":
                                                                 Result.Objects[ObjectCount].RotateXDamping = new ObjectManager.Damping(nf, dr);
                                                                 break;
                                                             case "rotateydamping":
                                                                 Result.Objects[ObjectCount].RotateYDamping = new ObjectManager.Damping(nf, dr);
                                                                 break;
                                                             case "rotatezdamping":
                                                                 Result.Objects[ObjectCount].RotateZDamping = new ObjectManager.Damping(nf, dr);
                                                                 break;
                                                         }
                                                     }
                                                 } else {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 2 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                 }
                                             } break;
                                         case "textureshiftxdirection":
                                         case "textureshiftydirection":
                                             {
                                                 string[] s = b.Split(',');
                                                 if (s.Length == 2) {
                                                     double x, y;
                                                     if (!double.TryParse(s[0], System.Globalization.NumberStyles.Float, Culture, out x)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else if (!double.TryParse(s[1], System.Globalization.NumberStyles.Float, Culture, out y)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                     } else {
                                                         switch (a.ToLowerInvariant()) {
                                                             case "textureshiftxdirection":
                                                                 Result.Objects[ObjectCount].TextureShiftXDirection = new World.Vector2D(x, y);
                                                                 break;
                                                             case "textureshiftydirection":
                                                                 Result.Objects[ObjectCount].TextureShiftYDirection = new World.Vector2D(x, y);
                                                                 break;
                                                         }
                                                     }
                                                 } else {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 2 arguments are expected in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                 }
                                             } break;
                                         case "textureshiftxfunction":
                                             try {
                                                 Result.Objects[ObjectCount].TextureShiftXFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "textureshiftyfunction":
                                             try {
                                                 Result.Objects[ObjectCount].TextureShiftYFunction = FunctionScripts.GetFunctionScriptFromInfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "textureshiftxfunctionrpn":
                                             try {
                                                 Result.Objects[ObjectCount].TextureShiftXFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "textureshiftyfunctionrpn":
                                             try {
                                                 Result.Objects[ObjectCount].TextureShiftYFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(b);
                                             } catch (Exception ex) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, ex.Message + " in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             } break;
                                         case "refreshrate":
                                             {
                                                 double r;
                                                 if (!double.TryParse(b, System.Globalization.NumberStyles.Float, Culture, out r)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is invalid in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                 } else if (r < 0.0) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is expected to be non-negative in " + a + " at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                                 } else {
                                                     Result.Objects[ObjectCount].RefreshRate = r;
                                                 }
                                             } break;
                                         default:
                                             Interface.AddMessage(Interface.MessageType.Error, false, "The attribute " + a + " is not supported at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                             break;
                                     }
                                 } else {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                                     return null;
                                 }
                             }
                             i++;
                         }
                         i--;
                         if (StateFiles != null) {
                             Result.Objects[ObjectCount].States = new ObjectManager.AnimatedObjectState[StateFiles.Length];
                             bool ForceTextureRepeatX = Result.Objects[ObjectCount].TextureShiftXFunction != null & Result.Objects[ObjectCount].TextureShiftXDirection.X != 0.0 |
                                 Result.Objects[ObjectCount].TextureShiftYFunction != null & Result.Objects[ObjectCount].TextureShiftYDirection.Y != 0.0;
                             bool ForceTextureRepeatY = Result.Objects[ObjectCount].TextureShiftXFunction != null & Result.Objects[ObjectCount].TextureShiftXDirection.X != 0.0 |
                                 Result.Objects[ObjectCount].TextureShiftYFunction != null & Result.Objects[ObjectCount].TextureShiftYDirection.Y != 0.0;
                             for (int k = 0; k < StateFiles.Length; k++) {
                                 Result.Objects[ObjectCount].States[k].Position = new World.Vector3D(0.0, 0.0, 0.0);
                                 if (StateFiles[k] != null) {
                                     Result.Objects[ObjectCount].States[k].Object = ObjectManager.LoadStaticObject(StateFiles[k], Encoding, LoadMode, false, ForceTextureRepeatX, ForceTextureRepeatY);
                                     Result.Objects[ObjectCount].States[k].Object.Dynamic = 1;
                                 } else {
                                     Result.Objects[ObjectCount].States[k].Object = null;
                                 }
                                 for (int j = 0; j < Result.Objects[ObjectCount].States.Length; j++) {
                                     Result.Objects[ObjectCount].States[j].Position = Position;
                                 }
                             }
                         } else {
                             Result.Objects[ObjectCount].States = new ObjectManager.AnimatedObjectState[] { };
                         }
                         ObjectCount++;
                     }
                     break;
                 default:
                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid statement " + Lines[i] + " encountered at line " + (i + 1).ToString(Culture) + " in file " + FileName);
                     return null;
             }
         }
     }
     Array.Resize<ObjectManager.AnimatedObject>(ref Result.Objects, ObjectCount);
     return Result;
 }
Example #24
0
        internal static void PlaySound(int SoundBufferIndex, World.Vector3D Position, Importance Important, bool Looped)
        {
            int a = -1;

            PlaySound(ref a, false, SoundBufferIndex, null, -1, Position, Important, Looped, 1.0, 1.0);
        }
Example #25
0
        internal static void PlaySound(int SoundBufferIndex, TrainManager.Train Train, int CarIndex, World.Vector3D Position, Importance Important, bool Looped)
        {
            int a = -1;

            PlaySound(ref a, false, SoundBufferIndex, Train, CarIndex, Position, Important, Looped, 1.0, 1.0);
        }
Example #26
0
	    internal static void MouseEvent(object sender, MouseButtonEventArgs e)
	    {
            MouseCameraPosition = World.AbsoluteCameraPosition;
            MouseCameraDirection = World.AbsoluteCameraDirection;
            MouseCameraUp = World.AbsoluteCameraUp;
            MouseCameraSide = World.AbsoluteCameraSide;
	        if (e.Button == OpenTK.Input.MouseButton.Left)
	        {
	            MouseButton = e.Mouse.LeftButton == ButtonState.Pressed ? 1 : 0;
	        }
	        if (e.Button == OpenTK.Input.MouseButton.Right)
	        {
	            MouseButton = e.Mouse.RightButton == ButtonState.Pressed ? 2 : 0;
	        }
	        if (e.Button == OpenTK.Input.MouseButton.Middle)
	        {
                MouseButton = e.Mouse.RightButton == ButtonState.Pressed ? 3 : 0;
	        }
            previousMouseState = Mouse.GetState();
	    }