UNPKG

pixpipe

Version:

A image processing pipeline in pure Javascript for browsers and Node

1,577 lines (1,300 loc) 2.03 MB
/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ let ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array; /** * Sets the type of array used when creating new vectors and matrices * * @param {Type} type Array type, such as Float32Array or Array */ function setMatrixArrayType(type) { ARRAY_TYPE = type; } const degree = Math.PI / 180; /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * 3x3 Matrix * @module mat3 */ /** * Creates a new identity mat3 * * @returns {mat3} a new 3x3 matrix */ function create$2() { let out = new ARRAY_TYPE(9); out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 1; out[5] = 0; out[6] = 0; out[7] = 0; out[8] = 1; return out; } /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * 4x4 Matrix * @module mat4 */ /** * Creates a new identity mat4 * * @returns {mat4} a new 4x4 matrix */ function create$3() { let out = new ARRAY_TYPE(16); out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 1; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 1; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; } /** * Create a new mat4 with the given values * * @param {Number} m00 Component in column 0, row 0 position (index 0) * @param {Number} m01 Component in column 0, row 1 position (index 1) * @param {Number} m02 Component in column 0, row 2 position (index 2) * @param {Number} m03 Component in column 0, row 3 position (index 3) * @param {Number} m10 Component in column 1, row 0 position (index 4) * @param {Number} m11 Component in column 1, row 1 position (index 5) * @param {Number} m12 Component in column 1, row 2 position (index 6) * @param {Number} m13 Component in column 1, row 3 position (index 7) * @param {Number} m20 Component in column 2, row 0 position (index 8) * @param {Number} m21 Component in column 2, row 1 position (index 9) * @param {Number} m22 Component in column 2, row 2 position (index 10) * @param {Number} m23 Component in column 2, row 3 position (index 11) * @param {Number} m30 Component in column 3, row 0 position (index 12) * @param {Number} m31 Component in column 3, row 1 position (index 13) * @param {Number} m32 Component in column 3, row 2 position (index 14) * @param {Number} m33 Component in column 3, row 3 position (index 15) * @returns {mat4} A new mat4 */ function fromValues$3(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { let out = new ARRAY_TYPE(16); out[0] = m00; out[1] = m01; out[2] = m02; out[3] = m03; out[4] = m10; out[5] = m11; out[6] = m12; out[7] = m13; out[8] = m20; out[9] = m21; out[10] = m22; out[11] = m23; out[12] = m30; out[13] = m31; out[14] = m32; out[15] = m33; return out; } /** * Inverts a mat4 * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ function invert$3(out, a) { let a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3]; let a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; let a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; let a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; let b00 = a00 * a11 - a01 * a10; let b01 = a00 * a12 - a02 * a10; let b02 = a00 * a13 - a03 * a10; let b03 = a01 * a12 - a02 * a11; let b04 = a01 * a13 - a03 * a11; let b05 = a02 * a13 - a03 * a12; let b06 = a20 * a31 - a21 * a30; let b07 = a20 * a32 - a22 * a30; let b08 = a20 * a33 - a23 * a30; let b09 = a21 * a32 - a22 * a31; let b10 = a21 * a33 - a23 * a31; let b11 = a22 * a33 - a23 * a32; // Calculate the determinant let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; if (!det) { return null; } det = 1.0 / det; out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; return out; } /** * Multiplies two mat4s * * @param {mat4} out the receiving matrix * @param {mat4} a the first operand * @param {mat4} b the second operand * @returns {mat4} out */ function multiply$3(out, a, b) { let a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3]; let a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; let a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; let a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; // Cache only the current line of the second matrix let b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; return out; } /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * 3 Dimensional Vector * @module vec3 */ /** * Creates a new, empty vec3 * * @returns {vec3} a new 3D vector */ function create$4() { let out = new ARRAY_TYPE(3); out[0] = 0; out[1] = 0; out[2] = 0; return out; } /** * Calculates the length of a vec3 * * @param {vec3} a vector to calculate length of * @returns {Number} length of a */ function length(a) { let x = a[0]; let y = a[1]; let z = a[2]; return Math.sqrt(x*x + y*y + z*z); } /** * Creates a new vec3 initialized with the given values * * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @returns {vec3} a new 3D vector */ function fromValues$4(x, y, z) { let out = new ARRAY_TYPE(3); out[0] = x; out[1] = y; out[2] = z; return out; } /** * Normalize a vec3 * * @param {vec3} out the receiving vector * @param {vec3} a vector to normalize * @returns {vec3} out */ function normalize(out, a) { let x = a[0]; let y = a[1]; let z = a[2]; let len = x*x + y*y + z*z; if (len > 0) { //TODO: evaluate use of glm_invsqrt here? len = 1 / Math.sqrt(len); out[0] = a[0] * len; out[1] = a[1] * len; out[2] = a[2] * len; } return out; } /** * Calculates the dot product of two vec3's * * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {Number} dot product of a and b */ function dot(a, b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; } /** * Computes the cross product of two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ function cross(out, a, b) { let ax = a[0], ay = a[1], az = a[2]; let bx = b[0], by = b[1], bz = b[2]; out[0] = ay * bz - az * by; out[1] = az * bx - ax * bz; out[2] = ax * by - ay * bx; return out; } /** * Alias for {@link vec3.length} * @function */ const len = length; /** * Perform some operation over an array of vec3s. * * @param {Array} a the array of vectors to iterate over * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed * @param {Number} offset Number of elements to skip at the beginning of the array * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array * @param {Function} fn Function to call for each vector in the array * @param {Object} [arg] additional argument to pass to fn * @returns {Array} a * @function */ const forEach = (function() { let vec = create$4(); return function(a, stride, offset, count, fn, arg) { let i, l; if(!stride) { stride = 3; } if(!offset) { offset = 0; } if(count) { l = Math.min((count * stride) + offset, a.length); } else { l = a.length; } for(i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; fn(vec, vec, arg); a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; } return a; }; })(); /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * 4 Dimensional Vector * @module vec4 */ /** * Creates a new, empty vec4 * * @returns {vec4} a new 4D vector */ function create$5() { let out = new ARRAY_TYPE(4); out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 0; return out; } /** * Creates a new vec4 initialized with the given values * * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @param {Number} w W component * @returns {vec4} a new 4D vector */ function fromValues$5(x, y, z, w) { let out = new ARRAY_TYPE(4); out[0] = x; out[1] = y; out[2] = z; out[3] = w; return out; } /** * Normalize a vec4 * * @param {vec4} out the receiving vector * @param {vec4} a vector to normalize * @returns {vec4} out */ function normalize$1(out, a) { let x = a[0]; let y = a[1]; let z = a[2]; let w = a[3]; let len = x*x + y*y + z*z + w*w; if (len > 0) { len = 1 / Math.sqrt(len); out[0] = x * len; out[1] = y * len; out[2] = z * len; out[3] = w * len; } return out; } /** * Transforms the vec4 with a mat4. * * @param {vec4} out the receiving vector * @param {vec4} a the vector to transform * @param {mat4} m matrix to transform with * @returns {vec4} out */ function transformMat4$1(out, a, m) { let x = a[0], y = a[1], z = a[2], w = a[3]; out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; return out; } /** * Perform some operation over an array of vec4s. * * @param {Array} a the array of vectors to iterate over * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed * @param {Number} offset Number of elements to skip at the beginning of the array * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array * @param {Function} fn Function to call for each vector in the array * @param {Object} [arg] additional argument to pass to fn * @returns {Array} a * @function */ const forEach$1 = (function() { let vec = create$5(); return function(a, stride, offset, count, fn, arg) { let i, l; if(!stride) { stride = 4; } if(!offset) { offset = 0; } if(count) { l = Math.min((count * stride) + offset, a.length); } else { l = a.length; } for(i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3]; fn(vec, vec, arg); a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3]; } return a; }; })(); /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * Quaternion * @module quat */ /** * Creates a new identity quat * * @returns {quat} a new quaternion */ function create$6() { let out = new ARRAY_TYPE(4); out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1; return out; } /** * Sets a quat from the given angle and rotation axis, * then returns it. * * @param {quat} out the receiving quaternion * @param {vec3} axis the axis around which to rotate * @param {Number} rad the angle in radians * @returns {quat} out **/ function setAxisAngle(out, axis, rad) { rad = rad * 0.5; let s = Math.sin(rad); out[0] = s * axis[0]; out[1] = s * axis[1]; out[2] = s * axis[2]; out[3] = Math.cos(rad); return out; } /** * Performs a spherical linear interpolation between two quat * * @param {quat} out the receiving quaternion * @param {quat} a the first operand * @param {quat} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {quat} out */ function slerp(out, a, b, t) { // benchmarks: // http://jsperf.com/quaternion-slerp-implementations let ax = a[0], ay = a[1], az = a[2], aw = a[3]; let bx = b[0], by = b[1], bz = b[2], bw = b[3]; let omega, cosom, sinom, scale0, scale1; // calc cosine cosom = ax * bx + ay * by + az * bz + aw * bw; // adjust signs (if necessary) if ( cosom < 0.0 ) { cosom = -cosom; bx = - bx; by = - by; bz = - bz; bw = - bw; } // calculate coefficients if ( (1.0 - cosom) > 0.000001 ) { // standard case (slerp) omega = Math.acos(cosom); sinom = Math.sin(omega); scale0 = Math.sin((1.0 - t) * omega) / sinom; scale1 = Math.sin(t * omega) / sinom; } else { // "from" and "to" quaternions are very close // ... so we can do a linear interpolation scale0 = 1.0 - t; scale1 = t; } // calculate final values out[0] = scale0 * ax + scale1 * bx; out[1] = scale0 * ay + scale1 * by; out[2] = scale0 * az + scale1 * bz; out[3] = scale0 * aw + scale1 * bw; return out; } /** * Creates a quaternion from the given 3x3 rotation matrix. * * NOTE: The resultant quaternion is not normalized, so you should be sure * to renormalize the quaternion yourself where necessary. * * @param {quat} out the receiving quaternion * @param {mat3} m rotation matrix * @returns {quat} out * @function */ function fromMat3(out, m) { // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes // article "Quaternion Calculus and Fast Animation". let fTrace = m[0] + m[4] + m[8]; let fRoot; if ( fTrace > 0.0 ) { // |w| > 1/2, may as well choose w > 1/2 fRoot = Math.sqrt(fTrace + 1.0); // 2w out[3] = 0.5 * fRoot; fRoot = 0.5/fRoot; // 1/(4w) out[0] = (m[5]-m[7])*fRoot; out[1] = (m[6]-m[2])*fRoot; out[2] = (m[1]-m[3])*fRoot; } else { // |w| <= 1/2 let i = 0; if ( m[4] > m[0] ) i = 1; if ( m[8] > m[i*3+i] ) i = 2; let j = (i+1)%3; let k = (i+2)%3; fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0); out[i] = 0.5 * fRoot; fRoot = 0.5 / fRoot; out[3] = (m[j*3+k] - m[k*3+j]) * fRoot; out[j] = (m[j*3+i] + m[i*3+j]) * fRoot; out[k] = (m[k*3+i] + m[i*3+k]) * fRoot; } return out; } /** * Normalize a quat * * @param {quat} out the receiving quaternion * @param {quat} a quaternion to normalize * @returns {quat} out * @function */ const normalize$2 = normalize$1; /** * Sets a quaternion to represent the shortest rotation from one * vector to another. * * Both vectors are assumed to be unit length. * * @param {quat} out the receiving quaternion. * @param {vec3} a the initial vector * @param {vec3} b the destination vector * @returns {quat} out */ const rotationTo = (function() { let tmpvec3 = create$4(); let xUnitVec3 = fromValues$4(1,0,0); let yUnitVec3 = fromValues$4(0,1,0); return function(out, a, b) { let dot$$1 = dot(a, b); if (dot$$1 < -0.999999) { cross(tmpvec3, xUnitVec3, a); if (len(tmpvec3) < 0.000001) cross(tmpvec3, yUnitVec3, a); normalize(tmpvec3, tmpvec3); setAxisAngle(out, tmpvec3, Math.PI); return out; } else if (dot$$1 > 0.999999) { out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1; return out; } else { cross(tmpvec3, a, b); out[0] = tmpvec3[0]; out[1] = tmpvec3[1]; out[2] = tmpvec3[2]; out[3] = 1 + dot$$1; return normalize$2(out, out); } }; })(); /** * Performs a spherical linear interpolation with two control points * * @param {quat} out the receiving quaternion * @param {quat} a the first operand * @param {quat} b the second operand * @param {quat} c the third operand * @param {quat} d the fourth operand * @param {Number} t interpolation amount * @returns {quat} out */ const sqlerp = (function () { let temp1 = create$6(); let temp2 = create$6(); return function (out, a, b, c, d, t) { slerp(temp1, a, d, t); slerp(temp2, b, c, t); slerp(out, temp1, temp2, 2 * t * (1 - t)); return out; }; }()); /** * Sets the specified quaternion with values corresponding to the given * axes. Each axis is a vec3 and is expected to be unit length and * perpendicular to all other specified axes. * * @param {vec3} view the vector representing the viewing direction * @param {vec3} right the vector representing the local "right" direction * @param {vec3} up the vector representing the local "up" direction * @returns {quat} out */ const setAxes = (function() { let matr = create$2(); return function(out, view, right, up) { matr[0] = right[0]; matr[3] = right[1]; matr[6] = right[2]; matr[1] = up[0]; matr[4] = up[1]; matr[7] = up[2]; matr[2] = -view[0]; matr[5] = -view[1]; matr[8] = -view[2]; return normalize$2(out, fromMat3(out, matr)); }; })(); /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * 2 Dimensional Vector * @module vec2 */ /** * Creates a new, empty vec2 * * @returns {vec2} a new 2D vector */ function create$7() { let out = new ARRAY_TYPE(2); out[0] = 0; out[1] = 0; return out; } /** * Perform some operation over an array of vec2s. * * @param {Array} a the array of vectors to iterate over * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed * @param {Number} offset Number of elements to skip at the beginning of the array * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array * @param {Function} fn Function to call for each vector in the array * @param {Object} [arg] additional argument to pass to fn * @returns {Array} a * @function */ const forEach$2 = (function() { let vec = create$7(); return function(a, stride, offset, count, fn, arg) { let i, l; if(!stride) { stride = 2; } if(!offset) { offset = 0; } if(count) { l = Math.min((count * stride) + offset, a.length); } else { l = a.length; } for(i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i+1]; fn(vec, vec, arg); a[i] = vec[0]; a[i+1] = vec[1]; } return a; }; })(); /** * @fileoverview gl-matrix - High performance matrix and vector operations * @author Brandon Jones * @author Colin MacKenzie IV * @version 2.4.0 */ /* * Author Jonathan Lurie - http://me.jonathanlurie.fr * License MIT * Link https://github.com/Pixpipe/pixpipejs * Lab MCIN - Montreal Neurological Institute */ // The index types are stored in this sort-of-private/sort-of-static object. var coreTypes = {}; /** * CoreTypes is bit of an exception in Pixpipejs because it does not inherit from * PixpipeObject and it contains only static methods. In a sens, it's comparable * to a singleton that stores all the core types constructors of Pixpipe so that * they can be retrived only by querying their name. * * At the creation of a new type, the static method `.addCoreType()` should be * called right after the closing curly bracket of the class declaration. * This is if we want to reference this class as a core type. */ class CoreTypes { /** * [STATIC] * Adds a new type to the collection of core types. This is used when we want * to retrieve a type and instanciate an object of this type using its constructor name. * @param {Class} typeClass - the class of the type */ static addCoreType( typeClass ){ if( typeof typeClass === "function" ){ coreTypes[ typeClass.name ] = typeClass; } } /** * [STATIC] * Return the constructor of the given type name. This is useful to instanciate * an object based on the name of its type (eg. in PixBinDecoder) * @param {String} typeName - the name of the type eg. "Image2D" * @return {Function} constructor for the given type */ static getCoreType( typeName ){ if( typeName in coreTypes ){ return coreTypes[ typeName ] }else{ return null; } } } var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function commonjsRequire () { throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs'); } function unwrapExports (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var joiBrowser = createCommonjsModule(function (module, exports) { (function webpackUniversalModuleDefinition(root, factory) { module.exports = factory(); })(commonjsGlobal, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { var Joi = __webpack_require__(1); module.exports = Joi; /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { // Load modules var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass); } var Hoek = __webpack_require__(2); var Any = __webpack_require__(11); var Cast = __webpack_require__(16); var Errors = __webpack_require__(13); var Lazy = __webpack_require__(29); var Ref = __webpack_require__(12); // Declare internals var internals = { alternatives: __webpack_require__(25), array: __webpack_require__(30), boolean: __webpack_require__(24), binary: __webpack_require__(31), date: __webpack_require__(17), number: __webpack_require__(23), object: __webpack_require__(26), string: __webpack_require__(18) }; internals.root = function () { var any = new Any(); var root = any.clone(); root.any = function () { Hoek.assert(arguments.length === 0, 'Joi.any() does not allow arguments.'); return any; }; root.alternatives = root.alt = function () { return arguments.length ? internals.alternatives.try.apply(internals.alternatives, arguments) : internals.alternatives; }; root.array = function () { Hoek.assert(arguments.length === 0, 'Joi.array() does not allow arguments.'); return internals.array; }; root.boolean = root.bool = function () { Hoek.assert(arguments.length === 0, 'Joi.boolean() does not allow arguments.'); return internals.boolean; }; root.binary = function () { Hoek.assert(arguments.length === 0, 'Joi.binary() does not allow arguments.'); return internals.binary; }; root.date = function () { Hoek.assert(arguments.length === 0, 'Joi.date() does not allow arguments.'); return internals.date; }; root.func = function () { Hoek.assert(arguments.length === 0, 'Joi.func() does not allow arguments.'); return internals.object._func(); }; root.number = function () { Hoek.assert(arguments.length === 0, 'Joi.number() does not allow arguments.'); return internals.number; }; root.object = function () { return arguments.length ? internals.object.keys.apply(internals.object, arguments) : internals.object; }; root.string = function () { Hoek.assert(arguments.length === 0, 'Joi.string() does not allow arguments.'); return internals.string; }; root.ref = function () { return Ref.create.apply(null, arguments); }; root.isRef = function (ref) { return Ref.isRef(ref); }; root.validate = function (value /*, [schema], [options], callback */) { var last = arguments[arguments.length - 1]; var callback = typeof last === 'function' ? last : null; var count = arguments.length - (callback ? 1 : 0); if (count === 1) { return any.validate(value, callback); } var options = count === 3 ? arguments[2] : {}; var schema = root.compile(arguments[1]); return schema._validateWithOptions(value, options, callback); }; root.describe = function () { var schema = arguments.length ? root.compile(arguments[0]) : any; return schema.describe(); }; root.compile = function (schema) { try { return Cast.schema(schema); } catch (err) { if (err.hasOwnProperty('path')) { err.message = err.message + '(' + err.path + ')'; } throw err; } }; root.assert = function (value, schema, message) { root.attempt(value, schema, message); }; root.attempt = function (value, schema, message) { var result = root.validate(value, schema); var error = result.error; if (error) { if (!message) { if (typeof error.annotate === 'function') { error.message = error.annotate(); } throw error; } if (!(message instanceof Error)) { if (typeof error.annotate === 'function') { error.message = message + ' ' + error.annotate(); } throw error; } throw message; } return result.value; }; root.reach = function (schema, path) { Hoek.assert(schema && schema instanceof Any, 'you must provide a joi schema'); Hoek.assert(typeof path === 'string', 'path must be a string'); if (path === '') { return schema; } var parts = path.split('.'); var children = schema._inner.children; if (!children) { return; } var key = parts[0]; for (var i = 0; i < children.length; ++i) { var child = children[i]; if (child.key === key) { return this.reach(child.schema, path.substr(key.length + 1)); } } }; root.lazy = function (fn) { return Lazy.set(fn); }; root.extend = function () { var _this = this; var extensions = Hoek.flatten(Array.prototype.slice.call(arguments)); Hoek.assert(extensions.length > 0, 'You need to provide at least one extension'); this.assert(extensions, root.extensionsSchema); var joi = Object.create(this.any()); _extends(joi, this); var _loop = function _loop(i) { var extension = extensions[i]; if (typeof extension === 'function') { extension = extension(joi); } _this.assert(extension, root.extensionSchema); var base = (extension.base || _this.any()).clone(); // Cloning because we're going to override language afterwards var ctor = base.constructor; var type = function (_ctor) { _inherits(type, _ctor); // eslint-disable-line no-loop-func function type() { _classCallCheck(this, type); var _this2 = _possibleConstructorReturn(this, _ctor.call(this)); if (extension.base) { _extends(_this2, base); } _this2._type = extension.name; if (extension.language) { _this2._settings = _this2._settings || { language: {} }; _this2._settings.language = Hoek.applyToDefaults(_this2._settings.language, _defineProperty({}, extension.name, extension.language)); } return _this2; } return type; }(ctor); if (extension.coerce) { type.prototype._coerce = function (value, state, options) { if (ctor.prototype._coerce) { var baseRet = ctor.prototype._coerce.call(this, value, state, options); if (baseRet.errors) { return baseRet; } value = baseRet.value; } var ret = extension.coerce.call(this, value, state, options); if (ret instanceof Errors.Err) { return { value: value, errors: ret }; } return { value: ret }; }; } if (extension.pre) { type.prototype._base = function (value, state, options) { if (ctor.prototype._base) { var baseRet = ctor.prototype._base.call(this, value, state, options); if (baseRet.errors) { return baseRet; } value = baseRet.value; } var ret = extension.pre.call(this, value, state, options); if (ret instanceof Errors.Err) { return { value: value, errors: ret }; } return { value: ret }; }; } if (extension.rules) { var _loop2 = function _loop2(j) { var rule = extension.rules[j]; var ruleArgs = rule.params ? rule.params instanceof Any ? rule.params._inner.children.map(function (k) { return k.key; }) : Object.keys(rule.params) : []; var validateArgs = rule.params ? Cast.schema(rule.params) : null; type.prototype[rule.name] = function () { // eslint-disable-line no-loop-func if (arguments.length > ruleArgs.length) { throw new Error('Unexpected number of arguments'); } var args = Array.prototype.slice.call(arguments); var hasRef = false; var arg = {}; for (var k = 0; k < ruleArgs.length; ++k) { arg[ruleArgs[k]] = args[k]; if (!hasRef && Ref.isRef(args[k])) { hasRef = true; } } if (validateArgs) { arg = joi.attempt(arg, validateArgs); } var schema = void 0; if (rule.validate) { var validate = function validate(value, state, options) { return rule.validate.call(this, arg, value, state, options); }; schema = this._test(rule.name, arg, validate, { description: rule.description, hasRef: hasRef }); } else { schema = this.clone(); } if (rule.setup) { var newSchema = rule.setup.call(schema, arg); if (newSchema !== undefined) { Hoek.assert(newSchema instanceof Any, 'Setup of extension Joi.' + this._type + '().' + rule.name + '() must return undefined or a Joi object'); schema = newSchema; } } return schema; }; }; for (var j = 0; j < extension.rules.length; ++j) { _loop2(j); } } if (extension.describe) { type.prototype.describe = function () { var description = ctor.prototype.describe.call(this); return extension.describe.call(this, description); }; } var instance = new type(); joi[extension.name] = function () { return instance; }; }; for (var i = 0; i < extensions.length; ++i) { _loop(i); } return joi; }; root.extensionSchema = internals.object.keys({ base: internals.object.type(Any, 'Joi object'), name: internals.string.required(), coerce: internals.object._func().arity(3), pre: internals.object._func().arity(3), language: internals.object, describe: internals.object._func().arity(1), rules: internals.array.items(internals.object.keys({ name: internals.string.required(), setup: internals.object._func().arity(1), validate: internals.object._func().arity(4), params: [internals.object.pattern(/.*/, internals.object.type(Any, 'Joi object')), internals.object.type(internals.object.constructor, 'Joi object')], description: [internals.string, internals.object._func().arity(1)] }).or('setup', 'validate')) }).strict(); root.extensionsSchema = internals.array.items([internals.object, internals.object._func().arity(1)]).strict(); root.version = __webpack_require__(32).version; return root; }; module.exports = internals.root(); /***/ }, /* 2 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(Buffer, process) { // Load modules var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var Crypto = __webpack_require__(5); var Path = __webpack_require__(6); var Util = __webpack_require__(7); var Escape = __webpack_require__(10); // Declare internals var internals = {}; // Clone object or array exports.clone = function (obj, seen) { if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object' || obj === null) { return obj; } seen = seen || new Map(); var lookup = seen.get(obj); if (lookup) { return lookup; } var newObj = void 0; var cloneDeep = false; if (!Array.isArray(obj)) { if (Buffer.isBuffer(obj)) { newObj = new Buffer(obj); } else if (obj instanceof Date) { newObj = new Date(obj.getTime()); } else if (obj instanceof RegExp) { newObj = new RegExp(obj); } else { var proto = Object.getPrototypeOf(obj); if (proto && proto.isImmutable) { newObj = obj; } else { newObj = Object.create(proto); cloneDeep = true; } } } else { newObj = []; cloneDeep = true; } seen.set(obj, newObj); if (cloneDeep) { var keys = Object.getOwnPropertyNames(obj); for (var i = 0; i < keys.length; ++i) { var key = keys[i]; var descriptor = Object.getOwnPropertyDescriptor(obj, key); if (descriptor && (descriptor.get || descriptor.set)) { Object.defineProperty(newObj, key, descriptor); } else { newObj[key] = exports.clone(obj[key], seen); } } } return newObj; }; // Merge all the properties of source into target, source wins in conflict, and by default null and undefined from source are applied /*eslint-disable */ exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) { /*eslint-enable */ exports.assert(target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object', 'Invalid target value: must be an object'); exports.assert(source === null || source === undefined || (typeof source === 'undefined' ? 'undefined' : _typeof(source)) === 'object', 'Invalid source value: must be null, undefined, or an object'); if (!source) { return target; } if (Array.isArray(source)) { exports.assert(Array.isArray(target), 'Cannot merge array onto an obj