1/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 2 3Redistribution and use in source and binary forms, with or without modification, 4are permitted provided that the following conditions are met: 5 6 * Redistributions of source code must retain the above copyright notice, this 7 list of conditions and the following disclaimer. 8 * Redistributions in binary form must reproduce the above copyright notice, 9 this list of conditions and the following disclaimer in the documentation 10 and/or other materials provided with the distribution. 11 12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 22 23describe("quat", function() { 24 var out, quatA, quatB, result; 25 26 beforeEach(function() { quatA = [1, 2, 3, 4]; quatB = [5, 6, 7, 8]; out = [0, 0, 0, 0]; }); 27 28 describe("create", function() { 29 beforeEach(function() { result = quat.create(); }); 30 it("should return a 4 element array initialized to an identity quaternion", function() { expect(result).toBeEqualish([0, 0, 0, 1]); }); 31 }); 32 33 describe("clone", function() { 34 beforeEach(function() { result = quat.clone(quatA); }); 35 it("should return a 4 element array initialized to the values in quatA", function() { expect(result).toBeEqualish(quatA); }); 36 }); 37 38 describe("fromValues", function() { 39 beforeEach(function() { result = quat.fromValues(1, 2, 3, 4); }); 40 it("should return a 4 element array initialized to the values passed", function() { expect(result).toBeEqualish([1, 2, 3, 4]); }); 41 }); 42 43 describe("copy", function() { 44 beforeEach(function() { result = quat.copy(out, quatA); }); 45 it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3, 4]); }); 46 it("should return out", function() { expect(result).toBe(out); }); 47 }); 48 49 describe("set", function() { 50 beforeEach(function() { result = quat.set(out, 1, 2, 3, 4); }); 51 it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3, 4]); }); 52 it("should return out", function() { expect(result).toBe(out); }); 53 }); 54 55 describe("identity", function() { 56 beforeEach(function() { result = quat.identity(out); }); 57 it("should place values into out", function() { expect(result).toBeEqualish([0, 0, 0, 1]); }); 58 it("should return out", function() { expect(result).toBe(out); }); 59 }); 60 61 describe("setAxisAngle", function() { 62 beforeEach(function() { result = quat.setAxisAngle(out, [1, 0, 0], Math.PI * 0.5); }); 63 it("should place values into out", function() { expect(result).toBeEqualish([0.707106, 0, 0, 0.707106]); }); 64 it("should return out", function() { expect(result).toBe(out); }); 65 }); 66 67 describe("add", function() { 68 describe("with a separate output quaternion", function() { 69 beforeEach(function() { result = quat.add(out, quatA, quatB); }); 70 71 it("should place values into out", function() { expect(out).toBeEqualish([6, 8, 10, 12]); }); 72 it("should return out", function() { expect(result).toBe(out); }); 73 it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); }); 74 it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); }); 75 }); 76 77 describe("when quatA is the output quaternion", function() { 78 beforeEach(function() { result = quat.add(quatA, quatA, quatB); }); 79 80 it("should place values into quatA", function() { expect(quatA).toBeEqualish([6, 8, 10, 12]); }); 81 it("should return quatA", function() { expect(result).toBe(quatA); }); 82 it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); }); 83 }); 84 85 describe("when quatB is the output quaternion", function() { 86 beforeEach(function() { result = quat.add(quatB, quatA, quatB); }); 87 88 it("should place values into quatB", function() { expect(quatB).toBeEqualish([6, 8, 10, 12]); }); 89 it("should return quatB", function() { expect(result).toBe(quatB); }); 90 it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); }); 91 }); 92 }); 93 94 describe("multiply", function() { 95 it("should have an alias called 'mul'", function() { expect(quat.mul).toEqual(quat.multiply); }); 96 97 describe("with a separate output quaternion", function() { 98 beforeEach(function() { result = quat.multiply(out, quatA, quatB); }); 99 100 it("should place values into out", function() { expect(out).toBeEqualish([24, 48, 48, -6]); }); 101 it("should return out", function() { expect(result).toBe(out); }); 102 it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); }); 103 it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); }); 104 }); 105 106 describe("when quatA is the output quaternion", function() { 107 beforeEach(function() { result = quat.multiply(quatA, quatA, quatB); }); 108 109 it("should place values into quatA", function() { expect(quatA).toBeEqualish([24, 48, 48, -6]); }); 110 it("should return quatA", function() { expect(result).toBe(quatA); }); 111 it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); }); 112 }); 113 114 describe("when quatB is the output quaternion", function() { 115 beforeEach(function() { result = quat.multiply(quatB, quatA, quatB); }); 116 117 it("should place values into quatB", function() { expect(quatB).toBeEqualish([24, 48, 48, -6]); }); 118 it("should return quatB", function() { expect(result).toBe(quatB); }); 119 it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); }); 120 }); 121 }); 122 123 describe("scale", function() { 124 describe("with a separate output quaternion", function() { 125 beforeEach(function() { result = quat.scale(out, quatA, 2); }); 126 127 it("should place values into out", function() { expect(out).toBeEqualish([2, 4, 6, 8]); }); 128 it("should return out", function() { expect(result).toBe(out); }); 129 it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); }); 130 }); 131 132 describe("when quatA is the output quaternion", function() { 133 beforeEach(function() { result = quat.scale(quatA, quatA, 2); }); 134 135 it("should place values into quatA", function() { expect(quatA).toBeEqualish([2, 4, 6, 8]); }); 136 it("should return quatA", function() { expect(result).toBe(quatA); }); 137 }); 138 }); 139 140 describe("length", function() { 141 it("should have an alias called 'len'", function() { expect(quat.len).toEqual(quat.length); }); 142 143 beforeEach(function() { result = quat.length(quatA); }); 144 145 it("should return the length", function() { expect(result).toBeCloseTo(5.477225); }); 146 }); 147 148 describe("squaredLength", function() { 149 it("should have an alias called 'sqrLen'", function() { expect(quat.sqrLen).toEqual(quat.squaredLength); }); 150 151 beforeEach(function() { result = quat.squaredLength(quatA); }); 152 153 it("should return the squared length", function() { expect(result).toEqual(30); }); 154 }); 155 156 describe("normalize", function() { 157 beforeEach(function() { quatA = [5, 0, 0, 0]; }); 158 159 describe("with a separate output quaternion", function() { 160 beforeEach(function() { result = quat.normalize(out, quatA); }); 161 162 it("should place values into out", function() { expect(out).toBeEqualish([1, 0, 0, 0]); }); 163 it("should return out", function() { expect(result).toBe(out); }); 164 it("should not modify quatA", function() { expect(quatA).toBeEqualish([5, 0, 0, 0]); }); 165 }); 166 167 describe("when quatA is the output quaternion", function() { 168 beforeEach(function() { result = quat.normalize(quatA, quatA); }); 169 170 it("should place values into quatA", function() { expect(quatA).toBeEqualish([1, 0, 0, 0]); }); 171 it("should return quatA", function() { expect(result).toBe(quatA); }); 172 }); 173 }); 174 175 describe("lerp", function() { 176 describe("with a separate output quaternion", function() { 177 beforeEach(function() { result = quat.lerp(out, quatA, quatB, 0.5); }); 178 179 it("should place values into out", function() { expect(out).toBeEqualish([3, 4, 5, 6]); }); 180 it("should return out", function() { expect(result).toBe(out); }); 181 it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); }); 182 it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); }); 183 }); 184 185 describe("when quatA is the output quaternion", function() { 186 beforeEach(function() { result = quat.lerp(quatA, quatA, quatB, 0.5); }); 187 188 it("should place values into quatA", function() { expect(quatA).toBeEqualish([3, 4, 5, 6]); }); 189 it("should return quatA", function() { expect(result).toBe(quatA); }); 190 it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); }); 191 }); 192 193 describe("when quatB is the output quaternion", function() { 194 beforeEach(function() { result = quat.lerp(quatB, quatA, quatB, 0.5); }); 195 196 it("should place values into quatB", function() { expect(quatB).toBeEqualish([3, 4, 5, 6]); }); 197 it("should return quatB", function() { expect(result).toBe(quatB); }); 198 it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); }); 199 }); 200 }); 201 202 /*describe("slerp", function() { 203 describe("with a separate output quaternion", function() { 204 beforeEach(function() { result = quat.slerp(out, quatA, quatB, 0.5); }); 205 206 it("should place values into out", function() { expect(out).toBeEqualish([3, 4, 5, 6]); }); 207 it("should return out", function() { expect(result).toBe(out); }); 208 it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); }); 209 it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); }); 210 }); 211 212 describe("when quatA is the output quaternion", function() { 213 beforeEach(function() { result = quat.slerp(quatA, quatA, quatB, 0.5); }); 214 215 it("should place values into quatA", function() { expect(quatA).toBeEqualish([3, 4, 5, 6]); }); 216 it("should return quatA", function() { expect(result).toBe(quatA); }); 217 it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); }); 218 }); 219 220 describe("when quatB is the output quaternion", function() { 221 beforeEach(function() { result = quat.slerp(quatB, quatA, quatB, 0.5); }); 222 223 it("should place values into quatB", function() { expect(quatB).toBeEqualish([3, 4, 5, 6]); }); 224 it("should return quatB", function() { expect(result).toBe(quatB); }); 225 it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); }); 226 }); 227 });*/ 228 229 // TODO: slerp, calcuateW, rotateX, rotateY, rotateZ 230 231 describe("invert", function() { 232 describe("with a separate output quaternion", function() { 233 beforeEach(function() { result = quat.invert(out, quatA); }); 234 235 it("should place values into out", function() { expect(out).toBeEqualish([-0.033333, -0.066666, -0.1, 0.133333]); }); 236 it("should return out", function() { expect(result).toBe(out); }); 237 it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); }); 238 }); 239 240 describe("when quatA is the output quaternion", function() { 241 beforeEach(function() { result = quat.invert(quatA, quatA); }); 242 243 it("should place values into quatA", function() { expect(quatA).toBeEqualish([-0.033333, -0.066666, -0.1, 0.133333]); }); 244 it("should return quatA", function() { expect(result).toBe(quatA); }); 245 }); 246 }); 247 248 describe("conjugate", function() { 249 describe("with a separate output quaternion", function() { 250 beforeEach(function() { result = quat.conjugate(out, quatA); }); 251 252 it("should place values into out", function() { expect(out).toBeEqualish([-1, -2, -3, 4]); }); 253 it("should return out", function() { expect(result).toBe(out); }); 254 it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); }); 255 }); 256 257 describe("when quatA is the output quaternion", function() { 258 beforeEach(function() { result = quat.conjugate(quatA, quatA); }); 259 260 it("should place values into quatA", function() { expect(quatA).toBeEqualish([-1, -2, -3, 4]); }); 261 it("should return quatA", function() { expect(result).toBe(quatA); }); 262 }); 263 }); 264 265 describe("str", function() { 266 beforeEach(function() { result = quat.str(quatA); }); 267 268 it("should return a string representation of the quaternion", function() { expect(result).toEqual("quat(1, 2, 3, 4)"); }); 269 }); 270}); 271