internal void ChangeSection(int SectionIndex) { if (CarSections.Length == 0) { CurrentCarSection = -1; //Hack: If no bogie objects are defined, just return return; } for (int i = 0; i < CarSections.Length; i++) { for (int j = 0; j < CarSections[i].Elements.Length; j++) { int o = CarSections[i].Elements[j].ObjectIndex; Renderer.HideObject(o); } } if (SectionIndex >= 0) { CarSections[SectionIndex].Initialize(CurrentlyVisible); for (int j = 0; j < CarSections[SectionIndex].Elements.Length; j++) { int o = CarSections[SectionIndex].Elements[j].ObjectIndex; Renderer.ShowObject(o, ObjectType.Dynamic); } } CurrentCarSection = SectionIndex; UpdateObjects(0.0, true); }
internal void Initialize(int StateIndex, bool Overlay, bool Show) { int i = ObjectIndex; Renderer.HideObject(i); int t = StateIndex; if (t >= 0 && States[t].Object != null) { int m = States[t].Object.Mesh.Vertices.Length; ObjectManager.Objects[i].Mesh.Vertices = new VertexTemplate[m]; for (int k = 0; k < m; k++) { if (States[t].Object.Mesh.Vertices[k] is ColoredVertex) { ObjectManager.Objects[i].Mesh.Vertices[k] = new ColoredVertex((ColoredVertex)States[t].Object.Mesh.Vertices[k]); } else { ObjectManager.Objects[i].Mesh.Vertices[k] = new Vertex((Vertex)States[t].Object.Mesh.Vertices[k]); } } m = States[t].Object.Mesh.Faces.Length; ObjectManager.Objects[i].Mesh.Faces = new MeshFace[m]; for (int k = 0; k < m; k++) { ObjectManager.Objects[i].Mesh.Faces[k].Flags = States[t].Object.Mesh.Faces[k].Flags; ObjectManager.Objects[i].Mesh.Faces[k].Material = States[t].Object.Mesh.Faces[k].Material; int o = States[t].Object.Mesh.Faces[k].Vertices.Length; ObjectManager.Objects[i].Mesh.Faces[k].Vertices = new MeshFaceVertex[o]; for (int h = 0; h < o; h++) { ObjectManager.Objects[i].Mesh.Faces[k].Vertices[h] = States[t].Object.Mesh.Faces[k].Vertices[h]; } } ObjectManager.Objects[i].Mesh.Materials = States[t].Object.Mesh.Materials; } else { ObjectManager.Objects[i] = new StaticObject(Program.CurrentHost); } CurrentState = StateIndex; if (Show) { if (Overlay) { Renderer.ShowObject(i, ObjectType.Overlay); } else { Renderer.ShowObject(i, ObjectType.Dynamic); } } }
/// <summary>Called once at the start of the simulation to setup the visibility for all objects</summary> internal static void InitializeVisibility() { // sort objects ObjectsSortedByStart = new int[ObjectsUsed]; ObjectsSortedByEnd = new int[ObjectsUsed]; double[] a = new double[ObjectsUsed]; double[] b = new double[ObjectsUsed]; int n = 0; for (int i = 0; i < ObjectsUsed; i++) { if (!Objects[i].Dynamic) { ObjectsSortedByStart[n] = i; ObjectsSortedByEnd[n] = i; a[n] = Objects[i].StartingDistance; b[n] = Objects[i].EndingDistance; n++; } } Array.Resize <int>(ref ObjectsSortedByStart, n); Array.Resize <int>(ref ObjectsSortedByEnd, n); Array.Resize <double>(ref a, n); Array.Resize <double>(ref b, n); Array.Sort <double, int>(a, ObjectsSortedByStart); Array.Sort <double, int>(b, ObjectsSortedByEnd); ObjectsSortedByStartPointer = 0; ObjectsSortedByEndPointer = 0; // initial visiblity double p = World.CameraTrackFollower.TrackPosition + World.CameraCurrentAlignment.Position.Z; for (int i = 0; i < ObjectsUsed; i++) { if (!Objects[i].Dynamic) { if (Objects[i].StartingDistance <= p + World.ForwardViewingDistance & Objects[i].EndingDistance >= p - World.BackwardViewingDistance) { Renderer.ShowObject(i, ObjectType.Static); } } } }
internal void Show() { if (Groups.Length > 0) { for (int i = 0; i < Groups[0].Elements.Length; i++) { int o = Groups[0].Elements[i].ObjectIndex; if (Groups[0].Overlay) { Renderer.ShowObject(o, ObjectType.Overlay); } else { Renderer.ShowObject(o, ObjectType.Dynamic); } } } int add = CurrentAdditionalGroup + 1; if (add < Groups.Length) { for (int i = 0; i < Groups[add].Elements.Length; i++) { int o = Groups[add].Elements[i].ObjectIndex; if (Groups[add].Overlay) { Renderer.ShowObject(o, ObjectType.Overlay); } else { Renderer.ShowObject(o, ObjectType.Dynamic); } } } }
internal override void Update(double TimeElapsed, bool ForceUpdate) { const double extraRadius = 10.0; double z = Object.TranslateZFunction == null ? 0.0 : Object.TranslateZFunction.LastResult; double pa = TrackPosition + z - Radius - extraRadius; double pb = TrackPosition + z + Radius + extraRadius; double ta = World.CameraTrackFollower.TrackPosition + World.CameraCurrentAlignment.Position.Z - World.BackgroundImageDistance - World.ExtraViewingDistance; double tb = World.CameraTrackFollower.TrackPosition + World.CameraCurrentAlignment.Position.Z + World.BackgroundImageDistance + World.ExtraViewingDistance; bool visible = pb >= ta & pa <= tb; if (visible | ForceUpdate) { if (Object.SecondsSinceLastUpdate >= Object.RefreshRate | ForceUpdate) { double timeDelta = Object.SecondsSinceLastUpdate + TimeElapsed; Object.SecondsSinceLastUpdate = 0.0; TrainManager.Train train = null; double trainDistance = double.MaxValue; for (int j = 0; j < TrainManager.Trains.Length; j++) { if (TrainManager.Trains[j].State == TrainManager.TrainState.Available) { double distance; if (TrainManager.Trains[j].Cars[0].FrontAxle.Follower.TrackPosition < TrackPosition) { distance = TrackPosition - TrainManager.Trains[j].Cars[0].FrontAxle.Follower.TrackPosition; } else if (TrainManager.Trains[j].Cars[TrainManager.Trains[j].Cars.Length - 1].RearAxle.Follower.TrackPosition > TrackPosition) { distance = TrainManager.Trains[j].Cars[TrainManager.Trains[j].Cars.Length - 1].RearAxle.Follower.TrackPosition - TrackPosition; } else { distance = 0; } if (distance < trainDistance) { train = TrainManager.Trains[j]; trainDistance = distance; } } } Object.Update(false, train, train == null ? 0 : train.DriverCar, SectionIndex, TrackPosition, Position, Direction, Up, Side, false, true, true, timeDelta, true); if (this.Object.CurrentState != this.lastState && Loading.SimulationSetup) { if (this.SingleBuffer && this.Buffers[0] != null) { switch (this.Object.CurrentState) { case -1: if (this.PlayOnHide) { this.Source = Sounds.PlaySound(this.Buffers[0], this.currentPitch, this.currentVolume, this.Position, false); } break; case 0: if (this.PlayOnShow || this.lastState != -1) { this.Source = Sounds.PlaySound(this.Buffers[0], this.currentPitch, this.currentVolume, this.Position, false); } break; default: this.Source = Sounds.PlaySound(this.Buffers[0], this.currentPitch, this.currentVolume, this.Position, false); break; } } else { int bufferIndex = this.Object.CurrentState + 1; if (bufferIndex < this.Buffers.Length && this.Buffers[bufferIndex] != null) { switch (bufferIndex) { case 0: if (this.PlayOnHide) { this.Source = Sounds.PlaySound(this.Buffers[bufferIndex], this.currentPitch, this.currentVolume, this.Position, false); } break; case 1: if (this.PlayOnShow || this.lastState != -1) { this.Source = Sounds.PlaySound(this.Buffers[bufferIndex], this.currentPitch, this.currentVolume, this.Position, false); } break; default: this.Source = Sounds.PlaySound(this.Buffers[bufferIndex], this.currentPitch, this.currentVolume, this.Position, false); break; } } } } } else { Object.SecondsSinceLastUpdate += TimeElapsed; } if (!Visible) { Renderer.ShowObject(Object.ObjectIndex, ObjectType.Dynamic); Visible = true; } } else { Object.SecondsSinceLastUpdate += TimeElapsed; if (Visible) { Renderer.HideObject(Object.ObjectIndex); Visible = false; } } this.lastState = this.Object.CurrentState; }
#pragma warning restore 0649 public override void Update(double TimeElapsed, bool ForceUpdate) { const double extraRadius = 10.0; double z = Object.TranslateZFunction == null ? 0.0 : Object.TranslateZFunction.LastResult; double pa = TrackPosition + z - Radius - extraRadius; double pb = TrackPosition + z + Radius + extraRadius; double ta = World.CameraTrackFollower.TrackPosition + Camera.CurrentAlignment.Position.Z - Backgrounds.BackgroundImageDistance - World.ExtraViewingDistance; double tb = World.CameraTrackFollower.TrackPosition + Camera.CurrentAlignment.Position.Z + Backgrounds.BackgroundImageDistance + World.ExtraViewingDistance; bool visible = pb >= ta & pa <= tb; if (visible | ForceUpdate) { if (Object.SecondsSinceLastUpdate >= Object.RefreshRate | ForceUpdate) { double timeDelta = Object.SecondsSinceLastUpdate + TimeElapsed; Object.SecondsSinceLastUpdate = 0.0; TrainManager.Train train = null; double trainDistance = double.MaxValue; for (int j = 0; j < TrainManager.Trains.Length; j++) { if (TrainManager.Trains[j].State == TrainState.Available) { double distance; if (TrainManager.Trains[j].Cars[0].FrontAxle.Follower.TrackPosition < TrackPosition) { distance = TrackPosition - TrainManager.Trains[j].Cars[0].FrontAxle.Follower.TrackPosition; } else if (TrainManager.Trains[j].Cars[TrainManager.Trains[j].Cars.Length - 1].RearAxle.Follower.TrackPosition > TrackPosition) { distance = TrainManager.Trains[j].Cars[TrainManager.Trains[j].Cars.Length - 1].RearAxle.Follower.TrackPosition - TrackPosition; } else { distance = 0; } if (distance < trainDistance) { train = TrainManager.Trains[j]; trainDistance = distance; } } } if (Visible) { //Calculate the distance travelled double delta = UpdateTrackFollowerScript(false, train, train == null ? 0 : train.DriverCar, SectionIndex, TrackPosition, Position, true, timeDelta); //Update the front and rear axle track followers FrontAxleFollower.Update((TrackPosition + FrontAxlePosition) + delta, true, true); RearAxleFollower.Update((TrackPosition + RearAxlePosition) + delta, true, true); //Update the base object position FrontAxleFollower.UpdateWorldCoordinates(false); RearAxleFollower.UpdateWorldCoordinates(false); UpdateObjectPosition(); } //Update the actual animated object- This must be done last in case the user has used Translation or Rotation Object.Update(false, train, train == null ? 0 : train.DriverCar, SectionIndex, FrontAxleFollower.TrackPosition, FrontAxleFollower.WorldPosition, Direction, Up, Side, false, true, true, timeDelta, true); } else { Object.SecondsSinceLastUpdate += TimeElapsed; } if (!Visible) { Renderer.ShowObject(Object.ObjectIndex, ObjectType.Dynamic); Visible = true; } } else { Object.SecondsSinceLastUpdate += TimeElapsed; if (Visible) { Renderer.HideObject(Object.ObjectIndex); Visible = false; } } }
/// <summary>Is called to update the visibility of the camera</summary> /// <param name="TrackPosition">The camera's track position</param> internal static void UpdateVisibility(double TrackPosition) { double d = TrackPosition - LastUpdatedTrackPosition; int n = ObjectsSortedByStart.Length; double p = World.CameraTrackFollower.TrackPosition + World.CameraCurrentAlignment.Position.Z; if (d < 0.0) { if (ObjectsSortedByStartPointer >= n) { ObjectsSortedByStartPointer = n - 1; } if (ObjectsSortedByEndPointer >= n) { ObjectsSortedByEndPointer = n - 1; } // dispose while (ObjectsSortedByStartPointer >= 0) { int o = ObjectsSortedByStart[ObjectsSortedByStartPointer]; if (Objects[o].StartingDistance > p + World.ForwardViewingDistance) { Renderer.HideObject(o); ObjectsSortedByStartPointer--; } else { break; } } // introduce while (ObjectsSortedByEndPointer >= 0) { int o = ObjectsSortedByEnd[ObjectsSortedByEndPointer]; if (Objects[o].EndingDistance >= p - World.BackwardViewingDistance) { if (Objects[o].StartingDistance <= p + World.ForwardViewingDistance) { Renderer.ShowObject(o, ObjectType.Static); } ObjectsSortedByEndPointer--; } else { break; } } } else if (d > 0.0) { if (ObjectsSortedByStartPointer < 0) { ObjectsSortedByStartPointer = 0; } if (ObjectsSortedByEndPointer < 0) { ObjectsSortedByEndPointer = 0; } // dispose while (ObjectsSortedByEndPointer < n) { int o = ObjectsSortedByEnd[ObjectsSortedByEndPointer]; if (Objects[o].EndingDistance < p - World.BackwardViewingDistance) { Renderer.HideObject(o); ObjectsSortedByEndPointer++; } else { break; } } // introduce while (ObjectsSortedByStartPointer < n) { int o = ObjectsSortedByStart[ObjectsSortedByStartPointer]; if (Objects[o].StartingDistance <= p + World.ForwardViewingDistance) { if (Objects[o].EndingDistance >= p - World.BackwardViewingDistance) { Renderer.ShowObject(o, ObjectType.Static); } ObjectsSortedByStartPointer++; } else { break; } } } LastUpdatedTrackPosition = TrackPosition; }
internal override void Update(double TimeElapsed, bool ForceUpdate) { const double extraRadius = 10.0; double z = Object.TranslateZFunction == null ? 0.0 : Object.TranslateZFunction.LastResult; double pa = TrackPosition + z - Radius - extraRadius; double pb = TrackPosition + z + Radius + extraRadius; double ta = World.CameraTrackFollower.TrackPosition + World.CameraCurrentAlignment.Position.Z - World.BackgroundImageDistance - World.ExtraViewingDistance; double tb = World.CameraTrackFollower.TrackPosition + World.CameraCurrentAlignment.Position.Z + World.BackgroundImageDistance + World.ExtraViewingDistance; bool visible = pb >= ta & pa <= tb; if (visible | ForceUpdate) { if (Object.SecondsSinceLastUpdate >= Object.RefreshRate | ForceUpdate) { double timeDelta = Object.SecondsSinceLastUpdate + TimeElapsed; Object.SecondsSinceLastUpdate = 0.0; TrainManager.Train train = null; double trainDistance = double.MaxValue; for (int j = 0; j < TrainManager.Trains.Length; j++) { if (TrainManager.Trains[j].State == TrainState.Available) { double distance; if (TrainManager.Trains[j].Cars[0].FrontAxle.Follower.TrackPosition < TrackPosition) { distance = TrackPosition - TrainManager.Trains[j].Cars[0].FrontAxle.Follower.TrackPosition; } else if (TrainManager.Trains[j].Cars[TrainManager.Trains[j].Cars.Length - 1].RearAxle.Follower.TrackPosition > TrackPosition) { distance = TrainManager.Trains[j].Cars[TrainManager.Trains[j].Cars.Length - 1].RearAxle.Follower.TrackPosition - TrackPosition; } else { distance = 0; } if (distance < trainDistance) { train = TrainManager.Trains[j]; trainDistance = distance; } } } Object.Update(false, train, train == null ? 0 : train.DriverCar, SectionIndex, TrackPosition, Position, Direction, Up, Side, false, true, true, timeDelta, true); } else { Object.SecondsSinceLastUpdate += TimeElapsed; } if (!Visible) { Renderer.ShowObject(Object.ObjectIndex, ObjectType.Dynamic); Visible = true; } } else { Object.SecondsSinceLastUpdate += TimeElapsed; if (Visible) { Renderer.HideObject(Object.ObjectIndex); Visible = false; } } }
/// <summary> Updates the position and state of the animated object</summary> /// <param name="IsPartOfTrain">Whether this object forms part of a train</param> /// <param name="Train">The train, or a null reference otherwise</param> /// <param name="CarIndex">If this object forms part of a train, the car index it refers to</param> /// <param name="SectionIndex">If this object has been placed via Track.Sig, the index of the section it is attached to</param> /// <param name="TrackPosition"></param> /// <param name="Position"></param> /// <param name="Direction"></param> /// <param name="Up"></param> /// <param name="Side"></param> /// <param name="Overlay">Whether this object should be overlaid over the other objects on-screen (Forms part of the cab etc.)</param> /// <param name="UpdateFunctions">Whether the functions associated with this object should be re-evaluated</param> /// <param name="Show"></param> /// <param name="TimeElapsed">The time elapsed since this object was last updated</param> /// <param name="EnableDamping">Whether damping is to be applied for this call</param> /// <param name="IsTouch">Whether Animated Object belonging to TouchElement class.</param> internal void Update(bool IsPartOfTrain, AbstractTrain Train, int CarIndex, int SectionIndex, double TrackPosition, Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, bool Overlay, bool UpdateFunctions, bool Show, double TimeElapsed, bool EnableDamping, bool IsTouch = false) { int s = CurrentState; int i = ObjectIndex; // state change if (StateFunction != null & UpdateFunctions) { double sd = StateFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState); int si = (int)Math.Round(sd); int sn = States.Length; if (si < 0 | si >= sn) { si = -1; } if (s != si) { Initialize(si, Overlay, Show); s = si; } } if (s == -1) { return; } // translation if (TranslateXFunction != null) { double x; if (UpdateFunctions) { x = TranslateXFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState); } else { x = TranslateXFunction.LastResult; } Vector3 translationVector = new Vector3(TranslateXDirection); //Must clone translationVector.Rotate(Direction, Up, Side); translationVector *= x; Position += translationVector; } else if (TranslateXScriptFile != null) { //Translate X Script if (TranslateXAnimationScript == null) { //Load the script if required try { CSScript.GlobalSettings.TargetFramework = "v4.0"; TranslateXAnimationScript = CSScript.LoadCodeFrom(TranslateXScriptFile) .CreateObject("OpenBVEScript") .AlignToInterface <AnimationScript>(true); } catch { Interface.AddMessage(MessageType.Error, false, "An error occcured whilst parsing script " + TranslateXScriptFile); TranslateXScriptFile = null; return; } } double x = TranslateXAnimationScript.ExecuteScript(Train, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed); Vector3 translationVector = new Vector3(TranslateXDirection); //Must clone translationVector.Rotate(Direction, Up, Side); translationVector *= x; Position += translationVector; } if (TranslateYFunction != null) { double y; if (UpdateFunctions) { y = TranslateYFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState); } else { y = TranslateYFunction.LastResult; } Vector3 translationVector = new Vector3(TranslateYDirection); //Must clone translationVector.Rotate(Direction, Up, Side); translationVector *= y; Position += translationVector; } else if (TranslateYScriptFile != null) { //Translate X Script if (TranslateYAnimationScript == null) { //Load the script if required try { CSScript.GlobalSettings.TargetFramework = "v4.0"; TranslateYAnimationScript = CSScript.LoadCodeFrom(TranslateYScriptFile) .CreateObject("OpenBVEScript") .AlignToInterface <AnimationScript>(true); } catch { Interface.AddMessage(MessageType.Error, false, "An error occcured whilst parsing script " + TranslateYScriptFile); TranslateYScriptFile = null; return; } } double y = TranslateYAnimationScript.ExecuteScript(Train, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed); Vector3 translationVector = new Vector3(TranslateYDirection); //Must clone translationVector.Rotate(Direction, Up, Side); translationVector *= y; Position += translationVector; } if (TranslateZFunction != null) { double z; if (UpdateFunctions) { z = TranslateZFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState); } else { z = TranslateZFunction.LastResult; } Vector3 translationVector = new Vector3(TranslateZDirection); //Must clone translationVector.Rotate(Direction, Up, Side); translationVector *= z; Position += translationVector; } else if (TranslateZScriptFile != null) { //Translate X Script if (TranslateZAnimationScript == null) { //Load the script if required try { CSScript.GlobalSettings.TargetFramework = "v4.0"; TranslateZAnimationScript = CSScript.LoadCodeFrom(TranslateZScriptFile) .CreateObject("OpenBVEScript") .AlignToInterface <AnimationScript>(true); } catch { Interface.AddMessage(MessageType.Error, false, "An error occcured whilst parsing script " + TranslateZScriptFile); TranslateZScriptFile = null; return; } } double z = TranslateZAnimationScript.ExecuteScript(Train, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed); Vector3 translationVector = new Vector3(TranslateZDirection); //Must clone translationVector.Rotate(Direction, Up, Side); translationVector *= z; Position += translationVector; } // rotation bool rotateX = RotateXFunction != null; bool rotateY = RotateYFunction != null; bool rotateZ = RotateZFunction != null; double cosX, sinX; if (rotateX) { double a; if (UpdateFunctions) { a = RotateXFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState); } else { a = RotateXFunction.LastResult; } if (RotateXDamping != null) { RotateXDamping.Update(TimeElapsed, ref a, EnableDamping); } cosX = Math.Cos(a); sinX = Math.Sin(a); } else { cosX = 0.0; sinX = 0.0; } double cosY, sinY; if (rotateY) { double a; if (UpdateFunctions) { a = RotateYFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState); } else { a = RotateYFunction.LastResult; } if (RotateYDamping != null) { RotateYDamping.Update(TimeElapsed, ref a, EnableDamping); } cosY = Math.Cos(a); sinY = Math.Sin(a); } else { cosY = 0.0; sinY = 0.0; } double cosZ, sinZ; if (rotateZ) { double a; if (UpdateFunctions) { a = RotateZFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState); } else { a = RotateZFunction.LastResult; } if (RotateZDamping != null) { RotateZDamping.Update(TimeElapsed, ref a, EnableDamping); } cosZ = Math.Cos(a); sinZ = Math.Sin(a); } else { cosZ = 0.0; sinZ = 0.0; } // texture shift bool shiftx = TextureShiftXFunction != null; bool shifty = TextureShiftYFunction != null; if ((shiftx | shifty) & UpdateFunctions) { for (int k = 0; k < ObjectManager.Objects[i].Mesh.Vertices.Length; k++) { ObjectManager.Objects[i].Mesh.Vertices[k].TextureCoordinates = States[s].Object.Mesh.Vertices[k].TextureCoordinates; } if (shiftx) { double x = TextureShiftXFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState); x -= Math.Floor(x); for (int k = 0; k < ObjectManager.Objects[i].Mesh.Vertices.Length; k++) { ObjectManager.Objects[i].Mesh.Vertices[k].TextureCoordinates.X += (float)(x * TextureShiftXDirection.X); ObjectManager.Objects[i].Mesh.Vertices[k].TextureCoordinates.Y += (float)(x * TextureShiftXDirection.Y); } } if (shifty) { double y = TextureShiftYFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState); y -= Math.Floor(y); for (int k = 0; k < ObjectManager.Objects[i].Mesh.Vertices.Length; k++) { ObjectManager.Objects[i].Mesh.Vertices[k].TextureCoordinates.X += (float)(y * TextureShiftYDirection.X); ObjectManager.Objects[i].Mesh.Vertices[k].TextureCoordinates.Y += (float)(y * TextureShiftYDirection.Y); } } } // led bool led = LEDFunction != null; double ledangle; if (led) { if (UpdateFunctions) { ledangle = LEDFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState); } else { ledangle = LEDFunction.LastResult; } } else { ledangle = 0.0; } // null object if (States[s].Object == null) { return; } // initialize vertices for (int k = 0; k < States[s].Object.Mesh.Vertices.Length; k++) { ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates = States[s].Object.Mesh.Vertices[k].Coordinates; } // led if (led) { /* * Edges: Vertices: * 0 - bottom 0 - bottom-left * 1 - left 1 - top-left * 2 - top 2 - top-right * 3 - right 3 - bottom-right * 4 - center * */ int v = 1; if (LEDClockwiseWinding) { /* winding is clockwise*/ if (ledangle < LEDInitialAngle) { ledangle = LEDInitialAngle; } if (ledangle < LEDLastAngle) { double currentEdgeFloat = Math.Floor(0.636619772367582 * (ledangle + 0.785398163397449)); int currentEdge = ((int)currentEdgeFloat % 4 + 4) % 4; double lastEdgeFloat = Math.Floor(0.636619772367582 * (LEDLastAngle + 0.785398163397449)); int lastEdge = ((int)lastEdgeFloat % 4 + 4) % 4; if (lastEdge < currentEdge | lastEdge == currentEdge & Math.Abs(currentEdgeFloat - lastEdgeFloat) > 2.0) { lastEdge += 4; } if (currentEdge == lastEdge) { /* current angle to last angle */ { double t = 0.5 + (0.636619772367582 * ledangle) - currentEdgeFloat; if (t < 0.0) { t = 0.0; } else if (t > 1.0) { t = 1.0; } t = 0.5 * (1.0 - Math.Tan(0.25 * (Math.PI - 2.0 * Math.PI * t))); double cx = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].X + t * LEDVectors[currentEdge].X; double cy = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Y + t * LEDVectors[currentEdge].Y; double cz = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Z + t * LEDVectors[currentEdge].Z; States[s].Object.Mesh.Vertices[v].Coordinates = new Vector3(cx, cy, cz); v++; } { double t = 0.5 + (0.636619772367582 * LEDLastAngle) - lastEdgeFloat; if (t < 0.0) { t = 0.0; } else if (t > 1.0) { t = 1.0; } t = 0.5 * (1.0 - Math.Tan(0.25 * (Math.PI - 2.0 * Math.PI * t))); double lx = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].X + t * LEDVectors[lastEdge].X; double ly = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Y + t * LEDVectors[lastEdge].Y; double lz = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Z + t * LEDVectors[lastEdge].Z; States[s].Object.Mesh.Vertices[v].Coordinates = new Vector3(lx, ly, lz); v++; } } else { { /* current angle to square vertex */ double t = 0.5 + (0.636619772367582 * ledangle) - currentEdgeFloat; if (t < 0.0) { t = 0.0; } else if (t > 1.0) { t = 1.0; } t = 0.5 * (1.0 - Math.Tan(0.25 * (Math.PI - 2.0 * Math.PI * t))); double cx = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].X + t * LEDVectors[currentEdge].X; double cy = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Y + t * LEDVectors[currentEdge].Y; double cz = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Z + t * LEDVectors[currentEdge].Z; States[s].Object.Mesh.Vertices[v + 0].Coordinates = new Vector3(cx, cy, cz); States[s].Object.Mesh.Vertices[v + 1].Coordinates = LEDVectors[currentEdge]; v += 2; } for (int j = currentEdge + 1; j < lastEdge; j++) { /* square-vertex to square-vertex */ States[s].Object.Mesh.Vertices[v + 0].Coordinates = LEDVectors[(j + 3) % 4]; States[s].Object.Mesh.Vertices[v + 1].Coordinates = LEDVectors[j % 4]; v += 2; } { /* square vertex to last angle */ double t = 0.5 + (0.636619772367582 * LEDLastAngle) - lastEdgeFloat; if (t < 0.0) { t = 0.0; } else if (t > 1.0) { t = 1.0; } t = 0.5 * (1.0 - Math.Tan(0.25 * (Math.PI - 2.0 * Math.PI * t))); double lx = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].X + t * LEDVectors[lastEdge % 4].X; double ly = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Y + t * LEDVectors[lastEdge % 4].Y; double lz = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Z + t * LEDVectors[lastEdge % 4].Z; States[s].Object.Mesh.Vertices[v + 0].Coordinates = LEDVectors[(lastEdge + 3) % 4]; States[s].Object.Mesh.Vertices[v + 1].Coordinates = new Vector3(lx, ly, lz); v += 2; } } } } else { /* winding is counter-clockwise*/ if (ledangle > LEDInitialAngle) { ledangle = LEDInitialAngle; } if (ledangle > LEDLastAngle) { double currentEdgeFloat = Math.Floor(0.636619772367582 * (ledangle + 0.785398163397449)); int currentEdge = ((int)currentEdgeFloat % 4 + 4) % 4; double lastEdgeFloat = Math.Floor(0.636619772367582 * (LEDLastAngle + 0.785398163397449)); int lastEdge = ((int)lastEdgeFloat % 4 + 4) % 4; if (currentEdge < lastEdge | lastEdge == currentEdge & Math.Abs(currentEdgeFloat - lastEdgeFloat) > 2.0) { currentEdge += 4; } if (currentEdge == lastEdge) { /* current angle to last angle */ { double t = 0.5 + (0.636619772367582 * LEDLastAngle) - lastEdgeFloat; if (t < 0.0) { t = 0.0; } else if (t > 1.0) { t = 1.0; } t = 0.5 * (1.0 - Math.Tan(0.25 * (Math.PI - 2.0 * Math.PI * t))); double lx = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].X + t * LEDVectors[lastEdge].X; double ly = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Y + t * LEDVectors[lastEdge].Y; double lz = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Z + t * LEDVectors[lastEdge].Z; States[s].Object.Mesh.Vertices[v].Coordinates = new Vector3(lx, ly, lz); v++; } { double t = 0.5 + (0.636619772367582 * ledangle) - currentEdgeFloat; if (t < 0.0) { t = 0.0; } else if (t > 1.0) { t = 1.0; } t = t - Math.Floor(t); t = 0.5 * (1.0 - Math.Tan(0.25 * (Math.PI - 2.0 * Math.PI * t))); double cx = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].X + t * LEDVectors[currentEdge].X; double cy = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Y + t * LEDVectors[currentEdge].Y; double cz = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Z + t * LEDVectors[currentEdge].Z; States[s].Object.Mesh.Vertices[v].Coordinates = new Vector3(cx, cy, cz); v++; } } else { { /* current angle to square vertex */ double t = 0.5 + (0.636619772367582 * ledangle) - currentEdgeFloat; if (t < 0.0) { t = 0.0; } else if (t > 1.0) { t = 1.0; } t = 0.5 * (1.0 - Math.Tan(0.25 * (Math.PI - 2.0 * Math.PI * t))); double cx = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].X + t * LEDVectors[currentEdge % 4].X; double cy = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Y + t * LEDVectors[currentEdge % 4].Y; double cz = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Z + t * LEDVectors[currentEdge % 4].Z; States[s].Object.Mesh.Vertices[v + 0].Coordinates = LEDVectors[(currentEdge + 3) % 4]; States[s].Object.Mesh.Vertices[v + 1].Coordinates = new Vector3(cx, cy, cz); v += 2; } for (int j = currentEdge - 1; j > lastEdge; j--) { /* square-vertex to square-vertex */ States[s].Object.Mesh.Vertices[v + 0].Coordinates = LEDVectors[(j + 3) % 4]; States[s].Object.Mesh.Vertices[v + 1].Coordinates = LEDVectors[j % 4]; v += 2; } { /* square vertex to last angle */ double t = 0.5 + (0.636619772367582 * LEDLastAngle) - lastEdgeFloat; if (t < 0.0) { t = 0.0; } else if (t > 1.0) { t = 1.0; } t = 0.5 * (1.0 - Math.Tan(0.25 * (Math.PI - 2.0 * Math.PI * t))); double lx = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].X + t * LEDVectors[lastEdge].X; double ly = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Y + t * LEDVectors[lastEdge].Y; double lz = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Z + t * LEDVectors[lastEdge].Z; States[s].Object.Mesh.Vertices[v + 0].Coordinates = new Vector3(lx, ly, lz); States[s].Object.Mesh.Vertices[v + 1].Coordinates = LEDVectors[lastEdge % 4]; v += 2; } } } } for (int j = v; v < 11; v++) { States[s].Object.Mesh.Vertices[j].Coordinates = LEDVectors[4]; } } // update vertices for (int k = 0; k < States[s].Object.Mesh.Vertices.Length; k++) { // rotate if (rotateX) { ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates.Rotate(RotateXDirection, cosX, sinX); } if (rotateY) { ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates.Rotate(RotateYDirection, cosY, sinY); } if (rotateZ) { ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates.Rotate(RotateZDirection, cosZ, sinZ); } // translate if (Overlay & Camera.CurrentRestriction != CameraRestrictionMode.NotAvailable) { ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates += States[s].Position - Position; ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates.Rotate(Camera.AbsoluteDirection, Camera.AbsoluteUp, Camera.AbsoluteSide); double dx = -Math.Tan(Camera.CurrentAlignment.Yaw) - Camera.CurrentAlignment.Position.X; double dy = -Math.Tan(Camera.CurrentAlignment.Pitch) - Camera.CurrentAlignment.Position.Y; double dz = -Camera.CurrentAlignment.Position.Z; ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates.X += Camera.AbsolutePosition.X + dx * Camera.AbsoluteSide.X + dy * Camera.AbsoluteUp.X + dz * Camera.AbsoluteDirection.X; ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates.Y += Camera.AbsolutePosition.Y + dx * Camera.AbsoluteSide.Y + dy * Camera.AbsoluteUp.Y + dz * Camera.AbsoluteDirection.Y; ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates.Z += Camera.AbsolutePosition.Z + dx * Camera.AbsoluteSide.Z + dy * Camera.AbsoluteUp.Z + dz * Camera.AbsoluteDirection.Z; } else { ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates += States[s].Position; ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates.Rotate(Direction, Up, Side); ObjectManager.Objects[i].Mesh.Vertices[k].Coordinates += Position; } } // update normals for (int k = 0; k < States[s].Object.Mesh.Faces.Length; k++) { for (int h = 0; h < States[s].Object.Mesh.Faces[k].Vertices.Length; h++) { ObjectManager.Objects[i].Mesh.Faces[k].Vertices[h].Normal = States[s].Object.Mesh.Faces[k].Vertices[h].Normal; if (!Vector3.IsZero(States[s].Object.Mesh.Faces[k].Vertices[h].Normal)) { if (rotateX) { ObjectManager.Objects[i].Mesh.Faces[k].Vertices[h].Normal.Rotate(RotateXDirection, cosX, sinX); } if (rotateY) { ObjectManager.Objects[i].Mesh.Faces[k].Vertices[h].Normal.Rotate(RotateYDirection, cosY, sinY); } if (rotateZ) { ObjectManager.Objects[i].Mesh.Faces[k].Vertices[h].Normal.Rotate(RotateZDirection, cosZ, sinZ); } ObjectManager.Objects[i].Mesh.Faces[k].Vertices[h].Normal.Rotate(Direction, Up, Side); } } // visibility changed // TouchElement is handled by another function. if (!IsTouch) { if (Show) { if (Overlay) { Renderer.ShowObject(i, ObjectType.Overlay); } else { Renderer.ShowObject(i, ObjectType.Dynamic); } } else { Renderer.HideObject(i); } } } }