Curve.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. // Purposely not including Base.h here, or any other gameplay dependencies
  2. // so this class can be reused between gameplay and gameplay-encoder.
  3. #include "Curve.h"
  4. #include <assert.h>
  5. #include <math.h>
  6. #include <memory.h>
  7. #ifndef NULL
  8. #define NULL 0
  9. #endif
  10. namespace gameplay
  11. {
  12. Curve::Curve(unsigned int pointCount, unsigned int componentCount)
  13. : _pointCount(pointCount), _componentCount(componentCount), _componentSize(0), _quaternionOffsets(NULL), _quaternionOffsetsCount(0), _points(NULL)
  14. {
  15. assert(pointCount > 1 && componentCount > 0);
  16. _componentSize = sizeof(float)*componentCount;
  17. _points = new Point[_pointCount];
  18. for (unsigned int i = 0; i < _pointCount; i++)
  19. {
  20. _points[i].time = 0.0f;
  21. _points[i].value = new float[_componentCount];
  22. _points[i].inValue = new float[_componentCount];
  23. _points[i].outValue = new float[_componentCount];
  24. _points[i].type = LINEAR;
  25. }
  26. _points[_pointCount - 1].time = 1.0f;
  27. }
  28. Curve::~Curve()
  29. {
  30. delete[] _points;
  31. delete[] _quaternionOffsets;
  32. }
  33. Curve::Point::Point()
  34. : time(0.0f), value(NULL), inValue(NULL), outValue(NULL)
  35. {
  36. }
  37. Curve::Point::~Point()
  38. {
  39. delete[] value;
  40. delete[] inValue;
  41. delete[] outValue;
  42. }
  43. unsigned int Curve::getPointCount() const
  44. {
  45. return _pointCount;
  46. }
  47. unsigned int Curve::getComponentCount() const
  48. {
  49. return _componentCount;
  50. }
  51. float Curve::getStartTime() const
  52. {
  53. return _points[0].time;
  54. }
  55. float Curve::getEndTime() const
  56. {
  57. return _points[_pointCount-1].time;
  58. }
  59. void Curve::setPoint(unsigned int index, float time, float* value, InterpolationType type)
  60. {
  61. setPoint(index, time, value, type, NULL, NULL);
  62. }
  63. void Curve::setPoint(unsigned int index, float time, float* value, InterpolationType type, float* inValue, float* outValue)
  64. {
  65. assert(index < _pointCount && time >= 0.0f && time <= 1.0f && !(index == 0 && time != 0.0f) && !(index == _pointCount - 1 && time != 1.0f));
  66. _points[index].time = time;
  67. _points[index].type = type;
  68. if (value)
  69. memcpy(_points[index].value, value, _componentSize);
  70. if (inValue)
  71. memcpy(_points[index].inValue, inValue, _componentSize);
  72. if (outValue)
  73. memcpy(_points[index].outValue, outValue, _componentSize);
  74. }
  75. void Curve::setTangent(unsigned int index, InterpolationType type, float* inValue, float* outValue)
  76. {
  77. assert(index < _pointCount);
  78. _points[index].type = type;
  79. if (inValue)
  80. memcpy(_points[index].inValue, inValue, _componentSize);
  81. if (outValue)
  82. memcpy(_points[index].outValue, outValue, _componentSize);
  83. }
  84. void Curve::evaluate(float time, float* dst) const
  85. {
  86. assert(dst && time >= 0 && time <= 1.0f);
  87. // Check if we are at or beyond the bounds of the curve.
  88. if (time <= _points[0].time)
  89. {
  90. memcpy(dst, _points[0].value, _componentSize);
  91. return;
  92. }
  93. else if (time >= _points[_pointCount - 1].time)
  94. {
  95. memcpy(dst, _points[_pointCount - 1].value, _componentSize);
  96. return;
  97. }
  98. // Locate the points we are interpolating between using a binary search.
  99. unsigned int index = determineIndex(time);
  100. Point* from = _points + index;
  101. Point* to = _points + (index + 1);
  102. // Calculate the fractional time between the two points.
  103. float scale = (to->time - from->time);
  104. float t = (time - from->time) / scale;
  105. // Calculate the value of the curve discretely if appropriate.
  106. switch (from->type)
  107. {
  108. case BEZIER:
  109. {
  110. interpolateBezier(t, from, to, dst);
  111. break;
  112. }
  113. case BSPLINE:
  114. {
  115. Point* c0;
  116. Point* c1;
  117. if (index == 0)
  118. {
  119. c0 = from;
  120. }
  121. else
  122. {
  123. c0 = (_points + index - 1);
  124. }
  125. if (index == _pointCount - 2)
  126. {
  127. c1 = to;
  128. }
  129. else
  130. {
  131. c1 = (_points + index + 2);
  132. }
  133. interpolateBSpline(t, c0, from, to, c1, dst);
  134. break;
  135. }
  136. case FLAT:
  137. {
  138. interpolateHermiteFlat(t, from, to, dst);
  139. break;
  140. }
  141. case HERMITE:
  142. {
  143. interpolateHermite(t, from, to, dst);
  144. break;
  145. }
  146. case LINEAR:
  147. {
  148. interpolateLinear(t, from, to, dst);
  149. break;
  150. }
  151. case SMOOTH:
  152. {
  153. interpolateHermiteSmooth(t, index, from, to, dst);
  154. break;
  155. }
  156. case STEP:
  157. {
  158. memcpy(dst, from->value, _componentSize);
  159. break;
  160. }
  161. }
  162. }
  163. void Curve::addQuaternionOffset(unsigned int offset)
  164. {
  165. if (!_quaternionOffsets)
  166. {
  167. _quaternionOffsetsCount = 1;
  168. _quaternionOffsets = new unsigned int[_quaternionOffsetsCount];
  169. _quaternionOffsets[0] = offset;
  170. }
  171. else
  172. {
  173. assert((offset >= _componentCount - 4) && (offset > (_quaternionOffsets[_quaternionOffsetsCount - 1] + 3)));
  174. unsigned int oldSize = _quaternionOffsetsCount;
  175. _quaternionOffsetsCount++;
  176. unsigned int* newArray = new unsigned int[_quaternionOffsetsCount];
  177. memcpy(newArray, _quaternionOffsets, sizeof(unsigned int) * oldSize);
  178. // set new offset.
  179. newArray[oldSize] = offset;
  180. delete[] _quaternionOffsets; // delete old array
  181. _quaternionOffsets = newArray; // point to new array.
  182. }
  183. }
  184. void Curve::interpolateBezier(float s, Point* from, Point* to, float* dst) const
  185. {
  186. float s_2 = s * s;
  187. float eq0 = 1 - s;
  188. float eq0_2 = eq0 * eq0;
  189. float eq1 = eq0_2 * eq0;
  190. float eq2 = 3 * s * eq0_2;
  191. float eq3 = 3 * s_2 * eq0;
  192. float eq4 = s_2 * s;
  193. if (!_quaternionOffsets)
  194. {
  195. for (unsigned int i = 0; i < _componentCount; i++)
  196. {
  197. dst[i] = from->value[i] * eq1 + from->outValue[i] * eq2 + to->inValue[i] * eq3 + to->value[i] * eq4;
  198. }
  199. }
  200. else
  201. {
  202. // Interpolate values as scalars up to first quaternion offset.
  203. unsigned int quaternionOffsetIndex = 0;
  204. unsigned int quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  205. unsigned int i = 0;
  206. do {
  207. while (i < quaternionOffset)
  208. {
  209. dst[i] = from->value[i] * eq1 + from->outValue[i] * eq2 + to->inValue[i] * eq3 + to->value[i] * eq4;
  210. i++;
  211. }
  212. // Handle quaternion component.
  213. interpolateQuaternion(s, (from->value + i), (to->value + i), (dst + i));
  214. i += 4;
  215. quaternionOffsetIndex++;
  216. quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  217. } while (quaternionOffsetIndex < _quaternionOffsetsCount);
  218. while (i < _componentCount)
  219. {
  220. dst[i] = from->value[i] * eq1 + from->outValue[i] * eq2 + to->inValue[i] * eq3 + to->value[i] * eq4;
  221. i++;
  222. }
  223. }
  224. }
  225. void Curve::interpolateBSpline(float s, Point* c0, Point* c1, Point* c2, Point* c3, float* dst) const
  226. {
  227. float s_2 = s * s;
  228. float s_3 = s_2 * s;
  229. float eq0 = (-s_3 + 3 * s_2 - 3 * s + 1) / 6.0f;
  230. float eq1 = (3 * s_3 - 6 * s_2 + 4) / 6.0f;
  231. float eq2 = (-3 * s_3 + 3 * s_2 + 3 * s + 1) / 6.0f;
  232. float eq3 = s_3 / 6.0f;
  233. if (!_quaternionOffsets)
  234. {
  235. for (unsigned int i = 0; i < _componentCount; i++)
  236. {
  237. dst[i] = c0->value[i] * eq0 + c1->value[i] * eq1 + c2->value[i] * eq2 + c3->value[i] * eq3;
  238. }
  239. }
  240. else
  241. {
  242. // Interpolate values as scalars up to first quaternion offset.
  243. unsigned int quaternionOffsetIndex = 0;
  244. unsigned int quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  245. unsigned int i = 0;
  246. do {
  247. while (i < quaternionOffset)
  248. {
  249. dst[i] = c0->value[i] * eq0 + c1->value[i] * eq1 + c2->value[i] * eq2 + c3->value[i] * eq3;
  250. i++;
  251. }
  252. // Handle quaternion component.
  253. float interpTime;
  254. if (c0->time == c1->time)
  255. interpTime = -c0->time * eq0 + c1->time * eq1 + c2->time * eq2 + c3->time * eq3;
  256. else if (c2->time == c3->time)
  257. interpTime = c0->time * eq0 + c1->time * eq1 + c2->time * eq2 - c3->time * eq3;
  258. else
  259. interpTime = c0->time * eq0 + c1->time * eq1 + c2->time * eq2 + c3->time * eq3;
  260. interpolateQuaternion(s, (c1->value + quaternionOffset) , (c2->value + quaternionOffset), (dst + quaternionOffset));
  261. i += 4;
  262. quaternionOffsetIndex++;
  263. quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  264. } while (quaternionOffsetIndex < _quaternionOffsetsCount);
  265. // Handle remaining scalar values.
  266. while (i < _componentCount)
  267. {
  268. dst[i] = c0->value[i] * eq0 + c1->value[i] * eq1 + c2->value[i] * eq2 + c3->value[i] * eq3;
  269. i++;
  270. }
  271. }
  272. }
  273. void Curve::interpolateHermite(float s, Point* from, Point* to, float* dst) const
  274. {
  275. // Calculate the hermite basis functions.
  276. float s_2 = s * s; // t^2
  277. float s_3 = s_2 * s; // t^3
  278. float h00 = 2 * s_3 - 3 * s_2 + 1; // basis function 0
  279. float h01 = -2 * s_3 + 3 * s_2; // basis function 1
  280. float h10 = s_3 - 2 * s_2 + s; // basis function 2
  281. float h11 = s_3 - s_2; // basis function 3
  282. if (!_quaternionOffsets)
  283. {
  284. for (unsigned int i = 0; i < _componentCount; i++)
  285. {
  286. dst[i] = h00 * from->value[i] + h01 * to->value[i] + h10 * from->outValue[i] + h11 * to->inValue[i];
  287. }
  288. }
  289. else
  290. {
  291. // Interpolate values as scalars up to first quaternion offset.
  292. unsigned int quaternionOffsetIndex = 0;
  293. unsigned int quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  294. unsigned int i = 0;
  295. do {
  296. while (i < quaternionOffset)
  297. {
  298. dst[i] = h00 * from->value[i] + h01 * to->value[i] + h10 * from->outValue[i] + h11 * to->inValue[i];
  299. i++;
  300. }
  301. // Handle quaternion component.
  302. float interpTime = h01 * 1.0f + h10 * from->outValue[quaternionOffset] + h11 * to->inValue[quaternionOffset];
  303. interpolateQuaternion(interpTime, (from->value + quaternionOffset), (to->value + quaternionOffset), (dst + quaternionOffset));
  304. i += 4;
  305. quaternionOffsetIndex++;
  306. quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  307. } while (quaternionOffsetIndex < _quaternionOffsetsCount);
  308. // Handle remaining scalar values.
  309. while (i < _componentCount)
  310. {
  311. dst[i] = h00 * from->value[i] + h01 * to->value[i] + h10 * from->outValue[i] + h11 * to->inValue[i];
  312. i++;
  313. }
  314. }
  315. }
  316. void Curve::interpolateHermiteFlat(float s, Point* from, Point* to, float* dst) const
  317. {
  318. // Calculate the hermite basis functions.
  319. float s_2 = s * s; // t^2
  320. float s_3 = s_2 * s; // t^3
  321. float h00 = 2 * s_3 - 3 * s_2 + 1; // basis function 0
  322. float h01 = -2 * s_3 + 3 * s_2; // basis function 1
  323. if (!_quaternionOffsets)
  324. {
  325. for (unsigned int i = 0; i < _componentCount; i++)
  326. {
  327. dst[i] = h00 * from->value[i] + h01 * to->value[i];
  328. }
  329. }
  330. else
  331. {
  332. // Interpolate values as scalars up to first quaternion offset.
  333. unsigned int quaternionOffsetIndex = 0;
  334. unsigned int quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  335. unsigned int i = 0;
  336. float interpTime = h01 * 1.0f; // Can drop all other terms because they will compute to 0. Only need to compute once.
  337. do {
  338. while (i < quaternionOffset)
  339. {
  340. dst[i] = h00 * from->value[i] + h01 * to->value[i];
  341. i++;
  342. }
  343. // We've hit a quaternion component, so handle it. increase the component counter by 4, and increase quaternionOffsetIndex
  344. interpolateQuaternion(interpTime, (from->value + quaternionOffset), (to->value + quaternionOffset), (dst + quaternionOffset));
  345. i += 4;
  346. quaternionOffsetIndex++;
  347. quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  348. } while (quaternionOffsetIndex < _quaternionOffsetsCount);
  349. // Handle remaining scalar values.
  350. while (i < _componentCount)
  351. {
  352. dst[i] = h00 * from->value[i] + h01 * to->value[i];
  353. i++;
  354. }
  355. }
  356. }
  357. void Curve::interpolateHermiteSmooth(float s, unsigned int index, Point* from, Point* to, float* dst) const
  358. {
  359. // Calculate the hermite basis functions.
  360. float s_2 = s * s; // t^2
  361. float s_3 = s_2 * s; // t^3
  362. float h00 = 2 * s_3 - 3 * s_2 + 1; // basis function 0
  363. float h01 = -2 * s_3 + 3 * s_2; // basis function 1
  364. float h10 = s_3 - 2 * s_2 + s; // basis function 2
  365. float h11 = s_3 - s_2; // basis function 3
  366. float inValue;
  367. float outValue;
  368. if (!_quaternionOffsets)
  369. {
  370. for (unsigned int i = 0; i < _componentCount; i++)
  371. {
  372. if (index == 0)
  373. {
  374. outValue = to->value[i] - from->value[i];
  375. }
  376. else
  377. {
  378. outValue = (to->value[i] - (from - 1)->value[i]) * ((from->time - (from - 1)->time) / (to->time - (from - 1)->time));
  379. }
  380. if (index == _pointCount - 2)
  381. {
  382. inValue = to->value[i] - from->value[i];
  383. }
  384. else
  385. {
  386. inValue = ((to + 1)->value[i] - from->value[i]) * ((to->time - from->time) / ((to + 1)->time - from->time));
  387. }
  388. dst[i] = h00 * from->value[i] + h01 * to->value[i] + h10 * outValue + h11 * inValue;
  389. }
  390. }
  391. else
  392. {
  393. // Calculates in/out values for interpolating the time for the quaternion component.
  394. // Only need to calculate this once.
  395. if (index == 0)
  396. {
  397. outValue = to->time - from->time;
  398. }
  399. else
  400. {
  401. outValue = (to->time - (from - 1)->time) * ((from->time - (from - 1)->time) / (to->time - (from - 1)->time));
  402. }
  403. if (index == _pointCount - 2)
  404. {
  405. inValue = to->time - from->time;
  406. }
  407. else
  408. {
  409. inValue = ((to + 1)->time - from->time) * ((to->time - from->time) / ((to + 1)->time - from->time));
  410. }
  411. // Interpolate values as scalars up to first quaternion offset.
  412. unsigned int quaternionOffsetIndex = 0;
  413. unsigned int quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  414. unsigned int i = 0;
  415. do {
  416. // Handle scalar values up to the quaternion offset.
  417. while (i < quaternionOffset)
  418. {
  419. // Interpolate as scalar.
  420. if (index == 0)
  421. {
  422. outValue = to->value[i] - from->value[i];
  423. }
  424. else
  425. {
  426. outValue = (to->value[i] - (from - 1)->value[i]) * ((from->time - (from - 1)->time) / (to->time - (from - 1)->time));
  427. }
  428. if (index == _pointCount - 2)
  429. {
  430. inValue = to->value[i] - from->value[i];
  431. }
  432. else
  433. {
  434. inValue = ((to + 1)->value[i] - from->value[i]) * ((to->time - from->time) / ((to + 1)->time - from->time));
  435. }
  436. dst[i] = h00 * from->value[i] + h01 * to->value[i] + h10 * outValue + h11 * inValue;
  437. i++;
  438. }
  439. float interpTime = h01 * 1.0f + h10 * outValue + h11 * inValue;
  440. interpolateQuaternion(interpTime, (from->value + quaternionOffset), (to->value + quaternionOffset), (dst + quaternionOffset));
  441. i+=4;
  442. quaternionOffsetIndex++;
  443. quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  444. } while (quaternionOffsetIndex < _quaternionOffsetsCount);
  445. // Handle remaining scalar values.
  446. while (i < _componentCount)
  447. {
  448. // Interpolate as scalar.
  449. if (index == 0)
  450. {
  451. outValue = to->value[i] - from->value[i];
  452. }
  453. else
  454. {
  455. outValue = (to->value[i] - (from - 1)->value[i]) * ((from->time - (from - 1)->time) / (to->time - (from - 1)->time));
  456. }
  457. if (index == _pointCount - 2)
  458. {
  459. inValue = to->value[i] - from->value[i];
  460. }
  461. else
  462. {
  463. inValue = ((to + 1)->value[i] - from->value[i]) * ((to->time - from->time) / ((to + 1)->time - from->time));
  464. }
  465. dst[i] = h00 * from->value[i] + h01 * to->value[i] + h10 * outValue + h11 * inValue;
  466. i++;
  467. }
  468. }
  469. }
  470. void Curve::interpolateLinear(float s, Point* from, Point* to, float* dst) const
  471. {
  472. if (!_quaternionOffsets)
  473. {
  474. for (unsigned int i = 0; i < _componentCount; i++)
  475. {
  476. dst[i] = from->value[i] + (to->value[i] - from->value[i]) * s;
  477. }
  478. }
  479. else
  480. {
  481. // Interpolate values as scalars up to first quaternion offset.
  482. unsigned int quaternionOffsetIndex = 0;
  483. unsigned int quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  484. unsigned int i = 0;
  485. do {
  486. // Loop through values until you hit the next quaternion offset.
  487. while (i < quaternionOffset)
  488. {
  489. dst[i] = from->value[i] + (to->value[i] - from->value[i]) * s;
  490. i++;
  491. }
  492. // Handle quaternion component.
  493. interpolateQuaternion(s, (from->value + quaternionOffset), (to->value + quaternionOffset), (dst + quaternionOffset));
  494. i += 4;
  495. quaternionOffsetIndex++;
  496. quaternionOffset = _quaternionOffsets[quaternionOffsetIndex];
  497. } while (quaternionOffsetIndex < _quaternionOffsetsCount);
  498. // Loop through the last remaining values, if any.
  499. while (i < _componentCount)
  500. {
  501. dst[i] = from->value[i] + (to->value[i] - from->value[i]) * s;
  502. i++;
  503. }
  504. }
  505. }
  506. void slerpQuat(float* q1, float* q2, float t, float* dst)
  507. {
  508. // Fast slerp implementation by kwhatmough:
  509. // It contains no division operations, no trig, no inverse trig
  510. // and no sqrt. Not only does this code tolerate small constraint
  511. // errors in the input quaternions, it actually corrects for them.
  512. assert(dst);
  513. assert(!(t < 0.0f || t > 1.0f));
  514. if (t == 0.0f)
  515. {
  516. memcpy(dst, q1, sizeof(float) * 4);
  517. return;
  518. }
  519. else if (t == 1.0f)
  520. {
  521. memcpy(dst, q2, sizeof(float) * 4);
  522. return;
  523. }
  524. float halfY, alpha, beta;
  525. float u, f1, f2a, f2b;
  526. float ratio1, ratio2;
  527. float halfSecHalfTheta, versHalfTheta;
  528. float sqNotU, sqU;
  529. float cosTheta = q1[3] * q2[3] + q1[0] * q2[0] + q1[1] * q2[1] + q1[2] * q2[2];
  530. // As usual in all slerp implementations, we fold theta.
  531. alpha = cosTheta >= 0 ? 1.0f : -1.0f;
  532. halfY = 1.0f + alpha * cosTheta;
  533. // Here we bisect the interval, so we need to fold t as well.
  534. f2b = t - 0.5f;
  535. u = f2b >= 0 ? f2b : -f2b;
  536. f2a = u - f2b;
  537. f2b += u;
  538. u += u;
  539. f1 = 1.0f - u;
  540. // One iteration of Newton to get 1-cos(theta / 2) to good accuracy.
  541. halfSecHalfTheta = 1.09f - (0.476537f - 0.0903321f * halfY) * halfY;
  542. halfSecHalfTheta *= 1.5f - halfY * halfSecHalfTheta * halfSecHalfTheta;
  543. versHalfTheta = 1.0f - halfY * halfSecHalfTheta;
  544. // Evaluate series expansions of the coefficients.
  545. sqNotU = f1 * f1;
  546. ratio2 = 0.0000440917108f * versHalfTheta;
  547. ratio1 = -0.00158730159f + (sqNotU - 16.0f) * ratio2;
  548. ratio1 = 0.0333333333f + ratio1 * (sqNotU - 9.0f) * versHalfTheta;
  549. ratio1 = -0.333333333f + ratio1 * (sqNotU - 4.0f) * versHalfTheta;
  550. ratio1 = 1.0f + ratio1 * (sqNotU - 1.0f) * versHalfTheta;
  551. sqU = u * u;
  552. ratio2 = -0.00158730159f + (sqU - 16.0f) * ratio2;
  553. ratio2 = 0.0333333333f + ratio2 * (sqU - 9.0f) * versHalfTheta;
  554. ratio2 = -0.333333333f + ratio2 * (sqU - 4.0f) * versHalfTheta;
  555. ratio2 = 1.0f + ratio2 * (sqU - 1.0f) * versHalfTheta;
  556. // Perform the bisection and resolve the folding done earlier.
  557. f1 *= ratio1 * halfSecHalfTheta;
  558. f2a *= ratio2;
  559. f2b *= ratio2;
  560. alpha *= f1 + f2a;
  561. beta = f1 + f2b;
  562. // Apply final coefficients to a and b as usual.
  563. float w = alpha * q1[3] + beta * q2[3];
  564. float x = alpha * q1[0] + beta * q2[0];
  565. float y = alpha * q1[1] + beta * q2[1];
  566. float z = alpha * q1[2] + beta * q2[2];
  567. // This final adjustment to the quaternion's length corrects for
  568. // any small constraint error in the inputs q1 and q2. But as you
  569. // can see, it comes at the cost of 9 additional multiplication
  570. // operations. If this error-correcting feature is not required,
  571. // the following code may be removed.
  572. f1 = 1.5f - 0.5f * (w * w + x * x + y * y + z * z);
  573. dst[3] = w * f1;
  574. dst[0] = x * f1;
  575. dst[1] = y * f1;
  576. dst[2] = z * f1;
  577. }
  578. void normalizeQuat(float* q)
  579. {
  580. float n = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
  581. // Do we need to normalize?
  582. if (fabs(n) > 0.00001f && fabs(n - 1.0f) > 0.00001f)
  583. {
  584. n = sqrtf(n);
  585. q[0] /= n;
  586. q[1] /= n;
  587. q[2] /= n;
  588. q[3] /= n;
  589. }
  590. }
  591. void Curve::interpolateQuaternion(float s, float* from, float* to, float* dst) const
  592. {
  593. float quatFrom[4] = { from[0], from[1], from[2], from[3] };
  594. float quatTo[4] = { to[0], to[1], to[2], to[3] };
  595. // Normalize the quaternions.
  596. normalizeQuat(quatFrom);
  597. normalizeQuat(quatTo);
  598. // Evaluate.
  599. if (s >= 0)
  600. slerpQuat(quatFrom, quatTo, s, dst);
  601. else
  602. slerpQuat(quatTo, quatFrom, -s, dst);
  603. }
  604. int Curve::determineIndex(float time) const
  605. {
  606. unsigned int min = 0;
  607. unsigned int max = _pointCount - 1;
  608. unsigned int mid = 0;
  609. // Do a binary search to determine the index.
  610. do
  611. {
  612. mid = (min + max) >> 1;
  613. if (time >= _points[mid].time && time <= _points[mid + 1].time)
  614. return mid;
  615. else if (time < _points[mid].time)
  616. max = mid - 1;
  617. else
  618. min = mid + 1;
  619. } while (min <= max);
  620. // We should never hit this!
  621. return -1;
  622. }
  623. }