QuaternionSpline.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. const points = spline.points;
  8. const times = spline.times;
  9. // use slerp interpolation
  10. return function (time, result) {
  11. if (!defined(result)) {
  12. result = new Quaternion();
  13. }
  14. const i = (spline._lastTimeIndex = spline.findTimeInterval(
  15. time,
  16. spline._lastTimeIndex
  17. ));
  18. const u = (time - times[i]) / (times[i + 1] - times[i]);
  19. const q0 = points[i];
  20. const 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 and times are required
  37. * @exception {DeveloperError} points.length must be greater than or equal to 2.
  38. * @exception {DeveloperError} times.length must be equal to points.length.
  39. * @see ConstantSpline
  40. * @see SteppedSpline
  41. * @see HermiteSpline
  42. * @see CatmullRomSpline
  43. * @see LinearSpline
  44. * @see MorphWeightSpline
  45. */
  46. function QuaternionSpline(options) {
  47. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  48. const points = options.points;
  49. const times = options.times;
  50. //>>includeStart('debug', pragmas.debug);
  51. if (!defined(points) || !defined(times)) {
  52. throw new DeveloperError("points and times are required.");
  53. }
  54. if (points.length < 2) {
  55. throw new DeveloperError(
  56. "points.length must be greater than or equal to 2."
  57. );
  58. }
  59. if (times.length !== points.length) {
  60. throw new DeveloperError("times.length must be equal to points.length.");
  61. }
  62. //>>includeEnd('debug');
  63. this._times = times;
  64. this._points = points;
  65. this._evaluateFunction = createEvaluateFunction(this);
  66. this._lastTimeIndex = 0;
  67. }
  68. Object.defineProperties(QuaternionSpline.prototype, {
  69. /**
  70. * An array of times for the control points.
  71. *
  72. * @memberof QuaternionSpline.prototype
  73. *
  74. * @type {number[]}
  75. * @readonly
  76. */
  77. times: {
  78. get: function () {
  79. return this._times;
  80. },
  81. },
  82. /**
  83. * An array of {@link Quaternion} control points.
  84. *
  85. * @memberof QuaternionSpline.prototype
  86. *
  87. * @type {Quaternion[]}
  88. * @readonly
  89. */
  90. points: {
  91. get: function () {
  92. return this._points;
  93. },
  94. },
  95. });
  96. /**
  97. * Finds an index <code>i</code> in <code>times</code> such that the parameter
  98. * <code>time</code> is in the interval <code>[times[i], times[i + 1]]</code>.
  99. * @function
  100. *
  101. * @param {number} time The time.
  102. * @returns {number} The index for the element at the start of the interval.
  103. *
  104. * @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>
  105. * is the first element in the array <code>times</code> and <code>t<sub>n</sub></code> is the last element
  106. * in the array <code>times</code>.
  107. */
  108. QuaternionSpline.prototype.findTimeInterval = Spline.prototype.findTimeInterval;
  109. /**
  110. * Wraps the given time to the period covered by the spline.
  111. * @function
  112. *
  113. * @param {number} time The time.
  114. * @return {number} The time, wrapped around to the updated animation.
  115. */
  116. QuaternionSpline.prototype.wrapTime = Spline.prototype.wrapTime;
  117. /**
  118. * Clamps the given time to the period covered by the spline.
  119. * @function
  120. *
  121. * @param {number} time The time.
  122. * @return {number} The time, clamped to the animation period.
  123. */
  124. QuaternionSpline.prototype.clampTime = Spline.prototype.clampTime;
  125. /**
  126. * Evaluates the curve at a given time.
  127. *
  128. * @param {number} time The time at which to evaluate the curve.
  129. * @param {Quaternion} [result] The object onto which to store the result.
  130. * @returns {Quaternion} The modified result parameter or a new instance of the point on the curve at the given time.
  131. *
  132. * @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>
  133. * is the first element in the array <code>times</code> and <code>t<sub>n</sub></code> is the last element
  134. * in the array <code>times</code>.
  135. */
  136. QuaternionSpline.prototype.evaluate = function (time, result) {
  137. return this._evaluateFunction(time, result);
  138. };
  139. export default QuaternionSpline;