Пример #1
0
		/// <summary>
		/// Copies the given Line Magnet's data into this Line Magnet's data
		/// </summary>
		/// <param name="cMagnetToCopy">The Line Magnet to copy from</param>
		public void CopyFrom(MagnetLine cMagnetToCopy)
		{
			base.CopyFrom(cMagnetToCopy);
			PositionOnLine = cMagnetToCopy.PositionOnLine;
			Direction = cMagnetToCopy.Direction;
		}
Пример #2
0
		/// <summary>
		/// Copy Constructor
		/// </summary>
		/// <param name="cMagnetToCopy">The Line Magnet to copy from</param>
		public MagnetLine(MagnetLine cMagnetToCopy)
			: base(MagnetModes.Attract, DistanceFunctions.Constant, 0, 0, 0, 0)
		{
			CopyFrom(cMagnetToCopy);
		}
Пример #3
0
 /// <summary>
 /// Copies the given Line Magnet's data into this Line Magnet's data
 /// </summary>
 /// <param name="cMagnetToCopy">The Line Magnet to copy from</param>
 public void CopyFrom(MagnetLine cMagnetToCopy)
 {
     base.CopyFrom(cMagnetToCopy);
     PositionOnLine = cMagnetToCopy.PositionOnLine;
     Direction      = cMagnetToCopy.Direction;
 }
Пример #4
0
        /// <summary>
        /// Returns the vector force that a Magnet should exert on a Particle
        /// </summary>
        /// <param name="cMagnet">The Magnet affecting the Particle</param>
        /// <param name="cParticle">The Particle being affected by the Magnet</param>
        /// <returns>Returns the vector force that a Magnet should exert on a Particle</returns>
        protected Vector3 CalculateForceMagnetShouldExertOnParticle(DefaultParticleSystemMagnet cMagnet, DPSFDefaultBaseParticle cParticle)
        {
            // Variable to store the Force to Exert on the Particle
            Vector3 sForceToExertOnParticle = Vector3.Zero;

            // Calculate which Direction to push the Particle
            Vector3 sDirectionToPushParticle;

            // If this is a Point Magnet
            if (cMagnet.MagnetType == DefaultParticleSystemMagnet.MagnetTypes.PointMagnet)
            {
                // Cast the Magnet to the proper type
                MagnetPoint cPointMagnet = (MagnetPoint)cMagnet;

                // Calculate the direction to attract the Particle to the point in space where the Magnet is
                sDirectionToPushParticle = cPointMagnet.PositionData.Position - cParticle.Position;
            }
            // Else If this is a Line Magnet
            else if (cMagnet.MagnetType == DefaultParticleSystemMagnet.MagnetTypes.LineMagnet)
            {
                // Cast the Magnet to the proper type
                MagnetLine cLineMagnet = (MagnetLine)cMagnet;

                // Calculate the closest point on the Line to the Particle.
                // Equation taken from http://ozviz.wasp.uwa.edu.au/~pbourke/geometry/pointline/
                // Also explained at http://www.allegro.cc/forums/thread/589720

                // Calculate 2 points on the Line
                Vector3 sPosition1 = cLineMagnet.PositionOnLine;
                Vector3 sPosition2 = cLineMagnet.PositionOnLine + cLineMagnet.Direction;

                // Put calculations into temp variables for speed and easy readability
                float fA = cParticle.Position.X - sPosition1.X;
                float fB = cParticle.Position.Y - sPosition1.Y;
                float fC = cParticle.Position.Z - sPosition1.Z;
                float fD = sPosition2.X - sPosition1.X;
                float fE = sPosition2.Y - sPosition1.Y;
                float fF = sPosition2.Z - sPosition1.Z;

                // Next calculate the value of U.
                // NOTE: The Direction is normalized, so the distance between Position1 and Position2 is one, so we
                // don't need to bother squaring and dividing by the length here.
                float fU = (fA * fD) + (fB * fE) + (fC * fF);

                // Calculate the closest point on the Line to the Particle
                Vector3 sClosestPointOnLine = new Vector3();
                sClosestPointOnLine.X = sPosition1.X + (fU * fD);
                sClosestPointOnLine.Y = sPosition1.Y + (fU * fE);
                sClosestPointOnLine.Z = sPosition1.Z + (fU * fF);

                // Calculate the direction to attract the Particle to the closest point on the Line
                sDirectionToPushParticle = sClosestPointOnLine - cParticle.Position;
            }
            // Else if the is a Line Segment Magnet
            else if (cMagnet.MagnetType == DefaultParticleSystemMagnet.MagnetTypes.LineSegmentMagnet)
            {
                // Cast the Magnet to the proper type
                MagnetLineSegment cLineSegmentMagnet = (MagnetLineSegment)cMagnet;

                // Calculate the closest point on the Line to the Particle.
                // Equation taken from http://ozviz.wasp.uwa.edu.au/~pbourke/geometry/pointline/
                // Also explained at http://www.allegro.cc/forums/thread/589720

                // Calculate 2 points on the Line
                Vector3 sPosition1 = cLineSegmentMagnet.EndPoint1;
                Vector3 sPosition2 = cLineSegmentMagnet.EndPoint2;

                // Put calculations into temp variables for speed and easy readability
                float fA = cParticle.Position.X - sPosition1.X;
                float fB = cParticle.Position.Y - sPosition1.Y;
                float fC = cParticle.Position.Z - sPosition1.Z;
                float fD = sPosition2.X - sPosition1.X;
                float fE = sPosition2.Y - sPosition1.Y;
                float fF = sPosition2.Z - sPosition1.Z;

                // Next calculate the value of U
                float fDot           = (fA * fD) + (fB * fE) + (fC * fF);
                float fLengthSquared = (fD * fD) + (fE * fE) + (fF * fF);
                float fU             = fDot / fLengthSquared;

                // Calculate the closest point on the Line to the Particle
                Vector3 sClosestPointOnLine = new Vector3();

                // If the Particle is closest to the first End Point
                if (fU < 0.0f)
                {
                    sClosestPointOnLine = sPosition1;
                }
                // Else If the Particle is closest to the second End Point
                else if (fU > 1.0f)
                {
                    sClosestPointOnLine = sPosition2;
                }
                // Else the Particle is closest to the Line Segment somewhere between the End Points
                else
                {
                    // Calculate where in between the End Points the Particle is closest to
                    sClosestPointOnLine.X = sPosition1.X + (fU * (sPosition2.X - sPosition1.X));
                    sClosestPointOnLine.Y = sPosition1.Y + (fU * (sPosition2.Y - sPosition1.Y));
                    sClosestPointOnLine.Z = sPosition1.Z + (fU * (sPosition2.Z - sPosition1.Z));
                }

                // Calculate the direction to attract the Particle to the closest point on the Line
                sDirectionToPushParticle = sClosestPointOnLine - cParticle.Position;
            }
            // Else If this is a Plane Magnet
            else if (cMagnet.MagnetType == DefaultParticleSystemMagnet.MagnetTypes.PlaneMagnet)
            {
                // Cast the Magnet to the proper type
                MagnetPlane cPlaneMagnet = (MagnetPlane)cMagnet;

                // Calculate the closest point on the Plane to the Particle.
                // Equation taken from http://ozviz.wasp.uwa.edu.au/~pbourke/geometry/pointline/

                // Calculate how far from the Plane the Particle is
                float fDistanceFromPlane = Vector3.Dot(cParticle.Position - cPlaneMagnet.PositionOnPlane, cPlaneMagnet.Normal);

                // Calculate the closest point on the Plane to the Particle
                Vector3 sClosestPointOnPlane = cParticle.Position + (-cPlaneMagnet.Normal * fDistanceFromPlane);

                // Calculate the direction to attract the Particle to the closest point on the Plane
                sDirectionToPushParticle = sClosestPointOnPlane - cParticle.Position;
            }
            // Else we don't know what kind of Magnet this is
            else
            {
                // So exit returning no force
                return(Vector3.Zero);
            }

            // If the Particle should be Repelled away from the Magnet (instead of attracted to it)
            if (cMagnet.Mode == DefaultParticleSystemMagnet.MagnetModes.Repel)
            {
                // Reverse the direction we are going to push the Particle
                sDirectionToPushParticle *= -1;
            }

            // If the Direction To Push the Particle is not valid and we should be Repelling the Particle
            if (sDirectionToPushParticle == Vector3.Zero && cMagnet.Mode == DefaultParticleSystemMagnet.MagnetModes.Repel)
            {
                // Pick a random Direction vector with a very short length to repel the Particle with
                sDirectionToPushParticle = DPSFHelper.RandomNormalizedVector() * 0.00001f;
            }

            // Get how far away the Particle is from the Magnet
            float fDistanceFromMagnet = sDirectionToPushParticle.Length();

            // If the Particle is within range to be affected by the Magnet
            if (fDistanceFromMagnet >= cMagnet.MinDistance && fDistanceFromMagnet <= cMagnet.MaxDistance)
            {
                // If the Direction To Push the Particle is valid
                if (sDirectionToPushParticle != Vector3.Zero)
                {
                    // Normalize the Direction To Push the Particle
                    sDirectionToPushParticle.Normalize();
                }

                // Calculate the normalized distance from the Magnet that the Particle is
                float fLerpAmount = 0.0f;
                if (cMagnet.MaxDistance != cMagnet.MinDistance)
                {
                    fLerpAmount = (fDistanceFromMagnet - cMagnet.MinDistance) / (cMagnet.MaxDistance - cMagnet.MinDistance);
                }
                // Else the Max Distance equals the Min Distance
                else
                {
                    // So to avoid a divide by zero we just assume a full Lerp amount
                    fLerpAmount = 1.0f;
                }

                // Calculate how much of the Max Force to apply to the Particle
                float fNormalizedForce = 0.0f;
                switch (cMagnet.DistanceFunction)
                {
                default:
                case DefaultParticleSystemMagnet.DistanceFunctions.Constant:
                    fNormalizedForce = cMagnet.MaxForce;
                    break;

                case DefaultParticleSystemMagnet.DistanceFunctions.Linear:
                    fNormalizedForce = MathHelper.Lerp(0, cMagnet.MaxForce, fLerpAmount);
                    break;

                case DefaultParticleSystemMagnet.DistanceFunctions.Squared:
                    fNormalizedForce = MathHelper.Lerp(0, cMagnet.MaxForce, fLerpAmount * fLerpAmount);
                    break;

                case DefaultParticleSystemMagnet.DistanceFunctions.Cubed:
                    fNormalizedForce = MathHelper.Lerp(0, cMagnet.MaxForce, fLerpAmount * fLerpAmount * fLerpAmount);
                    break;

                case DefaultParticleSystemMagnet.DistanceFunctions.LinearInverse:
                    fNormalizedForce = MathHelper.Lerp(cMagnet.MaxForce, 0, fLerpAmount);
                    break;

                case DefaultParticleSystemMagnet.DistanceFunctions.SquaredInverse:
                    fNormalizedForce = MathHelper.Lerp(cMagnet.MaxForce, 0, fLerpAmount * fLerpAmount);
                    break;

                case DefaultParticleSystemMagnet.DistanceFunctions.CubedInverse:
                    fNormalizedForce = MathHelper.Lerp(cMagnet.MaxForce, 0, fLerpAmount * fLerpAmount * fLerpAmount);
                    break;
                }

                // Calculate how much Force should be Exerted on the Particle
                sForceToExertOnParticle = sDirectionToPushParticle * (fNormalizedForce * cMagnet.MaxForce);
            }

            // Return how much Force to Exert on the Particle
            return(sForceToExertOnParticle);
        }
Пример #5
0
 /// <summary>
 /// Copy Constructor
 /// </summary>
 /// <param name="cMagnetToCopy">The Line Magnet to copy from</param>
 public MagnetLine(MagnetLine cMagnetToCopy)
     : base(MagnetModes.Attract, DistanceFunctions.Constant, 0, 0, 0, 0)
 {
     CopyFrom(cMagnetToCopy);
 }