Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123 строки
2.5 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #pragma once
  13. #include <lol/math>
  14. //
  15. // Interpolator classes
  16. // --------------------
  17. //
  18. namespace lol
  19. {
  20. template<typename T, int N = 16> class TimeInterp
  21. {
  22. public:
  23. inline TimeInterp()
  24. : m_precision(0.f),
  25. m_accum(0.f),
  26. m_pos(-N)
  27. {}
  28. inline ~TimeInterp() {}
  29. void SetPrecision(float seconds)
  30. {
  31. m_precision = seconds;
  32. }
  33. void Set(float seconds, T const &val)
  34. {
  35. m_accum += seconds;
  36. if (m_accum < m_precision)
  37. return;
  38. m_accum = 0.f;
  39. if (m_pos < 0)
  40. {
  41. if (m_pos > -N)
  42. seconds += m_key[m_pos + N - 1];
  43. m_key[m_pos + N] = seconds;
  44. m_val[m_pos + N] = val;
  45. ++m_pos;
  46. }
  47. else
  48. {
  49. if (m_pos > 0)
  50. seconds += m_key[m_pos - 1];
  51. m_key[m_pos] = seconds;
  52. m_val[m_pos] = val;
  53. m_pos = (m_pos + 1) % N;
  54. }
  55. }
  56. T Get(float seconds)
  57. {
  58. if (m_pos == -N)
  59. return T();
  60. if (m_pos == 1 - N)
  61. return m_val[0];
  62. seconds += m_accum;
  63. int start = max(0, m_pos);
  64. int a = 0;
  65. int b = min(m_pos + N - 1, N - 1);
  66. while (a + 1 < b)
  67. {
  68. int c = (a + b) / 2;
  69. if (GetTime((start + c) % N) >= seconds)
  70. b = c;
  71. else
  72. a = c;
  73. }
  74. float ka = GetTime((start + a) % N);
  75. float kb = GetTime((start + b) % N);
  76. float u = (seconds - ka) / (kb - ka);
  77. return (1.f - u) * m_val[(start + a) % N] + u * m_val[(start + b) % N];
  78. }
  79. inline void Reset()
  80. {
  81. m_pos = -N;
  82. }
  83. private:
  84. inline float GetTime(int i)
  85. {
  86. float k = m_key[i % N];
  87. if (m_pos >= 0 && i >= m_pos)
  88. k -= m_key[N - 1];
  89. if (m_pos != 0)
  90. k -= m_key[(m_pos + N - 1) % N];
  91. return k;
  92. }
  93. float m_key[N];
  94. T m_val[N];
  95. float m_precision, m_accum;
  96. /* If m_pos < 0, the value indicates how many free slots
  97. * there are. */
  98. int m_pos;
  99. };
  100. } /* namespace lol */