/// <summary> /// Calculate the outgoing tangent. /// </summary> /// <param name="previousControlPoint"></param> /// <param name="nextControlPoint"></param> /// <returns></returns> public Vector3 CalculateDestinationTangent(KochanekBartelsControlPoint previousControlPoint, KochanekBartelsControlPoint nextControlPoint) { var factor1 = (1 - Tension) * (1 + Continuity) * (1 + Bias) / 2; var factor2 = (1 - Tension) * (1 - Continuity) * (1 - Bias) / 2; return(factor1 * (Position - previousControlPoint.Position) + factor2 * (nextControlPoint.Position - Position)); }
/// <summary> /// Calculate one segment. /// </summary> /// <param name="point1"></param> /// <param name="point2"></param> /// <param name="point3"></param> /// <param name="point4"></param> /// <param name="steps">Steps for this segement, between point2 and point3.</param> /// <returns></returns> private static List <Vector3> InterpolateSegment(KochanekBartelsControlPoint point1, KochanekBartelsControlPoint point2, KochanekBartelsControlPoint point3, KochanekBartelsControlPoint point4, int steps, bool isLastSegment = false) { var interpolatedPoints = new List <Vector3>(); Vector3 point2DestinationTangent = point2.CalculateDestinationTangent(point1, point3); Vector3 point3SourceTangent = point3.CalculateSourceTangent(point2, point4); for (var i = 0; i < steps; i++) { float s; if (isLastSegment) { s = i / (float)(steps - 1); } else { s = i / (float)(steps); } var newPoint = CalculateInterpolatedPoint(point2.Position, point3.Position, point2DestinationTangent, point3SourceTangent, s); interpolatedPoints.Add(newPoint); } return(interpolatedPoints); }
/// <summary> /// Insert a control point at index. /// </summary> /// <param name="index"></param> /// <param name="controlPoint"></param> public SplineModificationInfo InsertControlPoint(int index, KochanekBartelsControlPoint controlPoint) { ControlPoints.Insert(index, controlPoint); if (ControlPoints.Count < 3 && InterpolatedPoints.Count < 2 * Steps) { Debug.LogWarning("KochanekBartelsSpline: Control point was added but the line can only be interpolated when there are at least 3 control points."); return(new SplineModificationInfo(0, 0, 0)); } else if (ControlPoints.Count == 3 && InterpolatedPoints.Count == Steps) { this.SetControlPoints(ControlPoints.ToArray()); return(new SplineModificationInfo(0, Steps, 2 * Steps)); } else if (ControlPoints.Count == 3) { this.SetControlPoints(ControlPoints.ToArray()); return(new SplineModificationInfo(0, 0, 2 * Steps)); } //determine which segments have to be reinterpolated int start = (index - 2) >= 0 ? (index - 2) : 0; int end = (index + 1) <= (ControlPoints.Count - 2) ? (index + 1) : (ControlPoints.Count - 2); for (int i = start; i <= end; i++) { try { if (index == ControlPoints.Count - 1) { //if we are inserting the control point as the new last element //dont try to remove the segment before the new control point because it doesnt exist yet if (i != index - 1) { //dont remove at added index so a new segment is added InterpolatedPoints.RemoveRange(i * Steps, Steps); } } else { if (i != index) { //dont remove at added index so a new segment is added InterpolatedPoints.RemoveRange(i * Steps, Steps); } } InterpolatedPoints.InsertRange(i * Steps, InterpolateSegment(i)); } catch (ArgumentException exception) { Debug.LogError("Can't insert control point at index that doesnt exist yet, add instead!\n" + exception); } } return(new SplineModificationInfo(start * Steps, (end - start) * Steps, (end - start + 1) * Steps)); }
/// <summary> /// Reset the existing control point at index. /// </summary> /// <param name="index"></param> /// <param name="controlPoints"></param> public SplineModificationInfo SetControlPoint(int index, KochanekBartelsControlPoint controlPoint) { ControlPoints[index] = controlPoint; int start = (index - 2) >= 0 ? (index - 2) : 0; int end = (index + 1) <= (ControlPoints.Count - 2) ? (index + 1) : (ControlPoints.Count - 2); for (int i = start; i <= end; i++) { try { InterpolatedPoints.RemoveRange(i * Steps, Steps); InterpolatedPoints.InsertRange(i * Steps, InterpolateSegment(i)); } catch (ArgumentException exception) { Debug.LogError("Can't set control point that doesnt exist yet, add instead!\n" + exception); } } return(new SplineModificationInfo(start * Steps, (end - start + 1) * Steps, (end - start + 1) * Steps)); }
/// <summary> /// Add control point at the end of the curve. /// </summary> /// <param name="controlPoint"></param> public SplineModificationInfo AddControlPoint(KochanekBartelsControlPoint controlPoint) { return(InsertControlPoint(ControlPoints.Count, controlPoint)); }