private static void SmoothLocalInterpolation(BezierKeyframe previous, float previousTime, ref BezierKeyframe current, BezierKeyframe next, float nextTime) { if (next.HasValue() && previous.HasValue()) { var inHandle = (current.value - previous.value) / 3f; var outHandle = (next.value - current.value) / 3f; var bothSegmentsDuration = nextTime - previousTime; var inRatio = (current.time - previousTime) / bothSegmentsDuration; var outRatio = (nextTime - current.time) / bothSegmentsDuration; var avg = inHandle * inRatio + outHandle * outRatio; if (inRatio > outRatio) { current.controlPointIn = current.value - avg; current.controlPointOut = current.value + avg * outRatio; } else { current.controlPointIn = current.value - avg * inRatio; current.controlPointOut = current.value + avg; } } else if (previous.IsNull()) { current.controlPointIn = current.value; current.controlPointOut = current.value + (next.value - current.value) / 3f; } else if (next.IsNull()) { current.controlPointIn = current.value - (current.value - previous.value) / 3f; current.controlPointOut = current.value; } }
public static float ComputeValue(BezierKeyframe current, BezierKeyframe next, float time) { if (next.IsNull()) { return(current.value); } var t = (time - current.time) / (next.time - current.time); switch (current.curveType) { case CurveTypeValues.Constant: return(current.value); case CurveTypeValues.Linear: case CurveTypeValues.FlatLinear: { return(current.value + (next.value - current.value) * t); } } var w0 = current.value; var w1 = current.controlPointOut; var w2 = next.controlPointIn; var w3 = next.value; // See https://pomax.github.io/bezierinfo/#how-to-implement-the-weighted-basis-function var mt = 1f - t; var mt2 = mt * mt; var mt3 = mt2 * mt; var t2 = t * t; var t3 = t2 * t; return(w0 * mt3 + 3f * w1 * mt2 * t + 3f * w2 * mt * t2 + w3 * t3); }
private static void SmoothLocalInterpolation(BezierKeyframe previous, float previousTime, ref BezierKeyframe current, BezierKeyframe next, float nextTime) { if (next.HasValue() && previous.HasValue()) { var inHandle = (current.value - previous.value) / 3f; var outHandle = (next.value - current.value) / 3f; var bothSegmentsDuration = nextTime - previousTime; var inRatio = (current.time - previousTime) / bothSegmentsDuration; var outRatio = (nextTime - current.time) / bothSegmentsDuration; /* // SMOOTH * // The larger the incoming curve, the weaker the effect on the other side * var weightedAvg = inHandle * outRatio + outHandle * inRatio; * if (inRatio > outRatio) * { * current.controlPointIn = current.value - weightedAvg * (inRatio / outRatio); * current.controlPointOut = current.value + weightedAvg; * } * else * { * current.controlPointIn = current.value - weightedAvg; * current.controlPointOut = current.value + weightedAvg * (outRatio / inRatio); * } */ // NO_OVERSHOOT // The larger the incoming curve, the stronger the effect on the other side var weightedAvg = inHandle * inRatio + outHandle * outRatio; if (inRatio > outRatio) { current.controlPointIn = current.value - weightedAvg; current.controlPointOut = current.value + weightedAvg * (outRatio / inRatio); } else { current.controlPointIn = current.value - weightedAvg * (inRatio / outRatio); current.controlPointOut = current.value + weightedAvg; } } else if (previous.IsNull()) { current.controlPointIn = current.value; current.controlPointOut = current.value + (next.value - current.value) / 3f; } else if (next.IsNull()) { current.controlPointIn = current.value - (current.value - previous.value) / 3f; current.controlPointOut = current.value; } }