QuaternionSpline.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import defaultValue from "./defaultValue.js";
  2. import defined from "./defined.js";
  3. import DeveloperError from "./DeveloperError.js";
  4. import Quaternion from "./Quaternion.js";
  5. import Spline from "./Spline.js";
  6. function createEvaluateFunction(spline) {
  7. var points = spline.points;
  8. var times = spline.times;
  9. // use slerp interpolation
  10. return function (time, result) {
  11. if (!defined(result)) {
  12. result = new Quaternion();
  13. }
  14. var i = (spline._lastTimeIndex = spline.findTimeInterval(
  15. time,
  16. spline._lastTimeIndex
  17. ));
  18. var u = (time - times[i]) / (times[i + 1] - times[i]);
  19. var q0 = points[i];
  20. var q1 = points[i + 1];
  21. return Quaternion.fastSlerp(q0, q1, u, result);
  22. };
  23. }
  24. /**
  25. * A spline that uses spherical linear (slerp) interpolation to create a quaternion curve.
  26. * The generated curve is in the class C<sup>1</sup>.
  27. *
  28. * @alias QuaternionSpline
  29. * @constructor
  30. *
  31. * @param {Object} options Object with the following properties:
  32. * @param {Number[]} options.times An array of strictly increasing, unit-less, floating-point times at each point.
  33. * The values are in no way connected to the clock time. They are the parameterization for the curve.
  34. * @param {Quaternion[]} options.points The array of {@link Quaternion} control points.
  35. *
  36. * @exception {DeveloperError} points.length must be greater than or equal to 2.
  37. * @exception {DeveloperError} times.length must be equal to points.length.
  38. *
  39. * @see HermiteSpline
  40. * @see CatmullRomSpline
  41. * @see LinearSpline
  42. * @see WeightSpline
  43. */
  44. function QuaternionSpline(options) {
  45. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  46. var points = options.points;
  47. var times = options.times;
  48. //>>includeStart('debug', pragmas.debug);
  49. if (!defined(points) || !defined(times)) {
  50. throw new DeveloperError("points and times are required.");
  51. }
  52. if (points.length < 2) {
  53. throw new DeveloperError(
  54. "points.length must be greater than or equal to 2."
  55. );
  56. }
  57. if (times.length !== points.length) {
  58. throw new DeveloperError("times.length must be equal to points.length.");
  59. }
  60. //>>includeEnd('debug');
  61. this._times = times;
  62. this._points = points;
  63. this._evaluateFunction = createEvaluateFunction(this);
  64. this._lastTimeIndex = 0;
  65. }
  66. Object.defineProperties(QuaternionSpline.prototype, {
  67. /**
  68. * An array of times for the control points.
  69. *
  70. * @memberof QuaternionSpline.prototype
  71. *
  72. * @type {Number[]}
  73. * @readonly
  74. */
  75. times: {
  76. get: function () {
  77. return this._times;
  78. },
  79. },
  80. /**
  81. * An array of {@link Quaternion} control points.
  82. *
  83. * @memberof QuaternionSpline.prototype
  84. *
  85. * @type {Quaternion[]}
  86. * @readonly
  87. */
  88. points: {
  89. get: function () {
  90. return this._points;
  91. },
  92. },
  93. });
  94. /**
  95. * Finds an index <code>i</code> in <code>times</code> such that the parameter
  96. * <code>time</code> is in the interval <code>[times[i], times[i + 1]]</code>.
  97. * @function
  98. *
  99. * @param {Number} time The time.
  100. * @returns {Number} The index for the element at the start of the interval.
  101. *
  102. * @exception {DeveloperError} time must be in the range <code>[t<sub>0</sub>, t<sub>n</sub>]</code>, where <code>t<sub>0</sub></code>
  103. * is the first element in the array <code>times</code> and <code>t<sub>n</sub></code> is the last element
  104. * in the array <code>times</code>.
  105. */
  106. QuaternionSpline.prototype.findTimeInterval = Spline.prototype.findTimeInterval;
  107. /**
  108. * Wraps the given time to the period covered by the spline.
  109. * @function
  110. *
  111. * @param {Number} time The time.
  112. * @return {Number} The time, wrapped around to the updated animation.
  113. */
  114. QuaternionSpline.prototype.wrapTime = Spline.prototype.wrapTime;
  115. /**
  116. * Clamps the given time to the period covered by the spline.
  117. * @function
  118. *
  119. * @param {Number} time The time.
  120. * @return {Number} The time, clamped to the animation period.
  121. */
  122. QuaternionSpline.prototype.clampTime = Spline.prototype.clampTime;
  123. /**
  124. * Evaluates the curve at a given time.
  125. *
  126. * @param {Number} time The time at which to evaluate the curve.
  127. * @param {Quaternion} [result] The object onto which to store the result.
  128. * @returns {Quaternion} The modified result parameter or a new instance of the point on the curve at the given time.
  129. *
  130. * @exception {DeveloperError} time must be in the range <code>[t<sub>0</sub>, t<sub>n</sub>]</code>, where <code>t<sub>0</sub></code>
  131. * is the first element in the array <code>times</code> and <code>t<sub>n</sub></code> is the last element
  132. * in the array <code>times</code>.
  133. */
  134. QuaternionSpline.prototype.evaluate = function (time, result) {
  135. return this._evaluateFunction(time, result);
  136. };
  137. export default QuaternionSpline;