1ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
2ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
3ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris CraikPermission is hereby granted, free of charge, to any person obtaining a copy
4ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikof this software and associated documentation files (the "Software"), to deal
5ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikin the Software without restriction, including without limitation the rights
6ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikcopies of the Software, and to permit persons to whom the Software is
8ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikfurnished to do so, subject to the following conditions:
9ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
10ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris CraikThe above copyright notice and this permission notice shall be included in
11ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikall copies or substantial portions of the Software.
12ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
13ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris CraikTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris CraikIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris CraikFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris CraikAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris CraikLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris CraikOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris CraikTHE SOFTWARE. */
20ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
21ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikvar glMatrix = require("./common.js");
22ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikvar mat3 = require("./mat3.js");
23ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikvar vec3 = require("./vec3.js");
24ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikvar vec4 = require("./vec4.js");
2566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
2666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
2766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @class Quaternion
2866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @name quat
2966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
3066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisvar quat = {};
3166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
3266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
3366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Creates a new identity quat
3466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
3566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} a new quaternion
3666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
3766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.create = function() {
38ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    var out = new glMatrix.ARRAY_TYPE(4);
3966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = 0;
4066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = 0;
4166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = 0;
4266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = 1;
4366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
4466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
4566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
4666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
47ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * Sets a quaternion to represent the shortest rotation from one
48ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * vector to another.
49ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik *
50ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * Both vectors are assumed to be unit length.
51ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik *
52ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {quat} out the receiving quaternion.
53ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {vec3} a the initial vector
54ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {vec3} b the destination vector
55ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @returns {quat} out
56ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik */
57ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikquat.rotationTo = (function() {
58ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    var tmpvec3 = vec3.create();
59ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    var xUnitVec3 = vec3.fromValues(1,0,0);
60ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    var yUnitVec3 = vec3.fromValues(0,1,0);
61ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
62ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    return function(out, a, b) {
63ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        var dot = vec3.dot(a, b);
64ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        if (dot < -0.999999) {
65ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            vec3.cross(tmpvec3, xUnitVec3, a);
66ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            if (vec3.length(tmpvec3) < 0.000001)
67ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik                vec3.cross(tmpvec3, yUnitVec3, a);
68ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            vec3.normalize(tmpvec3, tmpvec3);
69ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            quat.setAxisAngle(out, tmpvec3, Math.PI);
70ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            return out;
71ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        } else if (dot > 0.999999) {
72ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            out[0] = 0;
73ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            out[1] = 0;
74ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            out[2] = 0;
75ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            out[3] = 1;
76ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            return out;
77ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        } else {
78ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            vec3.cross(tmpvec3, a, b);
79ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            out[0] = tmpvec3[0];
80ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            out[1] = tmpvec3[1];
81ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            out[2] = tmpvec3[2];
82ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            out[3] = 1 + dot;
83ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik            return quat.normalize(out, out);
84ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        }
85ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    };
86ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik})();
87ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
88ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik/**
89ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * Sets the specified quaternion with values corresponding to the given
90ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * axes. Each axis is a vec3 and is expected to be unit length and
91ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * perpendicular to all other specified axes.
92ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik *
93ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {vec3} view  the vector representing the viewing direction
94ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {vec3} right the vector representing the local "right" direction
95ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {vec3} up    the vector representing the local "up" direction
96ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @returns {quat} out
97ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik */
98ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikquat.setAxes = (function() {
99ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    var matr = mat3.create();
100ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
101ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    return function(out, view, right, up) {
102ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        matr[0] = right[0];
103ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        matr[3] = right[1];
104ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        matr[6] = right[2];
105ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
106ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        matr[1] = up[0];
107ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        matr[4] = up[1];
108ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        matr[7] = up[2];
109ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
110ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        matr[2] = -view[0];
111ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        matr[5] = -view[1];
112ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        matr[8] = -view[2];
113ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
114ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        return quat.normalize(out, quat.fromMat3(out, matr));
115ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    };
116ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik})();
117ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
118ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik/**
11966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Creates a new quat initialized with values from an existing quaternion
12066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
12166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a quaternion to clone
12266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} a new quaternion
12366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
12466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
12566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.clone = vec4.clone;
12666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
12766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
12866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Creates a new quat initialized with the given values
12966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
13066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} x X component
13166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} y Y component
13266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} z Z component
13366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} w W component
13466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} a new quaternion
13566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
13666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
13766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.fromValues = vec4.fromValues;
13866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
13966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
14066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Copy the values from one quat to another
14166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
14266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
14366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a the source quaternion
14466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
14566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
14666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
14766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.copy = vec4.copy;
14866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
14966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
15066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Set the components of a quat to the given values
15166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
15266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
15366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} x X component
15466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} y Y component
15566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} z Z component
15666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} w W component
15766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
15866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
15966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
16066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.set = vec4.set;
16166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
16266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
16366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Set a quat to the identity quaternion
16466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
16566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
16666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
16766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
16866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.identity = function(out) {
16966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = 0;
17066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = 0;
17166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = 0;
17266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = 1;
17366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
17466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
17566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
17666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
17766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Sets a quat from the given angle and rotation axis,
17866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * then returns it.
17966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
18066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
18166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {vec3} axis the axis around which to rotate
18266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} rad the angle in radians
18366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
18466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis **/
18566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.setAxisAngle = function(out, axis, rad) {
18666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    rad = rad * 0.5;
18766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var s = Math.sin(rad);
18866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = s * axis[0];
18966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = s * axis[1];
19066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = s * axis[2];
19166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = Math.cos(rad);
19266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
19366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
19466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
19566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
19666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Adds two quat's
19766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
19866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
19966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a the first operand
20066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} b the second operand
20166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
20266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
20366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
20466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.add = vec4.add;
20566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
20666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
20766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Multiplies two quat's
20866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
20966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
21066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a the first operand
21166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} b the second operand
21266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
21366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
21466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.multiply = function(out, a, b) {
21566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
21666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        bx = b[0], by = b[1], bz = b[2], bw = b[3];
21766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
21866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = ax * bw + aw * bx + ay * bz - az * by;
21966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = ay * bw + aw * by + az * bx - ax * bz;
22066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = az * bw + aw * bz + ax * by - ay * bx;
22166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = aw * bw - ax * bx - ay * by - az * bz;
22266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
22366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
22466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
22566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
22666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Alias for {@link quat.multiply}
22766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
22866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
22966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.mul = quat.multiply;
23066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
23166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
23266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Scales a quat by a scalar number
23366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
23466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving vector
23566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a the vector to scale
23666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} b amount to scale the vector by
23766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
23866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
23966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
24066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.scale = vec4.scale;
24166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
24266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
243ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * Rotates a quaternion by the given angle about the X axis
24466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
24566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out quat receiving operation result
24666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a quat to rotate
24766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {number} rad angle (in radians) to rotate
24866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
24966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
25066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.rotateX = function (out, a, rad) {
25166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    rad *= 0.5;
25266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
25366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
25466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        bx = Math.sin(rad), bw = Math.cos(rad);
25566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
25666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = ax * bw + aw * bx;
25766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = ay * bw + az * bx;
25866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = az * bw - ay * bx;
25966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = aw * bw - ax * bx;
26066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
26166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
26266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
26366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
264ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * Rotates a quaternion by the given angle about the Y axis
26566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
26666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out quat receiving operation result
26766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a quat to rotate
26866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {number} rad angle (in radians) to rotate
26966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
27066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
27166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.rotateY = function (out, a, rad) {
27266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    rad *= 0.5;
27366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
27466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
27566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        by = Math.sin(rad), bw = Math.cos(rad);
27666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
27766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = ax * bw - az * by;
27866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = ay * bw + aw * by;
27966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = az * bw + ax * by;
28066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = aw * bw - ay * by;
28166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
28266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
28366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
28466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
285ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * Rotates a quaternion by the given angle about the Z axis
28666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
28766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out quat receiving operation result
28866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a quat to rotate
28966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {number} rad angle (in radians) to rotate
29066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
29166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
29266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.rotateZ = function (out, a, rad) {
29366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    rad *= 0.5;
29466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
29566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
29666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        bz = Math.sin(rad), bw = Math.cos(rad);
29766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
29866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = ax * bw + ay * bz;
29966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = ay * bw - ax * bz;
30066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = az * bw + aw * bz;
30166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = aw * bw - az * bz;
30266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
30366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
30466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
30566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
30666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Calculates the W component of a quat from the X, Y, and Z components.
30766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Assumes that quaternion is 1 unit in length.
30866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Any existing W component will be ignored.
30966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
31066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
31166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a quat to calculate W component of
31266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
31366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
31466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.calculateW = function (out, a) {
31566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var x = a[0], y = a[1], z = a[2];
31666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
31766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = x;
31866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = y;
31966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = z;
320ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
32166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
32266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
32366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
32466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
32566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Calculates the dot product of two quat's
32666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
32766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a the first operand
32866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} b the second operand
32966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {Number} dot product of a and b
33066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
33166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
33266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.dot = vec4.dot;
33366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
33466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
33566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Performs a linear interpolation between two quat's
33666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
33766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
33866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a the first operand
33966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} b the second operand
34066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} t interpolation amount between the two inputs
34166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
34266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
34366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
34466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.lerp = vec4.lerp;
34566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
34666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
34766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Performs a spherical linear interpolation between two quat
34866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
34966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
35066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a the first operand
35166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} b the second operand
35266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} t interpolation amount between the two inputs
35366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
35466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
35566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.slerp = function (out, a, b, t) {
356ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    // benchmarks:
357ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    //    http://jsperf.com/quaternion-slerp-implementations
358ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
35966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
36066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        bx = b[0], by = b[1], bz = b[2], bw = b[3];
36166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
362ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    var        omega, cosom, sinom, scale0, scale1;
363ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
364ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    // calc cosine
365ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    cosom = ax * bx + ay * by + az * bz + aw * bw;
366ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    // adjust signs (if necessary)
367ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    if ( cosom < 0.0 ) {
368ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        cosom = -cosom;
369ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        bx = - bx;
370ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        by = - by;
371ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        bz = - bz;
372ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        bw = - bw;
37366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    }
374ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    // calculate coefficients
375ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    if ( (1.0 - cosom) > 0.000001 ) {
376ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        // standard case (slerp)
377ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        omega  = Math.acos(cosom);
378ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        sinom  = Math.sin(omega);
379ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        scale0 = Math.sin((1.0 - t) * omega) / sinom;
380ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        scale1 = Math.sin(t * omega) / sinom;
381ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    } else {
382ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        // "from" and "to" quaternions are very close
383ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        //  ... so we can do a linear interpolation
384ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        scale0 = 1.0 - t;
385ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        scale1 = t;
38666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    }
387ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    // calculate final values
388ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    out[0] = scale0 * ax + scale1 * bx;
389ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    out[1] = scale0 * ay + scale1 * by;
390ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    out[2] = scale0 * az + scale1 * bz;
391ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    out[3] = scale0 * aw + scale1 * bw;
392ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
39366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
39466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
39566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
39666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
397ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * Performs a spherical linear interpolation with two control points
398ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik *
399ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {quat} out the receiving quaternion
400ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {quat} a the first operand
401ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {quat} b the second operand
402ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {quat} c the third operand
403ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {quat} d the fourth operand
404ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @param {Number} t interpolation amount
405ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * @returns {quat} out
406ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik */
407ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikquat.sqlerp = (function () {
408ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik  var temp1 = quat.create();
409ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik  var temp2 = quat.create();
410ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
411ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik  return function (out, a, b, c, d, t) {
412ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    quat.slerp(temp1, a, d, t);
413ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    quat.slerp(temp2, b, c, t);
414ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    quat.slerp(out, temp1, temp2, 2 * t * (1 - t));
415ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
416ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    return out;
417ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik  };
418ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik}());
419ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
420ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik/**
42166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Calculates the inverse of a quat
42266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
42366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
42466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a quat to calculate inverse of
42566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
42666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
42766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.invert = function(out, a) {
42866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
42966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        dot = a0*a0 + a1*a1 + a2*a2 + a3*a3,
43066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        invDot = dot ? 1.0/dot : 0;
43166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
43266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
43366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
43466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = -a0*invDot;
43566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = -a1*invDot;
43666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = -a2*invDot;
43766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = a3*invDot;
43866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
43966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
44066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
44166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
44266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Calculates the conjugate of a quat
44366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
44466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
44566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
44666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a quat to calculate conjugate of
44766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
44866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
44966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.conjugate = function (out, a) {
45066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = -a[0];
45166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = -a[1];
45266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = -a[2];
45366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = a[3];
45466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
45566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
45666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
45766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
45866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Calculates the length of a quat
45966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
46066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a vector to calculate length of
46166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {Number} length of a
46266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
46366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
46466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.length = vec4.length;
46566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
46666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
46766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Alias for {@link quat.length}
46866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
46966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
47066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.len = quat.length;
47166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
47266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
47366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Calculates the squared length of a quat
47466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
47566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a vector to calculate squared length of
47666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {Number} squared length of a
47766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
47866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
47966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.squaredLength = vec4.squaredLength;
48066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
48166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
48266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Alias for {@link quat.squaredLength}
48366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
48466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
48566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.sqrLen = quat.squaredLength;
48666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
48766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
48866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Normalize a quat
48966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
49066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
49166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} a quaternion to normalize
49266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
49366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
49466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
49566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.normalize = vec4.normalize;
49666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
49766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
49866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Creates a quaternion from the given 3x3 rotation matrix.
49966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
500ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * NOTE: The resultant quaternion is not normalized, so you should be sure
501ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik * to renormalize the quaternion yourself where necessary.
502ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik *
50366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} out the receiving quaternion
50466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} m rotation matrix
50566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {quat} out
50666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
50766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
508ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikquat.fromMat3 = function(out, m) {
509ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
510ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    // article "Quaternion Calculus and Fast Animation".
511ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    var fTrace = m[0] + m[4] + m[8];
512ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    var fRoot;
513ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
514ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    if ( fTrace > 0.0 ) {
515ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        // |w| > 1/2, may as well choose w > 1/2
516ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        fRoot = Math.sqrt(fTrace + 1.0);  // 2w
517ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        out[3] = 0.5 * fRoot;
518ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        fRoot = 0.5/fRoot;  // 1/(4w)
519ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        out[0] = (m[5]-m[7])*fRoot;
520ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        out[1] = (m[6]-m[2])*fRoot;
521ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        out[2] = (m[1]-m[3])*fRoot;
522ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    } else {
523ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        // |w| <= 1/2
524ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        var i = 0;
525ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        if ( m[4] > m[0] )
526ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik          i = 1;
527ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        if ( m[8] > m[i*3+i] )
528ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik          i = 2;
529ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        var j = (i+1)%3;
530ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        var k = (i+2)%3;
53166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
532ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0);
533ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        out[i] = 0.5 * fRoot;
534ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        fRoot = 0.5 / fRoot;
535ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        out[3] = (m[j*3+k] - m[k*3+j]) * fRoot;
536ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        out[j] = (m[j*3+i] + m[i*3+j]) * fRoot;
537ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik        out[k] = (m[k*3+i] + m[i*3+k]) * fRoot;
538ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    }
539ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik
540ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik    return out;
541ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craik};
54266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
54366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
54466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Returns a string representation of a quatenion
54566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
54666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {quat} vec vector to represent as a string
54766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {String} string representation of the vector
54866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
54966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisquat.str = function (a) {
55066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
55166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
55266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
553ced05db70069f9d84c4b0dd9b3b26b94e3482336Chris Craikmodule.exports = quat;
554