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