Spline.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. namespace UnityEditor.Experimental.Rendering.Universal.Path2D
  6. {
  7. internal struct Spline : IShape
  8. {
  9. public bool isOpenEnded;
  10. public Vector3[] points;
  11. ShapeType IShape.type => ShapeType.Spline;
  12. bool IShape.isOpenEnded => isOpenEnded;
  13. ControlPoint[] IShape.ToControlPoints()
  14. {
  15. if (points == null)
  16. throw new NullReferenceException("Points array is null");
  17. if (!points.IsSpline(isOpenEnded))
  18. throw new Exception("The provided control point array can't conform a Spline.");
  19. var controlPoints = new List<ControlPoint>();
  20. var leftTangent = Vector3.zero;
  21. var rightTangent = Vector3.zero;
  22. var pointCount = points.Length;
  23. for (var i = 0; i < pointCount; i += 3)
  24. {
  25. if (i == 0)
  26. {
  27. if (isOpenEnded)
  28. leftTangent = points[0];
  29. else
  30. leftTangent = points[EditablePathUtility.Mod(-1, pointCount)];
  31. }
  32. if (i == pointCount - 1 && isOpenEnded)
  33. rightTangent = points[i];
  34. else
  35. rightTangent = points[i+1];
  36. controlPoints.Add(
  37. new ControlPoint()
  38. {
  39. position = points[i],
  40. leftTangent = leftTangent,
  41. rightTangent = rightTangent,
  42. tangentMode = TangentMode.Broken
  43. });
  44. if (i == pointCount - 1 && isOpenEnded)
  45. leftTangent = Vector3.zero;
  46. else
  47. leftTangent = points[i+2];
  48. }
  49. pointCount = controlPoints.Count;
  50. for (var i = 0; i < pointCount; ++i)
  51. {
  52. var prevIndex = EditablePathUtility.Mod(i-1, pointCount);
  53. var nextIndex = EditablePathUtility.Mod(i+1, pointCount);
  54. var controlPoint = controlPoints[i];
  55. var prevControlPoint = controlPoints[prevIndex];
  56. var nextControlPoint = controlPoints[nextIndex];
  57. var liniarLeftPosition = (prevControlPoint.position - controlPoint.position) / 3f;
  58. var isLeftTangentLinear = (controlPoint.localLeftTangent - liniarLeftPosition).sqrMagnitude < 0.001f;
  59. if (isLeftTangentLinear)
  60. controlPoint.localLeftTangent = Vector3.zero;
  61. var liniarRightPosition = (nextControlPoint.position - controlPoint.position) / 3f;
  62. var isRightTangentLinear = (controlPoint.localRightTangent - liniarRightPosition).sqrMagnitude < 0.001f;
  63. if (isRightTangentLinear)
  64. controlPoint.localRightTangent = Vector3.zero;
  65. var tangentDotProduct = Vector3.Dot(controlPoint.localLeftTangent.normalized, controlPoint.localRightTangent.normalized);
  66. var isContinous = tangentDotProduct < 0f && (tangentDotProduct + 1) * (tangentDotProduct + 1) < 0.001f;
  67. if (isLeftTangentLinear && isRightTangentLinear)
  68. controlPoint.tangentMode = TangentMode.Linear;
  69. else if (isLeftTangentLinear || isRightTangentLinear)
  70. controlPoint.tangentMode = TangentMode.Broken;
  71. else if (isContinous)
  72. controlPoint.tangentMode = TangentMode.Continuous;
  73. controlPoints[i] = controlPoint;
  74. }
  75. return controlPoints.ToArray();
  76. }
  77. public static Spline empty = new Spline() { isOpenEnded = true, points = new Vector3[0] };
  78. }
  79. }