Home Reference Source

viewer/glmatrix/quat2.js

  1. import * as glMatrix from "./common.js";
  2. import * as quat from "./quat.js";
  3. import * as mat4 from "./mat4.js";
  4.  
  5. /**
  6. * Dual Quaternion<br>
  7. * Format: [real, dual]<br>
  8. * Quaternion format: XYZW<br>
  9. * Make sure to have normalized dual quaternions, otherwise the functions may not work as intended.<br>
  10. * @module quat2
  11. */
  12.  
  13. /**
  14. * Creates a new identity dual quat
  15. *
  16. * @returns {quat2} a new dual quaternion [real -> rotation, dual -> translation]
  17. */
  18. export function create() {
  19. let dq = new glMatrix.ARRAY_TYPE(8);
  20. if (glMatrix.ARRAY_TYPE != Float32Array) {
  21. dq[0] = 0;
  22. dq[1] = 0;
  23. dq[2] = 0;
  24. dq[4] = 0;
  25. dq[5] = 0;
  26. dq[6] = 0;
  27. dq[7] = 0;
  28. }
  29. dq[3] = 1;
  30. return dq;
  31. }
  32.  
  33. /**
  34. * Creates a new quat initialized with values from an existing quaternion
  35. *
  36. * @param {ReadonlyQuat2} a dual quaternion to clone
  37. * @returns {quat2} new dual quaternion
  38. * @function
  39. */
  40. export function clone(a) {
  41. let dq = new glMatrix.ARRAY_TYPE(8);
  42. dq[0] = a[0];
  43. dq[1] = a[1];
  44. dq[2] = a[2];
  45. dq[3] = a[3];
  46. dq[4] = a[4];
  47. dq[5] = a[5];
  48. dq[6] = a[6];
  49. dq[7] = a[7];
  50. return dq;
  51. }
  52.  
  53. /**
  54. * Creates a new dual quat initialized with the given values
  55. *
  56. * @param {Number} x1 X component
  57. * @param {Number} y1 Y component
  58. * @param {Number} z1 Z component
  59. * @param {Number} w1 W component
  60. * @param {Number} x2 X component
  61. * @param {Number} y2 Y component
  62. * @param {Number} z2 Z component
  63. * @param {Number} w2 W component
  64. * @returns {quat2} new dual quaternion
  65. * @function
  66. */
  67. export function fromValues(x1, y1, z1, w1, x2, y2, z2, w2) {
  68. let dq = new glMatrix.ARRAY_TYPE(8);
  69. dq[0] = x1;
  70. dq[1] = y1;
  71. dq[2] = z1;
  72. dq[3] = w1;
  73. dq[4] = x2;
  74. dq[5] = y2;
  75. dq[6] = z2;
  76. dq[7] = w2;
  77. return dq;
  78. }
  79.  
  80. /**
  81. * Creates a new dual quat from the given values (quat and translation)
  82. *
  83. * @param {Number} x1 X component
  84. * @param {Number} y1 Y component
  85. * @param {Number} z1 Z component
  86. * @param {Number} w1 W component
  87. * @param {Number} x2 X component (translation)
  88. * @param {Number} y2 Y component (translation)
  89. * @param {Number} z2 Z component (translation)
  90. * @returns {quat2} new dual quaternion
  91. * @function
  92. */
  93. export function fromRotationTranslationValues(x1, y1, z1, w1, x2, y2, z2) {
  94. let dq = new glMatrix.ARRAY_TYPE(8);
  95. dq[0] = x1;
  96. dq[1] = y1;
  97. dq[2] = z1;
  98. dq[3] = w1;
  99. let ax = x2 * 0.5,
  100. ay = y2 * 0.5,
  101. az = z2 * 0.5;
  102. dq[4] = ax * w1 + ay * z1 - az * y1;
  103. dq[5] = ay * w1 + az * x1 - ax * z1;
  104. dq[6] = az * w1 + ax * y1 - ay * x1;
  105. dq[7] = -ax * x1 - ay * y1 - az * z1;
  106. return dq;
  107. }
  108.  
  109. /**
  110. * Creates a dual quat from a quaternion and a translation
  111. *
  112. * @param {ReadonlyQuat2} dual quaternion receiving operation result
  113. * @param {ReadonlyQuat} q a normalized quaternion
  114. * @param {ReadonlyVec3} t tranlation vector
  115. * @returns {quat2} dual quaternion receiving operation result
  116. * @function
  117. */
  118. export function fromRotationTranslation(out, q, t) {
  119. let ax = t[0] * 0.5,
  120. ay = t[1] * 0.5,
  121. az = t[2] * 0.5,
  122. bx = q[0],
  123. by = q[1],
  124. bz = q[2],
  125. bw = q[3];
  126. out[0] = bx;
  127. out[1] = by;
  128. out[2] = bz;
  129. out[3] = bw;
  130. out[4] = ax * bw + ay * bz - az * by;
  131. out[5] = ay * bw + az * bx - ax * bz;
  132. out[6] = az * bw + ax * by - ay * bx;
  133. out[7] = -ax * bx - ay * by - az * bz;
  134. return out;
  135. }
  136.  
  137. /**
  138. * Creates a dual quat from a translation
  139. *
  140. * @param {ReadonlyQuat2} dual quaternion receiving operation result
  141. * @param {ReadonlyVec3} t translation vector
  142. * @returns {quat2} dual quaternion receiving operation result
  143. * @function
  144. */
  145. export function fromTranslation(out, t) {
  146. out[0] = 0;
  147. out[1] = 0;
  148. out[2] = 0;
  149. out[3] = 1;
  150. out[4] = t[0] * 0.5;
  151. out[5] = t[1] * 0.5;
  152. out[6] = t[2] * 0.5;
  153. out[7] = 0;
  154. return out;
  155. }
  156.  
  157. /**
  158. * Creates a dual quat from a quaternion
  159. *
  160. * @param {ReadonlyQuat2} dual quaternion receiving operation result
  161. * @param {ReadonlyQuat} q the quaternion
  162. * @returns {quat2} dual quaternion receiving operation result
  163. * @function
  164. */
  165. export function fromRotation(out, q) {
  166. out[0] = q[0];
  167. out[1] = q[1];
  168. out[2] = q[2];
  169. out[3] = q[3];
  170. out[4] = 0;
  171. out[5] = 0;
  172. out[6] = 0;
  173. out[7] = 0;
  174. return out;
  175. }
  176.  
  177. /**
  178. * Creates a new dual quat from a matrix (4x4)
  179. *
  180. * @param {quat2} out the dual quaternion
  181. * @param {ReadonlyMat4} a the matrix
  182. * @returns {quat2} dual quat receiving operation result
  183. * @function
  184. */
  185. export function fromMat4(out, a) {
  186. //TODO Optimize this
  187. let outer = quat.create();
  188. mat4.getRotation(outer, a);
  189. let t = new glMatrix.ARRAY_TYPE(3);
  190. mat4.getTranslation(t, a);
  191. fromRotationTranslation(out, outer, t);
  192. return out;
  193. }
  194.  
  195. /**
  196. * Copy the values from one dual quat to another
  197. *
  198. * @param {quat2} out the receiving dual quaternion
  199. * @param {ReadonlyQuat2} a the source dual quaternion
  200. * @returns {quat2} out
  201. * @function
  202. */
  203. export function copy(out, a) {
  204. out[0] = a[0];
  205. out[1] = a[1];
  206. out[2] = a[2];
  207. out[3] = a[3];
  208. out[4] = a[4];
  209. out[5] = a[5];
  210. out[6] = a[6];
  211. out[7] = a[7];
  212. return out;
  213. }
  214.  
  215. /**
  216. * Set a dual quat to the identity dual quaternion
  217. *
  218. * @param {quat2} out the receiving quaternion
  219. * @returns {quat2} out
  220. */
  221. export function identity(out) {
  222. out[0] = 0;
  223. out[1] = 0;
  224. out[2] = 0;
  225. out[3] = 1;
  226. out[4] = 0;
  227. out[5] = 0;
  228. out[6] = 0;
  229. out[7] = 0;
  230. return out;
  231. }
  232.  
  233. /**
  234. * Set the components of a dual quat to the given values
  235. *
  236. * @param {quat2} out the receiving quaternion
  237. * @param {Number} x1 X component
  238. * @param {Number} y1 Y component
  239. * @param {Number} z1 Z component
  240. * @param {Number} w1 W component
  241. * @param {Number} x2 X component
  242. * @param {Number} y2 Y component
  243. * @param {Number} z2 Z component
  244. * @param {Number} w2 W component
  245. * @returns {quat2} out
  246. * @function
  247. */
  248. export function set(out, x1, y1, z1, w1, x2, y2, z2, w2) {
  249. out[0] = x1;
  250. out[1] = y1;
  251. out[2] = z1;
  252. out[3] = w1;
  253.  
  254. out[4] = x2;
  255. out[5] = y2;
  256. out[6] = z2;
  257. out[7] = w2;
  258. return out;
  259. }
  260.  
  261. /**
  262. * Gets the real part of a dual quat
  263. * @param {quat} out real part
  264. * @param {ReadonlyQuat2} a Dual Quaternion
  265. * @return {quat} real part
  266. */
  267. export const getReal = quat.copy;
  268.  
  269. /**
  270. * Gets the dual part of a dual quat
  271. * @param {quat} out dual part
  272. * @param {ReadonlyQuat2} a Dual Quaternion
  273. * @return {quat} dual part
  274. */
  275. export function getDual(out, a) {
  276. out[0] = a[4];
  277. out[1] = a[5];
  278. out[2] = a[6];
  279. out[3] = a[7];
  280. return out;
  281. }
  282.  
  283. /**
  284. * Set the real component of a dual quat to the given quaternion
  285. *
  286. * @param {quat2} out the receiving quaternion
  287. * @param {ReadonlyQuat} q a quaternion representing the real part
  288. * @returns {quat2} out
  289. * @function
  290. */
  291. export const setReal = quat.copy;
  292.  
  293. /**
  294. * Set the dual component of a dual quat to the given quaternion
  295. *
  296. * @param {quat2} out the receiving quaternion
  297. * @param {ReadonlyQuat} q a quaternion representing the dual part
  298. * @returns {quat2} out
  299. * @function
  300. */
  301. export function setDual(out, q) {
  302. out[4] = q[0];
  303. out[5] = q[1];
  304. out[6] = q[2];
  305. out[7] = q[3];
  306. return out;
  307. }
  308.  
  309. /**
  310. * Gets the translation of a normalized dual quat
  311. * @param {vec3} out translation
  312. * @param {ReadonlyQuat2} a Dual Quaternion to be decomposed
  313. * @return {vec3} translation
  314. */
  315. export function getTranslation(out, a) {
  316. let ax = a[4],
  317. ay = a[5],
  318. az = a[6],
  319. aw = a[7],
  320. bx = -a[0],
  321. by = -a[1],
  322. bz = -a[2],
  323. bw = a[3];
  324. out[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;
  325. out[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;
  326. out[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;
  327. return out;
  328. }
  329.  
  330. /**
  331. * Translates a dual quat by the given vector
  332. *
  333. * @param {quat2} out the receiving dual quaternion
  334. * @param {ReadonlyQuat2} a the dual quaternion to translate
  335. * @param {ReadonlyVec3} v vector to translate by
  336. * @returns {quat2} out
  337. */
  338. export function translate(out, a, v) {
  339. let ax1 = a[0],
  340. ay1 = a[1],
  341. az1 = a[2],
  342. aw1 = a[3],
  343. bx1 = v[0] * 0.5,
  344. by1 = v[1] * 0.5,
  345. bz1 = v[2] * 0.5,
  346. ax2 = a[4],
  347. ay2 = a[5],
  348. az2 = a[6],
  349. aw2 = a[7];
  350. out[0] = ax1;
  351. out[1] = ay1;
  352. out[2] = az1;
  353. out[3] = aw1;
  354. out[4] = aw1 * bx1 + ay1 * bz1 - az1 * by1 + ax2;
  355. out[5] = aw1 * by1 + az1 * bx1 - ax1 * bz1 + ay2;
  356. out[6] = aw1 * bz1 + ax1 * by1 - ay1 * bx1 + az2;
  357. out[7] = -ax1 * bx1 - ay1 * by1 - az1 * bz1 + aw2;
  358. return out;
  359. }
  360.  
  361. /**
  362. * Rotates a dual quat around the X axis
  363. *
  364. * @param {quat2} out the receiving dual quaternion
  365. * @param {ReadonlyQuat2} a the dual quaternion to rotate
  366. * @param {number} rad how far should the rotation be
  367. * @returns {quat2} out
  368. */
  369. export function rotateX(out, a, rad) {
  370. let bx = -a[0],
  371. by = -a[1],
  372. bz = -a[2],
  373. bw = a[3],
  374. ax = a[4],
  375. ay = a[5],
  376. az = a[6],
  377. aw = a[7],
  378. ax1 = ax * bw + aw * bx + ay * bz - az * by,
  379. ay1 = ay * bw + aw * by + az * bx - ax * bz,
  380. az1 = az * bw + aw * bz + ax * by - ay * bx,
  381. aw1 = aw * bw - ax * bx - ay * by - az * bz;
  382. quat.rotateX(out, a, rad);
  383. bx = out[0];
  384. by = out[1];
  385. bz = out[2];
  386. bw = out[3];
  387. out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
  388. out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
  389. out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
  390. out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
  391. return out;
  392. }
  393.  
  394. /**
  395. * Rotates a dual quat around the Y axis
  396. *
  397. * @param {quat2} out the receiving dual quaternion
  398. * @param {ReadonlyQuat2} a the dual quaternion to rotate
  399. * @param {number} rad how far should the rotation be
  400. * @returns {quat2} out
  401. */
  402. export function rotateY(out, a, rad) {
  403. let bx = -a[0],
  404. by = -a[1],
  405. bz = -a[2],
  406. bw = a[3],
  407. ax = a[4],
  408. ay = a[5],
  409. az = a[6],
  410. aw = a[7],
  411. ax1 = ax * bw + aw * bx + ay * bz - az * by,
  412. ay1 = ay * bw + aw * by + az * bx - ax * bz,
  413. az1 = az * bw + aw * bz + ax * by - ay * bx,
  414. aw1 = aw * bw - ax * bx - ay * by - az * bz;
  415. quat.rotateY(out, a, rad);
  416. bx = out[0];
  417. by = out[1];
  418. bz = out[2];
  419. bw = out[3];
  420. out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
  421. out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
  422. out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
  423. out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
  424. return out;
  425. }
  426.  
  427. /**
  428. * Rotates a dual quat around the Z axis
  429. *
  430. * @param {quat2} out the receiving dual quaternion
  431. * @param {ReadonlyQuat2} a the dual quaternion to rotate
  432. * @param {number} rad how far should the rotation be
  433. * @returns {quat2} out
  434. */
  435. export function rotateZ(out, a, rad) {
  436. let bx = -a[0],
  437. by = -a[1],
  438. bz = -a[2],
  439. bw = a[3],
  440. ax = a[4],
  441. ay = a[5],
  442. az = a[6],
  443. aw = a[7],
  444. ax1 = ax * bw + aw * bx + ay * bz - az * by,
  445. ay1 = ay * bw + aw * by + az * bx - ax * bz,
  446. az1 = az * bw + aw * bz + ax * by - ay * bx,
  447. aw1 = aw * bw - ax * bx - ay * by - az * bz;
  448. quat.rotateZ(out, a, rad);
  449. bx = out[0];
  450. by = out[1];
  451. bz = out[2];
  452. bw = out[3];
  453. out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
  454. out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
  455. out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
  456. out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
  457. return out;
  458. }
  459.  
  460. /**
  461. * Rotates a dual quat by a given quaternion (a * q)
  462. *
  463. * @param {quat2} out the receiving dual quaternion
  464. * @param {ReadonlyQuat2} a the dual quaternion to rotate
  465. * @param {ReadonlyQuat} q quaternion to rotate by
  466. * @returns {quat2} out
  467. */
  468. export function rotateByQuatAppend(out, a, q) {
  469. let qx = q[0],
  470. qy = q[1],
  471. qz = q[2],
  472. qw = q[3],
  473. ax = a[0],
  474. ay = a[1],
  475. az = a[2],
  476. aw = a[3];
  477.  
  478. out[0] = ax * qw + aw * qx + ay * qz - az * qy;
  479. out[1] = ay * qw + aw * qy + az * qx - ax * qz;
  480. out[2] = az * qw + aw * qz + ax * qy - ay * qx;
  481. out[3] = aw * qw - ax * qx - ay * qy - az * qz;
  482. ax = a[4];
  483. ay = a[5];
  484. az = a[6];
  485. aw = a[7];
  486. out[4] = ax * qw + aw * qx + ay * qz - az * qy;
  487. out[5] = ay * qw + aw * qy + az * qx - ax * qz;
  488. out[6] = az * qw + aw * qz + ax * qy - ay * qx;
  489. out[7] = aw * qw - ax * qx - ay * qy - az * qz;
  490. return out;
  491. }
  492.  
  493. /**
  494. * Rotates a dual quat by a given quaternion (q * a)
  495. *
  496. * @param {quat2} out the receiving dual quaternion
  497. * @param {ReadonlyQuat} q quaternion to rotate by
  498. * @param {ReadonlyQuat2} a the dual quaternion to rotate
  499. * @returns {quat2} out
  500. */
  501. export function rotateByQuatPrepend(out, q, a) {
  502. let qx = q[0],
  503. qy = q[1],
  504. qz = q[2],
  505. qw = q[3],
  506. bx = a[0],
  507. by = a[1],
  508. bz = a[2],
  509. bw = a[3];
  510.  
  511. out[0] = qx * bw + qw * bx + qy * bz - qz * by;
  512. out[1] = qy * bw + qw * by + qz * bx - qx * bz;
  513. out[2] = qz * bw + qw * bz + qx * by - qy * bx;
  514. out[3] = qw * bw - qx * bx - qy * by - qz * bz;
  515. bx = a[4];
  516. by = a[5];
  517. bz = a[6];
  518. bw = a[7];
  519. out[4] = qx * bw + qw * bx + qy * bz - qz * by;
  520. out[5] = qy * bw + qw * by + qz * bx - qx * bz;
  521. out[6] = qz * bw + qw * bz + qx * by - qy * bx;
  522. out[7] = qw * bw - qx * bx - qy * by - qz * bz;
  523. return out;
  524. }
  525.  
  526. /**
  527. * Rotates a dual quat around a given axis. Does the normalisation automatically
  528. *
  529. * @param {quat2} out the receiving dual quaternion
  530. * @param {ReadonlyQuat2} a the dual quaternion to rotate
  531. * @param {ReadonlyVec3} axis the axis to rotate around
  532. * @param {Number} rad how far the rotation should be
  533. * @returns {quat2} out
  534. */
  535. export function rotateAroundAxis(out, a, axis, rad) {
  536. //Special case for rad = 0
  537. if (Math.abs(rad) < glMatrix.EPSILON) {
  538. return copy(out, a);
  539. }
  540. let axisLength = Math.hypot(axis[0], axis[1], axis[2]);
  541.  
  542. rad = rad * 0.5;
  543. let s = Math.sin(rad);
  544. let bx = (s * axis[0]) / axisLength;
  545. let by = (s * axis[1]) / axisLength;
  546. let bz = (s * axis[2]) / axisLength;
  547. let bw = Math.cos(rad);
  548.  
  549. let ax1 = a[0],
  550. ay1 = a[1],
  551. az1 = a[2],
  552. aw1 = a[3];
  553. out[0] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
  554. out[1] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
  555. out[2] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
  556. out[3] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
  557.  
  558. let ax = a[4],
  559. ay = a[5],
  560. az = a[6],
  561. aw = a[7];
  562. out[4] = ax * bw + aw * bx + ay * bz - az * by;
  563. out[5] = ay * bw + aw * by + az * bx - ax * bz;
  564. out[6] = az * bw + aw * bz + ax * by - ay * bx;
  565. out[7] = aw * bw - ax * bx - ay * by - az * bz;
  566.  
  567. return out;
  568. }
  569.  
  570. /**
  571. * Adds two dual quat's
  572. *
  573. * @param {quat2} out the receiving dual quaternion
  574. * @param {ReadonlyQuat2} a the first operand
  575. * @param {ReadonlyQuat2} b the second operand
  576. * @returns {quat2} out
  577. * @function
  578. */
  579. export function add(out, a, b) {
  580. out[0] = a[0] + b[0];
  581. out[1] = a[1] + b[1];
  582. out[2] = a[2] + b[2];
  583. out[3] = a[3] + b[3];
  584. out[4] = a[4] + b[4];
  585. out[5] = a[5] + b[5];
  586. out[6] = a[6] + b[6];
  587. out[7] = a[7] + b[7];
  588. return out;
  589. }
  590.  
  591. /**
  592. * Multiplies two dual quat's
  593. *
  594. * @param {quat2} out the receiving dual quaternion
  595. * @param {ReadonlyQuat2} a the first operand
  596. * @param {ReadonlyQuat2} b the second operand
  597. * @returns {quat2} out
  598. */
  599. export function multiply(out, a, b) {
  600. let ax0 = a[0],
  601. ay0 = a[1],
  602. az0 = a[2],
  603. aw0 = a[3],
  604. bx1 = b[4],
  605. by1 = b[5],
  606. bz1 = b[6],
  607. bw1 = b[7],
  608. ax1 = a[4],
  609. ay1 = a[5],
  610. az1 = a[6],
  611. aw1 = a[7],
  612. bx0 = b[0],
  613. by0 = b[1],
  614. bz0 = b[2],
  615. bw0 = b[3];
  616. out[0] = ax0 * bw0 + aw0 * bx0 + ay0 * bz0 - az0 * by0;
  617. out[1] = ay0 * bw0 + aw0 * by0 + az0 * bx0 - ax0 * bz0;
  618. out[2] = az0 * bw0 + aw0 * bz0 + ax0 * by0 - ay0 * bx0;
  619. out[3] = aw0 * bw0 - ax0 * bx0 - ay0 * by0 - az0 * bz0;
  620. out[4] =
  621. ax0 * bw1 +
  622. aw0 * bx1 +
  623. ay0 * bz1 -
  624. az0 * by1 +
  625. ax1 * bw0 +
  626. aw1 * bx0 +
  627. ay1 * bz0 -
  628. az1 * by0;
  629. out[5] =
  630. ay0 * bw1 +
  631. aw0 * by1 +
  632. az0 * bx1 -
  633. ax0 * bz1 +
  634. ay1 * bw0 +
  635. aw1 * by0 +
  636. az1 * bx0 -
  637. ax1 * bz0;
  638. out[6] =
  639. az0 * bw1 +
  640. aw0 * bz1 +
  641. ax0 * by1 -
  642. ay0 * bx1 +
  643. az1 * bw0 +
  644. aw1 * bz0 +
  645. ax1 * by0 -
  646. ay1 * bx0;
  647. out[7] =
  648. aw0 * bw1 -
  649. ax0 * bx1 -
  650. ay0 * by1 -
  651. az0 * bz1 +
  652. aw1 * bw0 -
  653. ax1 * bx0 -
  654. ay1 * by0 -
  655. az1 * bz0;
  656. return out;
  657. }
  658.  
  659. /**
  660. * Alias for {@link quat2.multiply}
  661. * @function
  662. */
  663. export const mul = multiply;
  664.  
  665. /**
  666. * Scales a dual quat by a scalar number
  667. *
  668. * @param {quat2} out the receiving dual quat
  669. * @param {ReadonlyQuat2} a the dual quat to scale
  670. * @param {Number} b amount to scale the dual quat by
  671. * @returns {quat2} out
  672. * @function
  673. */
  674. export function scale(out, a, b) {
  675. out[0] = a[0] * b;
  676. out[1] = a[1] * b;
  677. out[2] = a[2] * b;
  678. out[3] = a[3] * b;
  679. out[4] = a[4] * b;
  680. out[5] = a[5] * b;
  681. out[6] = a[6] * b;
  682. out[7] = a[7] * b;
  683. return out;
  684. }
  685.  
  686. /**
  687. * Calculates the dot product of two dual quat's (The dot product of the real parts)
  688. *
  689. * @param {ReadonlyQuat2} a the first operand
  690. * @param {ReadonlyQuat2} b the second operand
  691. * @returns {Number} dot product of a and b
  692. * @function
  693. */
  694. export const dot = quat.dot;
  695.  
  696. /**
  697. * Performs a linear interpolation between two dual quats's
  698. * NOTE: The resulting dual quaternions won't always be normalized (The error is most noticeable when t = 0.5)
  699. *
  700. * @param {quat2} out the receiving dual quat
  701. * @param {ReadonlyQuat2} a the first operand
  702. * @param {ReadonlyQuat2} b the second operand
  703. * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
  704. * @returns {quat2} out
  705. */
  706. export function lerp(out, a, b, t) {
  707. let mt = 1 - t;
  708. if (dot(a, b) < 0) t = -t;
  709.  
  710. out[0] = a[0] * mt + b[0] * t;
  711. out[1] = a[1] * mt + b[1] * t;
  712. out[2] = a[2] * mt + b[2] * t;
  713. out[3] = a[3] * mt + b[3] * t;
  714. out[4] = a[4] * mt + b[4] * t;
  715. out[5] = a[5] * mt + b[5] * t;
  716. out[6] = a[6] * mt + b[6] * t;
  717. out[7] = a[7] * mt + b[7] * t;
  718.  
  719. return out;
  720. }
  721.  
  722. /**
  723. * Calculates the inverse of a dual quat. If they are normalized, conjugate is cheaper
  724. *
  725. * @param {quat2} out the receiving dual quaternion
  726. * @param {ReadonlyQuat2} a dual quat to calculate inverse of
  727. * @returns {quat2} out
  728. */
  729. export function invert(out, a) {
  730. let sqlen = squaredLength(a);
  731. out[0] = -a[0] / sqlen;
  732. out[1] = -a[1] / sqlen;
  733. out[2] = -a[2] / sqlen;
  734. out[3] = a[3] / sqlen;
  735. out[4] = -a[4] / sqlen;
  736. out[5] = -a[5] / sqlen;
  737. out[6] = -a[6] / sqlen;
  738. out[7] = a[7] / sqlen;
  739. return out;
  740. }
  741.  
  742. /**
  743. * Calculates the conjugate of a dual quat
  744. * If the dual quaternion is normalized, this function is faster than quat2.inverse and produces the same result.
  745. *
  746. * @param {quat2} out the receiving quaternion
  747. * @param {ReadonlyQuat2} a quat to calculate conjugate of
  748. * @returns {quat2} out
  749. */
  750. export function conjugate(out, a) {
  751. out[0] = -a[0];
  752. out[1] = -a[1];
  753. out[2] = -a[2];
  754. out[3] = a[3];
  755. out[4] = -a[4];
  756. out[5] = -a[5];
  757. out[6] = -a[6];
  758. out[7] = a[7];
  759. return out;
  760. }
  761.  
  762. /**
  763. * Calculates the length of a dual quat
  764. *
  765. * @param {ReadonlyQuat2} a dual quat to calculate length of
  766. * @returns {Number} length of a
  767. * @function
  768. */
  769. export const length = quat.length;
  770.  
  771. /**
  772. * Alias for {@link quat2.length}
  773. * @function
  774. */
  775. export const len = length;
  776.  
  777. /**
  778. * Calculates the squared length of a dual quat
  779. *
  780. * @param {ReadonlyQuat2} a dual quat to calculate squared length of
  781. * @returns {Number} squared length of a
  782. * @function
  783. */
  784. export const squaredLength = quat.squaredLength;
  785.  
  786. /**
  787. * Alias for {@link quat2.squaredLength}
  788. * @function
  789. */
  790. export const sqrLen = squaredLength;
  791.  
  792. /**
  793. * Normalize a dual quat
  794. *
  795. * @param {quat2} out the receiving dual quaternion
  796. * @param {ReadonlyQuat2} a dual quaternion to normalize
  797. * @returns {quat2} out
  798. * @function
  799. */
  800. export function normalize(out, a) {
  801. let magnitude = squaredLength(a);
  802. if (magnitude > 0) {
  803. magnitude = Math.sqrt(magnitude);
  804.  
  805. let a0 = a[0] / magnitude;
  806. let a1 = a[1] / magnitude;
  807. let a2 = a[2] / magnitude;
  808. let a3 = a[3] / magnitude;
  809.  
  810. let b0 = a[4];
  811. let b1 = a[5];
  812. let b2 = a[6];
  813. let b3 = a[7];
  814.  
  815. let a_dot_b = a0 * b0 + a1 * b1 + a2 * b2 + a3 * b3;
  816.  
  817. out[0] = a0;
  818. out[1] = a1;
  819. out[2] = a2;
  820. out[3] = a3;
  821.  
  822. out[4] = (b0 - a0 * a_dot_b) / magnitude;
  823. out[5] = (b1 - a1 * a_dot_b) / magnitude;
  824. out[6] = (b2 - a2 * a_dot_b) / magnitude;
  825. out[7] = (b3 - a3 * a_dot_b) / magnitude;
  826. }
  827. return out;
  828. }
  829.  
  830. /**
  831. * Returns a string representation of a dual quatenion
  832. *
  833. * @param {ReadonlyQuat2} a dual quaternion to represent as a string
  834. * @returns {String} string representation of the dual quat
  835. */
  836. export function str(a) {
  837. return (
  838. "quat2(" +
  839. a[0] +
  840. ", " +
  841. a[1] +
  842. ", " +
  843. a[2] +
  844. ", " +
  845. a[3] +
  846. ", " +
  847. a[4] +
  848. ", " +
  849. a[5] +
  850. ", " +
  851. a[6] +
  852. ", " +
  853. a[7] +
  854. ")"
  855. );
  856. }
  857.  
  858. /**
  859. * Returns whether or not the dual quaternions have exactly the same elements in the same position (when compared with ===)
  860. *
  861. * @param {ReadonlyQuat2} a the first dual quaternion.
  862. * @param {ReadonlyQuat2} b the second dual quaternion.
  863. * @returns {Boolean} true if the dual quaternions are equal, false otherwise.
  864. */
  865. export function exactEquals(a, b) {
  866. return (
  867. a[0] === b[0] &&
  868. a[1] === b[1] &&
  869. a[2] === b[2] &&
  870. a[3] === b[3] &&
  871. a[4] === b[4] &&
  872. a[5] === b[5] &&
  873. a[6] === b[6] &&
  874. a[7] === b[7]
  875. );
  876. }
  877.  
  878. /**
  879. * Returns whether or not the dual quaternions have approximately the same elements in the same position.
  880. *
  881. * @param {ReadonlyQuat2} a the first dual quat.
  882. * @param {ReadonlyQuat2} b the second dual quat.
  883. * @returns {Boolean} true if the dual quats are equal, false otherwise.
  884. */
  885. export function equals(a, b) {
  886. let a0 = a[0],
  887. a1 = a[1],
  888. a2 = a[2],
  889. a3 = a[3],
  890. a4 = a[4],
  891. a5 = a[5],
  892. a6 = a[6],
  893. a7 = a[7];
  894. let b0 = b[0],
  895. b1 = b[1],
  896. b2 = b[2],
  897. b3 = b[3],
  898. b4 = b[4],
  899. b5 = b[5],
  900. b6 = b[6],
  901. b7 = b[7];
  902. return (
  903. Math.abs(a0 - b0) <=
  904. glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
  905. Math.abs(a1 - b1) <=
  906. glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
  907. Math.abs(a2 - b2) <=
  908. glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
  909. Math.abs(a3 - b3) <=
  910. glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) &&
  911. Math.abs(a4 - b4) <=
  912. glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) &&
  913. Math.abs(a5 - b5) <=
  914. glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) &&
  915. Math.abs(a6 - b6) <=
  916. glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) &&
  917. Math.abs(a7 - b7) <=
  918. glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7))
  919. );
  920. }