Interpolate.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. /**
  5. * Interpolation utility functions: easing, bezier, and catmull-rom.
  6. * Consider using Unity's Animation curve editor and AnimationCurve class
  7. * before scripting the desired behaviour using this utility.
  8. *
  9. * Interpolation functionality available at different levels of abstraction.
  10. * Low level access via individual easing functions (ex. EaseInOutCirc),
  11. * Bezier(), and CatmullRom(). High level access using sequence generators,
  12. * NewEase(), NewBezier(), and NewCatmullRom().
  13. *
  14. * Sequence generators are typically used as follows:
  15. *
  16. * IEnumerable<Vector3> sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration);
  17. * foreach (Vector3 newPoint in sequence) {
  18. * transform.position = newPoint;
  19. * yield return WaitForSeconds(1.0f);
  20. * }
  21. *
  22. * Or:
  23. *
  24. * IEnumerator<Vector3> sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration).GetEnumerator();
  25. * function Update() {
  26. * if (sequence.MoveNext()) {
  27. * transform.position = sequence.Current;
  28. * }
  29. * }
  30. *
  31. * The low level functions work similarly to Unity's built in Lerp and it is
  32. * up to you to track and pass in elapsedTime and duration on every call. The
  33. * functions take this form (or the logical equivalent for Bezier() and CatmullRom()).
  34. *
  35. * transform.position = ease(start, distance, elapsedTime, duration);
  36. *
  37. * For convenience in configuration you can use the Ease(EaseType) function to
  38. * look up a concrete easing function:
  39. *
  40. * [SerializeField]
  41. * Interpolate.EaseType easeType; // set using Unity's property inspector
  42. * Interpolate.Function ease; // easing of a particular EaseType
  43. * function Awake() {
  44. * ease = Interpolate.Ease(easeType);
  45. * }
  46. *
  47. * @author Fernando Zapata (fernando@cpudreams.com)
  48. * @Traduzione Andrea85cs (andrea85cs@dynematica.it)
  49. */
  50. [System.Serializable]
  51. public struct LinePointInfo
  52. {
  53. public Vector3 point;
  54. public bool smoothIn;
  55. public bool smoothOut;
  56. public Transform bindTrasform;
  57. }
  58. public class Interpolate
  59. {
  60. /**
  61. * Different methods of easing interpolation.
  62. */
  63. public enum EaseType
  64. {
  65. Linear,
  66. EaseInQuad,
  67. EaseOutQuad,
  68. EaseInOutQuad,
  69. EaseInCubic,
  70. EaseOutCubic,
  71. EaseInOutCubic,
  72. EaseInQuart,
  73. EaseOutQuart,
  74. EaseInOutQuart,
  75. EaseInQuint,
  76. EaseOutQuint,
  77. EaseInOutQuint,
  78. EaseInSine,
  79. EaseOutSine,
  80. EaseInOutSine,
  81. EaseInExpo,
  82. EaseOutExpo,
  83. EaseInOutExpo,
  84. EaseInCirc,
  85. EaseOutCirc,
  86. EaseInOutCirc
  87. }
  88. /**
  89. * Sequence of eleapsedTimes until elapsedTime is >= duration.
  90. *
  91. * Note: elapsedTimes are calculated using the value of Time.deltatTime each
  92. * time a value is requested.
  93. */
  94. static Vector3 Identity (Vector3 v)
  95. {
  96. return v;
  97. }
  98. static Vector3 TransformDotPosition (Transform t)
  99. {
  100. return t.position;
  101. }
  102. static IEnumerable<float> NewTimer (float duration)
  103. {
  104. float elapsedTime = 0.0f;
  105. while (elapsedTime < duration) {
  106. yield return elapsedTime;
  107. elapsedTime += Time.deltaTime;
  108. // make sure last value is never skipped
  109. if (elapsedTime >= duration) {
  110. yield return elapsedTime;
  111. }
  112. }
  113. }
  114. public delegate Vector3 ToVector3<T> (T v);
  115. public delegate float Function (float a, float b, float c, float d);
  116. /**
  117. * Generates sequence of integers from start to end (inclusive) one step
  118. * at a time.
  119. */
  120. static IEnumerable<float> NewCounter (int start, int end, int step)
  121. {
  122. for (int i = start; i <= end; i += step) {
  123. yield return i;
  124. }
  125. }
  126. /**
  127. * Returns sequence generator from start to end over duration using the
  128. * given easing function. The sequence is generated as it is accessed
  129. * using the Time.deltaTime to calculate the portion of duration that has
  130. * elapsed.
  131. */
  132. public static IEnumerator NewEase (Function ease, Vector3 start, Vector3 end, float duration)
  133. {
  134. IEnumerable<float> timer = Interpolate.NewTimer (duration);
  135. return NewEase (ease, start, end, duration, timer);
  136. }
  137. /**
  138. * Instead of easing based on time, generate n interpolated points (slices)
  139. * between the start and end positions.
  140. */
  141. public static IEnumerator NewEase (Function ease, Vector3 start, Vector3 end, int slices)
  142. {
  143. IEnumerable<float> counter = Interpolate.NewCounter (0, slices + 1, 1);
  144. return NewEase (ease, start, end, slices + 1, counter);
  145. }
  146. /**
  147. * Generic easing sequence generator used to implement the time and
  148. * slice variants. Normally you would not use this function directly.
  149. */
  150. static IEnumerator NewEase (Function ease, Vector3 start, Vector3 end, float total, IEnumerable<float> driver)
  151. {
  152. Vector3 distance = end - start;
  153. foreach (float i in driver) {
  154. yield return Ease (ease, start, distance, i, total);
  155. }
  156. }
  157. /**
  158. * Vector3 interpolation using given easing method. Easing is done independently
  159. * on all three vector axis.
  160. */
  161. static Vector3 Ease (Function ease, Vector3 start, Vector3 distance, float elapsedTime, float duration)
  162. {
  163. start.x = ease (start.x, distance.x, elapsedTime, duration);
  164. start.y = ease (start.y, distance.y, elapsedTime, duration);
  165. start.z = ease (start.z, distance.z, elapsedTime, duration);
  166. return start;
  167. }
  168. /**
  169. * Returns the static method that implements the given easing type for scalars.
  170. * Use this method to easily switch between easing interpolation types.
  171. *
  172. * All easing methods clamp elapsedTime so that it is always <= duration.
  173. *
  174. * var ease = Interpolate.Ease(EaseType.EaseInQuad);
  175. * i = ease(start, distance, elapsedTime, duration);
  176. */
  177. public static Function Ease (EaseType type)
  178. {
  179. // Source Flash easing functions:
  180. // http://gizma.com/easing/
  181. // http://www.robertpenner.com/easing/easing_demo.html
  182. //
  183. // Changed to use more friendly variable names, that follow my Lerp
  184. // conventions:
  185. // start = b (start value)
  186. // distance = c (change in value)
  187. // elapsedTime = t (current time)
  188. // duration = d (time duration)
  189. Function f = null;
  190. switch (type) {
  191. case EaseType.Linear:
  192. f = Interpolate.Linear;
  193. break;
  194. case EaseType.EaseInQuad:
  195. f = Interpolate.EaseInQuad;
  196. break;
  197. case EaseType.EaseOutQuad:
  198. f = Interpolate.EaseOutQuad;
  199. break;
  200. case EaseType.EaseInOutQuad:
  201. f = Interpolate.EaseInOutQuad;
  202. break;
  203. case EaseType.EaseInCubic:
  204. f = Interpolate.EaseInCubic;
  205. break;
  206. case EaseType.EaseOutCubic:
  207. f = Interpolate.EaseOutCubic;
  208. break;
  209. case EaseType.EaseInOutCubic:
  210. f = Interpolate.EaseInOutCubic;
  211. break;
  212. case EaseType.EaseInQuart:
  213. f = Interpolate.EaseInQuart;
  214. break;
  215. case EaseType.EaseOutQuart:
  216. f = Interpolate.EaseOutQuart;
  217. break;
  218. case EaseType.EaseInOutQuart:
  219. f = Interpolate.EaseInOutQuart;
  220. break;
  221. case EaseType.EaseInQuint:
  222. f = Interpolate.EaseInQuint;
  223. break;
  224. case EaseType.EaseOutQuint:
  225. f = Interpolate.EaseOutQuint;
  226. break;
  227. case EaseType.EaseInOutQuint:
  228. f = Interpolate.EaseInOutQuint;
  229. break;
  230. case EaseType.EaseInSine:
  231. f = Interpolate.EaseInSine;
  232. break;
  233. case EaseType.EaseOutSine:
  234. f = Interpolate.EaseOutSine;
  235. break;
  236. case EaseType.EaseInOutSine:
  237. f = Interpolate.EaseInOutSine;
  238. break;
  239. case EaseType.EaseInExpo:
  240. f = Interpolate.EaseInExpo;
  241. break;
  242. case EaseType.EaseOutExpo:
  243. f = Interpolate.EaseOutExpo;
  244. break;
  245. case EaseType.EaseInOutExpo:
  246. f = Interpolate.EaseInOutExpo;
  247. break;
  248. case EaseType.EaseInCirc:
  249. f = Interpolate.EaseInCirc;
  250. break;
  251. case EaseType.EaseOutCirc:
  252. f = Interpolate.EaseOutCirc;
  253. break;
  254. case EaseType.EaseInOutCirc:
  255. f = Interpolate.EaseInOutCirc;
  256. break;
  257. }
  258. return f;
  259. }
  260. /**
  261. * Returns sequence generator from the first node to the last node over
  262. * duration time using the points in-between the first and last node
  263. * as control points of a bezier curve used to generate the interpolated points
  264. * in the sequence. If there are no control points (ie. only two nodes, first
  265. * and last) then this behaves exactly the same as NewEase(). In other words
  266. * a zero-degree bezier spline curve is just the easing method. The sequence
  267. * is generated as it is accessed using the Time.deltaTime to calculate the
  268. * portion of duration that has elapsed.
  269. */
  270. public static IEnumerable<Vector3> NewBezier (Function ease, Transform[] nodes, float duration)
  271. {
  272. IEnumerable<float> timer = Interpolate.NewTimer (duration);
  273. return NewBezier<Transform> (ease, nodes, TransformDotPosition, duration, timer);
  274. }
  275. /**
  276. * Instead of interpolating based on time, generate n interpolated points
  277. * (slices) between the first and last node.
  278. */
  279. public static IEnumerable<Vector3> NewBezier (Function ease, Transform[] nodes, int slices)
  280. {
  281. IEnumerable<float> counter = NewCounter (0, slices + 1, 1);
  282. return NewBezier<Transform> (ease, nodes, TransformDotPosition, slices + 1, counter);
  283. }
  284. /**
  285. * A Vector3[] variation of the Transform[] NewBezier() function.
  286. * Same functionality but using Vector3s to define bezier curve.
  287. */
  288. public static IEnumerable<Vector3> NewBezier (Function ease, Vector3[] points, float duration)
  289. {
  290. IEnumerable<float> timer = NewTimer (duration);
  291. return NewBezier<Vector3> (ease, points, Identity, duration, timer);
  292. }
  293. /**
  294. * A Vector3[] variation of the Transform[] NewBezier() function.
  295. * Same functionality but using Vector3s to define bezier curve.
  296. */
  297. public static IEnumerable<Vector3> NewBezier (Function ease, Vector3[] points, int slices)
  298. {
  299. IEnumerable<float> counter = NewCounter (0, slices + 1, 1);
  300. return NewBezier<Vector3> (ease, points, Identity, slices + 1, counter);
  301. }
  302. /**
  303. * Generic bezier spline sequence generator used to implement the time and
  304. * slice variants. Normally you would not use this function directly.
  305. */
  306. static IEnumerable<Vector3> NewBezier<T> (Function ease, IList nodes, ToVector3<T> toVector3, float maxStep, IEnumerable<float> steps)
  307. {
  308. // need at least two nodes to spline between
  309. if (nodes.Count >= 2) {
  310. // copy nodes array since Bezier is destructive
  311. Vector3[] points = new Vector3[nodes.Count];
  312. foreach (float step in steps) {
  313. // re-initialize copy before each destructive call to Bezier
  314. for (int i = 0; i < nodes.Count; i++) {
  315. points [i] = toVector3 ((T)nodes [i]);
  316. }
  317. yield return Bezier (ease, points, step, maxStep);
  318. // make sure last value is always generated
  319. }
  320. }
  321. }
  322. /**
  323. * A Vector3 n-degree bezier spline.
  324. *
  325. * WARNING: The points array is modified by Bezier. See NewBezier() for a
  326. * safe and user friendly alternative.
  327. *
  328. * You can pass zero control points, just the start and end points, for just
  329. * plain easing. In other words a zero-degree bezier spline curve is just the
  330. * easing method.
  331. *
  332. * @param points start point, n control points, end point
  333. */
  334. static Vector3 Bezier (Function ease, Vector3[] points, float elapsedTime, float duration)
  335. {
  336. // Reference: http://ibiblio.org/e-notes/Splines/Bezier.htm
  337. // Interpolate the n starting points to generate the next j = (n - 1) points,
  338. // then interpolate those n - 1 points to generate the next n - 2 points,
  339. // continue this until we have generated the last point (n - (n - 1)), j = 1.
  340. // We store the next set of output points in the same array as the
  341. // input points used to generate them. This works because we store the
  342. // result in the slot of the input point that is no longer used for this
  343. // iteration.
  344. for (int j = points.Length - 1; j > 0; j--) {
  345. for (int i = 0; i < j; i++) {
  346. points [i].x = ease (points [i].x, points [i + 1].x - points [i].x, elapsedTime, duration);
  347. points [i].y = ease (points [i].y, points [i + 1].y - points [i].y, elapsedTime, duration);
  348. points [i].z = ease (points [i].z, points [i + 1].z - points [i].z, elapsedTime, duration);
  349. }
  350. }
  351. return points [0];
  352. }
  353. /**
  354. * Returns sequence generator from the first node, through each control point,
  355. * and to the last node. N points are generated between each node (slices)
  356. * using Catmull-Rom.
  357. */
  358. public static IEnumerable<Vector3> NewCatmullRom (Transform[] nodes, int slices, bool loop)
  359. {
  360. return NewCatmullRom<Transform> (nodes, TransformDotPosition, slices, loop);
  361. }
  362. /**
  363. * A Vector3[] variation of the Transform[] NewCatmullRom() function.
  364. * Same functionality but using Vector3s to define curve.
  365. */
  366. public static IEnumerable<Vector3> NewCatmullRom (Vector3[] points, int slices, bool loop)
  367. {
  368. return NewCatmullRom<Vector3> (points, Identity, slices, loop);
  369. }
  370. public static IEnumerable<Vector3> NewCatmullRomByPointInfo (LinePointInfo[] pointInfos, int slices, bool loop)
  371. {
  372. if (pointInfos.Length >= 2) {
  373. // yield the first point explicitly, if looping the first point
  374. // will be generated again in the step for loop when interpolating
  375. // from last point back to the first point
  376. yield return pointInfos [0].point;
  377. int last = pointInfos.Length - 1;
  378. for (int current = 0; loop || current < last; current++) {
  379. // wrap around when looping
  380. if (loop && current > last) {
  381. current = 0;
  382. }
  383. // handle edge cases for looping and non-looping scenarios
  384. // when looping we wrap around, when not looping use start for previous
  385. // and end for next when you at the ends of the nodes array
  386. int previous = (current == 0) ? ((loop) ? last : current) : (pointInfos [current].smoothOut ? current - 1 : current);
  387. int start = current;
  388. int end = (current == last) ? ((loop) ? 0 : current) : current + 1;
  389. int next = (end == last) ? ((loop) ? 0 : end) : (pointInfos [end].smoothIn ? end + 1 : end);
  390. // adding one guarantees yielding at least the end point
  391. int stepCount = slices + 1;
  392. for (int step = 1; step <= stepCount; step++) {
  393. yield return CatmullRom (pointInfos [previous].point,
  394. pointInfos [start].point,
  395. pointInfos [end].point,
  396. pointInfos [next].point,
  397. step, stepCount);
  398. }
  399. }
  400. }
  401. }
  402. /**
  403. * Generic catmull-rom spline sequence generator used to implement the
  404. * Vector3[] and Transform[] variants. Normally you would not use this
  405. * function directly.
  406. */
  407. static IEnumerable<Vector3> NewCatmullRom<T> (IList nodes, ToVector3<T> toVector3, int slices, bool loop)
  408. {
  409. // need at least two nodes to spline between
  410. if (nodes.Count >= 2) {
  411. // yield the first point explicitly, if looping the first point
  412. // will be generated again in the step for loop when interpolating
  413. // from last point back to the first point
  414. yield return toVector3 ((T)nodes [0]);
  415. int last = nodes.Count - 1;
  416. for (int current = 0; loop || current < last; current++) {
  417. // wrap around when looping
  418. if (loop && current > last) {
  419. current = 0;
  420. }
  421. // handle edge cases for looping and non-looping scenarios
  422. // when looping we wrap around, when not looping use start for previous
  423. // and end for next when you at the ends of the nodes array
  424. int previous = (current == 0) ? ((loop) ? last : current) : current - 1;
  425. int start = current;
  426. int end = (current == last) ? ((loop) ? 0 : current) : current + 1;
  427. int next = (end == last) ? ((loop) ? 0 : end) : end + 1;
  428. // adding one guarantees yielding at least the end point
  429. int stepCount = slices + 1;
  430. for (int step = 1; step <= stepCount; step++) {
  431. yield return CatmullRom (toVector3 ((T)nodes [previous]),
  432. toVector3 ((T)nodes [start]),
  433. toVector3 ((T)nodes [end]),
  434. toVector3 ((T)nodes [next]),
  435. step, stepCount);
  436. }
  437. }
  438. }
  439. }
  440. /**
  441. * A Vector3 Catmull-Rom spline. Catmull-Rom splines are similar to bezier
  442. * splines but have the useful property that the generated curve will go
  443. * through each of the control points.
  444. *
  445. * NOTE: The NewCatmullRom() functions are an easier to use alternative to this
  446. * raw Catmull-Rom implementation.
  447. *
  448. * @param previous the point just before the start point or the start point
  449. * itself if no previous point is available
  450. * @param start generated when elapsedTime == 0
  451. * @param end generated when elapsedTime >= duration
  452. * @param next the point just after the end point or the end point itself if no
  453. * next point is available
  454. */
  455. public static Vector3 CatmullRom (Vector3 previous, Vector3 start, Vector3 end, Vector3 next,
  456. float elapsedTime, float duration)
  457. {
  458. // References used:
  459. // p.266 GemsV1
  460. //
  461. // tension is often set to 0.5 but you can use any reasonable value:
  462. // http://www.cs.cmu.edu/~462/projects/assn2/assn2/catmullRom.pdf
  463. //
  464. // bias and tension controls:
  465. // http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/interpolation/
  466. float percentComplete = elapsedTime / duration;
  467. float percentCompleteSquared = percentComplete * percentComplete;
  468. float percentCompleteCubed = percentCompleteSquared * percentComplete;
  469. return previous * (-0.5f * percentCompleteCubed +
  470. percentCompleteSquared -
  471. 0.5f * percentComplete) +
  472. start * (1.5f * percentCompleteCubed +
  473. -2.5f * percentCompleteSquared + 1.0f) +
  474. end * (-1.5f * percentCompleteCubed +
  475. 2.0f * percentCompleteSquared +
  476. 0.5f * percentComplete) +
  477. next * (0.5f * percentCompleteCubed -
  478. 0.5f * percentCompleteSquared);
  479. }
  480. public static Vector3 GetDir (Vector3 previous, Vector3 start, Vector3 end, Vector3 next,
  481. float elapsedTime, float duration)
  482. {
  483. float percentComplete = elapsedTime / duration;
  484. float percentCompleteSquared = percentComplete * percentComplete;
  485. float percentCompleteCubed = percentCompleteSquared * percentComplete;
  486. Vector3 dir = percentCompleteSquared * (-1.5f * previous + 4.5f * start - 4.5f * end + 1.5f * next)
  487. + percentComplete * (2f * previous - 5f * start + 4f * end - next)
  488. + (-0.5f * previous + 0.5f * end);
  489. return dir.normalized;
  490. }
  491. public static Vector3 CatmullRomWithDir (Vector3 previous, Vector3 start, Vector3 end, Vector3 next,
  492. float elapsedTime, float duration, out Vector3 dir)
  493. {
  494. // References used:
  495. // p.266 GemsV1
  496. //
  497. // tension is often set to 0.5 but you can use any reasonable value:
  498. // http://www.cs.cmu.edu/~462/projects/assn2/assn2/catmullRom.pdf
  499. //
  500. // bias and tension controls:
  501. // http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/interpolation/
  502. float percentComplete = elapsedTime / duration;
  503. float percentCompleteSquared = percentComplete * percentComplete;
  504. float percentCompleteCubed = percentCompleteSquared * percentComplete;
  505. dir = percentCompleteSquared * (-1.5f * previous + 4.5f * start - 4.5f * end + 1.5f * next)
  506. + percentComplete * (2f * previous - 5f * start + 4f * end - next)
  507. + (-0.5f * previous + 0.5f * end);
  508. dir = dir.normalized;
  509. return previous * (-0.5f * percentCompleteCubed +
  510. percentCompleteSquared -
  511. 0.5f * percentComplete) +
  512. start * (1.5f * percentCompleteCubed +
  513. -2.5f * percentCompleteSquared + 1.0f) +
  514. end * (-1.5f * percentCompleteCubed +
  515. 2.0f * percentCompleteSquared +
  516. 0.5f * percentComplete) +
  517. next * (0.5f * percentCompleteCubed -
  518. 0.5f * percentCompleteSquared);
  519. }
  520. /**
  521. * Linear interpolation (same as Mathf.Lerp)
  522. */
  523. static float Linear (float start, float distance, float elapsedTime, float duration)
  524. {
  525. // clamp elapsedTime to be <= duration
  526. if (elapsedTime > duration) {
  527. elapsedTime = duration;
  528. }
  529. return distance * (elapsedTime / duration) + start;
  530. }
  531. /**
  532. * quadratic easing in - accelerating from zero velocity
  533. */
  534. static float EaseInQuad (float start, float distance, float elapsedTime, float duration)
  535. {
  536. // clamp elapsedTime so that it cannot be greater than duration
  537. elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
  538. return distance * elapsedTime * elapsedTime + start;
  539. }
  540. /**
  541. * quadratic easing out - decelerating to zero velocity
  542. */
  543. static float EaseOutQuad (float start, float distance, float elapsedTime, float duration)
  544. {
  545. // clamp elapsedTime so that it cannot be greater than duration
  546. elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
  547. return -distance * elapsedTime * (elapsedTime - 2) + start;
  548. }
  549. /**
  550. * quadratic easing in/out - acceleration until halfway, then deceleration
  551. */
  552. static float EaseInOutQuad (float start, float distance, float elapsedTime, float duration)
  553. {
  554. // clamp elapsedTime so that it cannot be greater than duration
  555. elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
  556. if (elapsedTime < 1)
  557. return distance / 2 * elapsedTime * elapsedTime + start;
  558. elapsedTime--;
  559. return -distance / 2 * (elapsedTime * (elapsedTime - 2) - 1) + start;
  560. }
  561. /**
  562. * cubic easing in - accelerating from zero velocity
  563. */
  564. static float EaseInCubic (float start, float distance, float elapsedTime, float duration)
  565. {
  566. // clamp elapsedTime so that it cannot be greater than duration
  567. elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
  568. return distance * elapsedTime * elapsedTime * elapsedTime + start;
  569. }
  570. /**
  571. * cubic easing out - decelerating to zero velocity
  572. */
  573. static float EaseOutCubic (float start, float distance, float elapsedTime, float duration)
  574. {
  575. // clamp elapsedTime so that it cannot be greater than duration
  576. elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
  577. elapsedTime--;
  578. return distance * (elapsedTime * elapsedTime * elapsedTime + 1) + start;
  579. }
  580. /**
  581. * cubic easing in/out - acceleration until halfway, then deceleration
  582. */
  583. static float EaseInOutCubic (float start, float distance, float elapsedTime, float duration)
  584. {
  585. // clamp elapsedTime so that it cannot be greater than duration
  586. elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
  587. if (elapsedTime < 1)
  588. return distance / 2 * elapsedTime * elapsedTime * elapsedTime + start;
  589. elapsedTime -= 2;
  590. return distance / 2 * (elapsedTime * elapsedTime * elapsedTime + 2) + start;
  591. }
  592. /**
  593. * quartic easing in - accelerating from zero velocity
  594. */
  595. static float EaseInQuart (float start, float distance, float elapsedTime, float duration)
  596. {
  597. // clamp elapsedTime so that it cannot be greater than duration
  598. elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
  599. return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
  600. }
  601. /**
  602. * quartic easing out - decelerating to zero velocity
  603. */
  604. static float EaseOutQuart (float start, float distance, float elapsedTime, float duration)
  605. {
  606. // clamp elapsedTime so that it cannot be greater than duration
  607. elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
  608. elapsedTime--;
  609. return -distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 1) + start;
  610. }
  611. /**
  612. * quartic easing in/out - acceleration until halfway, then deceleration
  613. */
  614. static float EaseInOutQuart (float start, float distance, float elapsedTime, float duration)
  615. {
  616. // clamp elapsedTime so that it cannot be greater than duration
  617. elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
  618. if (elapsedTime < 1)
  619. return distance / 2 * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
  620. elapsedTime -= 2;
  621. return -distance / 2 * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 2) + start;
  622. }
  623. /**
  624. * quintic easing in - accelerating from zero velocity
  625. */
  626. static float EaseInQuint (float start, float distance, float elapsedTime, float duration)
  627. {
  628. // clamp elapsedTime so that it cannot be greater than duration
  629. elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
  630. return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
  631. }
  632. /**
  633. * quintic easing out - decelerating to zero velocity
  634. */
  635. static float EaseOutQuint (float start, float distance, float elapsedTime, float duration)
  636. {
  637. // clamp elapsedTime so that it cannot be greater than duration
  638. elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
  639. elapsedTime--;
  640. return distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 1) + start;
  641. }
  642. /**
  643. * quintic easing in/out - acceleration until halfway, then deceleration
  644. */
  645. static float EaseInOutQuint (float start, float distance, float elapsedTime, float duration)
  646. {
  647. // clamp elapsedTime so that it cannot be greater than duration
  648. elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2f);
  649. if (elapsedTime < 1)
  650. return distance / 2 * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
  651. elapsedTime -= 2;
  652. return distance / 2 * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 2) + start;
  653. }
  654. /**
  655. * sinusoidal easing in - accelerating from zero velocity
  656. */
  657. static float EaseInSine (float start, float distance, float elapsedTime, float duration)
  658. {
  659. // clamp elapsedTime to be <= duration
  660. if (elapsedTime > duration) {
  661. elapsedTime = duration;
  662. }
  663. return -distance * Mathf.Cos (elapsedTime / duration * (Mathf.PI / 2)) + distance + start;
  664. }
  665. /**
  666. * sinusoidal easing out - decelerating to zero velocity
  667. */
  668. static float EaseOutSine (float start, float distance, float elapsedTime, float duration)
  669. {
  670. if (elapsedTime > duration) {
  671. elapsedTime = duration;
  672. }
  673. return distance * Mathf.Sin (elapsedTime / duration * (Mathf.PI / 2)) + start;
  674. }
  675. /**
  676. * sinusoidal easing in/out - accelerating until halfway, then decelerating
  677. */
  678. static float EaseInOutSine (float start, float distance, float elapsedTime, float duration)
  679. {
  680. // clamp elapsedTime to be <= duration
  681. if (elapsedTime > duration) {
  682. elapsedTime = duration;
  683. }
  684. return -distance / 2 * (Mathf.Cos (Mathf.PI * elapsedTime / duration) - 1) + start;
  685. }
  686. /**
  687. * exponential easing in - accelerating from zero velocity
  688. */
  689. static float EaseInExpo (float start, float distance, float elapsedTime, float duration)
  690. {
  691. // clamp elapsedTime to be <= duration
  692. if (elapsedTime > duration) {
  693. elapsedTime = duration;
  694. }
  695. return distance * Mathf.Pow (2, 10 * (elapsedTime / duration - 1)) + start;
  696. }
  697. /**
  698. * exponential easing out - decelerating to zero velocity
  699. */
  700. static float EaseOutExpo (float start, float distance, float elapsedTime, float duration)
  701. {
  702. // clamp elapsedTime to be <= duration
  703. if (elapsedTime > duration) {
  704. elapsedTime = duration;
  705. }
  706. return distance * (-Mathf.Pow (2, -10 * elapsedTime / duration) + 1) + start;
  707. }
  708. /**
  709. * exponential easing in/out - accelerating until halfway, then decelerating
  710. */
  711. static float EaseInOutExpo (float start, float distance, float elapsedTime, float duration)
  712. {
  713. // clamp elapsedTime so that it cannot be greater than duration
  714. elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
  715. if (elapsedTime < 1)
  716. return distance / 2 * Mathf.Pow (2, 10 * (elapsedTime - 1)) + start;
  717. elapsedTime--;
  718. return distance / 2 * (-Mathf.Pow (2, -10 * elapsedTime) + 2) + start;
  719. }
  720. /**
  721. * circular easing in - accelerating from zero velocity
  722. */
  723. static float EaseInCirc (float start, float distance, float elapsedTime, float duration)
  724. {
  725. // clamp elapsedTime so that it cannot be greater than duration
  726. elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
  727. return -distance * (Mathf.Sqrt (1 - elapsedTime * elapsedTime) - 1) + start;
  728. }
  729. /**
  730. * circular easing out - decelerating to zero velocity
  731. */
  732. static float EaseOutCirc (float start, float distance, float elapsedTime, float duration)
  733. {
  734. // clamp elapsedTime so that it cannot be greater than duration
  735. elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
  736. elapsedTime--;
  737. return distance * Mathf.Sqrt (1 - elapsedTime * elapsedTime) + start;
  738. }
  739. /**
  740. * circular easing in/out - acceleration until halfway, then deceleration
  741. */
  742. static float EaseInOutCirc (float start, float distance, float
  743. elapsedTime, float duration)
  744. {
  745. // clamp elapsedTime so that it cannot be greater than duration
  746. elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
  747. if (elapsedTime < 1)
  748. return -distance / 2 * (Mathf.Sqrt (1 - elapsedTime * elapsedTime) - 1) + start;
  749. elapsedTime -= 2;
  750. return distance / 2 * (Mathf.Sqrt (1 - elapsedTime * elapsedTime) + 1) + start;
  751. }
  752. }