/// <summary> /// Gets the curve vector for the curve section from startIndex to endIndex at t parameter. /// </summary> /// <param name="startIndex">The start index of the curve section.</param> /// <param name="endIndex">The end index of the curve section.</param> /// <param name="t">The t parameter for the curve section, t in [0, 1].</param> /// <returns>The curve vector position for the curve section at t.</returns> public Vector3 GetPoint(int startIndex, int endIndex, float t) { int i; if (t >= 1f) { t = 1f; i = (endIndex - 1) * 3; } else { t = Mathf.Clamp01(t) * (endIndex - startIndex); i = (int)t; t -= i; i = (startIndex + i) * 3; } return(transform.TransformPoint(Bezier.GetPoint(_points[i], _points[i + 1], _points[i + 2], _points[i + 3], t))); }
/// <summary> /// Gets the curve vector at t parameter. /// </summary> /// <param name="t">The t parameter.</param> /// <returns>Curve position vector</returns> public Vector3 GetPoint(float t) { int i; if (t >= 1f) { t = 1f; i = _points.Length - 4; } else { t = Mathf.Clamp01(t) * curveCount; i = (int)t; t -= i; i *= 3; } return(transform.TransformPoint(Bezier.GetPoint(_points[i], _points[i + 1], _points[i + 2], _points[i + 3], t))); }
/// <summary> /// Add a point to the spline. /// </summary> /// <remarks> /// Depending on the current selected point, the new point will be added between two points, or at the end of the curve. /// If there's no point selected, or the selected point is the last point, the new point will be added at the end of the curve, at a distance of 1 in the direction of the last point of the spline. /// If the selected point is not the last point, the new point will be created between previous and next point. The bezier handles of the new, of the previous and of the next point will be created/modified in order to maintain the same spline shape. /// </remarks> /// <param name="selectedIndex">The current selected control point index.</param> public void AddPoint(int selectedIndex) { // Add point to the end of the spline if (selectedIndex == -1 || selectedIndex == _points.Length - 1 || selectedIndex % 3 != 0) { Vector3 direction = Bezier.GetFirstDerivative(_points[curveCount * 3 - 3], _points[curveCount * 3 - 2], _points[curveCount * 3 - 1], _points[curveCount * 3], 1).normalized; Vector3 point = _points[_points.Length - 1]; Array.Resize(ref _points, _points.Length + 3); point += direction; _points[_points.Length - 3] = point; point += direction; _points[_points.Length - 2] = point; point += direction; _points[_points.Length - 1] = point; Array.Resize(ref _modes, _modes.Length + 1); _modes[_modes.Length - 1] = BezierControlPointMode.Corner; _modes[_modes.Length - 2] = BezierControlPointMode.Aligned; _EnforceMode(_points.Length - 4); if (_loop) { _points[_points.Length - 1] = _points[0]; _modes[_modes.Length - 1] = _modes[0]; _EnforceMode(0); } } // Add point between two points else if (selectedIndex % 3 == 0) { float s = 0; for (int i = 0; i < selectedIndex / 3; i++) { s += _CurveLength(i); } s += _CurveLength(selectedIndex / 3) / 2; float t0 = GetArcLengthParameter(s) * curveCount - selectedIndex / 3; Vector3 point = Bezier.GetPoint(_points[selectedIndex], _points[selectedIndex + 1], _points[selectedIndex + 2], _points[selectedIndex + 3], t0); Vector3 direction = Bezier.GetFirstDerivative(_points[selectedIndex], _points[selectedIndex + 1], _points[selectedIndex + 2], _points[selectedIndex + 3], t0); Array.Resize(ref _points, _points.Length + 3); for (int i = _points.Length - 1; i >= selectedIndex + 5; i--) { _points[i] = _points[i - 3]; } int newIndex = selectedIndex + 3; _points[newIndex] = point; _points[newIndex - 1] = point - direction * t0 / 3; _points[newIndex - 2] = _points[newIndex - 3] + (_points[newIndex - 2] - _points[newIndex - 3]) * t0; _points[newIndex + 1] = point + direction * (1 - t0) / 3; _points[newIndex + 2] = _points[newIndex + 3] + (_points[newIndex + 2] - _points[newIndex + 3]) * (1 - t0); Array.Resize(ref _modes, _modes.Length + 1); for (int i = _modes.Length - 1; i >= selectedIndex / 3 + 1; i--) { _modes[i] = _modes[i - 1]; } _modes[selectedIndex / 3] = BezierControlPointMode.Corner; _modes[selectedIndex / 3 + 1] = BezierControlPointMode.Aligned; _modes[selectedIndex / 3 + 2] = BezierControlPointMode.Corner; } SetDirty(); }