/// <summary> /// This will figure how much velocity to apply to each bodyCenter /// TODO: Also calculate angular velocities /// </summary> /// <param name="bodyCenters">The bodies to apply velocity to</param> /// <param name="hitStart">The point of impact</param> /// <param name="hitDirection">The direction and force of the impact</param> /// <param name="mainBodyRadius">The avg radius of the body that is getting blown apart</param> private static Vector3D[] DistributeForces(Point3D[] bodyCenters, Point3D hitStart, Vector3D hitDirection, double mainBodyRadius, HullVoronoiExploder_Options options) { Vector3D hitDirectionUnit = hitDirection.ToUnit(); double hitForceBase = hitDirection.Length / mainBodyRadius; var vectors = bodyCenters. Select(o => { Vector3D direction = o - hitStart; Vector3D directionUnit = direction.ToUnit(); double distance = direction.Length; double scaledDistance = distance; if (options.DistanceDot_Power != null) { double linearDot = Math3D.GetLinearDotProduct(hitDirectionUnit, directionUnit); // making it linear so the power function is more predictable // Exaggerate the distance based on dot product. That way, points in line with the hit will get more of the impact double scale = (1 - Math.Abs(linearDot)); scale = Math.Pow(scale, options.DistanceDot_Power.Value); scaledDistance = scale * distance; } return(new { ForcePoint = o, Distance = distance, ScaledDistance = scaledDistance, DirectionUnit = directionUnit, }); }). ToArray(); double[] percents = GetPercentOfProjForce(vectors.Select(o => o.ScaledDistance).ToArray()); Vector3D[] retVal = new Vector3D[vectors.Length]; for (int cntr = 0; cntr < vectors.Length; cntr++) { retVal[cntr] = vectors[cntr].DirectionUnit * (hitForceBase * percents[cntr]); } return(retVal); }