/// <summary> /// Copies the given Point Magnet's data into this Point Magnet's data /// </summary> /// <param name="cMagnetToCopy">The Point Magnet to copy from</param> public void CopyFrom(MagnetPoint cMagnetToCopy) { base.CopyFrom(cMagnetToCopy); PositionData.CopyFrom(cMagnetToCopy.PositionData); }
/// <summary> /// Copy Constructor /// </summary> /// <param name="cMagnetToCopy">The Point Magnet to copy from</param> public MagnetPoint(MagnetPoint cMagnetToCopy) : base(MagnetModes.Attract, DistanceFunctions.Constant, 0, 0, 0, 0) { CopyFrom(cMagnetToCopy); }
/// <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); }