1 /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
3 Redistribution and use in source and binary forms, with or without modification,
4 are permitted provided that the following conditions are met:
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.
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. */
30 * Creates a new identity quat
32 * @returns {quat} a new quaternion
34 quat.create = function() {
35 var out = new GLMAT_ARRAY_TYPE(4);
44 * Creates a new quat initialized with values from an existing quaternion
46 * @param {quat} a quaternion to clone
47 * @returns {quat} a new quaternion
50 quat.clone = vec4.clone;
53 * Creates a new quat initialized with the given values
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
62 quat.fromValues = vec4.fromValues;
65 * Copy the values from one quat to another
67 * @param {quat} out the receiving quaternion
68 * @param {quat} a the source quaternion
72 quat.copy = vec4.copy;
75 * Set the components of a quat to the given values
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
88 * Set a quat to the identity quaternion
90 * @param {quat} out the receiving quaternion
93 quat.identity = function(out) {
102 * Sets a quat from the given angle and rotation axis,
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
110 quat.setAxisAngle = function(out, axis, rad) {
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);
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
132 * Multiplies two quat's
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
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];
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;
151 * Alias for {@link quat.multiply}
154 quat.mul = quat.multiply;
157 * Scales a quat by a scalar number
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
165 quat.scale = vec4.scale;
168 * Rotates a quaternion by the given angle around the X axis
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
175 quat.rotateX = function (out, a, rad) {
178 var ax = a[0], ay = a[1], az = a[2], aw = a[3],
179 bx = Math.sin(rad), bw = Math.cos(rad);
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;
189 * Rotates a quaternion by the given angle around the Y axis
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
196 quat.rotateY = function (out, a, rad) {
199 var ax = a[0], ay = a[1], az = a[2], aw = a[3],
200 by = Math.sin(rad), bw = Math.cos(rad);
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;
210 * Rotates a quaternion by the given angle around the Z axis
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
217 quat.rotateZ = function (out, a, rad) {
220 var ax = a[0], ay = a[1], az = a[2], aw = a[3],
221 bz = Math.sin(rad), bw = Math.cos(rad);
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;
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.
235 * @param {quat} out the receiving quaternion
236 * @param {quat} a quat to calculate W component of
237 * @returns {quat} out
239 quat.calculateW = function (out, a) {
240 var x = a[0], y = a[1], z = a[2];
245 out[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
250 * Calculates the dot product of two quat's
252 * @param {quat} a the first operand
253 * @param {quat} b the second operand
254 * @returns {Number} dot product of a and b
260 * Performs a linear interpolation between two quat's
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
269 quat.lerp = vec4.lerp;
272 * Performs a spherical linear interpolation between two quat
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
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];
284 var cosHalfTheta = ax * bx + ay * by + az * bz + aw * bw,
290 if (Math.abs(cosHalfTheta) >= 1.0) {
300 halfTheta = Math.acos(cosHalfTheta);
301 sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta);
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);
311 ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta;
312 ratioB = Math.sin(t * halfTheta) / sinHalfTheta;
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);
323 * Calculates the inverse of a quat
325 * @param {quat} out the receiving quaternion
326 * @param {quat} a quat to calculate inverse of
327 * @returns {quat} out
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;
334 // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
344 * Calculates the conjugate of a quat
345 * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
347 * @param {quat} out the receiving quaternion
348 * @param {quat} a quat to calculate conjugate of
349 * @returns {quat} out
351 quat.conjugate = function (out, a) {
360 * Calculates the length of a quat
362 * @param {quat} a vector to calculate length of
363 * @returns {Number} length of a
366 quat.length = vec4.length;
369 * Alias for {@link quat.length}
372 quat.len = quat.length;
375 * Calculates the squared length of a quat
377 * @param {quat} a vector to calculate squared length of
378 * @returns {Number} squared length of a
381 quat.squaredLength = vec4.squaredLength;
384 * Alias for {@link quat.squaredLength}
387 quat.sqrLen = quat.squaredLength;
392 * @param {quat} out the receiving quaternion
393 * @param {quat} a quaternion to normalize
394 * @returns {quat} out
397 quat.normalize = vec4.normalize;
400 * Creates a quaternion from the given 3x3 rotation matrix.
402 * @param {quat} out the receiving quaternion
403 * @param {mat3} m rotation matrix
404 * @returns {quat} out
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];
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;
428 if ( m[8] > m[i*3+i] )
433 fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0);
434 out[i] = 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;
446 * Returns a string representation of a quatenion
448 * @param {quat} vec vector to represent as a string
449 * @returns {String} string representation of the vector
451 quat.str = function (a) {
452 return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
455 if(typeof(exports) !== 'undefined') {