コード例 #1
1
ファイル: Parser.Block.cs プロジェクト: sladen/openbve2
 internal Block(double location, Block previous)
 {
     this.Position = previous.Position;
     this.Orientation = previous.Orientation;
     this.Location = location;
     this.TurnRatio = 0.0;
     this.CurveRadius = previous.CurveRadius;
     this.CurveCant = previous.CurveCant;
     this.Pitch = previous.Pitch;
     this.Height = 0.0;
     this.HeightDefined = false;
     this.Rails = new Rail[previous.Rails.Length];
     for (int i = 0; i < previous.Rails.Length; i++) {
         if (previous.Rails[i] != null) {
             this.Rails[i] = new Rail(previous.Rails[i]);
         } else {
             this.Rails[i] = null;
         }
     }
     this.RailCount = previous.RailCount;
     this.GroundCycle = previous.GroundCycle;
     this.FreeObjs = null;
     this.FreeObjCount = 0;
 }
コード例 #2
1
ファイル: Parser.Block.cs プロジェクト: sladen/openbve2
 // constructors
 internal Block(double location)
 {
     this.Position = OpenBveApi.Math.Vector3.Null;
     this.Orientation = OpenBveApi.Math.Orientation3.Default;
     this.Location = location;
     this.TurnRatio = 0.0;
     this.CurveRadius = 0.0;
     this.CurveCant = 0.0;
     this.Pitch = 0.0;
     this.Height = 0.0;
     this.HeightDefined = false;
     this.Rails = new Rail[1];
     this.RailCount = 0;
     this.GroundCycle = 0;
     this.FreeObjs = null;
     this.FreeObjCount = 0;
 }
コード例 #3
1
 // constructors
 /// <summary>Creates a new instance of this class.</summary>
 /// <param name="libraryIndex">A reference to an object in the object library.</param>
 /// <param name="faceIndex">The face within the object.</param>
 /// <param name="position">The absolute world position.</param>
 /// <param name="orientation">The absolute world orientation.</param>
 /// <param name="index">An index by which to identify this face. The value is specific to the function that uses this data structure.</param>
 internal PositionedFace(int libraryIndex, int faceIndex, OpenBveApi.Math.Vector3 position, OpenBveApi.Math.Orientation3 orientation, int index)
 {
     this.LibraryIndex = libraryIndex;
     this.FaceIndex = faceIndex;
     this.Position = position;
     this.Orientation = orientation;
     OpenBveApi.Geometry.FaceVertexMesh mesh = ObjectLibrary.Library.Objects[libraryIndex] as OpenBveApi.Geometry.FaceVertexMesh;
     if (mesh != null && mesh.Faces[faceIndex].Vertices.Length >= 3) {
         OpenBveApi.Math.Vector3 vectorA = mesh.Vertices[mesh.Faces[faceIndex].Vertices[0]].SpatialCoordinates;
         OpenBveApi.Math.Vector3 vectorB = mesh.Vertices[mesh.Faces[faceIndex].Vertices[1]].SpatialCoordinates;
         OpenBveApi.Math.Vector3 vectorC = mesh.Vertices[mesh.Faces[faceIndex].Vertices[2]].SpatialCoordinates;
         if (OpenBveApi.Math.Vector3.CreateNormal(vectorA, vectorB, vectorC, out this.Normal)) {
             this.Normal.Rotate(orientation);
         } else {
             this.Normal = OpenBveApi.Math.Vector3.Up;
         }
     } else {
         this.Normal = OpenBveApi.Math.Vector3.Up;
     }
     this.Index = index;
     this.Tag = 0.0;
 }
コード例 #4
1
ファイル: Parser.cs プロジェクト: sladen/openbve2
 // constructors
 /// <summary>Creates a new instance of this class.</summary>
 internal Options()
 {
     this.UnitsOfLength = new double[] { 1.0 };
     this.UnitOfSpeed = 0.277777777777777778;
     this.BlockLength = 25.0;
     this.Light = new OpenBveApi.Route.DirectionalLight(
         new OpenBveApi.Color.ColorRGB(0.625f, 0.625f, 0.625f),
         new OpenBveApi.Color.ColorRGB(0.625f, 0.625f, 0.625f),
         new OpenBveApi.Color.ColorRGB(0.0f, 0.0f, 0.0f),
         new OpenBveApi.Math.Vector3(-0.219185573394538, -0.86602540378444, 0.449397023149582)
     );
     this.InitialPosition = OpenBveApi.Math.Vector3.Null;
     this.InitialOrientation = OpenBveApi.Math.Orientation3.Default;
 }
コード例 #5
0
 internal void Update(double tb, double tf)
 {
     if (baseTrain.CurrentSpeed > -0.277777777777778 & baseTrain.CurrentSpeed < 0.277777777777778)
     {
         // correct stop position
         if (!Lit & (baseTrain.StationDistanceToStopPoint > tb | baseTrain.StationDistanceToStopPoint < -tf))
         {
             SoundBuffer buffer = AdjustAlarm.Buffer;
             if (buffer != null)
             {
                 OpenBveApi.Math.Vector3 pos = AdjustAlarm.Position;
                 Program.Sounds.PlaySound(buffer, 1.0, 1.0, pos, baseTrain.Cars[baseTrain.DriverCar], false);
             }
             if (baseTrain.IsPlayerTrain)
             {
                 MessageManager.AddMessage(Translations.GetInterfaceString("message_station_correct"), MessageDependency.None, GameMode.Normal, MessageColor.Orange, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null);
             }
             Lit = true;
         }
     }
     else
     {
         Lit = false;
     }
 }
コード例 #6
0
 // --- constructors ---
 /// <summary>Creates a new sound source.</summary>
 /// <param name="buffer">The sound buffer.</param>
 /// <param name="radius">The effective sound radius.</param>
 /// <param name="pitch">The pitch change factor.</param>
 /// <param name="volume">The volume change factor.</param>
 /// <param name="position">The position. If a train and car are specified, the position is relative to the car, otherwise absolute.</param>
 /// <param name="parent">The parent object this sound source is attached to, or a null reference.</param>
 /// <param name="car">The car this sound source is attached to, or a null reference.</param>
 /// <param name="looped">Whether this sound source plays in a loop.</param>
 internal SoundSource(SoundBuffer buffer, double radius, double pitch, double volume, OpenBveApi.Math.Vector3 position, object parent, int car, bool looped)
 {
     this.Buffer           = buffer;
     this.Radius           = radius;
     this.Pitch            = pitch;
     this.Volume           = volume;
     this.Position         = position;
     this.Parent           = parent;
     this.Car              = car;
     this.Looped           = looped;
     this.State            = SoundSourceState.PlayPending;
     this.OpenAlSourceName = 0;
     //Set the sound type to undefined to use Michelle's original processing
     if (parent is TrainManager.Train)
     {
         this.Type = SoundType.TrainCar;
     }
     else if (parent is ObjectManager.WorldSound)
     {
         this.Type = SoundType.AnimatedObject;
     }
     else
     {
         this.Type = SoundType.Undefined;
     }
 }
コード例 #7
0
ファイル: Camera.cs プロジェクト: leezer3/OpenBVE
		// --- constructors ---

		/// <summary>Creates a new camera. A call to SetViewingAngle must be made to set the perspective in OpenGL.</summary>
		/// <param name="viewingDistance">The viewing distance in meters.</param>
		internal Camera(double viewingDistance) {
			const double degrees = 0.0174532925199433;
			this.Position = OpenBveApi.Math.Vector3.Null;
			this.Orientation = OpenBveApi.Math.Orientation3.Default;
			this.HorizontalViewingAngle = 45.0 * degrees;
			this.VerticalViewingAngle = 45.0 * degrees;
			this.ViewingDistance = viewingDistance;
		}
コード例 #8
0
ファイル: Doors.cs プロジェクト: tsdworks/RAGLINK-2
        /// <summary>Opens the left-hand or right-hand doors for the specified train</summary>
        /// <param name="Train">The train</param>
        /// <param name="Left">Whether to open the left-hand doors</param>
        /// <param name="Right">Whether to open the right-hand doors</param>
        internal static void OpenTrainDoors(Train Train, bool Left, bool Right)
        {
            bool sl = false, sr = false;

            for (int i = 0; i < Train.Cars.Length; i++)
            {
                if (Left & !Train.Cars[i].Doors[0].AnticipatedOpen)
                {
                    Train.Cars[i].Doors[0].AnticipatedOpen = true;
                    sl = true;
                }
                if (Right & !Train.Cars[i].Doors[1].AnticipatedOpen)
                {
                    Train.Cars[i].Doors[1].AnticipatedOpen = true;
                    sr = true;
                }
            }
            if (sl)
            {
                for (int i = 0; i < Train.Cars.Length; i++)
                {
                    Sounds.SoundBuffer buffer = Train.Cars[i].Doors[0].OpenSound.Buffer;
                    if (buffer != null)
                    {
                        OpenBveApi.Math.Vector3 pos = Train.Cars[i].Doors[0].OpenSound.Position;
                        Sounds.PlaySound(buffer, Train.Cars[i].Specs.DoorOpenPitch, 1.0, pos, Train, i, false);
                    }
                    for (int j = 0; j < Train.Cars[i].Doors.Length; j++)
                    {
                        if (Train.Cars[i].Doors[j].Direction == -1)
                        {
                            Train.Cars[i].Doors[j].DoorLockDuration = 0.0;
                        }
                    }
                }
            }
            if (sr)
            {
                for (int i = 0; i < Train.Cars.Length; i++)
                {
                    Sounds.SoundBuffer buffer = Train.Cars[i].Doors[1].OpenSound.Buffer;
                    if (buffer != null)
                    {
                        OpenBveApi.Math.Vector3 pos = Train.Cars[i].Doors[1].OpenSound.Position;
                        Sounds.PlaySound(buffer, Train.Cars[i].Specs.DoorOpenPitch, 1.0, pos, Train, i, false);
                    }
                    for (int j = 0; j < Train.Cars[i].Doors.Length; j++)
                    {
                        if (Train.Cars[i].Doors[j].Direction == 1)
                        {
                            Train.Cars[i].Doors[j].DoorLockDuration = 0.0;
                        }
                    }
                }
            }
        }
コード例 #9
0
        internal void LeaveCheck(Vector2 Point)
        {
            if (!Loading.SimulationSetup)
            {
                return;
            }

            if (renderer.Camera.CurrentMode != CameraViewMode.Interior && renderer.Camera.CurrentMode != CameraViewMode.InteriorLookAhead)
            {
                return;
            }

            TrainManager.Car Car = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar];
            int add = Car.CarSections[0].CurrentAdditionalGroup + 1;

            if (add >= Car.CarSections[0].Groups.Length)
            {
                return;
            }

            TrainManager.TouchElement[] TouchElements = Car.CarSections[0].Groups[add].TouchElements;

            if (TouchElements == null)
            {
                return;
            }

            ObjectState pickedObject = ParseFBO(Point, 5, 5);

            foreach (TrainManager.TouchElement TouchElement in TouchElements)
            {
                if (TouchElement.Element.internalObject == pickedObject)
                {
                    Car.CarSections[0].CurrentAdditionalGroup = TouchElement.JumpScreenIndex;
                    Car.ChangeCarSection(TrainManager.CarSectionType.Interior);

                    foreach (var index in TouchElement.SoundIndices.Where(x => x >= 0 && x < Car.Sounds.Touch.Length))
                    {
                        SoundBuffer             Buffer   = Car.Sounds.Touch[index].Buffer;
                        OpenBveApi.Math.Vector3 Position = Car.Sounds.Touch[index].Position;
                        Program.Sounds.PlaySound(Buffer, 1.0, 1.0, Position, TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar], false);
                    }
                }

                // HACK: Normally terminate the command issued once.
                if (TouchElement.Element.internalObject == pickedObject || (pickedObject != prePickedObject && TouchElement.Element.internalObject == prePickedObject))
                {
                    foreach (int index in TouchElement.ControlIndices)
                    {
                        Interface.CurrentControls[index].AnalogState  = 0.0;
                        Interface.CurrentControls[index].DigitalState = Interface.DigitalControlState.Released;
                        MainLoop.RemoveControlRepeat(index);
                    }
                }
            }
        }
コード例 #10
0
ファイル: Camera.cs プロジェクト: piotrulos/OpenBVE
        // --- constructors ---

        /// <summary>Creates a new camera. A call to SetViewingAngle must be made to set the perspective in OpenGL.</summary>
        /// <param name="viewingDistance">The viewing distance in meters.</param>
        internal Camera(double viewingDistance)
        {
            const double degrees = 0.0174532925199433;

            this.Position               = OpenBveApi.Math.Vector3.Null;
            this.Orientation            = OpenBveApi.Math.Orientation3.Default;
            this.HorizontalViewingAngle = 45.0 * degrees;
            this.VerticalViewingAngle   = 45.0 * degrees;
            this.ViewingDistance        = viewingDistance;
        }
コード例 #11
0
ファイル: Sounds.cs プロジェクト: zbx1425/OpenBVE
        /// <summary>Register the position to play microphone input.</summary>
        /// <param name="position">The position.</param>
        /// <param name="backwardTolerance">allowed tolerance in the backward direction</param>
        /// <param name="forwardTolerance">allowed tolerance in the forward direction</param>
        public void PlayMicSound(OpenBveApi.Math.Vector3 position, double backwardTolerance, double forwardTolerance)
        {
            if (OpenAlMic == null)
            {
                // This hardware has no AudioCapture device.
                return;
            }

            MicSources.Add(new MicSource(OpenAlMic, MicStore, position, backwardTolerance, forwardTolerance));
        }
コード例 #12
0
ファイル: Doors.cs プロジェクト: xfleet/OpenBVE
        /// <summary>Opens the left-hand or right-hand doors within a specific car in a specified train</summary>
        /// <param name="Train">The train</param>
        /// <param name="CarIndex">Car Index number - 1</param>
        /// <param name="Left">Whether to open the left-hand doors</param>
        /// <param name="Right">Whether to open the right-hand doors</param>
        internal static void OpenTrainDoors(Train Train, int CarIndex, bool Left, bool Right)
        {
            bool sl = false, sr = false;

            if (Left & !Train.Cars[CarIndex].Doors[0].AnticipatedOpen & (Train.SafetySystems.DoorInterlockState == DoorInterlockStates.Left | Train.SafetySystems.DoorInterlockState == DoorInterlockStates.Unlocked))
            {
                Train.Cars[CarIndex].Doors[0].AnticipatedOpen = true;
                sl = true;
            }
            if (Right & !Train.Cars[CarIndex].Doors[1].AnticipatedOpen & (Train.SafetySystems.DoorInterlockState == DoorInterlockStates.Right | Train.SafetySystems.DoorInterlockState == DoorInterlockStates.Unlocked))
            {
                Train.Cars[CarIndex].Doors[1].AnticipatedOpen = true;
                sr = true;
            }
            if (sl)
            {
                SoundBuffer buffer = Train.Cars[CarIndex].Doors[0].OpenSound.Buffer;
                if (buffer != null)
                {
                    OpenBveApi.Math.Vector3 pos = Train.Cars[CarIndex].Doors[0].OpenSound.Position;
                    Program.Sounds.PlaySound(buffer, Train.Cars[CarIndex].Specs.DoorOpenPitch, 1.0, pos, Train.Cars[CarIndex], false);
                }
                for (int i = 0; i < Train.Cars[CarIndex].Doors.Length; i++)
                {
                    if (Train.Cars[CarIndex].Doors[i].Direction == -1)
                    {
                        Train.Cars[CarIndex].Doors[i].DoorLockDuration = 0.0;
                    }
                }
            }
            if (sr)
            {
                SoundBuffer buffer = Train.Cars[CarIndex].Doors[1].OpenSound.Buffer;
                if (buffer != null)
                {
                    OpenBveApi.Math.Vector3 pos = Train.Cars[CarIndex].Doors[1].OpenSound.Position;
                    Program.Sounds.PlaySound(buffer, Train.Cars[CarIndex].Specs.DoorOpenPitch, 1.0, pos, Train.Cars[CarIndex], false);
                }
                for (int i = 0; i < Train.Cars[CarIndex].Doors.Length; i++)
                {
                    if (Train.Cars[CarIndex].Doors[i].Direction == 1)
                    {
                        Train.Cars[CarIndex].Doors[i].DoorLockDuration = 0.0;
                    }
                }
            }
            for (int i = 0; i < Train.Cars[CarIndex].Doors.Length; i++)
            {
                if (Train.Cars[CarIndex].Doors[i].AnticipatedOpen)
                {
                    Train.Cars[CarIndex].Doors[i].NextReopenTime = 0.0;
                    Train.Cars[CarIndex].Doors[i].ReopenCounter++;
                }
            }
        }
コード例 #13
0
ファイル: ProgramS.cs プロジェクト: tsdworks/RAGLINK-2
 // reset camera
 internal static void ResetCamera()
 {
     World.AbsoluteCameraPosition  = new Vector3(-5.0, 2.5, -25.0);
     World.AbsoluteCameraDirection = new Vector3(-World.AbsoluteCameraPosition.X, -World.AbsoluteCameraPosition.Y, -World.AbsoluteCameraPosition.Z);
     World.AbsoluteCameraSide      = new Vector3(-World.AbsoluteCameraPosition.Z, 0.0, World.AbsoluteCameraPosition.X);
     World.AbsoluteCameraDirection.Normalize();
     World.AbsoluteCameraSide.Normalize();
     World.AbsoluteCameraUp             = Vector3.Cross(World.AbsoluteCameraDirection, World.AbsoluteCameraSide);
     World.VerticalViewingAngle         = 45.0 * 0.0174532925199433;
     World.HorizontalViewingAngle       = 2.0 * Math.Atan(Math.Tan(0.5 * World.VerticalViewingAngle) * World.AspectRatio);
     World.OriginalVerticalViewingAngle = World.VerticalViewingAngle;
 }
コード例 #14
0
ファイル: Sounds.SoundSource.cs プロジェクト: sladen/openbve
 // --- constructors ---
 /// <summary>Creates a new sound source.</summary>
 /// <param name="buffer">The sound buffer.</param>
 /// <param name="radius">The effective sound radius.</param>
 /// <param name="pitch">The pitch change factor.</param>
 /// <param name="volume">The volume change factor.</param>
 /// <param name="position">The position. If a train and car are specified, the position is relative to the car, otherwise absolute.</param>
 /// <param name="train">The train this sound source is attached to, or a null reference.</param>
 /// <param name="car">The car this sound source is attached to, or a null reference.</param>
 /// <param name="looped">Whether this sound source plays in a loop.</param>
 internal SoundSource(SoundBuffer buffer, double radius, double pitch, double volume, OpenBveApi.Math.Vector3 position, TrainManager.Train train, int car, bool looped)
 {
     this.Buffer = buffer;
     this.Radius = radius;
     this.Pitch = pitch;
     this.Volume = volume;
     this.Position = position;
     this.Train = train;
     this.Car = car;
     this.Looped = looped;
     this.State = SoundSourceState.PlayPending;
     this.OpenAlSourceName = 0;
 }
コード例 #15
0
 // --- constructors ---
 /// <summary>Creates a new sound source.</summary>
 /// <param name="buffer">The sound buffer.</param>
 /// <param name="radius">The effective sound radius.</param>
 /// <param name="pitch">The pitch change factor.</param>
 /// <param name="volume">The volume change factor.</param>
 /// <param name="position">The position. If a train and car are specified, the position is relative to the car, otherwise absolute.</param>
 /// <param name="train">The train this sound source is attached to, or a null reference.</param>
 /// <param name="car">The car this sound source is attached to, or a null reference.</param>
 /// <param name="looped">Whether this sound source plays in a loop.</param>
 internal SoundSource(SoundBuffer buffer, double radius, double pitch, double volume, OpenBveApi.Math.Vector3 position, TrainManager.Train train, int car, bool looped)
 {
     this.Buffer           = buffer;
     this.Radius           = radius;
     this.Pitch            = pitch;
     this.Volume           = volume;
     this.Position         = position;
     this.Train            = train;
     this.Car              = car;
     this.Looped           = looped;
     this.State            = SoundSourceState.PlayPending;
     this.OpenAlSourceName = 0;
 }
コード例 #16
0
            // --- constructors ---
            /// <summary>Creates a new microphone source.</summary>
            /// <param name="position">The position.</param>
            /// <param name="backwardTolerance">allowed tolerance in the backward direction</param>
            /// <param name="forwardTolerance">allowed tolerance in the forward direction</param>
            internal MicSource(OpenBveApi.Math.Vector3 position, double backwardTolerance, double forwardTolerance)
            {
                this.Position          = position;
                this.BackwardTolerance = backwardTolerance;
                this.ForwardTolerance  = forwardTolerance;
                AL.GenSources(1, out OpenAlSourceName);

                // Prepare for monitoring the playback state.
                int dummyBuffer = AL.GenBuffer();

                AL.BufferData(dummyBuffer, OpenAlMic.SampleFormat, MicStore, 0, OpenAlMic.SampleFrequency);
                AL.SourceQueueBuffer(OpenAlSourceName, dummyBuffer);
                AL.SourcePlay(OpenAlSourceName);

                AL.Source(OpenAlSourceName, ALSourceb.SourceRelative, true);
            }
コード例 #17
0
ファイル: Renderer.Functions.cs プロジェクト: xfleet/OpenBVE
 /// <summary>Resets the renderer to the default state</summary>
 public static void Reset()
 {
     Objects                               = new RendererObject[256];
     ObjectCount                           = 0;
     StaticOpaque                          = new ObjectGroup[] { };
     DynamicOpaque                         = new ObjectList();
     DynamicAlpha                          = new ObjectList();
     OverlayOpaque                         = new ObjectList();
     OverlayAlpha                          = new ObjectList();
     OptionLighting                        = true;
     OptionAmbientColor                    = new Color24(160, 160, 160);
     OptionDiffuseColor                    = new Color24(160, 160, 160);
     OptionLightPosition                   = new Vector3(0.215920077052065f, 0.875724044222352f, -0.431840154104129f);
     OptionLightingResultingAmount         = 1.0f;
     GL.Disable(EnableCap.Fog); FogEnabled = false;
 }
コード例 #18
0
            /// <inheritdoc/>
            public override void CloseDoors(bool Left, bool Right)
            {
                bool sl = false, sr = false;

                for (int i = 0; i < Cars.Length; i++)
                {
                    if (Left & Cars[i].Doors[0].AnticipatedOpen & (SafetySystems.DoorInterlockState == DoorInterlockStates.Left | SafetySystems.DoorInterlockState == DoorInterlockStates.Unlocked))
                    {
                        Cars[i].Doors[0].AnticipatedOpen = false;
                        sl = true;
                    }

                    if (Right & Cars[i].Doors[1].AnticipatedOpen & (SafetySystems.DoorInterlockState == DoorInterlockStates.Right | SafetySystems.DoorInterlockState == DoorInterlockStates.Unlocked))
                    {
                        Cars[i].Doors[1].AnticipatedOpen = false;
                        sr = true;
                    }
                }

                if (sl)
                {
                    for (int i = 0; i < Cars.Length; i++)
                    {
                        SoundBuffer buffer = Cars[i].Doors[0].CloseSound.Buffer;
                        if (buffer != null)
                        {
                            OpenBveApi.Math.Vector3 pos = Cars[i].Doors[0].CloseSound.Position;
                            Program.Sounds.PlaySound(buffer, Cars[i].Specs.DoorClosePitch, 1.0, pos, Cars[i], false);
                        }
                    }
                }

                if (sr)
                {
                    for (int i = 0; i < Cars.Length; i++)
                    {
                        SoundBuffer buffer = Cars[i].Doors[1].CloseSound.Buffer;
                        if (buffer != null)
                        {
                            OpenBveApi.Math.Vector3 pos = Cars[i].Doors[1].CloseSound.Position;
                            Program.Sounds.PlaySound(buffer, Cars[i].Specs.DoorClosePitch, 1.0, pos, Cars[i], false);
                        }
                    }
                }
            }
コード例 #19
0
        /// <summary>Applies a reverser notch</summary>
        /// <param name="Train">The train</param>
        /// <param name="Value">The notch to apply</param>
        /// <param name="Relative">Whether this is an absolute value or relative to the previous</param>
        internal static void ApplyReverser(Train Train, int Value, bool Relative)
        {
            int a = (int)Train.Handles.Reverser.Driver;
            int r = Relative ? a + Value : Value;

            if (r < -1)
            {
                r = -1;
            }
            if (r > 1)
            {
                r = 1;
            }
            if (a != r)
            {
                Train.Handles.Reverser.Driver = (ReverserPosition)r;
                if (Train.Plugin != null)
                {
                    Train.Plugin.UpdateReverser();
                }
                Game.AddBlackBoxEntry(Game.BlackBoxEventToken.None);
                // sound
                if (a == 0 & r != 0)
                {
                    Sounds.SoundBuffer buffer = Train.Cars[Train.DriverCar].Sounds.ReverserOn.Buffer;
                    if (buffer == null)
                    {
                        return;
                    }
                    OpenBveApi.Math.Vector3 pos = Train.Cars[Train.DriverCar].Sounds.ReverserOn.Position;
                    Sounds.PlaySound(buffer, 1.0, 1.0, pos, Train, Train.DriverCar, false);
                }
                else if (a != 0 & r == 0)
                {
                    Sounds.SoundBuffer buffer = Train.Cars[Train.DriverCar].Sounds.ReverserOff.Buffer;
                    if (buffer == null)
                    {
                        return;
                    }
                    OpenBveApi.Math.Vector3 pos = Train.Cars[Train.DriverCar].Sounds.ReverserOff.Position;
                    Sounds.PlaySound(buffer, 1.0, 1.0, pos, Train, Train.DriverCar, false);
                }
            }
        }
コード例 #20
0
ファイル: Functions.cs プロジェクト: NeXuSTrain/OpenBVE
 /// <summary>
 /// Resets the state of the renderer
 /// </summary>
 internal static void Reset()
 {
     LoadTexturesImmediately = LoadTextureImmediatelyMode.NotYet;
     Objects                       = new Object[256];
     ObjectCount                   = 0;
     StaticOpaque                  = new ObjectGroup[] { };
     StaticOpaqueForceUpdate       = true;
     DynamicOpaque                 = new ObjectList();
     DynamicAlpha                  = new ObjectList();
     OverlayOpaque                 = new ObjectList();
     OverlayAlpha                  = new ObjectList();
     OptionLighting                = true;
     OptionAmbientColor            = new Color24(160, 160, 160);
     OptionDiffuseColor            = new Color24(160, 160, 160);
     OptionLightPosition           = new Vector3(0.223606797749979f, 0.86602540378444f, -0.447213595499958f);
     OptionLightingResultingAmount = 1.0f;
     OptionClock                   = false;
     OptionBrakeSystems            = false;
 }
コード例 #21
0
ファイル: Doors.cs プロジェクト: tsdworks/RAGLINK-2
        /// <summary>Closes the left-hand or right-hand doors for the specified train</summary>
        /// <param name="Train">The train</param>
        /// <param name="Left">Whether to close the left-hand doors</param>
        /// <param name="Right">Whether to close the right-hand doors</param>
        internal static void CloseTrainDoors(Train Train, bool Left, bool Right)
        {
            bool sl = false, sr = false;

            for (int i = 0; i < Train.Cars.Length; i++)
            {
                if (Left & Train.Cars[i].Doors[0].AnticipatedOpen)
                {
                    Train.Cars[i].Doors[0].AnticipatedOpen = false;
                    sl = true;
                }
                if (Right & Train.Cars[i].Doors[1].AnticipatedOpen)
                {
                    Train.Cars[i].Doors[1].AnticipatedOpen = false;
                    sr = true;
                }
            }
            if (sl)
            {
                for (int i = 0; i < Train.Cars.Length; i++)
                {
                    Sounds.SoundBuffer buffer = Train.Cars[i].Doors[0].CloseSound.Buffer;
                    if (buffer != null)
                    {
                        OpenBveApi.Math.Vector3 pos = Train.Cars[i].Doors[0].CloseSound.Position;
                        Sounds.PlaySound(buffer, Train.Cars[i].Specs.DoorClosePitch, 1.0, pos, Train, i, false);
                    }
                }
            }
            if (sr)
            {
                for (int i = 0; i < Train.Cars.Length; i++)
                {
                    Sounds.SoundBuffer buffer = Train.Cars[i].Doors[1].CloseSound.Buffer;
                    if (buffer != null)
                    {
                        OpenBveApi.Math.Vector3 pos = Train.Cars[i].Doors[1].CloseSound.Position;
                        Sounds.PlaySound(buffer, Train.Cars[i].Specs.DoorClosePitch, 1.0, pos, Train, i, false);
                    }
                }
            }
        }
コード例 #22
0
 /// <summary>May be called from a .Net plugin, in order to play a sound from a specific car of a train</summary>
 /// <param name="index">The plugin-based of the sound to play</param>
 /// <param name="volume">The volume of the sound- A volume of 1.0 represents nominal volume</param>
 /// <param name="pitch">The pitch of the sound- A pitch of 1.0 represents nominal pitch</param>
 /// <param name="looped">Whether the sound is looped</param>
 /// <param name="CarIndex">The index of the car which is to emit the sound</param>
 /// <returns>The sound handle, or null if not successful</returns>
 internal SoundHandleEx PlaySound(int index, double volume, double pitch, bool looped, int CarIndex)
 {
     if (index >= 0 && index < this.Train.Cars[this.Train.DriverCar].Sounds.Plugin.Length && this.Train.Cars[this.Train.DriverCar].Sounds.Plugin[index].Buffer != null && CarIndex < this.Train.Cars.Length && CarIndex >= 0)
     {
         Sounds.SoundBuffer buffer        = this.Train.Cars[CarIndex].Sounds.Plugin[index].Buffer;
         OpenBveApi.Math.Vector3 position = this.Train.Cars[CarIndex].Sounds.Plugin[index].Position;
         Sounds.SoundSource source        = Sounds.PlaySound(buffer, pitch, volume, position, this.Train, CarIndex, looped);
         if (this.SoundHandlesCount == this.SoundHandles.Length)
         {
             Array.Resize <SoundHandleEx>(ref this.SoundHandles, this.SoundHandles.Length << 1);
         }
         this.SoundHandles[this.SoundHandlesCount] = new SoundHandleEx(volume, pitch, source);
         this.SoundHandlesCount++;
         return(this.SoundHandles[this.SoundHandlesCount - 1]);
     }
     else
     {
         return(null);
     }
 }
コード例 #23
0
ファイル: ProgramS.cs プロジェクト: tsdworks/RAGLINK-2
 internal static void MouseEvent(object sender, MouseButtonEventArgs e)
 {
     MouseCameraPosition  = World.AbsoluteCameraPosition;
     MouseCameraDirection = World.AbsoluteCameraDirection;
     MouseCameraUp        = World.AbsoluteCameraUp;
     MouseCameraSide      = World.AbsoluteCameraSide;
     if (e.Button == OpenTK.Input.MouseButton.Left)
     {
         MouseButton = e.Mouse.LeftButton == ButtonState.Pressed ? 1 : 0;
     }
     if (e.Button == OpenTK.Input.MouseButton.Right)
     {
         MouseButton = e.Mouse.RightButton == ButtonState.Pressed ? 2 : 0;
     }
     if (e.Button == OpenTK.Input.MouseButton.Middle)
     {
         MouseButton = e.Mouse.RightButton == ButtonState.Pressed ? 3 : 0;
     }
     previousMouseState = Mouse.GetState();
 }
コード例 #24
0
ファイル: Renderer.cs プロジェクト: tsdworks/RAGLINK-2
        private static void RenderFace(ref ObjectFace Face, Vector3 Camera, bool IsDebugTouchMode = false)
        {
            if (CullEnabled)
            {
                if (!OptionBackfaceCulling || (ObjectManager.Objects[Face.ObjectIndex].Mesh.Faces[Face.FaceIndex].Flags & MeshFace.Face2Mask) != 0)
                {
                    GL.Disable(EnableCap.CullFace);
                    CullEnabled = false;
                }
            }
            else if (OptionBackfaceCulling)
            {
                if ((ObjectManager.Objects[Face.ObjectIndex].Mesh.Faces[Face.FaceIndex].Flags & MeshFace.Face2Mask) == 0)
                {
                    GL.Enable(EnableCap.CullFace);
                    CullEnabled = true;
                }
            }
            int r = (int)ObjectManager.Objects[Face.ObjectIndex].Mesh.Faces[Face.FaceIndex].Material;

            RenderFace(ref ObjectManager.Objects[Face.ObjectIndex].Mesh.Materials[r], ObjectManager.Objects[Face.ObjectIndex].Mesh.Vertices, Face.Wrap, ref ObjectManager.Objects[Face.ObjectIndex].Mesh.Faces[Face.FaceIndex], Camera, IsDebugTouchMode);
        }
コード例 #25
0
ファイル: Sounds.SoundSource.cs プロジェクト: leezer3/OpenBVE
			// --- constructors ---
			/// <summary>Creates a new sound source.</summary>
			/// <param name="buffer">The sound buffer.</param>
			/// <param name="radius">The effective sound radius.</param>
			/// <param name="pitch">The pitch change factor.</param>
			/// <param name="volume">The volume change factor.</param>
			/// <param name="position">The position. If a train and car are specified, the position is relative to the car, otherwise absolute.</param>
			/// <param name="train">The train this sound source is attached to, or a null reference.</param>
			/// <param name="car">The car this sound source is attached to, or a null reference.</param>
			/// <param name="looped">Whether this sound source plays in a loop.</param>
			internal SoundSource(SoundBuffer buffer, double radius, double pitch, double volume, OpenBveApi.Math.Vector3 position, TrainManager.Train train, int car, bool looped) {
				this.Buffer = buffer;
				this.Radius = radius;
				this.Pitch = pitch;
				this.Volume = volume;
				this.Position = position;
				this.Train = train;
				this.Car = car;
				this.Looped = looped;
				this.State = SoundSourceState.PlayPending;
				this.OpenAlSourceName = 0;
				//Set the sound type to undefined to use Michelle's original processing
				if (train != null)
				{
					this.Type = SoundType.TrainCar;
				}
				else
				{
					this.Type = SoundType.Undefined;	
				}
				
			}
コード例 #26
0
ファイル: Renderer.Lighting.cs プロジェクト: sladen/openbve2
 private static void UpdateLighting(double secondsSinceMidnight)
 {
     if (RoundTheClockLighting) {
         double hour = (secondsSinceMidnight % 86400.0) / 3600.0;
         LightAmbientColor = OpenBveApi.Color.ColorRGB.Black;
         LightDiffuseColor = OpenBveApi.Color.ColorRGB.Black;
         double sunIntensity;
         double moonIntensity;
         /* The sun */
         {
             double sunAngle = secondsSinceMidnight * 2.0 * Math.PI / 86400.0;
             SunPosition = new OpenBveApi.Math.Vector3(Math.Sin(sunAngle), -Math.Cos(sunAngle), 0.0);
             double r = 0.6 * Math.Max(0.0, Math.Min(1.0, SunPosition.Y + 0.18));
             double g = 0.6 * Math.Max(0.0, Math.Min(1.0, SunPosition.Y + 0.09));
             double b = 0.6 * Math.Max(0.0, Math.Min(1.0, SunPosition.Y + 0.03));
             sunIntensity = (r + g + b) / 3.0;
             LightAmbientColor += new OpenBveApi.Color.ColorRGB((float)r, (float)g, (float)b);
             LightDiffuseColor += new OpenBveApi.Color.ColorRGB((float)r, (float)g, (float)b);
         }
         /* The moon */
         {
             double moonAngle = secondsSinceMidnight * 2.0 * Math.PI / 86400.0 + 0.9 * Math.PI;
             MoonPosition = new OpenBveApi.Math.Vector3(0.0, -Math.Cos(moonAngle), Math.Sin(moonAngle));
             double r = Math.Max(0.0, Math.Min(1.0, 0.05 * MoonPosition.Y + 0.12));
             double g = Math.Max(0.0, Math.Min(1.0, 0.07 * MoonPosition.Y + 0.12));
             double b = Math.Max(0.0, Math.Min(1.0, 0.13 * MoonPosition.Y + 0.12));
             moonIntensity = (r + g + b) / 3.0;
             LightAmbientColor += new OpenBveApi.Color.ColorRGB((float)r, (float)g, (float)b);
             LightDiffuseColor += new OpenBveApi.Color.ColorRGB((float)r, (float)g, (float)b);
         }
         double sunFactor = sunIntensity / (sunIntensity + moonIntensity);
         double moonFactor = moonIntensity / (sunIntensity + moonIntensity);
         LightPosition = SunPosition * sunFactor + MoonPosition * moonFactor;
         LightPosition.Normalize();
     }
 }
コード例 #27
0
ファイル: Station.cs プロジェクト: piotrulos/OpenBVE
 internal override void Trigger(int Direction, EventTriggerType TriggerType, TrainManager.Train Train, int CarIndex)
 {
     if (TriggerType == EventTriggerType.FrontCarFrontAxle)
     {
         if (Direction > 0)
         {
             int d = Train.DriverCar;
             Sounds.SoundBuffer buffer = Train.Cars[d].Sounds.Halt.Buffer;
             if (buffer != null)
             {
                 OpenBveApi.Math.Vector3 pos = Train.Cars[d].Sounds.Halt.Position;
                 if (Train.Specs.PassAlarm == TrainManager.PassAlarmType.Single)
                 {
                     Train.Cars[d].Sounds.Halt.Source = Sounds.PlaySound(buffer, 1.0, 1.0, pos, Train, d, false);
                 }
                 else if (Train.Specs.PassAlarm == TrainManager.PassAlarmType.Loop)
                 {
                     Train.Cars[d].Sounds.Halt.Source = Sounds.PlaySound(buffer, 1.0, 1.0, pos, Train, d, true);
                 }
             }
             this.DontTriggerAnymore = true;
         }
     }
 }
コード例 #28
0
ファイル: Doors.cs プロジェクト: tsdworks/RAGLINK-2
        /// <summary>Is called once a frame, to update the door states of the specified train</summary>
        /// <param name="Train">The train</param>
        /// <param name="TimeElapsed">The frame time elapsed</param>
        private static void UpdateTrainDoors(Train Train, double TimeElapsed)
        {
            OpenBveApi.Runtime.DoorStates oldState = OpenBveApi.Runtime.DoorStates.None;
            OpenBveApi.Runtime.DoorStates newState = OpenBveApi.Runtime.DoorStates.None;
            for (int i = 0; i < Train.Cars.Length; i++)
            {
                bool   ld = Train.Cars[i].Doors[0].AnticipatedOpen;
                bool   rd = Train.Cars[i].Doors[1].AnticipatedOpen;
                double os = Train.Cars[i].Specs.DoorOpenFrequency;
                double cs = Train.Cars[i].Specs.DoorCloseFrequency;

                for (int j = 0; j < Train.Cars[i].Doors.Length; j++)
                {
                    if (Train.Cars[i].Doors[j].Direction == -1 | Train.Cars[i].Doors[j].Direction == 1)
                    {
                        bool shouldBeOpen = Train.Cars[i].Doors[j].Direction == -1 ? ld : rd;
                        if (Train.Cars[i].Doors[j].State > 0.0)
                        {
                            if (Train.Cars[i].Doors[j].Direction == -1)
                            {
                                oldState |= OpenBveApi.Runtime.DoorStates.Left;
                            }
                            else
                            {
                                oldState |= OpenBveApi.Runtime.DoorStates.Right;
                            }
                        }
                        if (shouldBeOpen)
                        {
                            // open
                            Train.Cars[i].Doors[j].State += os * TimeElapsed;
                            if (Train.Cars[i].Doors[j].State > 1.0)
                            {
                                Train.Cars[i].Doors[j].State = 1.0;
                            }
                        }
                        else
                        {
                            // close
                            if (Train.Cars[i].Doors[j].DoorLockDuration > 0.0)
                            {
                                if (Train.Cars[i].Doors[j].State > Train.Cars[i].Doors[j].DoorLockState)
                                {
                                    Train.Cars[i].Doors[j].State -= cs * TimeElapsed;
                                }
                                if (Train.Cars[i].Doors[j].State < Train.Cars[i].Doors[j].DoorLockState)
                                {
                                    Train.Cars[i].Doors[j].State = Train.Cars[i].Doors[j].DoorLockState;
                                }
                                Train.Cars[i].Doors[j].DoorLockDuration -= TimeElapsed;
                                if (Train.Cars[i].Doors[j].DoorLockDuration < 0.0)
                                {
                                    Train.Cars[i].Doors[j].DoorLockDuration = 0.0;
                                }
                            }
                            else
                            {
                                Train.Cars[i].Doors[j].State -= cs * TimeElapsed;
                            }
                            if (Train.Cars[i].Doors[j].AnticipatedReopen && Train.Cars[i].Doors[j].State < Train.Cars[i].Doors[j].InterferingObjectRate)
                            {
                                Train.Cars[i].Doors[j].State = Train.Cars[i].Doors[j].InterferingObjectRate;
                            }
                            if (Train.Cars[i].Doors[j].State < 0.0)
                            {
                                Train.Cars[i].Doors[j].State = 0.0;
                            }
                        }
                        if (Train.Cars[i].Doors[j].State > 0.0)
                        {
                            if (Train.Cars[i].Doors[j].Direction == -1)
                            {
                                newState |= OpenBveApi.Runtime.DoorStates.Left;
                            }
                            else
                            {
                                newState |= OpenBveApi.Runtime.DoorStates.Right;
                            }
                        }
                    }
                }
            }

            if (oldState != OpenBveApi.Runtime.DoorStates.None & newState == OpenBveApi.Runtime.DoorStates.None)
            {
                Sounds.SoundBuffer buffer = Train.Cars[Train.DriverCar].Sounds.PilotLampOn.Buffer;
                if (buffer != null)
                {
                    OpenBveApi.Math.Vector3 pos = Train.Cars[Train.DriverCar].Sounds.PilotLampOn.Position;
                    Sounds.PlaySound(buffer, 1.0, 1.0, pos, Train, Train.DriverCar, false);
                }
            }
            else if (oldState == OpenBveApi.Runtime.DoorStates.None & newState != OpenBveApi.Runtime.DoorStates.None)
            {
                Sounds.SoundBuffer buffer = Train.Cars[Train.DriverCar].Sounds.PilotLampOff.Buffer;
                if (buffer != null)
                {
                    OpenBveApi.Math.Vector3 pos = Train.Cars[Train.DriverCar].Sounds.PilotLampOff.Position;
                    Sounds.PlaySound(buffer, 1.0, 1.0, pos, Train, Train.DriverCar, false);
                }
            }
            if (oldState != newState)
            {
                if (Train.Plugin != null)
                {
                    Train.Plugin.DoorChange(oldState, newState);
                }
            }
        }
コード例 #29
0
ファイル: GameWindow.cs プロジェクト: perhenrik90/OpenBVE
        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;
            lock (Program.LockObj)
            {
                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);
                Program.Renderer.Camera.AbsoluteDirection.Rotate(Vector3.Down, cosa, sina);
                Program.Renderer.Camera.AbsoluteUp.Rotate(Vector3.Down, cosa, sina);
                Program.Renderer.Camera.AbsoluteSide.Rotate(Vector3.Down, 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);
                Program.Renderer.Camera.AbsoluteDirection.Rotate(Program.Renderer.Camera.AbsoluteSide, cosa, sina);
                Program.Renderer.Camera.AbsoluteUp.Rotate(Program.Renderer.Camera.AbsoluteSide, 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)
            {
                Program.Renderer.Camera.AbsolutePosition += MoveXSpeed * timeElapsed * Program.Renderer.Camera.AbsoluteSide;
                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)
            {
                Program.Renderer.Camera.AbsolutePosition += MoveYSpeed * timeElapsed * Program.Renderer.Camera.AbsoluteUp;
                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)
            {
                Program.Renderer.Camera.AbsolutePosition += MoveZSpeed * timeElapsed * Program.Renderer.Camera.AbsoluteDirection;

                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;
                    Program.Renderer.Camera.AbsoluteSide.Y = 0.0;
                    Program.Renderer.Camera.AbsoluteSide.Normalize();
                    Program.Renderer.Camera.AbsoluteDirection.Normalize();
                    Program.Renderer.Camera.AbsoluteUp = Vector3.Cross(Program.Renderer.Camera.AbsoluteDirection, Program.Renderer.Camera.AbsoluteSide);
                }
                else
                {
                    ReducedModeEnteringTime -= timeElapsed;
                }
            }
            if (updatelight)
            {
                Program.Renderer.Lighting.OptionAmbientColor.R = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative * (2.0 - Program.LightingRelative));
                Program.Renderer.Lighting.OptionAmbientColor.G = (byte)Math.Round(32.0 + 128.0 * 0.5 * (Program.LightingRelative + Program.LightingRelative * (2.0 - Program.LightingRelative)));
                Program.Renderer.Lighting.OptionAmbientColor.B = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative);
                Program.Renderer.Lighting.OptionDiffuseColor.R = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative);
                Program.Renderer.Lighting.OptionDiffuseColor.G = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative);
                Program.Renderer.Lighting.OptionDiffuseColor.B = (byte)Math.Round(32.0 + 128.0 * Math.Sqrt(Program.LightingRelative));
            }
            Program.Renderer.Lighting.Initialize();
            Program.Renderer.RenderScene();
            SwapBuffers();
        }
コード例 #30
0
ファイル: ObjectGrid.cs プロジェクト: sladen/openbve2
            /// <summary>Creates or updates the display list for the static objects. If the display list already exists, it is recreated.</summary>
            internal void CreateOrUpdateDisplayList()
            {
                /*
                 * Load all textures used by the objects in this leaf node.
                 * */
                this.LoadTextures();
                /*
                 * Begin rendering to the display list.
                 * */
                Renderer.OpenGlState state;
                this.DisplayList.Begin(out state);
                /*
                 * Render all attached static objects.
                 * */
                Renderer.RenderStaticOpaqueObjects(this.StaticOpaqueObjects, this.StaticOpaqueObjectCount, ref state);
                if (Program.CurrentOptions.ShowGrid) {
                    /*
                     * Render the rectangle and bounding rectangle for debugging purposes.
                     * */
                    OpenBveApi.Color.ColorRGB brightColor = new OpenBveApi.Color.ColorRGB(
                        (float)Program.RandomNumberGenerator.NextDouble(),
                        (float)Program.RandomNumberGenerator.NextDouble(),
                        (float)Program.RandomNumberGenerator.NextDouble()
                    );
                    OpenBveApi.Color.ColorRGB darkColor = new OpenBveApi.Color.ColorRGB(
                        0.5f * brightColor.R,
                        0.5f * brightColor.G,
                        0.5f * brightColor.B
                    );
                    { /* Render the rectangle. */
                        double x = 0.5 * (this.Rectangle.Right - this.Rectangle.Left);
                        double z = 0.5 * (this.Rectangle.Far - this.Rectangle.Near);
                        OpenBveApi.Math.Vector3[] vertices = new OpenBveApi.Math.Vector3[] {
                            new OpenBveApi.Math.Vector3(-x, -1.1, -z),
                            new OpenBveApi.Math.Vector3(-x, -1.1, z),
                            new OpenBveApi.Math.Vector3(x, -1.1, z),
                            new OpenBveApi.Math.Vector3(x, -1.1, -z)
                        };
                        Renderer.RenderPolygonFromVertices(vertices, darkColor, OpenBveApi.Color.ColorRGB.Black, ref state);
                    }
                    { /* Render the bounding rectangle. */
                        OpenBveApi.Math.Vector2 center = new OpenBveApi.Math.Vector2(
                            0.5 * (this.Rectangle.Left + this.Rectangle.Right),
                            0.5 * (this.Rectangle.Near + this.Rectangle.Far)
                        );
                        OpenBveApi.Math.Vector2 nearLeft = new OpenBveApi.Math.Vector2(
                            this.BoundingRectangle.Left - center.X,
                            this.BoundingRectangle.Near - center.Y
                        );
                        OpenBveApi.Math.Vector2 nearRight = new OpenBveApi.Math.Vector2(
                            this.BoundingRectangle.Right - center.X,
                            this.BoundingRectangle.Near - center.Y
                        );
                        OpenBveApi.Math.Vector2 farLeft = new OpenBveApi.Math.Vector2(
                            this.BoundingRectangle.Left - center.X,
                            this.BoundingRectangle.Far - center.Y
                        );
                        OpenBveApi.Math.Vector2 farRight = new OpenBveApi.Math.Vector2(
                            this.BoundingRectangle.Right - center.X,
                            this.BoundingRectangle.Far - center.Y
                        );
                        OpenBveApi.Math.Vector3[] vertices = new OpenBveApi.Math.Vector3[] {
                            new OpenBveApi.Math.Vector3(nearLeft.X, -1.0, nearLeft.Y),
                            new OpenBveApi.Math.Vector3(farLeft.X, -1.0, farLeft.Y),
                            new OpenBveApi.Math.Vector3(farRight.X, -1.0, farRight.Y),
                            new OpenBveApi.Math.Vector3(nearRight.X, -1.0, nearRight.Y)
                        };
                        Renderer.RenderPolygonFromVertices(vertices, brightColor, OpenBveApi.Color.ColorRGB.Black, ref state);
                    }
                }

                /*
                 * End rendering to the display list.
                 * */
                this.DisplayList.End(ref state);
            }
コード例 #31
0
 // process structure
 /// <summary>Loads binary .X object data and returns a compatible mesh.</summary>
 /// <param name="fileName">The platform-specific absolute file name of the object.</param>
 /// <param name="structure">The object structure to process.</param>
 /// <param name="obj">Receives the compatible mesh.</param>
 /// <param name="encoding">The fallback encoding.</param>
 private static bool ProcessStructure(string fileName, Structure structure, out OpenBveApi.Geometry.GenericObject obj, System.Text.Encoding encoding)
 {
     System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.InvariantCulture;
     OpenBveApi.Geometry.FaceVertexMesh compatibleMesh = new OpenBveApi.Geometry.FaceVertexMesh();
     obj = null;
     /*
      * file
      */
     for (int i = 0; i < structure.Data.Length; i++) {
         Structure f = structure.Data[i] as Structure;
         if (f == null) {
             IO.ReportError(fileName, "Top-level inlined arguments are invalid");
             return false;
         }
         switch (f.Name) {
             case "Mesh":
                 {
                     /*
                      * mesh
                      */
                     if (f.Data.Length < 4) {
                         IO.ReportError(fileName, "Mesh is expected to have at least 4 arguments");
                         return false;
                     } else if (!(f.Data[0] is int)) {
                         IO.ReportError(fileName, "nVertices is expected to be a DWORD in Mesh");
                         return false;
                     } else if (!(f.Data[1] is Structure[])) {
                         IO.ReportError(fileName, "vertices[nVertices] is expected to be a Vector array in Mesh");
                         return false;
                     } else if (!(f.Data[2] is int)) {
                         IO.ReportError(fileName, "nFaces is expected to be a DWORD in Mesh");
                         return false;
                     } else if (!(f.Data[3] is Structure[])) {
                         IO.ReportError(fileName, "faces[nFaces] is expected to be a MeshFace array in Mesh");
                         return false;
                     }
                     int nVertices = (int)f.Data[0];
                     if (nVertices < 0) {
                         IO.ReportError(fileName, "nVertices is expected to be non-negative in Mesh");
                         return false;
                     }
                     Structure[] sVertices = (Structure[])f.Data[1];
                     if (nVertices != sVertices.Length) {
                         IO.ReportError(fileName, "nVertices does not match with the length of array vertices in Mesh");
                         return false;
                     }
                     int nFaces = (int)f.Data[2];
                     if (nFaces < 0) {
                         IO.ReportError(fileName, "nFaces is expected to be non-negative in Mesh");
                         return false;
                     }
                     Structure[] sFaces = (Structure[])f.Data[3];
                     if (nFaces != sFaces.Length) {
                         IO.ReportError(fileName, "nFaces does not match with the length of array faces in Mesh");
                         return false;
                     }
                     /*
                      * collect vertices
                      */
                     OpenBveApi.Geometry.Vertex[] vertices = new OpenBveApi.Geometry.Vertex[nVertices];
                     for (int j = 0; j < nVertices; j++) {
                         if (sVertices[j].Name != "Vector") {
                             IO.ReportError(fileName, "vertices[" + j.ToString(culture) + "] is expected to be of template Vertex in Mesh");
                             return false;
                         } else if (sVertices[j].Data.Length != 3) {
                             IO.ReportError(fileName, "vertices[" + j.ToString(culture) + "] is expected to have 3 arguments in Mesh");
                             return false;
                         } else if (!(sVertices[j].Data[0] is double)) {
                             IO.ReportError(fileName, "x is expected to be a float in vertices[" + j.ToString(culture) + "] in Mesh");
                             return false;
                         } else if (!(sVertices[j].Data[1] is double)) {
                             IO.ReportError(fileName, "y is expected to be a float in vertices[" + j.ToString(culture) + "] in Mesh");
                             return false;
                         } else if (!(sVertices[j].Data[2] is double)) {
                             IO.ReportError(fileName, "z is expected to be a float in vertices[" + j.ToString(culture) + "] in Mesh");
                             return false;
                         }
                         double x = (double)sVertices[j].Data[0];
                         double y = (double)sVertices[j].Data[1];
                         double z = (double)sVertices[j].Data[2];
                         vertices[j].SpatialCoordinates = new OpenBveApi.Math.Vector3(x, y, z);
                     }
                     /*
                      * collect faces
                      */
                     int[][] faces = new int[nFaces][];
                     OpenBveApi.Math.Vector3[][] faceNormals = new OpenBveApi.Math.Vector3[nFaces][];
                     int[] faceMaterials = new int[nFaces];
                     for (int j = 0; j < nFaces; j++) {
                         faceMaterials[j] = -1;
                     }
                     for (int j = 0; j < nFaces; j++) {
                         if (sFaces[j].Name != "MeshFace") {
                             IO.ReportError(fileName, "faces[" + j.ToString(culture) + "] is expected to be of template MeshFace in Mesh");
                             return false;
                         } else if (sFaces[j].Data.Length != 2) {
                             IO.ReportError(fileName, "face[" + j.ToString(culture) + "] is expected to have 2 arguments in Mesh");
                             return false;
                         } else if (!(sFaces[j].Data[0] is int)) {
                             IO.ReportError(fileName, "nFaceVertexIndices is expected to be a DWORD in face[" + j.ToString(culture) + "] in Mesh");
                             return false;
                         } else if (!(sFaces[j].Data[1] is int[])) {
                             IO.ReportError(fileName, "faceVertexIndices[nFaceVertexIndices] is expected to be a DWORD array in face[" + j.ToString(culture) + "] in Mesh");
                             return false;
                         }
                         int nFaceVertexIndices = (int)sFaces[j].Data[0];
                         if (nFaceVertexIndices < 0) {
                             IO.ReportError(fileName, "nFaceVertexIndices is expected to be non-negative in MeshFace in Mesh");
                             return false;
                         }
                         int[] faceVertexIndices = (int[])sFaces[j].Data[1];
                         if (nFaceVertexIndices != faceVertexIndices.Length) {
                             IO.ReportError(fileName, "nFaceVertexIndices does not match with the length of array faceVertexIndices in face[" + j.ToString(culture) + "] in Mesh");
                             return false;
                         }
                         faces[j] = new int[nFaceVertexIndices];
                         faceNormals[j] = new OpenBveApi.Math.Vector3[nFaceVertexIndices];
                         for (int k = 0; k < nFaceVertexIndices; k++) {
                             if (faceVertexIndices[k] < 0 | faceVertexIndices[k] >= nVertices) {
                                 IO.ReportError(fileName, "faceVertexIndices[" + k.ToString(culture) + "] does not reference a valid vertex in face[" + j.ToString(culture) + "] in Mesh");
                                 return false;
                             }
                             faces[j][k] = faceVertexIndices[k];
                             faceNormals[j][k] = new OpenBveApi.Math.Vector3(0.0f, 0.0f, 0.0f);
                         }
                     }
                     /*
                      * collect additional templates
                      */
                     Material[] materials = new Material[] { };
                     for (int j = 4; j < f.Data.Length; j++) {
                         Structure g = f.Data[j] as Structure;
                         if (g == null) {
                             IO.ReportError(fileName, "Unexpected inlined argument encountered in Mesh");
                             return false;
                         }
                         switch (g.Name) {
                             case "MeshMaterialList":
                                 {
                                     /*
                                      * meshmateriallist
                                      */
                                     if (g.Data.Length < 3) {
                                         IO.ReportError(fileName, "MeshMaterialList is expected to have at least 3 arguments in Mesh");
                                         return false;
                                     } else if (!(g.Data[0] is int)) {
                                         IO.ReportError(fileName, "nMaterials is expected to be a DWORD in MeshMaterialList in Mesh");
                                         return false;
                                     } else if (!(g.Data[1] is int)) {
                                         IO.ReportError(fileName, "nFaceIndexes is expected to be a DWORD in MeshMaterialList in Mesh");
                                         return false;
                                     } else if (!(g.Data[2] is int[])) {
                                         IO.ReportError(fileName, "faceIndexes[nFaceIndexes] is expected to be a DWORD array in MeshMaterialList in Mesh");
                                         return false;
                                     }
                                     int nMaterials = (int)g.Data[0];
                                     if (nMaterials < 0) {
                                         IO.ReportError(fileName, "nMaterials is expected to be non-negative in MeshMaterialList in Mesh");
                                         return false;
                                     }
                                     int nFaceIndexes = (int)g.Data[1];
                                     if (nFaceIndexes < 0) {
                                         IO.ReportError(fileName, "nFaceIndexes is expected to be non-negative in MeshMaterialList in Mesh");
                                         return false;
                                     } else if (nFaceIndexes > nFaces) {
                                         IO.ReportError(fileName, "nFaceIndexes does not reference valid faces in MeshMaterialList in Mesh");
                                         return false;
                                     }
                                     int[] faceIndexes = (int[])g.Data[2];
                                     if (nFaceIndexes != faceIndexes.Length) {
                                         IO.ReportError(fileName, "nFaceIndexes does not match with the length of array faceIndexes in face[" + j.ToString(culture) + "] in Mesh");
                                         return false;
                                     }
                                     for (int k = 0; k < nFaceIndexes; k++) {
                                         if (faceIndexes[k] < 0 | faceIndexes[k] >= nMaterials) {
                                             IO.ReportError(fileName, "faceIndexes[" + k.ToString(culture) + "] does not reference a valid Material template in MeshMaterialList in Mesh");
                                             return false;
                                         }
                                     }
                                     /*
                                      * collect material templates
                                      */
                                     int mn = materials.Length;
                                     Array.Resize<Material>(ref materials, mn + nMaterials);
                                     for (int k = 0; k < nMaterials; k++) {
                                         materials[mn + k].FaceColor = new OpenBveApi.Color.ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);
                                         materials[mn + k].SpecularColor = new OpenBveApi.Color.ColorRGB(0.0f, 0.0f, 0.0f);
                                         materials[mn + k].EmissiveColor = new OpenBveApi.Color.ColorRGB(0.0f, 0.0f, 0.0f);
                                         materials[mn + k].TextureFilename = null;
                                     }
                                     int materialIndex = mn;
                                     for (int k = 3; k < g.Data.Length; k++) {
                                         Structure h = g.Data[k] as Structure;
                                         if (h == null) {
                                             IO.ReportError(fileName, "Unexpected inlined argument encountered in MeshMaterialList in Mesh");
                                             return false;
                                         } else if (h.Name != "Material") {
                                             IO.ReportError(fileName, "Material template expected in MeshMaterialList in Mesh");
                                             return false;
                                         } else {
                                             /*
                                              * material
                                              */
                                             if (h.Data.Length < 4) {
                                                 IO.ReportError(fileName, "Material is expected to have at least 4 arguments in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(h.Data[0] is Structure)) {
                                                 IO.ReportError(fileName, "faceColor is expected to be a ColorRGBA in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(h.Data[1] is double)) {
                                                 IO.ReportError(fileName, "power is expected to be a float in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(h.Data[2] is Structure)) {
                                                 IO.ReportError(fileName, "specularColor is expected to be a ColorRGBA in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(h.Data[3] is Structure)) {
                                                 IO.ReportError(fileName, "emissiveColor is expected to be a ColorRGBA in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             }
                                             Structure faceColor = (Structure)h.Data[0];
                                             Structure specularColor = (Structure)h.Data[2];
                                             Structure emissiveColor = (Structure)h.Data[3];
                                             double red, green, blue, alpha;
                                             /*
                                              * collect face color
                                              */
                                             if (faceColor.Name != "ColorRGBA") {
                                                 IO.ReportError(fileName, "faceColor is expected to be a ColorRGBA in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (faceColor.Data.Length != 4) {
                                                 IO.ReportError(fileName, "faceColor is expected to have 4 arguments in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(faceColor.Data[0] is double)) {
                                                 IO.ReportError(fileName, "red is expected to be a float in faceColor in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(faceColor.Data[1] is double)) {
                                                 IO.ReportError(fileName, "green is expected to be a float in faceColor in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(faceColor.Data[2] is double)) {
                                                 IO.ReportError(fileName, "blue is expected to be a float in faceColor in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(faceColor.Data[3] is double)) {
                                                 IO.ReportError(fileName, "alpha is expected to be a float in faceColor in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             }
                                             red = (double)faceColor.Data[0];
                                             green = (double)faceColor.Data[1];
                                             blue = (double)faceColor.Data[2];
                                             alpha = (double)faceColor.Data[3];
                                             if (red < 0.0 | red > 1.0) {
                                                 IO.ReportError(fileName, "red is expected to be in the range from 0.0 to 1.0 in faceColor in Material in MeshMaterialList in Mesh");
                                                 red = red < 0.5 ? 0.0 : 1.0;
                                             }
                                             if (green < 0.0 | green > 1.0) {
                                                 IO.ReportError(fileName, "green is expected to be in the range from 0.0 to 1.0 in faceColor in Material in MeshMaterialList in Mesh");
                                                 green = green < 0.5 ? 0.0 : 1.0;
                                             }
                                             if (blue < 0.0 | blue > 1.0) {
                                                 IO.ReportError(fileName, "blue is expected to be in the range from 0.0 to 1.0 in faceColor in Material in MeshMaterialList in Mesh");
                                                 blue = blue < 0.5 ? 0.0 : 1.0;
                                             }
                                             if (alpha < 0.0 | alpha > 1.0) {
                                                 IO.ReportError(fileName, "alpha is expected to be in the range from 0.0 to 1.0 in faceColor in Material in MeshMaterialList in Mesh");
                                                 alpha = alpha < 0.5 ? 0.0 : 1.0;
                                             }
                                             materials[materialIndex].FaceColor = new OpenBveApi.Color.ColorRGBA((float)red, (float)green, (float)blue, (float)alpha);
                                             /*
                                              * collect specular color
                                              */
                                             if (specularColor.Name != "ColorRGB") {
                                                 IO.ReportError(fileName, "specularColor is expected to be a ColorRGB in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (specularColor.Data.Length != 3) {
                                                 IO.ReportError(fileName, "specularColor is expected to have 3 arguments in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(specularColor.Data[0] is double)) {
                                                 IO.ReportError(fileName, "red is expected to be a float in specularColor in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(specularColor.Data[1] is double)) {
                                                 IO.ReportError(fileName, "green is expected to be a float in specularColor in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(specularColor.Data[2] is double)) {
                                                 IO.ReportError(fileName, "blue is expected to be a float in specularColor in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             }
                                             red = (double)specularColor.Data[0];
                                             green = (double)specularColor.Data[1];
                                             blue = (double)specularColor.Data[2];
                                             if (red < 0.0 | red > 1.0) {
                                                 IO.ReportError(fileName, "red is expected to be in the range from 0.0 to 1.0 in specularColor in Material in MeshMaterialList in Mesh");
                                                 red = red < 0.5 ? 0.0 : 1.0;
                                             }
                                             if (green < 0.0 | green > 1.0) {
                                                 IO.ReportError(fileName, "green is expected to be in the range from 0.0 to 1.0 in specularColor in Material in MeshMaterialList in Mesh");
                                                 green = green < 0.5 ? 0.0 : 1.0;
                                             }
                                             if (blue < 0.0 | blue > 1.0) {
                                                 IO.ReportError(fileName, "blue is expected to be in the range from 0.0 to 1.0 in specularColor in Material in MeshMaterialList in Mesh");
                                                 blue = blue < 0.5 ? 0.0 : 1.0;
                                             }
                                             materials[materialIndex].SpecularColor = new OpenBveApi.Color.ColorRGB((float)red, (float)green, (float)blue);
                                             /*
                                              * collect emissive color
                                              */
                                             if (emissiveColor.Name != "ColorRGB") {
                                                 IO.ReportError(fileName, "emissiveColor is expected to be a ColorRGBA in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (emissiveColor.Data.Length != 3) {
                                                 IO.ReportError(fileName, "emissiveColor is expected to have 3 arguments in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(emissiveColor.Data[0] is double)) {
                                                 IO.ReportError(fileName, "red is expected to be a float in emissiveColor in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(emissiveColor.Data[1] is double)) {
                                                 IO.ReportError(fileName, "green is expected to be a float in emissiveColor in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             } else if (!(emissiveColor.Data[2] is double)) {
                                                 IO.ReportError(fileName, "blue is expected to be a float in emissiveColor in Material in MeshMaterialList in Mesh");
                                                 return false;
                                             }
                                             red = (double)emissiveColor.Data[0];
                                             green = (double)emissiveColor.Data[1];
                                             blue = (double)emissiveColor.Data[2];
                                             if (red < 0.0 | red > 1.0) {
                                                 IO.ReportError(fileName, "red is expected to be in the range from 0.0 to 1.0 in emissiveColor in Material in MeshMaterialList in Mesh");
                                                 red = red < 0.5 ? 0.0 : 1.0;
                                             }
                                             if (green < 0.0 | green > 1.0) {
                                                 IO.ReportError(fileName, "green is expected to be in the range from 0.0 to 1.0 in emissiveColor in Material in MeshMaterialList in Mesh");
                                                 green = green < 0.5 ? 0.0 : 1.0;
                                             }
                                             if (blue < 0.0 | blue > 1.0) {
                                                 IO.ReportError(fileName, "blue is expected to be in the range from 0.0 to 1.0 in emissiveColor in Material in MeshMaterialList in Mesh");
                                                 blue = blue < 0.5 ? 0.0 : 1.0;
                                             }
                                             materials[materialIndex].EmissiveColor = new OpenBveApi.Color.ColorRGB((float)red, (float)green, (float)blue);
                                             /*
                                              * collect additional templates
                                              */
                                             for (int l = 4; l < h.Data.Length; l++) {
                                                 Structure e = h.Data[l] as Structure;
                                                 if (e == null) {
                                                     IO.ReportError(fileName, "Unexpected inlined argument encountered in Material in MeshMaterialList in Mesh");
                                                     return false;
                                                 }
                                                 switch (e.Name) {
                                                     case "TextureFilename":
                                                         {
                                                             /*
                                                              * texturefilename
                                                              */
                                                             if (e.Data.Length != 1) {
                                                                 IO.ReportError(fileName, "filename is expected to have 1 argument in TextureFilename in Material in MeshMaterialList in Mesh");
                                                                 return false;
                                                             } else if (!(e.Data[0] is string)) {
                                                                 IO.ReportError(fileName, "filename is expected to be a string in TextureFilename in Material in MeshMaterialList in Mesh");
                                                                 return false;
                                                             }
                                                             string filename = (string)e.Data[0];
                                                             materials[materialIndex].TextureFilename = filename;
                                                         } break;
                                                     default:
                                                         /*
                                                          * unknown
                                                          */
                                                         IO.ReportError(fileName, "Unsupported template " + e.Name + " encountered in MeshMaterialList in Mesh");
                                                         break;
                                                 }
                                             }
                                             /*
                                              * finish
                                              */
                                             materialIndex++;
                                         }
                                     }
                                     if (materialIndex != mn + nMaterials) {
                                         IO.ReportError(fileName, "nMaterials does not match the number of Material templates encountered in Material in MeshMaterialList in Mesh");
                                         return false;
                                     }
                                     /*
                                      * assign materials
                                      */
                                     for (int k = 0; k < nFaceIndexes; k++) {
                                         faceMaterials[k] = faceIndexes[k];
                                     }
                                     if (nMaterials != 0) {
                                         for (int k = 0; k < nFaces; k++) {
                                             if (faceMaterials[k] == -1) {
                                                 faceMaterials[k] = 0;
                                             }
                                         }
                                     }
                                     /*
                                      * assign reflective colors to the vertices within each face which uses each material
                                      */
                                     for (int currentMaterial = 0; currentMaterial < materials.Length; currentMaterial++) {
                                         for (int faceIndex = 0; faceIndex < faces.Length; faceIndex++) {
                                             if (faceMaterials[faceIndex] == currentMaterial) {
                                                 foreach (int vertex in faces[faceIndex]) {
                                                     vertices[vertex].ReflectiveColor = materials[currentMaterial].FaceColor;
                                                 }
                                             }
                                         }
                                     }
                                 } break;
                             case "MeshTextureCoords":
                                 {
                                     /*
                                      * meshtexturecoords
                                      */
                                     if (g.Data.Length != 2) {
                                         IO.ReportError(fileName, "MeshTextureCoords is expected to have 2 arguments in Mesh");
                                         return false;
                                     } else if (!(g.Data[0] is int)) {
                                         IO.ReportError(fileName, "nTextureCoords is expected to be a DWORD in MeshTextureCoords in Mesh");
                                         return false;
                                     } else if (!(g.Data[1] is Structure[])) {
                                         IO.ReportError(fileName, "textureCoords[nTextureCoords] is expected to be a Coords2d array in MeshTextureCoords in Mesh");
                                         return false;
                                     }
                                     int nTextureCoords = (int)g.Data[0];
                                     Structure[] textureCoords = (Structure[])g.Data[1];
                                     if (nTextureCoords < 0 | nTextureCoords > nVertices) {
                                         IO.ReportError(fileName, "nTextureCoords does not reference valid vertices in MeshTextureCoords in Mesh");
                                         return false;
                                     }
                                     for (int k = 0; k < nTextureCoords; k++) {
                                         if (textureCoords[k].Name != "Coords2d") {
                                             IO.ReportError(fileName, "textureCoords[" + k.ToString(culture) + "] is expected to be a Coords2d in MeshTextureCoords in Mesh");
                                             return false;
                                         } else if (textureCoords[k].Data.Length != 2) {
                                             IO.ReportError(fileName, "textureCoords[" + k.ToString(culture) + "] is expected to have 2 arguments in MeshTextureCoords in Mesh");
                                             return false;
                                         } else if (!(textureCoords[k].Data[0] is double)) {
                                             IO.ReportError(fileName, "u is expected to be a float in textureCoords[" + k.ToString(culture) + "] in MeshTextureCoords in Mesh");
                                             return false;
                                         } else if (!(textureCoords[k].Data[1] is double)) {
                                             IO.ReportError(fileName, "v is expected to be a float in textureCoords[" + k.ToString(culture) + "] in MeshTextureCoords in Mesh");
                                             return false;
                                         }
                                         double u = (double)textureCoords[k].Data[0];
                                         double v = (double)textureCoords[k].Data[1];
                                         vertices[k].TextureCoordinates = new OpenBveApi.Math.Vector2(u, v);
                                     }
                                 } break;
                             case "MeshNormals":
                                 {
                                     /*
                                      * meshnormals
                                      */
                                     if (g.Data.Length != 4) {
                                         IO.ReportError(fileName, "MeshNormals is expected to have 4 arguments in Mesh");
                                         return false;
                                     } else if (!(g.Data[0] is int)) {
                                         IO.ReportError(fileName, "nNormals is expected to be a DWORD in MeshNormals in Mesh");
                                         return false;
                                     } else if (!(g.Data[1] is Structure[])) {
                                         IO.ReportError(fileName, "normals is expected to be a Vector array in MeshNormals in Mesh");
                                         return false;
                                     } else if (!(g.Data[2] is int)) {
                                         IO.ReportError(fileName, "nFaceNormals is expected to be a DWORD in MeshNormals in Mesh");
                                         return false;
                                     } else if (!(g.Data[3] is Structure[])) {
                                         IO.ReportError(fileName, "faceNormals is expected to be a MeshFace array in MeshNormals in Mesh");
                                         return false;
                                     }
                                     int nNormals = (int)g.Data[0];
                                     if (nNormals < 0) {
                                         IO.ReportError(fileName, "nNormals is expected to be non-negative in MeshNormals in Mesh");
                                         return false;
                                     }
                                     Structure[] sNormals = (Structure[])g.Data[1];
                                     if (nNormals != sNormals.Length) {
                                         IO.ReportError(fileName, "nNormals does not match with the length of array normals in MeshNormals in Mesh");
                                         return false;
                                     }
                                     int nFaceNormals = (int)g.Data[2];
                                     if (nFaceNormals < 0 | nFaceNormals > nFaces) {
                                         IO.ReportError(fileName, "nNormals does not reference valid vertices in MeshNormals in Mesh");
                                         return false;
                                     }
                                     Structure[] sFaceNormals = (Structure[])g.Data[3];
                                     if (nFaceNormals != sFaceNormals.Length) {
                                         IO.ReportError(fileName, "nFaceNormals does not match with the length of array faceNormals in MeshNormals in Mesh");
                                         return false;
                                     }
                                     /*
                                      * collect normals
                                      */
                                     OpenBveApi.Math.Vector3[] normals = new OpenBveApi.Math.Vector3[nNormals];
                                     for (int k = 0; k < nNormals; k++) {
                                         if (sNormals[k].Name != "Vector") {
                                             IO.ReportError(fileName, "normals[" + k.ToString(culture) + "] is expected to be of template Vertex in MeshNormals in Mesh");
                                             return false;
                                         } else if (sNormals[k].Data.Length != 3) {
                                             IO.ReportError(fileName, "normals[" + k.ToString(culture) + "] is expected to have 3 arguments in MeshNormals in Mesh");
                                             return false;
                                         } else if (!(sNormals[k].Data[0] is double)) {
                                             IO.ReportError(fileName, "x is expected to be a float in normals[" + k.ToString(culture) + "] in MeshNormals in Mesh");
                                             return false;
                                         } else if (!(sNormals[k].Data[1] is double)) {
                                             IO.ReportError(fileName, "y is expected to be a float in normals[" + k.ToString(culture) + " ]in MeshNormals in Mesh");
                                             return false;
                                         } else if (!(sNormals[k].Data[2] is double)) {
                                             IO.ReportError(fileName, "z is expected to be a float in normals[" + k.ToString(culture) + "] in MeshNormals in Mesh");
                                             return false;
                                         }
                                         double x = (double)sNormals[k].Data[0];
                                         double y = (double)sNormals[k].Data[1];
                                         double z = (double)sNormals[k].Data[2];
                                         OpenBveApi.Math.Vector3 normal = new OpenBveApi.Math.Vector3(x, y, z);
                                         if (!normal.IsNullVector()) {
                                             normal.Normalize();
                                         }
                                         normals[k] = normal;
                                     }
                                     /*
                                      * collect faces
                                      */
                                     for (int k = 0; k < nFaceNormals; k++) {
                                         if (sFaceNormals[k].Name != "MeshFace") {
                                             IO.ReportError(fileName, "faceNormals[" + k.ToString(culture) + "] is expected to be of template MeshFace in MeshNormals in Mesh");
                                             return false;
                                         } else if (sFaceNormals[k].Data.Length != 2) {
                                             IO.ReportError(fileName, "faceNormals[" + k.ToString(culture) + "] is expected to have 2 arguments in MeshNormals in Mesh");
                                             return false;
                                         } else if (!(sFaceNormals[k].Data[0] is int)) {
                                             IO.ReportError(fileName, "nFaceVertexIndices is expected to be a DWORD in faceNormals[" + k.ToString(culture) + "] in MeshNormals in Mesh");
                                             return false;
                                         } else if (!(sFaceNormals[k].Data[1] is int[])) {
                                             IO.ReportError(fileName, "faceVertexIndices[nFaceVertexIndices] is expected to be a DWORD array in faceNormals[" + k.ToString(culture) + "] in MeshNormals in Mesh");
                                             return false;
                                         }
                                         int nFaceVertexIndices = (int)sFaceNormals[k].Data[0];
                                         if (nFaceVertexIndices < 0 | nFaceVertexIndices > faces[k].Length) {
                                             IO.ReportError(fileName, "nFaceVertexIndices does not reference a valid vertex in MeshFace in MeshNormals in Mesh");
                                             return false;
                                         }
                                         int[] faceVertexIndices = (int[])sFaceNormals[k].Data[1];
                                         if (nFaceVertexIndices != faceVertexIndices.Length) {
                                             IO.ReportError(fileName, "nFaceVertexIndices does not match with the length of array faceVertexIndices in faceNormals[" + k.ToString(culture) + "] in MeshFace in MeshNormals in Mesh");
                                             return false;
                                         }
                                         for (int l = 0; l < nFaceVertexIndices; l++) {
                                             if (faceVertexIndices[l] < 0 | faceVertexIndices[l] >= nNormals) {
                                                 IO.ReportError(fileName, "faceVertexIndices[" + l.ToString(culture) + "] does not reference a valid normal in faceNormals[" + k.ToString(culture) + "] in MeshFace in MeshNormals in Mesh");
                                                 return false;
                                             }
                                             faceNormals[k][l] = normals[faceVertexIndices[l]];
                                         }
                                     }
                                 } break;
                             default:
                                 /*
                                  * unknown
                                  */
                                 IO.ReportError(fileName, "Unsupported template " + g.Name + " encountered in Mesh");
                                 break;
                         }
                     }
                     /*
                      * default material
                      */
                     if (materials.Length == 0) {
                         materials = new Material[1];
                         materials[0].FaceColor = new OpenBveApi.Color.ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);
                         materials[0].EmissiveColor = new OpenBveApi.Color.ColorRGB(0.0f, 0.0f, 0.0f);
                         materials[0].SpecularColor = new OpenBveApi.Color.ColorRGB(0.0f, 0.0f, 0.0f);
                         materials[0].TextureFilename = null;
                         for (int j = 0; j < nFaces; j++) {
                             faceMaterials[j] = 0;
                         }
                     }
                     /*
                      * eliminate non-visible faces and associated properties
                      */
                     int[][] visibleFaces = new int[nFaces][];
                     int newFaceCount = 0;
                     for (int currentFace = 0; currentFace < faces.Length; currentFace++) {
                         if (faces[currentFace].Length >= 3) {
                             visibleFaces[newFaceCount] = faces[currentFace];
                             faceNormals[newFaceCount] = faceNormals[currentFace];
                             faceMaterials[newFaceCount] = faceMaterials[currentFace];
                             newFaceCount++;
                         }
                     }
                     Array.Resize<int[]>(ref visibleFaces, newFaceCount);
                     Array.Resize<OpenBveApi.Math.Vector3[]>(ref faceNormals, newFaceCount);
                     Array.Resize<int>(ref faceMaterials, newFaceCount);
                     /*
                      * prepare compatible mesh for data
                      */
                     int vertexCount = 0;
                     for (int j = 0; j < visibleFaces.Length; j++) {
                         foreach (int face in visibleFaces[j]) {
                             vertexCount++;
                         }
                     }
                     Array.Resize<OpenBveApi.Geometry.Vertex>(ref compatibleMesh.Vertices, vertexCount);
                     Array.Resize<OpenBveApi.Geometry.Face>(ref compatibleMesh.Faces, visibleFaces.Length);
                     Array.Resize<OpenBveApi.Geometry.Material>(ref compatibleMesh.Materials, materials.Length);
                     /*
                      * apply vertex data
                      */
                     vertexCount = 0;
                     for (int faceIndex = 0; faceIndex < visibleFaces.Length; faceIndex++) {
                         compatibleMesh.Faces[faceIndex].Vertices = new int[visibleFaces[faceIndex].Length];
                         /*
                          *  go through each list of vertices in face and get vertex data
                          */
                         for (int vertexIndex = 0; vertexIndex < visibleFaces[faceIndex].Length; vertexIndex++) {
                             OpenBveApi.Geometry.Vertex newVertex = new OpenBveApi.Geometry.Vertex();
                             newVertex.SpatialCoordinates = vertices[visibleFaces[faceIndex][vertexIndex]].SpatialCoordinates;
                             newVertex.ReflectiveColor = vertices[visibleFaces[faceIndex][vertexIndex]].ReflectiveColor;
                             newVertex.TextureCoordinates = vertices[visibleFaces[faceIndex][vertexIndex]].TextureCoordinates;
                             newVertex.Tag = visibleFaces[faceIndex][vertexIndex];
                             /*
                              * check for null vector normal and create face derived normal if necessary
                              */
                             if (!faceNormals[faceIndex][vertexIndex].IsNullVector()) {
                                 newVertex.Normal = faceNormals[faceIndex][vertexIndex];
                             } else if (visibleFaces[faceIndex].Length >= 3) {
                                 OpenBveApi.Math.Vector3 vertexA = vertices[visibleFaces[faceIndex][0]].SpatialCoordinates;
                                 OpenBveApi.Math.Vector3 vertexB = vertices[visibleFaces[faceIndex][1]].SpatialCoordinates;
                                 OpenBveApi.Math.Vector3 vertexC = vertices[visibleFaces[faceIndex][2]].SpatialCoordinates;
                                 if (!OpenBveApi.Math.Vector3.CreateNormal(vertexA, vertexB, vertexC, out newVertex.Normal)) {
                                     newVertex.Normal = OpenBveApi.Math.Vector3.Up;
                                 }
                             }
                             /*
                              * assign vertex to mesh and finalise faces
                              */
                             compatibleMesh.Vertices[vertexCount] = newVertex;
                             compatibleMesh.Faces[faceIndex].Vertices[vertexIndex] = vertexCount;
                             compatibleMesh.Faces[faceIndex].Type = OpenBveApi.Geometry.FaceType.Polygon;
                             vertexCount++;
                         }
                     }
                     /*
                      * assign texture wrap mode, texture handles, X format transparent color, and emissive colors
                      */
                     for (int materialIndex = 0; materialIndex < materials.Length; materialIndex++) {
                         bool emissive = materials[materialIndex].EmissiveColor.R != 0 | materials[materialIndex].EmissiveColor.G != 0 | materials[materialIndex].EmissiveColor.B != 0;
                         if (materials[materialIndex].TextureFilename != null) {
                             /*
                              * default to clamp to edge and override if necessary
                              */
                             OpenBveApi.Texture.TextureWrapMode horizontalWrapMode, verticalWrapMode;
                             horizontalWrapMode = OpenBveApi.Texture.TextureWrapMode.ClampToEdge;
                             verticalWrapMode = OpenBveApi.Texture.TextureWrapMode.ClampToEdge;
                             for (int j = 0; j < compatibleMesh.Faces.Length; j++) {
                                 for (int k = 0; k < visibleFaces[j].Length; k++) {
                                     if (vertices[visibleFaces[j][k]].TextureCoordinates.X < 0.0 | vertices[visibleFaces[j][k]].TextureCoordinates.X > 1.0) {
                                         horizontalWrapMode = OpenBveApi.Texture.TextureWrapMode.Repeat;
                                     }
                                     if (vertices[visibleFaces[j][k]].TextureCoordinates.Y < 0.0 | vertices[visibleFaces[j][k]].TextureCoordinates.Y > 1.0) {
                                         verticalWrapMode = OpenBveApi.Texture.TextureWrapMode.Repeat;
                                     }
                                 }
                             }
                             /*
                              * register texture and get handle
                              */
                             string folder = System.IO.Path.GetDirectoryName(fileName);
                             string textureFile = OpenBveApi.Path.CombineFile(folder, materials[materialIndex].TextureFilename);
                             OpenBveApi.Path.PathReference path = new OpenBveApi.Path.FileReference(textureFile);
                             OpenBveApi.General.Origin origin = new OpenBveApi.General.Origin(path, null, encoding);
                             OpenBveApi.Color.TransparentColor transparentColor = new OpenBveApi.Color.TransparentColor(0, 0, 0, true);
                             OpenBveApi.Texture.TextureParameters parameters = new OpenBveApi.Texture.TextureParameters(transparentColor, horizontalWrapMode, verticalWrapMode, null);
                             OpenBveApi.Texture.TextureHandle handle;
                             if (Interfaces.Host.RegisterTexture(origin, parameters, out handle) == OpenBveApi.General.Result.Successful) {
                                 compatibleMesh.Materials[materialIndex].DaytimeTexture = handle;
                             } else {
                                 compatibleMesh.Materials[materialIndex].DaytimeTexture = null;
                             }
                             if (!System.IO.File.Exists(textureFile)) {
                                 IO.ReportError(fileName, materialIndex.ToString(), textureFile.ToString());
                             }
                         }
                         compatibleMesh.Materials[materialIndex].EmissiveColor = materials[materialIndex].EmissiveColor;
                         compatibleMesh.Materials[materialIndex].NighttimeTexture = null;
                     }
                     /*
                      * assign material reference to face
                      */
                     for (int j = 0; j < faceMaterials.Length; j++) {
                         compatibleMesh.Faces[j].Material = faceMaterials[j];
                     }
                     break;
                 }
             case "Header":
                 break;
             default:
                 /*
                  * unknown
                  */
                 IO.ReportError(fileName, "Unsupported template " + f.Name + " encountered");
                 break;
         }
     }
     /*
      * return
      */
     obj = compatibleMesh;
     return true;
 }
コード例 #32
0
 internal static void PlaySound(ref int SoundSourceIndex, int SoundBufferIndex, TrainManager.Train Train, int CarIndex, Vector3 Position, Importance Important, bool Looped, double Pitch, double Gain)
 {
     PlaySound(ref SoundSourceIndex, true, SoundBufferIndex, Train, CarIndex, Position, Important, Looped, Pitch, Gain);
 }
コード例 #33
0
ファイル: Sounds.Update.cs プロジェクト: tsdworks/RAGLINK-2
        /// <summary>Updates the sound component. Should be called every frame.</summary>
        /// <param name="timeElapsed">The time in seconds that elapsed since the last call to this function.</param>
        private static void UpdateLinearModel(double timeElapsed)
        {
            /*
             * Set up the listener
             * */
            OpenBveApi.Math.Vector3      listenerPosition    = World.AbsoluteCameraPosition;
            OpenBveApi.Math.Orientation3 listenerOrientation = new OpenBveApi.Math.Orientation3(World.AbsoluteCameraSide, World.AbsoluteCameraUp, World.AbsoluteCameraDirection);
            OpenBveApi.Math.Vector3      listenerVelocity    = World.CameraAlignmentSpeed.Position;
            AL.Listener(ALListener3f.Position, 0.0f, 0.0f, 0.0f);
            AL.Listener(ALListener3f.Velocity, (float)listenerVelocity.X, (float)listenerVelocity.Y, (float)listenerVelocity.Z);
            var Orientation = new[] { (float)listenerOrientation.Z.X, (float)listenerOrientation.Z.Y, (float)listenerOrientation.Z.Z, -(float)listenerOrientation.Y.X, -(float)listenerOrientation.Y.Y, -(float)listenerOrientation.Y.Z };

            AL.Listener(ALListenerfv.Orientation, ref Orientation);

            /*
             * Set up the atmospheric attributes
             * */
            double elevation      = World.AbsoluteCameraPosition.Y + Game.RouteInitialElevation;
            double airTemperature = Game.GetAirTemperature(elevation);
            double airPressure    = Game.GetAirPressure(elevation, airTemperature);
            double speedOfSound   = Game.GetSpeedOfSound(airPressure, airTemperature);

            try
            {
                AL.SpeedOfSound((float)speedOfSound);
            }
            catch { }

            /*
             * Update the sound sources
             * */
            int actuallyPlaying = 0;

            for (int i = 0; i < SourceCount; i++)
            {
                if (Sources[i].State == SoundSourceState.StopPending)
                {
                    /*
                     * The sound is still playing but is to be stopped.
                     * Stop the sound, then remove it from the list of
                     * sound sources.
                     * */
                    AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                    Sources[i].State            = SoundSourceState.Stopped;
                    Sources[i].OpenAlSourceName = 0;
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (Sources[i].State == SoundSourceState.Stopped)
                {
                    /*
                     * The sound was already stopped. Remove it from
                     * the list of sound sources.
                     * */
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (GlobalMute)
                {
                    /*
                     * The sound is playing or about to be played, but
                     * the global mute option is enabled. Stop the sound
                     * sound if necessary, then remove it from the list
                     * of sound sources if the sound is not looping.
                     * */
                    if (Sources[i].State == SoundSourceState.Playing)
                    {
                        AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                        Sources[i].State            = SoundSourceState.PlayPending;
                        Sources[i].OpenAlSourceName = 0;
                    }
                    if (!Sources[i].Looped)
                    {
                        Sources[i].State            = SoundSourceState.Stopped;
                        Sources[i].OpenAlSourceName = 0;
                        Sources[i] = Sources[SourceCount - 1];
                        SourceCount--;
                        i--;
                    }
                }
                else
                {
                    /*
                     * The sound is to be played or is already playing.
                     * Calculate the sound gain.
                     * */
                    OpenBveApi.Math.Vector3 position;
                    OpenBveApi.Math.Vector3 velocity;

                    switch (Sources[i].Type)
                    {
                    case SoundType.TrainCar:
                        OpenBveApi.Math.Vector3 direction;
                        Sources[i].Train.Cars[Sources[i].Car].CreateWorldCoordinates(Sources[i].Position, out position, out direction);
                        velocity = Sources[i].Train.Cars[Sources[i].Car].Specs.CurrentSpeed * direction;
                        break;

                    default:
                        position = Sources[i].Position;
                        velocity = OpenBveApi.Math.Vector3.Zero;
                        break;
                    }
                    OpenBveApi.Math.Vector3 positionDifference = position - listenerPosition;
                    double gain;
                    if (GlobalMute)
                    {
                        gain = 0.0;
                    }
                    else
                    {
                        double distance    = positionDifference.Norm();
                        double innerRadius = Sources[i].Radius;
                        if (World.CameraMode == CameraViewMode.Interior | World.CameraMode == CameraViewMode.InteriorLookAhead)
                        {
                            if (Sources[i].Train != TrainManager.PlayerTrain || Sources[i].Car != TrainManager.PlayerTrain.DriverCar)
                            {
                                innerRadius *= 0.5;
                            }
                        }
                        double outerRadius = OuterRadiusFactor * innerRadius;
                        if (distance < outerRadius)
                        {
                            if (distance <= innerRadius)
                            {
                                gain = Sources[i].Volume;
                            }
                            else
                            {
                                gain  = (distance - outerRadius) / (innerRadius - outerRadius);
                                gain *= Sources[i].Volume;
                            }
                            gain = 3.0 * gain * gain - 2.0 * gain * gain * gain;
                        }
                        else
                        {
                            gain = 0.0;
                        }
                    }
                    if (gain <= GainThreshold)
                    {
                        /*
                         * If the gain is too low to be audible, stop the sound.
                         * If the sound is not looping, stop it if necessary,
                         * then remove it from the list of sound sources.
                         * */
                        if (Sources[i].State == SoundSourceState.Playing)
                        {
                            AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                            Sources[i].State            = SoundSourceState.PlayPending;
                            Sources[i].OpenAlSourceName = 0;
                        }
                        if (!Sources[i].Looped)
                        {
                            Sources[i].State            = SoundSourceState.Stopped;
                            Sources[i].OpenAlSourceName = 0;
                            Sources[i] = Sources[SourceCount - 1];
                            SourceCount--;
                            i--;
                        }
                    }
                    else
                    {
                        /*
                         * Play the sound and update position, velocity, pitch and gain.
                         * For non-looping sounds, check if the sound is still playing.
                         * */
                        gain = (gain - GainThreshold) / (1.0 - GainThreshold);
                        if (Sources[i].State != SoundSourceState.Playing)
                        {
                            LoadBuffer(Sources[i].Buffer);
                            if (Sources[i].Buffer.Loaded)
                            {
                                AL.GenSources(1, out Sources[i].OpenAlSourceName);
                                AL.Source(Sources[i].OpenAlSourceName, ALSourcei.Buffer, Sources[i].Buffer.OpenAlBufferName);
                            }
                            else
                            {
                                /*
                                 * We cannot play the sound because
                                 * the buffer could not be loaded.
                                 * */
                                Sources[i].State = SoundSourceState.Stopped;
                                continue;
                            }
                        }
                        AL.Source(Sources[i].OpenAlSourceName, ALSource3f.Position, (float)positionDifference.X, (float)positionDifference.Y, (float)positionDifference.Z);
                        AL.Source(Sources[i].OpenAlSourceName, ALSource3f.Velocity, (float)velocity.X, (float)velocity.Y, (float)velocity.Z);
                        AL.Source(Sources[i].OpenAlSourceName, ALSourcef.Pitch, (float)Sources[i].Pitch);
                        AL.Source(Sources[i].OpenAlSourceName, ALSourcef.Gain, (float)gain);
                        if (Sources[i].State != SoundSourceState.Playing)
                        {
                            AL.Source(Sources[i].OpenAlSourceName, ALSourceb.Looping, Sources[i].Looped);
                            AL.SourcePlay(Sources[i].OpenAlSourceName);
                            Sources[i].State = SoundSourceState.Playing;
                        }
                        if (!Sources[i].Looped)
                        {
                            int state;
                            AL.GetSource(Sources[i].OpenAlSourceName, ALGetSourcei.SourceState, out state);
                            if (state != (int)ALSourceState.Initial & state != (int)ALSourceState.Playing)
                            {
                                /*
                                 * The sound is not playing any longer.
                                 * Remove it from the list of sound sources.
                                 * */
                                AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                                Sources[i].State            = SoundSourceState.Stopped;
                                Sources[i].OpenAlSourceName = 0;
                                Sources[i] = Sources[SourceCount - 1];
                                SourceCount--;
                                i--;
                            }
                            else
                            {
                                actuallyPlaying++;
                            }
                        }
                        else
                        {
                            actuallyPlaying++;
                        }
                    }
                }
            }

            /*
             * Adjust the outer radius factor / the clamp factor.
             * */
            if (actuallyPlaying >= Interface.CurrentOptions.SoundNumber - 2)
            {
                /*
                 * Too many sounds are playing.
                 * Reduce the outer radius factor.
                 * */
                OuterRadiusFactorSpeed -= timeElapsed;
                if (OuterRadiusFactorSpeed < -OuterRadiusFactorMaximumSpeed)
                {
                    OuterRadiusFactorSpeed = -OuterRadiusFactorMaximumSpeed;
                }
            }
            else if (actuallyPlaying <= Interface.CurrentOptions.SoundNumber - 6)
            {
                /*
                 * Only few sounds are playing.
                 * Increase the outer radius factor.
                 * */
                OuterRadiusFactorSpeed += timeElapsed;
                if (OuterRadiusFactorSpeed > OuterRadiusFactorMaximumSpeed)
                {
                    OuterRadiusFactorSpeed = OuterRadiusFactorMaximumSpeed;
                }
            }
            else
            {
                /*
                 * Neither too many nor too few sounds are playing.
                 * Stabilize the outer radius factor.
                 * */
                if (OuterRadiusFactorSpeed < 0.0)
                {
                    OuterRadiusFactorSpeed += timeElapsed;
                    if (OuterRadiusFactorSpeed > 0.0)
                    {
                        OuterRadiusFactorSpeed = 0.0;
                    }
                }
                else
                {
                    OuterRadiusFactorSpeed -= timeElapsed;
                    if (OuterRadiusFactorSpeed < 0.0)
                    {
                        OuterRadiusFactorSpeed = 0.0;
                    }
                }
            }
            OuterRadiusFactor += OuterRadiusFactorSpeed * timeElapsed;
            if (OuterRadiusFactor < OuterRadiusFactorMinimum)
            {
                OuterRadiusFactor      = OuterRadiusFactorMinimum;
                OuterRadiusFactorSpeed = 0.0;
            }
            else if (OuterRadiusFactor > OuterRadiusFactorMaximum)
            {
                OuterRadiusFactor      = OuterRadiusFactorMaximum;
                OuterRadiusFactorSpeed = 0.0;
            }
        }
コード例 #34
0
ファイル: ObjectGrid.cs プロジェクト: sladen/openbve2
 // instance functions
 /// <summary>Takes an object, its position and orientation on the grid node, and then updates the bounding rectangle accordingly.</summary>
 /// <param name="libraryIndex">A reference to an object stored in the object library.</param>
 /// <param name="gridPosition">The position of the object relative to the center of the contained grid node.</param>
 /// <param name="gridOrientation">The orientation of the object.</param>
 internal void UpdateBoundingRectangle(int libraryIndex, OpenBveApi.Math.Vector3 gridPosition, OpenBveApi.Math.Orientation3 gridOrientation)
 {
     OpenBveApi.Geometry.FaceVertexMesh mesh = ObjectLibrary.Library.Objects[libraryIndex] as OpenBveApi.Geometry.FaceVertexMesh;
     if (mesh != null) {
         OpenBveApi.Math.Vector3 gridCenter = new OpenBveApi.Math.Vector3(
             0.5 * (this.Rectangle.Left + this.Rectangle.Right),
             0.0,
             0.5 * (this.Rectangle.Near + this.Rectangle.Far)
         );
         OpenBveApi.Math.Vector3 absolutePosition = gridCenter + gridPosition;
         for (int i = 0; i < mesh.Vertices.Length; i++) {
             OpenBveApi.Math.Vector3 vector = absolutePosition + OpenBveApi.Math.Vector3.Rotate(mesh.Vertices[i].SpatialCoordinates, gridOrientation);
             if (vector.X < this.BoundingRectangle.Left) {
                 this.BoundingRectangle.Left = vector.X;
             }
             if (vector.X > this.BoundingRectangle.Right) {
                 this.BoundingRectangle.Right = vector.X;
             }
             if (vector.Z < this.BoundingRectangle.Near) {
                 this.BoundingRectangle.Near = vector.Z;
             }
             if (vector.Z > this.BoundingRectangle.Far) {
                 this.BoundingRectangle.Far = vector.Z;
             }
         }
     }
     if (this.Parent is GridInternalNode) {
         GridInternalNode intern = (GridInternalNode)this.Parent;
         intern.UpdateBoundingRectangle();
     }
 }
コード例 #35
0
ファイル: Renderer.cs プロジェクト: sladen/openbve2
        // --- render the whole scene ---
        /// <summary>Renders the whole screen, including the scene and the interface components.</summary>
        internal static void Render(double elapsedTime)
        {
            /*
             * Initialize rendering this frame.
             * */
            Gl.glClearColor(LightAmbientColor.R, LightAmbientColor.G, LightAmbientColor.B, 1.0f);
            //Gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
            Gl.glLoadIdentity();

            if (false) {
                const double radius = 30.0;
                double angle = 0.001 * (double)System.Environment.TickCount;
                Camera.Position = new OpenBveApi.Math.Vector3(Math.Sin(angle) * radius, 10.0, -Math.Cos(angle) * radius);
                OpenBveApi.Math.Vector3 center = new OpenBveApi.Math.Vector3(0.0, 0.0, 0.0);
                OpenBveApi.Math.Vector3 direction = OpenBveApi.Math.Vector3.Normalize(center - Camera.Position);
                OpenBveApi.Math.Vector3 side = new OpenBveApi.Math.Vector3(direction.Z, 0.0, -direction.X);
                OpenBveApi.Math.Vector3 up = OpenBveApi.Math.Vector3.Cross(direction, side);
                Camera.Orientation = new OpenBveApi.Math.Orientation3(side, up, direction);
            }

            /*
             * Ensure that the leaf node the camera is currently in
             * has been updated to reflect the latest camera position.
             * */
            Camera.UpdateGridLeafNode();

            /*
             * Apply the camera's position and orientation to OpenGL.
             * */
            {
                OpenBveApi.Math.Vector3 position = Camera.Position - Camera.GridLeafNodeCenter;
                OpenBveApi.Math.Vector3 direction = Camera.Orientation.Z;
                OpenBveApi.Math.Vector3 up = Camera.Orientation.Y;
                OpenBveApi.Math.Vector3 center = position + direction;
                Glu.gluLookAt(position.X, position.Y, position.Z, center.X, center.Y, center.Z, up.X, up.Y, up.Z);
            }

            /*
             * Set lighting conditions
             * */
            Gl.glEnable(Gl.GL_LIGHTING);
            UpdateLighting(Timing.SecondsSinceMidnight);
            Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, new float[] { (float)LightPosition.X, (float)LightPosition.Y, (float)LightPosition.Z, 0.0f });
            Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_AMBIENT, new float[] { LightAmbientColor.R, LightAmbientColor.G, LightAmbientColor.B, 1.0f });
            Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_DIFFUSE, new float[] { LightDiffuseColor.R, LightDiffuseColor.G, LightDiffuseColor.B, 1.0f });

            /*
             * Render all leaf nodes visible from the leaf node the camera is currently in.
             * */
            Triangle[] triangles = null;
            if (Program.CurrentOptions.BlockClipping) {
                InitializeBlockClipping(out triangles);
            }
            int blockCount = 0;
            int blocksClipped = 0;
            int objectCount = 0;
            if (Camera.GridLeafNode != null) {
                int length = Camera.GridLeafNode.VisibleLeafNodes.Length;
                for (int i = 0; i < Camera.GridLeafNode.VisibleLeafNodes.Length; i++) {
                    bool visible;
                    if (Program.CurrentOptions.BlockClipping) {
                        visible = BlockIntersectsTriangles(Camera.GridLeafNode.VisibleLeafNodes[i].BoundingRectangle, triangles);
                    } else {
                        visible = true;
                    }
                    if (visible) {
                        RenderGridLeafNode(Camera.GridLeafNode.VisibleLeafNodes[i], false);
                        objectCount += Camera.GridLeafNode.VisibleLeafNodes[i].StaticOpaqueObjectCount;
                    } else {
                        blocksClipped++;
                    }
                    blockCount++;
                }
            }
            //Windows.UpdateDebugText("blockCount=" + blockCount.ToString() + ", blocksClipped=" + blocksClipped.ToString());

            //			if (Camera.GridLeafNode == null) {
            //				Windows.UpdateDebugText("NULL");
            //			} else if (Camera.GridLeafNode is ObjectGrid.GridPopulatedLeafNode) {
            //				ObjectGrid.GridLeafNode leaf = (ObjectGrid.GridLeafNode)Camera.GridLeafNode;
            //				Windows.UpdateDebugText("GridPopulatedLeafNode, rect(left=" + leaf.Rectangle.Left.ToString("0") + ", right=" + leaf.Rectangle.Right.ToString("0") + ", near=" + leaf.Rectangle.Near.ToString("0") + ", far=" + leaf.Rectangle.Far.ToString("0") + "), bounding(left=" + leaf.BoundingRectangle.Left.ToString("0") + ", right=" + leaf.BoundingRectangle.Right.ToString("0") + ", near=" + leaf.BoundingRectangle.Near.ToString("0") + ", far=" + leaf.BoundingRectangle.Far.ToString("0") + "), count=" + leaf.VisibleLeafNodes.Length.ToString());
            //			} else if (Camera.GridLeafNode is ObjectGrid.GridUnpopulatedLeafNode) {
            //				ObjectGrid.GridLeafNode leaf = (ObjectGrid.GridLeafNode)Camera.GridLeafNode;
            //				Windows.UpdateDebugText("GridUnpopulatedLeafNode, rect(left=" + leaf.Rectangle.Left.ToString("0") + ", right=" + leaf.Rectangle.Right.ToString("0") + ", near=" + leaf.Rectangle.Near.ToString("0") + ", far=" + leaf.Rectangle.Far.ToString("0") + "), bounding(left=" + leaf.BoundingRectangle.Left.ToString("0") + ", right=" + leaf.BoundingRectangle.Right.ToString("0") + ", near=" + leaf.BoundingRectangle.Near.ToString("0") + ", far=" + leaf.BoundingRectangle.Far.ToString("0") + "), count=" + leaf.VisibleLeafNodes.Length.ToString());
            //			} else {
            //				Windows.UpdateDebugText("invalid");
            //			}
            if (Camera.GridLeafNode == null) {
                Windows.UpdateDebugText("You have left the bounds of the grid root node.");
            }

            /*
             * Render transparent world faces.
             * */
            TransparentWorldFaces.SortAllFaces(elapsedTime, false);
            TransparentWorldFaces.RenderAllLists();
            /*
             * Render overlays in screen coordinates.
             * */
            {
                /*
                 * Prepare the projection matrix to work
                 * temporarily in screen coordinates.
                 * */
                Gl.glMatrixMode(Gl.GL_PROJECTION);
                Gl.glPushMatrix();
                Gl.glLoadIdentity();
                Gl.glOrtho(0.0, (double)Screen.Properties.Width, (double)Screen.Properties.Height, 0.0, -1.0, 1.0);
                Gl.glMatrixMode(Gl.GL_MODELVIEW);
                Gl.glPushMatrix();
                Gl.glLoadIdentity();
                Gl.glDisable(Gl.GL_LIGHTING);
                /*
                 * Render GUI.
                 * */
                Windows.Render();
                /*
                 * Undo the matrix transformation.
                 * */
                Gl.glPopMatrix();
                Gl.glMatrixMode(Gl.GL_PROJECTION);
                Gl.glPopMatrix();
                Gl.glMatrixMode(Gl.GL_MODELVIEW);
            }
            /*
             * Perform frame-finalizing tasks.
             * */
            Sdl.SDL_GL_SwapBuffers();
            #if DEBUG
            CheckForOpenGlError("Renderer.Render");
            #endif
        }
コード例 #36
0
ファイル: ObjectGrid.cs プロジェクト: sladen/openbve2
 // instance functions
 /// <summary>Adds a new instance of a static object to the grid.</summary>
 /// <param name="libraryIndex">The index to a library object.</param>
 /// <param name="position">The absolute world position of the object.</param>
 /// <param name="orientation">The absolute world orientation of the object.</param>
 internal void Add(int libraryIndex, OpenBveApi.Math.Vector3 position, OpenBveApi.Math.Orientation3 orientation)
 {
     if (this.Root == null) {
         // the root node does not exist yet
         OpenBveApi.Math.Vector3 gridPosition = new OpenBveApi.Math.Vector3(0.0, position.Y, 0.0);
         GridPopulatedLeafNode leaf = new GridPopulatedLeafNode(
             null,
             new GridBounds(
                 position.X - 0.5 * this.SideLength,
                 position.X + 0.5 * this.SideLength,
                 position.Z - 0.5 * this.SideLength,
                 position.Z + 0.5 * this.SideLength
             ),
             new StaticOpaqueObject(libraryIndex, gridPosition, orientation)
         );
         leaf.UpdateBoundingRectangle(libraryIndex, gridPosition, orientation);
         this.Root = leaf;
     } else {
         // the root node exists
         while (true) {
             if (position.X >= this.Root.Rectangle.Left & position.X <= this.Root.Rectangle.Right & position.Z >= this.Root.Rectangle.Near & position.Z <= this.Root.Rectangle.Far) {
                 // the position is within the bounds of the root node
                 GridNode node = this.Root;
                 double left = this.Root.Rectangle.Left;
                 double right = this.Root.Rectangle.Right;
                 double near = this.Root.Rectangle.Near;
                 double far = this.Root.Rectangle.Far;
                 while (true) {
                     if (node is GridPopulatedLeafNode) {
                         // populated leaf node
                         OpenBveApi.Math.Vector3 gridPosition = new OpenBveApi.Math.Vector3(
                             position.X - 0.5 * (left + right),
                             position.Y,
                             position.Z - 0.5 * (near + far)
                         );
                         GridPopulatedLeafNode leaf = (GridPopulatedLeafNode)node;
                         if (leaf.StaticOpaqueObjectCount == leaf.StaticOpaqueObjects.Length) {
                             Array.Resize<StaticOpaqueObject>(ref leaf.StaticOpaqueObjects, leaf.StaticOpaqueObjects.Length << 1);
                         }
                         leaf.VisibleLeafNodes = null;
                         leaf.StaticOpaqueObjects[leaf.StaticOpaqueObjectCount] = new StaticOpaqueObject(libraryIndex, gridPosition, orientation);
                         leaf.StaticOpaqueObjectCount++;
                         leaf.UpdateBoundingRectangle(libraryIndex, gridPosition, orientation);
                         break;
                     } else if (node is GridInternalNode) {
                         // internal node
                         GridInternalNode intern = (GridInternalNode)node;
                         int index;
                         double centerX = 0.5 * (left + right);
                         double centerZ = 0.5 * (near + far);
                         if (position.Z <= centerZ) {
                             if (position.X <= centerX) {
                                 index = 0;
                                 right = centerX;
                                 far = centerZ;
                             } else {
                                 index = 1;
                                 left = centerX;
                                 far = centerZ;
                             }
                         } else {
                             if (position.X <= centerX) {
                                 index = 2;
                                 right = centerX;
                                 near = centerZ;
                             } else {
                                 index = 3;
                                 left = centerX;
                                 near = centerZ;
                             }
                         }
                         if (intern.Children[index] is GridUnpopulatedLeafNode) {
                             double sideLength = 0.5 * (right - left + far - near);
                             const double toleranceFactor = 1.01;
                             if (sideLength < toleranceFactor * this.SideLength) {
                                 // create populated leaf child
                                 GridPopulatedLeafNode child = new GridPopulatedLeafNode(
                                     intern,
                                     new GridBounds(left, right, near, far),
                                     null
                                 );
                                 child.BoundingRectangle = GridBounds.Uninitialized;
                                 intern.Children[index] = child;
                                 node = child;
                             } else {
                                 // create internal child
                                 GridInternalNode child = new GridInternalNode(
                                     intern,
                                     new GridBounds(left, right, near, far),
                                     new GridNode[] { null, null, null, null }
                                 );
                                 child.Children[0] = new GridUnpopulatedLeafNode(child, new GridBounds(left, 0.5 * (left + right), near, 0.5 * (near + far)));
                                 child.Children[1] = new GridUnpopulatedLeafNode(child, new GridBounds(0.5 * (left + right), right, near, 0.5 * (near + far)));
                                 child.Children[2] = new GridUnpopulatedLeafNode(child, new GridBounds(left, 0.5 * (left + right), 0.5 * (near + far), far));
                                 child.Children[3] = new GridUnpopulatedLeafNode(child, new GridBounds(0.5 * (left + right), right, 0.5 * (near + far), far));
                                 intern.Children[index] = child;
                                 node = child;
                             }
                         } else {
                             // go to child
                             node = intern.Children[index];
                         }
                     } else {
                         throw new InvalidOperationException();
                     }
                 }
                 break;
             } else {
                 // the position is outside the bounds of the root node
                 if (position.Z <= 0.5 * (this.Root.Rectangle.Near + this.Root.Rectangle.Far)) {
                     if (position.X <= 0.5 * (this.Root.Rectangle.Left + this.Root.Rectangle.Right)) {
                         // expand toward near-left
                         GridInternalNode intern = new GridInternalNode(
                             null,
                             new GridBounds(
                                 2.0 * this.Root.Rectangle.Left - this.Root.Rectangle.Right,
                                 this.Root.Rectangle.Right,
                                 2.0 * this.Root.Rectangle.Near - this.Root.Rectangle.Far,
                                 this.Root.Rectangle.Far
                             ),
                             new GridNode[] { null, null, null, this.Root }
                         );
                         this.Root.Parent = intern;
                         intern.Children[0] = new GridUnpopulatedLeafNode(intern, new GridBounds(intern.Rectangle.Left, 0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), intern.Rectangle.Near, 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far)));
                         intern.Children[1] = new GridUnpopulatedLeafNode(intern, new GridBounds(0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), intern.Rectangle.Right, intern.Rectangle.Near, 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far)));
                         intern.Children[2] = new GridUnpopulatedLeafNode(intern, new GridBounds(intern.Rectangle.Left, 0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far), intern.Rectangle.Far));
                         intern.UpdateBoundingRectangle();
                         this.Root = intern;
                     } else {
                         // expand toward near-right
                         GridInternalNode intern = new GridInternalNode(
                             null,
                             new GridBounds(
                                 this.Root.Rectangle.Left,
                                 2.0 * this.Root.Rectangle.Right - this.Root.Rectangle.Left,
                                 2.0 * this.Root.Rectangle.Near - this.Root.Rectangle.Far,
                                 this.Root.Rectangle.Far
                             ),
                             new GridNode[] { null, null, this.Root, null }
                         );
                         this.Root.Parent = intern;
                         intern.Children[0] = new GridUnpopulatedLeafNode(intern, new GridBounds(intern.Rectangle.Left, 0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), intern.Rectangle.Near, 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far)));
                         intern.Children[1] = new GridUnpopulatedLeafNode(intern, new GridBounds(0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), intern.Rectangle.Right, intern.Rectangle.Near, 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far)));
                         intern.Children[3] = new GridUnpopulatedLeafNode(intern, new GridBounds(0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), intern.Rectangle.Right, 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far), intern.Rectangle.Far));
                         intern.UpdateBoundingRectangle();
                         this.Root = intern;
                     }
                 } else {
                     if (position.X <= 0.5 * (this.Root.Rectangle.Left + this.Root.Rectangle.Right)) {
                         // expand toward far-left
                         GridInternalNode intern = new GridInternalNode(
                             null,
                             new GridBounds(
                                 2.0 * this.Root.Rectangle.Left - this.Root.Rectangle.Right,
                                 this.Root.Rectangle.Right,
                                 this.Root.Rectangle.Near,
                                 2.0 * this.Root.Rectangle.Far - this.Root.Rectangle.Near
                             ),
                             new GridNode[] { null, this.Root, null, null }
                         );
                         this.Root.Parent = intern;
                         intern.Children[0] = new GridUnpopulatedLeafNode(intern, new GridBounds(intern.Rectangle.Left, 0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), intern.Rectangle.Near, 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far)));
                         intern.Children[2] = new GridUnpopulatedLeafNode(intern, new GridBounds(intern.Rectangle.Left, 0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far), intern.Rectangle.Far));
                         intern.Children[3] = new GridUnpopulatedLeafNode(intern, new GridBounds(0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), intern.Rectangle.Right, 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far), intern.Rectangle.Far));
                         intern.UpdateBoundingRectangle();
                         this.Root = intern;
                     } else {
                         // expand toward far-right
                         GridInternalNode intern = new GridInternalNode(
                             null,
                             new GridBounds(
                                 this.Root.Rectangle.Left,
                                 2.0 * this.Root.Rectangle.Right - this.Root.Rectangle.Left,
                                 this.Root.Rectangle.Near,
                                 2.0 * this.Root.Rectangle.Far - this.Root.Rectangle.Near
                             ),
                             new GridNode[] { this.Root, null, null, null }
                         );
                         this.Root.Parent = intern;
                         intern.Children[1] = new GridUnpopulatedLeafNode(intern, new GridBounds(0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), intern.Rectangle.Right, intern.Rectangle.Near, 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far)));
                         intern.Children[2] = new GridUnpopulatedLeafNode(intern, new GridBounds(intern.Rectangle.Left, 0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far), intern.Rectangle.Far));
                         intern.Children[3] = new GridUnpopulatedLeafNode(intern, new GridBounds(0.5 * (intern.Rectangle.Left + intern.Rectangle.Right), intern.Rectangle.Right, 0.5 * (intern.Rectangle.Near + intern.Rectangle.Far), intern.Rectangle.Far));
                         intern.UpdateBoundingRectangle();
                         this.Root = intern;
                     }
                 }
             }
         }
     }
 }
コード例 #37
0
ファイル: ObjectGrid.cs プロジェクト: sladen/openbve2
 // constructors
 /// <summary>Creates a new instance of this class.</summary>
 /// <param name="libraryIndex">A reference to an object stored in the object library.</param>
 /// <param name="gridPosition">The position of the object relative to the center of the grid node.</param>
 /// <param name="gridOrientation">The orientation of the object.</param>
 internal StaticOpaqueObject(int libraryIndex, OpenBveApi.Math.Vector3 gridPosition, OpenBveApi.Math.Orientation3 gridOrientation)
 {
     this.LibraryIndex = libraryIndex;
     this.GridPosition = gridPosition;
     this.GridOrientation = gridOrientation;
 }
コード例 #38
0
ファイル: Station.cs プロジェクト: xfleet/OpenBVE
        /// <summary>Is called once a frame to update the station state for the given train</summary>
        /// <param name="Train">The train</param>
        /// <param name="TimeElapsed">The frame time elapsed</param>
        private static void UpdateTrainStation(Train Train, double TimeElapsed)
        {
            if (Train.Station >= 0)
            {
                int    i = Train.Station;
                int    n = Program.CurrentRoute.Stations[Train.Station].GetStopIndex(Train.NumberOfCars);
                double tf, tb;
                if (n >= 0)
                {
                    double p0 = Train.Cars[0].FrontAxle.Follower.TrackPosition - Train.Cars[0].FrontAxle.Position + 0.5 * Train.Cars[0].Length;
                    double p1 = Program.CurrentRoute.Stations[i].Stops[n].TrackPosition;
                    tf = Program.CurrentRoute.Stations[i].Stops[n].ForwardTolerance;
                    tb = Program.CurrentRoute.Stations[i].Stops[n].BackwardTolerance;
                    Train.StationDistanceToStopPoint = p1 - p0;
                }
                else
                {
                    Train.StationDistanceToStopPoint = 0.0;
                    tf = 5.0;
                    tb = 5.0;
                }
                if (Train.StationState == TrainStopState.Pending)
                {
                    Train.StationDepartureSoundPlayed = false;
                    if (Program.CurrentRoute.Stations[i].StopsHere(Train))
                    {
                        Train.StationDepartureSoundPlayed = false;
                        //Check whether all doors are controlled by the driver
                        if (Train.Specs.DoorOpenMode != DoorMode.Manual)
                        {
                            //Check that we are not moving
                            if (Math.Abs(Train.CurrentSpeed) < 0.1 / 3.6 &
                                Math.Abs(Train.Specs.CurrentAverageAcceleration) < 0.1 / 3.6)
                            {
                                AttemptToOpenDoors(Train, i, tb, tf);
                            }
                        }
                        // detect arrival
                        if (Train.CurrentSpeed > -0.277777777777778 & Train.CurrentSpeed < 0.277777777777778)
                        {
                            bool left, right;
                            if (Program.CurrentRoute.Stations[i].OpenLeftDoors)
                            {
                                left = false;
                                for (int j = 0; j < Train.Cars.Length; j++)
                                {
                                    if (Train.Cars[j].Doors[0].AnticipatedOpen)
                                    {
                                        left = true; break;
                                    }
                                }
                            }
                            else
                            {
                                left = true;
                            }
                            if (Program.CurrentRoute.Stations[i].OpenRightDoors)
                            {
                                right = false;
                                for (int j = 0; j < Train.Cars.Length; j++)
                                {
                                    if (Train.Cars[j].Doors[1].AnticipatedOpen)
                                    {
                                        right = true; break;
                                    }
                                }
                            }
                            else
                            {
                                right = true;
                            }
                            if (left & right)
                            {
                                // arrival
                                Train.StationState = TrainStopState.Boarding;
                                Train.SafetySystems.StationAdjust.Lit = false;
                                Train.Specs.DoorClosureAttempted      = false;
                                Train.SafetySystems.PassAlarm.Halt();
                                SoundBuffer buffer = (SoundBuffer)Program.CurrentRoute.Stations[i].ArrivalSoundBuffer;
                                if (buffer != null)
                                {
                                    OpenBveApi.Math.Vector3 pos = Program.CurrentRoute.Stations[i].SoundOrigin;
                                    Program.Sounds.PlaySound(buffer, 1.0, 1.0, pos, false);
                                }
                                Train.StationArrivalTime   = Program.CurrentRoute.SecondsSinceMidnight;
                                Train.StationDepartureTime = Program.CurrentRoute.Stations[i].DepartureTime - Train.TimetableDelta;
                                if (Train.StationDepartureTime - Program.CurrentRoute.SecondsSinceMidnight < Program.CurrentRoute.Stations[i].StopTime)
                                {
                                    Train.StationDepartureTime = Program.CurrentRoute.SecondsSinceMidnight + Program.CurrentRoute.Stations[i].StopTime;
                                }
                                Train.Passengers.PassengerRatio = Program.CurrentRoute.Stations[i].PassengerRatio;
                                UpdateTrainMassFromPassengerRatio(Train);
                                if (Train.IsPlayerTrain)
                                {
                                    double early = 0.0;
                                    if (Program.CurrentRoute.Stations[i].ArrivalTime >= 0.0)
                                    {
                                        early = (Program.CurrentRoute.Stations[i].ArrivalTime - Train.TimetableDelta) - Train.StationArrivalTime;
                                    }
                                    string s;
                                    if (early < -1.0)
                                    {
                                        s = Translations.GetInterfaceString("message_station_arrival_late");
                                    }
                                    else if (early > 1.0)
                                    {
                                        s = Translations.GetInterfaceString("message_station_arrival_early");
                                    }
                                    else
                                    {
                                        s = Translations.GetInterfaceString("message_station_arrival");
                                    }
                                    System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
                                    TimeSpan a = TimeSpan.FromSeconds(Math.Abs(early));
                                    string   b = a.Hours.ToString("00", Culture) + ":" + a.Minutes.ToString("00", Culture) + ":" + a.Seconds.ToString("00", Culture);
                                    if (Train.StationDistanceToStopPoint < -0.1)
                                    {
                                        s += Translations.GetInterfaceString("message_delimiter") + Translations.GetInterfaceString("message_station_overrun");
                                    }
                                    else if (Train.StationDistanceToStopPoint > 0.1)
                                    {
                                        s += Translations.GetInterfaceString("message_delimiter") + Translations.GetInterfaceString("message_station_underrun");
                                    }
                                    double d = Math.Abs(Train.StationDistanceToStopPoint);
                                    string c = d.ToString("0.0", Culture);
                                    if (Program.CurrentRoute.Stations[i].Type == StationType.Terminal)
                                    {
                                        s += Translations.GetInterfaceString("message_delimiter") + Translations.GetInterfaceString("message_station_terminal");
                                    }
                                    s = s.Replace("[name]", Program.CurrentRoute.Stations[i].Name);
                                    s = s.Replace("[time]", b);
                                    s = s.Replace("[difference]", c);
                                    MessageManager.AddMessage(s, MessageDependency.StationArrival, GameMode.Normal, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null);
                                    if (Program.CurrentRoute.Stations[i].Type == StationType.Normal)
                                    {
                                        s = Translations.GetInterfaceString("message_station_deadline");
                                        MessageManager.AddMessage(s, MessageDependency.StationDeparture, GameMode.Normal, MessageColor.White, double.PositiveInfinity, null);
                                    }
                                    Timetable.UpdateCustomTimetable(Program.CurrentRoute.Stations[i].TimetableDaytimeTexture, Program.CurrentRoute.Stations[i].TimetableNighttimeTexture);
                                }
                                // schedule door locks (passengers stuck between the doors)
                                for (int j = 0; j < Train.Cars.Length; j++)
                                {
                                    for (int k = 0; k < Train.Cars[j].Doors.Length; k++)
                                    {
                                        Train.Cars[j].Doors[k].DoorLockDuration = 0.0;
                                        if (Program.CurrentRoute.Stations[i].OpenLeftDoors & Train.Cars[j].Doors[k].Direction == -1 | Program.CurrentRoute.Stations[i].OpenRightDoors & Train.Cars[j].Doors[k].Direction == 1)
                                        {
                                            double p = 0.005 * Program.CurrentRoute.Stations[i].PassengerRatio * Program.CurrentRoute.Stations[i].PassengerRatio * Program.CurrentRoute.Stations[i].PassengerRatio * Program.CurrentRoute.Stations[i].PassengerRatio;
                                            if (Program.RandomNumberGenerator.NextDouble() < p)
                                            {
                                                /*
                                                 * -- door lock at state --
                                                 * minimum: 0.2 (nearly closed)
                                                 * maximum: 0.8 (nearly opened)
                                                 * */
                                                Train.Cars[j].Doors[k].DoorLockState = 0.2 + 0.6 * Program.RandomNumberGenerator.NextDouble();

                                                /* -- waiting time --
                                                 * minimum: 2.9 s
                                                 * maximum: 40.0 s
                                                 * average: 7.6 s
                                                 * */
                                                p = Program.RandomNumberGenerator.NextDouble();
                                                Train.Cars[j].Doors[k].DoorLockDuration = (50.0 - 10.0 * p) / (17.0 - 16.0 * p);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (Train.SafetySystems.StationAdjust != null)
                                {
                                    Train.SafetySystems.StationAdjust.Update(tb, tf);
                                }
                            }
                        }
                    }
                }
                else if (Train.StationState == TrainStopState.Boarding)
                {
                    for (int j = 0; j < Train.Cars.Length; j++)
                    {
                        if (GetDoorsState(Train, j, Program.CurrentRoute.Stations[i].OpenLeftDoors, Program.CurrentRoute.Stations[i].OpenRightDoors) == (TrainDoorState.Opened | TrainDoorState.AllOpened))
                        {
                            //Check whether all doors are controlled by the driver, and whether this is a non-standard station type
                            //e.g. Change ends
                            if (Train.Specs.DoorCloseMode != DoorMode.Manual & Program.CurrentRoute.Stations[i].Type == StationType.Normal)
                            {
                                AttemptToCloseDoors(Train);

                                if (Train.Specs.DoorClosureAttempted)
                                {
                                    if (Program.CurrentRoute.Stations[i].OpenLeftDoors && !Train.Cars[j].Doors[0].AnticipatedReopen && Program.RandomNumberGenerator.NextDouble() < Program.CurrentRoute.Stations[i].ReopenDoor)
                                    {
                                        Train.Cars[j].Doors[0].ReopenLimit           = Program.RandomNumberGenerator.Next(1, Program.CurrentRoute.Stations[i].ReopenStationLimit);
                                        Train.Cars[j].Doors[0].ReopenCounter         = 0;
                                        Train.Cars[j].Doors[0].InterferingObjectRate = Program.RandomNumberGenerator.Next(1, Program.CurrentRoute.Stations[i].MaxInterferingObjectRate) * 0.01;
                                        if (Train.Cars[j].Doors[0].InterferingObjectRate * Train.Cars[j].Doors[0].Width >= Train.Cars[j].Doors[0].MaxTolerance)
                                        {
                                            Train.Cars[j].Doors[0].AnticipatedReopen = true;
                                        }
                                    }
                                    if (Program.CurrentRoute.Stations[i].OpenRightDoors && !Train.Cars[j].Doors[1].AnticipatedReopen && Program.RandomNumberGenerator.NextDouble() < Program.CurrentRoute.Stations[i].ReopenDoor)
                                    {
                                        Train.Cars[j].Doors[1].ReopenLimit           = Program.RandomNumberGenerator.Next(1, Program.CurrentRoute.Stations[i].ReopenStationLimit);
                                        Train.Cars[j].Doors[1].ReopenCounter         = 0;
                                        Train.Cars[j].Doors[1].InterferingObjectRate = Program.RandomNumberGenerator.Next(1, Program.CurrentRoute.Stations[i].MaxInterferingObjectRate) * 0.01;
                                        if (Train.Cars[j].Doors[1].InterferingObjectRate * Train.Cars[j].Doors[1].Width >= Train.Cars[j].Doors[1].MaxTolerance)
                                        {
                                            Train.Cars[j].Doors[1].AnticipatedReopen = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    // detect departure
                    bool left, right;
                    if (!Program.CurrentRoute.Stations[i].OpenLeftDoors & !Program.CurrentRoute.Stations[i].OpenRightDoors)
                    {
                        left  = true;
                        right = true;
                    }
                    else
                    {
                        if (Program.CurrentRoute.Stations[i].OpenLeftDoors)
                        {
                            left = false;
                            for (int j = 0; j < Train.Cars.Length; j++)
                            {
                                for (int k = 0; k < Train.Cars[j].Doors.Length; k++)
                                {
                                    if (Train.Cars[j].Doors[k].State != 0.0)
                                    {
                                        left = true; break;
                                    }
                                }
                                if (left)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            left = false;
                        }
                        if (Program.CurrentRoute.Stations[i].OpenRightDoors)
                        {
                            right = false;
                            for (int j = 0; j < Train.Cars.Length; j++)
                            {
                                for (int k = 0; k < Train.Cars[j].Doors.Length; k++)
                                {
                                    if (Train.Cars[j].Doors[k].State != 0.0)
                                    {
                                        right = true; break;
                                    }
                                }
                                if (right)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            right = false;
                        }
                    }
                    // departure sound
                    if (!Train.StationDepartureSoundPlayed)
                    {
                        SoundBuffer buffer = (SoundBuffer)Program.CurrentRoute.Stations[i].DepartureSoundBuffer;
                        if (buffer != null)
                        {
                            double dur = Program.Sounds.GetDuration(buffer);
                            if (Program.CurrentRoute.SecondsSinceMidnight >= Train.StationDepartureTime - dur)
                            {
                                Program.Sounds.PlaySound(buffer, 1.0, 1.0, Program.CurrentRoute.Stations[i].SoundOrigin, false);
                                Train.StationDepartureSoundPlayed = true;
                            }
                        }
                    }
                    for (int j = 0; j < Train.Cars.Length; j++)
                    {
                        if (Train.Cars[j].Doors[0].AnticipatedReopen && Train.Cars[j].Doors[0].State == Train.Cars[j].Doors[0].InterferingObjectRate)
                        {
                            if (Train.Cars[j].Doors[0].NextReopenTime == 0.0)
                            {
                                Train.Cars[j].Doors[0].NextReopenTime = Program.CurrentRoute.SecondsSinceMidnight + Program.CurrentRoute.Stations[i].InterferenceInDoor;
                            }
                            else if (Train.Cars[j].Doors[0].ReopenCounter < Train.Cars[j].Doors[0].ReopenLimit)
                            {
                                if (Program.CurrentRoute.SecondsSinceMidnight >= Train.Cars[j].Doors[0].NextReopenTime)
                                {
                                    OpenTrainDoors(Train, j, true, false);
                                }
                            }
                            else
                            {
                                Train.Cars[j].Doors[0].AnticipatedReopen = false;
                            }
                        }
                        if (Train.Cars[j].Doors[1].AnticipatedReopen && Train.Cars[j].Doors[1].State == Train.Cars[j].Doors[1].InterferingObjectRate)
                        {
                            if (Train.Cars[j].Doors[1].NextReopenTime == 0.0)
                            {
                                Train.Cars[j].Doors[1].NextReopenTime = Program.CurrentRoute.SecondsSinceMidnight + Program.CurrentRoute.Stations[i].InterferenceInDoor;
                            }
                            else if (Train.Cars[j].Doors[1].ReopenCounter < Train.Cars[j].Doors[1].ReopenLimit)
                            {
                                if (Program.CurrentRoute.SecondsSinceMidnight >= Train.Cars[j].Doors[1].NextReopenTime)
                                {
                                    OpenTrainDoors(Train, j, false, true);
                                }
                            }
                            else
                            {
                                Train.Cars[j].Doors[1].AnticipatedReopen = false;
                            }
                        }
                    }
                    TrainDoorState doorState = GetDoorsState(Train, Program.CurrentRoute.Stations[i].OpenLeftDoors, Program.CurrentRoute.Stations[i].OpenRightDoors);
                    if (left | right)
                    {
                        /*
                         * Assume that passengers only board at a scheduled stop
                         * If the player has opened the doors somewhere else (lineside?)
                         * then passengers should not be boarding
                         */
                        if (doorState != TrainDoorState.AllClosed && Interface.CurrentOptions.LoadingSway)
                        {
                            // passengers boarding
                            for (int j = 0; j < Train.Cars.Length; j++)
                            {
                                if (!Train.Cars[j].EnableLoadingSway)
                                {
                                    continue;
                                }
                                double r = 2.0 * Program.CurrentRoute.Stations[i].PassengerRatio * TimeElapsed;
                                if (r >= Program.RandomNumberGenerator.NextDouble())
                                {
                                    int d =
                                        (int)Math.Floor(Program.RandomNumberGenerator.NextDouble() * (double)Train.Cars[j].Doors.Length);
                                    if (Train.Cars[j].Doors[d].State == 1.0)
                                    {
                                        Train.Cars[j].Specs.CurrentRollShakeDirection += (double)Train.Cars[j].Doors[d].Direction;
                                    }
                                }
                            }
                        }
                    }
                    if (Train.Specs.DoorCloseMode == DoorMode.Manual || doorState == TrainDoorState.None || doorState == (TrainDoorState.Closed | TrainDoorState.AllClosed) || (Program.CurrentRoute.Stations[Train.Station].Type == StationType.ChangeEnds || Program.CurrentRoute.Stations[Train.Station].Type == StationType.Jump))
                    {
                        if (left | right)
                        {
                            // departure message
                            if (Program.CurrentRoute.SecondsSinceMidnight > Train.StationDepartureTime && (Program.CurrentRoute.Stations[i].Type != StationType.Terminal || Train != PlayerTrain))
                            {
                                Train.StationState = TrainStopState.Completed;
                                switch (Program.CurrentRoute.Stations[i].Type)
                                {
                                case StationType.Normal:
                                    if (!Train.IsPlayerTrain)
                                    {
                                        break;                                                 // Only trigger messages for the player train
                                    }
                                    if (!Program.CurrentRoute.Stations[i].OpenLeftDoors & !Program.CurrentRoute.Stations[i].OpenRightDoors | Train.Specs.DoorCloseMode != DoorMode.Manual)
                                    {
                                        MessageManager.AddMessage(Translations.GetInterfaceString("message_station_depart"), MessageDependency.None, GameMode.Normal, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                                    }
                                    else
                                    {
                                        MessageManager.AddMessage(Translations.GetInterfaceString("message_station_depart_closedoors"), MessageDependency.None, GameMode.Normal, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                                    }
                                    break;

                                case StationType.ChangeEnds:
                                    // Change ends always jumps to the NEXT station
                                    JumpTrain(Train, i + 1);
                                    break;

                                case StationType.Jump:
                                    // Jumps to an arbritrary station as defined in the routefile
                                    JumpTrain(Train, Program.CurrentRoute.Stations[i].JumpIndex);
                                    break;
                                }
                            }
                        }
                        else
                        {
                            Train.StationState = TrainStopState.Completed;
                            if (Train.IsPlayerTrain & Program.CurrentRoute.Stations[i].Type == StationType.Normal)
                            {
                                MessageManager.AddMessage(Translations.GetInterfaceString("message_station_depart"), MessageDependency.None, GameMode.Normal, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                            }
                        }
                    }
                }
            }
            else
            {
                if (Train.StationState != TrainStopState.Jumping)
                {
                    Train.StationState = TrainStopState.Pending;
                }
            }
            // automatically close doors
            if (Train.Specs.DoorCloseMode != DoorMode.Manual & !Train.Specs.DoorClosureAttempted)
            {
                if (Train.Station == -1 | Train.StationState == TrainStopState.Completed)
                {
                    if ((GetDoorsState(Train, true, true) & TrainDoorState.AllClosed) == 0)
                    {
                        CloseTrainDoors(Train, true, true);
                        Train.Specs.DoorClosureAttempted = true;
                    }
                }
            }
        }
コード例 #39
0
 /// <summary>Register the position to play microphone input.</summary>
 /// <param name="position">The position.</param>
 /// <param name="backwardTolerance">allowed tolerance in the backward direction</param>
 /// <param name="forwardTolerance">allowed tolerance in the forward direction</param>
 public void PlayMicSound(OpenBveApi.Math.Vector3 position, double backwardTolerance, double forwardTolerance)
 {
     MicSources.Add(new MicSource(OpenAlMic, MicStore, position, backwardTolerance, forwardTolerance));
 }
コード例 #40
0
 /// <summary>Plays a sound.</summary>
 /// <param name="buffer">The sound buffer.</param>
 /// <param name="pitch">The pitch change factor.</param>
 /// <param name="volume">The volume change factor.</param>
 /// <param name="position">The position. If a train car is specified, the position is relative to the car, otherwise absolute.</param>
 /// <param name="parent">The parent object the sound is attached to, or a null reference.</param>
 /// <param name="looped">Whether to play the sound in a loop.</param>
 /// <returns>The sound source.</returns>
 public SoundSource PlaySound(SoundBuffer buffer, double pitch, double volume, OpenBveApi.Math.Vector3 position, object parent, bool looped)
 {
     if (Sources.Length == SourceCount)
     {
         Array.Resize(ref Sources, Sources.Length << 1);
     }
     Sources[SourceCount] = new SoundSource(buffer, buffer.Radius, pitch, volume, position, parent, looped);
     SourceCount++;
     return(Sources[SourceCount - 1]);
 }
コード例 #41
0
ファイル: Camera.cs プロジェクト: sladen/openbve2
 // update grid leaf node
 internal static void UpdateGridLeafNode()
 {
     /*
      * Find the leaf node the camera is currently in.
      * */
     ObjectGrid.GridLeafNode leaf;
     if (ObjectGrid.Grid.GetLeafNode(Camera.Position, out leaf)) {
         double x = 0.5 * (leaf.Rectangle.Left + leaf.Rectangle.Right);
         double z = 0.5 * (leaf.Rectangle.Near + leaf.Rectangle.Far);
         Camera.GridLeafNodeCenter = new OpenBveApi.Math.Vector3(x, 0.0, z);
     } else {
         leaf = null;
         Camera.GridLeafNodeCenter = new OpenBveApi.Math.Vector3(0.0, 0.0, 0.0);
     }
     /*
      * Check if the leaf node the camera is in has changed.
      * */
     if (leaf != Camera.GridLeafNode) {
         if (leaf != null) {
             /*
              * The camera is within the bounds of a leaf node.
              * */
             ObjectGrid.GridPopulatedLeafNode[] oldLeafNodes;
             if (Camera.GridLeafNode != null) {
                 oldLeafNodes = Camera.GridLeafNode.VisibleLeafNodes;
             } else {
                 oldLeafNodes = null;
             }
             ObjectGrid.GridPopulatedLeafNode[] newLeafNodes = leaf.VisibleLeafNodes;
             /*
              * Find leaf nodes that were visible before but are not any longer.
              * */
             if (oldLeafNodes != null) {
                 for (int i = 0; i < oldLeafNodes.Length; i++) {
                     bool remove = true;
                     for (int j = 0; j < newLeafNodes.Length; j++) {
                         if (oldLeafNodes[i] == newLeafNodes[j]) {
                             remove = false;
                             break;
                         }
                     }
                     if (remove) {
                         /*
                          * This leaf node is not visible any longer. Remove its
                          * associated transparent faces from the renderer.
                          * */
                         for (int j = 0; j < oldLeafNodes[i].TransparentFaceCount; j++) {
                             Renderer.TransparentWorldFaces.Remove(oldLeafNodes[i].TransparentFaces[j]);
                         }
                         oldLeafNodes[i].TransparentFaceCount = 0;
                     }
                 }
             }
             /*
              * Find leaf nodes that are visible now but were not before.
              * */
             for (int i = 0; i < newLeafNodes.Length; i++) {
                 bool add = true;
                 if (oldLeafNodes != null) {
                     for (int j = 0; j < oldLeafNodes.Length; j++) {
                         if (newLeafNodes[i] == oldLeafNodes[j]) {
                             add = false;
                             break;
                         }
                     }
                 }
                 if (add) {
                     /*
                      * This leaf node has become visible. Add all
                      * its transparent faces to the renderer.
                      * */
                     ObjectGrid.GridPopulatedLeafNode visibleLeaf = newLeafNodes[i];
                     if (visibleLeaf.TransparentFaceCount != 0) {
                         throw new InvalidOperationException("#65517: A bug in the transparency management occured.");
                     }
                     visibleLeaf.LoadTextures();
                     double x = 0.5 * (visibleLeaf.Rectangle.Left + visibleLeaf.Rectangle.Right);
                     double z = 0.5 * (visibleLeaf.Rectangle.Near + visibleLeaf.Rectangle.Far);
                     OpenBveApi.Math.Vector3 offset = new OpenBveApi.Math.Vector3(x, 0.0, z);
                     for (int j = 0; j < visibleLeaf.StaticOpaqueObjectCount; j++) {
                         int libraryIndex = visibleLeaf.StaticOpaqueObjects[j].LibraryIndex;
                         OpenBveApi.Geometry.FaceVertexMesh mesh = ObjectLibrary.Library.Objects[libraryIndex] as OpenBveApi.Geometry.FaceVertexMesh;
                         if (mesh != null) {
                             for (int k = 0; k < mesh.Faces.Length; k++) {
                                 add = false;
                                 if (mesh.Materials[mesh.Faces[k].Material].BlendMode == OpenBveApi.Geometry.BlendMode.Additive) {
                                     add = true;
                                 }
                                 if (!add) {
                                     Textures.ApiHandle apiHandle = mesh.Materials[mesh.Faces[k].Material].DaytimeTexture as Textures.ApiHandle;
                                     if (apiHandle != null) {
                                         Textures.TextureType type = Textures.RegisteredTextures[apiHandle.TextureIndex].Type;
                                         if (type == Textures.TextureType.Unknown) {
                                             throw new InvalidOperationException("#31596: A bug in the texture management occured.");
                                         } else if (type == Textures.TextureType.Alpha) {
                                             add = true;
                                         }
                                     }
                                 }
                                 if (!add) {
                                     for (int h = 0; h < mesh.Faces[k].Vertices.Length; h++) {
                                         if (mesh.Vertices[mesh.Faces[k].Vertices[h]].ReflectiveColor.A != 1.0f) {
                                             add = true;
                                             break;
                                         }
                                     }
                                 }
                                 if (add) {
                                     OpenBveApi.Math.Vector3 position = visibleLeaf.StaticOpaqueObjects[j].GridPosition + offset;
                                     OpenBveApi.Math.Orientation3 orientation = visibleLeaf.StaticOpaqueObjects[j].GridOrientation;
                                     if (visibleLeaf.TransparentFaceCount == visibleLeaf.TransparentFaces.Length) {
                                         Array.Resize<object>(ref visibleLeaf.TransparentFaces, visibleLeaf.TransparentFaces.Length << 1);
                                     }
                                     visibleLeaf.TransparentFaces[visibleLeaf.TransparentFaceCount] = Renderer.TransparentWorldFaces.Add(libraryIndex, k, position, orientation);
                                     visibleLeaf.TransparentFaceCount++;
                                 }
                             }
                         }
                     }
                 }
             }
         } else if (Camera.GridLeafNode != null) {
             /*
              * Before, the camera was inside the bounds of
              * a leaf node, but now, it is not anymore.
              * Remove the transparent faces associated
              * to the old leaf node from the renderer.
              * */
             ObjectGrid.GridPopulatedLeafNode[] oldLeafNodes = Camera.GridLeafNode.VisibleLeafNodes;
             for (int i = 0; i < oldLeafNodes.Length; i++) {
                 for (int j = 0; j < oldLeafNodes[i].TransparentFaceCount; j++) {
                     Renderer.TransparentWorldFaces.Remove(oldLeafNodes[i].TransparentFaces[j]);
                 }
                 oldLeafNodes[i].TransparentFaceCount = 0;
             }
         }
     }
     /*
      * Apply the found leaf node.
      * */
     Camera.GridLeafNode = leaf;
 }
コード例 #42
0
ファイル: Sounds.cs プロジェクト: tsdworks/RAGLINK
 /// <summary>Register the position to play microphone input.</summary>
 /// <param name="position">The position.</param>
 /// <param name="backwardTolerance">allowed tolerance in the backward direction</param>
 /// <param name="forwardTolerance">allowed tolerance in the forward direction</param>
 internal static void PlayMicSound(OpenBveApi.Math.Vector3 position, double backwardTolerance, double forwardTolerance)
 {
     MicSources.Add(new MicSource(position, backwardTolerance, forwardTolerance));
 }
コード例 #43
0
ファイル: Renderer.Lighting.cs プロジェクト: sladen/openbve2
 // --- functions ---
 internal static void InitializeLighting(OpenBveApi.Route.DirectionalLight light)
 {
     LightPosition = -light.LightDirection;
     LightAmbientColor = light.AmbientLight;
     LightDiffuseColor = light.DiffuseLight;
 }
コード例 #44
0
ファイル: Sounds.Update.cs プロジェクト: tsdworks/RAGLINK-2
        /// <summary>Updates the sound component. Should be called every frame.</summary>
        /// <param name="timeElapsed">The time in seconds that elapsed since the last call to this function.</param>
        private static void UpdateInverseModel(double timeElapsed)
        {
            /*
             * Set up the listener.
             * */
            OpenBveApi.Math.Vector3      listenerPosition    = World.AbsoluteCameraPosition;
            OpenBveApi.Math.Orientation3 listenerOrientation = new OpenBveApi.Math.Orientation3(World.AbsoluteCameraSide, World.AbsoluteCameraUp, World.AbsoluteCameraDirection);
            OpenBveApi.Math.Vector3      listenerVelocity;
            if (World.CameraMode == CameraViewMode.Interior | World.CameraMode == CameraViewMode.InteriorLookAhead | World.CameraMode == CameraViewMode.Exterior)
            {
                TrainManager.Car        car  = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar];
                OpenBveApi.Math.Vector3 diff = car.FrontAxle.Follower.WorldPosition - car.RearAxle.Follower.WorldPosition;
                if (diff.IsNullVector())
                {
                    listenerVelocity = car.Specs.CurrentSpeed * OpenBveApi.Math.Vector3.Forward;
                }
                else
                {
                    listenerVelocity = car.Specs.CurrentSpeed * OpenBveApi.Math.Vector3.Normalize(diff);
                }
            }
            else
            {
                listenerVelocity = OpenBveApi.Math.Vector3.Zero;
            }
            AL.Listener(ALListener3f.Position, 0.0f, 0.0f, 0.0f);
            AL.Listener(ALListener3f.Velocity, (float)listenerVelocity.X, (float)listenerVelocity.Y, (float)listenerVelocity.Z);
            var Orientation = new float[] { (float)listenerOrientation.Z.X, (float)listenerOrientation.Z.Y, (float)listenerOrientation.Z.Z, -(float)listenerOrientation.Y.X, -(float)listenerOrientation.Y.Y, -(float)listenerOrientation.Y.Z };

            AL.Listener(ALListenerfv.Orientation, ref Orientation);

            /*
             * Set up the atmospheric attributes.
             * */
            double elevation      = World.AbsoluteCameraPosition.Y + Game.RouteInitialElevation;
            double airTemperature = Game.GetAirTemperature(elevation);
            double airPressure    = Game.GetAirPressure(elevation, airTemperature);
            double speedOfSound   = Game.GetSpeedOfSound(airPressure, airTemperature);

            try
            {
                AL.SpeedOfSound((float)speedOfSound);
            }
            catch { }

            /*
             * Collect all sounds that are to be played
             * and ensure that all others are stopped.
             * */
            List <SoundSourceAttenuation> toBePlayed = new List <SoundSourceAttenuation>();

            for (int i = 0; i < SourceCount; i++)
            {
                if (Sources[i].State == SoundSourceState.StopPending)
                {
                    /*
                     * The sound is still playing but is to be stopped.
                     * Stop the sound, then remove it from the list of
                     * sound sources.
                     * */
                    AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                    Sources[i].State            = SoundSourceState.Stopped;
                    Sources[i].OpenAlSourceName = 0;
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (Sources[i].State == SoundSourceState.Stopped)
                {
                    /*
                     * The sound was already stopped. Remove it from
                     * the list of sound sources.
                     * */
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (GlobalMute)
                {
                    /*
                     * The sound is playing or about to be played, but
                     * the global mute option is enabled. Stop the sound
                     * sound if necessary, then remove it from the list
                     * of sound sources if the sound is not looping.
                     * */
                    if (Sources[i].State == SoundSourceState.Playing)
                    {
                        AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                        Sources[i].State            = SoundSourceState.PlayPending;
                        Sources[i].OpenAlSourceName = 0;
                    }
                    if (!Sources[i].Looped)
                    {
                        Sources[i].State            = SoundSourceState.Stopped;
                        Sources[i].OpenAlSourceName = 0;
                        Sources[i] = Sources[SourceCount - 1];
                        SourceCount--;
                        i--;
                    }
                }
                else
                {
                    /*
                     * The sound is to be played or is already playing.
                     * */
                    if (Sources[i].State == SoundSourceState.Playing)
                    {
                        int state;
                        AL.GetSource(Sources[i].OpenAlSourceName, ALGetSourcei.SourceState, out state);
                        if (state != (int)ALSourceState.Initial & state != (int)ALSourceState.Playing)
                        {
                            /*
                             * The sound is not playing any longer.
                             * Remove it from the list of sound sources.
                             * */
                            AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                            Sources[i].State            = SoundSourceState.Stopped;
                            Sources[i].OpenAlSourceName = 0;
                            Sources[i] = Sources[SourceCount - 1];
                            SourceCount--;
                            i--;
                            continue;
                        }
                    }

                    /*
                     * Calculate the gain, then add the sound
                     * to the list of sounds to be played.
                     * */
                    OpenBveApi.Math.Vector3 position;
                    if (Sources[i].Train != null)
                    {
                        OpenBveApi.Math.Vector3 direction;
                        Sources[i].Train.Cars[Sources[i].Car].CreateWorldCoordinates(Sources[i].Position, out position, out direction);
                    }
                    else
                    {
                        position = Sources[i].Position;
                    }
                    OpenBveApi.Math.Vector3 positionDifference = position - listenerPosition;
                    double distance = positionDifference.Norm();
                    double radius   = Sources[i].Radius;
                    if (World.CameraMode == CameraViewMode.Interior | World.CameraMode == CameraViewMode.InteriorLookAhead)
                    {
                        if (Sources[i].Train != TrainManager.PlayerTrain || Sources[i].Car != TrainManager.PlayerTrain.DriverCar)
                        {
                            radius *= 0.5;
                        }
                    }
                    double gain;
                    if (distance < 2.0 * radius)
                    {
                        gain = 1.0 - distance * distance * (4.0 * radius - distance) / (16.0 * radius * radius * radius);
                    }
                    else
                    {
                        gain = radius / distance;
                    }
                    gain *= Sources[i].Volume;
                    if (gain <= 0.0)
                    {
                        /*
                         * The gain is too low. Stop the sound if playing,
                         * but keep looping sounds pending.
                         * */
                        if (Sources[i].State == SoundSourceState.Playing)
                        {
                            AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                            Sources[i].State            = SoundSourceState.PlayPending;
                            Sources[i].OpenAlSourceName = 0;
                        }
                        if (!Sources[i].Looped)
                        {
                            Sources[i].State            = SoundSourceState.Stopped;
                            Sources[i].OpenAlSourceName = 0;
                            Sources[i] = Sources[SourceCount - 1];
                            SourceCount--;
                            i--;
                        }
                    }
                    else
                    {
                        /*
                         * Add the source.
                         * */
                        toBePlayed.Add(new SoundSourceAttenuation(Sources[i], gain, distance));
                    }
                }
            }

            /*
             * Now that we have the list of sounds that are to be played,
             * sort them by their gain so that we can determine and
             * adjust the clamp factor.
             * */
            double clampFactor = Math.Exp(LogClampFactor);

            for (int i = 0; i < toBePlayed.Count; i++)
            {
                toBePlayed[i].Gain -= clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance;
            }
            toBePlayed.Sort();
            for (int i = 0; i < toBePlayed.Count; i++)
            {
                toBePlayed[i].Gain += clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance;
            }
            double desiredLogClampFactor;
            int    index = Interface.CurrentOptions.SoundNumber;

            if (toBePlayed.Count <= index)
            {
                desiredLogClampFactor = MinLogClampFactor;
            }
            else
            {
                double cutoffDistance = toBePlayed[index].Distance;
                if (cutoffDistance <= 0.0)
                {
                    desiredLogClampFactor = MaxLogClampFactor;
                }
                else
                {
                    double cutoffGain = toBePlayed[index].Gain;
                    desiredLogClampFactor = Math.Log(cutoffGain / (cutoffDistance * cutoffDistance));
                    if (desiredLogClampFactor < MinLogClampFactor)
                    {
                        desiredLogClampFactor = MinLogClampFactor;
                    }
                    else if (desiredLogClampFactor > MaxLogClampFactor)
                    {
                        desiredLogClampFactor = MaxLogClampFactor;
                    }
                }
            }
            const double rate = 3.0;

            if (LogClampFactor < desiredLogClampFactor)
            {
                LogClampFactor += timeElapsed * rate;
                if (LogClampFactor > desiredLogClampFactor)
                {
                    LogClampFactor = desiredLogClampFactor;
                }
            }
            else if (LogClampFactor > desiredLogClampFactor)
            {
                LogClampFactor -= timeElapsed * rate;
                if (LogClampFactor < desiredLogClampFactor)
                {
                    LogClampFactor = desiredLogClampFactor;
                }
            }

            /*
             * Play the sounds.
             * */
            clampFactor = Math.Exp(LogClampFactor);
            for (int i = index; i < toBePlayed.Count; i++)
            {
                toBePlayed[i].Gain = 0.0;
            }
            for (int i = 0; i < toBePlayed.Count; i++)
            {
                SoundSource source = toBePlayed[i].Source;
                double      gain   = toBePlayed[i].Gain - clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance;
                if (gain <= 0.0)
                {
                    /*
                     * Stop the sound.
                     * */
                    if (source.State == SoundSourceState.Playing)
                    {
                        AL.DeleteSources(1, ref source.OpenAlSourceName);
                        source.State            = SoundSourceState.PlayPending;
                        source.OpenAlSourceName = 0;
                    }
                    if (!source.Looped)
                    {
                        source.State            = SoundSourceState.Stopped;
                        source.OpenAlSourceName = 0;
                    }
                }
                else
                {
                    /*
                     * Ensure the buffer is loaded, then play the sound.
                     * */
                    if (source.State != SoundSourceState.Playing)
                    {
                        LoadBuffer(source.Buffer);
                        if (source.Buffer.Loaded)
                        {
                            AL.GenSources(1, out source.OpenAlSourceName);
                            AL.Source(source.OpenAlSourceName, ALSourcei.Buffer, source.Buffer.OpenAlBufferName);
                        }
                        else
                        {
                            /*
                             * We cannot play the sound because
                             * the buffer could not be loaded.
                             * */
                            source.State = SoundSourceState.Stopped;
                            continue;
                        }
                    }
                    OpenBveApi.Math.Vector3 position;
                    OpenBveApi.Math.Vector3 velocity;
                    if (source.Train != null)
                    {
                        OpenBveApi.Math.Vector3 direction;
                        source.Train.Cars[source.Car].CreateWorldCoordinates(source.Position, out position, out direction);
                        velocity = source.Train.Cars[source.Car].Specs.CurrentSpeed * direction;
                    }
                    else
                    {
                        position = source.Position;
                        velocity = OpenBveApi.Math.Vector3.Zero;
                    }
                    position -= listenerPosition;
                    AL.Source(source.OpenAlSourceName, ALSource3f.Position, (float)position.X, (float)position.Y, (float)position.Z);
                    AL.Source(source.OpenAlSourceName, ALSource3f.Velocity, (float)velocity.X, (float)velocity.Y, (float)velocity.Z);
                    AL.Source(source.OpenAlSourceName, ALSourcef.Pitch, (float)source.Pitch);
                    AL.Source(source.OpenAlSourceName, ALSourcef.Gain, (float)gain);
                    if (source.State != SoundSourceState.Playing)
                    {
                        AL.Source(source.OpenAlSourceName, ALSourceb.Looping, source.Looped);
                        AL.SourcePlay(source.OpenAlSourceName);
                        source.State = SoundSourceState.Playing;
                    }
                }
            }
        }
コード例 #45
0
ファイル: Sounds.cs プロジェクト: City-busz/OpenBVE
 /// <summary>Plays a sound.</summary>
 /// <param name="buffer">The sound buffer.</param>
 /// <param name="pitch">The pitch change factor.</param>
 /// <param name="volume">The volume change factor.</param>
 /// <param name="position">The position. If a train and car are specified, the position is relative to the car, otherwise absolute.</param>
 /// <param name="train">The train the sound is attached to, or a null reference.</param>
 /// <param name="car">The car in the train the sound is attached to.</param>
 /// <param name="looped">Whether to play the sound in a loop.</param>
 /// <returns>The sound source.</returns>
 internal static SoundSource PlaySound(SoundBuffer buffer, double pitch, double volume, OpenBveApi.Math.Vector3 position, TrainManager.Train train, int car, bool looped)
 {
     if (Sources.Length == SourceCount)
     {
         Array.Resize <SoundSource>(ref Sources, Sources.Length << 1);
     }
     Sources[SourceCount] = new SoundSource(buffer, buffer.Radius, pitch, volume, position, train, car, looped);
     SourceCount++;
     return(Sources[SourceCount - 1]);
 }
コード例 #46
0
 private static void PlaySound(ref int SoundSourceIndex, bool ReturnHandle, int SoundBufferIndex, TrainManager.Train Train, int CarIndex, Vector3 Position, Importance Important, bool Looped, double Pitch, double Gain)
 {
     if (OpenAlContext != ContextHandle.Zero)
     {
         if (Game.MinimalisticSimulation & Important == Importance.DontCare | SoundBufferIndex == -1)
         {
             return;
         }
         if (SoundSourceIndex >= 0)
         {
             StopSound(ref SoundSourceIndex);
         }
         int i;
         for (i = 0; i < SoundSources.Length; i++)
         {
             if (SoundSources[i] == null)
             {
                 break;
             }
         }
         if (i >= SoundSources.Length)
         {
             Array.Resize <SoundSource>(ref SoundSources, SoundSources.Length << 1);
         }
         SoundSources[i]                   = new SoundSource();
         SoundSources[i].Position          = Position;
         SoundSources[i].OpenAlPosition    = new float[] { 0.0f, 0.0f, 0.0f };
         SoundSources[i].OpenAlVelocity    = new float[] { 0.0f, 0.0f, 0.0f };
         SoundSources[i].SoundBufferIndex  = SoundBufferIndex;
         SoundSources[i].Radius            = SoundBuffers[SoundBufferIndex].Radius;
         SoundSources[i].Pitch             = (float)Pitch;
         SoundSources[i].Gain              = (float)Gain;
         SoundSources[i].Looped            = Looped;
         SoundSources[i].Suppressed        = true;
         SoundSources[i].FinishedPlaying   = false;
         SoundSources[i].Train             = Train;
         SoundSources[i].CarIndex          = CarIndex;
         SoundSources[i].OpenAlSourceIndex = new OpenAlIndex(0, false);
         SoundSources[i].HasHandle         = ReturnHandle;
         SoundSourceIndex                  = i;
     }
 }