namespace Sandbox; public static partial class SandboxSystemExtensions { /// /// Generates a Catmull-Rom spline from a collection of Vector3 points. Needs at least 3 points to create a spline. /// /// The collection of Vector3 points. /// The number of interpolated points to generate between each pair of input points. /// An IEnumerable of Vector3 points representing the Catmull-Rom spline. public static IEnumerable CatmullRomSpline( this IEnumerable points, int interpolation ) { Vector3 previousPoint = Vector3.Zero; Vector3 currentPoint = Vector3.Zero; Vector3 nextPoint = Vector3.Zero; Vector3 nextNextPoint = Vector3.Zero; int pointIndex = 0; foreach ( var point in points ) { if ( pointIndex == 0 ) { currentPoint = point; nextPoint = point; } else if ( pointIndex == 1 ) { nextPoint = point; previousPoint = currentPoint; // Assuming a simple linear extrapolation for the first control point } else if ( pointIndex == 2 ) { nextNextPoint = point; // Generate the first set of interpolated points now that we have enough points for ( int i = 0; i < interpolation; i++ ) { float t = (float)i / interpolation; yield return Vector3.CatmullRomSpline( previousPoint, currentPoint, nextPoint, nextNextPoint, t ); } } else { previousPoint = currentPoint; currentPoint = nextPoint; nextPoint = nextNextPoint; nextNextPoint = point; for ( int i = 0; i < interpolation; i++ ) { float t = (float)i / interpolation; yield return Vector3.CatmullRomSpline( previousPoint, currentPoint, nextPoint, nextNextPoint, t ); } } pointIndex++; } // Handle the last segment if ( pointIndex > 2 ) { previousPoint = currentPoint; currentPoint = nextPoint; nextPoint = nextNextPoint; nextNextPoint = nextNextPoint + (nextNextPoint - nextPoint); // Assuming a simple linear extrapolation for the last control point for ( int i = 0; i <= interpolation; i++ ) { float t = (float)i / interpolation; yield return Vector3.CatmullRomSpline( previousPoint, currentPoint, nextPoint, nextNextPoint, t ); } } } public static IEnumerable TcbSpline( this IEnumerable points, int interpolation, float tension, float continuity, float bias ) { Vector3 previousPoint = Vector3.Zero; Vector3 currentPoint = Vector3.Zero; Vector3 nextPoint = Vector3.Zero; Vector3 nextNextPoint = Vector3.Zero; int pointIndex = 0; foreach ( var point in points ) { if ( pointIndex == 0 ) { currentPoint = point; nextPoint = point; } else if ( pointIndex == 1 ) { nextPoint = point; previousPoint = currentPoint; // Assuming a simple linear extrapolation for the first control point } else if ( pointIndex == 2 ) { nextNextPoint = point; // Generate the first set of interpolated points now that we have enough points for ( int i = 0; i < interpolation; i++ ) { float t = (float)i / interpolation; yield return Vector3.TcbSpline( previousPoint, currentPoint, nextPoint, nextNextPoint, tension, continuity, bias, t ); } } else { previousPoint = currentPoint; currentPoint = nextPoint; nextPoint = nextNextPoint; nextNextPoint = point; for ( int i = 0; i < interpolation; i++ ) { float t = (float)i / interpolation; yield return Vector3.TcbSpline( previousPoint, currentPoint, nextPoint, nextNextPoint, tension, continuity, bias, t ); } } pointIndex++; } // Handle the last segment if ( pointIndex > 2 ) { previousPoint = currentPoint; currentPoint = nextPoint; nextPoint = nextNextPoint; nextNextPoint = nextNextPoint + (nextNextPoint - nextPoint); // Assuming a simple linear extrapolation for the last control point for ( int i = 0; i <= interpolation; i++ ) { float t = (float)i / interpolation; yield return Vector3.TcbSpline( previousPoint, currentPoint, nextPoint, nextNextPoint, tension, continuity, bias, t ); } } } }