CurvedLineRenderer.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // /******************************************************************************
  2. // * File: CurvedLineRenderer.cs
  3. // * Copyright (c) 2023 Qualcomm Technologies, Inc. and/or its subsidiaries. All rights reserved.
  4. // *
  5. // *
  6. // ******************************************************************************/
  7. using System;
  8. using System.Collections.Generic;
  9. using UnityEngine;
  10. namespace QCHT.Samples.Drawing
  11. {
  12. /// <summary>
  13. /// Changes the line renderer behaviour to draw a smooth line.
  14. /// </summary>
  15. [RequireComponent(typeof(LineRenderer))]
  16. public sealed class CurvedLineRenderer : MonoBehaviour
  17. {
  18. public float LineSegmentWidth = 0.15f;
  19. public float LineWidth = 0.1f;
  20. private Vector3[] _positions = Array.Empty<Vector3>();
  21. private static readonly AnimationCurve s_curveX = new AnimationCurve();
  22. private static readonly AnimationCurve s_curveY = new AnimationCurve();
  23. private static readonly AnimationCurve s_curveZ = new AnimationCurve();
  24. #region MonoBehaviour Functions
  25. #if UNITY_EDITOR
  26. private void OnValidate()
  27. {
  28. UpdateLine();
  29. }
  30. #endif
  31. #endregion
  32. /// <summary>
  33. /// Changes the line renderer positions.
  34. /// </summary>
  35. /// <param name="positions"> the new positions table. </param>
  36. public void SetPositions(Vector3[] positions)
  37. {
  38. _positions = positions;
  39. UpdateLine();
  40. }
  41. private void UpdateLine()
  42. {
  43. var smoothedPoints = Smooth(_positions, LineSegmentWidth);
  44. var lineRenderer = GetComponent<LineRenderer>();
  45. lineRenderer.positionCount = smoothedPoints.Length;
  46. lineRenderer.SetPositions(smoothedPoints);
  47. lineRenderer.startWidth = LineWidth;
  48. lineRenderer.endWidth = LineWidth;
  49. }
  50. private static Vector3[] Smooth(Vector3[] points, float stepSize)
  51. {
  52. var keysX = new Keyframe[points.Length];
  53. var keysY = new Keyframe[points.Length];
  54. var keysZ = new Keyframe[points.Length];
  55. for (var i = 0; i < points.Length; i++)
  56. {
  57. keysX[i] = new Keyframe(i, points[i].x);
  58. keysY[i] = new Keyframe(i, points[i].y);
  59. keysZ[i] = new Keyframe(i, points[i].z);
  60. }
  61. s_curveX.keys = keysX;
  62. s_curveY.keys = keysY;
  63. s_curveZ.keys = keysZ;
  64. for (var i = 0; i < points.Length; i++)
  65. {
  66. s_curveX.SmoothTangents(i, 0);
  67. s_curveY.SmoothTangents(i, 0);
  68. s_curveZ.SmoothTangents(i, 0);
  69. }
  70. var lineSegments = new List<Vector3>();
  71. for (var i = 0; i < points.Length; i++)
  72. {
  73. lineSegments.Add(points[i]);
  74. if (i + 1 >= points.Length)
  75. continue;
  76. var distanceToNextPoint = Vector3.Distance(points[i], points[i + 1]);
  77. var nbSegments = (int) (distanceToNextPoint / stepSize);
  78. for (var j = 1; j < nbSegments; j++)
  79. {
  80. var t = j / (float) nbSegments + i;
  81. var segment = new Vector3(
  82. s_curveX.Evaluate(t),
  83. s_curveY.Evaluate(t),
  84. s_curveZ.Evaluate(t));
  85. lineSegments.Add(segment);
  86. }
  87. }
  88. return lineSegments.ToArray();
  89. }
  90. }
  91. }