Represents an orientation in three-dimensional space.
Esempio n. 1
0
        /// <summary>Rotates a vector from the default orientation into a specified orientation.</summary>
        /// <param name="vector">The vector.</param>
        /// <param name="orientation">The orientation.</param>
        /// <returns>The rotated vector.</returns>
        /// <remarks>The default orientation is X = {1, 0, 0), Y = {0, 1, 0} and Z = {0, 0, 1}.</remarks>
        public static Vector3 Rotate(Vector3 vector, Orientation3 orientation)
        {
            double x = orientation.X.X * vector.X + orientation.Y.X * vector.Y + orientation.Z.X * vector.Z;
            double y = orientation.X.Y * vector.X + orientation.Y.Y * vector.Y + orientation.Z.Y * vector.Z;
            double z = orientation.X.Z * vector.X + orientation.Y.Z * vector.Y + orientation.Z.Z * vector.Z;

            return(new Vector3(x, y, z));
        }
Esempio n. 2
0
        /// <summary>Rotates the vector from the default orientation into a specified orientation.</summary>
        /// <param name="orientation">The orientation.</param>
        /// <remarks>The default orientation is X = {1, 0, 0), Y = {0, 1, 0} and Z = {0, 0, 1}.</remarks>
        public void Rotate(Orientation3 orientation)
        {
            double x = (orientation.X.X * this.X) + (orientation.Y.X * this.Y) + (orientation.Z.X * this.Z);
            double y = (orientation.X.Y * this.X) + (orientation.Y.Y * this.Y) + (orientation.Z.Y * this.Z);
            double z = (orientation.X.Z * this.X) + (orientation.Y.Z * this.Y) + (orientation.Z.Z * this.Z);

            this = new Vector3(x, y, z);
        }
Esempio n. 3
0
        /// <summary>Translates a vector by a specified offset that is measured along a specified orientation.</summary>
        /// <param name="vector">The vector.</param>
        /// <param name="orientation">The orientation.</param>
        /// <param name="offset">The offset measured in the specified orientation.</param>
        public static Vector3 Translate(Vector3 vector, Orientation3 orientation, Vector3 offset)
        {
            double x = vector.X + orientation.X.X * offset.X + orientation.Y.X * offset.Y + orientation.Z.X * offset.Z;
            double y = vector.Y + orientation.X.Y * offset.X + orientation.Y.Y * offset.Y + orientation.Z.Y * offset.Z;
            double z = vector.Z + orientation.X.Z * offset.X + orientation.Y.Z * offset.Y + orientation.Z.Z * offset.Z;

            return(new Vector3(x, y, z));
        }
Esempio n. 4
0
		/// <summary>Rotates the object from the default orientation into the specified orientation.</summary>
		/// <param name="orientation">The target orientation.</param>
		/// <remarks>The default orientation is X = {1, 0, 0), Y = {0, 1, 0} and Z = {0, 0, 1}.</remarks>
		public override void Rotate(Orientation3 orientation) {
			for (int i = 0; i < this.SpatialCoordinates.Length; i++) {
				this.SpatialCoordinates[i].Rotate(orientation);
			}
			for (int i = 0; i < this.Normals.Length; i++) {
				this.Normals[i].Rotate(orientation);
			}
		}
Esempio n. 5
0
        /// <summary>Rotates the vector from the default orientation into a specified orientation.</summary>
        /// <param name="orientation">The orientation.</param>
        /// <remarks>The default orientation is X = {1, 0, 0), Y = {0, 1, 0} and Z = {0, 0, 1}.</remarks>
        public void Rotate(Orientation3 orientation)
        {
            double x = orientation.X.X * this.X + orientation.Y.X * this.Y + orientation.Z.X * this.Z;
            double y = orientation.X.Y * this.X + orientation.Y.Y * this.Y + orientation.Z.Y * this.Z;
            double z = orientation.X.Z * this.X + orientation.Y.Z * this.Y + orientation.Z.Z * this.Z;

            this = new Vector3(x, y, z);
        }
Esempio n. 6
0
        /// <summary>Rotates a vector from the default orientation into a specified orientation.</summary>
        /// <param name="vector">The vector.</param>
        /// <param name="orientation">The orientation.</param>
        /// <returns>The rotated vector.</returns>
        /// <remarks>The default orientation is X = {1, 0, 0), Y = {0, 1, 0} and Z = {0, 0, 1}.</remarks>
        public static Vector3 Rotate(Vector3 vector, Orientation3 orientation)
        {
            double x = (orientation.X.X * vector.X) + (orientation.Y.X * vector.Y) + (orientation.Z.X * vector.Z);
            double y = (orientation.X.Y * vector.X) + (orientation.Y.Y * vector.Y) + (orientation.Z.Y * vector.Z);
            double z = (orientation.X.Z * vector.X) + (orientation.Y.Z * vector.Y) + (orientation.Z.Z * vector.Z);

            return(new Vector3(x, y, z));
        }
Esempio n. 7
0
        /// <summary>Rotates the vector from the default orientation into a specified orientation.</summary>
        /// <param name="orientation">The orientation.</param>
        /// <remarks>The default orientation is X = {1, 0, 0), Y = {0, 1, 0} and Z = {0, 0, 1}.</remarks>
        public void Rotate(Orientation3 orientation)
        {
            double x = orientation.X.X * this.X + orientation.Y.X * this.Y + orientation.Z.X * this.Z;
            double y = orientation.X.Y * this.X + orientation.Y.Y * this.Y + orientation.Z.Y * this.Z;
            double z = orientation.X.Z * this.X + orientation.Y.Z * this.Y + orientation.Z.Z * this.Z;

            X = x;
            Y = y;
            Z = z;
        }
Esempio n. 8
0
 /// <summary>Translates the vector by a specified offset that is measured in a specified orientation.</summary>
 /// <param name="orientation">The orientation.</param>
 /// <param name="offset">The offset measured in the specified orientation.</param>
 public void Translate(Orientation3 orientation, Vector3 offset)
 {
     this.X += orientation.X.X * offset.X + orientation.Y.X * offset.Y + orientation.Z.X * offset.Z;
     this.Y += orientation.X.Y * offset.X + orientation.Y.Y * offset.Y + orientation.Z.Y * offset.Z;
     this.Z += orientation.X.Z * offset.X + orientation.Y.Z * offset.Y + orientation.Z.Z * offset.Z;
 }
Esempio n. 9
0
		/// <summary>Rotates a vector from the default orientation into a specified orientation.</summary>
		/// <param name="vector">The vector.</param>
		/// <param name="orientation">The orientation.</param>
		/// <returns>The rotated vector.</returns>
		/// <remarks>The default orientation is X = {1, 0, 0), Y = {0, 1, 0} and Z = {0, 0, 1}.</remarks>
		public static Vector3 Rotate(Vector3 vector, Orientation3 orientation) {
			double x = orientation.X.X * vector.X + orientation.Y.X * vector.Y + orientation.Z.X * vector.Z;
			double y = orientation.X.Y * vector.X + orientation.Y.Y * vector.Y + orientation.Z.Y * vector.Z;
			double z = orientation.X.Z * vector.X + orientation.Y.Z * vector.Y + orientation.Z.Z * vector.Z;
			return new Vector3(x, y, z);
		}
Esempio n. 10
0
		/// <summary>Translates a vector by a specified offset that is measured along a specified orientation.</summary>
		/// <param name="vector">The vector.</param>
		/// <param name="orientation">The orientation.</param>
		/// <param name="offset">The offset measured in the specified orientation.</param>
		public static Vector3 Translate(Vector3 vector, Orientation3 orientation, Vector3 offset) {
			double x = vector.X + orientation.X.X * offset.X + orientation.Y.X * offset.Y + orientation.Z.X * offset.Z;
			double y = vector.Y + orientation.X.Y * offset.X + orientation.Y.Y * offset.Y + orientation.Z.Y * offset.Z;
			double z = vector.Z + orientation.X.Z * offset.X + orientation.Y.Z * offset.Y + orientation.Z.Z * offset.Z;
			return new Vector3(x, y, z);
		}
Esempio n. 11
0
 /// <summary>Rotates the object from the default orientation into the specified orientation.</summary>
 /// <param name="orientation">The target orientation.</param>
 /// <remarks>The default orientation is X = {1, 0, 0), Y = {0, 1, 0} and Z = {0, 0, 1}.</remarks>
 public abstract void Rotate(Orientation3 orientation);
Esempio n. 12
0
 // --- functions ---
 /// <summary>Gets the intensity of the glow.</summary>
 /// <param name="cameraPosition">The position of the camera.</param>
 /// <param name="cameraOrientation">The orientation of the camera.</param>
 /// <param name="objectPosition">The position of the object.</param>
 /// <param name="objectOrientation">The orientation of the object.</param>
 /// <returns>The intensity of the glow expressed as a value between 0 and 1.</returns>
 public override double GetIntensity(Vector3 cameraPosition, Orientation3 cameraOrientation, Vector3 objectPosition, Vector3 objectOrientation)
 {
     /* The underlying formula for the intensity is
      *    i = d^2 / (d^2 + h^2)
      * where
      *    i = intensity
      *    d = distance between object and camera
      *    h = distance at which intensity is 50% */
     double distanceSquared = (objectPosition - cameraPosition).NormSquared();
     return distanceSquared / (distanceSquared + this.HalfDistanceSquared);
 }
Esempio n. 13
0
        /// <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 == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead | World.CameraMode == World.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.Null;
            }
            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;
                    switch (Sources[i].Type)
                    {
                    case SoundType.TrainCar:
                        OpenBveApi.Math.Vector3 direction;
                        var Train = (TrainManager.Train)Sources[i].Parent;
                        Train.Cars[Sources[i].Car].CreateWorldCoordinates(Sources[i].Position.X, Sources[i].Position.Y, Sources[i].Position.Z, out position.X, out position.Y, out position.Z, out direction.X, out direction.Y, out direction.Z);
                        break;

                    case SoundType.AnimatedObject:
                        var WorldSound = (ObjectManager.WorldSound)Sources[i].Parent;
                        position = WorldSound.Follower.WorldPosition + WorldSound.Position;
                        break;

                    default:
                        position = Sources[i].Position;
                        break;
                    }
                    OpenBveApi.Math.Vector3 positionDifference = position - listenerPosition;
                    double distance = positionDifference.Norm();
                    double radius   = Sources[i].Radius;
                    if (World.CameraMode == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead)
                    {
                        if (Sources[i].Parent != 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;
                    switch (source.Type)
                    {
                    case SoundType.TrainCar:
                        OpenBveApi.Math.Vector3 direction;
                        var Train = (TrainManager.Train)source.Parent;
                        Train.Cars[source.Car].CreateWorldCoordinates(source.Position.X, source.Position.Y, source.Position.Z, out position.X, out position.Y, out position.Z, out direction.X, out direction.Y, out direction.Z);
                        velocity = Train.Cars[source.Car].Specs.CurrentSpeed * direction;
                        break;

                    case SoundType.AnimatedObject:
                        var WorldSound = (ObjectManager.WorldSound)source.Parent;
                        position = WorldSound.Follower.WorldPosition + WorldSound.Position;
                        velocity = OpenBveApi.Math.Vector3.Null;
                        break;

                    default:
                        position = source.Position;
                        velocity = OpenBveApi.Math.Vector3.Null;
                        break;
                    }
                    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;
                    }
                }
            }
        }
Esempio n. 14
0
        /// <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;
            if (World.CameraMode == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead | World.CameraMode == World.CameraViewMode.Exterior)
            {
                TrainManager.Car        car  = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar];
                OpenBveApi.Math.Vector3 diff = car.FrontAxle.Follower.WorldPosition - car.RearAxle.Follower.WorldPosition;
                listenerVelocity = car.Specs.CurrentSpeed * OpenBveApi.Math.Vector3.Normalize(diff) + World.CameraAlignmentSpeed.Position;
            }
            else
            {
                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 direction;
                    OpenBveApi.Math.Vector3 position;
                    OpenBveApi.Math.Vector3 velocity;

                    switch (Sources[i].Type)
                    {
                    case SoundType.TrainCar:
                        var Train = (TrainManager.Train)Sources[i].Parent;
                        Train.Cars[Sources[i].Car].CreateWorldCoordinates(Sources[i].Position.X, Sources[i].Position.Y, Sources[i].Position.Z, out position.X, out position.Y, out position.Z, out direction.X, out direction.Y, out direction.Z);
                        velocity = Train.Cars[Sources[i].Car].Specs.CurrentSpeed * direction;
                        break;

                    case SoundType.AnimatedObject:
                        var WorldSound = (ObjectManager.WorldSound)Sources[i].Parent;
                        //TODO: Calculate speed...
                        position = WorldSound.Follower.WorldPosition + WorldSound.Position;
                        velocity = Vector3.Null;
                        break;

                    default:
                        position = Sources[i].Position;
                        velocity = Vector3.Null;
                        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 == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead)
                        {
                            if (Sources[i].Parent != 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;
            }
        }
Esempio n. 15
0
 // constructors
 /// <summary>Creates a new instance of this structure.</summary>
 /// <param name="segment">The physical track segment the point lies on.</param>
 /// <param name="position">The position.</param>
 /// <param name="orientation">The orientation, either with or without factoring in the Roll parameter.</param>
 /// <param name="orientationIncludesRoll">Whether the Orientation has the Roll parameter factored in.</param>
 /// <param name="roll">The roll expressed as an angle.</param>
 public SegmentPoint(PhysicalSegment segment, Math.Vector3 position, Math.Orientation3 orientation, bool orientationIncludesRoll, double roll)
 {
     this.Segment = segment;
     this.Position = position;
     if (orientationIncludesRoll) {
         this.OrientationWithRoll = orientation;
         this.OrientationWithoutRoll = Math.Orientation3.RotateAroundZAxis(orientation, System.Math.Cos(roll), -System.Math.Sin(roll));
     } else {
         this.OrientationWithoutRoll = orientation;
         this.OrientationWithRoll = Math.Orientation3.RotateAroundZAxis(orientation, System.Math.Cos(roll), System.Math.Sin(roll));
     }
     this.Roll = roll;
 }
Esempio n. 16
0
 /// <summary>Translates the object by the specified offset that is measured in the specified orientation.</summary>
 /// <param name="orientation">The orientation along which to translate.</param>
 /// <param name="offset">The offset measured in the specified orientation.</param>
 public override void Translate(Orientation3 orientation, Vector3 offset)
 {
     for (int i = 0; i < this.SpatialCoordinates.Length; i++) {
         this.SpatialCoordinates[i].Translate(orientation, offset);
     }
 }
Esempio n. 17
0
 // constructors
 /// <summary>Creates a new instance of this class.</summary>
 /// <param name="position">The default position of the camera.</param>
 /// <param name="orientation">The default orientation of the camera.</param>
 /// <param name="lightingModel">The lighting model used by this route.</param>
 public RouteData(Math.Vector3 position, Math.Orientation3 orientation, LightingModel lightingModel)
 {
     this.Position = position;
     this.Orientation = orientation;
     this.LightingModel = lightingModel;
 }
Esempio n. 18
0
 /// <summary>Gets the intensity of the glow.</summary>
 /// <param name="cameraPosition">The position of the camera.</param>
 /// <param name="cameraOrientation">The orientation of the camera.</param>
 /// <param name="objectPosition">The position of the object.</param>
 /// <param name="objectOrientation">The orientation of the object.</param>
 /// <returns>The intensity of the glow expressed as a value between 0 and 1.</returns>
 public abstract double GetIntensity(Vector3 cameraPosition, Orientation3 cameraOrientation, Vector3 objectPosition, Vector3 objectOrientation);
Esempio n. 19
0
		/// <summary>Translates the vector by a specified offset that is measured in a specified orientation.</summary>
		/// <param name="orientation">The orientation.</param>
		/// <param name="offset">The offset measured in the specified orientation.</param>
		public void Translate(Orientation3 orientation, Vector3 offset) {
			this.X += orientation.X.X * offset.X + orientation.Y.X * offset.Y + orientation.Z.X * offset.Z;
			this.Y += orientation.X.Y * offset.X + orientation.Y.Y * offset.Y + orientation.Z.Y * offset.Z;
			this.Z += orientation.X.Z * offset.X + orientation.Y.Z * offset.Y + orientation.Z.Z * offset.Z;
		}
Esempio n. 20
0
 /// <summary>Translates the object by the specified offset that is measured in the specified orientation.</summary>
 /// <param name="orientation">The orientation along which to translate.</param>
 /// <param name="offset">The offset measured in the specified orientation.</param>
 public abstract void Translate(Orientation3 orientation, Vector3 offset);
Esempio n. 21
0
		/// <summary>Rotates the vector from the default orientation into a specified orientation.</summary>
		/// <param name="orientation">The orientation.</param>
		/// <remarks>The default orientation is X = {1, 0, 0), Y = {0, 1, 0} and Z = {0, 0, 1}.</remarks>
		public void Rotate(Orientation3 orientation) {
			double x = orientation.X.X * this.X + orientation.Y.X * this.Y + orientation.Z.X * this.Z;
			double y = orientation.X.Y * this.X + orientation.Y.Y * this.Y + orientation.Z.Y * this.Z;
			double z = orientation.X.Z * this.X + orientation.Y.Z * this.Y + orientation.Z.Z * this.Z;
			this = new Vector3(x, y, z);
		}