static private Rotate ( Vector2 &Vector, double cosa, double sina ) : void | ||
Vector | Vector2 | The vector to rotate |
cosa | double | The Cosine of the angle to rotate by |
sina | double | The Sine of the angle to rotate by |
Результат | void |
internal static void MouseMovement() { if (MouseButton == 0) { return; } currentMouseState = Mouse.GetState(); if (currentMouseState != previousMouseState) { if (MouseButton == 1) { World.AbsoluteCameraDirection = MouseCameraDirection; World.AbsoluteCameraUp = MouseCameraUp; World.AbsoluteCameraSide = MouseCameraSide; { double dx = 0.0025 * (double)(previousMouseState.X - currentMouseState.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)(previousMouseState.Y - currentMouseState.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 == 2) { World.AbsoluteCameraPosition = MouseCameraPosition; double dx = -0.025 * (double)(currentMouseState.X - previousMouseState.X); 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)(currentMouseState.Y - previousMouseState.Y); World.AbsoluteCameraPosition.X += dy * World.AbsoluteCameraUp.X; World.AbsoluteCameraPosition.Y += dy * World.AbsoluteCameraUp.Y; World.AbsoluteCameraPosition.Z += dy * World.AbsoluteCameraUp.Z; ReducedMode = false; } else { World.AbsoluteCameraPosition = MouseCameraPosition; double dx = -0.025 * (double)(currentMouseState.X - previousMouseState.X); 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)(currentMouseState.Y - previousMouseState.Y); World.AbsoluteCameraPosition.X += dz * World.AbsoluteCameraDirection.X; World.AbsoluteCameraPosition.Y += dz * World.AbsoluteCameraDirection.Y; World.AbsoluteCameraPosition.Z += dz * World.AbsoluteCameraDirection.Z; ReducedMode = false; } } }
/// <summary>Updates the position and rotation of an animated object which follows a track</summary> private void UpdateObjectPosition() { //Get vectors double dx, dy, dz; double ux, uy, uz; double sx, sy, sz; { dx = FrontAxleFollower.WorldPosition.X - RearAxleFollower.WorldPosition.X; dy = FrontAxleFollower.WorldPosition.Y - RearAxleFollower.WorldPosition.Y; dz = FrontAxleFollower.WorldPosition.Z - RearAxleFollower.WorldPosition.Z; double t = 1.0 / Math.Sqrt(dx * dx + dy * dy + dz * dz); dx *= t; dy *= t; dz *= t; t = 1.0 / Math.Sqrt(dx * dx + dz * dz); double ex = dx * t; double ez = dz * t; sx = ez; sy = 0.0; sz = -ex; World.Cross(dx, dy, dz, sx, sy, sz, out ux, out uy, out uz); } // apply position due to cant/toppling { double a = CurrentRollDueToTopplingAngle + CurrentRollDueToCantAngle; double x = Math.Sign(a) * 0.5 * Game.RouteRailGauge * (1.0 - Math.Cos(a)); double y = Math.Abs(0.5 * Game.RouteRailGauge * Math.Sin(a)); double cx = sx * x + ux * y; double cy = sy * x + uy * y; double cz = sz * x + uz * y; FrontAxleFollower.WorldPosition.X += cx; FrontAxleFollower.WorldPosition.Y += cy; FrontAxleFollower.WorldPosition.Z += cz; RearAxleFollower.WorldPosition.X += cx; RearAxleFollower.WorldPosition.Y += cy; RearAxleFollower.WorldPosition.Z += cz; } // apply rolling { double a = CurrentRollDueToTopplingAngle - CurrentRollDueToCantAngle; double cosa = Math.Cos(a); double sina = Math.Sin(a); World.Rotate(ref sx, ref sy, ref sz, dx, dy, dz, cosa, sina); World.Rotate(ref ux, ref uy, ref uz, dx, dy, dz, cosa, sina); Up.X = ux; Up.Y = uy; Up.Z = uz; } Direction.X = dx; Direction.Y = dy; Direction.Z = dz; Side.X = sx; Side.Y = sy; Side.Z = sz; }
private static void ApplyRotation(MeshBuilder Builder, double x, double y, double z, double a) { double cosa = Math.Cos(a); double sina = Math.Sin(a); for (int i = 0; i < Builder.Vertices.Length; i++) { World.Rotate(ref Builder.Vertices[i].Coordinates.X, ref Builder.Vertices[i].Coordinates.Y, ref Builder.Vertices[i].Coordinates.Z, x, y, z, cosa, sina); } for (int i = 0; i < Builder.Faces.Length; i++) { for (int j = 0; j < Builder.Faces[i].Vertices.Length; j++) { World.Rotate(ref Builder.Faces[i].Vertices[j].Normal.X, ref Builder.Faces[i].Vertices[j].Normal.Y, ref Builder.Faces[i].Vertices[j].Normal.Z, x, y, z, cosa, sina); } } }
internal void ApplyRotation(double x, double y, double z, double a) { double cosa = Math.Cos(a); double sina = Math.Sin(a); for (int j = 0; j < Mesh.Vertices.Length; j++) { World.Rotate(ref Mesh.Vertices[j].Coordinates, x, y, z, cosa, sina); } for (int j = 0; j < Mesh.Faces.Length; j++) { for (int k = 0; k < Mesh.Faces[j].Vertices.Length; k++) { World.Rotate(ref Mesh.Faces[j].Vertices[k].Normal, x, y, z, cosa, sina); } } }
// 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); }
internal void ApplyData(StaticObject Prototype, Vector3 Position, World.Transformation BaseTransformation, World.Transformation AuxTransformation, bool AccurateObjectDisposal, double AccurateObjectDisposalZOffset, double startingDistance, double endingDistance, double BlockLength, double TrackPosition, double Brightness, bool DuplicateMaterials) { StartingDistance = float.MaxValue; EndingDistance = float.MinValue; Mesh.Vertices = new World.Vertex[Prototype.Mesh.Vertices.Length]; // vertices for (int j = 0; j < Prototype.Mesh.Vertices.Length; j++) { Mesh.Vertices[j] = Prototype.Mesh.Vertices[j]; if (AccurateObjectDisposal) { World.Rotate(ref Mesh.Vertices[j].Coordinates.X, ref Mesh.Vertices[j].Coordinates.Y, ref Mesh.Vertices[j].Coordinates.Z, AuxTransformation); if (Mesh.Vertices[j].Coordinates.Z < StartingDistance) { StartingDistance = (float)Mesh.Vertices[j].Coordinates.Z; } if (Mesh.Vertices[j].Coordinates.Z > EndingDistance) { EndingDistance = (float)Mesh.Vertices[j].Coordinates.Z; } Mesh.Vertices[j].Coordinates = Prototype.Mesh.Vertices[j].Coordinates; } World.Rotate(ref Mesh.Vertices[j].Coordinates.X, ref Mesh.Vertices[j].Coordinates.Y, ref Mesh.Vertices[j].Coordinates.Z, AuxTransformation); World.Rotate(ref Mesh.Vertices[j].Coordinates.X, ref Mesh.Vertices[j].Coordinates.Y, ref Mesh.Vertices[j].Coordinates.Z, BaseTransformation); Mesh.Vertices[j].Coordinates.X += Position.X; Mesh.Vertices[j].Coordinates.Y += Position.Y; Mesh.Vertices[j].Coordinates.Z += Position.Z; } if (AccurateObjectDisposal) { StartingDistance += (float)AccurateObjectDisposalZOffset; EndingDistance += (float)AccurateObjectDisposalZOffset; } // faces Mesh.Faces = new World.MeshFace[Prototype.Mesh.Faces.Length]; for (int j = 0; j < Prototype.Mesh.Faces.Length; j++) { Mesh.Faces[j].Flags = Prototype.Mesh.Faces[j].Flags; Mesh.Faces[j].Material = Prototype.Mesh.Faces[j].Material; Mesh.Faces[j].Vertices = new World.MeshFaceVertex[Prototype.Mesh.Faces[j].Vertices.Length]; for (int k = 0; k < Prototype.Mesh.Faces[j].Vertices.Length; k++) { Mesh.Faces[j].Vertices[k] = Prototype.Mesh.Faces[j].Vertices[k]; double nx = Mesh.Faces[j].Vertices[k].Normal.X; double ny = Mesh.Faces[j].Vertices[k].Normal.Y; double nz = Mesh.Faces[j].Vertices[k].Normal.Z; if (nx * nx + ny * ny + nz * nz != 0.0) { World.Rotate(ref Mesh.Faces[j].Vertices[k].Normal.X, ref Mesh.Faces[j].Vertices[k].Normal.Y, ref Mesh.Faces[j].Vertices[k].Normal.Z, AuxTransformation); World.Rotate(ref Mesh.Faces[j].Vertices[k].Normal.X, ref Mesh.Faces[j].Vertices[k].Normal.Y, ref Mesh.Faces[j].Vertices[k].Normal.Z, BaseTransformation); } } } // materials Mesh.Materials = new World.MeshMaterial[Prototype.Mesh.Materials.Length]; for (int j = 0; j < Prototype.Mesh.Materials.Length; j++) { Mesh.Materials[j] = Prototype.Mesh.Materials[j]; Mesh.Materials[j].Color.R = (byte)Math.Round((double)Prototype.Mesh.Materials[j].Color.R * Brightness); Mesh.Materials[j].Color.G = (byte)Math.Round((double)Prototype.Mesh.Materials[j].Color.G * Brightness); Mesh.Materials[j].Color.B = (byte)Math.Round((double)Prototype.Mesh.Materials[j].Color.B * Brightness); } const double minBlockLength = 20.0; if (BlockLength < minBlockLength) { BlockLength = BlockLength * Math.Ceiling(minBlockLength / BlockLength); } if (AccurateObjectDisposal) { StartingDistance += (float)TrackPosition; EndingDistance += (float)TrackPosition; double z = BlockLength * Math.Floor(TrackPosition / BlockLength); startingDistance = Math.Min(z - BlockLength, (double)StartingDistance); endingDistance = Math.Max(z + 2.0 * BlockLength, (double)EndingDistance); StartingDistance = (float)(BlockLength * Math.Floor(startingDistance / BlockLength)); EndingDistance = (float)(BlockLength * Math.Ceiling(endingDistance / BlockLength)); } else { StartingDistance = (float)startingDistance; EndingDistance = (float)endingDistance; } if (BlockLength != 0.0) { checked { GroupIndex = (short)Mod(Math.Floor(StartingDistance / BlockLength), Math.Ceiling(Interface.CurrentOptions.ViewingDistance / BlockLength)); } } }
/// <summary>Call this method to update a single track follower</summary> /// <param name="NewTrackPosition">The new track position of the follower</param> /// <param name="UpdateWorldCoordinates">Whether to update the world co-ordinates</param> /// <param name="AddTrackInaccurary">Whether to add track innacuracy</param> internal void Update(double NewTrackPosition, bool UpdateWorldCoordinates, bool AddTrackInaccurary) { if (CurrentTrack.Elements.Length == 0) { return; } int i = LastTrackElement; while (i >= 0 && NewTrackPosition < CurrentTrack.Elements[i].StartingTrackPosition) { double ta = TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition; double tb = -0.01; CheckEvents(i, -1, ta, tb); i--; } if (i >= 0) { while (i < CurrentTrack.Elements.Length - 1) { if (NewTrackPosition < CurrentTrack.Elements[i + 1].StartingTrackPosition) { break; } double ta = TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition; double tb = CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition + 0.01; CheckEvents(i, 1, ta, tb); i++; } } else { i = 0; } double da = 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; Vector3 D = new Vector3(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, 0.0, 1.0, 0.0, cosa, sina); WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + c * D.X; WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + h; WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + c * D.Z; World.Rotate(ref D, 0.0, 1.0, 0.0, cosa, sina); WorldDirection.X = D.X; WorldDirection.Y = p; WorldDirection.Z = D.Z; World.Normalize(ref WorldDirection.X, ref WorldDirection.Y, ref WorldDirection.Z); double cos2a = Math.Cos(2.0 * a); double sin2a = Math.Sin(2.0 * a); WorldSide = CurrentTrack.Elements[i].WorldSide; World.Rotate(ref WorldSide, 0.0, 1.0, 0.0, cos2a, sin2a); World.Cross(WorldDirection, WorldSide, out WorldUp); } else { // straight WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + db * CurrentTrack.Elements[i].WorldDirection.X; WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + db * CurrentTrack.Elements[i].WorldDirection.Y; WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + db * CurrentTrack.Elements[i].WorldDirection.Z; WorldDirection = CurrentTrack.Elements[i].WorldDirection; WorldUp = CurrentTrack.Elements[i].WorldUp; WorldSide = CurrentTrack.Elements[i].WorldSide; 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; 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; CurveRadius = CurrentTrack.Elements[i].CurveRadius; } else { CurveCant = CurrentTrack.Elements[i].CurveCant; } } else { WorldPosition = CurrentTrack.Elements[i].WorldPosition; WorldDirection = CurrentTrack.Elements[i].WorldDirection; WorldUp = CurrentTrack.Elements[i].WorldUp; WorldSide = CurrentTrack.Elements[i].WorldSide; CurveRadius = CurrentTrack.Elements[i].CurveRadius; CurveCant = CurrentTrack.Elements[i].CurveCant; } } else { if (db != 0.0) { if (CurrentTrack.Elements[i].CurveRadius != 0.0) { CurveRadius = CurrentTrack.Elements[i].CurveRadius; } else { 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; 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 { CurveCant = CurrentTrack.Elements[i].CurveCant; } } else { CurveRadius = CurrentTrack.Elements[i].CurveRadius; CurveCant = CurrentTrack.Elements[i].CurveCant; } } AdhesionMultiplier = CurrentTrack.Elements[i].AdhesionMultiplier; //Pitch added for Plugin Data usage //Mutliply this by 1000 to get the original value Pitch = CurrentTrack.Elements[i].Pitch * 1000; // 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); } WorldPosition.X += x * WorldSide.X + y * WorldUp.X; WorldPosition.Y += x * WorldSide.Y + y * WorldUp.Y; WorldPosition.Z += x * WorldSide.Z + y * WorldUp.Z; CurveCant += c; CantDueToInaccuracy = c; } else { CantDueToInaccuracy = 0.0; } // events CheckEvents(i, Math.Sign(db - da), da, db); //Update the odometer if (TrackPosition != NewTrackPosition) { //HACK: Reset the odometer if we've moved more than 10m this frame if (Math.Abs(NewTrackPosition - TrackPosition) > 10) { Odometer = 0; } else { Odometer += NewTrackPosition - TrackPosition; } } // finish TrackPosition = NewTrackPosition; LastTrackElement = i; }
protected override void OnRenderFrame(FrameEventArgs e) { Program.MouseMovement(); double timeElapsed = CPreciseTimer.GetElapsedTime(); DateTime time = DateTime.Now; Game.SecondsSinceMidnight = (double)(3600 * time.Hour + 60 * time.Minute + time.Second) + 0.001 * (double)time.Millisecond; ObjectManager.UpdateAnimatedWorldObjects(timeElapsed, false); if (Program.ReducedMode) { System.Threading.Thread.Sleep(125); } else { System.Threading.Thread.Sleep(1); } bool updatelight = false; bool keep = false; // rotate x if (Program.RotateX == 0) { double d = (1.0 + Math.Abs(RotateXSpeed)) * timeElapsed; if (RotateXSpeed >= -d & RotateXSpeed <= d) { RotateXSpeed = 0.0; } else { RotateXSpeed -= (double)Math.Sign(RotateXSpeed) * d; } } else { double d = (1.0 + 1.0 - 1.0 / (1.0 + RotateXSpeed * RotateXSpeed)) * timeElapsed; double m = 1.0; RotateXSpeed += (double)Program.RotateX * d; if (RotateXSpeed < -m) { RotateXSpeed = -m; } else if (RotateXSpeed > m) { RotateXSpeed = m; } } if (RotateXSpeed != 0.0) { double cosa = Math.Cos(RotateXSpeed * timeElapsed); double sina = Math.Sin(RotateXSpeed * timeElapsed); 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); keep = true; } // rotate y if (Program.RotateY == 0) { double d = (1.0 + Math.Abs(RotateYSpeed)) * timeElapsed; if (RotateYSpeed >= -d & RotateYSpeed <= d) { RotateYSpeed = 0.0; } else { RotateYSpeed -= (double)Math.Sign(RotateYSpeed) * d; } } else { double d = (1.0 + 1.0 - 1.0 / (1.0 + RotateYSpeed * RotateYSpeed)) * timeElapsed; double m = 1.0; RotateYSpeed += (double)Program.RotateY * d; if (RotateYSpeed < -m) { RotateYSpeed = -m; } else if (RotateYSpeed > m) { RotateYSpeed = m; } } if (RotateYSpeed != 0.0) { double cosa = Math.Cos(RotateYSpeed * timeElapsed); double sina = Math.Sin(RotateYSpeed * timeElapsed); 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); keep = true; } // move x if (Program.MoveX == 0) { double d = (2.5 + Math.Abs(MoveXSpeed)) * timeElapsed; if (MoveXSpeed >= -d & MoveXSpeed <= d) { MoveXSpeed = 0.0; } else { MoveXSpeed -= (double)Math.Sign(MoveXSpeed) * d; } } else { double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveXSpeed * MoveXSpeed)) * timeElapsed; double m = 25.0; MoveXSpeed += (double)Program.MoveX * d; if (MoveXSpeed < -m) { MoveXSpeed = -m; } else if (MoveXSpeed > m) { MoveXSpeed = m; } } if (MoveXSpeed != 0.0) { World.AbsoluteCameraPosition.X += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.X; World.AbsoluteCameraPosition.Y += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.Y; World.AbsoluteCameraPosition.Z += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.Z; keep = true; } // move y if (Program.MoveY == 0) { double d = (2.5 + Math.Abs(MoveYSpeed)) * timeElapsed; if (MoveYSpeed >= -d & MoveYSpeed <= d) { MoveYSpeed = 0.0; } else { MoveYSpeed -= (double)Math.Sign(MoveYSpeed) * d; } } else { double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveYSpeed * MoveYSpeed)) * timeElapsed; double m = 25.0; MoveYSpeed += (double)Program.MoveY * d; if (MoveYSpeed < -m) { MoveYSpeed = -m; } else if (MoveYSpeed > m) { MoveYSpeed = m; } } if (MoveYSpeed != 0.0) { World.AbsoluteCameraPosition.X += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.X; World.AbsoluteCameraPosition.Y += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.Y; World.AbsoluteCameraPosition.Z += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.Z; keep = true; } // move z if (Program.MoveZ == 0) { double d = (2.5 + Math.Abs(MoveZSpeed)) * timeElapsed; if (MoveZSpeed >= -d & MoveZSpeed <= d) { MoveZSpeed = 0.0; } else { MoveZSpeed -= (double)Math.Sign(MoveZSpeed) * d; } } else { double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveZSpeed * MoveZSpeed)) * timeElapsed; double m = 25.0; MoveZSpeed += (double)Program.MoveZ * d; if (MoveZSpeed < -m) { MoveZSpeed = -m; } else if (MoveZSpeed > m) { MoveZSpeed = m; } } if (MoveZSpeed != 0.0) { World.AbsoluteCameraPosition.X += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.X; World.AbsoluteCameraPosition.Y += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.Y; World.AbsoluteCameraPosition.Z += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.Z; keep = true; } // lighting if (Program.LightingRelative == -1) { Program.LightingRelative = (double)Program.LightingTarget; updatelight = true; } if (Program.LightingTarget == 0) { if (Program.LightingRelative != 0.0) { Program.LightingRelative -= 0.5 * timeElapsed; if (Program.LightingRelative < 0.0) { Program.LightingRelative = 0.0; } updatelight = true; keep = true; } } else { if (Program.LightingRelative != 1.0) { Program.LightingRelative += 0.5 * timeElapsed; if (Program.LightingRelative > 1.0) { Program.LightingRelative = 1.0; } updatelight = true; keep = true; } } // continue if (Program.ReducedMode) { ReducedModeEnteringTime = 3.0; } else { if (keep) { ReducedModeEnteringTime = 3.0; } else if (ReducedModeEnteringTime <= 0) { Program.ReducedMode = true; World.AbsoluteCameraSide.Y = 0.0; World.Normalize(ref World.AbsoluteCameraSide.X, ref World.AbsoluteCameraSide.Y, ref World.AbsoluteCameraSide.Z); World.Normalize(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z); World.AbsoluteCameraUp = Vector3.Cross(World.AbsoluteCameraDirection, World.AbsoluteCameraSide); } else { ReducedModeEnteringTime -= timeElapsed; } } if (updatelight) { Renderer.OptionAmbientColor.R = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative * (2.0 - Program.LightingRelative)); Renderer.OptionAmbientColor.G = (byte)Math.Round(32.0 + 128.0 * 0.5 * (Program.LightingRelative + Program.LightingRelative * (2.0 - Program.LightingRelative))); Renderer.OptionAmbientColor.B = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative); Renderer.OptionDiffuseColor.R = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative); Renderer.OptionDiffuseColor.G = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative); Renderer.OptionDiffuseColor.B = (byte)Math.Round(32.0 + 128.0 * Math.Sqrt(Program.LightingRelative)); Renderer.InitializeLighting(); } Renderer.RenderScene(); SwapBuffers(); }
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; Vector3 D = new Vector3(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); Follower.WorldUp = Vector3.Cross(Follower.WorldDirection, Follower.WorldSide); 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 Main(string[] args) { // platform and mono int p = (int)Environment.OSVersion.Platform; if (p == 4 | p == 128) { // general Unix CurrentPlatform = Platform.Linux; } else if (p == 6) { // Mac CurrentPlatform = Platform.Mac; } else { // non-Unix CurrentPlatform = Platform.Windows; } CurrentlyRunOnMono = Type.GetType("Mono.Runtime") != null; // file system FileSystem = FileSystem.FromCommandLineArgs(args); FileSystem.CreateFileSystem(); SetPackageLookupDirectories(); // command line arguments bool[] SkipArgs = new bool[args.Length]; if (args.Length != 0) { string File = System.IO.Path.Combine(Application.StartupPath, "RouteViewer.exe"); if (System.IO.File.Exists(File)) { int Skips = 0; System.Text.StringBuilder NewArgs = new System.Text.StringBuilder(); for (int i = 0; i < args.Length; i++) { if (System.IO.File.Exists(args[i])) { if (System.IO.Path.GetExtension(args[i]).Equals(".csv", StringComparison.OrdinalIgnoreCase)) { string Text = System.IO.File.ReadAllText(args[i], System.Text.Encoding.UTF8); if (Text.Length != -1 && Text.IndexOf("CreateMeshBuilder", StringComparison.OrdinalIgnoreCase) == -1) { if (NewArgs.Length != 0) { NewArgs.Append(" "); } NewArgs.Append("\"" + args[i] + "\""); SkipArgs[i] = true; Skips++; } } } else { SkipArgs[i] = true; Skips++; } } if (NewArgs.Length != 0) { System.Diagnostics.Process.Start(File, NewArgs.ToString()); } if (Skips == args.Length) { return; } } } // application Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); if (SDL.SDL_Init(SDL.SDL_INIT_VIDEO) != 0) { MessageBox.Show("SDL failed to initialize the video subsystem.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand); return; } Interface.CurrentOptions.ObjectOptimizationBasicThreshold = 1000; Interface.CurrentOptions.ObjectOptimizationFullThreshold = 250; // initialize sdl window SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1); SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DEPTH_SIZE, 16); SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_RED_SIZE, 8); SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_GREEN_SIZE, 8); SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_BLUE_SIZE, 8); SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_ALPHA_SIZE, 8); SDL.SDL_ShowCursor(1); // initialize camera ResetCamera(); // create window Renderer.ScreenWidth = 960; Renderer.ScreenHeight = 600; // int Bits = 32; //Sdl.SDL_SetVideoMode(Renderer.ScreenWidth, Renderer.ScreenHeight, Bits, Sdl.SDL_OPENGL | Sdl.SDL_DOUBLEBUF); SDLWindow = SDL.SDL_CreateWindow(Application.ProductName, SDL.SDL_WINDOWPOS_UNDEFINED, SDL.SDL_WINDOWPOS_UNDEFINED, Renderer.ScreenWidth, Renderer.ScreenHeight, SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL.SDL_WindowFlags.SDL_WINDOW_RESIZABLE); if (SDLWindow != IntPtr.Zero) { // create window string File = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder(), "icon.png"); if (System.IO.File.Exists(File)) { // set up icon iconBmp = new Bitmap(File); // load file iconData = iconBmp.LockBits(new Rectangle(0, 0, iconBmp.Width, iconBmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); // lock data iconSurface = SDL.SDL_CreateRGBSurfaceFrom(iconData.Scan0, iconBmp.Width, iconBmp.Height, 32, iconData.Stride, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000); // upload to sdl SDL.SDL_SetWindowIcon(SDLWindow, iconSurface); // use icon // free is on the end of the program /* * IntPtr bitmap = SDL.SDL_LoadBMP(File); * if (bitmap != IntPtr.Zero) { * SDL.SDL_Surface Surface = (SDL.SDL_Surface)System.Runtime.InteropServices.Marshal.PtrToStructure(bitmap, typeof(SDL.SDL_Surface)); * uint ColorKey = SDL.SDL_MapRGB(Surface.format, 0, 0, 255); * SDL.SDL_SetColorKey(bitmap, 1, ColorKey); * SDL.SDL_SetWindowIcon(SDLWindow,bitmap); * } */ } GLContext = SDL.SDL_GL_CreateContext(SDLWindow); tkContext = new GraphicsContext(new ContextHandle(GLContext), SDL.SDL_GL_GetProcAddress, () => new ContextHandle(SDL.SDL_GL_GetCurrentContext())); // anisotropic filtering string[] extensions = GL.GetString(StringName.Extensions).Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries); Interface.CurrentOptions.AnisotropicFilteringMaximum = 0; for (int i = 0; i < extensions.Length; i++) { if (extensions[i] == "GL_EXT_texture_filter_anisotropic") { float n; GL.GetFloat((GetPName)ExtTextureFilterAnisotropic.MaxTextureMaxAnisotropyExt, out n); Interface.CurrentOptions.AnisotropicFilteringMaximum = (int)Math.Round((double)n); break; } } if (Interface.CurrentOptions.AnisotropicFilteringMaximum <= 0) { Interface.CurrentOptions.AnisotropicFilteringMaximum = 0; Interface.CurrentOptions.AnisotropicFilteringLevel = 0; Interface.CurrentOptions.Interpolation = TextureManager.InterpolationMode.AnisotropicFiltering; } else { Interface.CurrentOptions.AnisotropicFilteringLevel = Interface.CurrentOptions.AnisotropicFilteringMaximum; Interface.CurrentOptions.Interpolation = TextureManager.InterpolationMode.TrilinearMipmapped; } // module initialization Renderer.Initialize(); Renderer.InitializeLighting(); SDL.SDL_GL_SwapWindow(SDLWindow); Fonts.Initialize(); UpdateViewport(); // command line arguments for (int i = 0; i < args.Length; i++) { if (!SkipArgs[i] && System.IO.File.Exists(args[i])) { try { ObjectManager.UnifiedObject o = ObjectManager.LoadObject(args[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); } catch (Exception ex) { Interface.AddMessage(Interface.MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + args[i] + "."); } Array.Resize <string>(ref Files, Files.Length + 1); Files[Files.Length - 1] = args[i]; } } ObjectManager.InitializeVisibility(); ObjectManager.FinishCreatingObjects(); ObjectManager.UpdateVisibility(0.0, true); ObjectManager.UpdateAnimatedWorldObjects(0.01, true); UpdateCaption(); Stopwatch timer = new Stopwatch(); timer.Start(); LastTicks = timer.ElapsedMilliseconds; // loop while (!Quit) { long ticks = timer.ElapsedMilliseconds; double timeElapsed = 0.001 * (double)(ticks - LastTicks); if (timeElapsed < 0.0001) { timeElapsed = 0.0001; } LastTicks = ticks; DateTime time = DateTime.Now; Game.SecondsSinceMidnight = (double)(3600 * time.Hour + 60 * time.Minute + time.Second) + 0.001 * (double)time.Millisecond; ObjectManager.UpdateAnimatedWorldObjects(timeElapsed, false); ProcessEvents(); if (ReducedMode) { System.Threading.Thread.Sleep(125); } else { System.Threading.Thread.Sleep(1); } bool updatelight = false; bool keep = false; // rotate x if (RotateX == 0) { double d = (1.0 + Math.Abs(RotateXSpeed)) * timeElapsed; if (RotateXSpeed >= -d & RotateXSpeed <= d) { RotateXSpeed = 0.0; } else { RotateXSpeed -= (double)Math.Sign(RotateXSpeed) * d; } } else { double d = (1.0 + 1.0 - 1.0 / (1.0 + RotateXSpeed * RotateXSpeed)) * timeElapsed; double m = 1.0; RotateXSpeed += (double)RotateX * d; if (RotateXSpeed < -m) { RotateXSpeed = -m; } else if (RotateXSpeed > m) { RotateXSpeed = m; } } if (RotateXSpeed != 0.0) { double cosa = Math.Cos(RotateXSpeed * timeElapsed); double sina = Math.Sin(RotateXSpeed * timeElapsed); 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); keep = true; } // rotate y if (RotateY == 0) { double d = (1.0 + Math.Abs(RotateYSpeed)) * timeElapsed; if (RotateYSpeed >= -d & RotateYSpeed <= d) { RotateYSpeed = 0.0; } else { RotateYSpeed -= (double)Math.Sign(RotateYSpeed) * d; } } else { double d = (1.0 + 1.0 - 1.0 / (1.0 + RotateYSpeed * RotateYSpeed)) * timeElapsed; double m = 1.0; RotateYSpeed += (double)RotateY * d; if (RotateYSpeed < -m) { RotateYSpeed = -m; } else if (RotateYSpeed > m) { RotateYSpeed = m; } } if (RotateYSpeed != 0.0) { double cosa = Math.Cos(RotateYSpeed * timeElapsed); double sina = Math.Sin(RotateYSpeed * timeElapsed); 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); keep = true; } // move x if (MoveX == 0) { double d = (2.5 + Math.Abs(MoveXSpeed)) * timeElapsed; if (MoveXSpeed >= -d & MoveXSpeed <= d) { MoveXSpeed = 0.0; } else { MoveXSpeed -= (double)Math.Sign(MoveXSpeed) * d; } } else { double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveXSpeed * MoveXSpeed)) * timeElapsed; double m = 25.0; MoveXSpeed += (double)MoveX * d; if (MoveXSpeed < -m) { MoveXSpeed = -m; } else if (MoveXSpeed > m) { MoveXSpeed = m; } } if (MoveXSpeed != 0.0) { World.AbsoluteCameraPosition.X += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.X; World.AbsoluteCameraPosition.Y += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.Y; World.AbsoluteCameraPosition.Z += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.Z; keep = true; } // move y if (MoveY == 0) { double d = (2.5 + Math.Abs(MoveYSpeed)) * timeElapsed; if (MoveYSpeed >= -d & MoveYSpeed <= d) { MoveYSpeed = 0.0; } else { MoveYSpeed -= (double)Math.Sign(MoveYSpeed) * d; } } else { double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveYSpeed * MoveYSpeed)) * timeElapsed; double m = 25.0; MoveYSpeed += (double)MoveY * d; if (MoveYSpeed < -m) { MoveYSpeed = -m; } else if (MoveYSpeed > m) { MoveYSpeed = m; } } if (MoveYSpeed != 0.0) { World.AbsoluteCameraPosition.X += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.X; World.AbsoluteCameraPosition.Y += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.Y; World.AbsoluteCameraPosition.Z += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.Z; keep = true; } // move z if (MoveZ == 0) { double d = (2.5 + Math.Abs(MoveZSpeed)) * timeElapsed; if (MoveZSpeed >= -d & MoveZSpeed <= d) { MoveZSpeed = 0.0; } else { MoveZSpeed -= (double)Math.Sign(MoveZSpeed) * d; } } else { double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveZSpeed * MoveZSpeed)) * timeElapsed; double m = 25.0; MoveZSpeed += (double)MoveZ * d; if (MoveZSpeed < -m) { MoveZSpeed = -m; } else if (MoveZSpeed > m) { MoveZSpeed = m; } } if (MoveZSpeed != 0.0) { World.AbsoluteCameraPosition.X += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.X; World.AbsoluteCameraPosition.Y += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.Y; World.AbsoluteCameraPosition.Z += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.Z; keep = true; } // lighting if (LightingRelative == -1) { LightingRelative = (double)LightingTarget; updatelight = true; } if (LightingTarget == 0) { if (LightingRelative != 0.0) { LightingRelative -= 0.5 * timeElapsed; if (LightingRelative < 0.0) { LightingRelative = 0.0; } updatelight = true; keep = true; } } else { if (LightingRelative != 1.0) { LightingRelative += 0.5 * timeElapsed; if (LightingRelative > 1.0) { LightingRelative = 1.0; } updatelight = true; keep = true; } } // continue if (ReducedMode) { ReducedModeEnteringTime = (int)(ticks + 3000); } else { if (keep) { ReducedModeEnteringTime = (int)(ticks + 3000); } else if (ticks > ReducedModeEnteringTime) { ReducedMode = true; World.AbsoluteCameraSide.Y = 0.0; World.Normalize(ref World.AbsoluteCameraSide.X, ref World.AbsoluteCameraSide.Y, ref World.AbsoluteCameraSide.Z); World.Normalize(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z); World.AbsoluteCameraUp = World.Cross(World.AbsoluteCameraDirection, World.AbsoluteCameraSide); } } if (updatelight) { Renderer.OptionAmbientColor.R = (byte)Math.Round(32.0 + 128.0 * LightingRelative * (2.0 - LightingRelative)); Renderer.OptionAmbientColor.G = (byte)Math.Round(32.0 + 128.0 * 0.5 * (LightingRelative + LightingRelative * (2.0 - LightingRelative))); Renderer.OptionAmbientColor.B = (byte)Math.Round(32.0 + 128.0 * LightingRelative); Renderer.OptionDiffuseColor.R = (byte)Math.Round(32.0 + 128.0 * LightingRelative); Renderer.OptionDiffuseColor.G = (byte)Math.Round(32.0 + 128.0 * LightingRelative); Renderer.OptionDiffuseColor.B = (byte)Math.Round(32.0 + 128.0 * Math.Sqrt(LightingRelative)); Renderer.InitializeLighting(); } Renderer.RenderScene(); SDL.SDL_GL_SwapWindow(SDLWindow); } // quit TextureManager.UnuseAllTextures(); if (iconSurface != IntPtr.Zero) { SDL.SDL_FreeSurface(iconSurface); // free surface } if (iconBmp != null && iconData != null) { iconBmp.UnlockBits(iconData); // free pixels iconBmp.Dispose(); } SDL.SDL_GL_DeleteContext(GLContext); SDL.SDL_DestroyWindow(SDLWindow); SDL.SDL_Quit(); } else { MessageBox.Show("SDL failed to create the window.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand); } }
// 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; } } }
internal void UpdateTopplingCantAndSpring() { if (CarSections.Length != 0) { //FRONT BOGIE // get direction, up and side vectors double dx, dy, dz; double ux, uy, uz; double sx, sy, sz; { dx = FrontAxle.Follower.WorldPosition.X - RearAxle.Follower.WorldPosition.X; dy = FrontAxle.Follower.WorldPosition.Y - RearAxle.Follower.WorldPosition.Y; dz = FrontAxle.Follower.WorldPosition.Z - RearAxle.Follower.WorldPosition.Z; double t = 1.0 / Math.Sqrt(dx * dx + dy * dy + dz * dz); dx *= t; dy *= t; dz *= t; t = 1.0 / Math.Sqrt(dx * dx + dz * dz); double ex = dx * t; double ez = dz * t; sx = ez; sy = 0.0; sz = -ex; World.Cross(dx, dy, dz, sx, sy, sz, out ux, out uy, out uz); } // cant and radius //TODO: This currently uses the figures from the base car // apply position due to cant/toppling { double a = baseCar.Specs.CurrentRollDueToTopplingAngle + baseCar.Specs.CurrentRollDueToCantAngle; double x = Math.Sign(a) * 0.5 * Game.RouteRailGauge * (1.0 - Math.Cos(a)); double y = Math.Abs(0.5 * Game.RouteRailGauge * Math.Sin(a)); double cx = sx * x + ux * y; double cy = sy * x + uy * y; double cz = sz * x + uz * y; FrontAxle.Follower.WorldPosition.X += cx; FrontAxle.Follower.WorldPosition.Y += cy; FrontAxle.Follower.WorldPosition.Z += cz; RearAxle.Follower.WorldPosition.X += cx; RearAxle.Follower.WorldPosition.Y += cy; RearAxle.Follower.WorldPosition.Z += cz; } // apply rolling { double a = -baseCar.Specs.CurrentRollDueToTopplingAngle - baseCar.Specs.CurrentRollDueToCantAngle; double cosa = Math.Cos(a); double sina = Math.Sin(a); World.Rotate(ref sx, ref sy, ref sz, dx, dy, dz, cosa, sina); World.Rotate(ref ux, ref uy, ref uz, dx, dy, dz, cosa, sina); Up.X = ux; Up.Y = uy; Up.Z = uz; } // apply pitching if (CurrentCarSection >= 0 && CarSections[CurrentCarSection].Overlay) { double a = baseCar.Specs.CurrentPitchDueToAccelerationAngle; double cosa = Math.Cos(a); double sina = Math.Sin(a); 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); double cx = 0.5 * (FrontAxle.Follower.WorldPosition.X + RearAxle.Follower.WorldPosition.X); double cy = 0.5 * (FrontAxle.Follower.WorldPosition.Y + RearAxle.Follower.WorldPosition.Y); double cz = 0.5 * (FrontAxle.Follower.WorldPosition.Z + RearAxle.Follower.WorldPosition.Z); FrontAxle.Follower.WorldPosition.X -= cx; FrontAxle.Follower.WorldPosition.Y -= cy; FrontAxle.Follower.WorldPosition.Z -= cz; RearAxle.Follower.WorldPosition.X -= cx; RearAxle.Follower.WorldPosition.Y -= cy; RearAxle.Follower.WorldPosition.Z -= cz; World.Rotate(ref FrontAxle.Follower.WorldPosition, sx, sy, sz, cosa, sina); World.Rotate(ref RearAxle.Follower.WorldPosition, sx, sy, sz, cosa, sina); FrontAxle.Follower.WorldPosition.X += cx; FrontAxle.Follower.WorldPosition.Y += cy; FrontAxle.Follower.WorldPosition.Z += cz; RearAxle.Follower.WorldPosition.X += cx; RearAxle.Follower.WorldPosition.Y += cy; RearAxle.Follower.WorldPosition.Z += cz; Up.X = ux; Up.Y = uy; Up.Z = uz; } } }
private static void RenderCube(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, double Size, double CameraX, double CameraY, double CameraZ, Textures.Texture TextureIndex) { Vector3[] v = new Vector3[8]; v[0] = new Vector3(Size, Size, -Size); v[1] = new Vector3(Size, -Size, -Size); v[2] = new Vector3(-Size, -Size, -Size); v[3] = new Vector3(-Size, Size, -Size); v[4] = new Vector3(Size, Size, Size); v[5] = new Vector3(Size, -Size, Size); v[6] = new Vector3(-Size, -Size, Size); v[7] = new Vector3(-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 (TextureIndex == null || !Textures.LoadTexture(TextureIndex, Textures.OpenGlTextureWrapMode.ClampClamp)) { if (TexturingEnabled) { GL.Disable(EnableCap.Texture2D); TexturingEnabled = false; } for (int i = 0; i < 6; i++) { GL.Begin(PrimitiveType.Quads); GL.Color3(1.0, 1.0, 1.0); 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(); } return; } else { TexturingEnabled = true; GL.Enable(EnableCap.Texture2D); } GL.BindTexture(TextureTarget.Texture2D, TextureIndex.OpenGlTextures[(int)Textures.OpenGlTextureWrapMode.ClampClamp].Name); Vector2[][] t = new Vector2[6][]; t[0] = new Vector2[] { new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0) }; t[1] = new Vector2[] { new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0) }; t[2] = new Vector2[] { new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0) }; t[3] = new Vector2[] { new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0) }; t[4] = new Vector2[] { new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0) }; t[5] = new Vector2[] { new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0) }; for (int i = 0; i < 6; i++) { GL.Begin(PrimitiveType.Quads); GL.Color3(1.0, 1.0, 1.0); for (int j = 0; j < 4; j++) { GL.TexCoord2(t[i][j].X, t[i][j].Y); GL.Vertex3(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z); } GL.End(); } }