quat-spec.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. import * as mat3 from "../../src/gl-matrix/mat3"
  2. import * as mat4 from "../../src/gl-matrix/mat4"
  3. import * as quat from "../../src/gl-matrix/quat"
  4. import * as vec3 from "../../src/gl-matrix/vec3"
  5. describe("quat", function() {
  6. let out, quatA, quatB, result;
  7. let vec, id, deg90;
  8. beforeEach(function() {
  9. quatA = [1, 2, 3, 4];
  10. quatB = [5, 6, 7, 8];
  11. out = [0, 0, 0, 0];
  12. vec = [1, 1, -1];
  13. id = [0, 0, 0, 1];
  14. deg90 = Math.PI / 2;
  15. });
  16. describe("slerp", function() {
  17. describe("the normal case", function() {
  18. beforeEach(function() {
  19. result = quat.slerp(out, [0, 0, 0, 1], [0, 1, 0, 0], 0.5);
  20. });
  21. it("should return out", function() { expect(result).toBe(out); });
  22. it("should calculate proper quat", function() {
  23. expect(result).toBeEqualish([0, 0.707106, 0, 0.707106]);
  24. });
  25. });
  26. describe("where a == b", function() {
  27. beforeEach(function() {
  28. result = quat.slerp(out, [0, 0, 0, 1], [0, 0, 0, 1], 0.5);
  29. });
  30. it("should return out", function() { expect(result).toBe(out); });
  31. it("should calculate proper quat", function() {
  32. expect(result).toBeEqualish([0, 0, 0, 1]);
  33. });
  34. });
  35. describe("where theta == 180deg", function() {
  36. beforeEach(function() {
  37. quat.rotateX(quatA, [1,0,0,0], Math.PI); // 180 deg
  38. result = quat.slerp(out, [1,0,0,0], quatA, 1);
  39. });
  40. it("should calculate proper quat", function() {
  41. expect(result).toBeEqualish([0,0,0,-1]);
  42. });
  43. });
  44. describe("where a == -b", function() {
  45. beforeEach(function() {
  46. result = quat.slerp(out, [1, 0, 0, 0], [-1, 0, 0, 0], 0.5);
  47. });
  48. it("should return out", function() { expect(result).toBe(out); });
  49. it("should calculate proper quat", function() {
  50. expect(result).toBeEqualish([1, 0, 0, 0]);
  51. });
  52. });
  53. });
  54. describe("rotateX", function() {
  55. beforeEach(function() {
  56. result = quat.rotateX(out, id, deg90);
  57. });
  58. it("should return out", function() { expect(result).toBe(out); });
  59. it("should transform vec accordingly", function() {
  60. vec3.transformQuat(vec, [0,0,-1], out);
  61. expect(vec).toBeEqualish([0, 1, 0]);
  62. });
  63. });
  64. describe("rotateY", function() {
  65. beforeEach(function() {
  66. result = quat.rotateY(out, id, deg90);
  67. });
  68. it("should return out", function() { expect(result).toBe(out); });
  69. it("should transform vec accordingly", function() {
  70. vec3.transformQuat(vec, [0,0,-1], out);
  71. expect(vec).toBeEqualish([-1, 0, 0]);
  72. });
  73. });
  74. describe("rotateZ", function() {
  75. beforeEach(function() {
  76. result = quat.rotateZ(out, id, deg90);
  77. });
  78. it("should return out", function() { expect(result).toBe(out); });
  79. it("should transform vec accordingly", function() {
  80. vec3.transformQuat(vec, [0,1,0], out);
  81. expect(vec).toBeEqualish([-1, 0, 0]);
  82. });
  83. });
  84. describe("fromMat3", function() {
  85. let matr;
  86. describe("legacy", function() {
  87. beforeEach(function() {
  88. matr = [ 1, 0, 0,
  89. 0, 0, -1,
  90. 0, 1, 0 ];
  91. result = quat.fromMat3(out, matr);
  92. });
  93. it("should set dest to the correct value", function() {
  94. expect(result).toBeEqualish([-0.707106, 0, 0, 0.707106]);
  95. });
  96. });
  97. describe("where trace > 0", function() {
  98. beforeEach(function() {
  99. matr = [ 1, 0, 0,
  100. 0, 0, -1,
  101. 0, 1, 0 ];
  102. result = quat.fromMat3(out, matr);
  103. });
  104. it("should return out", function() { expect(result).toBe(out); });
  105. it("should produce the correct transformation", function() {
  106. expect(vec3.transformQuat([], [0,1,0], out)).toBeEqualish([0,0,-1]);
  107. });
  108. });
  109. describe("from a normal matrix looking 'backward'", function() {
  110. beforeEach(function() {
  111. matr = mat3.create();
  112. mat3.transpose(matr, mat3.invert(matr, mat3.fromMat4(matr, mat4.lookAt(mat4.create(), [0, 0, 0], [0, 0, 1], [0, 1, 0]))));
  113. result = quat.fromMat3(out, matr);
  114. });
  115. it("should return out", function() { expect(result).toBe(out); });
  116. it("should produce the same transformation as the given matrix", function() {
  117. expect(vec3.transformQuat([], [3,2,-1], quat.normalize(out, out))).toBeEqualish(vec3.transformMat3([], [3,2,-1], matr));
  118. });
  119. });
  120. describe("from a normal matrix looking 'left' and 'upside down'", function() {
  121. beforeEach(function() {
  122. matr = mat3.create();
  123. mat3.transpose(matr, mat3.invert(matr, mat3.fromMat4(matr, mat4.lookAt(mat4.create(), [0, 0, 0], [-1, 0, 0], [0, -1, 0]))));
  124. result = quat.fromMat3(out, matr);
  125. });
  126. it("should return out", function() { expect(result).toBe(out); });
  127. it("should produce the same transformation as the given matrix", function() {
  128. expect(vec3.transformQuat([], [3,2,-1], quat.normalize(out, out))).toBeEqualish(vec3.transformMat3([], [3,2,-1], matr));
  129. });
  130. });
  131. describe("from a normal matrix looking 'upside down'", function() {
  132. beforeEach(function() {
  133. matr = mat3.create();
  134. mat3.transpose(matr, mat3.invert(matr, mat3.fromMat4(matr, mat4.lookAt(mat4.create(), [0, 0, 0], [0, 0, -1], [0, -1, 0]))));
  135. result = quat.fromMat3(out, matr);
  136. });
  137. it("should return out", function() { expect(result).toBe(out); });
  138. it("should produce the same transformation as the given matrix", function() {
  139. expect(vec3.transformQuat([], [3,2,-1], quat.normalize(out, out))).toBeEqualish(vec3.transformMat3([], [3,2,-1], matr));
  140. });
  141. });
  142. });
  143. describe("fromEuler", function() {
  144. describe("legacy", function() {
  145. beforeEach(function() {
  146. result = quat.fromEuler(out, -90, 0, 0);
  147. });
  148. it("should set dest to the correct value", function() {
  149. expect(result).toBeEqualish([-0.707106, 0, 0, 0.707106]);
  150. });
  151. });
  152. describe("where trace > 0", function() {
  153. beforeEach(function() {
  154. result = quat.fromEuler(out, -90, 0, 0);
  155. });
  156. it("should return out", function() { expect(result).toBe(out); });
  157. it("should produce the correct transformation", function() {
  158. expect(vec3.transformQuat([], [0,1,0], out)).toBeEqualish([0,0,-1]);
  159. });
  160. });
  161. });
  162. describe("setAxes", function() {
  163. let r;
  164. beforeEach(function() { r = vec3.create(); });
  165. describe("looking left", function() {
  166. let view, up, right;
  167. beforeEach(function() {
  168. view = [-1, 0, 0];
  169. up = [ 0, 1, 0];
  170. right= [ 0, 0,-1];
  171. result = quat.setAxes([], view, right, up);
  172. });
  173. it("should transform local view into world left", function() {
  174. r = vec3.transformQuat([], [0,0,-1], result);
  175. expect(r).toBeEqualish([1, 0, 0]);
  176. });
  177. it("should transform local right into world front", function() {
  178. r = vec3.transformQuat([], [1,0,0], result);
  179. expect(r).toBeEqualish([0, 0, 1]);
  180. });
  181. });
  182. describe("given opengl defaults", function() {
  183. let view, up, right;
  184. beforeEach(function() {
  185. view = [0, 0, -1];
  186. up = [0, 1, 0];
  187. right= [1, 0, 0];
  188. result = quat.setAxes(out, view, right, up);
  189. });
  190. it("should return out", function() {
  191. expect(result).toBe(out);
  192. });
  193. it("should produce identity", function() {
  194. expect(out).toBeEqualish([0, 0, 0, 1]);
  195. });
  196. });
  197. describe("legacy example", function() {
  198. let view, up, right;
  199. beforeEach(function() {
  200. right= [1, 0, 0];
  201. up = [0, 0, 1];
  202. view = [0, -1, 0];
  203. result = quat.setAxes(out, view, right, up);
  204. });
  205. xit("should set correct quat4 values", function() {
  206. expect(result).toBeEqualish([0.707106, 0, 0, 0.707106]);
  207. });
  208. });
  209. });
  210. describe("rotationTo", function() {
  211. let r;
  212. beforeEach(function() { r = vec3.create(); });
  213. describe("at right angle", function() {
  214. beforeEach(function() {
  215. result = quat.rotationTo(out, [0, 1, 0], [1, 0, 0]);
  216. });
  217. it("should return out", function() { expect(result).toBe(out); });
  218. it("should calculate proper quaternion", function() {
  219. expect(out).toBeEqualish([0, 0, -0.707106, 0.707106]);
  220. });
  221. });
  222. describe("when vectors are parallel", function() {
  223. beforeEach(function() {
  224. result = quat.rotationTo(out, [0, 1, 0], [0, 1, 0]);
  225. });
  226. it("should return out", function() { expect(result).toBe(out); });
  227. it("multiplying A should produce B", function() {
  228. expect(vec3.transformQuat(r, [0, 1, 0], out)).toBeEqualish([0, 1, 0]);
  229. });
  230. });
  231. describe("when vectors are opposed X", function() {
  232. beforeEach(function() {
  233. result = quat.rotationTo(out, [1, 0, 0], [-1, 0, 0]);
  234. });
  235. it("should return out", function() { expect(result).toBe(out); });
  236. it("multiplying A should produce B", function() {
  237. expect(vec3.transformQuat(r, [1, 0, 0], out)).toBeEqualish([-1, 0, 0]);
  238. });
  239. });
  240. describe("when vectors are opposed Y", function() {
  241. beforeEach(function() {
  242. result = quat.rotationTo(out, [0, 1, 0], [0, -1, 0]);
  243. });
  244. it("should return out", function() { expect(result).toBe(out); });
  245. it("multiplying A should produce B", function() {
  246. expect(vec3.transformQuat(r, [0, 1, 0], out)).toBeEqualish([0, -1, 0]);
  247. });
  248. });
  249. describe("when vectors are opposed Z", function() {
  250. beforeEach(function() {
  251. result = quat.rotationTo(out, [0, 0, 1], [0, 0, -1]);
  252. });
  253. it("should return out", function() { expect(result).toBe(out); });
  254. it("multiplying A should produce B", function() {
  255. expect(vec3.transformQuat(r, [0, 0, 1], out)).toBeEqualish([0, 0, -1]);
  256. });
  257. });
  258. });
  259. describe("create", function() {
  260. beforeEach(function() { result = quat.create(); });
  261. it("should return a 4 element array initialized to an identity quaternion", function() { expect(result).toBeEqualish([0, 0, 0, 1]); });
  262. });
  263. describe("clone", function() {
  264. beforeEach(function() { result = quat.clone(quatA); });
  265. it("should return a 4 element array initialized to the values in quatA", function() { expect(result).toBeEqualish(quatA); });
  266. });
  267. describe("fromValues", function() {
  268. beforeEach(function() { result = quat.fromValues(1, 2, 3, 4); });
  269. it("should return a 4 element array initialized to the values passed", function() { expect(result).toBeEqualish([1, 2, 3, 4]); });
  270. });
  271. describe("copy", function() {
  272. beforeEach(function() { result = quat.copy(out, quatA); });
  273. it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3, 4]); });
  274. it("should return out", function() { expect(result).toBe(out); });
  275. });
  276. describe("set", function() {
  277. beforeEach(function() { result = quat.set(out, 1, 2, 3, 4); });
  278. it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3, 4]); });
  279. it("should return out", function() { expect(result).toBe(out); });
  280. });
  281. describe("identity", function() {
  282. beforeEach(function() { result = quat.identity(out); });
  283. it("should place values into out", function() { expect(result).toBeEqualish([0, 0, 0, 1]); });
  284. it("should return out", function() { expect(result).toBe(out); });
  285. });
  286. describe("setAxisAngle", function() {
  287. beforeEach(function() { result = quat.setAxisAngle(out, [1, 0, 0], Math.PI * 0.5); });
  288. it("should place values into out", function() { expect(result).toBeEqualish([0.707106, 0, 0, 0.707106]); });
  289. it("should return out", function() { expect(result).toBe(out); });
  290. });
  291. describe("getAxisAngle", function() {
  292. describe("for a quaternion representing no rotation", function() {
  293. beforeEach(function() { result = quat.setAxisAngle(out, [0, 1, 0], 0.0); deg90 = quat.getAxisAngle(vec, out); });
  294. it("should return a multiple of 2*PI as the angle component", function() { expect(deg90 % (Math.PI * 2.0)).toBeEqualish(0.0); });
  295. });
  296. describe("for a simple rotation about X axis", function() {
  297. beforeEach(function() { result = quat.setAxisAngle(out, [1, 0, 0], 0.7778); deg90 = quat.getAxisAngle(vec, out); });
  298. it("should return the same provided angle", function() { expect(deg90).toBeEqualish(0.7778); });
  299. it("should return the X axis as the angle", function() { expect(vec).toBeEqualish([1, 0, 0]); });
  300. });
  301. describe("for a simple rotation about Y axis", function() {
  302. beforeEach(function() { result = quat.setAxisAngle(out, [0, 1, 0], 0.879546); deg90 = quat.getAxisAngle(vec, out); });
  303. it("should return the same provided angle", function() { expect(deg90).toBeEqualish(0.879546); });
  304. it("should return the X axis as the angle", function() { expect(vec).toBeEqualish([0, 1, 0]); });
  305. });
  306. describe("for a simple rotation about Z axis", function() {
  307. beforeEach(function() { result = quat.setAxisAngle(out, [0, 0, 1], 0.123456); deg90 = quat.getAxisAngle(vec, out); });
  308. it("should return the same provided angle", function() { expect(deg90).toBeEqualish(0.123456); });
  309. it("should return the X axis as the angle", function() { expect(vec).toBeEqualish([0, 0, 1]); });
  310. });
  311. describe("for a slightly irregular axis and right angle", function() {
  312. beforeEach(function() { result = quat.setAxisAngle(out, [0.707106, 0, 0.707106], Math.PI * 0.5); deg90 = quat.getAxisAngle(vec, out); });
  313. it("should place values into vec", function() { expect(vec).toBeEqualish([0.707106, 0, 0.707106]); });
  314. it("should return a numeric angle", function() { expect(deg90).toBeEqualish(Math.PI * 0.5); });
  315. });
  316. describe("for a very irregular axis and negative input angle", function() {
  317. beforeEach(function() {
  318. quatA = quat.setAxisAngle(quatA, [0.65538555, 0.49153915, 0.57346237], 8.8888);
  319. deg90 = quat.getAxisAngle(vec, quatA);
  320. quatB = quat.setAxisAngle(quatB, vec, deg90);
  321. });
  322. it("should return an angle between 0 and 2*PI", function() { expect(deg90).toBeGreaterThan(0.0); expect(deg90).toBeLessThan(Math.PI * 2.0); });
  323. it("should create the same quaternion from axis and angle extracted", function() { expect(quatA).toBeEqualish(quatB); });
  324. });
  325. });
  326. describe("add", function() {
  327. describe("with a separate output quaternion", function() {
  328. beforeEach(function() { result = quat.add(out, quatA, quatB); });
  329. it("should place values into out", function() { expect(out).toBeEqualish([6, 8, 10, 12]); });
  330. it("should return out", function() { expect(result).toBe(out); });
  331. it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
  332. it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
  333. });
  334. describe("when quatA is the output quaternion", function() {
  335. beforeEach(function() { result = quat.add(quatA, quatA, quatB); });
  336. it("should place values into quatA", function() { expect(quatA).toBeEqualish([6, 8, 10, 12]); });
  337. it("should return quatA", function() { expect(result).toBe(quatA); });
  338. it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
  339. });
  340. describe("when quatB is the output quaternion", function() {
  341. beforeEach(function() { result = quat.add(quatB, quatA, quatB); });
  342. it("should place values into quatB", function() { expect(quatB).toBeEqualish([6, 8, 10, 12]); });
  343. it("should return quatB", function() { expect(result).toBe(quatB); });
  344. it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
  345. });
  346. });
  347. describe("multiply", function() {
  348. it("should have an alias called 'mul'", function() { expect(quat.mul).toEqual(quat.multiply); });
  349. describe("with a separate output quaternion", function() {
  350. beforeEach(function() { result = quat.multiply(out, quatA, quatB); });
  351. it("should place values into out", function() { expect(out).toBeEqualish([24, 48, 48, -6]); });
  352. it("should return out", function() { expect(result).toBe(out); });
  353. it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
  354. it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
  355. });
  356. describe("when quatA is the output quaternion", function() {
  357. beforeEach(function() { result = quat.multiply(quatA, quatA, quatB); });
  358. it("should place values into quatA", function() { expect(quatA).toBeEqualish([24, 48, 48, -6]); });
  359. it("should return quatA", function() { expect(result).toBe(quatA); });
  360. it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
  361. });
  362. describe("when quatB is the output quaternion", function() {
  363. beforeEach(function() { result = quat.multiply(quatB, quatA, quatB); });
  364. it("should place values into quatB", function() { expect(quatB).toBeEqualish([24, 48, 48, -6]); });
  365. it("should return quatB", function() { expect(result).toBe(quatB); });
  366. it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
  367. });
  368. });
  369. describe("scale", function() {
  370. describe("with a separate output quaternion", function() {
  371. beforeEach(function() { result = quat.scale(out, quatA, 2); });
  372. it("should place values into out", function() { expect(out).toBeEqualish([2, 4, 6, 8]); });
  373. it("should return out", function() { expect(result).toBe(out); });
  374. it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
  375. });
  376. describe("when quatA is the output quaternion", function() {
  377. beforeEach(function() { result = quat.scale(quatA, quatA, 2); });
  378. it("should place values into quatA", function() { expect(quatA).toBeEqualish([2, 4, 6, 8]); });
  379. it("should return quatA", function() { expect(result).toBe(quatA); });
  380. });
  381. });
  382. describe("length", function() {
  383. it("should have an alias called 'len'", function() { expect(quat.len).toEqual(quat.length); });
  384. beforeEach(function() { result = quat.len(quatA); });
  385. it("should return the length", function() { expect(result).toBeEqualish(5.477225); });
  386. });
  387. describe("squaredLength", function() {
  388. it("should have an alias called 'sqrLen'", function() { expect(quat.sqrLen).toEqual(quat.squaredLength); });
  389. beforeEach(function() { result = quat.squaredLength(quatA); });
  390. it("should return the squared length", function() { expect(result).toEqual(30); });
  391. });
  392. describe("normalize", function() {
  393. beforeEach(function() { quatA = [5, 0, 0, 0]; });
  394. describe("with a separate output quaternion", function() {
  395. beforeEach(function() { result = quat.normalize(out, quatA); });
  396. it("should place values into out", function() { expect(out).toBeEqualish([1, 0, 0, 0]); });
  397. it("should return out", function() { expect(result).toBe(out); });
  398. it("should not modify quatA", function() { expect(quatA).toBeEqualish([5, 0, 0, 0]); });
  399. });
  400. describe("when quatA is the output quaternion", function() {
  401. beforeEach(function() { result = quat.normalize(quatA, quatA); });
  402. it("should place values into quatA", function() { expect(quatA).toBeEqualish([1, 0, 0, 0]); });
  403. it("should return quatA", function() { expect(result).toBe(quatA); });
  404. });
  405. });
  406. describe("lerp", function() {
  407. describe("with a separate output quaternion", function() {
  408. beforeEach(function() { result = quat.lerp(out, quatA, quatB, 0.5); });
  409. it("should place values into out", function() { expect(out).toBeEqualish([3, 4, 5, 6]); });
  410. it("should return out", function() { expect(result).toBe(out); });
  411. it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
  412. it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
  413. });
  414. describe("when quatA is the output quaternion", function() {
  415. beforeEach(function() { result = quat.lerp(quatA, quatA, quatB, 0.5); });
  416. it("should place values into quatA", function() { expect(quatA).toBeEqualish([3, 4, 5, 6]); });
  417. it("should return quatA", function() { expect(result).toBe(quatA); });
  418. it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
  419. });
  420. describe("when quatB is the output quaternion", function() {
  421. beforeEach(function() { result = quat.lerp(quatB, quatA, quatB, 0.5); });
  422. it("should place values into quatB", function() { expect(quatB).toBeEqualish([3, 4, 5, 6]); });
  423. it("should return quatB", function() { expect(result).toBe(quatB); });
  424. it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
  425. });
  426. });
  427. describe("slerp", function() {
  428. describe("with a separate output quaternion", function() {
  429. beforeEach(function() { result = quat.slerp(out, quatA, quatB, 0.5); });
  430. it("should place values into out", function() { expect(out).toBeEqualish([3, 4, 5, 6]); });
  431. it("should return out", function() { expect(result).toBe(out); });
  432. it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
  433. it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
  434. });
  435. describe("when quatA is the output quaternion", function() {
  436. beforeEach(function() { result = quat.slerp(quatA, quatA, quatB, 0.5); });
  437. it("should place values into quatA", function() { expect(quatA).toBeEqualish([3, 4, 5, 6]); });
  438. it("should return quatA", function() { expect(result).toBe(quatA); });
  439. it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
  440. });
  441. describe("when quatB is the output quaternion", function() {
  442. beforeEach(function() { result = quat.slerp(quatB, quatA, quatB, 0.5); });
  443. it("should place values into quatB", function() { expect(quatB).toBeEqualish([3, 4, 5, 6]); });
  444. it("should return quatB", function() { expect(result).toBe(quatB); });
  445. it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
  446. });
  447. });
  448. describe("random", function() {
  449. beforeEach(function() { result = quat.random(out); });
  450. it("should result in a normalized quaternion", function() {
  451. let copy = quat.clone(out);
  452. expect(quat.normalize(out, out)).toBeEqualish(copy);
  453. });
  454. it("should return out", function() { expect(result).toBe(out); });
  455. });
  456. describe("invert", function() {
  457. describe("with a separate output quaternion", function() {
  458. beforeEach(function() { result = quat.invert(out, quatA); });
  459. it("should place values into out", function() { expect(out).toBeEqualish([-0.033333, -0.066666, -0.1, 0.133333]); });
  460. it("should return out", function() { expect(result).toBe(out); });
  461. it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
  462. });
  463. describe("when quatA is the output quaternion", function() {
  464. beforeEach(function() { result = quat.invert(quatA, quatA); });
  465. it("should place values into quatA", function() { expect(quatA).toBeEqualish([-0.033333, -0.066666, -0.1, 0.133333]); });
  466. it("should return quatA", function() { expect(result).toBe(quatA); });
  467. });
  468. });
  469. describe("conjugate", function() {
  470. describe("with a separate output quaternion", function() {
  471. beforeEach(function() { result = quat.conjugate(out, quatA); });
  472. it("should place values into out", function() { expect(out).toBeEqualish([-1, -2, -3, 4]); });
  473. it("should return out", function() { expect(result).toBe(out); });
  474. it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
  475. });
  476. describe("when quatA is the output quaternion", function() {
  477. beforeEach(function() { result = quat.conjugate(quatA, quatA); });
  478. it("should place values into quatA", function() { expect(quatA).toBeEqualish([-1, -2, -3, 4]); });
  479. it("should return quatA", function() { expect(result).toBe(quatA); });
  480. });
  481. });
  482. describe("str", function() {
  483. beforeEach(function() { result = quat.str(quatA); });
  484. it("should return a string representation of the quaternion", function() { expect(result).toEqual("quat(1, 2, 3, 4)"); });
  485. });
  486. describe("exactEquals", function() {
  487. let quatC, r0, r1;
  488. beforeEach(function() {
  489. quatA = [0, 1, 2, 3];
  490. quatB = [0, 1, 2, 3];
  491. quatC = [1, 2, 3, 4];
  492. r0 = quat.exactEquals(quatA, quatB);
  493. r1 = quat.exactEquals(quatA, quatC);
  494. });
  495. it("should return true for identical quaternions", function() { expect(r0).toBe(true); });
  496. it("should return false for different quaternions", function() { expect(r1).toBe(false); });
  497. it("should not modify quatA", function() { expect(quatA).toBeEqualish([0, 1, 2, 3]); });
  498. it("should not modify quatB", function() { expect(quatB).toBeEqualish([0, 1, 2, 3]); });
  499. });
  500. describe("equals", function() {
  501. let quatC, quatD, r0, r1, r2;
  502. beforeEach(function() {
  503. quatA = [0, 1, 2, 3];
  504. quatB = [0, 1, 2, 3];
  505. quatC = [1, 2, 3, 4];
  506. quatD = [1e-16, 1, 2, 3];
  507. r0 = quat.equals(quatA, quatB);
  508. r1 = quat.equals(quatA, quatC);
  509. r2 = quat.equals(quatA, quatD);
  510. });
  511. it("should return true for identical quaternions", function() { expect(r0).toBe(true); });
  512. it("should return false for different quaternions", function() { expect(r1).toBe(false); });
  513. it("should return true for close but not identical quaternions", function() { expect(r2).toBe(true); });
  514. it("should not modify quatA", function() { expect(quatA).toBeEqualish([0, 1, 2, 3]); });
  515. it("should not modify quatB", function() { expect(quatB).toBeEqualish([0, 1, 2, 3]); });
  516. });
  517. });