CurveSample.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using UnityEngine;
  6. namespace SplineMesh {
  7. /// <summary>
  8. /// Imutable class containing all data about a point on a cubic bezier curve.
  9. /// </summary>
  10. public struct CurveSample
  11. {
  12. public readonly Vector3 location;
  13. public readonly Vector3 tangent;
  14. public readonly Vector3 up;
  15. public readonly Vector2 scale;
  16. public readonly float roll;
  17. public readonly float distanceInCurve;
  18. public readonly float timeInCurve;
  19. public readonly CubicBezierCurve curve;
  20. private Quaternion rotation;
  21. /// <summary>
  22. /// Rotation is a look-at quaternion calculated from the tangent, roll and up vector. Mixing non zero roll and custom up vector is not advised.
  23. /// </summary>
  24. public Quaternion Rotation {
  25. get {
  26. if (rotation == Quaternion.identity) {
  27. var upVector = Vector3.Cross(tangent, Vector3.Cross(Quaternion.AngleAxis(roll, Vector3.forward) * up, tangent).normalized);
  28. rotation = Quaternion.LookRotation(tangent, upVector);
  29. }
  30. return rotation;
  31. }
  32. }
  33. public CurveSample(Vector3 location, Vector3 tangent, Vector3 up, Vector2 scale, float roll, float distanceInCurve, float timeInCurve, CubicBezierCurve curve) {
  34. this.location = location;
  35. this.tangent = tangent;
  36. this.up = up;
  37. this.roll = roll;
  38. this.scale = scale;
  39. this.distanceInCurve = distanceInCurve;
  40. this.timeInCurve = timeInCurve;
  41. this.curve = curve;
  42. rotation = Quaternion.identity;
  43. }
  44. public override bool Equals(object obj) {
  45. if (obj == null || GetType() != obj.GetType()) {
  46. return false;
  47. }
  48. CurveSample other = (CurveSample)obj;
  49. return location == other.location &&
  50. tangent == other.tangent &&
  51. up == other.up &&
  52. scale == other.scale &&
  53. roll == other.roll &&
  54. distanceInCurve == other.distanceInCurve &&
  55. timeInCurve == other.timeInCurve;
  56. }
  57. public override int GetHashCode() {
  58. return base.GetHashCode();
  59. }
  60. public static bool operator ==(CurveSample cs1, CurveSample cs2) {
  61. return cs1.Equals(cs2);
  62. }
  63. public static bool operator !=(CurveSample cs1, CurveSample cs2) {
  64. return !cs1.Equals(cs2);
  65. }
  66. /// <summary>
  67. /// Linearly interpolates between two curve samples.
  68. /// </summary>
  69. /// <param name="a"></param>
  70. /// <param name="b"></param>
  71. /// <param name="t"></param>
  72. /// <returns></returns>
  73. public static CurveSample Lerp(CurveSample a, CurveSample b, float t) {
  74. return new CurveSample(
  75. Vector3.Lerp(a.location, b.location, t),
  76. Vector3.Lerp(a.tangent, b.tangent, t).normalized,
  77. Vector3.Lerp(a.up, b.up, t),
  78. Vector2.Lerp(a.scale, b.scale, t),
  79. Mathf.Lerp(a.roll, b.roll, t),
  80. Mathf.Lerp(a.distanceInCurve, b.distanceInCurve, t),
  81. Mathf.Lerp(a.timeInCurve, b.timeInCurve, t),
  82. a.curve);
  83. }
  84. public MeshVertex GetBent(MeshVertex vert) {
  85. var res = new MeshVertex(vert.position, vert.normal, vert.uv);
  86. // application of scale
  87. res.position = Vector3.Scale(res.position, new Vector3(0, scale.y, scale.x));
  88. // application of roll
  89. res.position = Quaternion.AngleAxis(roll, Vector3.right) * res.position;
  90. res.normal = Quaternion.AngleAxis(roll, Vector3.right) * res.normal;
  91. // reset X value
  92. res.position.x = 0;
  93. // application of the rotation + location
  94. Quaternion q = Rotation * Quaternion.Euler(0, -90, 0);
  95. res.position = q * res.position + location;
  96. res.normal = q * res.normal;
  97. return res;
  98. }
  99. }
  100. }