UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.

1,429 lines • 1.15 MB
globalThis.GLTF_PROGRESSIVE_VERSION = ""; console.debug("[gltf-progressive] version -"); const Ra = "182", Ih = 0, Xo = 1, Sh = 2, Ws = 1, vh = 2, as = 3, Dn = 0, Gt = 1, An = 2, Rn = 0, Mi = 1, Yo = 2, Ko = 3, jo = 4, Mh = 5, ri = 100, yh = 101, Bh = 102, wh = 103, Th = 104, Rh = 200, Dh = 201, Lh = 202, Fh = 203, $r = 204, ea = 205, Uh = 206, Ph = 207, Nh = 208, Qh = 209, Oh = 210, kh = 211, Gh = 212, Hh = 213, Vh = 214, ta = 0, na = 1, ia = 2, Ri = 3, sa = 4, ra = 5, aa = 6, oa = 7, pc = 0, zh = 1, Wh = 2, En = 0, gc = 1, mc = 2, _c = 3, bc = 4, Ec = 5, xc = 6, Cc = 7, Jo = "attached", qh = "detached", Ic = 300, Wn = 301, Di = 302, ca = 303, la = 304, dr = 306, Li = 1e3, sn = 1001, js = 1002, _t = 1003, Da = 1004, os = 1005, ft = 1006, qs = 1007, rn = 1008, Re = 1009, Sc = 1010, vc = 1011, ds = 1012, La = 1013, Sn = 1014, Tt = 1015, Dt = 1016, Fa = 1017, Ua = 1018, fs = 1020, fr = 35902, Ar = 35899, Mc = 1021, As = 1022, St = 1023, Ln = 1026, ai = 1027, Vn = 1028, Pa = 1029, an = 1030, Na = 1031, Qa = 1033, yi = 33776, hi = 33777, Bi = 33778, cs = 33779, Js = 35840, ha = 35841, Fi = 35842, ps = 35843, Zs = 36196, gs = 37492, ms = 37496, $s = 37488, er = 37489, tr = 37490, nr = 37491, ui = 37808, ua = 37809, da = 37810, fa = 37811, wi = 37812, Aa = 37813, pa = 37814, ga = 37815, ma = 37816, _a = 37817, ba = 37818, Ea = 37819, xa = 37820, Ca = 37821, Ui = 36492, Ia = 36494, ir = 36495, sr = 36283, rr = 36284, ar = 36285, or = 36286, _s = 2300, bs = 2301, jr = 2302, Zo = 2400, $o = 2401, ec = 2402, Xh = 2500, Yh = 0, yc = 1, Sa = 2, Kh = 3200, Bc = 0, jh = 1, pn = "", At = "srgb", Rt = "srgb-linear", cr = "linear", Je = "srgb", Ii = 7680, tc = 519, Jh = 512, Zh = 513, $h = 514, Oa = 515, eu = 516, tu = 517, ka = 518, nu = 519, va = 35044, nc = "300 es", mn = 2e3, lr = 2001; function iu(s) { for (let e = s.length - 1; e >= 0; --e) if (s[e] >= 65535) return !0; return !1; } function Wd(s) { return ArrayBuffer.isView(s) && !(s instanceof DataView); } function hr(s) { return document.createElementNS("http://www.w3.org/1999/xhtml", s); } function su() { const s = hr("canvas"); return s.style.display = "block", s; } const al = {}; function ur(...s) { const e = "THREE." + s.shift(); console.log(e, ...s); } function Se(...s) { const e = "THREE." + s.shift(); console.warn(e, ...s); } function Be(...s) { const e = "THREE." + s.shift(); console.error(e, ...s); } function Es(...s) { const e = s.join(" "); e in al || (al[e] = !0, Se(...s)); } function qd(s, e, t) { return new Promise(function(n, i) { function r() { switch (s.clientWaitSync(e, s.SYNC_FLUSH_COMMANDS_BIT, 0)) { case s.WAIT_FAILED: i(); break; case s.TIMEOUT_EXPIRED: setTimeout(r, t); break; default: n(); } } setTimeout(r, t); }); } class Oi { /** * Adds the given event listener to the given event type. * * @param {string} type - The type of event to listen to. * @param {Function} listener - The function that gets called when the event is fired. */ addEventListener(e, t) { this._listeners === void 0 && (this._listeners = {}); const n = this._listeners; n[e] === void 0 && (n[e] = []), n[e].indexOf(t) === -1 && n[e].push(t); } /** * Returns `true` if the given event listener has been added to the given event type. * * @param {string} type - The type of event. * @param {Function} listener - The listener to check. * @return {boolean} Whether the given event listener has been added to the given event type. */ hasEventListener(e, t) { const n = this._listeners; return n === void 0 ? !1 : n[e] !== void 0 && n[e].indexOf(t) !== -1; } /** * Removes the given event listener from the given event type. * * @param {string} type - The type of event. * @param {Function} listener - The listener to remove. */ removeEventListener(e, t) { const n = this._listeners; if (n === void 0) return; const i = n[e]; if (i !== void 0) { const r = i.indexOf(t); r !== -1 && i.splice(r, 1); } } /** * Dispatches an event object. * * @param {Object} event - The event that gets fired. */ dispatchEvent(e) { const t = this._listeners; if (t === void 0) return; const n = t[e.type]; if (n !== void 0) { e.target = this; const i = n.slice(0); for (let r = 0, a = i.length; r < a; r++) i[r].call(this, e); e.target = null; } } } const Lt = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff"]; let ol = 1234567; const Xs = Math.PI / 180, xs = 180 / Math.PI; function xn() { const s = Math.random() * 4294967295 | 0, e = Math.random() * 4294967295 | 0, t = Math.random() * 4294967295 | 0, n = Math.random() * 4294967295 | 0; return (Lt[s & 255] + Lt[s >> 8 & 255] + Lt[s >> 16 & 255] + Lt[s >> 24 & 255] + "-" + Lt[e & 255] + Lt[e >> 8 & 255] + "-" + Lt[e >> 16 & 15 | 64] + Lt[e >> 24 & 255] + "-" + Lt[t & 63 | 128] + Lt[t >> 8 & 255] + "-" + Lt[t >> 16 & 255] + Lt[t >> 24 & 255] + Lt[n & 255] + Lt[n >> 8 & 255] + Lt[n >> 16 & 255] + Lt[n >> 24 & 255]).toLowerCase(); } function Ve(s, e, t) { return Math.max(e, Math.min(t, s)); } function wc(s, e) { return (s % e + e) % e; } function Xd(s, e, t, n, i) { return n + (s - e) * (i - n) / (t - e); } function Yd(s, e, t) { return s !== e ? (t - s) / (e - s) : 0; } function Ys(s, e, t) { return (1 - t) * s + t * e; } function Kd(s, e, t, n) { return Ys(s, e, 1 - Math.exp(-t * n)); } function jd(s, e = 1) { return e - Math.abs(wc(s, e * 2) - e); } function Jd(s, e, t) { return s <= e ? 0 : s >= t ? 1 : (s = (s - e) / (t - e), s * s * (3 - 2 * s)); } function Zd(s, e, t) { return s <= e ? 0 : s >= t ? 1 : (s = (s - e) / (t - e), s * s * s * (s * (s * 6 - 15) + 10)); } function $d(s, e) { return s + Math.floor(Math.random() * (e - s + 1)); } function ef(s, e) { return s + Math.random() * (e - s); } function tf(s) { return s * (0.5 - Math.random()); } function nf(s) { s !== void 0 && (ol = s); let e = ol += 1831565813; return e = Math.imul(e ^ e >>> 15, e | 1), e ^= e + Math.imul(e ^ e >>> 7, e | 61), ((e ^ e >>> 14) >>> 0) / 4294967296; } function sf(s) { return s * Xs; } function rf(s) { return s * xs; } function af(s) { return (s & s - 1) === 0 && s !== 0; } function of(s) { return Math.pow(2, Math.ceil(Math.log(s) / Math.LN2)); } function cf(s) { return Math.pow(2, Math.floor(Math.log(s) / Math.LN2)); } function lf(s, e, t, n, i) { const r = Math.cos, a = Math.sin, o = r(t / 2), c = a(t / 2), l = r((e + n) / 2), h = a((e + n) / 2), u = r((e - n) / 2), d = a((e - n) / 2), A = r((n - e) / 2), g = a((n - e) / 2); switch (i) { case "XYX": s.set(o * h, c * u, c * d, o * l); break; case "YZY": s.set(c * d, o * h, c * u, o * l); break; case "ZXZ": s.set(c * u, c * d, o * h, o * l); break; case "XZX": s.set(o * h, c * g, c * A, o * l); break; case "YXY": s.set(c * A, o * h, c * g, o * l); break; case "ZYZ": s.set(c * g, c * A, o * h, o * l); break; default: Se("MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: " + i); } } function gn(s, e) { switch (e.constructor) { case Float32Array: return s; case Uint32Array: return s / 4294967295; case Uint16Array: return s / 65535; case Uint8Array: return s / 255; case Int32Array: return Math.max(s / 2147483647, -1); case Int16Array: return Math.max(s / 32767, -1); case Int8Array: return Math.max(s / 127, -1); default: throw new Error("Invalid component type."); } } function it(s, e) { switch (e.constructor) { case Float32Array: return s; case Uint32Array: return Math.round(s * 4294967295); case Uint16Array: return Math.round(s * 65535); case Uint8Array: return Math.round(s * 255); case Int32Array: return Math.round(s * 2147483647); case Int16Array: return Math.round(s * 32767); case Int8Array: return Math.round(s * 127); default: throw new Error("Invalid component type."); } } const ru = { DEG2RAD: Xs, RAD2DEG: xs, /** * Generate a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) * (universally unique identifier). * * @static * @method * @return {string} The UUID. */ generateUUID: xn, /** * Clamps the given value between min and max. * * @static * @method * @param {number} value - The value to clamp. * @param {number} min - The min value. * @param {number} max - The max value. * @return {number} The clamped value. */ clamp: Ve, /** * Computes the Euclidean modulo of the given parameters that * is `( ( n % m ) + m ) % m`. * * @static * @method * @param {number} n - The first parameter. * @param {number} m - The second parameter. * @return {number} The Euclidean modulo. */ euclideanModulo: wc, /** * Performs a linear mapping from range `<a1, a2>` to range `<b1, b2>` * for the given value. * * @static * @method * @param {number} x - The value to be mapped. * @param {number} a1 - Minimum value for range A. * @param {number} a2 - Maximum value for range A. * @param {number} b1 - Minimum value for range B. * @param {number} b2 - Maximum value for range B. * @return {number} The mapped value. */ mapLinear: Xd, /** * Returns the percentage in the closed interval `[0, 1]` of the given value * between the start and end point. * * @static * @method * @param {number} x - The start point * @param {number} y - The end point. * @param {number} value - A value between start and end. * @return {number} The interpolation factor. */ inverseLerp: Yd, /** * Returns a value linearly interpolated from two known points based on the given interval - * `t = 0` will return `x` and `t = 1` will return `y`. * * @static * @method * @param {number} x - The start point * @param {number} y - The end point. * @param {number} t - The interpolation factor in the closed interval `[0, 1]`. * @return {number} The interpolated value. */ lerp: Ys, /** * Smoothly interpolate a number from `x` to `y` in a spring-like manner using a delta * time to maintain frame rate independent movement. For details, see * [Frame rate independent damping using lerp](http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/). * * @static * @method * @param {number} x - The current point. * @param {number} y - The target point. * @param {number} lambda - A higher lambda value will make the movement more sudden, * and a lower value will make the movement more gradual. * @param {number} dt - Delta time in seconds. * @return {number} The interpolated value. */ damp: Kd, /** * Returns a value that alternates between `0` and the given `length` parameter. * * @static * @method * @param {number} x - The value to pingpong. * @param {number} [length=1] - The positive value the function will pingpong to. * @return {number} The alternated value. */ pingpong: jd, /** * Returns a value in the range `[0,1]` that represents the percentage that `x` has * moved between `min` and `max`, but smoothed or slowed down the closer `x` is to * the `min` and `max`. * * See [Smoothstep](http://en.wikipedia.org/wiki/Smoothstep) for more details. * * @static * @method * @param {number} x - The value to evaluate based on its position between min and max. * @param {number} min - The min value. Any x value below min will be `0`. * @param {number} max - The max value. Any x value above max will be `1`. * @return {number} The alternated value. */ smoothstep: Jd, /** * A [variation on smoothstep](https://en.wikipedia.org/wiki/Smoothstep#Variations) * that has zero 1st and 2nd order derivatives at x=0 and x=1. * * @static * @method * @param {number} x - The value to evaluate based on its position between min and max. * @param {number} min - The min value. Any x value below min will be `0`. * @param {number} max - The max value. Any x value above max will be `1`. * @return {number} The alternated value. */ smootherstep: Zd, /** * Returns a random integer from `<low, high>` interval. * * @static * @method * @param {number} low - The lower value boundary. * @param {number} high - The upper value boundary * @return {number} A random integer. */ randInt: $d, /** * Returns a random float from `<low, high>` interval. * * @static * @method * @param {number} low - The lower value boundary. * @param {number} high - The upper value boundary * @return {number} A random float. */ randFloat: ef, /** * Returns a random integer from `<-range/2, range/2>` interval. * * @static * @method * @param {number} range - Defines the value range. * @return {number} A random float. */ randFloatSpread: tf, /** * Returns a deterministic pseudo-random float in the interval `[0, 1]`. * * @static * @method * @param {number} [s] - The integer seed. * @return {number} A random float. */ seededRandom: nf, /** * Converts degrees to radians. * * @static * @method * @param {number} degrees - A value in degrees. * @return {number} The converted value in radians. */ degToRad: sf, /** * Converts radians to degrees. * * @static * @method * @param {number} radians - A value in radians. * @return {number} The converted value in degrees. */ radToDeg: rf, /** * Returns `true` if the given number is a power of two. * * @static * @method * @param {number} value - The value to check. * @return {boolean} Whether the given number is a power of two or not. */ isPowerOfTwo: af, /** * Returns the smallest power of two that is greater than or equal to the given number. * * @static * @method * @param {number} value - The value to find a POT for. * @return {number} The smallest power of two that is greater than or equal to the given number. */ ceilPowerOfTwo: of, /** * Returns the largest power of two that is less than or equal to the given number. * * @static * @method * @param {number} value - The value to find a POT for. * @return {number} The largest power of two that is less than or equal to the given number. */ floorPowerOfTwo: cf, /** * Sets the given quaternion from the [Intrinsic Proper Euler Angles](https://en.wikipedia.org/wiki/Euler_angles) * defined by the given angles and order. * * Rotations are applied to the axes in the order specified by order: * rotation by angle `a` is applied first, then by angle `b`, then by angle `c`. * * @static * @method * @param {Quaternion} q - The quaternion to set. * @param {number} a - The rotation applied to the first axis, in radians. * @param {number} b - The rotation applied to the second axis, in radians. * @param {number} c - The rotation applied to the third axis, in radians. * @param {('XYX'|'XZX'|'YXY'|'YZY'|'ZXZ'|'ZYZ')} order - A string specifying the axes order. */ setQuaternionFromProperEuler: lf, /** * Normalizes the given value according to the given typed array. * * @static * @method * @param {number} value - The float value in the range `[0,1]` to normalize. * @param {TypedArray} array - The typed array that defines the data type of the value. * @return {number} The normalize value. */ normalize: it, /** * Denormalizes the given value according to the given typed array. * * @static * @method * @param {number} value - The value to denormalize. * @param {TypedArray} array - The typed array that defines the data type of the value. * @return {number} The denormalize (float) value in the range `[0,1]`. */ denormalize: gn }; class We { /** * Constructs a new 2D vector. * * @param {number} [x=0] - The x value of this vector. * @param {number} [y=0] - The y value of this vector. */ constructor(e = 0, t = 0) { We.prototype.isVector2 = !0, this.x = e, this.y = t; } /** * Alias for {@link Vector2#x}. * * @type {number} */ get width() { return this.x; } set width(e) { this.x = e; } /** * Alias for {@link Vector2#y}. * * @type {number} */ get height() { return this.y; } set height(e) { this.y = e; } /** * Sets the vector components. * * @param {number} x - The value of the x component. * @param {number} y - The value of the y component. * @return {Vector2} A reference to this vector. */ set(e, t) { return this.x = e, this.y = t, this; } /** * Sets the vector components to the same value. * * @param {number} scalar - The value to set for all vector components. * @return {Vector2} A reference to this vector. */ setScalar(e) { return this.x = e, this.y = e, this; } /** * Sets the vector's x component to the given value * * @param {number} x - The value to set. * @return {Vector2} A reference to this vector. */ setX(e) { return this.x = e, this; } /** * Sets the vector's y component to the given value * * @param {number} y - The value to set. * @return {Vector2} A reference to this vector. */ setY(e) { return this.y = e, this; } /** * Allows to set a vector component with an index. * * @param {number} index - The component index. `0` equals to x, `1` equals to y. * @param {number} value - The value to set. * @return {Vector2} A reference to this vector. */ setComponent(e, t) { switch (e) { case 0: this.x = t; break; case 1: this.y = t; break; default: throw new Error("index is out of range: " + e); } return this; } /** * Returns the value of the vector component which matches the given index. * * @param {number} index - The component index. `0` equals to x, `1` equals to y. * @return {number} A vector component value. */ getComponent(e) { switch (e) { case 0: return this.x; case 1: return this.y; default: throw new Error("index is out of range: " + e); } } /** * Returns a new vector with copied values from this instance. * * @return {Vector2} A clone of this instance. */ clone() { return new this.constructor(this.x, this.y); } /** * Copies the values of the given vector to this instance. * * @param {Vector2} v - The vector to copy. * @return {Vector2} A reference to this vector. */ copy(e) { return this.x = e.x, this.y = e.y, this; } /** * Adds the given vector to this instance. * * @param {Vector2} v - The vector to add. * @return {Vector2} A reference to this vector. */ add(e) { return this.x += e.x, this.y += e.y, this; } /** * Adds the given scalar value to all components of this instance. * * @param {number} s - The scalar to add. * @return {Vector2} A reference to this vector. */ addScalar(e) { return this.x += e, this.y += e, this; } /** * Adds the given vectors and stores the result in this instance. * * @param {Vector2} a - The first vector. * @param {Vector2} b - The second vector. * @return {Vector2} A reference to this vector. */ addVectors(e, t) { return this.x = e.x + t.x, this.y = e.y + t.y, this; } /** * Adds the given vector scaled by the given factor to this instance. * * @param {Vector2} v - The vector. * @param {number} s - The factor that scales `v`. * @return {Vector2} A reference to this vector. */ addScaledVector(e, t) { return this.x += e.x * t, this.y += e.y * t, this; } /** * Subtracts the given vector from this instance. * * @param {Vector2} v - The vector to subtract. * @return {Vector2} A reference to this vector. */ sub(e) { return this.x -= e.x, this.y -= e.y, this; } /** * Subtracts the given scalar value from all components of this instance. * * @param {number} s - The scalar to subtract. * @return {Vector2} A reference to this vector. */ subScalar(e) { return this.x -= e, this.y -= e, this; } /** * Subtracts the given vectors and stores the result in this instance. * * @param {Vector2} a - The first vector. * @param {Vector2} b - The second vector. * @return {Vector2} A reference to this vector. */ subVectors(e, t) { return this.x = e.x - t.x, this.y = e.y - t.y, this; } /** * Multiplies the given vector with this instance. * * @param {Vector2} v - The vector to multiply. * @return {Vector2} A reference to this vector. */ multiply(e) { return this.x *= e.x, this.y *= e.y, this; } /** * Multiplies the given scalar value with all components of this instance. * * @param {number} scalar - The scalar to multiply. * @return {Vector2} A reference to this vector. */ multiplyScalar(e) { return this.x *= e, this.y *= e, this; } /** * Divides this instance by the given vector. * * @param {Vector2} v - The vector to divide. * @return {Vector2} A reference to this vector. */ divide(e) { return this.x /= e.x, this.y /= e.y, this; } /** * Divides this vector by the given scalar. * * @param {number} scalar - The scalar to divide. * @return {Vector2} A reference to this vector. */ divideScalar(e) { return this.multiplyScalar(1 / e); } /** * Multiplies this vector (with an implicit 1 as the 3rd component) by * the given 3x3 matrix. * * @param {Matrix3} m - The matrix to apply. * @return {Vector2} A reference to this vector. */ applyMatrix3(e) { const t = this.x, n = this.y, i = e.elements; return this.x = i[0] * t + i[3] * n + i[6], this.y = i[1] * t + i[4] * n + i[7], this; } /** * If this vector's x or y value is greater than the given vector's x or y * value, replace that value with the corresponding min value. * * @param {Vector2} v - The vector. * @return {Vector2} A reference to this vector. */ min(e) { return this.x = Math.min(this.x, e.x), this.y = Math.min(this.y, e.y), this; } /** * If this vector's x or y value is less than the given vector's x or y * value, replace that value with the corresponding max value. * * @param {Vector2} v - The vector. * @return {Vector2} A reference to this vector. */ max(e) { return this.x = Math.max(this.x, e.x), this.y = Math.max(this.y, e.y), this; } /** * If this vector's x or y value is greater than the max vector's x or y * value, it is replaced by the corresponding value. * If this vector's x or y value is less than the min vector's x or y value, * it is replaced by the corresponding value. * * @param {Vector2} min - The minimum x and y values. * @param {Vector2} max - The maximum x and y values in the desired range. * @return {Vector2} A reference to this vector. */ clamp(e, t) { return this.x = Ve(this.x, e.x, t.x), this.y = Ve(this.y, e.y, t.y), this; } /** * If this vector's x or y values are greater than the max value, they are * replaced by the max value. * If this vector's x or y values are less than the min value, they are * replaced by the min value. * * @param {number} minVal - The minimum value the components will be clamped to. * @param {number} maxVal - The maximum value the components will be clamped to. * @return {Vector2} A reference to this vector. */ clampScalar(e, t) { return this.x = Ve(this.x, e, t), this.y = Ve(this.y, e, t), this; } /** * If this vector's length is greater than the max value, it is replaced by * the max value. * If this vector's length is less than the min value, it is replaced by the * min value. * * @param {number} min - The minimum value the vector length will be clamped to. * @param {number} max - The maximum value the vector length will be clamped to. * @return {Vector2} A reference to this vector. */ clampLength(e, t) { const n = this.length(); return this.divideScalar(n || 1).multiplyScalar(Ve(n, e, t)); } /** * The components of this vector are rounded down to the nearest integer value. * * @return {Vector2} A reference to this vector. */ floor() { return this.x = Math.floor(this.x), this.y = Math.floor(this.y), this; } /** * The components of this vector are rounded up to the nearest integer value. * * @return {Vector2} A reference to this vector. */ ceil() { return this.x = Math.ceil(this.x), this.y = Math.ceil(this.y), this; } /** * The components of this vector are rounded to the nearest integer value * * @return {Vector2} A reference to this vector. */ round() { return this.x = Math.round(this.x), this.y = Math.round(this.y), this; } /** * The components of this vector are rounded towards zero (up if negative, * down if positive) to an integer value. * * @return {Vector2} A reference to this vector. */ roundToZero() { return this.x = Math.trunc(this.x), this.y = Math.trunc(this.y), this; } /** * Inverts this vector - i.e. sets x = -x and y = -y. * * @return {Vector2} A reference to this vector. */ negate() { return this.x = -this.x, this.y = -this.y, this; } /** * Calculates the dot product of the given vector with this instance. * * @param {Vector2} v - The vector to compute the dot product with. * @return {number} The result of the dot product. */ dot(e) { return this.x * e.x + this.y * e.y; } /** * Calculates the cross product of the given vector with this instance. * * @param {Vector2} v - The vector to compute the cross product with. * @return {number} The result of the cross product. */ cross(e) { return this.x * e.y - this.y * e.x; } /** * Computes the square of the Euclidean length (straight-line length) from * (0, 0) to (x, y). If you are comparing the lengths of vectors, you should * compare the length squared instead as it is slightly more efficient to calculate. * * @return {number} The square length of this vector. */ lengthSq() { return this.x * this.x + this.y * this.y; } /** * Computes the Euclidean length (straight-line length) from (0, 0) to (x, y). * * @return {number} The length of this vector. */ length() { return Math.sqrt(this.x * this.x + this.y * this.y); } /** * Computes the Manhattan length of this vector. * * @return {number} The length of this vector. */ manhattanLength() { return Math.abs(this.x) + Math.abs(this.y); } /** * Converts this vector to a unit vector - that is, sets it equal to a vector * with the same direction as this one, but with a vector length of `1`. * * @return {Vector2} A reference to this vector. */ normalize() { return this.divideScalar(this.length() || 1); } /** * Computes the angle in radians of this vector with respect to the positive x-axis. * * @return {number} The angle in radians. */ angle() { return Math.atan2(-this.y, -this.x) + Math.PI; } /** * Returns the angle between the given vector and this instance in radians. * * @param {Vector2} v - The vector to compute the angle with. * @return {number} The angle in radians. */ angleTo(e) { const t = Math.sqrt(this.lengthSq() * e.lengthSq()); if (t === 0) return Math.PI / 2; const n = this.dot(e) / t; return Math.acos(Ve(n, -1, 1)); } /** * Computes the distance from the given vector to this instance. * * @param {Vector2} v - The vector to compute the distance to. * @return {number} The distance. */ distanceTo(e) { return Math.sqrt(this.distanceToSquared(e)); } /** * Computes the squared distance from the given vector to this instance. * If you are just comparing the distance with another distance, you should compare * the distance squared instead as it is slightly more efficient to calculate. * * @param {Vector2} v - The vector to compute the squared distance to. * @return {number} The squared distance. */ distanceToSquared(e) { const t = this.x - e.x, n = this.y - e.y; return t * t + n * n; } /** * Computes the Manhattan distance from the given vector to this instance. * * @param {Vector2} v - The vector to compute the Manhattan distance to. * @return {number} The Manhattan distance. */ manhattanDistanceTo(e) { return Math.abs(this.x - e.x) + Math.abs(this.y - e.y); } /** * Sets this vector to a vector with the same direction as this one, but * with the specified length. * * @param {number} length - The new length of this vector. * @return {Vector2} A reference to this vector. */ setLength(e) { return this.normalize().multiplyScalar(e); } /** * Linearly interpolates between the given vector and this instance, where * alpha is the percent distance along the line - alpha = 0 will be this * vector, and alpha = 1 will be the given one. * * @param {Vector2} v - The vector to interpolate towards. * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`. * @return {Vector2} A reference to this vector. */ lerp(e, t) { return this.x += (e.x - this.x) * t, this.y += (e.y - this.y) * t, this; } /** * Linearly interpolates between the given vectors, where alpha is the percent * distance along the line - alpha = 0 will be first vector, and alpha = 1 will * be the second one. The result is stored in this instance. * * @param {Vector2} v1 - The first vector. * @param {Vector2} v2 - The second vector. * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`. * @return {Vector2} A reference to this vector. */ lerpVectors(e, t, n) { return this.x = e.x + (t.x - e.x) * n, this.y = e.y + (t.y - e.y) * n, this; } /** * Returns `true` if this vector is equal with the given one. * * @param {Vector2} v - The vector to test for equality. * @return {boolean} Whether this vector is equal with the given one. */ equals(e) { return e.x === this.x && e.y === this.y; } /** * Sets this vector's x value to be `array[ offset ]` and y * value to be `array[ offset + 1 ]`. * * @param {Array<number>} array - An array holding the vector component values. * @param {number} [offset=0] - The offset into the array. * @return {Vector2} A reference to this vector. */ fromArray(e, t = 0) { return this.x = e[t], this.y = e[t + 1], this; } /** * Writes the components of this vector to the given array. If no array is provided, * the method returns a new instance. * * @param {Array<number>} [array=[]] - The target array holding the vector components. * @param {number} [offset=0] - Index of the first element in the array. * @return {Array<number>} The vector components. */ toArray(e = [], t = 0) { return e[t] = this.x, e[t + 1] = this.y, e; } /** * Sets the components of this vector from the given buffer attribute. * * @param {BufferAttribute} attribute - The buffer attribute holding vector data. * @param {number} index - The index into the attribute. * @return {Vector2} A reference to this vector. */ fromBufferAttribute(e, t) { return this.x = e.getX(t), this.y = e.getY(t), this; } /** * Rotates this vector around the given center by the given angle. * * @param {Vector2} center - The point around which to rotate. * @param {number} angle - The angle to rotate, in radians. * @return {Vector2} A reference to this vector. */ rotateAround(e, t) { const n = Math.cos(t), i = Math.sin(t), r = this.x - e.x, a = this.y - e.y; return this.x = r * n - a * i + e.x, this.y = r * i + a * n + e.y, this; } /** * Sets each component of this vector to a pseudo-random value between `0` and * `1`, excluding `1`. * * @return {Vector2} A reference to this vector. */ random() { return this.x = Math.random(), this.y = Math.random(), this; } *[Symbol.iterator]() { yield this.x, yield this.y; } } class qn { /** * Constructs a new quaternion. * * @param {number} [x=0] - The x value of this quaternion. * @param {number} [y=0] - The y value of this quaternion. * @param {number} [z=0] - The z value of this quaternion. * @param {number} [w=1] - The w value of this quaternion. */ constructor(e = 0, t = 0, n = 0, i = 1) { this.isQuaternion = !0, this._x = e, this._y = t, this._z = n, this._w = i; } /** * Interpolates between two quaternions via SLERP. This implementation assumes the * quaternion data are managed in flat arrays. * * @param {Array<number>} dst - The destination array. * @param {number} dstOffset - An offset into the destination array. * @param {Array<number>} src0 - The source array of the first quaternion. * @param {number} srcOffset0 - An offset into the first source array. * @param {Array<number>} src1 - The source array of the second quaternion. * @param {number} srcOffset1 - An offset into the second source array. * @param {number} t - The interpolation factor in the range `[0,1]`. * @see {@link Quaternion#slerp} */ static slerpFlat(e, t, n, i, r, a, o) { let c = n[i + 0], l = n[i + 1], h = n[i + 2], u = n[i + 3], d = r[a + 0], A = r[a + 1], g = r[a + 2], m = r[a + 3]; if (o <= 0) { e[t + 0] = c, e[t + 1] = l, e[t + 2] = h, e[t + 3] = u; return; } if (o >= 1) { e[t + 0] = d, e[t + 1] = A, e[t + 2] = g, e[t + 3] = m; return; } if (u !== m || c !== d || l !== A || h !== g) { let p = c * d + l * A + h * g + u * m; p < 0 && (d = -d, A = -A, g = -g, m = -m, p = -p); let f = 1 - o; if (p < 0.9995) { const E = Math.acos(p), I = Math.sin(E); f = Math.sin(f * E) / I, o = Math.sin(o * E) / I, c = c * f + d * o, l = l * f + A * o, h = h * f + g * o, u = u * f + m * o; } else { c = c * f + d * o, l = l * f + A * o, h = h * f + g * o, u = u * f + m * o; const E = 1 / Math.sqrt(c * c + l * l + h * h + u * u); c *= E, l *= E, h *= E, u *= E; } } e[t] = c, e[t + 1] = l, e[t + 2] = h, e[t + 3] = u; } /** * Multiplies two quaternions. This implementation assumes the quaternion data are managed * in flat arrays. * * @param {Array<number>} dst - The destination array. * @param {number} dstOffset - An offset into the destination array. * @param {Array<number>} src0 - The source array of the first quaternion. * @param {number} srcOffset0 - An offset into the first source array. * @param {Array<number>} src1 - The source array of the second quaternion. * @param {number} srcOffset1 - An offset into the second source array. * @return {Array<number>} The destination array. * @see {@link Quaternion#multiplyQuaternions}. */ static multiplyQuaternionsFlat(e, t, n, i, r, a) { const o = n[i], c = n[i + 1], l = n[i + 2], h = n[i + 3], u = r[a], d = r[a + 1], A = r[a + 2], g = r[a + 3]; return e[t] = o * g + h * u + c * A - l * d, e[t + 1] = c * g + h * d + l * u - o * A, e[t + 2] = l * g + h * A + o * d - c * u, e[t + 3] = h * g - o * u - c * d - l * A, e; } /** * The x value of this quaternion. * * @type {number} * @default 0 */ get x() { return this._x; } set x(e) { this._x = e, this._onChangeCallback(); } /** * The y value of this quaternion. * * @type {number} * @default 0 */ get y() { return this._y; } set y(e) { this._y = e, this._onChangeCallback(); } /** * The z value of this quaternion. * * @type {number} * @default 0 */ get z() { return this._z; } set z(e) { this._z = e, this._onChangeCallback(); } /** * The w value of this quaternion. * * @type {number} * @default 1 */ get w() { return this._w; } set w(e) { this._w = e, this._onChangeCallback(); } /** * Sets the quaternion components. * * @param {number} x - The x value of this quaternion. * @param {number} y - The y value of this quaternion. * @param {number} z - The z value of this quaternion. * @param {number} w - The w value of this quaternion. * @return {Quaternion} A reference to this quaternion. */ set(e, t, n, i) { return this._x = e, this._y = t, this._z = n, this._w = i, this._onChangeCallback(), this; } /** * Returns a new quaternion with copied values from this instance. * * @return {Quaternion} A clone of this instance. */ clone() { return new this.constructor(this._x, this._y, this._z, this._w); } /** * Copies the values of the given quaternion to this instance. * * @param {Quaternion} quaternion - The quaternion to copy. * @return {Quaternion} A reference to this quaternion. */ copy(e) { return this._x = e.x, this._y = e.y, this._z = e.z, this._w = e.w, this._onChangeCallback(), this; } /** * Sets this quaternion from the rotation specified by the given * Euler angles. * * @param {Euler} euler - The Euler angles. * @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not. * @return {Quaternion} A reference to this quaternion. */ setFromEuler(e, t = !0) { const n = e._x, i = e._y, r = e._z, a = e._order, o = Math.cos, c = Math.sin, l = o(n / 2), h = o(i / 2), u = o(r / 2), d = c(n / 2), A = c(i / 2), g = c(r / 2); switch (a) { case "XYZ": this._x = d * h * u + l * A * g, this._y = l * A * u - d * h * g, this._z = l * h * g + d * A * u, this._w = l * h * u - d * A * g; break; case "YXZ": this._x = d * h * u + l * A * g, this._y = l * A * u - d * h * g, this._z = l * h * g - d * A * u, this._w = l * h * u + d * A * g; break; case "ZXY": this._x = d * h * u - l * A * g, this._y = l * A * u + d * h * g, this._z = l * h * g + d * A * u, this._w = l * h * u - d * A * g; break; case "ZYX": this._x = d * h * u - l * A * g, this._y = l * A * u + d * h * g, this._z = l * h * g - d * A * u, this._w = l * h * u + d * A * g; break; case "YZX": this._x = d * h * u + l * A * g, this._y = l * A * u + d * h * g, this._z = l * h * g - d * A * u, this._w = l * h * u - d * A * g; break; case "XZY": this._x = d * h * u - l * A * g, this._y = l * A * u - d * h * g, this._z = l * h * g + d * A * u, this._w = l * h * u + d * A * g; break; default: Se("Quaternion: .setFromEuler() encountered an unknown order: " + a); } return t === !0 && this._onChangeCallback(), this; } /** * Sets this quaternion from the given axis and angle. * * @param {Vector3} axis - The normalized axis. * @param {number} angle - The angle in radians. * @return {Quaternion} A reference to this quaternion. */ setFromAxisAngle(e, t) { const n = t / 2, i = Math.sin(n); return this._x = e.x * i, this._y = e.y * i, this._z = e.z * i, this._w = Math.cos(n), this._onChangeCallback(), this; } /** * Sets this quaternion from the given rotation matrix. * * @param {Matrix4} m - A 4x4 matrix of which the upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled). * @return {Quaternion} A reference to this quaternion. */ setFromRotationMatrix(e) { const t = e.elements, n = t[0], i = t[4], r = t[8], a = t[1], o = t[5], c = t[9], l = t[2], h = t[6], u = t[10], d = n + o + u; if (d > 0) { const A = 0.5 / Math.sqrt(d + 1); this._w = 0.25 / A, this._x = (h - c) * A, this._y = (r - l) * A, this._z = (a - i) * A; } else if (n > o && n > u) { const A = 2 * Math.sqrt(1 + n - o - u); this._w = (h - c) / A, this._x = 0.25 * A, this._y = (i + a) / A, this._z = (r + l) / A; } else if (o > u) { const A = 2 * Math.sqrt(1 + o - n - u); this._w = (r - l) / A, this._x = (i + a) / A, this._y = 0.25 * A, this._z = (c + h) / A; } else { const A = 2 * Math.sqrt(1 + u - n - o); this._w = (a - i) / A, this._x = (r + l) / A, this._y = (c + h) / A, this._z = 0.25 * A; } return this._onChangeCallback(), this; } /** * Sets this quaternion to the rotation required to rotate the direction vector * `vFrom` to the direction vector `vTo`. * * @param {Vector3} vFrom - The first (normalized) direction vector. * @param {Vector3} vTo - The second (normalized) direction vector. * @return {Quaternion} A reference to this quaternion. */ setFromUnitVectors(e, t) { let n = e.dot(t) + 1; return n < 1e-8 ? (n = 0, Math.abs(e.x) > Math.abs(e.z) ? (this._x = -e.y, this._y = e.x, this._z = 0, this._w = n) : (this._x = 0, this._y = -e.z, this._z = e.y, this._w = n)) : (this._x = e.y * t.z - e.z * t.y, this._y = e.z * t.x - e.x * t.z, this._z = e.x * t.y - e.y * t.x, this._w = n), this.normalize(); } /** * Returns the angle between this quaternion and the given one in radians. * * @param {Quaternion} q - The quaternion to compute the angle with. * @return {number} The angle in radians. */ angleTo(e) { return 2 * Math.acos(Math.abs(Ve(this.dot(e), -1, 1))); } /** * Rotates this quaternion by a given angular step to the given quaternion. * The method ensures that the final quaternion will not overshoot `q`. * * @param {Quaternion} q - The target quaternion. * @param {number} step - The angular step in radians. * @return {Quaternion} A reference to this quaternion. */ rotateTowards(e, t) { const n = this.angleTo(e); if (n === 0) return this; const i = Math.min(1, t / n); return this.slerp(e, i), this; } /** * Sets this quaternion to the identity quaternion; that is, to the * quaternion that represents "no rotation". * * @return {Quaternion} A reference to this quaternion. */ identity() { return this.set(0, 0, 0, 1); } /** * Inverts this quaternion via {@link Quaternion#conjugate}. The * quaternion is assumed to have unit length. * * @return {Quaternion} A reference to this quaternion. */ invert() { return this.conjugate(); } /** * Returns the rotational conjugate of this quaternion. The conjugate of a * quaternion represents the same rotation in the opposite direction about * the rotational axis. * * @return {Quaternion} A reference to this quaternion. */ conjugate() { return this._x *= -1, this._y *= -1, this._z *= -1, this._onChangeCallback(), this; } /** * Calculates the dot product of this quaternion and the given one. * * @param {Quaternion} v - The quaternion to compute the dot product with. * @return {number} The result of the dot product. */ dot(e) { return this._x * e._x + this._y * e._y + this._z * e._z + this._w * e._w; } /** * Computes the squared Euclidean length (straight-line length) of this quaternion, * considered as a 4 dimensional vector. This can be useful if you are comparing the * lengths of two quaternions, as this is a slightly more efficient calculation than * {@link Quaternion#length}. * * @return {number} The squared Euclidean length. */ lengthSq() { return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; } /** * Computes the Euclidean length (straight-line length) of this quaternion, * considered as a 4 dimensional vector. * * @return {number} The Euclidean length. */ length() { return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w); } /** * Normalizes this quaternion - that is, calculated the quaternion that performs * the same rotation as this one, but has a length equal to `1`. * * @return {Quaternion} A reference to this quaternion. */ normalize() { let e = this.length(); return e === 0 ? (this._x = 0, this._y = 0, this._z = 0, this._w = 1) : (e = 1 / e, this._x = this._x * e, this._y = this._y * e, this._z = this._z * e, this._w = this._w * e), this._onChangeCallback(), this; } /** * Multiplies this quaternion by the given one. * * @param {Quaternion} q - The quaternion. * @return {Quaternion} A reference to this quaternion. */ multiply(e) { return this.multiplyQuaternions(this, e); } /** * Pre-multiplies this quaternion by the given one. * * @param {Quaternion} q - The quaternion. * @return {Quaternion} A reference to this quaternion. */ premultiply(e) { return this.multiplyQuaternions(e, this); } /** * Multiplies the given quaternions and stores the result in this instance. * * @param {Quaternion} a - The first quaternion. * @param {Quaternion} b - The second quaternion. * @return {Quaternion} A reference to this quaternion. */ multiplyQuaternions(e, t) { const n = e._x, i = e._y, r = e._z, a = e._w, o = t._x, c = t._y, l = t._z, h = t._w; return this._x = n * h + a * o + i * l - r * c, this._y = i * h + a * c + r * o - n * l, this._z = r * h + a * l + n * c - i * o, this._w = a * h - n * o - i * c - r * l, this._onChangeCallback(), this; } /** * Performs a spherical linear interpolation between quaternions. * * @param {Quaternion} qb - The target quaternion. * @param {number} t - The interpolation factor in the closed interval `[0, 1]`. * @return {Quaternion} A reference to this quaternion. */ slerp(e, t) { if (t <= 0) return this; if (t >= 1) return this.copy(e); let n = e._x, i = e._y, r = e._z, a = e._w, o = this.dot(e); o < 0 && (n = -n, i = -i, r = -r, a = -a, o = -o); let c = 1 - t; if (o < 0.9995) { const l = Math.acos(o), h = Math.sin(l); c = Math.sin(c * l) / h, t = Math.sin(t * l) / h, this._x = this._x * c + n * t, this._y = this._y * c + i * t, this._z = this._z * c + r * t, this._w = this._w * c + a * t, this._onChangeCallback(); } else this._x = this._x * c + n * t, this._y = this._y * c + i * t, this._z = this._z * c + r * t, this._w = this._w * c + a * t, this.normalize(); return this; } /** * Performs a spherical linear interpolation between the given quaternions * and stores the result in this quaternion. * * @param {Quaternion} qa - The source quaternion. * @param {Quaternion} qb - The target quaternion. * @param {number} t - The interpolation factor in the closed interval `[0, 1]`. * @return {Quaternion} A reference to this quaternion. */ slerpQuaternions(e, t, n) { return this.copy(e).slerp(t, n); } /** * Sets this quaternion to a uniformly random, normalized quaternion. * * @return {Quaternion} A reference to this quaternion. */ random() { const e = 2 * Math.PI * Math.random(), t = 2 * Math.PI * Math.random(), n = Math.random(), i = Math.sqrt(1 - n), r = Math.sqrt(n); return this.set( i * Math.sin(e), i * Math.cos(e), r * Math.sin(t), r * Math.cos(t) ); } /** * Returns `true` if this quaternion is equal with the given one. * * @param {Quaternion} quaternion - The quaternion to test for equality. * @return {boolean} Whether this quaternion is equal with the given one. */ equals(e) { return e._x === this._x && e._y === this._y && e._z === this._z && e._w === this._w; } /** * Sets this quaternion's components from the given array. * * @param {Array<number>} array - An array holding the quaternion component values. * @param {number} [offset=0] - The offset into the array. * @return {Quaternion} A reference to this quaternion. */ fromArray(e, t = 0) { return this._x = e[t], this._y = e[t + 1], this._z = e[t + 2], this._w = e[t + 3], this._onChangeCallback(), this; } /** * Writes the components of this quaternion to the gi