public override CurvePoint[] GetCurvePoints() { // avoids rebuilding entire curve on every call, should be cleared if we wanted to rebuild the curve (if control points move for example) if (_curvePoints != null) { return(_curvePoints); } // First for loop goes through each control point, the second subdivides the path between CPs based on resolution var distanceOnCurve = 0f; var prevPoint = new CurvePoint { Position = ControlPoints[0] }; var nbPoints = ControlPoints.Length * Resolution; var points = new CurvePoint[nbPoints]; var step = 1f / (nbPoints - 1); for (var i = 0; i < nbPoints; i++) { var t = i * step; var point = new CurvePoint(); point.Position = Evaluate(t, out point.Tangent, out point.Curvature); point.Bank = GetBankAngle(point.Tangent, point.Curvature, MaxBankAngle); // Currently breaks if 3 consecutive points are colinear, to be improved with second pass on curve point.Normal = Vector3.Cross(point.Curvature, point.Tangent).normalized; if (Vector3.Dot(point.Normal, prevPoint.Normal) < 0) { point.Normal *= -1; } distanceOnCurve += Vector3.Distance(point.Position, prevPoint.Position); point.DistanceOnCurve = distanceOnCurve; points[i] = point; prevPoint = point; } FixNormals(ref points); _curvePoints = points; return(points); }
public override CurvePoint[] GetCurvePoints() { // avoids rebuilding entire curve on every call, should be cleared if we wanted to rebuild the curve (if control points move for example) if (_curvePoints != null) { return(_curvePoints); } // First for loop goes through each control point, the second subdivides the path between CPs based on resolution var distanceOnCurve = 0f; var prevPoint = new CurvePoint { Position = ControlPoints[0] }; // If we are looping, we are adding an extra segment, so we need an extra point var nbPoints = CloseLoop ? ControlPoints.Length : ControlPoints.Length - 1; var points = new CurvePoint[nbPoints * Resolution + 1]; Vector3 p0 = Vector3.zero, p1 = Vector3.zero, m0 = Vector3.zero, m1 = Vector3.zero; for (var i = 0; i < nbPoints; i++) { p0 = ControlPoints[i]; p1 = ControlPoints[GetClampedPointIdx(i + 1)]; m0 = 0.5f * (p1 - ControlPoints[GetClampedPointIdx(i - 1)]); m1 = 0.5f * (ControlPoints[GetClampedPointIdx(i + 2)] - p0); // Second for loop actually creates the spline for this particular segment for (var j = 0; j < Resolution; j++) { points[i * Resolution + j] = GetPointOnCurve(p0, p1, m0, m1, (float)j / Resolution, ref distanceOnCurve, ref prevPoint); } } // we have to manually add the last point on the spline points[nbPoints * Resolution] = GetPointOnCurve(p0, p1, m0, m1, 1f, ref distanceOnCurve, ref prevPoint); FixNormals(ref points); _curvePoints = points; return(points); }
private static CurvePoint GetPointOnCurve(Vector3 p0, Vector3 p1, Vector3 m0, Vector3 m1, float t, ref float distanceOnCurve, ref CurvePoint prevPoint) { var point = new CurvePoint(); point.Position = Evaluate(p0, p1, m0, m1, t, out point.Tangent, out point.Curvature); point.Bank = GetBankAngle(point.Tangent, point.Curvature, MaxBankAngle); // Currently breaks if 3 consecutive points are colinear, to be improved with second pass on curve point.Normal = Vector3.Cross(point.Curvature, point.Tangent).normalized; if (Vector3.Dot(point.Normal, prevPoint.Normal) < 0) point.Normal *= -1; distanceOnCurve += Vector3.Distance(point.Position, prevPoint.Position); point.DistanceOnCurve = distanceOnCurve; prevPoint = point; return point; }
public override CurvePoint[] GetCurvePoints() { // avoids rebuilding entire curve on every call, should be cleared if we wanted to rebuild the curve (if control points move for example) if (_curvePoints != null) return _curvePoints; // First for loop goes through each control point, the second subdivides the path between CPs based on resolution var distanceOnCurve = 0f; var prevPoint = new CurvePoint { Position = ControlPoints[0] }; // If we are looping, we are adding an extra segment, so we need an extra point var nbPoints = CloseLoop ? ControlPoints.Length : ControlPoints.Length - 1; var points = new CurvePoint[nbPoints * Resolution + 1]; Vector3 p0 = Vector3.zero, p1 = Vector3.zero, m0 = Vector3.zero, m1 = Vector3.zero; for (var i = 0; i < nbPoints; i++) { p0 = ControlPoints[i]; p1 = ControlPoints[GetClampedPointIdx(i + 1)]; m0 = 0.5f * (p1 - ControlPoints[GetClampedPointIdx(i - 1)]); m1 = 0.5f * (ControlPoints[GetClampedPointIdx(i + 2)] - p0); // Second for loop actually creates the spline for this particular segment for (var j = 0; j < Resolution; j++) points[i * Resolution + j] = GetPointOnCurve(p0, p1, m0, m1, (float)j / Resolution, ref distanceOnCurve, ref prevPoint); } // we have to manually add the last point on the spline points[nbPoints * Resolution] = GetPointOnCurve(p0, p1, m0, m1, 1f, ref distanceOnCurve, ref prevPoint); FixNormals(ref points); _curvePoints = points; return points; }
public override CurvePoint[] GetCurvePoints() { // avoids rebuilding entire curve on every call, should be cleared if we wanted to rebuild the curve (if control points move for example) if(_curvePoints != null) return _curvePoints; // First for loop goes through each control point, the second subdivides the path between CPs based on resolution var distanceOnCurve = 0f; var prevPoint = new CurvePoint { Position = ControlPoints[0] }; var nbPoints = ControlPoints.Length * Resolution; var points = new CurvePoint[nbPoints]; var step = 1f / (nbPoints - 1); for (var i = 0; i < nbPoints; i++) { var t = i * step; var point = new CurvePoint(); point.Position = Evaluate(t, out point.Tangent, out point.Curvature); point.Bank = GetBankAngle(point.Tangent, point.Curvature, MaxBankAngle); // Currently breaks if 3 consecutive points are colinear, to be improved with second pass on curve point.Normal = Vector3.Cross(point.Curvature, point.Tangent).normalized; if (Vector3.Dot(point.Normal, prevPoint.Normal) < 0) point.Normal *= -1; distanceOnCurve += Vector3.Distance(point.Position, prevPoint.Position); point.DistanceOnCurve = distanceOnCurve; points[i] = point; prevPoint = point; } FixNormals(ref points); _curvePoints = points; return points; }
protected static void FixNormals(ref CurvePoint[] curvePoints) { for (var i = 0; i < curvePoints.Length; i++) { var point = curvePoints[i]; if (point.Normal == Vector3.zero) { // look forward until we find a non zero normal var j = i; while (j < curvePoints.Length) { if (curvePoints[j].Normal != Vector3.zero) break; j++; } if (j < curvePoints.Length) { while (i < j) { curvePoints[i].Normal = curvePoints[j].Normal; i++; } } } } }
private static CurvePoint GetPointOnCurve(Vector3 p0, Vector3 p1, Vector3 m0, Vector3 m1, float t, ref float distanceOnCurve, ref CurvePoint prevPoint) { var point = new CurvePoint(); point.Position = Evaluate(p0, p1, m0, m1, t, out point.Tangent, out point.Curvature); point.Bank = GetBankAngle(point.Tangent, point.Curvature, MaxBankAngle); // Currently breaks if 3 consecutive points are colinear, to be improved with second pass on curve point.Normal = Vector3.Cross(point.Curvature, point.Tangent).normalized; if (Vector3.Dot(point.Normal, prevPoint.Normal) < 0) { point.Normal *= -1; } distanceOnCurve += Vector3.Distance(point.Position, prevPoint.Position); point.DistanceOnCurve = distanceOnCurve; prevPoint = point; return(point); }