PageRenderTime 3774ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Squared/Util/Interpolators.cs

http://github.com/kevingadd/Fracture
C# | 296 lines | 252 code | 44 blank | 0 comment | 13 complexity | e2ab91a49cf84c82ad79c7006a79d55c MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Text;
  6. namespace Squared.Util {
  7. public delegate T InterpolatorSource<out T> (int index) where T : struct;
  8. public delegate T Interpolator<T> (InterpolatorSource<T> data, int dataOffset, float positionInWindow) where T : struct;
  9. public delegate T BoundInterpolatorSource<out T, U> (ref U obj, int index) where T : struct;
  10. public delegate T BoundInterpolator<T, U> (BoundInterpolatorSource<T, U> data, ref U obj, int dataOffset, float positionInWindow) where T : struct;
  11. public static class Interpolators<T>
  12. where T : struct {
  13. public delegate T LinearFn (T a, T b, float x);
  14. public delegate T CosineFn (T a, T b, float x);
  15. public delegate T CubicPFn (T a, T b, T c, T d);
  16. public delegate T CubicRFn (T a, T b, T c, T d, T p, float x, float x2, float x3);
  17. public delegate T HermiteFn (T a, T u, T d, T v, float t, float t2, float tSquared, float s, float s2, float sSquared);
  18. private static LinearFn _Linear = null;
  19. private static CosineFn _Cosine = null;
  20. private static CubicPFn _CubicP = null;
  21. private static CubicRFn _CubicR = null;
  22. private static HermiteFn _Hermite = null;
  23. static Interpolators () {
  24. CompileFallbackExpressions();
  25. CompileNativeExpressions();
  26. }
  27. private static void CompileFallbackExpressions () {
  28. var m_sub = Arithmetic.GetOperator<T, T>(Arithmetic.Operators.Subtract);
  29. var m_add = Arithmetic.GetOperator<T, T>(Arithmetic.Operators.Add);
  30. var m_mul_float = Arithmetic.GetOperator<T, float>(Arithmetic.Operators.Multiply);
  31. _Linear = (a, b, x) => {
  32. return m_add(a, m_mul_float(m_sub(b, a), x));
  33. };
  34. _Cosine = (a, b, x) => {
  35. var temp = (1.0f - (float)Math.Cos(x * Math.PI)) * 0.5f;
  36. return m_add(a, m_mul_float(m_sub(b, a), temp));
  37. };
  38. _CubicP = (a, b, c, d) => {
  39. return m_sub(m_sub(d, c), m_sub(a, b));
  40. };
  41. _CubicR = (a, b, c, d, p, x, x2, x3) => {
  42. return m_add(
  43. m_add(
  44. m_mul_float(p, x3),
  45. m_mul_float(
  46. m_sub(
  47. m_sub(a, b),
  48. p
  49. ),
  50. x2
  51. )
  52. ),
  53. m_add(
  54. m_mul_float(
  55. m_sub(c, a),
  56. x
  57. ),
  58. b
  59. )
  60. );
  61. };
  62. _Hermite = (a, u, d, v, t, t2, tSquared, s, s2, sSquared) => {
  63. return m_sub(
  64. m_add(
  65. m_add(
  66. m_mul_float(a, sSquared * (1 + t2)),
  67. m_mul_float(d, tSquared * (1 + s2))
  68. ),
  69. m_mul_float(u, sSquared * t)
  70. ),
  71. m_mul_float(v, s * tSquared)
  72. );
  73. };
  74. }
  75. private static void CompileNativeExpressions () {
  76. #if WINDOWS
  77. Arithmetic.CompileExpression(
  78. (a, b, x) =>
  79. a + ((b - a) * x),
  80. out _Linear
  81. );
  82. Arithmetic.CompileExpression(
  83. (a, b, x) =>
  84. a + ((b - a) * ((1.0f - (float)Math.Cos(x * Math.PI)) * 0.5f)),
  85. out _Cosine
  86. );
  87. Arithmetic.CompileExpression(
  88. (a, b, c, d) =>
  89. (d - c) - (a - b),
  90. out _CubicP
  91. );
  92. Arithmetic.CompileExpression(
  93. (a, b, c, d, p, x, x2, x3) =>
  94. (p * x3) + ((a - b - p) * x2) + ((c - a) * x) + b,
  95. out _CubicR
  96. );
  97. #endif
  98. }
  99. public static T Null (InterpolatorSource<T> data, int dataOffset, float positionInWindow) {
  100. return data(dataOffset);
  101. }
  102. public static T Linear (InterpolatorSource<T> data, int dataOffset, float positionInWindow) {
  103. return _Linear(
  104. data(dataOffset),
  105. data(dataOffset + 1),
  106. positionInWindow
  107. );
  108. }
  109. public static T Cosine (InterpolatorSource<T> data, int dataOffset, float positionInWindow) {
  110. return _Cosine(
  111. data(dataOffset),
  112. data(dataOffset + 1),
  113. positionInWindow
  114. );
  115. }
  116. public static T Cubic (InterpolatorSource<T> data, int dataOffset, float positionInWindow) {
  117. if (positionInWindow < 0) {
  118. var n = Math.Ceiling(Math.Abs(positionInWindow));
  119. positionInWindow += (float)n;
  120. dataOffset -= (int)n;
  121. }
  122. T a = data(dataOffset - 1);
  123. T b = data(dataOffset);
  124. T c = data(dataOffset + 1);
  125. T d = data(dataOffset + 2);
  126. T p = _CubicP(a, b, c, d);
  127. float x2 = positionInWindow * positionInWindow;
  128. float x3 = positionInWindow * x2;
  129. return _CubicR(a, b, c, d, p, positionInWindow, x2, x3);
  130. }
  131. public static T Hermite (InterpolatorSource<T> data, int dataOffset, float positionInWindow) {
  132. if (positionInWindow < 0) {
  133. var n = Math.Ceiling(Math.Abs(positionInWindow));
  134. positionInWindow += (float)n;
  135. dataOffset -= (int)n;
  136. }
  137. T a = data(dataOffset);
  138. T u = data(dataOffset + 1);
  139. T d = data(dataOffset + 2);
  140. T v = data(dataOffset + 3);
  141. var tSquared = positionInWindow * positionInWindow;
  142. var t2 = positionInWindow * 2;
  143. var s = 1 - positionInWindow;
  144. var s2 = s * 2;
  145. var sSquared = s * s;
  146. return _Hermite(a, u, d, v, positionInWindow, t2, tSquared, s, s2, sSquared);
  147. }
  148. public static T Null<U> (BoundInterpolatorSource<T, U> data, ref U obj, int dataOffset, float positionInWindow) {
  149. return data(ref obj, dataOffset);
  150. }
  151. public static T Linear<U> (BoundInterpolatorSource<T, U> data, ref U obj, int dataOffset, float positionInWindow) {
  152. return _Linear(
  153. data(ref obj, dataOffset),
  154. data(ref obj, dataOffset + 1),
  155. positionInWindow
  156. );
  157. }
  158. public static T Cosine<U> (BoundInterpolatorSource<T, U> data, ref U obj, int dataOffset, float positionInWindow) {
  159. return _Cosine(
  160. data(ref obj, dataOffset),
  161. data(ref obj, dataOffset + 1),
  162. positionInWindow
  163. );
  164. }
  165. public static T Cubic<U> (BoundInterpolatorSource<T, U> data, ref U obj, int dataOffset, float positionInWindow) {
  166. if (positionInWindow < 0) {
  167. var n = Math.Ceiling(Math.Abs(positionInWindow));
  168. positionInWindow += (float)n;
  169. dataOffset -= (int)n;
  170. }
  171. T a = data(ref obj, dataOffset - 1);
  172. T b = data(ref obj, dataOffset);
  173. T c = data(ref obj, dataOffset + 1);
  174. T d = data(ref obj, dataOffset + 2);
  175. T p = _CubicP(a, b, c, d);
  176. float x2 = positionInWindow * positionInWindow;
  177. float x3 = positionInWindow * x2;
  178. return _CubicR(a, b, c, d, p, positionInWindow, x2, x3);
  179. }
  180. public static T Hermite<U> (BoundInterpolatorSource<T, U> data, ref U obj, int dataOffset, float positionInWindow) {
  181. if (positionInWindow < 0) {
  182. var n = Math.Ceiling(Math.Abs(positionInWindow));
  183. positionInWindow += (float)n;
  184. dataOffset -= (int)n;
  185. }
  186. T a = data(ref obj, dataOffset);
  187. T u = data(ref obj, dataOffset + 1);
  188. T d = data(ref obj, dataOffset + 2);
  189. T v = data(ref obj, dataOffset + 3);
  190. var tSquared = positionInWindow * positionInWindow;
  191. var t2 = positionInWindow * 2;
  192. var s = 1 - positionInWindow;
  193. var s2 = s * 2;
  194. var sSquared = s * s;
  195. return _Hermite(a, u, d, v, positionInWindow, t2, tSquared, s, s2, sSquared);
  196. }
  197. private static T[] _TemporaryValues = new T[4];
  198. private static int _NumTemporaryValues = 0;
  199. private static InterpolatorSource<T> _TemporarySource;
  200. private static T TemporarySource (int index) {
  201. return _TemporaryValues[Arithmetic.Wrap(index, 0, _NumTemporaryValues - 1)];
  202. }
  203. public static T Interpolate (Interpolator<T> interpolator, T a, T b, float progress) {
  204. if ((_TemporaryValues == null) || (_TemporaryValues.Length < 2))
  205. _TemporaryValues = new T[2];
  206. if (_TemporarySource == null)
  207. _TemporarySource = TemporarySource;
  208. _TemporaryValues[0] = a;
  209. _TemporaryValues[1] = b;
  210. _NumTemporaryValues = 2;
  211. return interpolator(_TemporarySource, 0, progress);
  212. }
  213. public static T Interpolate (Interpolator<T> interpolator, T[] values, float progress) {
  214. var previousValues = _TemporaryValues;
  215. if (_TemporarySource == null)
  216. _TemporarySource = TemporarySource;
  217. try {
  218. _TemporaryValues = values;
  219. _NumTemporaryValues = values.Length;
  220. return interpolator(_TemporarySource, 0, progress);
  221. } finally {
  222. _TemporaryValues = previousValues;
  223. }
  224. }
  225. public static Interpolator<T> GetByName (string name) {
  226. var types = new Type[] {
  227. typeof(InterpolatorSource<T>), typeof(int), typeof(float)
  228. };
  229. Type myType = typeof(Interpolators<T>);
  230. Type resultType = typeof(Interpolator<T>);
  231. MethodInfo mi = myType.GetMethod(name, types);
  232. if (mi == null)
  233. mi = myType.GetMethod("Null", types);
  234. return Delegate.CreateDelegate(resultType, null, mi) as Interpolator<T>;
  235. }
  236. public static BoundInterpolator<T, U> GetBoundDefault<U>() {
  237. return Linear<U>;
  238. }
  239. public static Interpolator<T> Default {
  240. get {
  241. return Linear;
  242. }
  243. }
  244. }
  245. public static class InterpolatorExtensions {
  246. public static T Interpolate<T> (this Interpolator<T> interpolator, T a, T b, float progress)
  247. where T : struct
  248. {
  249. return Interpolators<T>.Interpolate(interpolator, a, b, progress);
  250. }
  251. }
  252. }