quat2-spec.js 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. import * as quat from "../../src/gl-matrix/quat";
  2. import * as quat2 from "../../src/gl-matrix/quat2";
  3. import * as mat4 from "../../src/gl-matrix/mat4";
  4. describe("quat2", function() {
  5. let out, outVec, quat2A, quat2B, result, resultVec, outQuat;
  6. let vec;
  7. beforeEach(function() {
  8. quat2A = [1, 2, 3, 4, 2, 5, 6, -2];
  9. quat2B = [5, 6, 7, 8, 9, 8, 6, -4];
  10. out = [0, 0, 0, 0, 0, 0, 0, 0];
  11. outVec = [0, 0, 0];
  12. outQuat = [0, 0, 0, 0];
  13. vec = [1, 1, -1];
  14. });
  15. describe("translate", function() {
  16. let matrixA = mat4.create(), matOut = mat4.create(), quatOut = quat2.create();
  17. beforeEach(function() {
  18. //quat2A only seems to work when created using this function?
  19. quat2B = quat2.fromRotationTranslation(quat2A, [1,2,3,4], [-5, 4, 10]);
  20. quat2.normalize(quat2A, quat2A);
  21. mat4.fromQuat2(matrixA, quat2A);
  22. });
  23. describe("with a separate output quaternion", function() {
  24. beforeEach(function() {
  25. result = quat2.translate(out, quat2A, vec);
  26. //Same thing with a matrix
  27. mat4.translate(matOut, matrixA, vec);
  28. quat2.fromMat4(quatOut, matOut);
  29. });
  30. it("should place values into out", function() { expect(out).toBeEqualishQuat2(quatOut); });
  31. it("should return out", function() { expect(result).toBe(out); });
  32. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2(quat2B); });
  33. it("should not modify vec", function() { expect(vec).toBeEqualish([1,1,-1]); });
  34. });
  35. describe("when quat2A is the output quaternion", function() {
  36. beforeEach(function() {
  37. result = quat2.translate(quat2A, quat2A, vec);
  38. //Same thing with a matrix
  39. mat4.translate(matOut, matrixA, vec);
  40. quat2.fromMat4(quatOut, matOut);
  41. });
  42. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2(quatOut); });
  43. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  44. });
  45. });
  46. describe("rotateAroundAxis", function() {
  47. let matrixA = mat4.create(), matOut = mat4.create(), ax = [1,4,2];
  48. beforeEach(function() {
  49. //quat2A only seems to work when created using this function?
  50. quat2.fromRotationTranslation(quat2A, [1,2,3,4], [-5, 4, 10]);
  51. quat2.normalize(quat2A, quat2A);
  52. mat4.fromQuat2(matrixA, quat2A);
  53. });
  54. describe("with a separate output quaternion", function() {
  55. beforeEach(function() {
  56. result = quat2.rotateAroundAxis(out, quat2A, ax, 5);
  57. //Same thing with a matrix
  58. mat4.rotate(matOut, matrixA, 5, ax);
  59. quat2.fromMat4(quat2B, matOut);
  60. });
  61. it("should place values into out", function() { expect(out).toBeEqualishQuat2(quat2B); });
  62. it("should return out", function() { expect(result).toBe(out); });
  63. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2(
  64. [0.18257418583505536, 0.3651483716701107, 0.5477225575051661, 0.7302967433402214,
  65. -2.556038601690775, 3.742770809618635, 2.37346441585572, -3.0124740662784135]
  66. ); });
  67. it("should not modify ax", function() { expect(ax).toBeEqualish([1, 4, 2]); });
  68. });
  69. describe("when quat2A is the output quaternion", function() {
  70. beforeEach(function() {
  71. result = quat2.rotateAroundAxis(quat2A, quat2A, ax, 5);
  72. //Same thing with a matrix
  73. mat4.rotate(matOut, matrixA, 5, ax);
  74. quat2.fromMat4(quat2B, matOut);
  75. });
  76. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2(quat2B); });
  77. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  78. it("should not modify ax", function() { expect(ax).toBeEqualish([1, 4, 2]); });
  79. });
  80. });
  81. describe("rotateByQuatAppend", function() {
  82. let correctResult = quat2.create();
  83. let rotationQuat = quat2.create();
  84. beforeEach(function() {
  85. rotationQuat[0] = 2;
  86. rotationQuat[1] = 5;
  87. rotationQuat[2] = 2;
  88. rotationQuat[3] = -10;
  89. quat2.multiply(correctResult, quat2A, rotationQuat);
  90. })
  91. describe("with a separate output quaternion", function() {
  92. beforeEach(function() {
  93. result = quat2.rotateByQuatAppend(out, quat2A, [2, 5, 2, -10]);
  94. });
  95. it("should place values into out", function() { expect(out).toBeEqualishQuat2(correctResult); });
  96. it("should return out", function() { expect(result).toBe(out); });
  97. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  98. it("should not modify the rotation quaternion", function() { expect(rotationQuat).toBeEqualishQuat2([2,5,2,-10,0,0,0,0]); });
  99. });
  100. describe("when quat2A is the output quaternion", function() {
  101. beforeEach(function() { result = quat2.rotateByQuatAppend(quat2A, quat2A, [2, 5, 2, -10]); });
  102. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2(correctResult); });
  103. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  104. it("should not modify the rotation quaternion", function() { expect(rotationQuat).toBeEqualishQuat2([2,5,2,-10,0,0,0,0]); });
  105. });
  106. });
  107. describe("rotateByQuatPrepend", function() {
  108. let correctResult = quat2.create();
  109. let rotationQuat = quat2.create();
  110. beforeEach(function() {
  111. rotationQuat[0] = 2;
  112. rotationQuat[1] = 5;
  113. rotationQuat[2] = 2;
  114. rotationQuat[3] = -10;
  115. quat2.multiply(correctResult, rotationQuat, quat2A);
  116. })
  117. describe("with a separate output quaternion", function() {
  118. beforeEach(function() {
  119. result = quat2.rotateByQuatPrepend(out, quat2.getReal(outQuat, rotationQuat), quat2A);
  120. });
  121. it("should place values into out", function() { expect(out).toBeEqualishQuat2(correctResult); });
  122. it("should return out", function() { expect(result).toBe(out); });
  123. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  124. it("should not modify the rotation quaternion", function() { expect(rotationQuat).toBeEqualishQuat2([2,5,2,-10,0,0,0,0]); });
  125. });
  126. describe("when quat2A is the output quaternion", function() {
  127. beforeEach(function() { result = quat2.rotateByQuatPrepend(quat2A, quat2.getReal(outQuat, rotationQuat), quat2A); });
  128. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2(correctResult); });
  129. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  130. it("should not modify the rotation quaternion", function() { expect(rotationQuat).toBeEqualishQuat2([2,5,2,-10,0,0,0,0]); });
  131. });
  132. });
  133. describe("rotateX", function() {
  134. let matrixA = mat4.create(), matOut = mat4.create(), quatOut = quat2.create();
  135. beforeEach(function() {
  136. //quat2A only seems to work when created using this function?
  137. quat2B = quat2.fromRotationTranslation(quat2A, [1,2,3,4], [-5, 4, 10]);
  138. quat2.normalize(quat2A, quat2A);
  139. mat4.fromQuat2(matrixA, quat2A);
  140. });
  141. describe("with a separate output quaternion", function() {
  142. beforeEach(function() {
  143. result = quat2.rotateX(out, quat2A, 5);
  144. //Same thing with a matrix
  145. mat4.rotateX(matOut, matrixA, 5);
  146. quat2.fromMat4(quatOut, matOut);
  147. });
  148. it("should place values into out", function() { expect(out).toBeEqualishQuat2(quatOut); });
  149. it("should return out", function() { expect(result).toBe(out); });
  150. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2(quat2B); });
  151. });
  152. describe("when quat2A is the output quaternion", function() {
  153. beforeEach(function() {
  154. result = quat2.rotateX(quat2A, quat2A, 5);
  155. //Same thing with a matrix
  156. mat4.rotateX(matOut, matrixA, 5);
  157. quat2.fromMat4(quatOut, matOut);
  158. });
  159. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2(quatOut); });
  160. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  161. });
  162. });
  163. describe("rotateY", function() {
  164. let matrixA = mat4.create(), matOut = mat4.create(), quatOut = quat2.create();
  165. beforeEach(function() {
  166. //quat2A only seems to work when created using this function?
  167. quat2B = quat2.fromRotationTranslation(quat2A, [1,2,3,4], [5, 4, -10]);
  168. quat2.normalize(quat2A, quat2A);
  169. mat4.fromQuat2(matrixA, quat2A);
  170. });
  171. describe("with a separate output quaternion", function() {
  172. beforeEach(function() {
  173. result = quat2.rotateY(out, quat2A, -2);
  174. //Same thing with a matrix
  175. mat4.rotateY(matOut, matrixA, -2);
  176. quat2.fromMat4(quatOut, matOut);
  177. });
  178. it("should place values into out", function() { expect(out).toBeEqualishQuat2(quatOut); });
  179. it("should return out", function() { expect(result).toBe(out); });
  180. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2(quat2B); });
  181. });
  182. describe("when quat2A is the output quaternion", function() {
  183. beforeEach(function() {
  184. result = quat2.rotateY(quat2A, quat2A, -2);
  185. //Same thing with a matrix
  186. mat4.rotateY(matOut, matrixA, -2);
  187. quat2.fromMat4(quatOut, matOut);
  188. });
  189. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2(quatOut); });
  190. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  191. });
  192. });
  193. describe("rotateZ", function() {
  194. let matrixA = mat4.create(), matOut = mat4.create(), quatOut = quat2.create();
  195. beforeEach(function() {
  196. //quat2A only seems to work when created using this function?
  197. quat2B = quat2.fromRotationTranslation(quat2A, [1,0,3,-4], [0, -4, -10]);
  198. quat2.normalize(quat2A, quat2A);
  199. mat4.fromQuat2(matrixA, quat2A);
  200. });
  201. describe("with a separate output quaternion", function() {
  202. beforeEach(function() {
  203. result = quat2.rotateZ(out, quat2A, 1);
  204. //Same thing with a matrix
  205. mat4.rotateZ(matOut, matrixA, 1);
  206. quat2.fromMat4(quatOut, matOut);
  207. });
  208. it("should place values into out", function() { expect(out).toBeEqualishQuat2(quatOut); });
  209. it("should return out", function() { expect(result).toBe(out); });
  210. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2(quat2B); });
  211. });
  212. describe("when quat2A is the output quaternion", function() {
  213. beforeEach(function() {
  214. result = quat2.rotateZ(quat2A, quat2A, 1);
  215. //Same thing with a matrix
  216. mat4.rotateZ(matOut, matrixA, 1);
  217. quat2.fromMat4(quatOut, matOut);
  218. });
  219. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2(quatOut); });
  220. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  221. });
  222. });
  223. describe("from/toMat4", function() {
  224. let matRes = mat4.create(), matOut = mat4.create();
  225. describe("quat to matrix and back", function() {
  226. beforeEach(function() {
  227. //only seems to work when created with this function
  228. quat2.fromRotationTranslation(quat2A, [1,2,3,4], [1,-5,3]);
  229. matRes = mat4.fromQuat2(matOut, quat2A);
  230. result = quat2.fromMat4(out, matRes);
  231. });
  232. it("should return out", function() { expect(result).toBe(out); });
  233. it("should return matOut", function() { expect(matRes).toBe(matOut); });
  234. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, -8.5, -10, 9.5, 0 ]); });
  235. it("should be equal to the starting dual quat", function() {
  236. expect(quat2A[0]).toBeEqualish(result[0]);
  237. });
  238. it("should be equal to the starting dual quat", function() {
  239. expect(quat2A[1]).toBeEqualish(result[1]);
  240. });
  241. });
  242. });
  243. describe("create", function() {
  244. beforeEach(function() { result = quat2.create(); });
  245. it("should return 2 4 element arrays initialized to an identity dual quaternion", function() { expect(result).toBeEqualishQuat2([0, 0, 0, 1, 0, 0, 0, 0]); });
  246. });
  247. describe("clone", function() {
  248. beforeEach(function() { result = quat2.clone(quat2A); });
  249. it("should return 2 4 element arrays initialized to the values in quat2A", function() { expect(result).toBeEqualishQuat2(quat2A); });
  250. });
  251. describe("fromValues", function() {
  252. beforeEach(function() { result = quat2.fromValues(1, 2, 3, 4, 5, 7, 8, -2); });
  253. it("should return 2 4 element arrays initialized to the values passedd to the values passed", function() {
  254. expect(result).toBeEqualishQuat2([1, 2, 3, 4, 5, 7, 8, -2]);
  255. });
  256. });
  257. describe("copy", function() {
  258. beforeEach(function() { result = quat2.copy(out, quat2A); });
  259. it("should place values into out", function() { expect(out).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  260. it("should return out", function() { expect(result).toBe(out); });
  261. });
  262. describe("set", function() {
  263. beforeEach(function() { result = quat2.set(out, 1, 2, 3, 4, 2, 5, 6, -2); });
  264. it("should place values into out", function() { expect(out).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  265. it("should return out", function() { expect(result).toBe(out); });
  266. });
  267. describe("identity", function() {
  268. beforeEach(function() { result = quat2.identity(out); });
  269. it("should place values into out", function() { expect(result).toBeEqualishQuat2([0, 0, 0, 1, 0, 0, 0, 0]); });
  270. it("should return out", function() { expect(result).toBe(out); });
  271. });
  272. describe("add", function() {
  273. describe("with a separate output dual quaternion", function() {
  274. beforeEach(function() { result = quat2.add(out, quat2A, quat2B); });
  275. it("should place values into out", function() { expect(out).toBeEqualishQuat2([6, 8, 10, 12, 11, 13, 12, -6]); });
  276. it("should return out", function() { expect(result).toBe(out); });
  277. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  278. it("should not modify quat2B", function() { expect(quat2B).toBeEqualishQuat2([5, 6, 7, 8, 9, 8, 6, -4]); });
  279. });
  280. describe("when quat2A is the output dual quaternion", function() {
  281. beforeEach(function() { result = quat2.add(quat2A, quat2A, quat2B); });
  282. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2([6, 8, 10, 12, 11, 13, 12, -6]); });
  283. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  284. it("should not modify quat2B", function() { expect(quat2B).toBeEqualishQuat2([5, 6, 7, 8, 9, 8, 6, -4])});
  285. });
  286. describe("when quat2B is the output dual quaternion", function() {
  287. beforeEach(function() { result = quat2.add(quat2B, quat2A, quat2B); });
  288. it("should place values into quat2B", function() { expect(quat2B).toBeEqualishQuat2([6, 8, 10, 12, 11, 13, 12, -6]); });
  289. it("should return quat2B", function() { expect(result).toBe(quat2B); });
  290. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  291. });
  292. });
  293. describe("multiply", function() {
  294. it("should have an alias called 'mul'", function() { expect(quat2.mul).toEqual(quat2.multiply); });
  295. describe("with a separate output quaternion", function() {
  296. beforeEach(function() { result = quat2.multiply(out, quat2A, quat2B); });
  297. it("should place values into out", function() { expect(out).toBeEqualishQuat2([24, 48, 48, -6, 25, 89, 23, -157 ]); });
  298. it("should return out", function() { expect(result).toBe(out); });
  299. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  300. it("should not modify quat2B", function() { expect(quat2B).toBeEqualishQuat2([5, 6, 7, 8, 9, 8, 6, -4]); });
  301. });
  302. describe("when quat2A is the output quaternion", function() {
  303. beforeEach(function() { result = quat2.multiply(quat2A, quat2A, quat2B); });
  304. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2([24, 48, 48, -6, 25, 89, 23, -157 ]); });
  305. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  306. it("should not modify quat2B", function() { expect(quat2B).toBeEqualishQuat2([5, 6, 7, 8, 9, 8, 6, -4]); });
  307. });
  308. describe("when quat2B is the output quaternion", function() {
  309. beforeEach(function() { result = quat2.multiply(quat2B, quat2A, quat2B); });
  310. it("should place values into quat2B", function() { expect(quat2B).toBeEqualishQuat2([24, 48, 48, -6, 25, 89, 23, -157 ]); });
  311. it("should return quat2B", function() { expect(result).toBe(quat2B); });
  312. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  313. });
  314. describe("same as matrix multiplication", function() {
  315. let matrixA = mat4.create(), matrixB = mat4.create();
  316. let matOut = mat4.create(), quatOut = quat2.create();
  317. beforeEach(function() {
  318. //quat2A and quat2B only seem to work when created using this function?
  319. quat2.fromRotationTranslation(quat2A, [1,2,3,4], [-5, 4, 10]);
  320. quat2.normalize(quat2A, quat2A);
  321. mat4.fromQuat2(matrixA, quat2A);
  322. quat2.fromRotationTranslation(quat2B, [5, 6, 7, 8], [9, 8, 6]);
  323. quat2.normalize(quat2B, quat2B);
  324. mat4.fromQuat2(matrixB, quat2B);
  325. });
  326. it("the matrices should be equal to the dual quaternions", function() {
  327. let testQuat = quat2.create();
  328. quat2.fromMat4(testQuat, matrixA);
  329. expect(testQuat).toBeEqualishQuat2(quat2A);
  330. quat2.fromMat4(testQuat, matrixB);
  331. expect(testQuat).toBeEqualishQuat2(quat2B);
  332. });
  333. it("should be equal to the matrix multiplication", function() {
  334. quat2.multiply(out, quat2A, quat2B);
  335. mat4.mul(matOut, matrixA, matrixB);
  336. quat2.fromMat4(quatOut, matOut);
  337. expect(out).toBeEqualishQuat2(quatOut);
  338. });
  339. });
  340. });
  341. describe("scale", function() {
  342. describe("with a separate output dual quaternion", function() {
  343. beforeEach(function() { result = quat2.scale(out, quat2A, 2); });
  344. it("should place values into out", function() { expect(out).toBeEqualishQuat2([2, 4, 6, 8, 4, 10, 12, -4]); });
  345. it("should return out", function() { expect(result).toBe(out); });
  346. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  347. });
  348. describe("when quat2A is the output dual quaternion", function() {
  349. beforeEach(function() { result = quat2.scale(quat2A, quat2A, 2); });
  350. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2([2, 4, 6, 8, 4, 10, 12, -4]); });
  351. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  352. });
  353. });
  354. describe("length", function() {
  355. it("should have an alias called 'len'", function() { expect(quat2.len).toEqual(quat2.length); });
  356. beforeEach(function() { result = quat2.length(quat2A); });
  357. it("should return the length", function() { expect(result).toBeEqualish(5.477225); });
  358. });
  359. describe("squaredLength", function() {
  360. it("should have an alias called 'sqrLen'", function() { expect(quat2.sqrLen).toEqual(quat2.squaredLength); });
  361. beforeEach(function() { result = quat2.squaredLength(quat2A); });
  362. it("should return the squared length", function() { expect(result).toEqual(30); });
  363. });
  364. describe("fromRotation", function() {
  365. beforeEach(function() { result = quat2.fromRotation(out, [1, 2, 3, 4]); });
  366. it("should place values into out", function() { expect(out).toBeEqualishQuat2([1, 2, 3, 4, 0, 0, 0, 0]); });
  367. it("should return out", function() { expect(result).toBe(out); });
  368. it("should not modify the quaternion", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  369. });
  370. describe("fromTranslation", function(){
  371. beforeEach(function() { vec = [1, 2, 3]; result = quat2.fromTranslation(out, vec); });
  372. it("should place values into out", function() { expect(out).toBeEqualishQuat2([0, 0, 0, 1, 0.5, 1, 1.5, 0]); });
  373. it("should return out", function() { expect(result).toBe(out); });
  374. it("should not modify the vector", function() { expect(vec).toBeEqualish([1, 2, 3]); });
  375. });
  376. describe("fromRotationTranslation", function() {
  377. beforeEach(function() {
  378. vec = [1, 2, 3];
  379. result = quat2.fromRotationTranslation(out, [1, 2, 3, 4], vec);
  380. });
  381. it("should place values into out", function() { expect(out).toBeEqualishQuat2([1, 2, 3, 4, 2, 4, 6, -7]); });
  382. it("should return out", function() { expect(result).toBe(out); });
  383. it("should not modify the quaternion", function() { expect(quat2.getReal(outQuat, quat2A)).toBeEqualish([1, 2, 3, 4]); });
  384. it("should not modify the vector", function() { expect(vec).toBeEqualish([1, 2, 3]); });
  385. it("should have a translation that can be retrieved with getTranslation", function() {
  386. let t = [0, 0, 0];
  387. quat2.normalize(out, out);
  388. quat2.getTranslation(t, out);
  389. expect(t).toBeEqualish([1, 2, 3]);
  390. });
  391. });
  392. describe("fromRotationTranslationValues", function() {
  393. beforeEach(function() { result = quat2.fromRotationTranslationValues(1,2,3,4, 1,2,3); });
  394. it("should return the correct result", function() { expect(result).toBeEqualishQuat2([1, 2, 3, 4, 2, 4, 6, -7]); });
  395. it("should have a translation that can be retrieved with getTranslation", function() {
  396. let t = [0, 0, 0];
  397. quat2.normalize(result, result);
  398. quat2.getTranslation(t, result);
  399. expect(t).toBeEqualish([1, 2, 3]);
  400. });
  401. });
  402. describe("getTranslation", function() {
  403. describe("without a real part", function() {
  404. beforeEach(function() {
  405. quat2.fromTranslation(out, [1,2,3]);
  406. resultVec = quat2.getTranslation(outVec, out);
  407. });
  408. describe("not normalized", function() {
  409. it("should return the same translation value", function() { expect(outVec).toBeEqualish([1, 2, 3]); });
  410. it("should return out", function() { expect(outVec).toBe(resultVec); });
  411. });
  412. describe("normalized", function() {
  413. it("should return the same translation value", function() {
  414. quat2.normalize(outVec, outVec);
  415. expect(outVec).toBeEqualish([1, 2, 3]);
  416. });
  417. });
  418. });
  419. describe("with a real part", function() {
  420. beforeEach(function() {
  421. quat2.fromRotationTranslation(out, [2, 4, 6, 2], [1, 2, 3]);
  422. resultVec = quat2.getTranslation(outVec, out);
  423. });
  424. describe("not normalized", function() {
  425. it("should not return the same translation value", function() { expect(outVec).not.toBeEqualish([1, 2, 3]); });
  426. it("should return out", function() { expect(outVec).toBe(resultVec); });
  427. });
  428. describe("normalized", function() {
  429. it("should return the same translation value", function() {
  430. quat2.normalize(out, out);
  431. quat2.getTranslation(outVec, out);
  432. expect(outVec).toBeEqualish([1, 2, 3]);
  433. });
  434. });
  435. });
  436. });
  437. describe("normalize", function() {
  438. describe("when it is normalizing quat2A", function() {
  439. beforeEach(function() {
  440. quat2A = [1, 2, 3, 4, 2, 5, 6, -2];
  441. quat2.normalize(out, quat2A);
  442. });
  443. it("both parts should have been normalized", function() { expect(out).toBeEqualishQuat2([1/5.4772255, 2/5.4772255, 3/5.4772255, 4/5.4772255, 0.231260, 0.6450954, 0.693781,-0.9006993]); });
  444. });
  445. beforeEach(function() { quat2A = [5, 0, 0, 0, 0, 0, 0, 0]; });
  446. describe("with a separate output quaternion", function() {
  447. beforeEach(function() { result = quat2.normalize(out, quat2A); });
  448. it("should place values into out", function() { expect(out).toBeEqualishQuat2([1, 0, 0, 0, 0, 0, 0, 0]); });
  449. it("should return out", function() { expect(result).toBe(out); });
  450. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([5, 0, 0, 0, 0, 0, 0, 0]); });
  451. });
  452. describe("when quat2A is the output quaternion", function() {
  453. beforeEach(function() { result = quat2.normalize(quat2A, quat2A); });
  454. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 0, 0, 0, 0, 0, 0, 0]); });
  455. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  456. });
  457. describe("when it contains a translation", function() {
  458. beforeEach(function() {
  459. quat2.set(out, 5, 0, 0, 0, 1, 2, 3, 5);
  460. quat2.normalize(out, out);
  461. });
  462. it("both parts should have been normalized", function() { expect(out).toBeEqualishQuat2([1, 0, 0, 0, 0, 0.4, 0.6, 1]); });
  463. });
  464. });
  465. describe("lerp", function() {
  466. describe("with a separate output quaternion", function() {
  467. beforeEach(function() { result = quat2.lerp(out, quat2A, quat2B, 0.7); });
  468. it("should place values into out", function() { expect(out).toBeEqualishQuat2([3.8, 4.8, 5.8, 6.8, 6.9, 7.1, 6.0, -3.4]); });
  469. it("should return out", function() { expect(result).toBe(out); });
  470. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  471. it("should not modify quat2B", function() { expect(quat2B).toBeEqualishQuat2([5, 6, 7, 8, 9, 8, 6, -4]); });
  472. });
  473. describe("when quat2A is the output quaternion", function() {
  474. beforeEach(function() { result = quat2.lerp(quat2A, quat2A, quat2B, 0.5); });
  475. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2([3, 4, 5, 6,5.5, 6.5, 6, -3]); });
  476. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  477. it("should not modify quat2B", function() { expect(quat2B).toBeEqualishQuat2([5, 6, 7, 8, 9, 8, 6, -4]); });
  478. });
  479. describe("when quat2B is the output quaternion", function() {
  480. beforeEach(function() { result = quat2.lerp(quat2B, quat2A, quat2B, 0.5); });
  481. it("should place values into quat2B", function() { expect(quat2B).toBeEqualishQuat2([3, 4, 5, 6,5.5, 6.5, 6, -3]); });
  482. it("should return quat2B", function() { expect(result).toBe(quat2B); });
  483. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  484. });
  485. describe("shortest path", function() {
  486. beforeEach(function() { result = quat2.lerp(out, [1, 2, 3, -4, 2, 5, 6, -2], [5, -6, 7, 8, 9, 8, 6, -4], 0.4); });
  487. it("should pick the shorter path", function() { expect(out).toBeEqualishQuat2([ -1.4, 3.6, -1, -5.6, -2.4, -0.2, 1.2, 0.4 ]); });
  488. });
  489. });
  490. describe("dot", function() {
  491. describe("with a separate output dual quaternion", function() {
  492. beforeEach(function() { result = quat2.dot(quat2A, quat2B); });
  493. it("should return the dot product", function() { expect(result).toBeEqualish(70); });
  494. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  495. it("should not modify quat2B", function() { expect(quat2B).toBeEqualishQuat2([5, 6, 7, 8, 9, 8, 6, -4]); });
  496. });
  497. });
  498. describe("invert", function() {
  499. describe("with a separate output dual quaternion", function() {
  500. beforeEach(function() { result = quat2.invert(out, quat2A); });
  501. it("should place values into out", function() { expect(out).toBeEqualishQuat2([-0.0333333333, -0.06666666666, -0.1, 0.13333333333, -2/30, -5/30, -6/30, -2/30]); });
  502. it("should return out", function() { expect(result).toBe(out); });
  503. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  504. it("the real part should be equal to a inverted quaternion", function() {
  505. quat.invert(outQuat, [1, 2, 3, 4]);
  506. expect(quat2.getReal(outQuat, out)).toBeEqualish(outQuat);
  507. });
  508. });
  509. describe("when quat2A is the output quaternion", function() {
  510. beforeEach(function() { result = quat2.invert(quat2A, quat2A); });
  511. it("should place values into quat2A", function() { expect(quat2A).toBeEqualish([-0.0333333333, -0.06666666666, -0.1, 0.13333333333, -2/30, -5/30, -6/30, -2/30]); });
  512. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  513. });
  514. });
  515. describe("get real/dual", function() {
  516. describe("get real", function() {
  517. beforeEach(function() { result = quat2.getReal(outQuat, quat2A); });
  518. it("should place values into out", function() { expect(outQuat).toBeEqualish([1, 2, 3, 4]); });
  519. it("should return out", function() { expect(result).toBe(outQuat); });
  520. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  521. });
  522. describe("get dual", function() {
  523. beforeEach(function() { result = quat2.getDual(outQuat, quat2A); });
  524. it("should place values into out", function() { expect(outQuat).toBeEqualish([2, 5, 6, -2]); });
  525. it("should return out", function() { expect(result).toBe(outQuat); });
  526. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  527. });
  528. });
  529. describe("set real/dual", function() {
  530. describe("set real", function() {
  531. beforeEach(function() {
  532. outQuat = [4, 6, 8, -100];
  533. result = quat2.setReal(quat2A, outQuat);
  534. });
  535. it("should place values into out", function() { expect(quat2A).toBeEqualishQuat2([4, 6, 8, -100, 2, 5, 6, -2]); });
  536. it("should return out", function() { expect(result).toBe(quat2A); });
  537. it("should not modify outQuat", function() { expect(outQuat).toBeEqualish([4, 6, 8, -100]); });
  538. });
  539. describe("set dual", function() {
  540. beforeEach(function() {
  541. outQuat = [4.3, 6, 8, -100];
  542. result = quat2.setDual(quat2A, outQuat);
  543. });
  544. it("should place values into out", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 4.3, 6, 8, -100]); });
  545. it("should return out", function() { expect(result).toBe(quat2A); });
  546. it("should not modify outQuat", function() { expect(outQuat).toBeEqualish([4.3, 6, 8, -100]); });
  547. });
  548. });
  549. describe("conjugate", function() {
  550. describe("with a separate output dual quaternion", function() {
  551. beforeEach(function() { result = quat2.conjugate(out, quat2A); });
  552. it("should place values into out", function() { expect(out).toBeEqualishQuat2([-1, -2, -3, 4, -2, -5, -6, -2]); });
  553. it("should return out", function() { expect(result).toBe(out); });
  554. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([1, 2, 3, 4, 2, 5, 6, -2]); });
  555. });
  556. describe("when quat2A is the output dual quaternion", function() {
  557. beforeEach(function() { result = quat2.conjugate(quat2A, quat2A); });
  558. it("should place values into quat2A", function() { expect(quat2A).toBeEqualishQuat2([-1, -2, -3, 4, -2, -5, -6, -2]); });
  559. it("should return quat2A", function() { expect(result).toBe(quat2A); });
  560. });
  561. });
  562. describe("str", function() {
  563. beforeEach(function() { result = quat2.str(quat2A); });
  564. it("should return a string representation of the quaternion", function() { expect(result).toEqual("quat2(1, 2, 3, 4, 2, 5, 6, -2)"); });
  565. });
  566. describe("exactEquals", function() {
  567. let quat2C, r0, r1;
  568. beforeEach(function() {
  569. quat2A = [0, 1, 2, 3, 4, 5, 6, 7];
  570. quat2B = [0, 1, 2, 3, 4, 5, 6, 7];
  571. quat2C = [1, 2, 3, 4, 5, 6, 7, 8];
  572. r0 = quat2.exactEquals(quat2A, quat2B);
  573. r1 = quat2.exactEquals(quat2A, quat2C);
  574. });
  575. it("should return true for identical quaternions", function() { expect(r0).toBe(true); });
  576. it("should return false for different quaternions", function() { expect(r1).toBe(false); });
  577. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([0, 1, 2, 3, 4, 5, 6, 7]); });
  578. it("should not modify quat2B", function() { expect(quat2B).toBeEqualishQuat2([0, 1, 2, 3, 4, 5, 6, 7]); });
  579. });
  580. describe("equals", function() {
  581. let quat2C, quat2D, r0, r1, r2;
  582. beforeEach(function() {
  583. quat2A = [0, 1, 2, 3, 4, 5, 6, 7];
  584. quat2B = [0, 1, 2, 3, 4, 5, 6, 7];
  585. quat2C = [1, 2, 3, 4, 5, 6, 7, 8];
  586. quat2D = [1e-16, 1, 2, 3, 4, 5, 6, 7];
  587. r0 = quat2.equals(quat2A, quat2B);
  588. r1 = quat2.equals(quat2A, quat2C);
  589. r2 = quat2.equals(quat2A, quat2D);
  590. });
  591. it("should return true for identical dual quaternions", function() { expect(r0).toBe(true); });
  592. it("should return false for different dual quaternions", function() { expect(r1).toBe(false); });
  593. it("should return true for close but not identical quaternions", function() { expect(r2).toBe(true); });
  594. it("should not modify quat2A", function() { expect(quat2A).toBeEqualishQuat2([0, 1, 2, 3, 4, 5, 6, 7]); });
  595. it("should not modify quat2B", function() { expect(quat2B).toBeEqualishQuat2([0, 1, 2, 3, 4, 5, 6, 7]); });
  596. });
  597. });