var GSPLAT = (() => { var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // gsplat-entry.js var gsplat_entry_exports = {}; __export(gsplat_entry_exports, { Camera: () => wt, CameraData: () => Rt, Color32: () => dt, FPSControls: () => Gt, FadeInPass: () => Nt, IntersectionTester: () => Kt, Loader: () => Tt, Matrix3: () => _, Matrix4: () => K, Object3D: () => st, OrbitControls: () => Lt, PLYLoader: () => bt, Plane: () => vt, Quaternion: () => y, RenderData: () => Ut, RenderProgram: () => Ct, Scene: () => kt, ShaderPass: () => _t, ShaderProgram: () => lt, Splat: () => X, SplatData: () => Y, Splatv: () => tt, SplatvData: () => ot, SplatvLoader: () => xt, Vector3: () => R, Vector4: () => z, VideoRenderProgram: () => Yt, WebGLRenderer: () => Mt }); // node_modules/gsplat/dist/index.es.js var import_meta = {}; var R = class _R { constructor(t = 0, n = 0, i = 0) { this.x = t, this.y = n, this.z = i; } equals(t) { return !(this.x !== t.x || this.y !== t.y || this.z !== t.z); } add(t) { return typeof t == "number" ? new _R(this.x + t, this.y + t, this.z + t) : new _R(this.x + t.x, this.y + t.y, this.z + t.z); } subtract(t) { return typeof t == "number" ? new _R(this.x - t, this.y - t, this.z - t) : new _R(this.x - t.x, this.y - t.y, this.z - t.z); } multiply(t) { return typeof t == "number" ? new _R(this.x * t, this.y * t, this.z * t) : t instanceof _R ? new _R(this.x * t.x, this.y * t.y, this.z * t.z) : new _R( this.x * t.buffer[0] + this.y * t.buffer[4] + this.z * t.buffer[8] + t.buffer[12], this.x * t.buffer[1] + this.y * t.buffer[5] + this.z * t.buffer[9] + t.buffer[13], this.x * t.buffer[2] + this.y * t.buffer[6] + this.z * t.buffer[10] + t.buffer[14] ); } divide(t) { return typeof t == "number" ? new _R(this.x / t, this.y / t, this.z / t) : new _R(this.x / t.x, this.y / t.y, this.z / t.z); } cross(t) { const n = this.y * t.z - this.z * t.y, i = this.z * t.x - this.x * t.z, e = this.x * t.y - this.y * t.x; return new _R(n, i, e); } dot(t) { return this.x * t.x + this.y * t.y + this.z * t.z; } lerp(t, n) { return new _R(this.x + (t.x - this.x) * n, this.y + (t.y - this.y) * n, this.z + (t.z - this.z) * n); } min(t) { return new _R(Math.min(this.x, t.x), Math.min(this.y, t.y), Math.min(this.z, t.z)); } max(t) { return new _R(Math.max(this.x, t.x), Math.max(this.y, t.y), Math.max(this.z, t.z)); } getComponent(t) { switch (t) { case 0: return this.x; case 1: return this.y; case 2: return this.z; default: throw new Error(`Invalid component index: ${t}`); } } minComponent() { return this.x < this.y && this.x < this.z ? 0 : this.y < this.z ? 1 : 2; } maxComponent() { return this.x > this.y && this.x > this.z ? 0 : this.y > this.z ? 1 : 2; } magnitude() { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); } distanceTo(t) { return Math.sqrt((this.x - t.x) ** 2 + (this.y - t.y) ** 2 + (this.z - t.z) ** 2); } normalize() { const t = this.magnitude(); return new _R(this.x / t, this.y / t, this.z / t); } flat() { return [this.x, this.y, this.z]; } clone() { return new _R(this.x, this.y, this.z); } toString() { return `[${this.flat().join(", ")}]`; } static One(t = 1) { return new _R(t, t, t); } }; var y = class _y { constructor(t = 0, n = 0, i = 0, e = 1) { this.x = t, this.y = n, this.z = i, this.w = e; } equals(t) { return !(this.x !== t.x || this.y !== t.y || this.z !== t.z || this.w !== t.w); } normalize() { const t = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w); return new _y(this.x / t, this.y / t, this.z / t, this.w / t); } multiply(t) { const n = this.w, i = this.x, e = this.y, A = this.z, o = t.w, s = t.x, r = t.y, Q = t.z; return new _y( n * s + i * o + e * Q - A * r, n * r - i * Q + e * o + A * s, n * Q + i * r - e * s + A * o, n * o - i * s - e * r - A * Q ); } inverse() { const t = this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; return new _y(-this.x / t, -this.y / t, -this.z / t, this.w / t); } apply(t) { const n = new _y(t.x, t.y, t.z, 0), i = new _y(-this.x, -this.y, -this.z, this.w), e = this.multiply(n).multiply(i); return new R(e.x, e.y, e.z); } flat() { return [this.x, this.y, this.z, this.w]; } clone() { return new _y(this.x, this.y, this.z, this.w); } static FromEuler(t) { const n = t.x / 2, i = t.y / 2, e = t.z / 2, A = Math.cos(i), o = Math.sin(i), s = Math.cos(n), r = Math.sin(n), Q = Math.cos(e), I = Math.sin(e); return new _y( A * r * Q + o * s * I, o * s * Q - A * r * I, A * s * I - o * r * Q, A * s * Q + o * r * I ); } toEuler() { const t = 2 * (this.w * this.x + this.y * this.z), n = 1 - 2 * (this.x * this.x + this.y * this.y), i = Math.atan2(t, n); let e; const A = 2 * (this.w * this.y - this.z * this.x); Math.abs(A) >= 1 ? e = Math.sign(A) * Math.PI / 2 : e = Math.asin(A); const o = 2 * (this.w * this.z + this.x * this.y), s = 1 - 2 * (this.y * this.y + this.z * this.z), r = Math.atan2(o, s); return new R(i, e, r); } static FromMatrix3(t) { const n = t.buffer, i = n[0] + n[4] + n[8]; let e, A, o, s; if (i > 0) { const r = 0.5 / Math.sqrt(i + 1); s = 0.25 / r, e = (n[7] - n[5]) * r, A = (n[2] - n[6]) * r, o = (n[3] - n[1]) * r; } else if (n[0] > n[4] && n[0] > n[8]) { const r = 2 * Math.sqrt(1 + n[0] - n[4] - n[8]); s = (n[7] - n[5]) / r, e = 0.25 * r, A = (n[1] + n[3]) / r, o = (n[2] + n[6]) / r; } else if (n[4] > n[8]) { const r = 2 * Math.sqrt(1 + n[4] - n[0] - n[8]); s = (n[2] - n[6]) / r, e = (n[1] + n[3]) / r, A = 0.25 * r, o = (n[5] + n[7]) / r; } else { const r = 2 * Math.sqrt(1 + n[8] - n[0] - n[4]); s = (n[3] - n[1]) / r, e = (n[2] + n[6]) / r, A = (n[5] + n[7]) / r, o = 0.25 * r; } return new _y(e, A, o, s); } static FromAxisAngle(t, n) { const i = n / 2, e = Math.sin(i), A = Math.cos(i); return new _y(t.x * e, t.y * e, t.z * e, A); } static LookRotation(t) { const n = new R(0, 0, 1), i = n.dot(t); if (Math.abs(i - -1) < 1e-6) return new _y(0, 1, 0, Math.PI); if (Math.abs(i - 1) < 1e-6) return new _y(); const e = Math.acos(i), A = n.cross(t).normalize(); return _y.FromAxisAngle(A, e); } toString() { return `[${this.flat().join(", ")}]`; } }; var Ft = class { constructor() { const t = /* @__PURE__ */ new Map(); this.addEventListener = (n, i) => { t.has(n) || t.set(n, /* @__PURE__ */ new Set()), t.get(n).add(i); }, this.removeEventListener = (n, i) => { t.has(n) && t.get(n).delete(i); }, this.hasEventListener = (n, i) => t.has(n) ? t.get(n).has(i) : false, this.dispatchEvent = (n) => { if (t.has(n.type)) for (const i of t.get(n.type)) i(n); }; } }; var K = class _K { // prettier-ignore constructor(t = 1, n = 0, i = 0, e = 0, A = 0, o = 1, s = 0, r = 0, Q = 0, I = 0, d = 1, a = 0, U = 0, F = 0, g = 0, B = 1) { this.buffer = [ t, n, i, e, A, o, s, r, Q, I, d, a, U, F, g, B ]; } equals(t) { if (this.buffer.length !== t.buffer.length) return false; if (this.buffer === t.buffer) return true; for (let n = 0; n < this.buffer.length; n++) if (this.buffer[n] !== t.buffer[n]) return false; return true; } multiply(t) { const n = this.buffer, i = t.buffer; return new _K( i[0] * n[0] + i[1] * n[4] + i[2] * n[8] + i[3] * n[12], i[0] * n[1] + i[1] * n[5] + i[2] * n[9] + i[3] * n[13], i[0] * n[2] + i[1] * n[6] + i[2] * n[10] + i[3] * n[14], i[0] * n[3] + i[1] * n[7] + i[2] * n[11] + i[3] * n[15], i[4] * n[0] + i[5] * n[4] + i[6] * n[8] + i[7] * n[12], i[4] * n[1] + i[5] * n[5] + i[6] * n[9] + i[7] * n[13], i[4] * n[2] + i[5] * n[6] + i[6] * n[10] + i[7] * n[14], i[4] * n[3] + i[5] * n[7] + i[6] * n[11] + i[7] * n[15], i[8] * n[0] + i[9] * n[4] + i[10] * n[8] + i[11] * n[12], i[8] * n[1] + i[9] * n[5] + i[10] * n[9] + i[11] * n[13], i[8] * n[2] + i[9] * n[6] + i[10] * n[10] + i[11] * n[14], i[8] * n[3] + i[9] * n[7] + i[10] * n[11] + i[11] * n[15], i[12] * n[0] + i[13] * n[4] + i[14] * n[8] + i[15] * n[12], i[12] * n[1] + i[13] * n[5] + i[14] * n[9] + i[15] * n[13], i[12] * n[2] + i[13] * n[6] + i[14] * n[10] + i[15] * n[14], i[12] * n[3] + i[13] * n[7] + i[14] * n[11] + i[15] * n[15] ); } clone() { const t = this.buffer; return new _K( t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15] ); } determinant() { const t = this.buffer; return t[12] * t[9] * t[6] * t[3] - t[8] * t[13] * t[6] * t[3] - t[12] * t[5] * t[10] * t[3] + t[4] * t[13] * t[10] * t[3] + t[8] * t[5] * t[14] * t[3] - t[4] * t[9] * t[14] * t[3] - t[12] * t[9] * t[2] * t[7] + t[8] * t[13] * t[2] * t[7] + t[12] * t[1] * t[10] * t[7] - t[0] * t[13] * t[10] * t[7] - t[8] * t[1] * t[14] * t[7] + t[0] * t[9] * t[14] * t[7] + t[12] * t[5] * t[2] * t[11] - t[4] * t[13] * t[2] * t[11] - t[12] * t[1] * t[6] * t[11] + t[0] * t[13] * t[6] * t[11] + t[4] * t[1] * t[14] * t[11] - t[0] * t[5] * t[14] * t[11] - t[8] * t[5] * t[2] * t[15] + t[4] * t[9] * t[2] * t[15] + t[8] * t[1] * t[6] * t[15] - t[0] * t[9] * t[6] * t[15] - t[4] * t[1] * t[10] * t[15] + t[0] * t[5] * t[10] * t[15]; } invert() { const t = this.buffer, n = this.determinant(); if (n === 0) throw new Error("Matrix is not invertible."); const i = 1 / n; return new _K( i * (t[5] * t[10] * t[15] - t[5] * t[11] * t[14] - t[9] * t[6] * t[15] + t[9] * t[7] * t[14] + t[13] * t[6] * t[11] - t[13] * t[7] * t[10]), i * (-t[1] * t[10] * t[15] + t[1] * t[11] * t[14] + t[9] * t[2] * t[15] - t[9] * t[3] * t[14] - t[13] * t[2] * t[11] + t[13] * t[3] * t[10]), i * (t[1] * t[6] * t[15] - t[1] * t[7] * t[14] - t[5] * t[2] * t[15] + t[5] * t[3] * t[14] + t[13] * t[2] * t[7] - t[13] * t[3] * t[6]), i * (-t[1] * t[6] * t[11] + t[1] * t[7] * t[10] + t[5] * t[2] * t[11] - t[5] * t[3] * t[10] - t[9] * t[2] * t[7] + t[9] * t[3] * t[6]), i * (-t[4] * t[10] * t[15] + t[4] * t[11] * t[14] + t[8] * t[6] * t[15] - t[8] * t[7] * t[14] - t[12] * t[6] * t[11] + t[12] * t[7] * t[10]), i * (t[0] * t[10] * t[15] - t[0] * t[11] * t[14] - t[8] * t[2] * t[15] + t[8] * t[3] * t[14] + t[12] * t[2] * t[11] - t[12] * t[3] * t[10]), i * (-t[0] * t[6] * t[15] + t[0] * t[7] * t[14] + t[4] * t[2] * t[15] - t[4] * t[3] * t[14] - t[12] * t[2] * t[7] + t[12] * t[3] * t[6]), i * (t[0] * t[6] * t[11] - t[0] * t[7] * t[10] - t[4] * t[2] * t[11] + t[4] * t[3] * t[10] + t[8] * t[2] * t[7] - t[8] * t[3] * t[6]), i * (t[4] * t[9] * t[15] - t[4] * t[11] * t[13] - t[8] * t[5] * t[15] + t[8] * t[7] * t[13] + t[12] * t[5] * t[11] - t[12] * t[7] * t[9]), i * (-t[0] * t[9] * t[15] + t[0] * t[11] * t[13] + t[8] * t[1] * t[15] - t[8] * t[3] * t[13] - t[12] * t[1] * t[11] + t[12] * t[3] * t[9]), i * (t[0] * t[5] * t[15] - t[0] * t[7] * t[13] - t[4] * t[1] * t[15] + t[4] * t[3] * t[13] + t[12] * t[1] * t[7] - t[12] * t[3] * t[5]), i * (-t[0] * t[5] * t[11] + t[0] * t[7] * t[9] + t[4] * t[1] * t[11] - t[4] * t[3] * t[9] - t[8] * t[1] * t[7] + t[8] * t[3] * t[5]), i * (-t[4] * t[9] * t[14] + t[4] * t[10] * t[13] + t[8] * t[5] * t[14] - t[8] * t[6] * t[13] - t[12] * t[5] * t[10] + t[12] * t[6] * t[9]), i * (t[0] * t[9] * t[14] - t[0] * t[10] * t[13] - t[8] * t[1] * t[14] + t[8] * t[2] * t[13] + t[12] * t[1] * t[10] - t[12] * t[2] * t[9]), i * (-t[0] * t[5] * t[14] + t[0] * t[6] * t[13] + t[4] * t[1] * t[14] - t[4] * t[2] * t[13] - t[12] * t[1] * t[6] + t[12] * t[2] * t[5]), i * (t[0] * t[5] * t[10] - t[0] * t[6] * t[9] - t[4] * t[1] * t[10] + t[4] * t[2] * t[9] + t[8] * t[1] * t[6] - t[8] * t[2] * t[5]) ); } static Compose(t, n, i) { const e = n.x, A = n.y, o = n.z, s = n.w, r = e + e, Q = A + A, I = o + o, d = e * r, a = e * Q, U = e * I, F = A * Q, g = A * I, B = o * I, C = s * r, c = s * Q, p = s * I, u = i.x, S = i.y, W = i.z; return new _K( (1 - (F + B)) * u, (a + p) * u, (U - c) * u, 0, (a - p) * S, (1 - (d + B)) * S, (g + C) * S, 0, (U + c) * W, (g - C) * W, (1 - (d + F)) * W, 0, t.x, t.y, t.z, 1 ); } toString() { return `[${this.buffer.join(", ")}]`; } }; var It = class extends Event { constructor(t) { super("objectAdded"), this.object = t; } }; var ht = class extends Event { constructor(t) { super("objectRemoved"), this.object = t; } }; var ct = class extends Event { constructor(t) { super("objectChanged"), this.object = t; } }; var st = class extends Ft { constructor() { super(), this.positionChanged = false, this.rotationChanged = false, this.scaleChanged = false, this._position = new R(), this._rotation = new y(), this._scale = new R(1, 1, 1), this._transform = new K(), this._changeEvent = new ct(this), this.update = () => { }, this.applyPosition = () => { this.position = new R(); }, this.applyRotation = () => { this.rotation = new y(); }, this.applyScale = () => { this.scale = new R(1, 1, 1); }, this.raiseChangeEvent = () => { this.dispatchEvent(this._changeEvent); }; } _updateMatrix() { this._transform = K.Compose(this._position, this._rotation, this._scale); } get position() { return this._position; } set position(t) { this._position.equals(t) || (this._position = t, this.positionChanged = true, this._updateMatrix(), this.dispatchEvent(this._changeEvent)); } get rotation() { return this._rotation; } set rotation(t) { this._rotation.equals(t) || (this._rotation = t, this.rotationChanged = true, this._updateMatrix(), this.dispatchEvent(this._changeEvent)); } get scale() { return this._scale; } set scale(t) { this._scale.equals(t) || (this._scale = t, this.scaleChanged = true, this._updateMatrix(), this.dispatchEvent(this._changeEvent)); } get forward() { let t = new R(0, 0, 1); return t = this.rotation.apply(t), t; } get transform() { return this._transform; } }; var _ = class __ { // prettier-ignore constructor(t = 1, n = 0, i = 0, e = 0, A = 1, o = 0, s = 0, r = 0, Q = 1) { this.buffer = [ t, n, i, e, A, o, s, r, Q ]; } equals(t) { if (this.buffer.length !== t.buffer.length) return false; if (this.buffer === t.buffer) return true; for (let n = 0; n < this.buffer.length; n++) if (this.buffer[n] !== t.buffer[n]) return false; return true; } multiply(t) { const n = this.buffer, i = t.buffer; return new __( i[0] * n[0] + i[3] * n[1] + i[6] * n[2], i[1] * n[0] + i[4] * n[1] + i[7] * n[2], i[2] * n[0] + i[5] * n[1] + i[8] * n[2], i[0] * n[3] + i[3] * n[4] + i[6] * n[5], i[1] * n[3] + i[4] * n[4] + i[7] * n[5], i[2] * n[3] + i[5] * n[4] + i[8] * n[5], i[0] * n[6] + i[3] * n[7] + i[6] * n[8], i[1] * n[6] + i[4] * n[7] + i[7] * n[8], i[2] * n[6] + i[5] * n[7] + i[8] * n[8] ); } clone() { const t = this.buffer; return new __( t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8] ); } static Eye(t = 1) { return new __(t, 0, 0, 0, t, 0, 0, 0, t); } static Diagonal(t) { return new __(t.x, 0, 0, 0, t.y, 0, 0, 0, t.z); } static RotationFromQuaternion(t) { return new __( 1 - 2 * t.y * t.y - 2 * t.z * t.z, 2 * t.x * t.y - 2 * t.z * t.w, 2 * t.x * t.z + 2 * t.y * t.w, 2 * t.x * t.y + 2 * t.z * t.w, 1 - 2 * t.x * t.x - 2 * t.z * t.z, 2 * t.y * t.z - 2 * t.x * t.w, 2 * t.x * t.z - 2 * t.y * t.w, 2 * t.y * t.z + 2 * t.x * t.w, 1 - 2 * t.x * t.x - 2 * t.y * t.y ); } static RotationFromEuler(t) { const n = Math.cos(t.x), i = Math.sin(t.x), e = Math.cos(t.y), A = Math.sin(t.y), o = Math.cos(t.z), s = Math.sin(t.z), r = [ e * o + A * i * s, -e * s + A * i * o, A * n, n * s, n * o, -i, -A * o + e * i * s, A * s + e * i * o, e * n ]; return new __(...r); } toString() { return `[${this.buffer.join(", ")}]`; } }; var _Y = class _Y { constructor(t = 0, n = null, i = null, e = null, A = null) { this.changed = false, this.detached = false, this._vertexCount = t, this._positions = n || new Float32Array(0), this._rotations = i || new Float32Array(0), this._scales = e || new Float32Array(0), this._colors = A || new Uint8Array(0), this._selection = new Uint8Array(this.vertexCount), this.translate = (o) => { for (let s = 0; s < this.vertexCount; s++) this.positions[3 * s + 0] += o.x, this.positions[3 * s + 1] += o.y, this.positions[3 * s + 2] += o.z; this.changed = true; }, this.rotate = (o) => { const s = _.RotationFromQuaternion(o).buffer; for (let r = 0; r < this.vertexCount; r++) { const Q = this.positions[3 * r + 0], I = this.positions[3 * r + 1], d = this.positions[3 * r + 2]; this.positions[3 * r + 0] = s[0] * Q + s[1] * I + s[2] * d, this.positions[3 * r + 1] = s[3] * Q + s[4] * I + s[5] * d, this.positions[3 * r + 2] = s[6] * Q + s[7] * I + s[8] * d; const a = new y( this.rotations[4 * r + 1], this.rotations[4 * r + 2], this.rotations[4 * r + 3], this.rotations[4 * r + 0] ), U = o.multiply(a); this.rotations[4 * r + 1] = U.x, this.rotations[4 * r + 2] = U.y, this.rotations[4 * r + 3] = U.z, this.rotations[4 * r + 0] = U.w; } this.changed = true; }, this.scale = (o) => { for (let s = 0; s < this.vertexCount; s++) this.positions[3 * s + 0] *= o.x, this.positions[3 * s + 1] *= o.y, this.positions[3 * s + 2] *= o.z, this.scales[3 * s + 0] *= o.x, this.scales[3 * s + 1] *= o.y, this.scales[3 * s + 2] *= o.z; this.changed = true; }, this.serialize = () => { const o = new Uint8Array(this.vertexCount * _Y.RowLength), s = new Float32Array(o.buffer), r = new Uint8Array(o.buffer); for (let Q = 0; Q < this.vertexCount; Q++) s[8 * Q + 0] = this.positions[3 * Q + 0], s[8 * Q + 1] = this.positions[3 * Q + 1], s[8 * Q + 2] = this.positions[3 * Q + 2], r[32 * Q + 24 + 0] = this.colors[4 * Q + 0], r[32 * Q + 24 + 1] = this.colors[4 * Q + 1], r[32 * Q + 24 + 2] = this.colors[4 * Q + 2], r[32 * Q + 24 + 3] = this.colors[4 * Q + 3], s[8 * Q + 3 + 0] = this.scales[3 * Q + 0], s[8 * Q + 3 + 1] = this.scales[3 * Q + 1], s[8 * Q + 3 + 2] = this.scales[3 * Q + 2], r[32 * Q + 28 + 0] = this.rotations[4 * Q + 0] * 128 + 128 & 255, r[32 * Q + 28 + 1] = this.rotations[4 * Q + 1] * 128 + 128 & 255, r[32 * Q + 28 + 2] = this.rotations[4 * Q + 2] * 128 + 128 & 255, r[32 * Q + 28 + 3] = this.rotations[4 * Q + 3] * 128 + 128 & 255; return o; }, this.reattach = (o, s, r, Q, I) => { console.assert( o.byteLength === this.vertexCount * 3 * 4, `Expected ${this.vertexCount * 3 * 4} bytes, got ${o.byteLength} bytes` ), this._positions = new Float32Array(o), this._rotations = new Float32Array(s), this._scales = new Float32Array(r), this._colors = new Uint8Array(Q), this._selection = new Uint8Array(I), this.detached = false; }; } static Deserialize(t) { const n = t.length / _Y.RowLength, i = new Float32Array(3 * n), e = new Float32Array(4 * n), A = new Float32Array(3 * n), o = new Uint8Array(4 * n), s = new Float32Array(t.buffer), r = new Uint8Array(t.buffer); for (let Q = 0; Q < n; Q++) i[3 * Q + 0] = s[8 * Q + 0], i[3 * Q + 1] = s[8 * Q + 1], i[3 * Q + 2] = s[8 * Q + 2], e[4 * Q + 0] = (r[32 * Q + 28 + 0] - 128) / 128, e[4 * Q + 1] = (r[32 * Q + 28 + 1] - 128) / 128, e[4 * Q + 2] = (r[32 * Q + 28 + 2] - 128) / 128, e[4 * Q + 3] = (r[32 * Q + 28 + 3] - 128) / 128, A[3 * Q + 0] = s[8 * Q + 3 + 0], A[3 * Q + 1] = s[8 * Q + 3 + 1], A[3 * Q + 2] = s[8 * Q + 3 + 2], o[4 * Q + 0] = r[32 * Q + 24 + 0], o[4 * Q + 1] = r[32 * Q + 24 + 1], o[4 * Q + 2] = r[32 * Q + 24 + 2], o[4 * Q + 3] = r[32 * Q + 24 + 3]; return new _Y(n, i, e, A, o); } get vertexCount() { return this._vertexCount; } get positions() { return this._positions; } get rotations() { return this._rotations; } get scales() { return this._scales; } get colors() { return this._colors; } get selection() { return this._selection; } clone() { return new _Y( this.vertexCount, new Float32Array(this.positions), new Float32Array(this.rotations), new Float32Array(this.scales), new Uint8Array(this.colors) ); } }; _Y.RowLength = 3 * 4 + 3 * 4 + 4 + 4; var Y = _Y; var _ot = class _ot { constructor(t, n, i, e, A) { this._vertexCount = t, this._positions = n, this._data = i, this._width = e, this._height = A, this.serialize = () => new Uint8Array(this._data.buffer); } static Deserialize(t, n, i) { const e = new Uint32Array(t.buffer), A = new Float32Array(t.buffer), o = Math.floor(A.byteLength / this.RowLength), s = new Float32Array(o * 3); for (let r = 0; r < o; r++) s[3 * r + 0] = A[16 * r + 0], s[3 * r + 1] = A[16 * r + 1], s[3 * r + 2] = A[16 * r + 2], s[3 * r + 0] = A[16 * r + 3]; return new _ot(o, s, e, n, i); } get vertexCount() { return this._vertexCount; } get positions() { return this._positions; } get data() { return this._data; } get width() { return this._width; } get height() { return this._height; } }; _ot.RowLength = 64; var ot = _ot; var _et = class _et { static SplatToPLY(t, n) { let i = `ply format binary_little_endian 1.0 `; i += `element vertex ${n} `; const e = ["x", "y", "z", "nx", "ny", "nz", "f_dc_0", "f_dc_1", "f_dc_2"]; for (let B = 0; B < 45; B++) e.push(`f_rest_${B}`); e.push("opacity"), e.push("scale_0"), e.push("scale_1"), e.push("scale_2"), e.push("rot_0"), e.push("rot_1"), e.push("rot_2"), e.push("rot_3"); for (const B of e) i += `property float ${B} `; i += `end_header `; const A = new TextEncoder().encode(i), o = 4 * 3 + 4 * 3 + 4 * 3 + 4 * 45 + 4 + 4 * 3 + 4 * 4, s = n * o, r = new DataView(new ArrayBuffer(A.length + s)); new Uint8Array(r.buffer).set(A, 0); const Q = new Float32Array(t), I = new Uint8Array(t), d = A.length, a = 4 * 3 + 4 * 3, U = a + 4 * 3 + 4 * 45, F = U + 4, g = F + 4 * 3; for (let B = 0; B < n; B++) { const C = Q[8 * B + 0], c = Q[8 * B + 1], p = Q[8 * B + 2], u = (I[32 * B + 24 + 0] / 255 - 0.5) / this.SH_C0, S = (I[32 * B + 24 + 1] / 255 - 0.5) / this.SH_C0, W = (I[32 * B + 24 + 2] / 255 - 0.5) / this.SH_C0, Z = I[32 * B + 24 + 3] / 255, k = Math.log(Z / (1 - Z)), f = Math.log(Q[8 * B + 3 + 0]), H = Math.log(Q[8 * B + 3 + 1]), L = Math.log(Q[8 * B + 3 + 2]); let M = new y( (I[32 * B + 28 + 1] - 128) / 128, (I[32 * B + 28 + 2] - 128) / 128, (I[32 * B + 28 + 3] - 128) / 128, (I[32 * B + 28 + 0] - 128) / 128 ); M = M.normalize(); const V = M.w, w = M.x, P = M.y, T = M.z; r.setFloat32(d + o * B + 0, C, true), r.setFloat32(d + o * B + 4, c, true), r.setFloat32(d + o * B + 8, p, true), r.setFloat32(d + o * B + a + 0, u, true), r.setFloat32(d + o * B + a + 4, S, true), r.setFloat32(d + o * B + a + 8, W, true), r.setFloat32(d + o * B + U, k, true), r.setFloat32(d + o * B + F + 0, f, true), r.setFloat32(d + o * B + F + 4, H, true), r.setFloat32(d + o * B + F + 8, L, true), r.setFloat32(d + o * B + g + 0, V, true), r.setFloat32(d + o * B + g + 4, w, true), r.setFloat32(d + o * B + g + 8, P, true), r.setFloat32(d + o * B + g + 12, T, true); } return r.buffer; } }; _et.SH_C0 = 0.28209479177387814; var et = _et; var nt = class { constructor(t, n) { this.min = t, this.max = n; } contains(t) { return t.x >= this.min.x && t.x <= this.max.x && t.y >= this.min.y && t.y <= this.max.y && t.z >= this.min.z && t.z <= this.max.z; } intersects(t) { return this.max.x >= t.min.x && this.min.x <= t.max.x && this.max.y >= t.min.y && this.min.y <= t.max.y && this.max.z >= t.min.z && this.min.z <= t.max.z; } size() { return this.max.subtract(this.min); } center() { return this.min.add(this.max).divide(2); } expand(t) { this.min = this.min.min(t), this.max = this.max.max(t); } permute() { const t = this.min, n = this.max; this.min = new R(Math.min(t.x, n.x), Math.min(t.y, n.y), Math.min(t.z, n.z)), this.max = new R(Math.max(t.x, n.x), Math.max(t.y, n.y), Math.max(t.z, n.z)); } }; var X = class _X extends st { constructor(t = void 0) { super(), this.selectedChanged = false, this.colorTransformChanged = false, this._selected = false, this._colorTransforms = [], this._colorTransformsMap = /* @__PURE__ */ new Map(), this._data = t || new Y(), this._bounds = new nt( new R(1 / 0, 1 / 0, 1 / 0), new R(-1 / 0, -1 / 0, -1 / 0) ), this.recalculateBounds = () => { this._bounds = new nt( new R(1 / 0, 1 / 0, 1 / 0), new R(-1 / 0, -1 / 0, -1 / 0) ); for (let n = 0; n < this._data.vertexCount; n++) this._bounds.expand( new R( this._data.positions[3 * n], this._data.positions[3 * n + 1], this._data.positions[3 * n + 2] ) ); }, this.applyPosition = () => { this.data.translate(this.position), this.position = new R(); }, this.applyRotation = () => { this.data.rotate(this.rotation), this.rotation = new y(); }, this.applyScale = () => { this.data.scale(this.scale), this.scale = new R(1, 1, 1); }, this.recalculateBounds(); } saveToFile(t = null, n = "splat") { if (!document) return; if (!t) { const s = /* @__PURE__ */ new Date(); t = `splat-${s.getFullYear()}-${s.getMonth() + 1}-${s.getDate()}.${n}`; } const i = this.clone(); i.applyRotation(), i.applyScale(), i.applyPosition(); const e = i.data.serialize(); let A; if (n === "ply") { const s = et.SplatToPLY(e.buffer, i.data.vertexCount); A = new Blob([s], { type: "application/octet-stream" }); } else A = new Blob([e.buffer], { type: "application/octet-stream" }); const o = document.createElement("a"); o.download = t, o.href = URL.createObjectURL(A), o.click(); } get data() { return this._data; } get selected() { return this._selected; } set selected(t) { this._selected !== t && (this._selected = t, this.selectedChanged = true, this.dispatchEvent(this._changeEvent)); } get colorTransforms() { return this._colorTransforms; } get colorTransformsMap() { return this._colorTransformsMap; } get bounds() { let t = this._bounds.center(); t = t.add(this.position); let n = this._bounds.size(); return n = n.multiply(this.scale), new nt(t.subtract(n.divide(2)), t.add(n.divide(2))); } clone() { const t = new _X(this.data.clone()); return t.position = this.position.clone(), t.rotation = this.rotation.clone(), t.scale = this.scale.clone(), t; } }; var tt = class extends st { constructor(t) { super(), this._data = t; } get data() { return this._data; } }; var Rt = class { constructor() { this._fx = 1132, this._fy = 1132, this._near = 0.1, this._far = 100, this._width = 512, this._height = 512, this._projectionMatrix = new K(), this._viewMatrix = new K(), this._viewProj = new K(), this._updateProjectionMatrix = () => { this._projectionMatrix = new K( 2 * this.fx / this.width, 0, 0, 0, 0, -2 * this.fy / this.height, 0, 0, 0, 0, this.far / (this.far - this.near), 1, 0, 0, -(this.far * this.near) / (this.far - this.near), 0 ), this._viewProj = this.projectionMatrix.multiply(this.viewMatrix); }, this.update = (t, n) => { const i = _.RotationFromQuaternion(n).buffer, e = t.flat(); this._viewMatrix = new K( i[0], i[1], i[2], 0, i[3], i[4], i[5], 0, i[6], i[7], i[8], 0, -e[0] * i[0] - e[1] * i[3] - e[2] * i[6], -e[0] * i[1] - e[1] * i[4] - e[2] * i[7], -e[0] * i[2] - e[1] * i[5] - e[2] * i[8], 1 ), this._viewProj = this.projectionMatrix.multiply(this.viewMatrix); }, this.setSize = (t, n) => { this._width = t, this._height = n, this._updateProjectionMatrix(); }; } get fx() { return this._fx; } set fx(t) { this._fx !== t && (this._fx = t, this._updateProjectionMatrix()); } get fy() { return this._fy; } set fy(t) { this._fy !== t && (this._fy = t, this._updateProjectionMatrix()); } get near() { return this._near; } set near(t) { this._near !== t && (this._near = t, this._updateProjectionMatrix()); } get far() { return this._far; } set far(t) { this._far !== t && (this._far = t, this._updateProjectionMatrix()); } get width() { return this._width; } get height() { return this._height; } get projectionMatrix() { return this._projectionMatrix; } get viewMatrix() { return this._viewMatrix; } get viewProj() { return this._viewProj; } }; var z = class _z { constructor(t = 0, n = 0, i = 0, e = 0) { this.x = t, this.y = n, this.z = i, this.w = e; } equals(t) { return !(this.x !== t.x || this.y !== t.y || this.z !== t.z || this.w !== t.w); } add(t) { return typeof t == "number" ? new _z(this.x + t, this.y + t, this.z + t, this.w + t) : new _z(this.x + t.x, this.y + t.y, this.z + t.z, this.w + t.w); } subtract(t) { return typeof t == "number" ? new _z(this.x - t, this.y - t, this.z - t, this.w - t) : new _z(this.x - t.x, this.y - t.y, this.z - t.z, this.w - t.w); } multiply(t) { return typeof t == "number" ? new _z(this.x * t, this.y * t, this.z * t, this.w * t) : t instanceof _z ? new _z(this.x * t.x, this.y * t.y, this.z * t.z, this.w * t.w) : new _z( this.x * t.buffer[0] + this.y * t.buffer[4] + this.z * t.buffer[8] + this.w * t.buffer[12], this.x * t.buffer[1] + this.y * t.buffer[5] + this.z * t.buffer[9] + this.w * t.buffer[13], this.x * t.buffer[2] + this.y * t.buffer[6] + this.z * t.buffer[10] + this.w * t.buffer[14], this.x * t.buffer[3] + this.y * t.buffer[7] + this.z * t.buffer[11] + this.w * t.buffer[15] ); } dot(t) { return this.x * t.x + this.y * t.y + this.z * t.z + this.w * t.w; } lerp(t, n) { return new _z( this.x + (t.x - this.x) * n, this.y + (t.y - this.y) * n, this.z + (t.z - this.z) * n, this.w + (t.w - this.w) * n ); } magnitude() { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w); } distanceTo(t) { return Math.sqrt((this.x - t.x) ** 2 + (this.y - t.y) ** 2 + (this.z - t.z) ** 2 + (this.w - t.w) ** 2); } normalize() { const t = this.magnitude(); return new _z(this.x / t, this.y / t, this.z / t, this.w / t); } flat() { return [this.x, this.y, this.z, this.w]; } clone() { return new _z(this.x, this.y, this.z, this.w); } toString() { return `[${this.flat().join(", ")}]`; } }; var wt = class extends st { constructor(t = void 0) { super(), this._data = t || new Rt(), this._position = new R(0, 0, -5), this.update = () => { this.data.update(this.position, this.rotation); }, this.screenPointToRay = (n, i) => { const e = new z(n, i, -1, 1), A = this._data.projectionMatrix.invert(), o = e.multiply(A), s = this._data.viewMatrix.invert(), r = o.multiply(s); return new R( r.x / r.w, r.y / r.w, r.z / r.w ).subtract(this.position).normalize(); }; } get data() { return this._data; } }; var kt = class extends Ft { constructor() { super(), this._objects = [], this.addObject = (t) => { this.objects.push(t), this.dispatchEvent(new It(t)); }, this.removeObject = (t) => { const n = this.objects.indexOf(t); if (n < 0) throw new Error("Object not found in scene"); this.objects.splice(n, 1), this.dispatchEvent(new ht(t)); }, this.findObject = (t) => { for (const n of this.objects) if (t(n)) return n; }, this.findObjectOfType = (t) => { for (const n of this.objects) if (n instanceof t) return n; }, this.reset = () => { const t = this.objects.slice(); for (const n of t) this.removeObject(n); }, this.reset(); } getMergedSceneDataBuffer(t = "splat") { const n = []; let i = 0; for (const o of this.objects) if (o instanceof X) { const s = o.clone(); s.applyRotation(), s.applyScale(), s.applyPosition(); const r = s.data.serialize(); n.push(r), i += s.data.vertexCount; } const e = new Uint8Array(i * Y.RowLength); let A = 0; for (const o of n) e.set(o, A), A += o.length; return t === "ply" ? et.SplatToPLY(e.buffer, i) : e.buffer; } saveToFile(t = null, n = "splat") { if (!document) return; if (!t) { const o = /* @__PURE__ */ new Date(); t = `scene-${o.getFullYear()}-${o.getMonth() + 1}-${o.getDate()}.${n}`; } const i = this.getMergedSceneDataBuffer(n), e = new Blob([i], { type: "application/octet-stream" }), A = document.createElement("a"); A.download = t, A.href = URL.createObjectURL(e), A.click(); } get objects() { return this._objects; } }; async function rt(E, t) { const n = await fetch(E, { mode: "cors", credentials: "same-origin", cache: t ? "force-cache" : "default" }); if (n.status != 200) throw new Error(n.status + " Unable to load " + n.url); return n; } async function At(E, t) { const n = E.body.getReader(), i = E.headers.get("content-length"), e = i && !isNaN(parseInt(i)) ? parseInt(i) : void 0, A = []; let o = 0; for (; ; ) { const { done: Q, value: I } = await n.read(); if (Q) break; if (A.push(I), o += I.length, t && e) { const d = o / e, a = Math.min(d * 0.95, 0.95); t(a); } } const s = new Uint8Array(o); let r = 0; for (const Q of A) s.set(Q, r), r += Q.length; return t && t(1), s; } var Tt = class { static async LoadAsync(t, n, i, e = false) { const A = await rt(t, e), o = await At(A, i); return this.LoadFromArrayBuffer(o.buffer, n); } static async LoadFromFileAsync(t, n, i) { const e = new FileReader(); let A = new X(); return e.onload = (o) => { A = this.LoadFromArrayBuffer(o.target.result, n); }, e.onprogress = (o) => { i?.(o.loaded / o.total); }, e.readAsArrayBuffer(t), await new Promise((o) => { e.onloadend = () => { o(); }; }), A; } static LoadFromArrayBuffer(t, n) { const i = new Uint8Array(t), e = Y.Deserialize(i), A = new X(e); return n.addObject(A), A; } }; var bt = class { static async LoadAsync(t, n, i, e = "", A = false) { const o = await rt(t, A), s = await At(o, i); if (s[0] !== 112 || s[1] !== 108 || s[2] !== 121 || s[3] !== 10) throw new Error("Invalid PLY file"); return this.LoadFromArrayBuffer(s.buffer, n, e); } static async LoadFromFileAsync(t, n, i, e = "") { const A = new FileReader(); let o = new X(); return A.onload = (s) => { o = this.LoadFromArrayBuffer(s.target.result, n, e); }, A.onprogress = (s) => { i?.(s.loaded / s.total); }, A.readAsArrayBuffer(t), await new Promise((s) => { A.onloadend = () => { s(); }; }), o; } static LoadFromArrayBuffer(t, n, i = "") { const e = new Uint8Array(this._ParsePLYBuffer(t, i)), A = Y.Deserialize(e), o = new X(A); return n.addObject(o), o; } static _ParsePLYBuffer(t, n) { const i = new Uint8Array(t), e = new TextDecoder().decode(i.slice(0, 1024 * 10)), A = `end_header `, o = e.indexOf(A); if (o < 0) throw new Error("Unable to read .ply file header"); const s = parseInt(/element vertex (\d+)\n/.exec(e)[1]); let r = 0; const Q = { double: 8, int: 4, uint: 4, float: 4, short: 2, ushort: 2, uchar: 1 }, I = []; for (const F of e.slice(0, o).split(` `).filter((g) => g.startsWith("property "))) { const [g, B, C] = F.split(" "); if (I.push({ name: C, type: B, offset: r }), !Q[B]) throw new Error(`Unsupported property type: ${B}`); r += Q[B]; } const d = new DataView(t, o + A.length), a = new ArrayBuffer(Y.RowLength * s), U = y.FromEuler(new R(Math.PI / 2, 0, 0)); for (let F = 0; F < s; F++) { const g = new Float32Array(a, F * Y.RowLength, 3), B = new Float32Array(a, F * Y.RowLength + 12, 3), C = new Uint8ClampedArray(a, F * Y.RowLength + 24, 4), c = new Uint8ClampedArray(a, F * Y.RowLength + 28, 4); let p = 255, u = 0, S = 0, W = 0; I.forEach((k) => { let f; switch (k.type) { case "float": f = d.getFloat32(k.offset + F * r, true); break; case "int": f = d.getInt32(k.offset + F * r, true); break; default: throw new Error(`Unsupported property type: ${k.type}`); } switch (k.name) { case "x": g[0] = f; break; case "y": g[1] = f; break; case "z": g[2] = f; break; case "scale_0": case "scaling_0": B[0] = Math.exp(f); break; case "scale_1": case "scaling_1": B[1] = Math.exp(f); break; case "scale_2": case "scaling_2": B[2] = Math.exp(f); break; case "red": C[0] = f; break; case "green": C[1] = f; break; case "blue": C[2] = f; break; case "f_dc_0": case "features_0": C[0] = (0.5 + et.SH_C0 * f) * 255; break; case "f_dc_1": case "features_1": C[1] = (0.5 + et.SH_C0 * f) * 255; break; case "f_dc_2": case "features_2": C[2] = (0.5 + et.SH_C0 * f) * 255; break; case "f_dc_3": C[3] = (0.5 + et.SH_C0 * f) * 255; break; case "opacity": case "opacity_0": C[3] = 1 / (1 + Math.exp(-f)) * 255; break; case "rot_0": case "rotation_0": p = f; break; case "rot_1": case "rotation_1": u = f; break; case "rot_2": case "rotation_2": S = f; break; case "rot_3": case "rotation_3": W = f; break; } }); let Z = new y(u, S, W, p); switch (n) { case "polycam": { const k = g[1]; g[1] = -g[2], g[2] = k, Z = U.multiply(Z); break; } case "": break; default: throw new Error(`Unsupported format: ${n}`); } Z = Z.normalize(), c[0] = Z.w * 128 + 128, c[1] = Z.x * 128 + 128, c[2] = Z.y * 128 + 128, c[3] = Z.z * 128 + 128; } return a; } }; var xt = class { static async LoadAsync(t, n, i, e, A = false) { const o = await rt(t, A), s = await At(o, e); return this._ParseSplatvBuffer(s.buffer, n, i); } static async LoadFromFileAsync(t, n, i, e) { const A = new FileReader(); let o = null; if (A.onload = (s) => { o = this._ParseSplatvBuffer(s.target.result, n, i); }, A.onprogress = (s) => { e?.(s.loaded / s.total); }, A.readAsArrayBuffer(t), await new Promise((s) => { A.onloadend = () => { s(); }; }), !o) throw new Error("Failed to load splatv file"); return o; } static _ParseSplatvBuffer(t, n, i) { let e = null; const A = (a, U, F) => { if (a.type === "magic") { const g = new Int32Array(U.buffer); if (g[0] !== 26443) throw new Error("Invalid splatv file"); F.push({ size: g[1], type: "chunks" }); } else if (a.type === "chunks") { const g = JSON.parse(new TextDecoder("utf-8").decode(U)); if (g.length == 0) throw new Error("Invalid splatv file"); g.length > 1 && console.warn("Splatv file contains more than one chunk, only the first one will be loaded"); const B = g[0], C = B.cameras; if (i && C && C.length) { const c = C[0], p = new R( c.position[0], c.position[1], c.position[2] ), u = y.FromMatrix3( new _( c.rotation[0][0], c.rotation[0][1], c.rotation[0][2], c.rotation[1][0], c.rotation[1][1], c.rotation[1][2], c.rotation[2][0], c.rotation[2][1], c.rotation[2][2] ) ); i.position = p, i.rotation = u; } F.push(B); } else if (a.type === "splat") { const g = ot.Deserialize(U, a.texwidth, a.texheight), B = new tt(g); n.addObject(B), e = B; } }, o = new Uint8Array(t), s = [ { size: 8, type: "magic", texwidth: 0, texheight: 0 } ]; let r = s.shift(), Q = new Uint8Array(r.size), I = 0, d = 0; for (; r; ) { for (; I < r.size; ) { const a = Math.min(r.size - I, o.length - d); Q.set(o.subarray(d, d + a), I), I += a, d += a; } if (A(r, Q, s), e) return e; r = s.shift(), r && (Q = new Uint8Array(r.size), I = 0); } throw new Error("Invalid splatv file"); } }; var Bt = "dmFyIGVBID0gZnVuY3Rpb24oQyA9IHt9KSB7CiAgdmFyIHIsIEkgPSBDLCBsID0gaW1wb3J0Lm1ldGEudXJsLCBqID0gIiIsIFU7CiAgewogICAgdHJ5IHsKICAgICAgaiA9IG5ldyBVUkwoIi4iLCBsKS5ocmVmOwogICAgfSBjYXRjaCB7CiAgICB9CiAgICBVID0gKEEpID0+IHsKICAgICAgdmFyIEIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsKICAgICAgcmV0dXJuIEIub3BlbigiR0VUIiwgQSwgITEpLCBCLnJlc3BvbnNlVHlwZSA9ICJhcnJheWJ1ZmZlciIsIEIuc2VuZChudWxsKSwgbmV3IFVpbnQ4QXJyYXkoQi5yZXNwb25zZSk7CiAgICB9OwogIH0KICBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpLCBjb25zb2xlLmVycm9yLmJpbmQoY29uc29sZSk7CiAgdmFyIE0sIHUsIEw7CiAgZnVuY3Rpb24gcSgpIHsKICAgIHZhciBBID0gdS5idWZmZXI7CiAgICBJLkhFQVBVOCA9IEwgPSBuZXcgVWludDhBcnJheShBKSwgSS5IRUFQVTMyID0gbmV3IFVpbnQzMkFycmF5KEEpLCBJLkhFQVBGMzIgPSBuZXcgRmxvYXQzMkFycmF5KEEpLCBuZXcgQmlnSW50NjRBcnJheShBKSwgbmV3IEJpZ1VpbnQ2NEFycmF5KEEpOwogIH0KICBmdW5jdGlvbiBQKCkgewogICAgaWYgKEkucHJlUnVuKQogICAgICBmb3IgKHR5cGVvZiBJLnByZVJ1biA9PSAiZnVuY3Rpb24iICYmIChJLnByZVJ1biA9IFtJLnByZVJ1bl0pOyBJLnByZVJ1bi5sZW5ndGg7ICkKICAgICAgICBDQShJLnByZVJ1bi5zaGlmdCgpKTsKICAgIHgoVCk7CiAgfQogIGZ1bmN0aW9uIGIoKSB7CiAgICB5LmMoKTsKICB9CiAgZnVuY3Rpb24gVygpIHsKICAgIGlmIChJLnBvc3RSdW4pCiAgICAgIGZvciAodHlwZW9mIEkucG9zdFJ1biA9PSAiZnVuY3Rpb24iICYmIChJLnBvc3RSdW4gPSBbSS5wb3N0UnVuXSk7IEkucG9zdFJ1bi5sZW5ndGg7ICkKICAgICAgICBnQShJLnBvc3RSdW4uc2hpZnQoKSk7CiAgICB4KHYpOwogIH0KICB2YXIgcyA9IDAsIGYgPSBudWxsOwogIGZ1bmN0aW9uIF8oQSkgewogICAgcysrLCBJLm1vbml0b3JSdW5EZXBlbmRlbmNpZXM/LihzKTsKICB9CiAgZnVuY3Rpb24geihBKSB7CiAgICBpZiAocy0tLCBJLm1vbml0b3JSdW5EZXBlbmRlbmNpZXM/LihzKSwgcyA9PSAwICYmIGYpIHsKICAgICAgdmFyIEIgPSBmOwogICAgICBmID0gbnVsbCwgQigpOwogICAgfQogIH0KICB2YXIgUzsKICBmdW5jdGlvbiBWKCkgewogICAgcmV0dXJuIEJBKCJBR0Z6YlFFQUFBQUJHUVJnQVg4QmYyQUJmd0JnQ1g5L2YzOS9mMzkvZndCZ0FBQUNCd0VCWVFGaEFBQURCZ1VBQVFBQ0F3VUhBUUdDQW9DQUFnWUlBWDhCUVlDTUJBc0hGUVVCWWdJQUFXTUFCUUZrQUFRQlpRQURBV1lBQWd3QkFRck5PQVZQQVFKL1FZQUlLQUlBSWdFZ0FFRUhha0Y0Y1NJQ2FpRUFBa0FnQWtFQUlBQWdBVTBiUlFSQUlBQS9BRUVRZEUwTkFTQUFFQUFOQVF0QmhBaEJNRFlDQUVGL0R3dEJnQWdnQURZQ0FDQUJDOXdMQVFoL0FrQWdBRVVOQUNBQVFRaHJJZ01nQUVFRWF5Z0NBQ0lDUVhoeElnQnFJUVVDUUNBQ1FRRnhEUUFnQWtFQ2NVVU5BU0FESUFNb0FnQWlCR3NpQTBHWUNDZ0NBRWtOQVNBQUlBUnFJUUFDUUFKQUFrQkJuQWdvQWdBZ0EwY0VRQ0FES0FJTUlRRWdCRUgvQVUwRVFDQUJJQU1vQWdnaUFrY05Ba0dJQ0VHSUNDZ0NBRUYrSUFSQkEzWjNjVFlDQUF3RkN5QURLQUlZSVFjZ0FTQURSd1JBSUFNb0FnZ2lBaUFCTmdJTUlBRWdBallDQ0F3RUN5QURLQUlVSWdJRWZ5QURRUlJxQlNBREtBSVFJZ0pGRFFNZ0EwRVFhZ3NoQkFOQUlBUWhCaUFDSWdGQkZHb2hCQ0FCS0FJVUlnSU5BQ0FCUVJCcUlRUWdBU2dDRUNJQ0RRQUxJQVpCQURZQ0FBd0RDeUFGS0FJRUlnSkJBM0ZCQTBjTkEwR1FDQ0FBTmdJQUlBVWdBa0YrY1RZQ0JDQURJQUJCQVhJMkFnUWdCU0FBTmdJQUR3c2dBaUFCTmdJTUlBRWdBallDQ0F3Q0MwRUFJUUVMSUFkRkRRQUNRQ0FES0FJY0lnUkJBblJCdUFwcUlnSW9BZ0FnQTBZRVFDQUNJQUUyQWdBZ0FRMEJRWXdJUVl3SUtBSUFRWDRnQkhkeE5nSUFEQUlMQWtBZ0F5QUhLQUlRUmdSQUlBY2dBVFlDRUF3QkN5QUhJQUUyQWhRTElBRkZEUUVMSUFFZ0J6WUNHQ0FES0FJUUlnSUVRQ0FCSUFJMkFoQWdBaUFCTmdJWUN5QURLQUlVSWdKRkRRQWdBU0FDTmdJVUlBSWdBVFlDR0FzZ0F5QUZUdzBBSUFVb0FnUWlCRUVCY1VVTkFBSkFBa0FDUUFKQUlBUkJBbkZGQkVCQm9BZ29BZ0FnQlVZRVFFR2dDQ0FETmdJQVFaUUlRWlFJS0FJQUlBQnFJZ0EyQWdBZ0F5QUFRUUZ5TmdJRUlBTkJuQWdvQWdCSERRWkJrQWhCQURZQ0FFR2NDRUVBTmdJQUR3dEJuQWdvQWdBaUJ5QUZSZ1JBUVp3SUlBTTJBZ0JCa0FoQmtBZ29BZ0FnQUdvaUFEWUNBQ0FESUFCQkFYSTJBZ1FnQUNBRGFpQUFOZ0lBRHdzZ0JFRjRjU0FBYWlFQUlBVW9BZ3doQVNBRVFmOEJUUVJBSUFVb0FnZ2lBaUFCUmdSQVFZZ0lRWWdJS0FJQVFYNGdCRUVEZG5keE5nSUFEQVVMSUFJZ0FUWUNEQ0FCSUFJMkFnZ01CQXNnQlNnQ0dDRUlJQUVnQlVjRVFDQUZLQUlJSWdJZ0FUWUNEQ0FCSUFJMkFnZ01Bd3NnQlNnQ0ZDSUNCSDhnQlVFVWFnVWdCU2dDRUNJQ1JRMENJQVZCRUdvTElRUURRQ0FFSVFZZ0FpSUJRUlJxSVFRZ0FTZ0NGQ0lDRFFBZ0FVRVFhaUVFSUFFb0FoQWlBZzBBQ3lBR1FRQTJBZ0FNQWdzZ0JTQUVRWDV4TmdJRUlBTWdBRUVCY2pZQ0JDQUFJQU5xSUFBMkFnQU1Bd3RCQUNFQkN5QUlSUTBBQWtBZ0JTZ0NIQ0lFUVFKMFFiZ0thaUlDS0FJQUlBVkdCRUFnQWlBQk5nSUFJQUVOQVVHTUNFR01DQ2dDQUVGK0lBUjNjVFlDQUF3Q0N3SkFJQVVnQ0NnQ0VFWUVRQ0FJSUFFMkFoQU1BUXNnQ0NBQk5nSVVDeUFCUlEwQkN5QUJJQWcyQWhnZ0JTZ0NFQ0lDQkVBZ0FTQUNOZ0lRSUFJZ0FUWUNHQXNnQlNnQ0ZDSUNSUTBBSUFFZ0FqWUNGQ0FDSUFFMkFoZ0xJQU1nQUVFQmNqWUNCQ0FBSUFOcUlBQTJBZ0FnQXlBSFJ3MEFRWkFJSUFBMkFnQVBDeUFBUWY4QlRRUkFJQUJCZUhGQnNBaHFJUUlDZjBHSUNDZ0NBQ0lFUVFFZ0FFRURkblFpQUhGRkJFQkJpQWdnQUNBRWNqWUNBQ0FDREFFTElBSW9BZ2dMSVFBZ0FpQUROZ0lJSUFBZ0F6WUNEQ0FESUFJMkFnd2dBeUFBTmdJSUR3dEJIeUVCSUFCQi8vLy9CMDBFUUNBQVFTWWdBRUVJZG1jaUFtdDJRUUZ4SUFKQkFYUnJRVDVxSVFFTElBTWdBVFlDSENBRFFnQTNBaEFnQVVFQ2RFRzRDbW9oQkFKL0FrQUNmMEdNQ0NnQ0FDSUdRUUVnQVhRaUFuRkZCRUJCakFnZ0FpQUdjallDQUNBRUlBTTJBZ0JCR0NFQlFRZ01BUXNnQUVFWklBRkJBWFpyUVFBZ0FVRWZSeHQwSVFFZ0JDZ0NBQ0VFQTBBZ0JDSUNLQUlFUVhoeElBQkdEUUlnQVVFZGRpRUVJQUZCQVhRaEFTQUNJQVJCQkhGcUlnWW9BaEFpQkEwQUN5QUdJQU0yQWhCQkdDRUJJQUloQkVFSUN5RUFJQU1pQWd3QkN5QUNLQUlJSWdRZ0F6WUNEQ0FDSUFNMkFnaEJHQ0VBUVFnaEFVRUFDeUVHSUFFZ0Eyb2dCRFlDQUNBRElBSTJBZ3dnQUNBRGFpQUdOZ0lBUWFnSVFhZ0lLQUlBUVFGcklnQkJmeUFBR3pZQ0FBc0wwU2NCQzM4akFFRVFheUlLSkFBQ1FBSkFBa0FDUUFKQUFrQUNRQUpBQWtBQ1FDQUFRZlFCVFFSQVFZZ0lLQUlBSWdSQkVDQUFRUXRxUWZnRGNTQUFRUXRKR3lJR1FRTjJJZ0IySWdGQkEzRUVRQUpBSUFGQmYzTkJBWEVnQUdvaUFrRURkQ0lCUWJBSWFpSUFJQUZCdUFocUtBSUFJZ0VvQWdnaUJVWUVRRUdJQ0NBRVFYNGdBbmR4TmdJQURBRUxJQVVnQURZQ0RDQUFJQVUyQWdnTElBRkJDR29oQUNBQklBSkJBM1FpQWtFRGNqWUNCQ0FCSUFKcUlnRWdBU2dDQkVFQmNqWUNCQXdMQ3lBR1FaQUlLQUlBSWdoTkRRRWdBUVJBQWtCQkFpQUFkQ0lDUVFBZ0FtdHlJQUVnQUhSeGFDSUJRUU4wSWdCQnNBaHFJZ0lnQUVHNENHb29BZ0FpQUNnQ0NDSUZSZ1JBUVlnSUlBUkJmaUFCZDNFaUJEWUNBQXdCQ3lBRklBSTJBZ3dnQWlBRk5nSUlDeUFBSUFaQkEzSTJBZ1FnQUNBR2FpSUhJQUZCQTNRaUFTQUdheUlGUVFGeU5nSUVJQUFnQVdvZ0JUWUNBQ0FJQkVBZ0NFRjRjVUd3Q0dvaEFVR2NDQ2dDQUNFQ0FuOGdCRUVCSUFoQkEzWjBJZ054UlFSQVFZZ0lJQU1nQkhJMkFnQWdBUXdCQ3lBQktBSUlDeUVESUFFZ0FqWUNDQ0FESUFJMkFnd2dBaUFCTmdJTUlBSWdBellDQ0FzZ0FFRUlhaUVBUVp3SUlBYzJBZ0JCa0FnZ0JUWUNBQXdMQzBHTUNDZ0NBQ0lMUlEwQklBdG9RUUowUWJnS2FpZ0NBQ0lDS0FJRVFYaHhJQVpySVFNZ0FpRUJBMEFDUUNBQktBSVFJZ0JGQkVBZ0FTZ0NGQ0lBUlEwQkN5QUFLQUlFUVhoeElBWnJJZ0VnQXlBQklBTkpJZ0ViSVFNZ0FDQUNJQUViSVFJZ0FDRUJEQUVMQ3lBQ0tBSVlJUWtnQWlBQ0tBSU1JZ0JIQkVBZ0FpZ0NDQ0lCSUFBMkFnd2dBQ0FCTmdJSURBb0xJQUlvQWhRaUFRUi9JQUpCRkdvRklBSW9BaEFpQVVVTkF5QUNRUkJxQ3lFRkEwQWdCU0VISUFFaUFFRVVhaUVGSUFBb0FoUWlBUTBBSUFCQkVHb2hCU0FBS0FJUUlnRU5BQXNnQjBFQU5nSUFEQWtMUVg4aEJpQUFRYjkvU3cwQUlBQkJDMm9pQVVGNGNTRUdRWXdJS0FJQUlnZEZEUUJCSHlFSVFRQWdCbXNoQXlBQVFmVC8vd2ROQkVBZ0JrRW1JQUZCQ0habklnQnJka0VCY1NBQVFRRjBhMEUrYWlFSUN3SkFBa0FDUUNBSVFRSjBRYmdLYWlnQ0FDSUJSUVJBUVFBaEFBd0JDMEVBSVFBZ0JrRVpJQWhCQVhaclFRQWdDRUVmUnh0MElRSURRQUpBSUFFb0FnUkJlSEVnQm1zaUJDQURUdzBBSUFFaEJTQUVJZ01OQUVFQUlRTWdBU0VBREFNTElBQWdBU2dDRkNJRUlBUWdBU0FDUVIxMlFRUnhhaWdDRUNJQlJoc2dBQ0FFR3lFQUlBSkJBWFFoQWlBQkRRQUxDeUFBSUFWeVJRUkFRUUFoQlVFQ0lBaDBJZ0JCQUNBQWEzSWdCM0VpQUVVTkF5QUFhRUVDZEVHNENtb29BZ0FoQUFzZ0FFVU5BUXNEUUNBQUtBSUVRWGh4SUFacklnSWdBMGtoQVNBQ0lBTWdBUnNoQXlBQUlBVWdBUnNoQlNBQUtBSVFJZ0VFZnlBQkJTQUFLQUlVQ3lJQURRQUxDeUFGUlEwQUlBTkJrQWdvQWdBZ0JtdFBEUUFnQlNnQ0dDRUlJQVVnQlNnQ0RDSUFSd1JBSUFVb0FnZ2lBU0FBTmdJTUlBQWdBVFlDQ0F3SUN5QUZLQUlVSWdFRWZ5QUZRUlJxQlNBRktBSVFJZ0ZGRFFNZ0JVRVFhZ3NoQWdOQUlBSWhCQ0FCSWdCQkZHb2hBaUFBS0FJVUlnRU5BQ0FBUVJCcUlRSWdBQ2dDRUNJQkRRQUxJQVJCQURZQ0FBd0hDeUFHUVpBSUtBSUFJZ1ZOQkVCQm5BZ29BZ0FoQUFKQUlBVWdCbXNpQVVFUVR3UkFJQUFnQm1vaUFpQUJRUUZ5TmdJRUlBQWdCV29nQVRZQ0FDQUFJQVpCQTNJMkFnUU1BUXNnQUNBRlFRTnlOZ0lFSUFBZ0JXb2lBU0FCS0FJRVFRRnlOZ0lFUVFBaEFrRUFJUUVMUVpBSUlBRTJBZ0JCbkFnZ0FqWUNBQ0FBUVFocUlRQU1DUXNnQmtHVUNDZ0NBQ0lDU1FSQVFaUUlJQUlnQm1zaUFUWUNBRUdnQ0VHZ0NDZ0NBQ0lBSUFacUlnSTJBZ0FnQWlBQlFRRnlOZ0lFSUFBZ0JrRURjallDQkNBQVFRaHFJUUFNQ1F0QkFDRUFJQVpCTDJvaUF3Si9RZUFMS0FJQUJFQkI2QXNvQWdBTUFRdEI3QXRDZnpjQ0FFSGtDMEtBb0lDQWdJQUVOd0lBUWVBTElBcEJER3BCY0hGQjJLclZxZ1Z6TmdJQVFmUUxRUUEyQWdCQnhBdEJBRFlDQUVHQUlBc2lBV29pQkVFQUlBRnJJZ2R4SWdFZ0JrME5DRUhBQ3lnQ0FDSUZCRUJCdUFzb0FnQWlDQ0FCYWlJSklBaE5JQVVnQ1VseURRa0xBa0JCeEFzdEFBQkJCSEZGQkVBQ1FBSkFBa0FDUUVHZ0NDZ0NBQ0lGQkVCQnlBc2hBQU5BSUFBb0FnQWlDQ0FGVFFSQUlBVWdDQ0FBS0FJRWFra05Bd3NnQUNnQ0NDSUFEUUFMQzBFQUVBRWlBa0YvUmcwRElBRWhCRUhrQ3lnQ0FDSUFRUUZySWdVZ0FuRUVRQ0FCSUFKcklBSWdCV3BCQUNBQWEzRnFJUVFMSUFRZ0JrME5BMEhBQ3lnQ0FDSUFCRUJCdUFzb0FnQWlCU0FFYWlJSElBVk5JQUFnQjBseURRUUxJQVFRQVNJQUlBSkhEUUVNQlFzZ0JDQUNheUFIY1NJRUVBRWlBaUFBS0FJQUlBQW9BZ1JxUmcwQklBSWhBQXNnQUVGL1JnMEJJQVpCTUdvZ0JFMEVRQ0FBSVFJTUJBdEI2QXNvQWdBaUFpQURJQVJyYWtFQUlBSnJjU0lDRUFGQmYwWU5BU0FDSUFScUlRUWdBQ0VDREFNTElBSkJmMGNOQWd0QnhBdEJ4QXNvQWdCQkJISTJBZ0FMSUFFUUFTSUNRWDlHUVFBUUFTSUFRWDlHY2lBQUlBSk5jZzBGSUFBZ0Ftc2lCQ0FHUVNocVRRMEZDMEc0QzBHNEN5Z0NBQ0FFYWlJQU5nSUFRYndMS0FJQUlBQkpCRUJCdkFzZ0FEWUNBQXNDUUVHZ0NDZ0NBQ0lEQkVCQnlBc2hBQU5BSUFJZ0FDZ0NBQ0lCSUFBb0FnUWlCV3BHRFFJZ0FDZ0NDQ0lBRFFBTERBUUxRWmdJS0FJQUlnQkJBQ0FBSUFKTkcwVUVRRUdZQ0NBQ05nSUFDMEVBSVFCQnpBc2dCRFlDQUVISUN5QUNOZ0lBUWFnSVFYODJBZ0JCckFoQjRBc29BZ0EyQWdCQjFBdEJBRFlDQUFOQUlBQkJBM1FpQVVHNENHb2dBVUd3Q0dvaUJUWUNBQ0FCUWJ3SWFpQUZOZ0lBSUFCQkFXb2lBRUVnUncwQUMwR1VDQ0FFUVNocklnQkJlQ0FDYTBFSGNTSUJheUlGTmdJQVFhQUlJQUVnQW1vaUFUWUNBQ0FCSUFWQkFYSTJBZ1FnQUNBQ2FrRW9OZ0lFUWFRSVFmQUxLQUlBTmdJQURBUUxJQUlnQTAwZ0FTQURTM0lOQWlBQUtBSU1RUWh4RFFJZ0FDQUVJQVZxTmdJRVFhQUlJQU5CZUNBRGEwRUhjU0lBYWlJQk5nSUFRWlFJUVpRSUtBSUFJQVJxSWdJZ0FHc2lBRFlDQUNBQklBQkJBWEkyQWdRZ0FpQURha0VvTmdJRVFhUUlRZkFMS0FJQU5nSUFEQU1MUVFBaEFBd0dDMEVBSVFBTUJBdEJtQWdvQWdBZ0Frc0VRRUdZQ0NBQ05nSUFDeUFDSUFScUlRVkJ5QXNoQUFKQUEwQWdCU0FBS0FJQUlnRkhCRUFnQUNnQ0NDSUFEUUVNQWdzTElBQXRBQXhCQ0hGRkRRTUxRY2dMSVFBRFFBSkFJQUFvQWdBaUFTQURUUVJBSUFNZ0FTQUFLQUlFYWlJRlNRMEJDeUFBS0FJSUlRQU1BUXNMUVpRSUlBUkJLR3NpQUVGNElBSnJRUWR4SWdGcklnYzJBZ0JCb0FnZ0FTQUNhaUlCTmdJQUlBRWdCMEVCY2pZQ0JDQUFJQUpxUVNnMkFnUkJwQWhCOEFzb0FnQTJBZ0FnQXlBRlFTY2dCV3RCQjNGcVFTOXJJZ0FnQUNBRFFSQnFTUnNpQVVFYk5nSUVJQUZCMEFzcEFnQTNBaEFnQVVISUN5a0NBRGNDQ0VIUUN5QUJRUWhxTmdJQVFjd0xJQVEyQWdCQnlBc2dBallDQUVIVUMwRUFOZ0lBSUFGQkdHb2hBQU5BSUFCQkJ6WUNCQ0FBUVFocUlBQkJCR29oQUNBRlNRMEFDeUFCSUFOR0RRQWdBU0FCS0FJRVFYNXhOZ0lFSUFNZ0FTQURheUlDUVFGeU5nSUVJQUVnQWpZQ0FBSi9JQUpCL3dGTkJFQWdBa0Y0Y1VHd0NHb2hBQUovUVlnSUtBSUFJZ0ZCQVNBQ1FRTjJkQ0lDY1VVRVFFR0lDQ0FCSUFKeU5nSUFJQUFNQVFzZ0FDZ0NDQXNoQVNBQUlBTTJBZ2dnQVNBRE5nSU1RUXdoQWtFSURBRUxRUjhoQUNBQ1FmLy8vd2ROQkVBZ0FrRW1JQUpCQ0habklnQnJka0VCY1NBQVFRRjBhMEUrYWlFQUN5QURJQUEyQWh3Z0EwSUFOd0lRSUFCQkFuUkJ1QXBxSVFFQ1FBSkFRWXdJS0FJQUlnVkJBU0FBZENJRWNVVUVRRUdNQ0NBRUlBVnlOZ0lBSUFFZ0F6WUNBQXdCQ3lBQ1FSa2dBRUVCZG10QkFDQUFRUjlIRzNRaEFDQUJLQUlBSVFVRFFDQUZJZ0VvQWdSQmVIRWdBa1lOQWlBQVFSMTJJUVVnQUVFQmRDRUFJQUVnQlVFRWNXb2lCQ2dDRUNJRkRRQUxJQVFnQXpZQ0VBc2dBeUFCTmdJWVFRZ2hBaUFESWdFaEFFRU1EQUVMSUFFb0FnZ2lBQ0FETmdJTUlBRWdBellDQ0NBRElBQTJBZ2hCQUNFQVFSZ2hBa0VNQ3lBRGFpQUJOZ0lBSUFJZ0Eyb2dBRFlDQUF0QmxBZ29BZ0FpQUNBR1RRMEFRWlFJSUFBZ0Jtc2lBVFlDQUVHZ0NFR2dDQ2dDQUNJQUlBWnFJZ0kyQWdBZ0FpQUJRUUZ5TmdJRUlBQWdCa0VEY2pZQ0JDQUFRUWhxSVFBTUJBdEJoQWhCTURZQ0FFRUFJUUFNQXdzZ0FDQUNOZ0lBSUFBZ0FDZ0NCQ0FFYWpZQ0JDQUNRWGdnQW10QkIzRnFJZ2dnQmtFRGNqWUNCQ0FCUVhnZ0FXdEJCM0ZxSWdRZ0JpQUlhaUlEYXlFSEFrQkJvQWdvQWdBZ0JFWUVRRUdnQ0NBRE5nSUFRWlFJUVpRSUtBSUFJQWRxSWdBMkFnQWdBeUFBUVFGeU5nSUVEQUVMUVp3SUtBSUFJQVJHQkVCQm5BZ2dBellDQUVHUUNFR1FDQ2dDQUNBSGFpSUFOZ0lBSUFNZ0FFRUJjallDQkNBQUlBTnFJQUEyQWdBTUFRc2dCQ2dDQkNJQVFRTnhRUUZHQkVBZ0FFRjRjU0VKSUFRb0Fnd2hBZ0pBSUFCQi93Rk5CRUFnQkNnQ0NDSUJJQUpHQkVCQmlBaEJpQWdvQWdCQmZpQUFRUU4yZDNFMkFnQU1BZ3NnQVNBQ05nSU1JQUlnQVRZQ0NBd0JDeUFFS0FJWUlRWUNRQ0FDSUFSSEJFQWdCQ2dDQ0NJQUlBSTJBZ3dnQWlBQU5nSUlEQUVMQWtBZ0JDZ0NGQ0lBQkg4Z0JFRVVhZ1VnQkNnQ0VDSUFSUTBCSUFSQkVHb0xJUUVEUUNBQklRVWdBQ0lDUVJScUlRRWdBQ2dDRkNJQURRQWdBa0VRYWlFQklBSW9BaEFpQUEwQUN5QUZRUUEyQWdBTUFRdEJBQ0VDQ3lBR1JRMEFBa0FnQkNnQ0hDSUFRUUowUWJnS2FpSUJLQUlBSUFSR0JFQWdBU0FDTmdJQUlBSU5BVUdNQ0VHTUNDZ0NBRUYrSUFCM2NUWUNBQXdDQ3dKQUlBUWdCaWdDRUVZRVFDQUdJQUkyQWhBTUFRc2dCaUFDTmdJVUN5QUNSUTBCQ3lBQ0lBWTJBaGdnQkNnQ0VDSUFCRUFnQWlBQU5nSVFJQUFnQWpZQ0dBc2dCQ2dDRkNJQVJRMEFJQUlnQURZQ0ZDQUFJQUkyQWhnTElBY2dDV29oQnlBRUlBbHFJZ1FvQWdRaEFBc2dCQ0FBUVg1eE5nSUVJQU1nQjBFQmNqWUNCQ0FESUFkcUlBYzJBZ0FnQjBIL0FVMEVRQ0FIUVhoeFFiQUlhaUVBQW45QmlBZ29BZ0FpQVVFQklBZEJBM1owSWdKeFJRUkFRWWdJSUFFZ0FuSTJBZ0FnQUF3QkN5QUFLQUlJQ3lFQklBQWdBellDQ0NBQklBTTJBZ3dnQXlBQU5nSU1JQU1nQVRZQ0NBd0JDMEVmSVFJZ0IwSC8vLzhIVFFSQUlBZEJKaUFIUVFoMlp5SUFhM1pCQVhFZ0FFRUJkR3RCUG1vaEFnc2dBeUFDTmdJY0lBTkNBRGNDRUNBQ1FRSjBRYmdLYWlFQUFrQUNRRUdNQ0NnQ0FDSUJRUUVnQW5RaUJYRkZCRUJCakFnZ0FTQUZjallDQUNBQUlBTTJBZ0FNQVFzZ0IwRVpJQUpCQVhaclFRQWdBa0VmUnh0MElRSWdBQ2dDQUNFQkEwQWdBU0lBS0FJRVFYaHhJQWRHRFFJZ0FrRWRkaUVCSUFKQkFYUWhBaUFBSUFGQkJIRnFJZ1VvQWhBaUFRMEFDeUFGSUFNMkFoQUxJQU1nQURZQ0dDQURJQU0yQWd3Z0F5QUROZ0lJREFFTElBQW9BZ2dpQVNBRE5nSU1JQUFnQXpZQ0NDQURRUUEyQWhnZ0F5QUFOZ0lNSUFNZ0FUWUNDQXNnQ0VFSWFpRUFEQUlMQWtBZ0NFVU5BQUpBSUFVb0Fod2lBVUVDZEVHNENtb2lBaWdDQUNBRlJnUkFJQUlnQURZQ0FDQUFEUUZCakFnZ0IwRitJQUYzY1NJSE5nSUFEQUlMQWtBZ0JTQUlLQUlRUmdSQUlBZ2dBRFlDRUF3QkN5QUlJQUEyQWhRTElBQkZEUUVMSUFBZ0NEWUNHQ0FGS0FJUUlnRUVRQ0FBSUFFMkFoQWdBU0FBTmdJWUN5QUZLQUlVSWdGRkRRQWdBQ0FCTmdJVUlBRWdBRFlDR0FzQ1FDQURRUTlOQkVBZ0JTQURJQVpxSWdCQkEzSTJBZ1FnQUNBRmFpSUFJQUFvQWdSQkFYSTJBZ1FNQVFzZ0JTQUdRUU55TmdJRUlBVWdCbW9pQkNBRFFRRnlOZ0lFSUFNZ0JHb2dBellDQUNBRFFmOEJUUVJBSUFOQmVIRkJzQWhxSVFBQ2YwR0lDQ2dDQUNJQlFRRWdBMEVEZG5RaUFuRkZCRUJCaUFnZ0FTQUNjallDQUNBQURBRUxJQUFvQWdnTElRRWdBQ0FFTmdJSUlBRWdCRFlDRENBRUlBQTJBZ3dnQkNBQk5nSUlEQUVMUVI4aEFDQURRZi8vL3dkTkJFQWdBMEVtSUFOQkNIWm5JZ0JyZGtFQmNTQUFRUUYwYTBFK2FpRUFDeUFFSUFBMkFod2dCRUlBTndJUUlBQkJBblJCdUFwcUlRRUNRQUpBSUFkQkFTQUFkQ0lDY1VVRVFFR01DQ0FDSUFkeU5nSUFJQUVnQkRZQ0FDQUVJQUUyQWhnTUFRc2dBMEVaSUFCQkFYWnJRUUFnQUVFZlJ4dDBJUUFnQVNnQ0FDRUJBMEFnQVNJQ0tBSUVRWGh4SUFOR0RRSWdBRUVkZGlFQklBQkJBWFFoQUNBQ0lBRkJCSEZxSWdjb0FoQWlBUTBBQ3lBSElBUTJBaEFnQkNBQ05nSVlDeUFFSUFRMkFnd2dCQ0FFTmdJSURBRUxJQUlvQWdnaUFDQUVOZ0lNSUFJZ0JEWUNDQ0FFUVFBMkFoZ2dCQ0FDTmdJTUlBUWdBRFlDQ0FzZ0JVRUlhaUVBREFFTEFrQWdDVVVOQUFKQUlBSW9BaHdpQVVFQ2RFRzRDbW9pQlNnQ0FDQUNSZ1JBSUFVZ0FEWUNBQ0FBRFFGQmpBZ2dDMEYrSUFGM2NUWUNBQXdDQ3dKQUlBSWdDU2dDRUVZRVFDQUpJQUEyQWhBTUFRc2dDU0FBTmdJVUN5QUFSUTBCQ3lBQUlBazJBaGdnQWlnQ0VDSUJCRUFnQUNBQk5nSVFJQUVnQURZQ0dBc2dBaWdDRkNJQlJRMEFJQUFnQVRZQ0ZDQUJJQUEyQWhnTEFrQWdBMEVQVFFSQUlBSWdBeUFHYWlJQVFRTnlOZ0lFSUFBZ0Ftb2lBQ0FBS0FJRVFRRnlOZ0lFREFFTElBSWdCa0VEY2pZQ0JDQUNJQVpxSWdVZ0EwRUJjallDQkNBRElBVnFJQU0yQWdBZ0NBUkFJQWhCZUhGQnNBaHFJUUJCbkFnb0FnQWhBUUovUVFFZ0NFRURkblFpQnlBRWNVVUVRRUdJQ0NBRUlBZHlOZ0lBSUFBTUFRc2dBQ2dDQ0FzaEJDQUFJQUUyQWdnZ0JDQUJOZ0lNSUFFZ0FEWUNEQ0FCSUFRMkFnZ0xRWndJSUFVMkFnQkJrQWdnQXpZQ0FBc2dBa0VJYWlFQUN5QUtRUkJxSkFBZ0FBdkdCQUlHZndwOVFmLy8vLzhISVF4QmdJQ0FnSGdoRFVGL0lRa0RRQ0FESUFwR0JFQkJBQ0VBSUFoQkFFR0FnQkQ4Q3dCREFQOS9SeUFOSUF4cnNwVWhEd1VnQkNBS1FReHNhaUlMS2dJQUlSTWdDeW9DQ0NFVUlBc3FBZ1FoRlNBSklBSWdDa0VDZENJT2FpZ0NBQ0lMUndSQUlBRWdDMEhRQUd4cUlna3FBandnQUNvQ09DSVBsQ0FKS2dJNElBQXFBaWdpRUpRZ0NTb0NNQ0FBS2dJSUloR1VJQUFxQWhnaUVpQUpLZ0kwbEpLU2tpRVdJQWtxQWl3Z0Q1UWdDU29DS0NBUWxDQUpLZ0lnSUJHVUlCSWdDU29DSkpTU2twSWhGeUFKS2dJY0lBK1VJQWtxQWhnZ0VKUWdDU29DRUNBUmxDQVNJQWtxQWhTVWtwS1NJUmdnQ1NvQ0RDQVBsQ0FKS2dJSUlCQ1VJQWtxQWdBZ0VaUWdDU29DQkNBU2xKS1NraUVQSUFzaENRc2dCU0FPYWlBV0lCY2dGSlFnRHlBVGxDQVZJQmlVa3BLU1F3QUFnRVdVL0FBaUN6WUNBQ0FNSUFzZ0N5QU1TaHNoRENBTklBc2dDeUFOU0JzaERTQUtRUUZxSVFvTUFRc0xBMEFnQUNBRFJrVUVRQ0FGSUFCQkFuUnFJZ0VnRHlBQktBSUFJQXhyczVUOEFTSUJOZ0lBSUFnZ0FVRUNkR29pQVNBQktBSUFRUUZxTmdJQUlBQkJBV29oQUF3QkN3dEJBQ0VBSUFkQkFEWUNBQ0FJUVFScklRRkJBQ0VNUVFFaENnTkFJQXBCZ0lBRVJnUkFBMEFDUUNBQUlBTkdEUUFnQnlBRklBQkJBblJxS0FJQVFRSjBhaUlCSUFFb0FnQWlBVUVCYWpZQ0FDQUdJQUZCQW5ScUlBQTJBZ0FnQUVFQmFpRUFEQUVMQ3dVZ0J5QUtRUUowSWdKcUlBRWdBbW9vQWdBZ0RHb2lERFlDQUNBS1FRRnFJUW9NQVFzTEN3SUFDd3NKQVFCQmdRZ0xBZ1lCIik7CiAgfQogIGZ1bmN0aW9uIE8oQSkgewogICAgaWYgKEFycmF5QnVmZmVyLmlzVmlldyhBKSkKICAgICAgcmV0dXJuIEE7CiAgICBpZiAoQSA9PSBTICYmIE0pCiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShNKTsKICAgIGlmIChVKQogICAgICByZXR1cm4gVShBKTsKICAgIHRocm93ICdzeW5jIGZldGNoaW5nIG9mIHRoZSB3YXNtIGZhaWxlZDogeW91IGNhbiBwcmVsb2FkIGl0IHRvIE1vZHVsZVsid2FzbUJpbmFyeSJdIG1hbnVhbGx5LCBvciBlbWNjLnB5IHdpbGwgZG8gdGhhdCBmb3IgeW91IHdoZW4gZ2VuZXJhdGluZyBIVE1MIChidXQgbm90IEpTKSc7CiAgfQogIGZ1bmN0aW9uICQoQSwgQikgewogICAgdmFyIHQsIEUgPSBPKEEpOwogICAgdCA9IG5ldyBXZWJBc3NlbWJseS5Nb2R1bGUoRSk7CiAgICB2YXIgaSA9IG5ldyBXZWJBc3NlbWJseS5JbnN0YW5jZSh0LCBCKTsKICAgIHJldHVybiBbaSwgdF07CiAgfQogIGZ1bmN0aW9uIEFBKCkgewogICAgcmV0dXJuIHsgYTogbkEgfTsKICB9CiAgZnVuY3Rpb24gSUEoKSB7CiAgICBmdW5jdGlvbiBBKEUsIGkpIHsKICAgICAgcmV0dXJuIHkgPSBFLmV4cG9ydHMsIHUgPSB5LmIsIHEoKSwgckEoeSksIHooKSwgeTsKICAgIH0KICAgIF8oKTsKICAgIHZhciBCID0gQUEoKTsKICAgIGlmIChJLmluc3RhbnRpYXRlV2FzbSkKICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChFLCBpKSA9PiB7CiAgICAgICAgSS5pbnN0YW50aWF0ZVdhc20oQiwgKG8sIGgpID0+IHsKICAgICAgICAgIEUoQShvKSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgUyA/Pz0gVigpOwogICAgdmFyIHQgPSAkKFMsIEIpOwogICAgcmV0dXJuIEEodFswXSk7CiAgfQogIGZvciAodmFyIHggPSAoQSkgPT4gewogICAgZm9yICg7IEEubGVuZ3RoID4gMDsgKQogICAgICBBLnNoaWZ0KCkoSSk7CiAgfSwgdiA9IFtdLCBnQSA9IChBKSA9PiB2LnB1c2goQSksIFQgPSBbXSwgQ0EgPSAoQSkgPT4gVC5wdXNoKEEpLCBCQSA9IChBKSA9PiB7CiAgICBmb3IgKHZhciBCLCB0LCBFID0gMCwgaSA9IDAsIG8gPSBBLmxlbmd0aCwgaCA9IG5ldyBVaW50OEFycmF5KChvICogMyA+PiAyKSAtIChBW28gLSAyXSA9PSAiPSIpIC0gKEFbbyAtIDFdID09ICI9IikpOyBFIDwgbzsgRSArPSA0LCBpICs9IDMpCiAgICAgIEIgPSBuW0EuY2hhckNvZGVBdChFICsgMSldLCB0ID0gbltBLmNoYXJDb2RlQXQoRSArIDIpXSwgaFtpXSA9IG5bQS5jaGFyQ29kZUF0KEUpXSA8PCAyIHwgQiA+PiA0LCBoW2kgKyAxXSA9IEIgPDwgNCB8IHQgPj4gMiwgaFtpICsgMl0gPSB0IDw8IDYgfCBuW0EuY2hhckNvZGVBdChFICsgMyldOwogICAgcmV0dXJuIGg7CiAgfSwgUUEgPSAoKSA9PiAyMTQ3NDgzNjQ4LCBFQSA9IChBLCBCKSA9PiBNYXRoLmNlaWwoQSAvIEIpICogQiwgdEEgPSAoQSkgPT4gewogICAgdmFyIEIgPSB1LmJ1ZmZlciwgdCA9IChBIC0gQi5ieXRlTGVuZ3RoICsgNjU1MzUpIC8gNjU1MzYgfCAwOwogICAgdHJ5IHsKICAgICAgcmV0dXJuIHUuZ3Jvdyh0KSwgcSgpLCAxOwogICAgfSBjYXRjaCB7CiAgICB9CiAgfSwgaUEgPSAoQSkgPT4gewogICAgdmFyIEIgPSBMLmxlbmd0aDsKICAgIEEgPj4+PSAwOwogICAgdmFyIHQgPSBRQSgpOwogICAgaWYgKEEgPiB0KQogICAgICByZXR1cm4gITE7CiAgICBmb3IgKHZhciBFID0gMTsgRSA8PSA0OyBFICo9IDIpIHsKICAgICAgdmFyIGkgPSBCICogKDEgKyAwLjIgLyBFKTsKICAgICAgaSA9IE1hdGgubWluKGksIEEgKyAxMDA2NjMyOTYpOwogICAgICB2YXIgbyA9IE1hdGgubWluKHQsIEVBKE1hdGgubWF4KEEsIGkpLCA2NTUzNikpLCBoID0gdEEobyk7CiAgICAgIGlmIChoKQogICAgICAgIHJldHVybiAhMDsKICAgIH0KICAgIHJldHVybiAhMTsKICB9LCBuID0gbmV3IFVpbnQ4QXJyYXkoMTIzKSwgZSA9IDI1OyBlID49IDA7IC0tZSkKICAgIG5bNDggKyBlXSA9IDUyICsgZSwgbls2NSArIGVdID0gZSwgbls5NyArIGVdID0gMjYgKyBlOwogIG5bNDNdID0gNjIsIG5bNDddID0gNjMsIEkubm9FeGl0UnVudGltZSAmJiBJLm5vRXhpdFJ1bnRpbWUsIEkucHJpbnQgJiYgSS5wcmludCwgSS5wcmludEVyciAmJiBJLnByaW50RXJyLCBJLndhc21CaW5hcnkgJiYgKE0gPSBJLndhc21CaW5hcnkpLCBJLmFyZ3VtZW50cyAmJiBJLmFyZ3VtZW50cywgSS50aGlzUHJvZ3JhbSAmJiBJLnRoaXNQcm9ncmFtOwogIGZ1bmN0aW9uIHJBKEEpIHsKICAgIEkuX3NvcnQgPSBBLmQsIEkuX21hbGxvYyA9IEEuZSwgSS5fZnJlZSA9IEEuZjsKICB9CiAgdmFyIG5BID0geyBhOiBpQSB9LCB5ID0gSUEoKTsKICBmdW5jdGlvbiBtKCkgewogICAgaWYgKHMgPiAwKSB7CiAgICAgIGYgPSBtOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoUCgpLCBzID4gMCkgewogICAgICBmID0gbTsKICAgICAgcmV0dXJuOwogICAgfQogICAgZnVuY3Rpb24gQSgpIHsKICAgICAgSS5jYWxsZWRSdW4gPSAhMCwgYigpLCBJLm9uUnVudGltZUluaXRpYWxpemVkPy4oKSwgVygpOwogICAgfQogICAgSS5zZXRTdGF0dXMgPyAoSS5zZXRTdGF0dXMoIlJ1bm5pbmcuLi4iKSwgc2V0VGltZW91dCgoKSA9PiB7CiAgICAgIHNldFRpbWVvdXQoKCkgPT4gSS5zZXRTdGF0dXMoIiIpLCAxKSwgQSgpOwogICAgfSwgMSkpIDogQSgpOwogIH0KICBmdW5jdGlvbiBhQSgpIHsKICAgIGlmIChJLnByZUluaXQpCiAgICAgIGZvciAodHlwZW9mIEkucHJlSW5pdCA9PSAiZnVuY3Rpb24iICYmIChJLnByZUluaXQgPSBbSS5wcmVJbml0XSk7IEkucHJlSW5pdC5sZW5ndGggPiAwOyApCiAgICAgICAgSS5wcmVJbml0LnNoaWZ0KCkoKTsKICB9CiAgcmV0dXJuIGFBKCksIG0oKSwgciA9IEksIHI7Cn07CmxldCBnLCBRLCBkLCBjLCBOLCB3LCBwLCBSLCBrLCBKLCBhID0gMCwgWSA9IDAsIEggPSBbXSwgRyA9ICEwLCBEID0gITEsIEYgPSAhMSwgSyA9ICExOwphc3luYyBmdW5jdGlvbiBvQSgpIHsKICBpZiAoIWcgJiYgKGcgPSBhd2FpdCBlQSgpLCAhZyB8fCAhZy5IRUFQRjMyIHx8ICFnLl9zb3J0KSkKICAgIHRocm93IG5ldyBFcnJvcigiV0FTTSBtb2R1bGUgZmFpbGVkIHRvIGluaXRpYWxpemUgcHJvcGVybHkiKTsKfQpjb25zdCBaID0gYXN5bmMgKCkgPT4gewogIGlmIChEKSB7CiAgICBGID0gITA7CiAgICByZXR1cm47CiAgfQogIEQgPSAhMCwgRiA9ICExLCBnIHx8IGF3YWl0IG9BKCk7CiAgY29uc3QgQyA9IE1hdGgucG93KDIsIE1hdGguY2VpbChNYXRoLmxvZzIoUS52ZXJ0ZXhDb3VudCkpKTsKICBhIDwgQyAmJiAoYSA+IDAgJiYgKGcuX2ZyZWUoZCksIGcuX2ZyZWUoTiksIGcuX2ZyZWUodyksIGcuX2ZyZWUocCksIGcuX2ZyZWUoUiksIGcuX2ZyZWUoayksIGcuX2ZyZWUoSikpLCBhID0gQywgZCA9IGcuX21hbGxvYygxNiAqIDQpLCBOID0gZy5fbWFsbG9jKGEgKiA0KSwgdyA9IGcuX21hbGxvYygzICogYSAqIDQpLCBwID0gZy5fbWFsbG9jKGEgKiA0KSwgUiA9IGcuX21hbGxvYyhhICogNCksIGsgPSBnLl9tYWxsb2MoYSAqIDQpLCBKID0gZy5fbWFsbG9jKGEgKiA0KSksIFkgPCBRLnRyYW5zZm9ybXMubGVuZ3RoICYmIChZID4gMCAmJiBnLl9mcmVlKGMpLCBZID0gUS50cmFuc2Zvcm1zLmxlbmd0aCwgYyA9IGcuX21hbGxvYyhZICogNCkpLCBEID0gITEsIEYgJiYgKEYgPSAhMSwgYXdhaXQgWigpKTsKfSwgc0EgPSAoKSA9PiB7CiAgaWYgKCEoRCB8fCBGIHx8ICFnIHx8ICFRKSkgewogICAgRCA9ICEwOwogICAgdHJ5IHsKICAgICAgY29uc3QgQyA9IGcuSEVBUEYzMiwgciA9IGcuSEVBUFUzMjsKICAgICAgaWYgKHcgLyA0ICsgUS5wb3NpdGlvbnMubGVuZ3RoID4gQy5sZW5ndGgpCiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJQb3NpdGlvbnMgYnVmZmVyIG92ZXJmbG93Iik7CiAgICAgIGlmIChjIC8gNCArIFEudHJhbnNmb3Jtcy5sZW5ndGggPiBDLmxlbmd0aCkKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlRyYW5zZm9ybXMgYnVmZmVyIG92ZXJmbG93Iik7CiAgICAgIGlmIChOIC8gNCArIFEudHJhbnNmb3JtSW5kaWNlcy5sZW5ndGggPiByLmxlbmd0aCkKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlRyYW5zZm9ybSBpbmRpY2VzIGJ1ZmZlciBvdmVyZmxvdyIpOwogICAgICBpZiAoQy5zZXQoUS5wb3NpdGlvbnMsIHcgLyA0KSwgQy5zZXQoUS50cmFuc2Zvcm1zLCBjIC8gNCksIHIuc2V0KFEudHJhbnNmb3JtSW5kaWNlcywgTiAvIDQpLCBDLnNldChuZXcgRmxvYXQzMkFycmF5KEgpLCBkIC8gNCksIGcuX3NvcnQoCiAgICAgICAgZCwKICAgICAgICBjLAogICAgICAgIE4sCiAgICAgICAgUS52ZXJ0ZXhDb3VudCwKICAgICAgICB3LAogICAgICAgIHAsCiAgICAgICAgUiwKICAgICAgICBrLAogICAgICAgIEoKICAgICAgKSwgUiArIFEudmVydGV4Q291bnQgKiA0ID4gci5idWZmZXIuYnl0ZUxlbmd0aCkKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkRlcHRoIGluZGV4IGJ1ZmZlciBvdmVyZmxvdyIpOwogICAgICBjb25zdCBJID0gbmV3IFVpbnQzMkFycmF5KHIuYnVmZmVyLCBSLCBRLnZlcnRleENvdW50KSwgbCA9IG5ldyBVaW50MzJBcnJheShJLnNsaWNlKCkuYnVmZmVyKTsKICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7IGRlcHRoSW5kZXg6IGwgfSwgW2wuYnVmZmVyXSk7CiAgICB9IGNhdGNoIHsKICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7IGRlcHRoSW5kZXg6IG5ldyBVaW50MzJBcnJheSgwKSB9LCBbXSk7CiAgICB9CiAgICBEID0gITEsIEcgPSAhMTsKICB9Cn0sIFggPSAoKSA9PiB7CiAgSyB8fCAoSyA9ICEwLCBHICYmIHNBKCksIHNldFRpbWVvdXQoKCkgPT4gewogICAgSyA9ICExLCBYKCk7CiAgfSkpOwp9OwpzZWxmLm9ubWVzc2FnZSA9IChDKSA9PiB7CiAgQy5kYXRhLnNvcnREYXRhICYmIChRID8gKFEucG9zaXRpb25zLnNldChDLmRhdGEuc29ydERhdGEucG9zaXRpb25zKSwgUS50cmFuc2Zvcm1zLnNldChDLmRhdGEuc29ydERhdGEudHJhbnNmb3JtcyksIFEudHJhbnNmb3JtSW5kaWNlcy5zZXQoQy5kYXRhLnNvcnREYXRhLnRyYW5zZm9ybUluZGljZXMpLCBRLnZlcnRleENvdW50ID0gQy5kYXRhLnNvcnREYXRhLnZlcnRleENvdW50KSA6IFEgPSB7CiAgICBwb3NpdGlvbnM6IG5ldyBGbG9hdDMyQXJyYXkoQy5kYXRhLnNvcnREYXRhLnBvc2l0aW9ucyksCiAgICB0cmFuc2Zvcm1zOiBuZXcgRmxvYXQzMkFycmF5KEMuZGF0YS5zb3J0RGF0YS50cmFuc2Zvcm1zKSwKICAgIHRyYW5zZm9ybUluZGljZXM6IG5ldyBVaW50MzJBcnJheShDLmRhdGEuc29ydERhdGEudHJhbnNmb3JtSW5kaWNlcyksCiAgICB2ZXJ0ZXhDb3VudDogQy5kYXRhLnNvcnREYXRhLnZlcnRleENvdW50CiAgfSwgRyA9ICEwLCBaKCkpLCBDLmRhdGEudmlld1Byb2ogJiYgKEMuZGF0YS52aWV3UHJvai5ldmVyeSgocikgPT4gSC5pbmNsdWRlcyhyKSkgPT09ICExICYmIChIID0gQy5kYXRhLnZpZXdQcm9qLCBHID0gITApLCBYKCkpOwp9OwovLyMgc291cmNlTWFwcGluZ1VSTD1Tb3J0V29ya2VyLURRTDdVVEVoLmpzLm1hcAo="; var Et = (E) => Uint8Array.from(atob(E), (t) => t.charCodeAt(0)); var Qt = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", Et(Bt)], { type: "text/javascript;charset=utf-8" }); function St(E) { let t; try { if (t = Qt && (self.URL || self.webkitURL).createObjectURL(Qt), !t) throw ""; const n = new Worker(t, { type: "module", name: E?.name }); return n.addEventListener("error", () => { (self.URL || self.webkitURL).revokeObjectURL(t); }), n; } catch { return new Worker( "data:text/javascript;base64," + Bt, { type: "module", name: E?.name } ); } } var lt = class { constructor(t, n) { this._scene = null, this._camera = null, this._started = false, this._initialized = false, this._renderer = t; const i = t.gl; this._program = i.createProgram(), this._passes = n || []; const e = i.createShader(i.VERTEX_SHADER); i.shaderSource(e, this._getVertexSource()), i.compileShader(e), i.getShaderParameter(e, i.COMPILE_STATUS) || console.error(i.getShaderInfoLog(e)); const A = i.createShader(i.FRAGMENT_SHADER); i.shaderSource(A, this._getFragmentSource()), i.compileShader(A), i.getShaderParameter(A, i.COMPILE_STATUS) || console.error(i.getShaderInfoLog(A)), i.attachShader(this.program, e), i.attachShader(this.program, A), i.linkProgram(this.program), i.getProgramParameter(this.program, i.LINK_STATUS) || console.error(i.getProgramInfoLog(this.program)), this.resize = () => { i.useProgram(this._program), this._resize(); }, this.initialize = () => { console.assert(!this._initialized, "ShaderProgram already initialized"), i.useProgram(this._program), this._initialize(); for (const o of this.passes) o.initialize(this); this._initialized = true, this._started = true; }, this.render = (o, s) => { i.useProgram(this._program), (this._scene !== o || this._camera !== s) && (this.dispose(), this._scene = o, this._camera = s, this.initialize()); for (const r of this.passes) r.render(); this._render(); }, this.dispose = () => { if (this._initialized) { i.useProgram(this._program); for (const o of this.passes) o.dispose(); this._dispose(), this._scene = null, this._camera = null, this._initialized = false; } }; } get renderer() { return this._renderer; } get scene() { return this._scene; } get camera() { return this._camera; } get program() { return this._program; } get passes() { return this._passes; } get started() { return this._started; } }; var gt = "dmFyIG9BID0gZnVuY3Rpb24oQyA9IHt9KSB7CiAgdmFyIGUsIEEgPSBDLCBoID0gaW1wb3J0Lm1ldGEudXJsLCBrID0gIiIsIHk7CiAgewogICAgdHJ5IHsKICAgICAgayA9IG5ldyBVUkwoIi4iLCBoKS5ocmVmOwogICAgfSBjYXRjaCB7CiAgICB9CiAgICB5ID0gKGcpID0+IHsKICAgICAgdmFyIEIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsKICAgICAgcmV0dXJuIEIub3BlbigiR0VUIiwgZywgITEpLCBCLnJlc3BvbnNlVHlwZSA9ICJhcnJheWJ1ZmZlciIsIEIuc2VuZChudWxsKSwgbmV3IFVpbnQ4QXJyYXkoQi5yZXNwb25zZSk7CiAgICB9OwogIH0KICBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpLCBjb25zb2xlLmVycm9yLmJpbmQoY29uc29sZSk7CiAgdmFyIEYsIEQsIE47CiAgZnVuY3Rpb24gVSgpIHsKICAgIHZhciBnID0gRC5idWZmZXI7CiAgICBBLkhFQVBVOCA9IE4gPSBuZXcgVWludDhBcnJheShnKSwgQS5IRUFQVTMyID0gbmV3IFVpbnQzMkFycmF5KGcpLCBBLkhFQVBGMzIgPSBuZXcgRmxvYXQzMkFycmF5KGcpLCBuZXcgQmlnSW50NjRBcnJheShnKSwgbmV3IEJpZ1VpbnQ2NEFycmF5KGcpOwogIH0KICBmdW5jdGlvbiBpKCkgewogICAgaWYgKEEucHJlUnVuKQogICAgICBmb3IgKHR5cGVvZiBBLnByZVJ1biA9PSAiZnVuY3Rpb24iICYmIChBLnByZVJ1biA9IFtBLnByZVJ1bl0pOyBBLnByZVJ1bi5sZW5ndGg7ICkKICAgICAgICAkKEEucHJlUnVuLnNoaWZ0KCkpOwogICAgeChUKTsKICB9CiAgZnVuY3Rpb24gSCgpIHsKICAgIGYuYygpOwogIH0KICBmdW5jdGlvbiBiKCkgewogICAgaWYgKEEucG9zdFJ1bikKICAgICAgZm9yICh0eXBlb2YgQS5wb3N0UnVuID09ICJmdW5jdGlvbiIgJiYgKEEucG9zdFJ1biA9IFtBLnBvc3RSdW5dKTsgQS5wb3N0UnVuLmxlbmd0aDsgKQogICAgICAgIE8oQS5wb3N0UnVuLnNoaWZ0KCkpOwogICAgeChqKTsKICB9CiAgdmFyIHMgPSAwLCB3ID0gbnVsbDsKICBmdW5jdGlvbiB2KGcpIHsKICAgIHMrKywgQS5tb25pdG9yUnVuRGVwZW5kZW5jaWVzPy4ocyk7CiAgfQogIGZ1bmN0aW9uIFAoZykgewogICAgaWYgKHMtLSwgQS5tb25pdG9yUnVuRGVwZW5kZW5jaWVzPy4ocyksIHMgPT0gMCAmJiB3KSB7CiAgICAgIHZhciBCID0gdzsKICAgICAgdyA9IG51bGwsIEIoKTsKICAgIH0KICB9CiAgdmFyIG07CiAgZnVuY3Rpb24gWCgpIHsKICAgIHJldHVybiBBQSgiQUdGemJRRUFBQUFCSmdaZ0FYOEJmMkFDZlgwQmYyQUJmUUYvWUFGL0FHQUxmMzkvZjM5L2YzOS9mMzhBWUFBQUFnY0JBV0VCWVFBQUF3Z0hBQUVDQXdBRUJRVUhBUUdDQW9DQUFnWUlBWDhCUVlDTUJBc0hGUVVCWWdJQUFXTUFCd0ZrQUFZQlpRQUZBV1lBQkF3QkFRcXFRQWRQQVFKL1FZQUlLQUlBSWdFZ0FFRUhha0Y0Y1NJQ2FpRUFBa0FnQWtFQUlBQWdBVTBiUlFSQUlBQS9BRUVRZEUwTkFTQUFFQUFOQVF0QmhBaEJNRFlDQUVGL0R3dEJnQWdnQURZQ0FDQUJDdzRBSUFBUUF5QUJFQU5CRUhSeUMzSUJCSDhnQUx3aUJFSC8vLzhEY1NFQkFrQWdCRUVYZGtIL0FYRWlBa1VOQUNBQ1FmQUFUUVJBSUFGQmdJQ0FCSEpCOFFBZ0FtdDJJUUVNQVFzZ0FrR05BVXNFUUVHQStBRWhBMEVBSVFFTUFRc2dBa0VLZEVHQWdBZHJJUU1MSUFNZ0JFRVFka0dBZ0FKeGNpQUJRUTEyY2d2Y0N3RUlmd0pBSUFCRkRRQWdBRUVJYXlJRElBQkJCR3NvQWdBaUFrRjRjU0lBYWlFRkFrQWdBa0VCY1EwQUlBSkJBbkZGRFFFZ0F5QURLQUlBSWdScklnTkJtQWdvQWdCSkRRRWdBQ0FFYWlFQUFrQUNRQUpBUVp3SUtBSUFJQU5IQkVBZ0F5Z0NEQ0VCSUFSQi93Rk5CRUFnQVNBREtBSUlJZ0pIRFFKQmlBaEJpQWdvQWdCQmZpQUVRUU4yZDNFMkFnQU1CUXNnQXlnQ0dDRUhJQUVnQTBjRVFDQURLQUlJSWdJZ0FUWUNEQ0FCSUFJMkFnZ01CQXNnQXlnQ0ZDSUNCSDhnQTBFVWFnVWdBeWdDRUNJQ1JRMERJQU5CRUdvTElRUURRQ0FFSVFZZ0FpSUJRUlJxSVFRZ0FTZ0NGQ0lDRFFBZ0FVRVFhaUVFSUFFb0FoQWlBZzBBQ3lBR1FRQTJBZ0FNQXdzZ0JTZ0NCQ0lDUVFOeFFRTkhEUU5Ca0FnZ0FEWUNBQ0FGSUFKQmZuRTJBZ1FnQXlBQVFRRnlOZ0lFSUFVZ0FEWUNBQThMSUFJZ0FUWUNEQ0FCSUFJMkFnZ01BZ3RCQUNFQkN5QUhSUTBBQWtBZ0F5Z0NIQ0lFUVFKMFFiZ0thaUlDS0FJQUlBTkdCRUFnQWlBQk5nSUFJQUVOQVVHTUNFR01DQ2dDQUVGK0lBUjNjVFlDQUF3Q0N3SkFJQU1nQnlnQ0VFWUVRQ0FISUFFMkFoQU1BUXNnQnlBQk5nSVVDeUFCUlEwQkN5QUJJQWMyQWhnZ0F5Z0NFQ0lDQkVBZ0FTQUNOZ0lRSUFJZ0FUWUNHQXNnQXlnQ0ZDSUNSUTBBSUFFZ0FqWUNGQ0FDSUFFMkFoZ0xJQU1nQlU4TkFDQUZLQUlFSWdSQkFYRkZEUUFDUUFKQUFrQUNRQ0FFUVFKeFJRUkFRYUFJS0FJQUlBVkdCRUJCb0FnZ0F6WUNBRUdVQ0VHVUNDZ0NBQ0FBYWlJQU5nSUFJQU1nQUVFQmNqWUNCQ0FEUVp3SUtBSUFSdzBHUVpBSVFRQTJBZ0JCbkFoQkFEWUNBQThMUVp3SUtBSUFJZ2NnQlVZRVFFR2NDQ0FETmdJQVFaQUlRWkFJS0FJQUlBQnFJZ0EyQWdBZ0F5QUFRUUZ5TmdJRUlBQWdBMm9nQURZQ0FBOExJQVJCZUhFZ0FHb2hBQ0FGS0FJTUlRRWdCRUgvQVUwRVFDQUZLQUlJSWdJZ0FVWUVRRUdJQ0VHSUNDZ0NBRUYrSUFSQkEzWjNjVFlDQUF3RkN5QUNJQUUyQWd3Z0FTQUNOZ0lJREFRTElBVW9BaGdoQ0NBQklBVkhCRUFnQlNnQ0NDSUNJQUUyQWd3Z0FTQUNOZ0lJREFNTElBVW9BaFFpQWdSL0lBVkJGR29GSUFVb0FoQWlBa1VOQWlBRlFSQnFDeUVFQTBBZ0JDRUdJQUlpQVVFVWFpRUVJQUVvQWhRaUFnMEFJQUZCRUdvaEJDQUJLQUlRSWdJTkFBc2dCa0VBTmdJQURBSUxJQVVnQkVGK2NUWUNCQ0FESUFCQkFYSTJBZ1FnQUNBRGFpQUFOZ0lBREFNTFFRQWhBUXNnQ0VVTkFBSkFJQVVvQWh3aUJFRUNkRUc0Q21vaUFpZ0NBQ0FGUmdSQUlBSWdBVFlDQUNBQkRRRkJqQWhCakFnb0FnQkJmaUFFZDNFMkFnQU1BZ3NDUUNBRklBZ29BaEJHQkVBZ0NDQUJOZ0lRREFFTElBZ2dBVFlDRkFzZ0FVVU5BUXNnQVNBSU5nSVlJQVVvQWhBaUFnUkFJQUVnQWpZQ0VDQUNJQUUyQWhnTElBVW9BaFFpQWtVTkFDQUJJQUkyQWhRZ0FpQUJOZ0lZQ3lBRElBQkJBWEkyQWdRZ0FDQURhaUFBTmdJQUlBTWdCMGNOQUVHUUNDQUFOZ0lBRHdzZ0FFSC9BVTBFUUNBQVFYaHhRYkFJYWlFQ0FuOUJpQWdvQWdBaUJFRUJJQUJCQTNaMElnQnhSUVJBUVlnSUlBQWdCSEkyQWdBZ0Fnd0JDeUFDS0FJSUN5RUFJQUlnQXpZQ0NDQUFJQU0yQWd3Z0F5QUNOZ0lNSUFNZ0FEWUNDQThMUVI4aEFTQUFRZi8vL3dkTkJFQWdBRUVtSUFCQkNIWm5JZ0pyZGtFQmNTQUNRUUYwYTBFK2FpRUJDeUFESUFFMkFod2dBMElBTndJUUlBRkJBblJCdUFwcUlRUUNmd0pBQW45QmpBZ29BZ0FpQmtFQklBRjBJZ0p4UlFSQVFZd0lJQUlnQm5JMkFnQWdCQ0FETmdJQVFSZ2hBVUVJREFFTElBQkJHU0FCUVFGMmEwRUFJQUZCSDBjYmRDRUJJQVFvQWdBaEJBTkFJQVFpQWlnQ0JFRjRjU0FBUmcwQ0lBRkJIWFloQkNBQlFRRjBJUUVnQWlBRVFRUnhhaUlHS0FJUUlnUU5BQXNnQmlBRE5nSVFRUmdoQVNBQ0lRUkJDQXNoQUNBRElnSU1BUXNnQWlnQ0NDSUVJQU0yQWd3Z0FpQUROZ0lJUVJnaEFFRUlJUUZCQUFzaEJpQUJJQU5xSUFRMkFnQWdBeUFDTmdJTUlBQWdBMm9nQmpZQ0FFR29DRUdvQ0NnQ0FFRUJheUlBUVg4Z0FCczJBZ0FMQzlFbkFRdC9Jd0JCRUdzaUNpUUFBa0FDUUFKQUFrQUNRQUpBQWtBQ1FBSkFBa0FnQUVIMEFVMEVRRUdJQ0NnQ0FDSUVRUkFnQUVFTGFrSDRBM0VnQUVFTFNSc2lCa0VEZGlJQWRpSUJRUU54QkVBQ1FDQUJRWDl6UVFGeElBQnFJZ0pCQTNRaUFVR3dDR29pQUNBQlFiZ0lhaWdDQUNJQktBSUlJZ1ZHQkVCQmlBZ2dCRUYrSUFKM2NUWUNBQXdCQ3lBRklBQTJBZ3dnQUNBRk5nSUlDeUFCUVFocUlRQWdBU0FDUVFOMElnSkJBM0kyQWdRZ0FTQUNhaUlCSUFFb0FnUkJBWEkyQWdRTUN3c2dCa0dRQ0NnQ0FDSUlUUTBCSUFFRVFBSkFRUUlnQUhRaUFrRUFJQUpyY2lBQklBQjBjV2dpQVVFRGRDSUFRYkFJYWlJQ0lBQkJ1QWhxS0FJQUlnQW9BZ2dpQlVZRVFFR0lDQ0FFUVg0Z0FYZHhJZ1EyQWdBTUFRc2dCU0FDTmdJTUlBSWdCVFlDQ0FzZ0FDQUdRUU55TmdJRUlBQWdCbW9pQnlBQlFRTjBJZ0VnQm1zaUJVRUJjallDQkNBQUlBRnFJQVUyQWdBZ0NBUkFJQWhCZUhGQnNBaHFJUUZCbkFnb0FnQWhBZ0ovSUFSQkFTQUlRUU4yZENJRGNVVUVRRUdJQ0NBRElBUnlOZ0lBSUFFTUFRc2dBU2dDQ0FzaEF5QUJJQUkyQWdnZ0F5QUNOZ0lNSUFJZ0FUWUNEQ0FDSUFNMkFnZ0xJQUJCQ0dvaEFFR2NDQ0FITmdJQVFaQUlJQVUyQWdBTUN3dEJqQWdvQWdBaUMwVU5BU0FMYUVFQ2RFRzRDbW9vQWdBaUFpZ0NCRUY0Y1NBR2F5RURJQUloQVFOQUFrQWdBU2dDRUNJQVJRUkFJQUVvQWhRaUFFVU5BUXNnQUNnQ0JFRjRjU0FHYXlJQklBTWdBU0FEU1NJQkd5RURJQUFnQWlBQkd5RUNJQUFoQVF3QkN3c2dBaWdDR0NFSklBSWdBaWdDRENJQVJ3UkFJQUlvQWdnaUFTQUFOZ0lNSUFBZ0FUWUNDQXdLQ3lBQ0tBSVVJZ0VFZnlBQ1FSUnFCU0FDS0FJUUlnRkZEUU1nQWtFUWFnc2hCUU5BSUFVaEJ5QUJJZ0JCRkdvaEJTQUFLQUlVSWdFTkFDQUFRUkJxSVFVZ0FDZ0NFQ0lCRFFBTElBZEJBRFlDQUF3SkMwRi9JUVlnQUVHL2Ywc05BQ0FBUVF0cUlnRkJlSEVoQmtHTUNDZ0NBQ0lIUlEwQVFSOGhDRUVBSUFacklRTWdBRUgwLy84SFRRUkFJQVpCSmlBQlFRaDJaeUlBYTNaQkFYRWdBRUVCZEd0QlBtb2hDQXNDUUFKQUFrQWdDRUVDZEVHNENtb29BZ0FpQVVVRVFFRUFJUUFNQVF0QkFDRUFJQVpCR1NBSVFRRjJhMEVBSUFoQkgwY2JkQ0VDQTBBQ1FDQUJLQUlFUVhoeElBWnJJZ1FnQTA4TkFDQUJJUVVnQkNJRERRQkJBQ0VESUFFaEFBd0RDeUFBSUFFb0FoUWlCQ0FFSUFFZ0FrRWRka0VFY1dvb0FoQWlBVVliSUFBZ0JCc2hBQ0FDUVFGMElRSWdBUTBBQ3dzZ0FDQUZja1VFUUVFQUlRVkJBaUFJZENJQVFRQWdBR3R5SUFkeElnQkZEUU1nQUdoQkFuUkJ1QXBxS0FJQUlRQUxJQUJGRFFFTEEwQWdBQ2dDQkVGNGNTQUdheUlDSUFOSklRRWdBaUFESUFFYklRTWdBQ0FGSUFFYklRVWdBQ2dDRUNJQkJIOGdBUVVnQUNnQ0ZBc2lBQTBBQ3dzZ0JVVU5BQ0FEUVpBSUtBSUFJQVpyVHcwQUlBVW9BaGdoQ0NBRklBVW9BZ3dpQUVjRVFDQUZLQUlJSWdFZ0FEWUNEQ0FBSUFFMkFnZ01DQXNnQlNnQ0ZDSUJCSDhnQlVFVWFnVWdCU2dDRUNJQlJRMERJQVZCRUdvTElRSURRQ0FDSVFRZ0FTSUFRUlJxSVFJZ0FDZ0NGQ0lCRFFBZ0FFRVFhaUVDSUFBb0FoQWlBUTBBQ3lBRVFRQTJBZ0FNQndzZ0JrR1FDQ2dDQUNJRlRRUkFRWndJS0FJQUlRQUNRQ0FGSUFacklnRkJFRThFUUNBQUlBWnFJZ0lnQVVFQmNqWUNCQ0FBSUFWcUlBRTJBZ0FnQUNBR1FRTnlOZ0lFREFFTElBQWdCVUVEY2pZQ0JDQUFJQVZxSWdFZ0FTZ0NCRUVCY2pZQ0JFRUFJUUpCQUNFQkMwR1FDQ0FCTmdJQVFad0lJQUkyQWdBZ0FFRUlhaUVBREFrTElBWkJsQWdvQWdBaUFra0VRRUdVQ0NBQ0lBWnJJZ0UyQWdCQm9BaEJvQWdvQWdBaUFDQUdhaUlDTmdJQUlBSWdBVUVCY2pZQ0JDQUFJQVpCQTNJMkFnUWdBRUVJYWlFQURBa0xRUUFoQUNBR1FTOXFJZ01DZjBIZ0N5Z0NBQVJBUWVnTEtBSUFEQUVMUWV3TFFuODNBZ0JCNUF0Q2dLQ0FnSUNBQkRjQ0FFSGdDeUFLUVF4cVFYQnhRZGlxMWFvRmN6WUNBRUgwQzBFQU5nSUFRY1FMUVFBMkFnQkJnQ0FMSWdGcUlnUkJBQ0FCYXlJSGNTSUJJQVpORFFoQndBc29BZ0FpQlFSQVFiZ0xLQUlBSWdnZ0FXb2lDU0FJVFNBRklBbEpjZzBKQ3dKQVFjUUxMUUFBUVFSeFJRUkFBa0FDUUFKQUFrQkJvQWdvQWdBaUJRUkFRY2dMSVFBRFFDQUFLQUlBSWdnZ0JVMEVRQ0FGSUFnZ0FDZ0NCR3BKRFFNTElBQW9BZ2dpQUEwQUN3dEJBQkFCSWdKQmYwWU5BeUFCSVFSQjVBc29BZ0FpQUVFQmF5SUZJQUp4QkVBZ0FTQUNheUFDSUFWcVFRQWdBR3R4YWlFRUN5QUVJQVpORFFOQndBc29BZ0FpQUFSQVFiZ0xLQUlBSWdVZ0JHb2lCeUFGVFNBQUlBZEpjZzBFQ3lBRUVBRWlBQ0FDUncwQkRBVUxJQVFnQW1zZ0IzRWlCQkFCSWdJZ0FDZ0NBQ0FBS0FJRWFrWU5BU0FDSVFBTElBQkJmMFlOQVNBR1FUQnFJQVJOQkVBZ0FDRUNEQVFMUWVnTEtBSUFJZ0lnQXlBRWEycEJBQ0FDYTNFaUFoQUJRWDlHRFFFZ0FpQUVhaUVFSUFBaEFnd0RDeUFDUVg5SERRSUxRY1FMUWNRTEtBSUFRUVJ5TmdJQUN5QUJFQUVpQWtGL1JrRUFFQUVpQUVGL1JuSWdBQ0FDVFhJTkJTQUFJQUpySWdRZ0JrRW9hazBOQlF0QnVBdEJ1QXNvQWdBZ0JHb2lBRFlDQUVHOEN5Z0NBQ0FBU1FSQVFid0xJQUEyQWdBTEFrQkJvQWdvQWdBaUF3UkFRY2dMSVFBRFFDQUNJQUFvQWdBaUFTQUFLQUlFSWdWcVJnMENJQUFvQWdnaUFBMEFDd3dFQzBHWUNDZ0NBQ0lBUVFBZ0FDQUNUUnRGQkVCQm1BZ2dBallDQUF0QkFDRUFRY3dMSUFRMkFnQkJ5QXNnQWpZQ0FFR29DRUYvTmdJQVFhd0lRZUFMS0FJQU5nSUFRZFFMUVFBMkFnQURRQ0FBUVFOMElnRkJ1QWhxSUFGQnNBaHFJZ1UyQWdBZ0FVRzhDR29nQlRZQ0FDQUFRUUZxSWdCQklFY05BQXRCbEFnZ0JFRW9heUlBUVhnZ0FtdEJCM0VpQVdzaUJUWUNBRUdnQ0NBQklBSnFJZ0UyQWdBZ0FTQUZRUUZ5TmdJRUlBQWdBbXBCS0RZQ0JFR2tDRUh3Q3lnQ0FEWUNBQXdFQ3lBQ0lBTk5JQUVnQTB0eURRSWdBQ2dDREVFSWNRMENJQUFnQkNBRmFqWUNCRUdnQ0NBRFFYZ2dBMnRCQjNFaUFHb2lBVFlDQUVHVUNFR1VDQ2dDQUNBRWFpSUNJQUJySWdBMkFnQWdBU0FBUVFGeU5nSUVJQUlnQTJwQktEWUNCRUdrQ0VId0N5Z0NBRFlDQUF3REMwRUFJUUFNQmd0QkFDRUFEQVFMUVpnSUtBSUFJQUpMQkVCQm1BZ2dBallDQUFzZ0FpQUVhaUVGUWNnTElRQUNRQU5BSUFVZ0FDZ0NBQ0lCUndSQUlBQW9BZ2dpQUEwQkRBSUxDeUFBTFFBTVFRaHhSUTBEQzBISUN5RUFBMEFDUUNBQUtBSUFJZ0VnQTAwRVFDQURJQUVnQUNnQ0JHb2lCVWtOQVFzZ0FDZ0NDQ0VBREFFTEMwR1VDQ0FFUVNocklnQkJlQ0FDYTBFSGNTSUJheUlITmdJQVFhQUlJQUVnQW1vaUFUWUNBQ0FCSUFkQkFYSTJBZ1FnQUNBQ2FrRW9OZ0lFUWFRSVFmQUxLQUlBTmdJQUlBTWdCVUVuSUFWclFRZHhha0V2YXlJQUlBQWdBMEVRYWtrYklnRkJHellDQkNBQlFkQUxLUUlBTndJUUlBRkJ5QXNwQWdBM0FnaEIwQXNnQVVFSWFqWUNBRUhNQ3lBRU5nSUFRY2dMSUFJMkFnQkIxQXRCQURZQ0FDQUJRUmhxSVFBRFFDQUFRUWMyQWdRZ0FFRUlhaUFBUVFScUlRQWdCVWtOQUFzZ0FTQURSZzBBSUFFZ0FTZ0NCRUYrY1RZQ0JDQURJQUVnQTJzaUFrRUJjallDQkNBQklBSTJBZ0FDZnlBQ1FmOEJUUVJBSUFKQmVIRkJzQWhxSVFBQ2YwR0lDQ2dDQUNJQlFRRWdBa0VEZG5RaUFuRkZCRUJCaUFnZ0FTQUNjallDQUNBQURBRUxJQUFvQWdnTElRRWdBQ0FETmdJSUlBRWdBellDREVFTUlRSkJDQXdCQzBFZklRQWdBa0gvLy84SFRRUkFJQUpCSmlBQ1FRaDJaeUlBYTNaQkFYRWdBRUVCZEd0QlBtb2hBQXNnQXlBQU5nSWNJQU5DQURjQ0VDQUFRUUowUWJnS2FpRUJBa0FDUUVHTUNDZ0NBQ0lGUVFFZ0FIUWlCSEZGQkVCQmpBZ2dCQ0FGY2pZQ0FDQUJJQU0yQWdBTUFRc2dBa0VaSUFCQkFYWnJRUUFnQUVFZlJ4dDBJUUFnQVNnQ0FDRUZBMEFnQlNJQktBSUVRWGh4SUFKR0RRSWdBRUVkZGlFRklBQkJBWFFoQUNBQklBVkJCSEZxSWdRb0FoQWlCUTBBQ3lBRUlBTTJBaEFMSUFNZ0FUWUNHRUVJSVFJZ0F5SUJJUUJCREF3QkN5QUJLQUlJSWdBZ0F6WUNEQ0FCSUFNMkFnZ2dBeUFBTmdJSVFRQWhBRUVZSVFKQkRBc2dBMm9nQVRZQ0FDQUNJQU5xSUFBMkFnQUxRWlFJS0FJQUlnQWdCazBOQUVHVUNDQUFJQVpySWdFMkFnQkJvQWhCb0Fnb0FnQWlBQ0FHYWlJQ05nSUFJQUlnQVVFQmNqWUNCQ0FBSUFaQkEzSTJBZ1FnQUVFSWFpRUFEQVFMUVlRSVFUQTJBZ0JCQUNFQURBTUxJQUFnQWpZQ0FDQUFJQUFvQWdRZ0JHbzJBZ1FnQWtGNElBSnJRUWR4YWlJSUlBWkJBM0kyQWdRZ0FVRjRJQUZyUVFkeGFpSUVJQVlnQ0dvaUEyc2hCd0pBUWFBSUtBSUFJQVJHQkVCQm9BZ2dBellDQUVHVUNFR1VDQ2dDQUNBSGFpSUFOZ0lBSUFNZ0FFRUJjallDQkF3QkMwR2NDQ2dDQUNBRVJnUkFRWndJSUFNMkFnQkJrQWhCa0Fnb0FnQWdCMm9pQURZQ0FDQURJQUJCQVhJMkFnUWdBQ0FEYWlBQU5nSUFEQUVMSUFRb0FnUWlBRUVEY1VFQlJnUkFJQUJCZUhFaENTQUVLQUlNSVFJQ1FDQUFRZjhCVFFSQUlBUW9BZ2dpQVNBQ1JnUkFRWWdJUVlnSUtBSUFRWDRnQUVFRGRuZHhOZ0lBREFJTElBRWdBallDRENBQ0lBRTJBZ2dNQVFzZ0JDZ0NHQ0VHQWtBZ0FpQUVSd1JBSUFRb0FnZ2lBQ0FDTmdJTUlBSWdBRFlDQ0F3QkN3SkFJQVFvQWhRaUFBUi9JQVJCRkdvRklBUW9BaEFpQUVVTkFTQUVRUkJxQ3lFQkEwQWdBU0VGSUFBaUFrRVVhaUVCSUFBb0FoUWlBQTBBSUFKQkVHb2hBU0FDS0FJUUlnQU5BQXNnQlVFQU5nSUFEQUVMUVFBaEFnc2dCa1VOQUFKQUlBUW9BaHdpQUVFQ2RFRzRDbW9pQVNnQ0FDQUVSZ1JBSUFFZ0FqWUNBQ0FDRFFGQmpBaEJqQWdvQWdCQmZpQUFkM0UyQWdBTUFnc0NRQ0FFSUFZb0FoQkdCRUFnQmlBQ05nSVFEQUVMSUFZZ0FqWUNGQXNnQWtVTkFRc2dBaUFHTmdJWUlBUW9BaEFpQUFSQUlBSWdBRFlDRUNBQUlBSTJBaGdMSUFRb0FoUWlBRVVOQUNBQ0lBQTJBaFFnQUNBQ05nSVlDeUFISUFscUlRY2dCQ0FKYWlJRUtBSUVJUUFMSUFRZ0FFRitjVFlDQkNBRElBZEJBWEkyQWdRZ0F5QUhhaUFITmdJQUlBZEIvd0ZOQkVBZ0IwRjRjVUd3Q0dvaEFBSi9RWWdJS0FJQUlnRkJBU0FIUVFOMmRDSUNjVVVFUUVHSUNDQUJJQUp5TmdJQUlBQU1BUXNnQUNnQ0NBc2hBU0FBSUFNMkFnZ2dBU0FETmdJTUlBTWdBRFlDRENBRElBRTJBZ2dNQVF0Qkh5RUNJQWRCLy8vL0IwMEVRQ0FIUVNZZ0IwRUlkbWNpQUd0MlFRRnhJQUJCQVhSclFUNXFJUUlMSUFNZ0FqWUNIQ0FEUWdBM0FoQWdBa0VDZEVHNENtb2hBQUpBQWtCQmpBZ29BZ0FpQVVFQklBSjBJZ1Z4UlFSQVFZd0lJQUVnQlhJMkFnQWdBQ0FETmdJQURBRUxJQWRCR1NBQ1FRRjJhMEVBSUFKQkgwY2JkQ0VDSUFBb0FnQWhBUU5BSUFFaUFDZ0NCRUY0Y1NBSFJnMENJQUpCSFhZaEFTQUNRUUYwSVFJZ0FDQUJRUVJ4YWlJRktBSVFJZ0VOQUFzZ0JTQUROZ0lRQ3lBRElBQTJBaGdnQXlBRE5nSU1JQU1nQXpZQ0NBd0JDeUFBS0FJSUlnRWdBellDRENBQUlBTTJBZ2dnQTBFQU5nSVlJQU1nQURZQ0RDQURJQUUyQWdnTElBaEJDR29oQUF3Q0N3SkFJQWhGRFFBQ1FDQUZLQUljSWdGQkFuUkJ1QXBxSWdJb0FnQWdCVVlFUUNBQ0lBQTJBZ0FnQUEwQlFZd0lJQWRCZmlBQmQzRWlCellDQUF3Q0N3SkFJQVVnQ0NnQ0VFWUVRQ0FJSUFBMkFoQU1BUXNnQ0NBQU5nSVVDeUFBUlEwQkN5QUFJQWcyQWhnZ0JTZ0NFQ0lCQkVBZ0FDQUJOZ0lRSUFFZ0FEWUNHQXNnQlNnQ0ZDSUJSUTBBSUFBZ0FUWUNGQ0FCSUFBMkFoZ0xBa0FnQTBFUFRRUkFJQVVnQXlBR2FpSUFRUU55TmdJRUlBQWdCV29pQUNBQUtBSUVRUUZ5TmdJRURBRUxJQVVnQmtFRGNqWUNCQ0FGSUFacUlnUWdBMEVCY2pZQ0JDQURJQVJxSUFNMkFnQWdBMEgvQVUwRVFDQURRWGh4UWJBSWFpRUFBbjlCaUFnb0FnQWlBVUVCSUFOQkEzWjBJZ0p4UlFSQVFZZ0lJQUVnQW5JMkFnQWdBQXdCQ3lBQUtBSUlDeUVCSUFBZ0JEWUNDQ0FCSUFRMkFnd2dCQ0FBTmdJTUlBUWdBVFlDQ0F3QkMwRWZJUUFnQTBILy8vOEhUUVJBSUFOQkppQURRUWgyWnlJQWEzWkJBWEVnQUVFQmRHdEJQbW9oQUFzZ0JDQUFOZ0ljSUFSQ0FEY0NFQ0FBUVFKMFFiZ0thaUVCQWtBQ1FDQUhRUUVnQUhRaUFuRkZCRUJCakFnZ0FpQUhjallDQUNBQklBUTJBZ0FnQkNBQk5nSVlEQUVMSUFOQkdTQUFRUUYyYTBFQUlBQkJIMGNiZENFQUlBRW9BZ0FoQVFOQUlBRWlBaWdDQkVGNGNTQURSZzBDSUFCQkhYWWhBU0FBUVFGMElRQWdBaUFCUVFSeGFpSUhLQUlRSWdFTkFBc2dCeUFFTmdJUUlBUWdBallDR0FzZ0JDQUVOZ0lNSUFRZ0JEWUNDQXdCQ3lBQ0tBSUlJZ0FnQkRZQ0RDQUNJQVEyQWdnZ0JFRUFOZ0lZSUFRZ0FqWUNEQ0FFSUFBMkFnZ0xJQVZCQ0dvaEFBd0JDd0pBSUFsRkRRQUNRQ0FDS0FJY0lnRkJBblJCdUFwcUlnVW9BZ0FnQWtZRVFDQUZJQUEyQWdBZ0FBMEJRWXdJSUF0QmZpQUJkM0UyQWdBTUFnc0NRQ0FDSUFrb0FoQkdCRUFnQ1NBQU5nSVFEQUVMSUFrZ0FEWUNGQXNnQUVVTkFRc2dBQ0FKTmdJWUlBSW9BaEFpQVFSQUlBQWdBVFlDRUNBQklBQTJBaGdMSUFJb0FoUWlBVVVOQUNBQUlBRTJBaFFnQVNBQU5nSVlDd0pBSUFOQkQwMEVRQ0FDSUFNZ0Jtb2lBRUVEY2pZQ0JDQUFJQUpxSWdBZ0FDZ0NCRUVCY2pZQ0JBd0JDeUFDSUFaQkEzSTJBZ1FnQWlBR2FpSUZJQU5CQVhJMkFnUWdBeUFGYWlBRE5nSUFJQWdFUUNBSVFYaHhRYkFJYWlFQVFad0lLQUlBSVFFQ2YwRUJJQWhCQTNaMElnY2dCSEZGQkVCQmlBZ2dCQ0FIY2pZQ0FDQUFEQUVMSUFBb0FnZ0xJUVFnQUNBQk5nSUlJQVFnQVRZQ0RDQUJJQUEyQWd3Z0FTQUVOZ0lJQzBHY0NDQUZOZ0lBUVpBSUlBTTJBZ0FMSUFKQkNHb2hBQXNnQ2tFUWFpUUFJQUFMb1FzQ0MzOEpmU01BUWFBQmF5SUxKQUFnQzBFd2FrRUFRU1Q4Q3dBRFFDQUJJQTVIQkVBZ0FpQU9RUU5zSWd4QkFtcEJBblFpRDJvcUFnQWhGeUFDSUF4QkFXcEJBblFpRUdvcUFnQWhHQ0FJSUF4QkFuUWlFV29nQWlBUmFpb0NBQ0laT0FJQUlBZ2dFR29nR0RnQ0FDQUlJQTlxSUJjNEFnQWdCeUFPUVFWMGFpSU5RUUEyQWd3Z0RTQVhPQUlJSUEwZ0dEZ0NCQ0FOSUJrNEFnQUNRQ0FBUlFSQUlBWWdEbW90QUFCRkRRRUxJQTFCZ0lDQUNEWUNEQXNnRFNBRklBNUJBblFpREVFQmNpSVNhaTBBQUVFSWRDQUZJQXhxTFFBQWNpQUZJQXhCQW5JaUUyb3RBQUJCRUhSeUlBVWdERUVEY2lJTWFpMEFBRUVZZEhJMkFod2dDeUFESUJKQkFuUWlFbW9xQWdBaUZ6Z0NrQUVnQ3lBRElCTkJBblFpRTJvcUFnQWlHRGdDbEFFZ0N5QURJQXhCQW5RaUZHb3FBZ0FpR1RnQ21BRWdDeUFESUE1QkJIUWlGV29xQWdDTUlobzRBcHdCSUF0QjRBQnFJZ3dnQ3lvQ21BRWlGa01BQUFEQWxDQVdsQ0FMS2dLVUFTSVdRd0FBQU1DVUlCYVVRd0FBZ0QrU2tqZ0NBQ0FNSUFzcUFwQUJJaFlnRnBJZ0N5b0NsQUdVSUFzcUFwZ0JJaFlnRnBJZ0N5b0NuQUdVa3pnQ0JDQU1JQXNxQXBBQkloWWdGcElnQ3lvQ21BR1VJQXNxQXBRQkloWWdGcElnQ3lvQ25BR1VramdDQ0NBTUlBc3FBcEFCSWhZZ0ZwSWdDeW9DbEFHVUlBc3FBcGdCSWhZZ0ZwSWdDeW9DbkFHVWtqZ0NEQ0FNSUFzcUFwZ0JJaFpEQUFBQXdKUWdGcFFnQ3lvQ2tBRWlGa01BQUFEQWxDQVdsRU1BQUlBL2twSTRBaEFnRENBTEtnS1VBU0lXSUJhU0lBc3FBcGdCbENBTEtnS1FBU0lXSUJhU0lBc3FBcHdCbEpNNEFoUWdEQ0FMS2dLUUFTSVdJQmFTSUFzcUFwZ0JsQ0FMS2dLVUFTSVdJQmFTSUFzcUFwd0JsSk00QWhnZ0RDQUxLZ0tVQVNJV0lCYVNJQXNxQXBnQmxDQUxLZ0tRQVNJV0lCYVNJQXNxQXB3QmxKSTRBaHdnRENBTEtnS1VBU0lXUXdBQUFNQ1VJQmFVSUFzcUFwQUJJaFpEQUFBQXdKUWdGcFJEQUFDQVA1S1NPQUlnSUFrZ0ZXb2dGemdDQUNBSklCSnFJQmc0QWdBZ0NTQVRhaUFaT0FJQUlBa2dGR29nR2pnQ0FDQUxJQVFnRVdvcUFnQWlGemdDTUNBTElBUWdFR29xQWdBaUdEZ0NRQ0FMSUFRZ0Qyb3FBZ0FpR1RnQ1VDQUtJQkZxSUJjNEFnQWdDaUFRYWlBWU9BSUFJQW9nRDJvZ0dUZ0NBQ0FMSUF3cUFoZ2dDeW9DT0pRZ0RDb0NBQ0FMS2dJd2xDQU1LZ0lNSUFzcUFqU1VrcEk0QWdBZ0N5QU1LZ0ljSUFzcUFqaVVJQXdxQWdRZ0N5b0NNSlFnRENvQ0VDQUxLZ0kwbEpLU09BSUVJQXNnRENvQ0lDQUxLZ0k0bENBTUtnSUlJQXNxQWpDVUlBd3FBaFFnQ3lvQ05KU1NramdDQ0NBTElBd3FBaGdnQ3lvQ1JKUWdEQ29DQUNBTEtnSThsQ0FNS2dJTUlBc3FBa0NVa3BJNEFnd2dDeUFNS2dJY0lBc3FBa1NVSUF3cUFnUWdDeW9DUEpRZ0RDb0NFQ0FMS2dKQWxKS1NPQUlRSUFzZ0RDb0NJQ0FMS2dKRWxDQU1LZ0lJSUFzcUFqeVVJQXdxQWhRZ0N5b0NRSlNTa2pnQ0ZDQUxJQXdxQWhnZ0N5b0NVSlFnRENvQ0FDQUxLZ0pJbENBTUtnSU1JQXNxQWt5VWtwSTRBaGdnQ3lBTUtnSWNJQXNxQWxDVUlBd3FBZ1FnQ3lvQ1NKUWdEQ29DRUNBTEtnSk1sSktTT0FJY0lBc2dEQ29DSUNBTEtnSlFsQ0FNS2dJSUlBc3FBa2lVSUF3cUFoUWdDeW9DVEpTU2tqZ0NJQ0FMS2dJZ0lSY2dDeW9DQ0NFWUlBc3FBaFFoR1NBTklBc3FBaGdpR2lBYWxDQUxLZ0lBSWhZZ0ZwUWdDeW9DRENJYklCdVVrcEpEQUFDQVFKUWdHaUFMS2dJY0loeVVJQllnQ3lvQ0JDSWRsQ0FiSUFzcUFoQWlIcFNTa2tNQUFJQkFsQkFDTmdJUUlBMGdHaUFYbENBV0lCaVVJQnNnR1pTU2trTUFBSUJBbENBY0lCeVVJQjBnSFpRZ0hpQWVsSktTUXdBQWdFQ1VFQUkyQWhRZ0RTQWNJQmVVSUIwZ0dKUWdIaUFabEpLU1F3QUFnRUNVSUJjZ0Y1UWdHQ0FZbENBWklCbVVrcEpEQUFDQVFKUVFBallDR0NBT1FRRnFJUTRNQVFzTElBdEJvQUZxSkFBTEFnQUxDd2tCQUVHQkNBc0NCZ0U9Iik7CiAgfQogIGZ1bmN0aW9uIFcoZykgewogICAgaWYgKEFycmF5QnVmZmVyLmlzVmlldyhnKSkKICAgICAgcmV0dXJuIGc7CiAgICBpZiAoZyA9PSBtICYmIEYpCiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShGKTsKICAgIGlmICh5KQogICAgICByZXR1cm4geShnKTsKICAgIHRocm93ICdzeW5jIGZldGNoaW5nIG9mIHRoZSB3YXNtIGZhaWxlZDogeW91IGNhbiBwcmVsb2FkIGl0IHRvIE1vZHVsZVsid2FzbUJpbmFyeSJdIG1hbnVhbGx5LCBvciBlbWNjLnB5IHdpbGwgZG8gdGhhdCBmb3IgeW91IHdoZW4gZ2VuZXJhdGluZyBIVE1MIChidXQgbm90IEpTKSc7CiAgfQogIGZ1bmN0aW9uIF8oZywgQikgewogICAgdmFyIEUsIFEgPSBXKGcpOwogICAgRSA9IG5ldyBXZWJBc3NlbWJseS5Nb2R1bGUoUSk7CiAgICB2YXIgbyA9IG5ldyBXZWJBc3NlbWJseS5JbnN0YW5jZShFLCBCKTsKICAgIHJldHVybiBbbywgRV07CiAgfQogIGZ1bmN0aW9uIFYoKSB7CiAgICByZXR1cm4geyBhOiBFQSB9OwogIH0KICBmdW5jdGlvbiB6KCkgewogICAgZnVuY3Rpb24gZyhRLCBvKSB7CiAgICAgIHJldHVybiBmID0gUS5leHBvcnRzLCBEID0gZi5iLCBVKCksIFFBKGYpLCBQKCksIGY7CiAgICB9CiAgICB2KCk7CiAgICB2YXIgQiA9IFYoKTsKICAgIGlmIChBLmluc3RhbnRpYXRlV2FzbSkKICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChRLCBvKSA9PiB7CiAgICAgICAgQS5pbnN0YW50aWF0ZVdhc20oQiwgKHIsIGMpID0+IHsKICAgICAgICAgIFEoZyhyKSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgbSA/Pz0gWCgpOwogICAgdmFyIEUgPSBfKG0sIEIpOwogICAgcmV0dXJuIGcoRVswXSk7CiAgfQogIGZvciAodmFyIHggPSAoZykgPT4gewogICAgZm9yICg7IGcubGVuZ3RoID4gMDsgKQogICAgICBnLnNoaWZ0KCkoQSk7CiAgfSwgaiA9IFtdLCBPID0gKGcpID0+IGoucHVzaChnKSwgVCA9IFtdLCAkID0gKGcpID0+IFQucHVzaChnKSwgQUEgPSAoZykgPT4gewogICAgZm9yICh2YXIgQiwgRSwgUSA9IDAsIG8gPSAwLCByID0gZy5sZW5ndGgsIGMgPSBuZXcgVWludDhBcnJheSgociAqIDMgPj4gMikgLSAoZ1tyIC0gMl0gPT0gIj0iKSAtIChnW3IgLSAxXSA9PSAiPSIpKTsgUSA8IHI7IFEgKz0gNCwgbyArPSAzKQogICAgICBCID0gbltnLmNoYXJDb2RlQXQoUSArIDEpXSwgRSA9IG5bZy5jaGFyQ29kZUF0KFEgKyAyKV0sIGNbb10gPSBuW2cuY2hhckNvZGVBdChRKV0gPDwgMiB8IEIgPj4gNCwgY1tvICsgMV0gPSBCIDw8IDQgfCBFID4+IDIsIGNbbyArIDJdID0gRSA8PCA2IHwgbltnLmNoYXJDb2RlQXQoUSArIDMpXTsKICAgIHJldHVybiBjOwogIH0sIGdBID0gKCkgPT4gMjE0NzQ4MzY0OCwgSUEgPSAoZywgQikgPT4gTWF0aC5jZWlsKGcgLyBCKSAqIEIsIENBID0gKGcpID0+IHsKICAgIHZhciBCID0gRC5idWZmZXIsIEUgPSAoZyAtIEIuYnl0ZUxlbmd0aCArIDY1NTM1KSAvIDY1NTM2IHwgMDsKICAgIHRyeSB7CiAgICAgIHJldHVybiBELmdyb3coRSksIFUoKSwgMTsKICAgIH0gY2F0Y2ggewogICAgfQogIH0sIEJBID0gKGcpID0+IHsKICAgIHZhciBCID0gTi5sZW5ndGg7CiAgICBnID4+Pj0gMDsKICAgIHZhciBFID0gZ0EoKTsKICAgIGlmIChnID4gRSkKICAgICAgcmV0dXJuICExOwogICAgZm9yICh2YXIgUSA9IDE7IFEgPD0gNDsgUSAqPSAyKSB7CiAgICAgIHZhciBvID0gQiAqICgxICsgMC4yIC8gUSk7CiAgICAgIG8gPSBNYXRoLm1pbihvLCBnICsgMTAwNjYzMjk2KTsKICAgICAgdmFyIHIgPSBNYXRoLm1pbihFLCBJQShNYXRoLm1heChnLCBvKSwgNjU1MzYpKSwgYyA9IENBKHIpOwogICAgICBpZiAoYykKICAgICAgICByZXR1cm4gITA7CiAgICB9CiAgICByZXR1cm4gITE7CiAgfSwgbiA9IG5ldyBVaW50OEFycmF5KDEyMyksIGEgPSAyNTsgYSA+PSAwOyAtLWEpCiAgICBuWzQ4ICsgYV0gPSA1MiArIGEsIG5bNjUgKyBhXSA9IGEsIG5bOTcgKyBhXSA9IDI2ICsgYTsKICBuWzQzXSA9IDYyLCBuWzQ3XSA9IDYzLCBBLm5vRXhpdFJ1bnRpbWUgJiYgQS5ub0V4aXRSdW50aW1lLCBBLnByaW50ICYmIEEucHJpbnQsIEEucHJpbnRFcnIgJiYgQS5wcmludEVyciwgQS53YXNtQmluYXJ5ICYmIChGID0gQS53YXNtQmluYXJ5KSwgQS5hcmd1bWVudHMgJiYgQS5hcmd1bWVudHMsIEEudGhpc1Byb2dyYW0gJiYgQS50aGlzUHJvZ3JhbTsKICBmdW5jdGlvbiBRQShnKSB7CiAgICBBLl9wYWNrID0gZy5kLCBBLl9tYWxsb2MgPSBnLmUsIEEuX2ZyZWUgPSBnLmY7CiAgfQogIHZhciBFQSA9IHsgYTogQkEgfSwgZiA9IHooKTsKICBmdW5jdGlvbiBxKCkgewogICAgaWYgKHMgPiAwKSB7CiAgICAgIHcgPSBxOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoaSgpLCBzID4gMCkgewogICAgICB3ID0gcTsKICAgICAgcmV0dXJuOwogICAgfQogICAgZnVuY3Rpb24gZygpIHsKICAgICAgQS5jYWxsZWRSdW4gPSAhMCwgSCgpLCBBLm9uUnVudGltZUluaXRpYWxpemVkPy4oKSwgYigpOwogICAgfQogICAgQS5zZXRTdGF0dXMgPyAoQS5zZXRTdGF0dXMoIlJ1bm5pbmcuLi4iKSwgc2V0VGltZW91dCgoKSA9PiB7CiAgICAgIHNldFRpbWVvdXQoKCkgPT4gQS5zZXRTdGF0dXMoIiIpLCAxKSwgZygpOwogICAgfSwgMSkpIDogZygpOwogIH0KICBmdW5jdGlvbiBpQSgpIHsKICAgIGlmIChBLnByZUluaXQpCiAgICAgIGZvciAodHlwZW9mIEEucHJlSW5pdCA9PSAiZnVuY3Rpb24iICYmIChBLnByZUluaXQgPSBbQS5wcmVJbml0XSk7IEEucHJlSW5pdC5sZW5ndGggPiAwOyApCiAgICAgICAgQS5wcmVJbml0LnNoaWZ0KCkoKTsKICB9CiAgcmV0dXJuIGlBKCksIHEoKSwgZSA9IEEsIGU7Cn07CmxldCBJOwphc3luYyBmdW5jdGlvbiB0QSgpIHsKICBpZiAoSSA9IGF3YWl0IG9BKCksICFJIHx8ICFJLkhFQVBGMzIgfHwgIUkuX3BhY2spCiAgICB0aHJvdyBuZXcgRXJyb3IoIldBU00gbW9kdWxlIGZhaWxlZCB0byBpbml0aWFsaXplIHByb3Blcmx5Iik7Cn0KbGV0IHQgPSAwOwpjb25zdCBsID0gbmV3IEFycmF5KCk7CmxldCBLID0gITEsIHAgPSAhMSwgWSwgUiwgRywgdSwgZCwgTSwgUywgTCwgSjsKY29uc3QgZUEgPSBhc3luYyAoQykgPT4gewogIGZvciAoOyBwOyApCiAgICBhd2FpdCBuZXcgUHJvbWlzZSgoSCkgPT4gc2V0VGltZW91dChILCAwKSk7CiAgSSB8fCAocCA9ICEwLCBhd2FpdCB0QSgpLCBwID0gITEpOwogIGNvbnN0IGUgPSBNYXRoLnBvdygyLCBNYXRoLmNlaWwoTWF0aC5sb2cyKEMudmVydGV4Q291bnQpKSk7CiAgZSA+IHQgJiYgKHQgPiAwICYmIChJLl9mcmVlKFkpLCBJLl9mcmVlKFIpLCBJLl9mcmVlKEcpLCBJLl9mcmVlKHUpLCBJLl9mcmVlKGQpLCBJLl9mcmVlKE0pLCBJLl9mcmVlKFMpLCBJLl9mcmVlKEwpLCBJLl9mcmVlKEopKSwgdCA9IGUsIFkgPSBJLl9tYWxsb2MoMyAqIHQgKiA0KSwgUiA9IEkuX21hbGxvYyg0ICogdCAqIDQpLCBHID0gSS5fbWFsbG9jKDMgKiB0ICogNCksIHUgPSBJLl9tYWxsb2MoNCAqIHQpLCBkID0gSS5fbWFsbG9jKHQpLCBNID0gSS5fbWFsbG9jKDggKiB0ICogNCksIFMgPSBJLl9tYWxsb2MoMyAqIHQgKiA0KSwgTCA9IEkuX21hbGxvYyg0ICogdCAqIDQpLCBKID0gSS5fbWFsbG9jKDMgKiB0ICogNCkpLCBJLkhFQVBGMzIuc2V0KEMucG9zaXRpb25zLCBZIC8gNCksIEkuSEVBUEYzMi5zZXQoQy5yb3RhdGlvbnMsIFIgLyA0KSwgSS5IRUFQRjMyLnNldChDLnNjYWxlcywgRyAvIDQpLCBJLkhFQVBVOC5zZXQoQy5jb2xvcnMsIHUpLCBJLkhFQVBVOC5zZXQoQy5zZWxlY3Rpb24sIGQpLCBJLl9wYWNrKAogICAgQy5zZWxlY3RlZCwKICAgIEMudmVydGV4Q291bnQsCiAgICBZLAogICAgUiwKICAgIEcsCiAgICB1LAogICAgZCwKICAgIE0sCiAgICBTLAogICAgTCwKICAgIEoKICApOwogIGNvbnN0IEEgPSBuZXcgVWludDMyQXJyYXkoSS5IRUFQVTMyLmJ1ZmZlciwgTSwgQy52ZXJ0ZXhDb3VudCAqIDgpLCBoID0gbmV3IFVpbnQzMkFycmF5KEEuc2xpY2UoKS5idWZmZXIpLCBrID0gbmV3IEZsb2F0MzJBcnJheShJLkhFQVBGMzIuYnVmZmVyLCBTLCBDLnZlcnRleENvdW50ICogMyksIHkgPSBuZXcgRmxvYXQzMkFycmF5KGsuc2xpY2UoKS5idWZmZXIpLCBGID0gbmV3IEZsb2F0MzJBcnJheShJLkhFQVBGMzIuYnVmZmVyLCBMLCBDLnZlcnRleENvdW50ICogNCksIEQgPSBuZXcgRmxvYXQzMkFycmF5KEYuc2xpY2UoKS5idWZmZXIpLCBOID0gbmV3IEZsb2F0MzJBcnJheShJLkhFQVBGMzIuYnVmZmVyLCBKLCBDLnZlcnRleENvdW50ICogMyksIFUgPSBuZXcgRmxvYXQzMkFycmF5KE4uc2xpY2UoKS5idWZmZXIpLCBpID0gewogICAgZGF0YTogaCwKICAgIHdvcmxkUG9zaXRpb25zOiB5LAogICAgd29ybGRSb3RhdGlvbnM6IEQsCiAgICB3b3JsZFNjYWxlczogVSwKICAgIG9mZnNldDogQy5vZmZzZXQsCiAgICB2ZXJ0ZXhDb3VudDogQy52ZXJ0ZXhDb3VudCwKICAgIHBvc2l0aW9uczogQy5wb3NpdGlvbnMuYnVmZmVyLAogICAgcm90YXRpb25zOiBDLnJvdGF0aW9ucy5idWZmZXIsCiAgICBzY2FsZXM6IEMuc2NhbGVzLmJ1ZmZlciwKICAgIGNvbG9yczogQy5jb2xvcnMuYnVmZmVyLAogICAgc2VsZWN0aW9uOiBDLnNlbGVjdGlvbi5idWZmZXIKICB9OwogIHNlbGYucG9zdE1lc3NhZ2UoeyByZXNwb25zZTogaSB9LCBbCiAgICBpLmRhdGEuYnVmZmVyLAogICAgaS53b3JsZFBvc2l0aW9ucy5idWZmZXIsCiAgICBpLndvcmxkUm90YXRpb25zLmJ1ZmZlciwKICAgIGkud29ybGRTY2FsZXMuYnVmZmVyLAogICAgaS5wb3NpdGlvbnMsCiAgICBpLnJvdGF0aW9ucywKICAgIGkuc2NhbGVzLAogICAgaS5jb2xvcnMsCiAgICBpLnNlbGVjdGlvbgogIF0pLCBLID0gITE7Cn0sIFogPSAoKSA9PiB7CiAgaWYgKGwubGVuZ3RoICE9PSAwICYmICFLKSB7CiAgICBLID0gITA7CiAgICBjb25zdCBDID0gbC5zaGlmdCgpOwogICAgZUEoQyksIHNldFRpbWVvdXQoKCkgPT4gewogICAgICBLID0gITEsIFooKTsKICAgIH0sIDApOwogIH0KfTsKc2VsZi5vbm1lc3NhZ2UgPSAoQykgPT4gewogIGlmIChDLmRhdGEuc3BsYXQpIHsKICAgIGNvbnN0IGUgPSBDLmRhdGEuc3BsYXQ7CiAgICBmb3IgKGNvbnN0IFtBLCBoXSBvZiBsLmVudHJpZXMoKSkKICAgICAgaWYgKGgub2Zmc2V0ID09PSBlLm9mZnNldCkgewogICAgICAgIGxbQV0gPSBlOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgbC5wdXNoKGUpLCBaKCk7CiAgfQp9OwovLyMgc291cmNlTWFwcGluZ1VSTD1EYXRhV29ya2VyLUJ6RWRfWmo2LmpzLm1hcAo="; var ut = (E) => Uint8Array.from(atob(E), (t) => t.charCodeAt(0)); var at = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", ut(gt)], { type: "text/javascript;charset=utf-8" }); function Jt(E) { let t; try { if (t = at && (self.URL || self.webkitURL).createObjectURL(at), !t) throw ""; const n = new Worker(t, { type: "module", name: E?.name }); return n.addEventListener("error", () => { (self.URL || self.webkitURL).revokeObjectURL(t); }), n; } catch { return new Worker( "data:text/javascript;base64," + gt, { type: "module", name: E?.name } ); } } var mt = function(E = {}) { var t, n = E, i = import_meta.url, e = "", A; { try { e = new URL(".", i).href; } catch { } A = (h) => { var m = new XMLHttpRequest(); return m.open("GET", h, false), m.responseType = "arraybuffer", m.send(null), new Uint8Array(m.response); }; } console.log.bind(console), console.error.bind(console); var o, s, r; function Q() { var h = s.buffer; n.HEAPU8 = r = new Uint8Array(h), n.HEAPU32 = new Uint32Array(h), n.HEAPF32 = new Float32Array(h), new BigInt64Array(h), new BigUint64Array(h); } function I() { if (n.preRun) for (typeof n.preRun == "function" && (n.preRun = [n.preRun]); n.preRun.length; ) L(n.preRun.shift()); Z(H); } function d() { j.c(); } function a() { if (n.postRun) for (typeof n.postRun == "function" && (n.postRun = [n.postRun]); n.postRun.length; ) f(n.postRun.shift()); Z(k); } var U = 0, F = null; function g(h) { U++, n.monitorRunDependencies?.(U); } function B(h) { if (U--, n.monitorRunDependencies?.(U), U == 0 && F) { var m = F; F = null, m(); } } var C; function c() { return M("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"); } function p(h) { if (ArrayBuffer.isView(h)) return h; if (h == C && o) return new Uint8Array(o); if (A) return A(h); throw 'sync fetching of the wasm failed: you can preload it to Module["wasmBinary"] manually, or emcc.py will do that for you when generating HTML (but not JS)'; } function u(h, m) { var x, N = p(h); x = new WebAssembly.Module(N); var v = new WebAssembly.Instance(x, m); return [v, x]; } function S() { return { a: b }; } function W() { function h(N, v) { return j = N.exports, s = j.b, Q(), D(j), B(), j; } g(); var m = S(); if (n.instantiateWasm) return new Promise((N, v) => { n.instantiateWasm(m, (O, $) => { N(h(O)); }); }); C ?? (C = c()); var x = u(C, m); return h(x[0]); } for (var Z = (h) => { for (; h.length > 0; ) h.shift()(n); }, k = [], f = (h) => k.push(h), H = [], L = (h) => H.push(h), M = (h) => { for (var m, x, N = 0, v = 0, O = h.length, $ = new Uint8Array((O * 3 >> 2) - (h[O - 2] == "=") - (h[O - 1] == "=")); N < O; N += 4, v += 3) m = l[h.charCodeAt(N + 1)], x = l[h.charCodeAt(N + 2)], $[v] = l[h.charCodeAt(N)] << 2 | m >> 4, $[v + 1] = m << 4 | x >> 2, $[v + 2] = x << 6 | l[h.charCodeAt(N + 3)]; return $; }, V = () => 2147483648, w = (h, m) => Math.ceil(h / m) * m, P = (h) => { var m = s.buffer, x = (h - m.byteLength + 65535) / 65536 | 0; try { return s.grow(x), Q(), 1; } catch { } }, T = (h) => { var m = r.length; h >>>= 0; var x = V(); if (h > x) return false; for (var N = 1; N <= 4; N *= 2) { var v = m * (1 + 0.2 / N); v = Math.min(v, h + 100663296); var O = Math.min(x, w(Math.max(h, v), 65536)), $ = P(O); if ($) return true; } return false; }, l = new Uint8Array(123), J = 25; J >= 0; --J) l[48 + J] = 52 + J, l[65 + J] = J, l[97 + J] = 26 + J; l[43] = 62, l[47] = 63, n.noExitRuntime && n.noExitRuntime, n.print && n.print, n.printErr && n.printErr, n.wasmBinary && (o = n.wasmBinary), n.arguments && n.arguments, n.thisProgram && n.thisProgram; function D(h) { n._pack = h.d, n._malloc = h.e, n._free = h.f; } var b = { a: T }, j = W(); function q() { if (U > 0) { F = q; return; } if (I(), U > 0) { F = q; return; } function h() { n.calledRun = true, d(), n.onRuntimeInitialized?.(), a(); } n.setStatus ? (n.setStatus("Running..."), setTimeout(() => { setTimeout(() => n.setStatus(""), 1), h(); }, 1)) : h(); } function G() { if (n.preInit) for (typeof n.preInit == "function" && (n.preInit = [n.preInit]); n.preInit.length > 0; ) n.preInit.shift()(); } return G(), q(), t = n, t; }; var ft = () => new Jt(); var Ut = class { constructor(t) { this.dataChanged = false, this.transformsChanged = false, this.colorTransformsChanged = false, this._updating = /* @__PURE__ */ new Set(), this._dirty = /* @__PURE__ */ new Set(); let n = 0, i = 0; this._splatIndices = /* @__PURE__ */ new Map(), this._offsets = /* @__PURE__ */ new Map(); const e = /* @__PURE__ */ new Map(); for (const a of t.objects) a instanceof X && (this._splatIndices.set(a, i), this._offsets.set(a, n), e.set(n, a), n += a.data.vertexCount, i++); this._vertexCount = n, this._width = 2048, this._height = Math.ceil(2 * this.vertexCount / this.width), this._data = new Uint32Array(this.width * this.height * 4), this._transformsWidth = 5, this._transformsHeight = e.size, this._transforms = new Float32Array(this._transformsWidth * this._transformsHeight * 4), this._transformIndicesWidth = 1024, this._transformIndicesHeight = Math.ceil(this.vertexCount / this._transformIndicesWidth), this._transformIndices = new Uint32Array(this._transformIndicesWidth * this._transformIndicesHeight), this._colorTransformsWidth = 4, this._colorTransformsHeight = 64, this._colorTransforms = new Float32Array(this._colorTransformsWidth * this._colorTransformsHeight * 4), this._colorTransforms.fill(0), this._colorTransforms[0] = 1, this._colorTransforms[5] = 1, this._colorTransforms[10] = 1, this._colorTransforms[15] = 1, this._colorTransformIndicesWidth = 1024, this._colorTransformIndicesHeight = Math.ceil(this.vertexCount / this._colorTransformIndicesWidth), this._colorTransformIndices = new Uint32Array( this._colorTransformIndicesWidth * this._colorTransformIndicesHeight ), this.colorTransformIndices.fill(0), this._positions = new Float32Array(this.vertexCount * 3), this._rotations = new Float32Array(this.vertexCount * 4), this._scales = new Float32Array(this.vertexCount * 3), this._worker = ft(); const A = (a) => { const U = this._splatIndices.get(a); this._transforms.set(a.transform.buffer, U * 20), this._transforms[U * 20 + 16] = a.selected ? 1 : 0, a.positionChanged = false, a.rotationChanged = false, a.scaleChanged = false, a.selectedChanged = false, this.transformsChanged = true; }, o = () => { let a = false; for (const g of this._splatIndices.keys()) if (g.colorTransformChanged) { a = true; break; } if (!a) return; const U = [new K()]; this._colorTransformIndices.fill(0); let F = 1; for (const g of this._splatIndices.keys()) { const B = this._offsets.get(g); for (const C of g.colorTransforms) U.includes(C) || (U.push(C), F++); for (const C of g.colorTransformsMap.keys()) { const c = g.colorTransformsMap.get(C); this._colorTransformIndices[C + B] = c + F - 1; } g.colorTransformChanged = false; } for (let g = 0; g < U.length; g++) { const B = U[g]; this._colorTransforms.set(B.buffer, g * 16); } this.colorTransformsChanged = true; }; this._worker.onmessage = (a) => { if (a.data.response) { const U = a.data.response, F = e.get(U.offset); A(F), o(); const g = this._splatIndices.get(F); for (let B = 0; B < F.data.vertexCount; B++) this._transformIndices[U.offset + B] = g; this._data.set(U.data, U.offset * 8), F.data.reattach( U.positions, U.rotations, U.scales, U.colors, U.selection ), this._positions.set(U.worldPositions, U.offset * 3), this._rotations.set(U.worldRotations, U.offset * 4), this._scales.set(U.worldScales, U.offset * 3), this._updating.delete(F), F.selectedChanged = false, this.dataChanged = true; } }; let s; async function r() { s = await mt(); } r(); async function Q() { for (; !s; ) await new Promise((a) => setTimeout(a, 0)); } const I = (a) => { if (!s) { Q().then(() => { I(a); }); return; } A(a); const U = s._malloc(3 * a.data.vertexCount * 4), F = s._malloc(4 * a.data.vertexCount * 4), g = s._malloc(3 * a.data.vertexCount * 4), B = s._malloc(4 * a.data.vertexCount), C = s._malloc(a.data.vertexCount), c = s._malloc(8 * a.data.vertexCount * 4), p = s._malloc(3 * a.data.vertexCount * 4), u = s._malloc(4 * a.data.vertexCount * 4), S = s._malloc(3 * a.data.vertexCount * 4); s.HEAPF32.set(a.data.positions, U / 4), s.HEAPF32.set(a.data.rotations, F / 4), s.HEAPF32.set(a.data.scales, g / 4), s.HEAPU8.set(a.data.colors, B), s.HEAPU8.set(a.data.selection, C), s._pack( a.selected, a.data.vertexCount, U, F, g, B, C, c, p, u, S ); const W = new Uint32Array(s.HEAPU32.buffer, c, a.data.vertexCount * 8), Z = new Float32Array( s.HEAPF32.buffer, p, a.data.vertexCount * 3 ), k = new Float32Array( s.HEAPF32.buffer, u, a.data.vertexCount * 4 ), f = new Float32Array(s.HEAPF32.buffer, S, a.data.vertexCount * 3), H = this._splatIndices.get(a), L = this._offsets.get(a); for (let M = 0; M < a.data.vertexCount; M++) this._transformIndices[L + M] = H; this._data.set(W, L * 8), this._positions.set(Z, L * 3), this._rotations.set(k, L * 4), this._scales.set(f, L * 3), s._free(U), s._free(F), s._free(g), s._free(B), s._free(C), s._free(c), s._free(p), s._free(u), s._free(S), this.dataChanged = true, this.colorTransformsChanged = true; }, d = (a) => { if ((a.positionChanged || a.rotationChanged || a.scaleChanged || a.selectedChanged) && A(a), a.colorTransformChanged && o(), !a.data.changed || a.data.detached) return; const U = { position: new Float32Array(a.position.flat()), rotation: new Float32Array(a.rotation.flat()), scale: new Float32Array(a.scale.flat()), selected: a.selected, vertexCount: a.data.vertexCount, positions: a.data.positions, rotations: a.data.rotations, scales: a.data.scales, colors: a.data.colors, selection: a.data.selection, offset: this._offsets.get(a) }; this._worker.postMessage( { splat: U }, [ U.position.buffer, U.rotation.buffer, U.scale.buffer, U.positions.buffer, U.rotations.buffer, U.scales.buffer, U.colors.buffer, U.selection.buffer ] ), this._updating.add(a), a.data.detached = true; }; this.getSplat = (a) => { let U = null; for (const [F, g] of this._offsets) if (a >= g) U = F; else break; return U; }, this.getLocalIndex = (a, U) => { const F = this._offsets.get(a); return U - F; }, this.markDirty = (a) => { this._dirty.add(a); }, this.rebuild = () => { for (const a of this._dirty) d(a); this._dirty.clear(); }, this.dispose = () => { this._worker.terminate(); }; for (const a of this._splatIndices.keys()) I(a); o(); } get offsets() { return this._offsets; } get data() { return this._data; } get width() { return this._width; } get height() { return this._height; } get transforms() { return this._transforms; } get transformsWidth() { return this._transformsWidth; } get transformsHeight() { return this._transformsHeight; } get transformIndices() { return this._transformIndices; } get transformIndicesWidth() { return this._transformIndicesWidth; } get transformIndicesHeight() { return this._transformIndicesHeight; } get colorTransforms() { return this._colorTransforms; } get colorTransformsWidth() { return this._colorTransformsWidth; } get colorTransformsHeight() { return this._colorTransformsHeight; } get colorTransformIndices() { return this._colorTransformIndices; } get colorTransformIndicesWidth() { return this._colorTransformIndicesWidth; } get colorTransformIndicesHeight() { return this._colorTransformIndicesHeight; } get positions() { return this._positions; } get rotations() { return this._rotations; } get scales() { return this._scales; } get vertexCount() { return this._vertexCount; } get needsRebuild() { return this._dirty.size > 0; } get updating() { return this._updating.size > 0; } }; var dt = class { constructor(t = 0, n = 0, i = 0, e = 255) { this.r = t, this.g = n, this.b = i, this.a = e; } flat() { return [this.r, this.g, this.b, this.a]; } flatNorm() { return [this.r / 255, this.g / 255, this.b / 255, this.a / 255]; } toHexString() { return "#" + this.flat().map((t) => t.toString(16).padStart(2, "0")).join(""); } toString() { return `[${this.flat().join(", ")}]`; } }; var Vt = () => new St(); var Zt = ( /* glsl */ `#version 300 es precision highp float; precision highp int; uniform highp usampler2D u_texture; uniform highp sampler2D u_transforms; uniform highp usampler2D u_transformIndices; uniform highp sampler2D u_colorTransforms; uniform highp usampler2D u_colorTransformIndices; uniform mat4 projection, view; uniform vec2 focal; uniform vec2 viewport; uniform bool useDepthFade; uniform float depthFade; in vec2 position; in int index; out vec4 vColor; out vec2 vPosition; out float vSize; out float vSelected; void main () { uvec4 cen = texelFetch(u_texture, ivec2((uint(index) & 0x3ffu) << 1, uint(index) >> 10), 0); float selected = float((cen.w >> 24) & 0xffu); uint transformIndex = texelFetch(u_transformIndices, ivec2(uint(index) & 0x3ffu, uint(index) >> 10), 0).x; mat4 transform = mat4( texelFetch(u_transforms, ivec2(0, transformIndex), 0), texelFetch(u_transforms, ivec2(1, transformIndex), 0), texelFetch(u_transforms, ivec2(2, transformIndex), 0), texelFetch(u_transforms, ivec2(3, transformIndex), 0) ); if (selected < 0.5) { selected = texelFetch(u_transforms, ivec2(4, transformIndex), 0).x; } mat4 viewTransform = view * transform; vec4 cam = viewTransform * vec4(uintBitsToFloat(cen.xyz), 1); vec4 pos2d = projection * cam; float clip = 1.2 * pos2d.w; if (pos2d.z < -pos2d.w || pos2d.z > pos2d.w || pos2d.x < -clip || pos2d.x > clip || pos2d.y < -clip || pos2d.y > clip) { gl_Position = vec4(0.0, 0.0, 2.0, 1.0); return; } uvec4 cov = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 1) | 1u, uint(index) >> 10), 0); vec2 u1 = unpackHalf2x16(cov.x), u2 = unpackHalf2x16(cov.y), u3 = unpackHalf2x16(cov.z); mat3 Vrk = mat3(u1.x, u1.y, u2.x, u1.y, u2.y, u3.x, u2.x, u3.x, u3.y); mat3 J = mat3( focal.x / cam.z, 0., -(focal.x * cam.x) / (cam.z * cam.z), 0., -focal.y / cam.z, (focal.y * cam.y) / (cam.z * cam.z), 0., 0., 0. ); mat3 T = transpose(mat3(viewTransform)) * J; mat3 cov2d = transpose(T) * Vrk * T; //ref: https://github.com/graphdeco-inria/diff-gaussian-rasterization/blob/main/cuda_rasterizer/forward.cu#L110-L111 cov2d[0][0] += 0.3; cov2d[1][1] += 0.3; float mid = (cov2d[0][0] + cov2d[1][1]) / 2.0; float radius = length(vec2((cov2d[0][0] - cov2d[1][1]) / 2.0, cov2d[0][1])); float lambda1 = mid + radius, lambda2 = mid - radius; if (lambda2 < 0.0) return; vec2 diagonalVector = normalize(vec2(cov2d[0][1], lambda1 - cov2d[0][0])); vec2 majorAxis = min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector; vec2 minorAxis = min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x); uint colorTransformIndex = texelFetch(u_colorTransformIndices, ivec2(uint(index) & 0x3ffu, uint(index) >> 10), 0).x; mat4 colorTransform = mat4( texelFetch(u_colorTransforms, ivec2(0, colorTransformIndex), 0), texelFetch(u_colorTransforms, ivec2(1, colorTransformIndex), 0), texelFetch(u_colorTransforms, ivec2(2, colorTransformIndex), 0), texelFetch(u_colorTransforms, ivec2(3, colorTransformIndex), 0) ); vec4 color = vec4((cov.w) & 0xffu, (cov.w >> 8) & 0xffu, (cov.w >> 16) & 0xffu, (cov.w >> 24) & 0xffu) / 255.0; vColor = colorTransform * color; vPosition = position; vSize = length(majorAxis); vSelected = selected; float scalingFactor = 1.0; if (useDepthFade) { float depthNorm = (pos2d.z / pos2d.w + 1.0) / 2.0; float near = 0.1; float far = 100.0; float normalizedDepth = (2.0 * near) / (far + near - depthNorm * (far - near)); float start = max(normalizedDepth - 0.1, 0.0); float end = min(normalizedDepth + 0.1, 1.0); scalingFactor = clamp((depthFade - start) / (end - start), 0.0, 1.0); } vec2 vCenter = vec2(pos2d) / pos2d.w; gl_Position = vec4( vCenter + position.x * majorAxis * scalingFactor / viewport + position.y * minorAxis * scalingFactor / viewport, 0.0, 1.0); } ` ); var pt = ( /* glsl */ `#version 300 es precision highp float; uniform float outlineThickness; uniform vec4 outlineColor; in vec4 vColor; in vec2 vPosition; in float vSize; in float vSelected; out vec4 fragColor; void main () { float A = -dot(vPosition, vPosition); if (A < -4.0) discard; if (vSelected < 0.5) { float B = exp(A) * vColor.a; fragColor = vec4(B * vColor.rgb, B); return; } float outlineThreshold = -4.0 + (outlineThickness / vSize); if (A < outlineThreshold) { fragColor = outlineColor; } else { float B = exp(A) * vColor.a; fragColor = vec4(B * vColor.rgb, B); } } ` ); var Ct = class extends lt { constructor(t, n) { super(t, n), this._outlineThickness = 10, this._outlineColor = new dt(255, 165, 0, 255), this._renderData = null, this._depthIndex = new Uint32Array(), this._splatTexture = null, this._worker = null; const i = t.canvas, e = t.gl; let A, o, s, r, Q, I, d, a, U, F, g, B, C, c, p, u, S, W, Z; this._resize = () => { this._camera && (this._camera.data.setSize(i.width, i.height), this._camera.update(), A = e.getUniformLocation(this.program, "projection"), e.uniformMatrix4fv(A, false, this._camera.data.projectionMatrix.buffer), o = e.getUniformLocation(this.program, "viewport"), e.uniform2fv(o, new Float32Array([i.width, i.height]))); }; const k = () => { this._worker = Vt(), this._worker.onmessage = (V) => { if (V.data.depthIndex) { const { depthIndex: w } = V.data; this._depthIndex = w, e.bindBuffer(e.ARRAY_BUFFER, Z), e.bufferData(e.ARRAY_BUFFER, w, e.STATIC_DRAW); } }; }; this._initialize = () => { if (!this._scene || !this._camera) { console.error("Cannot render without scene and camera"); return; } this._resize(), this._scene.addEventListener("objectAdded", f), this._scene.addEventListener("objectRemoved", H); for (const V of this._scene.objects) V instanceof X && V.addEventListener("objectChanged", L); this._renderData = new Ut(this._scene), s = e.getUniformLocation(this.program, "focal"), e.uniform2fv(s, new Float32Array([this._camera.data.fx, this._camera.data.fy])), r = e.getUniformLocation(this.program, "view"), e.uniformMatrix4fv(r, false, this._camera.data.viewMatrix.buffer), F = e.getUniformLocation(this.program, "outlineThickness"), e.uniform1f(F, this.outlineThickness), g = e.getUniformLocation(this.program, "outlineColor"), e.uniform4fv(g, new Float32Array(this.outlineColor.flatNorm())), this._splatTexture = e.createTexture(), Q = e.getUniformLocation(this.program, "u_texture"), e.uniform1i(Q, 0), c = e.createTexture(), I = e.getUniformLocation(this.program, "u_transforms"), e.uniform1i(I, 1), p = e.createTexture(), d = e.getUniformLocation(this.program, "u_transformIndices"), e.uniform1i(d, 2), u = e.createTexture(), a = e.getUniformLocation(this.program, "u_colorTransforms"), e.uniform1i(a, 3), S = e.createTexture(), U = e.getUniformLocation( this.program, "u_colorTransformIndices" ), e.uniform1i(U, 4), W = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, W), e.bufferData(e.ARRAY_BUFFER, new Float32Array([-2, -2, 2, -2, 2, 2, -2, 2]), e.STATIC_DRAW), B = e.getAttribLocation(this.program, "position"), e.enableVertexAttribArray(B), e.vertexAttribPointer(B, 2, e.FLOAT, false, 0, 0), Z = e.createBuffer(), C = e.getAttribLocation(this.program, "index"), e.enableVertexAttribArray(C), e.bindBuffer(e.ARRAY_BUFFER, Z), k(); }; const f = (V) => { const w = V; w.object instanceof X && w.object.addEventListener("objectChanged", L), M(); }, H = (V) => { const w = V; w.object instanceof X && w.object.removeEventListener("objectChanged", L), M(); }, L = (V) => { const w = V; w.object instanceof X && this._renderData && this._renderData.markDirty(w.object); }, M = () => { this._renderData?.dispose(), this._renderData = new Ut(this._scene), this._worker?.terminate(), k(); }; this._render = () => { if (!this._scene || !this._camera || !this.renderData) { console.error("Cannot render without scene and camera"); return; } if (this.renderData.needsRebuild && this.renderData.rebuild(), this.renderData.dataChanged || this.renderData.transformsChanged || this.renderData.colorTransformsChanged) { this.renderData.dataChanged && (e.activeTexture(e.TEXTURE0), e.bindTexture(e.TEXTURE_2D, this.splatTexture), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST), e.texImage2D( e.TEXTURE_2D, 0, e.RGBA32UI, this.renderData.width, this.renderData.height, 0, e.RGBA_INTEGER, e.UNSIGNED_INT, this.renderData.data )), this.renderData.transformsChanged && (e.activeTexture(e.TEXTURE1), e.bindTexture(e.TEXTURE_2D, c), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST), e.texImage2D( e.TEXTURE_2D, 0, e.RGBA32F, this.renderData.transformsWidth, this.renderData.transformsHeight, 0, e.RGBA, e.FLOAT, this.renderData.transforms ), e.activeTexture(e.TEXTURE2), e.bindTexture(e.TEXTURE_2D, p), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST), e.texImage2D( e.TEXTURE_2D, 0, e.R32UI, this.renderData.transformIndicesWidth, this.renderData.transformIndicesHeight, 0, e.RED_INTEGER, e.UNSIGNED_INT, this.renderData.transformIndices )), this.renderData.colorTransformsChanged && (e.activeTexture(e.TEXTURE3), e.bindTexture(e.TEXTURE_2D, u), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST), e.texImage2D( e.TEXTURE_2D, 0, e.RGBA32F, this.renderData.colorTransformsWidth, this.renderData.colorTransformsHeight, 0, e.RGBA, e.FLOAT, this.renderData.colorTransforms ), e.activeTexture(e.TEXTURE4), e.bindTexture(e.TEXTURE_2D, S), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST), e.texImage2D( e.TEXTURE_2D, 0, e.R32UI, this.renderData.colorTransformIndicesWidth, this.renderData.colorTransformIndicesHeight, 0, e.RED_INTEGER, e.UNSIGNED_INT, this.renderData.colorTransformIndices )); const V = new Float32Array(this.renderData.positions.slice().buffer), w = new Float32Array(this.renderData.transforms.slice().buffer), P = new Uint32Array(this.renderData.transformIndices.slice().buffer); this._worker?.postMessage( { sortData: { positions: V, transforms: w, transformIndices: P, vertexCount: this.renderData.vertexCount } }, [V.buffer, w.buffer, P.buffer] ), this.renderData.dataChanged = false, this.renderData.transformsChanged = false, this.renderData.colorTransformsChanged = false; } this._camera.update(), this._worker?.postMessage({ viewProj: this._camera.data.viewProj.buffer }), e.viewport(0, 0, i.width, i.height), e.clearColor(0, 0, 0, 0), e.clear(e.COLOR_BUFFER_BIT), e.disable(e.DEPTH_TEST), e.enable(e.BLEND), e.blendFuncSeparate(e.ONE_MINUS_DST_ALPHA, e.ONE, e.ONE_MINUS_DST_ALPHA, e.ONE), e.blendEquationSeparate(e.FUNC_ADD, e.FUNC_ADD), e.uniformMatrix4fv(A, false, this._camera.data.projectionMatrix.buffer), e.uniformMatrix4fv(r, false, this._camera.data.viewMatrix.buffer), e.bindBuffer(e.ARRAY_BUFFER, W), e.vertexAttribPointer(B, 2, e.FLOAT, false, 0, 0), e.bindBuffer(e.ARRAY_BUFFER, Z), e.bufferData(e.ARRAY_BUFFER, this.depthIndex, e.STATIC_DRAW), e.vertexAttribIPointer(C, 1, e.INT, 0, 0), e.vertexAttribDivisor(C, 1), e.drawArraysInstanced(e.TRIANGLE_FAN, 0, 4, this.depthIndex.length); }, this._dispose = () => { if (!this._scene || !this._camera || !this.renderData) { console.error("Cannot dispose without scene and camera"); return; } this._scene.removeEventListener("objectAdded", f), this._scene.removeEventListener("objectRemoved", H); for (const V of this._scene.objects) V instanceof X && V.removeEventListener("objectChanged", L); this._worker?.terminate(), this.renderData.dispose(), e.deleteTexture(this.splatTexture), e.deleteTexture(c), e.deleteTexture(p), e.deleteBuffer(Z), e.deleteBuffer(W); }, this._setOutlineThickness = (V) => { this._outlineThickness = V, this._initialized && e.uniform1f(F, V); }, this._setOutlineColor = (V) => { this._outlineColor = V, this._initialized && e.uniform4fv(g, new Float32Array(V.flatNorm())); }; } get renderData() { return this._renderData; } get depthIndex() { return this._depthIndex; } get splatTexture() { return this._splatTexture; } get outlineThickness() { return this._outlineThickness; } set outlineThickness(t) { this._setOutlineThickness(t); } get outlineColor() { return this._outlineColor; } set outlineColor(t) { this._setOutlineColor(t); } get worker() { return this._worker; } _getVertexSource() { return Zt; } _getFragmentSource() { return pt; } }; var Nt = class { constructor(t = 1) { let n = 0, i = false, e, A, o, s; this.initialize = (r) => { if (!(r instanceof Ct)) throw new Error("FadeInPass requires a RenderProgram"); n = r.started ? 1 : 0, i = true, e = r, A = r.renderer.gl, o = A.getUniformLocation(e.program, "useDepthFade"), A.uniform1i(o, 1), s = A.getUniformLocation(e.program, "depthFade"), A.uniform1f(s, n); }, this.render = () => { !i || e.renderData?.updating || (A.useProgram(e.program), n = Math.min(n + t * 0.01, 1), n >= 1 && (i = false, A.uniform1i(o, 0)), A.uniform1f(s, n)); }; } dispose() { } }; var Mt = class { constructor(t = null, n = null) { this._backgroundColor = new dt(); const i = t || document.createElement("canvas"); t || (i.style.display = "block", i.style.boxSizing = "border-box", i.style.width = "100%", i.style.height = "100%", i.style.margin = "0", i.style.padding = "0", document.body.appendChild(i)), i.style.background = this._backgroundColor.toHexString(), this._canvas = i, this._gl = i.getContext("webgl2", { antialias: false, preserveDrawingBuffer: true }); const e = n || []; n || e.push(new Nt()), this._renderProgram = new Ct(this, e); const A = [this._renderProgram]; this.resize = () => { const o = i.clientWidth, s = i.clientHeight; (i.width !== o || i.height !== s) && this.setSize(o, s); }, this.setSize = (o, s) => { i.width = o, i.height = s, this._gl.viewport(0, 0, i.width, i.height); for (const r of A) r.resize(); }, this.render = (o, s) => { for (const r of A) r.render(o, s); }, this.dispose = () => { for (const o of A) o.dispose(); }, this.addProgram = (o) => { A.push(o); }, this.removeProgram = (o) => { const s = A.indexOf(o); if (s < 0) throw new Error("Program not found"); A.splice(s, 1); }, this.resize(); } get canvas() { return this._canvas; } get gl() { return this._gl; } get renderProgram() { return this._renderProgram; } get backgroundColor() { return this._backgroundColor; } set backgroundColor(t) { this._backgroundColor = t, this._canvas.style.background = t.toHexString(); } }; var Lt = class { constructor(t, n, i = 0.5, e = 0.5, A = 5, o = true, s = new R()) { this.minAngle = -90, this.maxAngle = 90, this.minZoom = 0.1, this.maxZoom = 30, this.orbitSpeed = 1, this.panSpeed = 1, this.zoomSpeed = 1, this.dampening = 0.12, this.setCameraTarget = () => { }; let r = s.clone(), Q = r.clone(), I = i, d = e, a = A, U = false, F = false, g = 0, B = 0, C = 0; const c = {}; let p = false; const u = () => { if (p) return; const l = t.rotation.toEuler(); I = -l.y, d = -l.x; const J = t.position.x - a * Math.sin(I) * Math.cos(d), D = t.position.y + a * Math.sin(d), b = t.position.z + a * Math.cos(I) * Math.cos(d); Q = new R(J, D, b); }; t.addEventListener("objectChanged", u), this.setCameraTarget = (l) => { const J = l.x - t.position.x, D = l.y - t.position.y, b = l.z - t.position.z; a = Math.sqrt(J * J + D * D + b * b), d = Math.atan2(D, Math.sqrt(J * J + b * b)), I = -Math.atan2(J, b), Q = new R(l.x, l.y, l.z), i = I, e = d, A = a, r = Q.clone(); }; const S = () => 0.1 + 0.9 * (a - this.minZoom) / (this.maxZoom - this.minZoom), W = (l) => { c[l.code] = true, l.code === "ArrowUp" && (c.KeyW = true), l.code === "ArrowDown" && (c.KeyS = true), l.code === "ArrowLeft" && (c.KeyA = true), l.code === "ArrowRight" && (c.KeyD = true); }, Z = (l) => { c[l.code] = false, l.code === "ArrowUp" && (c.KeyW = false), l.code === "ArrowDown" && (c.KeyS = false), l.code === "ArrowLeft" && (c.KeyA = false), l.code === "ArrowRight" && (c.KeyD = false); }, k = (l) => { T(l), U = true, F = l.button === 2, B = l.clientX, C = l.clientY, window.addEventListener("mouseup", f); }, f = (l) => { T(l), U = false, F = false, window.removeEventListener("mouseup", f); }, H = (l) => { if (T(l), !U || !t) return; const J = l.clientX - B, D = l.clientY - C; if (F) { const b = S(), j = -J * this.panSpeed * 0.01 * b, q = -D * this.panSpeed * 0.01 * b, G = _.RotationFromQuaternion(t.rotation).buffer, h = new R(G[0], G[3], G[6]), m = new R(G[1], G[4], G[7]); Q = Q.add(h.multiply(j)), Q = Q.add(m.multiply(q)); } else I -= J * this.orbitSpeed * 3e-3, d += D * this.orbitSpeed * 3e-3, d = Math.min( Math.max(d, this.minAngle * Math.PI / 180), this.maxAngle * Math.PI / 180 ); B = l.clientX, C = l.clientY; }, L = (l) => { T(l); const J = S(); a += l.deltaY * this.zoomSpeed * 0.025 * J, a = Math.min(Math.max(a, this.minZoom), this.maxZoom); }, M = (l) => { if (T(l), l.touches.length === 1) U = true, F = false, B = l.touches[0].clientX, C = l.touches[0].clientY, g = 0; else if (l.touches.length === 2) { U = true, F = true, B = (l.touches[0].clientX + l.touches[1].clientX) / 2, C = (l.touches[0].clientY + l.touches[1].clientY) / 2; const J = l.touches[0].clientX - l.touches[1].clientX, D = l.touches[0].clientY - l.touches[1].clientY; g = Math.sqrt(J * J + D * D); } }, V = (l) => { T(l), U = false, F = false; }, w = (l) => { if (T(l), !(!U || !t)) if (F) { const J = S(), D = l.touches[0].clientX - l.touches[1].clientX, b = l.touches[0].clientY - l.touches[1].clientY, j = Math.sqrt(D * D + b * b), q = g - j; a += q * this.zoomSpeed * 0.1 * J, a = Math.min(Math.max(a, this.minZoom), this.maxZoom), g = j; const G = (l.touches[0].clientX + l.touches[1].clientX) / 2, h = (l.touches[0].clientY + l.touches[1].clientY) / 2, m = G - B, x = h - C, N = _.RotationFromQuaternion(t.rotation).buffer, v = new R(N[0], N[3], N[6]), O = new R(N[1], N[4], N[7]); Q = Q.add(v.multiply(-m * this.panSpeed * 0.025 * J)), Q = Q.add(O.multiply(-x * this.panSpeed * 0.025 * J)), B = G, C = h; } else { const J = l.touches[0].clientX - B, D = l.touches[0].clientY - C; I -= J * this.orbitSpeed * 3e-3, d += D * this.orbitSpeed * 3e-3, d = Math.min( Math.max(d, this.minAngle * Math.PI / 180), this.maxAngle * Math.PI / 180 ), B = l.touches[0].clientX, C = l.touches[0].clientY; } }, P = (l, J, D) => (1 - D) * l + D * J; this.update = () => { p = true, i = P(i, I, this.dampening), e = P(e, d, this.dampening), A = P(A, a, this.dampening), r = r.lerp(Q, this.dampening); const l = r.x + A * Math.sin(i) * Math.cos(e), J = r.y - A * Math.sin(e), D = r.z - A * Math.cos(i) * Math.cos(e); t.position = new R(l, J, D); const b = r.subtract(t.position).normalize(), j = Math.asin(-b.y), q = Math.atan2(b.x, b.z); t.rotation = y.FromEuler(new R(j, q, 0)); const G = 0.025, h = 0.01, m = _.RotationFromQuaternion(t.rotation).buffer, x = new R(-m[2], -m[5], -m[8]), N = new R(m[0], m[3], m[6]); c.KeyS && (Q = Q.add(x.multiply(G))), c.KeyW && (Q = Q.subtract(x.multiply(G))), c.KeyA && (Q = Q.subtract(N.multiply(G))), c.KeyD && (Q = Q.add(N.multiply(G))), c.KeyE && (I += h), c.KeyQ && (I -= h), c.KeyR && (d += h), c.KeyF && (d -= h), p = false; }; const T = (l) => { l.preventDefault(), l.stopPropagation(); }; this.dispose = () => { n.removeEventListener("dragenter", T), n.removeEventListener("dragover", T), n.removeEventListener("dragleave", T), n.removeEventListener("contextmenu", T), n.removeEventListener("mousedown", k), n.removeEventListener("mousemove", H), n.removeEventListener("wheel", L), n.removeEventListener("touchstart", M), n.removeEventListener("touchend", V), n.removeEventListener("touchmove", w), o && (window.removeEventListener("keydown", W), window.removeEventListener("keyup", Z)); }, o && (window.addEventListener("keydown", W), window.addEventListener("keyup", Z)), n.addEventListener("dragenter", T), n.addEventListener("dragover", T), n.addEventListener("dragleave", T), n.addEventListener("contextmenu", T), n.addEventListener("mousedown", k), n.addEventListener("mousemove", H), n.addEventListener("wheel", L), n.addEventListener("touchstart", M), n.addEventListener("touchend", V), n.addEventListener("touchmove", w), this.update(); } }; var Gt = class { constructor(t, n) { this.moveSpeed = 1.5, this.lookSpeed = 0.7, this.dampening = 0.5; const i = {}; let e = t.rotation.toEuler().x, A = t.rotation.toEuler().y, o = t.position, s = false; const r = () => { n.requestPointerLock(); }, Q = () => { s = document.pointerLockElement === n, s ? n.addEventListener("mousemove", I) : n.removeEventListener("mousemove", I); }, I = (F) => { const g = F.movementX, B = F.movementY; A += g * this.lookSpeed * 1e-3, e -= B * this.lookSpeed * 1e-3, e = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, e)); }, d = (F) => { i[F.code] = true, F.code === "ArrowUp" && (i.KeyW = true), F.code === "ArrowDown" && (i.KeyS = true), F.code === "ArrowLeft" && (i.KeyA = true), F.code === "ArrowRight" && (i.KeyD = true); }, a = (F) => { i[F.code] = false, F.code === "ArrowUp" && (i.KeyW = false), F.code === "ArrowDown" && (i.KeyS = false), F.code === "ArrowLeft" && (i.KeyA = false), F.code === "ArrowRight" && (i.KeyD = false), F.code === "Escape" && document.exitPointerLock(); }; this.update = () => { const F = _.RotationFromQuaternion(t.rotation).buffer, g = new R(-F[2], -F[5], -F[8]), B = new R(F[0], F[3], F[6]); let C = new R(0, 0, 0); i.KeyS && (C = C.add(g)), i.KeyW && (C = C.subtract(g)), i.KeyA && (C = C.subtract(B)), i.KeyD && (C = C.add(B)), C = new R(C.x, 0, C.z), C.magnitude() > 0 && (C = C.normalize()), o = o.add(C.multiply(this.moveSpeed * 0.01)), t.position = t.position.add(o.subtract(t.position).multiply(this.dampening)), t.rotation = y.FromEuler(new R(e, A, 0)); }; const U = (F) => { F.preventDefault(), F.stopPropagation(); }; this.dispose = () => { n.removeEventListener("dragenter", U), n.removeEventListener("dragover", U), n.removeEventListener("dragleave", U), n.removeEventListener("contextmenu", U), n.removeEventListener("mousedown", r), document.removeEventListener("pointerlockchange", Q), window.removeEventListener("keydown", d), window.removeEventListener("keyup", a); }, window.addEventListener("keydown", d), window.addEventListener("keyup", a), n.addEventListener("dragenter", U), n.addEventListener("dragover", U), n.addEventListener("dragleave", U), n.addEventListener("contextmenu", U), n.addEventListener("mousedown", r), document.addEventListener("pointerlockchange", Q), this.update(); } }; var vt = class { constructor(t, n) { this.normal = t, this.point = n; } intersect(t, n) { const i = this.normal.dot(n); if (Math.abs(i) < 1e-4) return null; const e = this.normal.dot(this.point.subtract(t)) / i; return e < 0 ? null : t.add(n.multiply(e)); } }; var _t = class { // eslint-disable-next-line @typescript-eslint/no-unused-vars initialize(t) { } render() { } dispose() { } }; var Wt = ( /* glsl */ `#version 300 es precision highp float; precision highp int; uniform highp usampler2D u_texture; uniform mat4 projection, view; uniform vec2 focal; uniform vec2 viewport; uniform float time; in vec2 position; in int index; out vec4 vColor; out vec2 vPosition; void main () { gl_Position = vec4(0.0, 0.0, 2.0, 1.0); uvec4 motion1 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2) | 3u, uint(index) >> 10), 0); vec2 trbf = unpackHalf2x16(motion1.w); float dt = time - trbf.x; float topacity = exp(-1.0 * pow(dt / trbf.y, 2.0)); if(topacity < 0.02) return; uvec4 motion0 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2) | 2u, uint(index) >> 10), 0); uvec4 static0 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2), uint(index) >> 10), 0); vec2 m0 = unpackHalf2x16(motion0.x), m1 = unpackHalf2x16(motion0.y), m2 = unpackHalf2x16(motion0.z), m3 = unpackHalf2x16(motion0.w), m4 = unpackHalf2x16(motion1.x); vec4 trot = vec4(unpackHalf2x16(motion1.y).xy, unpackHalf2x16(motion1.z).xy) * dt; vec3 tpos = (vec3(m0.xy, m1.x) * dt + vec3(m1.y, m2.xy) * dt*dt + vec3(m3.xy, m4.x) * dt*dt*dt); vec4 cam = view * vec4(uintBitsToFloat(static0.xyz) + tpos, 1); vec4 pos = projection * cam; float clip = 1.2 * pos.w; if (pos.z < -clip || pos.x < -clip || pos.x > clip || pos.y < -clip || pos.y > clip) return; uvec4 static1 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2) | 1u, uint(index) >> 10), 0); vec4 rot = vec4(unpackHalf2x16(static0.w).xy, unpackHalf2x16(static1.x).xy) + trot; vec3 scale = vec3(unpackHalf2x16(static1.y).xy, unpackHalf2x16(static1.z).x); rot /= sqrt(dot(rot, rot)); mat3 S = mat3(scale.x, 0.0, 0.0, 0.0, scale.y, 0.0, 0.0, 0.0, scale.z); mat3 R = mat3( 1.0 - 2.0 * (rot.z * rot.z + rot.w * rot.w), 2.0 * (rot.y * rot.z - rot.x * rot.w), 2.0 * (rot.y * rot.w + rot.x * rot.z), 2.0 * (rot.y * rot.z + rot.x * rot.w), 1.0 - 2.0 * (rot.y * rot.y + rot.w * rot.w), 2.0 * (rot.z * rot.w - rot.x * rot.y), 2.0 * (rot.y * rot.w - rot.x * rot.z), 2.0 * (rot.z * rot.w + rot.x * rot.y), 1.0 - 2.0 * (rot.y * rot.y + rot.z * rot.z)); mat3 M = S * R; mat3 Vrk = 4.0 * transpose(M) * M; mat3 J = mat3( focal.x / cam.z, 0., -(focal.x * cam.x) / (cam.z * cam.z), 0., -focal.y / cam.z, (focal.y * cam.y) / (cam.z * cam.z), 0., 0., 0. ); mat3 T = transpose(mat3(view)) * J; mat3 cov2d = transpose(T) * Vrk * T; float mid = (cov2d[0][0] + cov2d[1][1]) / 2.0; float radius = length(vec2((cov2d[0][0] - cov2d[1][1]) / 2.0, cov2d[0][1])); float lambda1 = mid + radius, lambda2 = mid - radius; if(lambda2 < 0.0) return; vec2 diagonalVector = normalize(vec2(cov2d[0][1], lambda1 - cov2d[0][0])); vec2 majorAxis = min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector; vec2 minorAxis = min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x); uint rgba = static1.w; vColor = clamp(pos.z/pos.w+1.0, 0.0, 1.0) * vec4(1.0, 1.0, 1.0, topacity) * vec4( (rgba) & 0xffu, (rgba >> 8) & 0xffu, (rgba >> 16) & 0xffu, (rgba >> 24) & 0xffu) / 255.0; vec2 vCenter = vec2(pos) / pos.w; gl_Position = vec4( vCenter + position.x * majorAxis / viewport + position.y * minorAxis / viewport, 0.0, 1.0); vPosition = position; } ` ); var Dt = ( /* glsl */ `#version 300 es precision highp float; in vec4 vColor; in vec2 vPosition; out vec4 fragColor; void main () { float A = -dot(vPosition, vPosition); if (A < -4.0) discard; float B = exp(A) * vColor.a; fragColor = vec4(B * vColor.rgb, B); } ` ); var Yt = class extends lt { constructor(t, n = []) { super(t, n), this._renderData = null, this._depthIndex = new Uint32Array(), this._splatTexture = null; const i = t.canvas, e = t.gl; let A, o, s, r, Q, I, d, a, U, F, g; this._resize = () => { this._camera && (this._camera.data.setSize(i.width, i.height), this._camera.update(), o = e.getUniformLocation(this.program, "projection"), e.uniformMatrix4fv(o, false, this._camera.data.projectionMatrix.buffer), s = e.getUniformLocation(this.program, "viewport"), e.uniform2fv(s, new Float32Array([i.width, i.height]))); }; const B = () => { if (t.renderProgram.worker === null) { console.error("Render program is not initialized. Cannot render without worker"); return; } A = t.renderProgram.worker, A.onmessage = (u) => { if (u.data.depthIndex) { const { depthIndex: S } = u.data; this._depthIndex = S, e.bindBuffer(e.ARRAY_BUFFER, g), e.bufferData(e.ARRAY_BUFFER, S, e.STATIC_DRAW); } }; }; this._initialize = () => { if (!this._scene || !this._camera) { console.error("Cannot render without scene and camera"); return; } this._resize(), this._scene.addEventListener("objectAdded", C), this._scene.addEventListener("objectRemoved", c); for (const Z of this._scene.objects) Z instanceof tt && (this._renderData === null ? (this._renderData = Z.data, Z.addEventListener("objectChanged", p)) : console.warn("Multiple Splatv objects are not currently supported")); if (this._renderData === null) { console.error("Cannot render without Splatv object"); return; } r = e.getUniformLocation(this.program, "focal"), e.uniform2fv(r, new Float32Array([this._camera.data.fx, this._camera.data.fy])), Q = e.getUniformLocation(this.program, "view"), e.uniformMatrix4fv(Q, false, this._camera.data.viewMatrix.buffer), this._splatTexture = e.createTexture(), I = e.getUniformLocation(this.program, "u_texture"), e.uniform1i(I, 0), d = e.getUniformLocation(this.program, "time"), e.uniform1f(d, Math.sin(Date.now() / 1e3) / 2 + 1 / 2), F = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, F), e.bufferData(e.ARRAY_BUFFER, new Float32Array([-2, -2, 2, -2, 2, 2, -2, 2]), e.STATIC_DRAW), a = e.getAttribLocation(this.program, "position"), e.enableVertexAttribArray(a), e.vertexAttribPointer(a, 2, e.FLOAT, false, 0, 0), g = e.createBuffer(), U = e.getAttribLocation(this.program, "index"), e.enableVertexAttribArray(U), e.bindBuffer(e.ARRAY_BUFFER, g), B(), e.activeTexture(e.TEXTURE0), e.bindTexture(e.TEXTURE_2D, this._splatTexture), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST), e.texImage2D( e.TEXTURE_2D, 0, e.RGBA32UI, this._renderData.width, this._renderData.height, 0, e.RGBA_INTEGER, e.UNSIGNED_INT, this._renderData.data ); const u = this._renderData.positions, S = new Float32Array(new K().buffer), W = new Uint32Array(this._renderData.vertexCount); W.fill(0), A.postMessage( { sortData: { positions: u, transforms: S, transformIndices: W, vertexCount: this._renderData.vertexCount } }, [u.buffer, S.buffer, W.buffer] ); }; const C = (u) => { const S = u; S.object instanceof tt && (this._renderData === null ? (this._renderData = S.object.data, S.object.addEventListener("objectChanged", p)) : console.warn("Splatv not supported by default RenderProgram. Use VideoRenderProgram instead.")), this.dispose(); }, c = (u) => { const S = u; S.object instanceof tt && this._renderData === S.object.data && (this._renderData = null, S.object.removeEventListener("objectChanged", p)), this.dispose(); }, p = (u) => { const S = u; S.object instanceof tt && this._renderData === S.object.data && this.dispose(); }; this._render = () => { if (!this._scene || !this._camera) { console.error("Cannot render without scene and camera"); return; } if (!this._renderData) { console.warn("Cannot render without Splatv object"); return; } this._camera.update(), A.postMessage({ viewProj: this._camera.data.viewProj.buffer }), e.viewport(0, 0, i.width, i.height), e.clearColor(0, 0, 0, 0), e.clear(e.COLOR_BUFFER_BIT), e.disable(e.DEPTH_TEST), e.enable(e.BLEND), e.blendFuncSeparate(e.ONE_MINUS_DST_ALPHA, e.ONE, e.ONE_MINUS_DST_ALPHA, e.ONE), e.blendEquationSeparate(e.FUNC_ADD, e.FUNC_ADD), e.uniformMatrix4fv(o, false, this._camera.data.projectionMatrix.buffer), e.uniformMatrix4fv(Q, false, this._camera.data.viewMatrix.buffer), e.uniform1f(d, Math.sin(Date.now() / 1e3) / 2 + 1 / 2), e.bindBuffer(e.ARRAY_BUFFER, F), e.vertexAttribPointer(a, 2, e.FLOAT, false, 0, 0), e.bindBuffer(e.ARRAY_BUFFER, g), e.bufferData(e.ARRAY_BUFFER, this._depthIndex, e.STATIC_DRAW), e.vertexAttribIPointer(U, 1, e.INT, 0, 0), e.vertexAttribDivisor(U, 1), e.drawArraysInstanced(e.TRIANGLE_FAN, 0, 4, this._renderData.vertexCount); }, this._dispose = () => { if (!this._scene || !this._camera) { console.error("Cannot dispose without scene and camera"); return; } this._scene.removeEventListener("objectAdded", C), this._scene.removeEventListener("objectRemoved", c); for (const u of this._scene.objects) u instanceof tt && this._renderData === u.data && (this._renderData = null, u.removeEventListener("objectChanged", p)); A?.terminate(), e.deleteTexture(this._splatTexture), e.deleteBuffer(g), e.deleteBuffer(F); }; } get renderData() { return this._renderData; } _getVertexSource() { return Wt; } _getFragmentSource() { return Dt; } }; var it = class _it { constructor(t, n, i) { this.bounds = t, this.boxes = n, this.left = null, this.right = null, this.pointIndices = [], i.length > 1 ? this.split(t, n, i) : i.length > 0 && (this.pointIndices = i); } split(t, n, i) { const e = t.size().maxComponent(); i.sort((r, Q) => n[r].center().getComponent(e) - n[Q].center().getComponent(e)); const A = Math.floor(i.length / 2), o = i.slice(0, A), s = i.slice(A); this.left = new _it(t, n, o), this.right = new _it(t, n, s); } queryRange(t) { return this.bounds.intersects(t) ? this.left !== null && this.right !== null ? this.left.queryRange(t).concat(this.right.queryRange(t)) : this.pointIndices.filter((n) => t.intersects(this.boxes[n])) : []; } }; var yt = class { constructor(t, n) { const i = n.map((e, A) => A); this.root = new it(t, n, i); } queryRange(t) { return this.root.queryRange(t); } }; var Kt = class { constructor(t, n = 100, i = 1) { let e = 0, A = null, o = []; const s = () => { if (t.renderData === null) { console.error("IntersectionTester cannot be called before renderProgram has been initialized"); return; } o = []; const r = t.renderData, Q = new Array(r.offsets.size); let I = 0; const d = new nt( new R(1 / 0, 1 / 0, 1 / 0), new R(-1 / 0, -1 / 0, -1 / 0) ); for (const a of r.offsets.keys()) { const U = a.bounds; Q[I++] = U, d.expand(U.min), d.expand(U.max), o.push(a); } d.permute(), A = new yt(d, Q), e = r.vertexCount; }; this.testPoint = (r, Q) => { if (t.renderData === null || t.camera === null) return console.error("IntersectionTester cannot be called before renderProgram has been initialized"), null; if (s(), A === null) return console.error("Failed to build octree for IntersectionTester"), null; const I = t.renderData, d = t.camera; e !== I.vertexCount && console.warn("IntersectionTester has not been rebuilt since the last render"); const a = d.screenPointToRay(r, Q); for (let U = 0; U < n; U += i) { const F = d.position.add(a.multiply(U)), g = new R( F.x - i / 2, F.y - i / 2, F.z - i / 2 ), B = new R( F.x + i / 2, F.y + i / 2, F.z + i / 2 ), C = new nt(g, B), c = A.queryRange(C); if (c.length > 0) return o[c[0]]; } return null; }; } }; return __toCommonJS(gsplat_entry_exports); })();