public Quaternion Evaluate(float t) { // Sanity checks if (rotations.Length == 0) { return(Quaternion.identity); } if (rotations.Length == 1) { return(rotations[0]); } int startIndex = 0; for (startIndex = 0; startIndex < times.Length - 1; ++startIndex) { if (t < times[startIndex + 1]) { break; } } // Edge case 0: at the end of the path. if (startIndex == rotations.Length - 1) { return(rotations[startIndex]); } switch (interpolationTypes[startIndex]) { case RotationInterpolationType.Linear: { int nextIndex = Mathf.RoundToInt(Mathf.Min(startIndex + 1, times.Length - 1)); float overTime = t - times[startIndex]; float intervalTime = times[nextIndex] - times[startIndex]; if (intervalTime <= 0) { return(rotations[nextIndex]); } float normTime = overTime / intervalTime; return(Quaternion.Lerp(rotations[startIndex], rotations[nextIndex], normTime)); } case RotationInterpolationType.CubicSpline: { Quaternion slope1, slope2; // Edge case 1: entire curve is just two points. if (rotations.Length == 2) { slope1 = SplineUtils.EstimateSlope(rotations[0], rotations[1], times[1] - times[0]); slope2 = slope1; } // Edge case 2: first section of the curve. else if (startIndex == 0) { slope1 = SplineUtils.EstimateSlope(rotations[0], rotations[1], times[1] - times[0]); slope2 = SplineUtils.EstimateSlope(rotations[0], rotations[1], rotations[2], times[1] - times[0], times[2] - times[1]); } else if (startIndex == rotations.Length - 2) // Edge case 3: last section of the curve. { slope1 = SplineUtils.EstimateSlope(rotations[startIndex - 1], rotations[startIndex], rotations[startIndex + 1], times[startIndex] - times[startIndex - 1], times[startIndex + 1] - times[startIndex]); slope2 = SplineUtils.EstimateSlope(rotations[startIndex], rotations[startIndex + 1], times[startIndex + 1] - times[startIndex]); } else // General case: in the middle of the curve. { slope1 = SplineUtils.EstimateSlope(rotations[startIndex - 1], rotations[startIndex], rotations[startIndex + 1], times[startIndex] - times[startIndex - 1], times[startIndex + 1] - times[startIndex]); slope2 = SplineUtils.EstimateSlope(rotations[startIndex], rotations[startIndex + 1], rotations[startIndex + 2], times[startIndex + 1] - times[startIndex], times[startIndex + 2] - times[startIndex + 1]); } return(SplineUtils.EvaluateSpline(rotations[startIndex], slope1, rotations[startIndex + 1], slope2, t, times[startIndex], times[startIndex + 1])); } case RotationInterpolationType.Slerp: { return(Quaternion.Slerp(rotations[startIndex], rotations[startIndex + 1], (t - times[startIndex]) / (times[startIndex + 1] - times[startIndex]))); } default: Debug.LogError($"[CameraTools.RotationAnimation]: Invalid interpolation type {interpolationTypes[startIndex]}"); return(Quaternion.identity); } }
public Vector3 Evaluate(float t) { // Sanity checks if (positions.Length == 0) { return(Vector3.zero); } if (positions.Length == 1) { return(positions[0]); } int startIndex = 0; for (startIndex = 0; startIndex < times.Length - 1; ++startIndex) { if (t < times[startIndex + 1]) { break; } } // Edge case 0: at the end of the path. if (startIndex == positions.Length - 1) { return(positions[startIndex]); } switch (interpolationTypes[startIndex]) { case PositionInterpolationType.Linear: // Linear interpolation. int nextIndex = Mathf.Min(startIndex + 1, times.Length - 1); float overTime = t - times[startIndex]; float intervalTime = times[nextIndex] - times[startIndex]; if (intervalTime <= 0) { return(positions[nextIndex]); } float normTime = overTime / intervalTime; return(Vector3.Lerp(positions[startIndex], positions[nextIndex], normTime)); case PositionInterpolationType.CubicSpline: // Cubic spline interpolation using Hermite polynomials. Vector3 slope1, slope2; // Edge case 1: entire curve is just two points. if (positions.Length == 2) { slope1 = SplineUtils.EstimateSlope(positions[0], positions[1], times[1] - times[0]); slope2 = slope1; } // Edge case 2: first section of the curve. else if (startIndex == 0) { slope1 = SplineUtils.EstimateSlope(positions[0], positions[1], times[1] - times[0]); slope2 = SplineUtils.EstimateSlope(positions[0], positions[1], positions[2], times[1] - times[0], times[2] - times[1]); } else if (startIndex == positions.Length - 2) // Edge case 3: last section of the curve. { slope1 = SplineUtils.EstimateSlope(positions[startIndex - 1], positions[startIndex], positions[startIndex + 1], times[startIndex] - times[startIndex - 1], times[startIndex + 1] - times[startIndex]); slope2 = SplineUtils.EstimateSlope(positions[startIndex], positions[startIndex + 1], times[startIndex + 1] - times[startIndex]); } else // General case: in the middle of the curve. { slope1 = SplineUtils.EstimateSlope(positions[startIndex - 1], positions[startIndex], positions[startIndex + 1], times[startIndex] - times[startIndex - 1], times[startIndex + 1] - times[startIndex]); slope2 = SplineUtils.EstimateSlope(positions[startIndex], positions[startIndex + 1], positions[startIndex + 2], times[startIndex + 1] - times[startIndex], times[startIndex + 2] - times[startIndex + 1]); } return(SplineUtils.EvaluateSpline(positions[startIndex], slope1, positions[startIndex + 1], slope2, t, times[startIndex], times[startIndex + 1])); default: Debug.LogError($"[CameraTools.Vector3Animation]: Invalid interpolation type {interpolationTypes[startIndex]}"); return(Vector3.zero); } }