OLD | NEW |
(Empty) | |
| 1 /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. |
| 2 |
| 3 Redistribution and use in source and binary forms, with or without modification, |
| 4 are 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 |
| 12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 13 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 14 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 15 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
| 16 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 17 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 18 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| 19 ANY 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 |
| 21 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ |
| 22 |
| 23 /** |
| 24 * @class Quaternion |
| 25 * @name quat |
| 26 */ |
| 27 var quat = {}; |
| 28 |
| 29 /** |
| 30 * Creates a new identity quat |
| 31 * |
| 32 * @returns {quat} a new quaternion |
| 33 */ |
| 34 quat.create = function() { |
| 35 var out = new GLMAT_ARRAY_TYPE(4); |
| 36 out[0] = 0; |
| 37 out[1] = 0; |
| 38 out[2] = 0; |
| 39 out[3] = 1; |
| 40 return out; |
| 41 }; |
| 42 |
| 43 /** |
| 44 * Creates a new quat initialized with values from an existing quaternion |
| 45 * |
| 46 * @param {quat} a quaternion to clone |
| 47 * @returns {quat} a new quaternion |
| 48 * @function |
| 49 */ |
| 50 quat.clone = vec4.clone; |
| 51 |
| 52 /** |
| 53 * Creates a new quat initialized with the given values |
| 54 * |
| 55 * @param {Number} x X component |
| 56 * @param {Number} y Y component |
| 57 * @param {Number} z Z component |
| 58 * @param {Number} w W component |
| 59 * @returns {quat} a new quaternion |
| 60 * @function |
| 61 */ |
| 62 quat.fromValues = vec4.fromValues; |
| 63 |
| 64 /** |
| 65 * Copy the values from one quat to another |
| 66 * |
| 67 * @param {quat} out the receiving quaternion |
| 68 * @param {quat} a the source quaternion |
| 69 * @returns {quat} out |
| 70 * @function |
| 71 */ |
| 72 quat.copy = vec4.copy; |
| 73 |
| 74 /** |
| 75 * Set the components of a quat to the given values |
| 76 * |
| 77 * @param {quat} out the receiving quaternion |
| 78 * @param {Number} x X component |
| 79 * @param {Number} y Y component |
| 80 * @param {Number} z Z component |
| 81 * @param {Number} w W component |
| 82 * @returns {quat} out |
| 83 * @function |
| 84 */ |
| 85 quat.set = vec4.set; |
| 86 |
| 87 /** |
| 88 * Set a quat to the identity quaternion |
| 89 * |
| 90 * @param {quat} out the receiving quaternion |
| 91 * @returns {quat} out |
| 92 */ |
| 93 quat.identity = function(out) { |
| 94 out[0] = 0; |
| 95 out[1] = 0; |
| 96 out[2] = 0; |
| 97 out[3] = 1; |
| 98 return out; |
| 99 }; |
| 100 |
| 101 /** |
| 102 * Sets a quat from the given angle and rotation axis, |
| 103 * then returns it. |
| 104 * |
| 105 * @param {quat} out the receiving quaternion |
| 106 * @param {vec3} axis the axis around which to rotate |
| 107 * @param {Number} rad the angle in radians |
| 108 * @returns {quat} out |
| 109 **/ |
| 110 quat.setAxisAngle = function(out, axis, rad) { |
| 111 rad = rad * 0.5; |
| 112 var s = Math.sin(rad); |
| 113 out[0] = s * axis[0]; |
| 114 out[1] = s * axis[1]; |
| 115 out[2] = s * axis[2]; |
| 116 out[3] = Math.cos(rad); |
| 117 return out; |
| 118 }; |
| 119 |
| 120 /** |
| 121 * Adds two quat's |
| 122 * |
| 123 * @param {quat} out the receiving quaternion |
| 124 * @param {quat} a the first operand |
| 125 * @param {quat} b the second operand |
| 126 * @returns {quat} out |
| 127 * @function |
| 128 */ |
| 129 quat.add = vec4.add; |
| 130 |
| 131 /** |
| 132 * Multiplies two quat's |
| 133 * |
| 134 * @param {quat} out the receiving quaternion |
| 135 * @param {quat} a the first operand |
| 136 * @param {quat} b the second operand |
| 137 * @returns {quat} out |
| 138 */ |
| 139 quat.multiply = function(out, a, b) { |
| 140 var ax = a[0], ay = a[1], az = a[2], aw = a[3], |
| 141 bx = b[0], by = b[1], bz = b[2], bw = b[3]; |
| 142 |
| 143 out[0] = ax * bw + aw * bx + ay * bz - az * by; |
| 144 out[1] = ay * bw + aw * by + az * bx - ax * bz; |
| 145 out[2] = az * bw + aw * bz + ax * by - ay * bx; |
| 146 out[3] = aw * bw - ax * bx - ay * by - az * bz; |
| 147 return out; |
| 148 }; |
| 149 |
| 150 /** |
| 151 * Alias for {@link quat.multiply} |
| 152 * @function |
| 153 */ |
| 154 quat.mul = quat.multiply; |
| 155 |
| 156 /** |
| 157 * Scales a quat by a scalar number |
| 158 * |
| 159 * @param {quat} out the receiving vector |
| 160 * @param {quat} a the vector to scale |
| 161 * @param {Number} b amount to scale the vector by |
| 162 * @returns {quat} out |
| 163 * @function |
| 164 */ |
| 165 quat.scale = vec4.scale; |
| 166 |
| 167 /** |
| 168 * Rotates a quaternion by the given angle around the X axis |
| 169 * |
| 170 * @param {quat} out quat receiving operation result |
| 171 * @param {quat} a quat to rotate |
| 172 * @param {number} rad angle (in radians) to rotate |
| 173 * @returns {quat} out |
| 174 */ |
| 175 quat.rotateX = function (out, a, rad) { |
| 176 rad *= 0.5; |
| 177 |
| 178 var ax = a[0], ay = a[1], az = a[2], aw = a[3], |
| 179 bx = Math.sin(rad), bw = Math.cos(rad); |
| 180 |
| 181 out[0] = ax * bw + aw * bx; |
| 182 out[1] = ay * bw + az * bx; |
| 183 out[2] = az * bw - ay * bx; |
| 184 out[3] = aw * bw - ax * bx; |
| 185 return out; |
| 186 }; |
| 187 |
| 188 /** |
| 189 * Rotates a quaternion by the given angle around the Y axis |
| 190 * |
| 191 * @param {quat} out quat receiving operation result |
| 192 * @param {quat} a quat to rotate |
| 193 * @param {number} rad angle (in radians) to rotate |
| 194 * @returns {quat} out |
| 195 */ |
| 196 quat.rotateY = function (out, a, rad) { |
| 197 rad *= 0.5; |
| 198 |
| 199 var ax = a[0], ay = a[1], az = a[2], aw = a[3], |
| 200 by = Math.sin(rad), bw = Math.cos(rad); |
| 201 |
| 202 out[0] = ax * bw - az * by; |
| 203 out[1] = ay * bw + aw * by; |
| 204 out[2] = az * bw + ax * by; |
| 205 out[3] = aw * bw - ay * by; |
| 206 return out; |
| 207 }; |
| 208 |
| 209 /** |
| 210 * Rotates a quaternion by the given angle around the Z axis |
| 211 * |
| 212 * @param {quat} out quat receiving operation result |
| 213 * @param {quat} a quat to rotate |
| 214 * @param {number} rad angle (in radians) to rotate |
| 215 * @returns {quat} out |
| 216 */ |
| 217 quat.rotateZ = function (out, a, rad) { |
| 218 rad *= 0.5; |
| 219 |
| 220 var ax = a[0], ay = a[1], az = a[2], aw = a[3], |
| 221 bz = Math.sin(rad), bw = Math.cos(rad); |
| 222 |
| 223 out[0] = ax * bw + ay * bz; |
| 224 out[1] = ay * bw - ax * bz; |
| 225 out[2] = az * bw + aw * bz; |
| 226 out[3] = aw * bw - az * bz; |
| 227 return out; |
| 228 }; |
| 229 |
| 230 /** |
| 231 * Calculates the W component of a quat from the X, Y, and Z components. |
| 232 * Assumes that quaternion is 1 unit in length. |
| 233 * Any existing W component will be ignored. |
| 234 * |
| 235 * @param {quat} out the receiving quaternion |
| 236 * @param {quat} a quat to calculate W component of |
| 237 * @returns {quat} out |
| 238 */ |
| 239 quat.calculateW = function (out, a) { |
| 240 var x = a[0], y = a[1], z = a[2]; |
| 241 |
| 242 out[0] = x; |
| 243 out[1] = y; |
| 244 out[2] = z; |
| 245 out[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); |
| 246 return out; |
| 247 }; |
| 248 |
| 249 /** |
| 250 * Calculates the dot product of two quat's |
| 251 * |
| 252 * @param {quat} a the first operand |
| 253 * @param {quat} b the second operand |
| 254 * @returns {Number} dot product of a and b |
| 255 * @function |
| 256 */ |
| 257 quat.dot = vec4.dot; |
| 258 |
| 259 /** |
| 260 * Performs a linear interpolation between two quat's |
| 261 * |
| 262 * @param {quat} out the receiving quaternion |
| 263 * @param {quat} a the first operand |
| 264 * @param {quat} b the second operand |
| 265 * @param {Number} t interpolation amount between the two inputs |
| 266 * @returns {quat} out |
| 267 * @function |
| 268 */ |
| 269 quat.lerp = vec4.lerp; |
| 270 |
| 271 /** |
| 272 * Performs a spherical linear interpolation between two quat |
| 273 * |
| 274 * @param {quat} out the receiving quaternion |
| 275 * @param {quat} a the first operand |
| 276 * @param {quat} b the second operand |
| 277 * @param {Number} t interpolation amount between the two inputs |
| 278 * @returns {quat} out |
| 279 */ |
| 280 quat.slerp = function (out, a, b, t) { |
| 281 var ax = a[0], ay = a[1], az = a[2], aw = a[3], |
| 282 bx = b[0], by = b[1], bz = b[2], bw = b[3]; |
| 283 |
| 284 var cosHalfTheta = ax * bx + ay * by + az * bz + aw * bw, |
| 285 halfTheta, |
| 286 sinHalfTheta, |
| 287 ratioA, |
| 288 ratioB; |
| 289 |
| 290 if (Math.abs(cosHalfTheta) >= 1.0) { |
| 291 if (out !== a) { |
| 292 out[0] = ax; |
| 293 out[1] = ay; |
| 294 out[2] = az; |
| 295 out[3] = aw; |
| 296 } |
| 297 return out; |
| 298 } |
| 299 |
| 300 halfTheta = Math.acos(cosHalfTheta); |
| 301 sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta); |
| 302 |
| 303 if (Math.abs(sinHalfTheta) < 0.001) { |
| 304 out[0] = (ax * 0.5 + bx * 0.5); |
| 305 out[1] = (ay * 0.5 + by * 0.5); |
| 306 out[2] = (az * 0.5 + bz * 0.5); |
| 307 out[3] = (aw * 0.5 + bw * 0.5); |
| 308 return out; |
| 309 } |
| 310 |
| 311 ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta; |
| 312 ratioB = Math.sin(t * halfTheta) / sinHalfTheta; |
| 313 |
| 314 out[0] = (ax * ratioA + bx * ratioB); |
| 315 out[1] = (ay * ratioA + by * ratioB); |
| 316 out[2] = (az * ratioA + bz * ratioB); |
| 317 out[3] = (aw * ratioA + bw * ratioB); |
| 318 |
| 319 return out; |
| 320 }; |
| 321 |
| 322 /** |
| 323 * Calculates the inverse of a quat |
| 324 * |
| 325 * @param {quat} out the receiving quaternion |
| 326 * @param {quat} a quat to calculate inverse of |
| 327 * @returns {quat} out |
| 328 */ |
| 329 quat.invert = function(out, a) { |
| 330 var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], |
| 331 dot = a0*a0 + a1*a1 + a2*a2 + a3*a3, |
| 332 invDot = dot ? 1.0/dot : 0; |
| 333 |
| 334 // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 |
| 335 |
| 336 out[0] = -a0*invDot; |
| 337 out[1] = -a1*invDot; |
| 338 out[2] = -a2*invDot; |
| 339 out[3] = a3*invDot; |
| 340 return out; |
| 341 }; |
| 342 |
| 343 /** |
| 344 * Calculates the conjugate of a quat |
| 345 * If the quaternion is normalized, this function is faster than quat.inverse an
d produces the same result. |
| 346 * |
| 347 * @param {quat} out the receiving quaternion |
| 348 * @param {quat} a quat to calculate conjugate of |
| 349 * @returns {quat} out |
| 350 */ |
| 351 quat.conjugate = function (out, a) { |
| 352 out[0] = -a[0]; |
| 353 out[1] = -a[1]; |
| 354 out[2] = -a[2]; |
| 355 out[3] = a[3]; |
| 356 return out; |
| 357 }; |
| 358 |
| 359 /** |
| 360 * Calculates the length of a quat |
| 361 * |
| 362 * @param {quat} a vector to calculate length of |
| 363 * @returns {Number} length of a |
| 364 * @function |
| 365 */ |
| 366 quat.length = vec4.length; |
| 367 |
| 368 /** |
| 369 * Alias for {@link quat.length} |
| 370 * @function |
| 371 */ |
| 372 quat.len = quat.length; |
| 373 |
| 374 /** |
| 375 * Calculates the squared length of a quat |
| 376 * |
| 377 * @param {quat} a vector to calculate squared length of |
| 378 * @returns {Number} squared length of a |
| 379 * @function |
| 380 */ |
| 381 quat.squaredLength = vec4.squaredLength; |
| 382 |
| 383 /** |
| 384 * Alias for {@link quat.squaredLength} |
| 385 * @function |
| 386 */ |
| 387 quat.sqrLen = quat.squaredLength; |
| 388 |
| 389 /** |
| 390 * Normalize a quat |
| 391 * |
| 392 * @param {quat} out the receiving quaternion |
| 393 * @param {quat} a quaternion to normalize |
| 394 * @returns {quat} out |
| 395 * @function |
| 396 */ |
| 397 quat.normalize = vec4.normalize; |
| 398 |
| 399 /** |
| 400 * Creates a quaternion from the given 3x3 rotation matrix. |
| 401 * |
| 402 * @param {quat} out the receiving quaternion |
| 403 * @param {mat3} m rotation matrix |
| 404 * @returns {quat} out |
| 405 * @function |
| 406 */ |
| 407 quat.fromMat3 = (function() { |
| 408 var s_iNext = [1,2,0]; |
| 409 return function(out, m) { |
| 410 // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes |
| 411 // article "Quaternion Calculus and Fast Animation". |
| 412 var fTrace = m[0] + m[4] + m[8]; |
| 413 var fRoot; |
| 414 |
| 415 if ( fTrace > 0.0 ) { |
| 416 // |w| > 1/2, may as well choose w > 1/2 |
| 417 fRoot = Math.sqrt(fTrace + 1.0); // 2w |
| 418 out[3] = 0.5 * fRoot; |
| 419 fRoot = 0.5/fRoot; // 1/(4w) |
| 420 out[0] = (m[7]-m[5])*fRoot; |
| 421 out[1] = (m[2]-m[6])*fRoot; |
| 422 out[2] = (m[3]-m[1])*fRoot; |
| 423 } else { |
| 424 // |w| <= 1/2 |
| 425 var i = 0; |
| 426 if ( m[4] > m[0] ) |
| 427 i = 1; |
| 428 if ( m[8] > m[i*3+i] ) |
| 429 i = 2; |
| 430 var j = s_iNext[i]; |
| 431 var k = s_iNext[j]; |
| 432 |
| 433 fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0); |
| 434 out[i] = 0.5 * fRoot; |
| 435 fRoot = 0.5 / fRoot; |
| 436 out[3] = (m[k*3+j] - m[j*3+k]) * fRoot; |
| 437 out[j] = (m[j*3+i] + m[i*3+j]) * fRoot; |
| 438 out[k] = (m[k*3+i] + m[i*3+k]) * fRoot; |
| 439 } |
| 440 |
| 441 return out; |
| 442 }; |
| 443 })(); |
| 444 |
| 445 /** |
| 446 * Returns a string representation of a quatenion |
| 447 * |
| 448 * @param {quat} vec vector to represent as a string |
| 449 * @returns {String} string representation of the vector |
| 450 */ |
| 451 quat.str = function (a) { |
| 452 return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; |
| 453 }; |
| 454 |
| 455 if(typeof(exports) !== 'undefined') { |
| 456 exports.quat = quat; |
| 457 } |
OLD | NEW |