protected override double EaseInCore(double normalizedTime) { double bounces = Math.Max(0.0, (double)Bounces); double bounciness = Bounciness; //Anything less than one will cause a DivideByZeroException if (bounciness < 1.0 || DoubleUtils.IsOne(bounciness)) { // Just a bit more than one to get (almost) the same effect without dividing by zero bounciness = 1.001; } double bouncinessCompliment = 1.0 - bounciness; double power = Math.Pow(bounciness, bounces); //Get the number of units, where the first bounce has a width of 1 unit, using a geometric series plus half a unit //for the final bounce double totalUnits = (1.0 - power) / bouncinessCompliment + power * 0.5; //The unit we are currently in double currentUnit = normalizedTime * totalUnits; // Which bounce are we in, based on current unit double currentBounce = Math.Log(-currentUnit * (1.0 - bounciness) + 1.0, bounciness); double start = Math.Floor(currentBounce); double end = start + 1.0; //Convert the start and end of the bounce into time double startTime = (1.0 - Math.Pow(bounciness, start)) / (bouncinessCompliment * totalUnits); double endTime = (1.0 - Math.Pow(bounciness, end)) / (bouncinessCompliment * totalUnits); //Create a curve to fit the bounce double peakTime = (startTime + endTime) * 0.5; double timeToPeak = normalizedTime - peakTime; double radius = peakTime - startTime; double amplitude = Math.Pow(1.0 / bounciness, (bounces - start)); //Quadratic curve to match the start, end and peak return((-amplitude / (radius * radius)) * (timeToPeak - radius) * (timeToPeak + radius)); }