3d-tiles-renderer
Version:
https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/specification
5,322 lines • 201 kB
JavaScript
import { Q as Un, b as Vn, C as Fn, a as Nn } from "./QuantizedMeshLoaderBase-DA143Nnz.js";
import { PlaneGeometry as qt, Mesh as Oe, MeshBasicMaterial as Ue, Vector2 as q, MathUtils as M, Vector3 as E, Sphere as he, Texture as kn, SRGBColorSpace as Ks, TextureUtils as Gn, DefaultLoadingManager as jn, BufferGeometry as et, MeshStandardMaterial as en, BufferAttribute as J, DataTexture as Wt, RGFormat as tn, UnsignedByteType as sn, LinearMipMapLinearFilter as zn, LinearFilter as nn, Triangle as Xt, Vector4 as Ve, Matrix4 as K, Matrix3 as Hn, Matrix2 as qn, WebGLRenderer as Wn, WebGLRenderTarget as Ft, ShaderMaterial as rn, OneFactor as Xn, ZeroFactor as Yn, CustomBlending as $n, Box2 as Qn, FileLoader as Zn, Quaternion as on, BatchedMesh as Jn, Source as Kn, Box3 as lt, REVISION as ei, WebGLArrayRenderTarget as ss, Raycaster as ti, DoubleSide as an, OrthographicCamera as si, Color as Yt, CanvasTexture as ln, Ray as ni, LineSegments as cn, LineBasicMaterial as ii, EdgesGeometry as ri, BoxGeometry as oi, Group as Ge, Box3Helper as ai, PointsMaterial as li } from "three";
import { a as un, O as ci, W as ui, g as hi, c as di, b as pi } from "./MemoryUtils-R1TfIs9h.js";
import { GLTFLoader as fi } from "three/examples/jsm/loaders/GLTFLoader.js";
import { FullScreenQuad as hn } from "three/examples/jsm/postprocessing/Pass.js";
import { L as mi, f as gi, e as ns, W as dn } from "./constants-z3YLhXg0.js";
import { b as yi, L as pn } from "./LoaderBase-CfTLVHyZ.js";
const fe = /* @__PURE__ */ new q(), xe = Symbol("TILE_X"), Te = Symbol("TILE_Y"), oe = Symbol("TILE_LEVEL");
class fn {
get tiling() {
return this.imageSource.tiling;
}
constructor(e = {}) {
const {
pixelSize: t = null,
center: s = !1,
useRecommendedSettings: n = !0,
imageSource: i = null
} = e;
this.priority = -10, this.tiles = null, this.imageSource = i, this.pixelSize = t, this.center = s, this.useRecommendedSettings = n, t !== null && console.warn('ImageFormatPlugin: "pixelSize" has been deprecated in favor of scaling the tiles root.');
}
// Plugin functions
init(e) {
this.useRecommendedSettings && (e.errorTarget = 1), this.tiles = e, this.imageSource.fetchOptions = e.fetchOptions, this.imageSource.fetchData = (t, s) => (e.invokeAllPlugins((n) => t = n.preprocessURL ? n.preprocessURL(t, null) : t), e.invokeOnePlugin((n) => n !== this && n.fetchData && n.fetchData(t, s)));
}
async loadRootTileset() {
const { tiles: e, imageSource: t } = this;
return t.url = t.url || e.rootURL, e.invokeAllPlugins((s) => t.url = s.preprocessURL ? s.preprocessURL(t.url, null) : t.url), await t.init(), e.rootURL = t.url, this.getTileset(t.url);
}
async parseToMesh(e, t, s, n, i) {
if (i.aborted)
return null;
const { imageSource: r } = this, o = t[xe], l = t[Te], c = t[oe], u = await r.processBufferToTexture(e);
if (i.aborted)
return u.dispose(), u.image.close(), null;
r.setData(o, l, c, u);
let h = 1, d = 1, m = 0, f = 0, p = 0;
const g = t.boundingVolume.box;
g && ([m, f, p] = g, h = g[3], d = g[7]);
const y = new qt(2 * h, 2 * d), x = new Oe(y, new Ue({ map: u, transparent: !0 }));
x.position.set(m, f, p);
const _ = r.tiling.getTileContentUVBounds(o, l, c), { uv: S } = y.attributes;
for (let b = 0; b < S.count; b++)
fe.fromBufferAttribute(S, b), fe.x = M.mapLinear(fe.x, 0, 1, _[0], _[2]), fe.y = M.mapLinear(fe.y, 0, 1, _[1], _[3]), S.setXY(b, fe.x, fe.y);
return x;
}
preprocessNode(e) {
const { tiling: t } = this, s = t.maxLevel;
e[oe] < s && e.parent !== null && this.expandChildren(e);
}
disposeTile(e) {
const t = e[xe], s = e[Te], n = e[oe], { imageSource: i } = this;
i.has(t, s, n) && i.release(t, s, n);
}
// Local functions
getTileset(e) {
const { tiling: t, tiles: s } = this, n = t.minLevel, { tileCountX: i, tileCountY: r } = t.getLevel(n), o = [];
for (let c = 0; c < i; c++)
for (let u = 0; u < r; u++) {
const h = this.createChild(c, u, n);
h !== null && o.push(h);
}
const l = {
asset: {
version: "1.1"
},
geometricError: 1e5,
root: {
refine: "REPLACE",
geometricError: 1e5,
boundingVolume: this.createBoundingVolume(0, 0, -1),
children: o,
[oe]: -1,
[xe]: 0,
[Te]: 0
}
};
return s.preprocessTileset(l, e), l;
}
getUrl(e, t, s) {
return this.imageSource.getUrl(e, t, s);
}
createBoundingVolume(e, t, s) {
const { center: n, pixelSize: i, tiling: r } = this, { pixelWidth: o, pixelHeight: l } = r.getLevel(r.maxLevel), [c, u, h, d] = s === -1 ? r.getContentBounds(!0) : r.getTileBounds(e, t, s, !0);
let m = (h - c) / 2, f = (d - u) / 2, p = c + m, g = u + f;
return n && (p -= 0.5, g -= 0.5), i ? (p *= o * i, m *= o * i, g *= l * i, f *= l * i) : (p *= r.aspectRatio, m *= r.aspectRatio), {
box: [
// center
p,
g,
0,
// x, y, z half vectors
m,
0,
0,
0,
f,
0,
0,
0,
0
]
};
}
createChild(e, t, s) {
const { pixelSize: n, tiling: i } = this;
if (!i.getTileExists(e, t, s))
return null;
const { pixelWidth: r, pixelHeight: o } = i.getLevel(s);
let l = Math.max(i.aspectRatio / r, 1 / o);
if (n) {
const c = i.getLevel(i.maxLevel);
l *= n * Math.max(c.pixelWidth, c.pixelHeight);
}
return {
refine: "REPLACE",
geometricError: l,
boundingVolume: this.createBoundingVolume(e, t, s),
content: {
uri: this.getUrl(e, t, s)
},
children: [],
// save the tile params so we can expand later
[xe]: e,
[Te]: t,
[oe]: s
};
}
expandChildren(e) {
const t = e[oe], s = e[xe], n = e[Te];
for (let i = 0; i < 2; i++)
for (let r = 0; r < 2; r++) {
const o = this.createChild(2 * s + i, 2 * n + r, t + 1);
o && e.children.push(o);
}
}
}
const pt = /* @__PURE__ */ new E(), je = /* @__PURE__ */ new E();
function xi(a, e, t) {
const n = t + 1e-5;
let i = e + 1e-5;
Math.abs(i) > Math.PI / 2 && (i = i - 1e-5), a.getCartographicToPosition(e, t, 0, pt), a.getCartographicToPosition(i, t, 0, je);
const r = pt.distanceTo(je) / 1e-5;
return a.getCartographicToPosition(e, n, 0, je), [pt.distanceTo(je) / 1e-5, r];
}
const Ti = 30, bi = 15, ft = /* @__PURE__ */ new E(), is = /* @__PURE__ */ new E(), ie = /* @__PURE__ */ new q(), mt = /* @__PURE__ */ new he();
class ct extends fn {
get projection() {
return this.tiling.projection;
}
constructor(e = {}) {
const {
shape: t = "planar",
endCaps: s = !0,
...n
} = e;
super(n), this.shape = t, this.endCaps = s;
}
// override the parse to mesh logic to support a region mesh
async parseToMesh(e, t, ...s) {
const n = await super.parseToMesh(e, t, ...s), { shape: i, projection: r, tiles: o, tiling: l } = this;
if (i === "ellipsoid") {
const c = o.ellipsoid, u = t[oe], h = t[xe], d = t[Te], [m, f, p, g] = t.boundingVolume.region, y = Math.ceil((g - f) * M.RAD2DEG * 0.25), x = Math.ceil((p - m) * M.RAD2DEG * 0.25), T = Math.max(bi, y), _ = Math.max(Ti, x), S = new qt(1, 1, _, T), [b, C, A, w] = l.getTileBounds(h, d, u, !0, !0), P = l.getTileContentUVBounds(h, d, u), { position: U, normal: B, uv: W } = S.attributes, $ = U.count;
t.cached.boundingVolume.getSphere(mt);
for (let z = 0; z < $; z++) {
ft.fromBufferAttribute(U, z), ie.fromBufferAttribute(W, z);
const L = r.convertProjectionToLongitude(M.mapLinear(ie.x, 0, 1, b, A));
let v = r.convertProjectionToLatitude(M.mapLinear(ie.y, 0, 1, C, w));
if (r.isMercator && this.endCaps && (w === 1 && ie.y === 1 && (v = Math.PI / 2), C === 0 && ie.y === 0 && (v = -Math.PI / 2)), r.isMercator && ie.y !== 0 && ie.y !== 1) {
const I = r.convertProjectionToLatitude(1), N = 1 / T, Q = M.mapLinear(ie.y - N, 0, 1, f, g), k = M.mapLinear(ie.y + N, 0, 1, f, g);
v > I && Q < I && (v = I), v < -I && k > -I && (v = -I);
}
c.getCartographicToPosition(v, L, 0, ft).sub(mt.center), c.getCartographicToNormal(v, L, is);
const D = M.mapLinear(r.convertLongitudeToProjection(L), b, A, P[0], P[2]), V = M.mapLinear(r.convertLatitudeToProjection(v), C, w, P[1], P[3]);
W.setXY(z, D, V), U.setXYZ(z, ...ft), B.setXYZ(z, ...is);
}
n.geometry = S, n.position.copy(mt.center);
}
return n;
}
createBoundingVolume(e, t, s) {
if (this.shape === "ellipsoid") {
const { tiling: n, endCaps: i } = this, r = s === -1, o = r ? n.getContentBounds(!0) : n.getTileBounds(e, t, s, !0, !0), l = r ? n.getContentBounds() : n.getTileBounds(e, t, s, !1, !0);
return i && (o[3] === 1 && (l[3] = Math.PI / 2), o[1] === 0 && (l[1] = -Math.PI / 2)), {
region: [...l, -1, 1]
};
} else
return super.createBoundingVolume(e, t, s);
}
createChild(...e) {
const t = super.createChild(...e), { shape: s, projection: n, tiling: i } = this;
if (t && s === "ellipsoid") {
const r = t[oe], o = t[xe], l = t[Te];
if (r === -1)
return t.geometricError = 1e50, parent;
const [c, u, h, d] = i.getTileBounds(o, l, r, !0), { tilePixelWidth: m, tilePixelHeight: f } = i.getLevel(r), p = (h - c) / m, g = (d - u) / f, [
/* west */
,
y,
x,
T
] = i.getTileBounds(o, l, r), _ = y > 0 != T > 0 ? 0 : Math.min(Math.abs(y), Math.abs(T)), S = n.convertLatitudeToProjection(_), b = n.getLongitudeDerivativeAtProjection(c), C = n.getLatitudeDerivativeAtProjection(S), [A, w] = xi(this.tiles.ellipsoid, _, x), P = Math.max(p * b * A, g * C * w);
t.geometricError = P;
}
return t;
}
}
class de {
get isMercator() {
return this.scheme === "EPSG:3857";
}
constructor(e = "EPSG:4326") {
this.scheme = e, this.tileCountX = 1, this.tileCountY = 1, this.setScheme(e);
}
setScheme(e) {
switch (this.scheme = e, e) {
// equirect
case "CRS:84":
case "EPSG:4326":
this.tileCountX = 2, this.tileCountY = 1;
break;
// mercator
case "EPSG:3857":
this.tileCountX = 1, this.tileCountY = 1;
break;
default:
throw new Error(`ProjectionScheme: Unknown projection scheme "${e}"`);
}
}
convertProjectionToLatitude(e) {
if (this.isMercator) {
const t = M.mapLinear(e, 0, 1, -1, 1);
return 2 * Math.atan(Math.exp(t * Math.PI)) - Math.PI / 2;
} else
return M.mapLinear(e, 0, 1, -Math.PI / 2, Math.PI / 2);
}
convertProjectionToLongitude(e) {
return M.mapLinear(e, 0, 1, -Math.PI, Math.PI);
}
convertLatitudeToProjection(e) {
if (this.isMercator) {
const t = Math.log(Math.tan(Math.PI / 4 + e / 2));
return 1 / 2 + 1 * t / (2 * Math.PI);
} else
return M.mapLinear(e, -Math.PI / 2, Math.PI / 2, 0, 1);
}
convertLongitudeToProjection(e) {
return (e + Math.PI) / (2 * Math.PI);
}
getLongitudeDerivativeAtProjection(e) {
return 2 * Math.PI;
}
getLatitudeDerivativeAtProjection(e) {
let s = e - 1e-5;
return s < 0 && (s = e + 1e-5), this.isMercator ? Math.abs(this.convertProjectionToLatitude(e) - this.convertProjectionToLatitude(s)) / 1e-5 : Math.PI;
}
getBounds() {
return [
this.convertProjectionToLongitude(0),
this.convertProjectionToLatitude(0),
this.convertProjectionToLongitude(1),
this.convertProjectionToLatitude(1)
];
}
}
function ve(...a) {
return a.join("_");
}
class _i {
constructor() {
this.cache = {}, this.count = 0, this.cachedBytes = 0, this.active = 0;
}
// overridable
fetchItem() {
}
disposeItem() {
}
getMemoryUsage(e) {
return 0;
}
// sets the data in the cache explicitly without need to load
setData(...e) {
const { cache: t } = this, s = e.pop(), n = ve(...e);
if (n in t)
throw new Error(`DataCache: "${n}" is already present.`);
return this.cache[n] = {
abortController: new AbortController(),
result: s,
count: 1,
bytes: this.getMemoryUsage(s)
}, this.count++, this.cachedBytes += this.cache[n].bytes, s;
}
// fetches the associated data if it doesn't exist and increments the lock counter
lock(...e) {
const { cache: t } = this, s = ve(...e);
if (s in t)
t[s].count++;
else {
const n = new AbortController(), i = {
abortController: n,
result: null,
count: 1,
bytes: 0
};
this.active++, i.result = this.fetchItem(e, n.signal), i.result instanceof Promise ? i.result.then((r) => (i.result = r, i.bytes = this.getMemoryUsage(r), this.cachedBytes += i.bytes, r)).finally(() => {
this.active--;
}).catch((r) => {
}) : (this.active--, i.bytes = this.getMemoryUsage(i.result), this.cachedBytes += i.bytes), this.cache[s] = i, this.count++;
}
return t[s].result;
}
// decrements the lock counter for the item and deletes the item if it has reached zero
release(...e) {
const t = ve(...e);
this.releaseViaFullKey(t);
}
// get the loaded item
get(...e) {
const { cache: t } = this, s = ve(...e);
return s in t && t[s].count > 0 ? t[s].result : null;
}
has(...e) {
const { cache: t } = this;
return ve(...e) in t;
}
// dispose all items
dispose() {
const { cache: e } = this;
for (const t in e) {
const { abortController: s } = e[t];
s.abort(), this.releaseViaFullKey(t, !0);
}
this.cache = {};
}
// releases an item with an optional force flag
releaseViaFullKey(e, t = !1) {
const { cache: s } = this;
if (e in s && s[e].count > 0) {
const n = s[e];
if (n.count--, n.count === 0 || t) {
const i = () => {
if (s[e] !== n)
return;
const { result: r, abortController: o } = n;
o.abort(), r instanceof Promise ? r.then((l) => {
this.disposeItem(l), this.count--, this.cachedBytes -= n.bytes;
}).catch(() => {
}) : (this.disposeItem(r), this.count--, this.cachedBytes -= n.bytes), delete s[e];
};
t ? i() : queueMicrotask(() => {
n.count === 0 && i();
});
}
return !0;
}
throw new Error("DataCache: Attempting to release key that does not exist");
}
}
function rs(a, e) {
const [t, s, n, i] = a, [r, o, l, c] = e;
return !(t >= l || n <= r || s >= c || i <= o);
}
class mn {
get levelCount() {
return this._levels.length;
}
get maxLevel() {
return this.levelCount - 1;
}
get minLevel() {
const e = this._levels;
for (let t = 0; t < e.length; t++)
if (e[t] !== null)
return t;
return -1;
}
// prioritize user-set bounds over projection bounds if present
get contentBounds() {
var e;
return this._contentBounds ?? ((e = this.projection) == null ? void 0 : e.getBounds()) ?? [0, 0, 1, 1];
}
get aspectRatio() {
const { pixelWidth: e, pixelHeight: t } = this.getLevel(this.maxLevel);
return e / t;
}
constructor() {
this.flipY = !1, this.pixelOverlap = 0, this._contentBounds = null, this.projection = null, this._levels = [];
}
// build the zoom levels
setLevel(e, t = {}) {
const s = this._levels;
for (; s.length < e; )
s.push(null);
const {
tilePixelWidth: n = 256,
tilePixelHeight: i = 256,
tileCountX: r = 2 ** e,
tileCountY: o = 2 ** e,
tileBounds: l = null
} = t, {
pixelWidth: c = n * r,
pixelHeight: u = i * o
} = t;
s[e] = {
// The pixel resolution of each tile.
tilePixelWidth: n,
tilePixelHeight: i,
// The total pixel resolution of the final image at this level. These numbers
// may not be a round multiple of the tile width.
pixelWidth: c,
pixelHeight: u,
// Or the total number of tiles that can be loaded at this level.
tileCountX: r,
tileCountY: o,
// The bounds covered by the extent of the tiles at this loaded. The actual content covered by the overall tileset
// may be a subset of this range (eg there may be unused space).
tileBounds: l
};
}
generateLevels(e, t, s, n = {}) {
const {
minLevel: i = 0,
tilePixelWidth: r = 256,
tilePixelHeight: o = 256
} = n, l = e - 1, {
pixelWidth: c = r * t * 2 ** l,
pixelHeight: u = o * s * 2 ** l
} = n;
for (let h = i; h < e; h++) {
const d = e - h - 1, m = Math.ceil(c * 2 ** -d), f = Math.ceil(u * 2 ** -d), p = Math.ceil(m / r), g = Math.ceil(f / o);
this.setLevel(h, {
tilePixelWidth: r,
tilePixelHeight: o,
pixelWidth: m,
pixelHeight: f,
tileCountX: p,
tileCountY: g
});
}
}
getLevel(e) {
return this._levels[e];
}
// bounds representing the contentful region of the image
setContentBounds(e, t, s, n) {
this._contentBounds = [e, t, s, n];
}
setProjection(e) {
this.projection = e;
}
// query functions
getTileAtPoint(e, t, s, n = !1) {
const { flipY: i } = this, { tileCountX: r, tileCountY: o, tileBounds: l } = this.getLevel(s), c = 1 / r, u = 1 / o;
if (n || ([e, t] = this.toNormalizedPoint(e, t)), l) {
const m = this.toNormalizedRange(l);
e = M.mapLinear(e, m[0], m[2], 0, 1), t = M.mapLinear(t, m[1], m[3], 0, 1);
}
const h = Math.floor(e / c);
let d = Math.floor(t / u);
return i && (d = o - 1 - d), [h, d];
}
getTilesInRange(e, t, s, n, i, r = !1) {
const o = [e, t, s, n], l = this.getContentBounds(r);
let c = this.getLevel(i).tileBounds;
if (!rs(o, l))
return [0, 0, -1, -1];
if (c && (r && (c = this.toNormalizedRange(c)), !rs(o, l)))
return [0, 0, -1, -1];
const [u, h, d, m] = this.clampToContentBounds(o, r), f = this.getTileAtPoint(u, h, i, r), p = this.getTileAtPoint(d, m, i, r);
this.flipY && ([f[1], p[1]] = [p[1], f[1]]);
const { tileCountX: g, tileCountY: y } = this.getLevel(i), [x, T] = f, [_, S] = p;
return _ < 0 || S < 0 || x >= g || T >= y ? [0, 0, -1, -1] : [
M.clamp(x, 0, g - 1),
M.clamp(T, 0, y - 1),
M.clamp(_, 0, g - 1),
M.clamp(S, 0, y - 1)
];
}
getTileExists(e, t, s) {
const [n, i, r, o] = this.contentBounds, [l, c, u, h] = this.getTileBounds(e, t, s);
return !(l >= u || c >= h) && l <= r && c <= o && u >= n && h >= i;
}
getContentBounds(e = !1) {
const { projection: t } = this, s = [...this.contentBounds];
return t && e && (s[0] = t.convertLongitudeToProjection(s[0]), s[1] = t.convertLatitudeToProjection(s[1]), s[2] = t.convertLongitudeToProjection(s[2]), s[3] = t.convertLatitudeToProjection(s[3])), s;
}
// returns the UV range associated with the content in the given tile
getTileContentUVBounds(e, t, s) {
const [n, i, r, o] = this.getTileBounds(e, t, s, !0, !0), [l, c, u, h] = this.getTileBounds(e, t, s, !0, !1);
return [
M.mapLinear(n, l, u, 0, 1),
M.mapLinear(i, c, h, 0, 1),
M.mapLinear(r, l, u, 0, 1),
M.mapLinear(o, c, h, 0, 1)
];
}
getTileBounds(e, t, s, n = !1, i = !0) {
const { flipY: r, pixelOverlap: o, projection: l } = this, { tilePixelWidth: c, tilePixelHeight: u, pixelWidth: h, pixelHeight: d, tileBounds: m } = this.getLevel(s);
let f = c * e - o, p = u * t - o, g = f + c + o * 2, y = p + u + o * 2;
if (f = Math.max(f, 0), p = Math.max(p, 0), g = Math.min(g, h), y = Math.min(y, d), f = f / h, g = g / h, p = p / d, y = y / d, r) {
const T = (y - p) / 2, S = 1 - (p + y) / 2;
p = S - T, y = S + T;
}
let x = [f, p, g, y];
if (m) {
const T = this.toNormalizedRange(m);
x[0] = M.mapLinear(x[0], 0, 1, T[0], T[2]), x[2] = M.mapLinear(x[2], 0, 1, T[0], T[2]), x[1] = M.mapLinear(x[1], 0, 1, T[1], T[3]), x[3] = M.mapLinear(x[3], 0, 1, T[1], T[3]);
}
return i && (x = this.clampToProjectionBounds(x, !0)), l && !n && (x[0] = l.convertProjectionToLongitude(x[0]), x[1] = l.convertProjectionToLatitude(x[1]), x[2] = l.convertProjectionToLongitude(x[2]), x[3] = l.convertProjectionToLatitude(x[3])), x;
}
toNormalizedPoint(e, t) {
const { projection: s } = this, n = [e, t];
return this.projection && (n[0] = s.convertLongitudeToProjection(n[0]), n[1] = s.convertLatitudeToProjection(n[1])), n;
}
toNormalizedRange(e) {
return [
...this.toNormalizedPoint(e[0], e[1]),
...this.toNormalizedPoint(e[2], e[3])
];
}
toCartographicPoint(e, t) {
const { projection: s } = this, n = [e, t];
if (this.projection)
n[0] = s.convertProjectionToLongitude(n[0]), n[1] = s.convertProjectionToLatitude(n[1]);
else
throw new Error("TilingScheme: Projection not available.");
return n;
}
toCartographicRange(e) {
return [
...this.toCartographicPoint(e[0], e[1]),
...this.toCartographicPoint(e[2], e[3])
];
}
clampToContentBounds(e, t = !1) {
const s = [...e], [n, i, r, o] = this.getContentBounds(t);
return s[0] = M.clamp(s[0], n, r), s[1] = M.clamp(s[1], i, o), s[2] = M.clamp(s[2], n, r), s[3] = M.clamp(s[3], i, o), s;
}
clampToProjectionBounds(e, t = !1) {
const s = [...e], { projection: n } = this;
let i;
t || !n ? i = [0, 0, 1, 1] : i = n.getBounds();
const [r, o, l, c] = i;
return s[0] = M.clamp(s[0], r, l), s[1] = M.clamp(s[1], o, c), s[2] = M.clamp(s[2], r, l), s[3] = M.clamp(s[3], o, c), s;
}
}
class Ae extends _i {
constructor(e = {}) {
super();
const {
fetchOptions: t = {}
} = e;
this.tiling = new mn(), this.fetchOptions = t, this.fetchData = (...s) => fetch(...s);
}
// async function for initializing the tiled image set
init() {
}
// helper for processing the buffer into a texture
async processBufferToTexture(e) {
const t = new Blob([e]), s = await createImageBitmap(t, {
premultiplyAlpha: "none",
colorSpaceConversion: "none",
imageOrientation: "flipY"
}), n = new kn(s);
return n.generateMipmaps = !1, n.colorSpace = Ks, n.needsUpdate = !0, n;
}
getMemoryUsage(e) {
const { format: t, type: s, image: n, generateMipmaps: i } = e, { width: r, height: o } = n, l = Gn.getByteLength(r, o, t, s);
return i ? l * 4 / 3 : l;
}
// fetch the item with the given key fields
fetchItem(e, t) {
const s = {
...this.fetchOptions,
signal: t
}, n = this.getUrl(...e);
return this.fetchData(n, s).then((i) => i.arrayBuffer()).then((i) => this.processBufferToTexture(i));
}
// dispose of the item that was fetched
disposeItem(e) {
e.dispose(), e.image instanceof ImageBitmap && e.image.close();
}
getUrl(...e) {
}
}
class Fe extends Ae {
constructor(e = {}) {
const {
levels: t = 20,
tileDimension: s = 256,
url: n = null,
...i
} = e;
super(i), this.tileDimension = s, this.levels = t, this.url = n;
}
getUrl(e, t, s) {
return this.url.replace(/{\s*z\s*}/gi, s).replace(/{\s*x\s*}/gi, e).replace(/{\s*(y|reverseY|-\s*y)\s*}/gi, t);
}
init() {
const { tiling: e, tileDimension: t, levels: s, url: n } = this;
return e.flipY = !/{\s*reverseY|-\s*y\s*}/g.test(n), e.setProjection(new de("EPSG:3857")), e.setContentBounds(...e.projection.getBounds()), e.generateLevels(s, e.projection.tileCountX, e.projection.tileCountY, {
tilePixelWidth: t,
tilePixelHeight: t
}), this.url = n, Promise.resolve();
}
}
class $t extends Ae {
constructor(e = {}) {
const {
url: t = null,
...s
} = e;
super(s), this.tileSets = null, this.extension = null, this.url = t;
}
getUrl(e, t, s) {
const { url: n, extension: i, tileSets: r, tiling: o } = this;
return new URL(`${parseInt(r[s - o.minLevel].href)}/${e}/${t}.${i}`, n).toString();
}
init() {
const { url: e } = this;
return this.fetchData(new URL("tilemapresource.xml", e), this.fetchOptions).then((t) => t.text()).then((t) => {
const { tiling: s } = this, n = new DOMParser().parseFromString(t, "text/xml"), i = n.querySelector("BoundingBox"), r = n.querySelector("TileFormat"), l = [...n.querySelector("TileSets").querySelectorAll("TileSet")].map((y) => ({
href: parseInt(y.getAttribute("href")),
unitsPerPixel: parseFloat(y.getAttribute("units-per-pixel")),
order: parseInt(y.getAttribute("order"))
})).sort((y, x) => y.order - x.order), c = parseFloat(i.getAttribute("minx")) * M.DEG2RAD, u = parseFloat(i.getAttribute("maxx")) * M.DEG2RAD, h = parseFloat(i.getAttribute("miny")) * M.DEG2RAD, d = parseFloat(i.getAttribute("maxy")) * M.DEG2RAD, m = parseInt(r.getAttribute("width")), f = parseInt(r.getAttribute("height")), p = r.getAttribute("extension"), g = n.querySelector("SRS").textContent;
this.extension = p, this.url = e, this.tileSets = l, s.setProjection(new de(g)), s.setContentBounds(c, h, u, d), l.forEach(({ order: y }) => {
s.setLevel(y, {
tileCountX: s.projection.tileCountX * 2 ** y,
tilePixelWidth: m,
tilePixelHeight: f
});
});
});
}
}
function Mi(a) {
return /(:84|:crs84)$/i.test(a);
}
class gn extends Ae {
constructor(e = {}) {
const {
capabilities: t = null,
layer: s = null,
tileMatrixSet: n = null,
style: i = null,
url: r = null,
dimensions: o = {},
...l
} = e;
super(l), this.capabilities = t, this.layer = s, this.tileMatrixSet = n, this.style = i, this.dimensions = o, this.url = r;
}
getUrl(e, t, s) {
return this.url.replace(/{\s*TileMatrix\s*}/gi, s).replace(/{\s*TileCol\s*}/gi, e).replace(/{\s*TileRow\s*}/gi, t);
}
init() {
const { tiling: e, dimensions: t, capabilities: s } = this;
let { layer: n, tileMatrixSet: i, style: r, url: o } = this;
n ? typeof n == "string" && (n = s.layers.find((u) => u.identifier === n)) : n = s.layers[0], i ? typeof i == "string" && (i = n.tileMatrixSets.find((u) => u.identifier === i)) : i = n.tileMatrixSets[0], r || (r = n.styles.find((u) => u.isDefault).identifier), o || (o = n.resourceUrls[0].template);
const l = i.supportedCRS, c = l.includes("4326") || Mi(l) ? "EPSG:4326" : "EPSG:3857";
e.flipY = !0, e.setProjection(new de(c)), n.boundingBox !== null ? e.setContentBounds(...n.boundingBox.bounds) : e.setContentBounds(...e.projection.getBounds()), i.tileMatrices.forEach((u, h) => {
const { tileWidth: d, tileHeight: m, matrixWidth: f, matrixHeight: p } = u;
e.setLevel(h, {
tilePixelWidth: d,
tilePixelHeight: m,
tileCountX: f || e.projection.tileCountX * 2 ** h,
tileCountY: p || e.projection.tileCountY * 2 ** h,
tileBounds: u.bounds
});
}), o = o.replace(/{\s*TileMatrixSet\s*}/g, i.identifier).replace(/{\s*Style\s*}/g, r);
for (const u in t)
o = o.replace(new RegExp(`{\\s*${u}\\s*}`), t[u]);
return n.dimensions.forEach((u) => {
o = o.replace(new RegExp(`{\\s*${u.identifier}\\s*}`), u.defaultValue);
}), this.url = o, Promise.resolve();
}
}
class yn extends Ae {
// TODO: layer and styles can be arrays, comma separated lists
constructor(e = {}) {
const {
url: t = null,
layer: s = null,
styles: n = null,
contentBoundingBox: i = null,
version: r = "1.3.0",
crs: o = "EPSG:4326",
format: l = "image/png",
transparent: c = !1,
levels: u = 18,
tileDimension: h = 256,
...d
} = e;
super(d), this.url = t, this.layer = s, this.crs = o, this.format = l, this.tileDimension = h, this.styles = n, this.version = r, this.levels = u, this.transparent = c, this.contentBoundingBox = i;
}
init() {
const { tiling: e, levels: t, tileDimension: s, contentBoundingBox: n } = this;
return e.setProjection(new de(this.crs)), e.flipY = !0, e.generateLevels(t, e.projection.tileCountX, e.projection.tileCountY, {
tilePixelWidth: s,
tilePixelHeight: s
}), n !== null ? e.setContentBounds(...n) : e.setContentBounds(...e.projection.getBounds()), Promise.resolve();
}
// TODO: handle this in ProjectionScheme or TilingScheme? Or Loader?
normalizedToMercatorX(e) {
return M.mapLinear(e, 0, 1, -20037508342789244e-9, 20037508342789244e-9);
}
normalizedToMercatorY(e) {
return M.mapLinear(e, 0, 1, -20037508342789244e-9, 20037508342789244e-9);
}
getUrl(e, t, s) {
const {
tiling: n,
layer: i,
crs: r,
format: o,
tileDimension: l,
styles: c,
version: u,
transparent: h
} = this, d = u === "1.1.1" ? "SRS" : "CRS";
let m;
if (r === "EPSG:3857") {
const p = n.getTileBounds(e, t, s, !0, !1), g = this.normalizedToMercatorX(p[0]), y = this.normalizedToMercatorY(p[1]), x = this.normalizedToMercatorX(p[2]), T = this.normalizedToMercatorY(p[3]);
m = [g, y, x, T];
} else {
const [p, g, y, x] = n.getTileBounds(e, t, s, !1, !1).map((T) => T * M.RAD2DEG);
r === "EPSG:4326" ? u === "1.1.1" ? m = [p, g, y, x] : m = [g, p, x, y] : m = [p, g, y, x];
}
const f = new URLSearchParams({
SERVICE: "WMS",
REQUEST: "GetMap",
VERSION: u,
LAYERS: i,
[d]: r,
BBOX: m.join(","),
WIDTH: l,
HEIGHT: l,
FORMAT: o,
TRANSPARENT: h ? "TRUE" : "FALSE"
});
return c != null && f.set("STYLES", c), new URL("?" + f.toString(), this.url).toString();
}
}
class no extends ct {
constructor(e = {}) {
const {
levels: t,
tileDimension: s,
url: n,
...i
} = e;
super(i), this.name = "XYZ_TILES_PLUGIN", this.imageSource = new Fe({ url: n, levels: t, tileDimension: s });
}
}
class Si extends ct {
constructor(e = {}) {
const { url: t, ...s } = e;
super(s), this.name = "TMS_TILES_PLUGIN", this.imageSource = new $t({ url: t });
}
}
class io extends ct {
constructor(e = {}) {
const {
capabilities: t,
layer: s,
tileMatrixSet: n,
style: i,
dimensions: r,
...o
} = e;
super(o), this.name = "WTMS_TILES_PLUGIN", this.imageSource = new gn({
capabilities: t,
layer: s,
tileMatrixSet: n,
style: i,
dimensions: r
});
}
}
class ro extends ct {
constructor(e = {}) {
const {
url: t,
layer: s,
crs: n,
format: i,
tileDimension: r,
styles: o,
version: l,
...c
} = e;
super(c), this.name = "WMS_TILES_PLUGIN", this.imageSource = new yn({
url: t,
layer: s,
crs: n,
format: i,
tileDimension: r,
styles: o,
version: l
});
}
}
const os = /* @__PURE__ */ new E(), ze = /* @__PURE__ */ new Xt(), F = /* @__PURE__ */ new E(), re = /* @__PURE__ */ new E();
class Ci extends Un {
constructor(e = jn) {
super(), this.manager = e, this.ellipsoid = new un(), this.skirtLength = 1e3, this.smoothSkirtNormals = !0, this.generateNormals = !0, this.solid = !1, this.minLat = -Math.PI / 2, this.maxLat = Math.PI / 2, this.minLon = -Math.PI, this.maxLon = Math.PI;
}
parse(e) {
const {
ellipsoid: t,
solid: s,
skirtLength: n,
smoothSkirtNormals: i,
generateNormals: r,
minLat: o,
maxLat: l,
minLon: c,
maxLon: u
} = this, {
header: h,
indices: d,
vertexData: m,
edgeIndices: f,
extensions: p
} = super.parse(e), g = new et(), y = new en(), x = new Oe(g, y);
x.position.set(...h.center);
const T = "octvertexnormals" in p, _ = T || r, S = m.u.length, b = [], C = [], A = [], w = [];
let P = 0, U = 0;
for (let L = 0; L < S; L++)
W(L, F), $(F.x, F.y, F.z, re), C.push(F.x, F.y), b.push(...re);
for (let L = 0, v = d.length; L < v; L++)
A.push(d[L]);
if (_)
if (T) {
const L = p.octvertexnormals.normals;
for (let v = 0, D = L.length; v < D; v++)
w.push(L[v]);
} else {
const L = new et(), v = d.length > 21845 ? new Uint32Array(d) : new Uint16Array(d);
L.setIndex(new J(v, 1, !1)), L.setAttribute("position", new J(new Float32Array(b), 3, !1)), L.computeVertexNormals();
const V = L.getAttribute("normal").array;
p.octvertexnormals = { normals: V };
for (let I = 0, N = V.length; I < N; I++)
w.push(V[I]);
}
if (g.addGroup(P, d.length, U), P += d.length, U++, s) {
const L = b.length / 3;
for (let v = 0; v < S; v++)
W(v, F), $(F.x, F.y, F.z, re, -n), C.push(F.x, F.y), b.push(...re);
for (let v = d.length - 1; v >= 0; v--)
A.push(d[v] + L);
if (_) {
const v = p.octvertexnormals.normals;
for (let D = 0, V = v.length; D < V; D++)
w.push(-v[D]);
}
g.addGroup(P, d.length, U), P += d.length, U++;
}
if (n > 0) {
const {
westIndices: L,
eastIndices: v,
southIndices: D,
northIndices: V
} = f;
let I;
const N = z(L);
I = b.length / 3, C.push(...N.uv), b.push(...N.positions);
for (let O = 0, Z = N.indices.length; O < Z; O++)
A.push(N.indices[O] + I);
const Q = z(v);
I = b.length / 3, C.push(...Q.uv), b.push(...Q.positions);
for (let O = 0, Z = Q.indices.length; O < Z; O++)
A.push(Q.indices[O] + I);
const k = z(D);
I = b.length / 3, C.push(...k.uv), b.push(...k.positions);
for (let O = 0, Z = k.indices.length; O < Z; O++)
A.push(k.indices[O] + I);
const G = z(V);
I = b.length / 3, C.push(...G.uv), b.push(...G.positions);
for (let O = 0, Z = G.indices.length; O < Z; O++)
A.push(G.indices[O] + I);
_ && (w.push(...N.normals), w.push(...Q.normals), w.push(...k.normals), w.push(...G.normals)), g.addGroup(P, d.length, U), P += d.length, U++;
}
for (let L = 0, v = b.length; L < v; L += 3)
b[L + 0] -= h.center[0], b[L + 1] -= h.center[1], b[L + 2] -= h.center[2];
const B = b.length / 3 > 65535 ? new Uint32Array(A) : new Uint16Array(A);
if (g.setIndex(new J(B, 1, !1)), g.setAttribute("position", new J(new Float32Array(b), 3, !1)), g.setAttribute("uv", new J(new Float32Array(C), 2, !1)), _ && g.setAttribute("normal", new J(new Float32Array(w), 3, !1)), "watermask" in p) {
const { mask: L, size: v } = p.watermask, D = new Uint8Array(2 * v * v);
for (let I = 0, N = L.length; I < N; I++) {
const Q = L[I] === 255 ? 0 : 255;
D[2 * I + 0] = Q, D[2 * I + 1] = Q;
}
const V = new Wt(D, v, v, tn, sn);
V.flipY = !0, V.minFilter = zn, V.magFilter = nn, V.needsUpdate = !0, y.roughnessMap = V;
}
return x.userData.minHeight = h.minHeight, x.userData.maxHeight = h.maxHeight, "metadata" in p && (x.userData.metadata = p.metadata.json), x;
function W(L, v) {
return v.x = m.u[L], v.y = m.v[L], v.z = m.height[L], v;
}
function $(L, v, D, V, I = 0) {
const N = M.lerp(h.minHeight, h.maxHeight, D), Q = M.lerp(c, u, L), k = M.lerp(o, l, v);
return t.getCartographicToPosition(k, Q, N + I, V), V;
}
function z(L) {
const v = [], D = [], V = [], I = [], N = [];
for (let G = 0, O = L.length; G < O; G++)
W(L[G], F), v.push(F.x, F.y), V.push(F.x, F.y), $(F.x, F.y, F.z, re), D.push(...re), $(F.x, F.y, F.z, re, -n), I.push(...re);
const Q = L.length - 1;
for (let G = 0; G < Q; G++) {
const O = G, Z = G + 1, pe = G + L.length, ht = G + L.length + 1;
N.push(O, pe, Z), N.push(Z, pe, ht);
}
let k = null;
if (_) {
const G = (D.length + I.length) / 3;
if (i) {
k = new Array(G * 3);
const O = p.octvertexnormals.normals, Z = k.length / 2;
for (let pe = 0, ht = G / 2; pe < ht; pe++) {
const dt = L[pe], _e = 3 * pe, Kt = O[3 * dt + 0], es = O[3 * dt + 1], ts = O[3 * dt + 2];
k[_e + 0] = Kt, k[_e + 1] = es, k[_e + 2] = ts, k[Z + _e + 0] = Kt, k[Z + _e + 1] = es, k[Z + _e + 2] = ts;
}
} else {
k = [], ze.a.fromArray(D, 0), ze.b.fromArray(I, 0), ze.c.fromArray(D, 3), ze.getNormal(os);
for (let O = 0; O < G; O++)
k.push(...os);
}
}
return {
uv: [...v, ...V],
positions: [...D, ...I],
indices: N,
normals: k
};
}
}
}
const j = 0, le = ["a", "b", "c"], R = /* @__PURE__ */ new Ve(), as = /* @__PURE__ */ new Ve(), ls = /* @__PURE__ */ new Ve(), cs = /* @__PURE__ */ new Ve();
class xn {
constructor() {
this.attributeList = null, this.splitOperations = [], this.trianglePool = new Ai();
}
forEachSplitPermutation(e) {
const { splitOperations: t } = this, s = (n = 0) => {
if (n >= t.length) {
e();
return;
}
t[n].keepPositive = !0, s(n + 1), t[n].keepPositive = !1, s(n + 1);
};
s();
}
// Takes an operation that returns a value for the given vertex passed to the callback. Triangles
// are clipped along edges where the interpolated value is equal to 0. The polygons on the positive
// side of the operation are kept if "keepPositive" is true.
// callback( geometry, i0, i1, i2, barycoord );
addSplitOperation(e, t = !0) {
this.splitOperations.push({
callback: e,
keepPositive: t
});
}
// Removes all split operations
clearSplitOperations() {
this.splitOperations.length = 0;
}
// clips an object hierarchy
clipObject(e) {
const t = e.clone(), s = [];
return t.traverse((n) => {
n.isMesh && (n.geometry = this.clip(n).geometry, (n.geometry.index ? n.geometry.index.count / 3 : n.attributes.position.count / 3) === 0 && s.push(n));
}), s.forEach((n) => {
n.removeFromParent();
}), t;
}
// Returns a new mesh that has been clipped by the split operations. Range indicates the range of
// elements to include when clipping.
clip(e, t = null) {
const s = this.getClippedData(e, t);
return this.constructMesh(s.attributes, s.index, e);
}
// Appends the clip operation data to the given "target" object so multiple ranges can be appended.
// The "target" object is returned with an "index" field, "vertexIsClipped" field, and series of arrays
// in "attributes".
// attributes - set of attribute arrays
// index - triangle indices referencing vertices in attributes
// vertexIsClipped - array indicating whether a vertex is on a clipped edge
getClippedData(e, t = null, s = {}) {
const { trianglePool: n, splitOperations: i, attributeList: r } = this, o = e.geometry, l = o.attributes.position, c = o.index;
let u = 0;
const h = {};
s.index = s.index || [], s.vertexIsClipped = s.vertexIsClipped || [], s.attributes = s.attributes || {};
for (const p in o.attributes) {
if (r !== null) {
if (r instanceof Function && !r(p))
continue;
if (Array.isArray(r) && !r.includes(p))
continue;
}
s.attributes[p] = [];
}
let d = 0, m = c ? c.count : l.count;
t !== null && (d = t.start, m = t.count);
for (let p = d, g = d + m; p < g; p += 3) {
let y = p + 0, x = p + 1, T = p + 2;
c && (y = c.getX(y), x = c.getX(x), T = c.getX(T));
const _ = n.get();
_.initFromIndices(y, x, T);
let S = [_];
for (let b = 0; b < i.length; b++) {
const { keepPositive: C, callback: A } = i[b], w = [];
for (let P = 0; P < S.length; P++) {
const U = S[P], { indices: B, barycoord: W } = U;
U.clipValues.a = A(o, B.a, B.b, B.c, W.a, e.matrixWorld), U.clipValues.b = A(o, B.a, B.b, B.c, W.b, e.matrixWorld), U.clipValues.c = A(o, B.a, B.b, B.c, W.c, e.matrixWorld), this.splitTriangle(U, !C, w);
}
S = w;
}
for (let b = 0, C = S.length; b < C; b++) {
const A = S[b];
f(A, o);
}
n.reset();
}
return s;
function f(p, g) {
for (let y = 0; y < 3; y++) {
const x = p.getVertexHash(y, g);
x in h || (h[x] = u, u++, p.getVertexData(y, g, s.attributes), s.vertexIsClipped.push(p.clipValues[le[y]] === j));
const T = h[x];
s.index.push(T);
}
}
}
// Takes the set of resultant data and constructs a mesh
constructMesh(e, t, s) {
const n = s.geometry, i = new et(), r = e.position.length / 3 > 65535 ? new Uint32Array(t) : new Uint16Array(t);
i.setIndex(new J(r, 1, !1));
for (const l in e) {
const c = n.getAttribute(l), u = new c.array.constructor(e[l]), h = new J(u, c.itemSize, c.normalized);
h.gpuType = c.gpuType, i.setAttribute(l, h);
}
const o = new Oe(i, s.material.clone());
return o.position.copy(s.position), o.quaternion.copy(s.quaternion), o.scale.copy(s.scale), o;
}
// Splits the given triangle
splitTriangle(e, t, s) {
const { trianglePool: n } = this, i = [], r = [], o = [];
for (let l = 0; l < 3; l++) {
const c = le[l], u = le[(l + 1) % 3], h = e.clipValues[c], d = e.clipValues[u];
(h < j != d < j || h === j) && (i.push(l), r.push([c, u]), h === d ? o.push(0) : o.push(M.mapLinear(j, h, d, 0, 1)));
}
if (i.length !== 2)
Math.min(
e.clipValues.a,
e.clipValues.b,
e.clipValues.c
) < j === t && s.push(e);
else if (i.length === 2) {
const l = n.get().initFromTriangle(e), c = n.get().initFromTriangle(e), u = n.get().initFromTriangle(e);
(i[0] + 1) % 3 === i[1] ? (l.lerpVertexFromEdge(e, r[0][0], r[0][1], o[0], "a"), l.copyVertex(e, r[0][1], "b"), l.lerpVertexFromEdge(e, r[1][0], r[1][1], o[1], "c"), l.clipValues.a = j, l.clipValues.c = j, c.lerpVertexFromEdge(e, r[0][0], r[0][1], o[0], "a"), c.copyVertex(e, r[1][1], "b"), c.copyVertex(e, r[0][0], "c"), c.clipValues.a = j, u.lerpVertexFromEdge(e, r[0][0], r[0][1], o[0], "a"), u.lerpVertexFromEdge(e, r[1][0], r[1][1], o[1], "b"), u.copyVertex(e, r[1][1], "c"), u.clipValues.a = j, u.clipValues.b = j) : (l.lerpVertexFromEdge(e, r[0][0], r[0][1], o[0], "a"), l.lerpVertexFromEdge(e, r[1][0], r[1][1], o[1], "b"), l.copyVertex(e, r[0][0], "c"), l.clipValues.a = j, l.clipValues.b = j, c.lerpVertexFromEdge(e, r[0][0], r[0][1], o[0], "a"), c.copyVertex(e, r[0][1], "b"), c.lerpVertexFromEdge(e, r[1][0], r[1][1], o[1], "c"), c.clipValues.a = j, c.clipValues.c = j, u.copyVertex(e, r[0][1], "a"), u.copyVertex(e, r[1][0], "b"), u.lerpVertexFromEdge(e, r[1][0], r[1][1], o[1], "c"), u.clipValues.c = j);
let d, m;
d = Math.min(l.clipValues.a, l.clipValues.b, l.clipValues.c), m = d < j, m === t && s.push(l), d = Math.min(c.clipValues.a, c.clipValues.b, c.clipValues.c), m = d < j, m === t && s.push(c), d = Math.min(u.clipValues.a, u.clipValues.b, u.clipValues.c), m = d < j, m === t && s.push(u);
}
}
}
class Ai {
constructor() {
this.pool = [], this.index = 0;
}
get() {
if (this.index >= this.pool.length) {
const t = new vi();
this.pool.push(t);
}
const e = this.pool[this.index];
return this.index++, e;
}
reset() {
this.index = 0;
}
}
class vi {
constructor() {
this.indices = {
a: -1,
b: -1,
c: -1
}, this.clipValues = {
a: -1,
b: -1,
c: -1
}, this.barycoord = new Xt();
}
// returns a hash for the given [0, 2] index based on attributes of the referenced geometry
getVertexHash(e, t) {
const { barycoord: s, indices: n } = this, i = le[e], r = s[i];
if (r.x === 1)
return n[le[0]];
if (r.y === 1)
return n[le[1]];
if (r.z === 1)
return n[le[2]];
{
const { attributes: o } = t;
let l = "";
for (const c in o) {
const u = o[c];
switch (us(u, n.a, n.b, n.c, r, R), (c === "normal" || c === "tangent" || c === "bitangent") && R.normalize(), u.itemSize) {
case 4:
l += Pe(R.x, R.y, R.z, R.w);
break;
case 3:
l += Pe(R.x, R.y, R.z);
break;
case 2:
l += Pe(R.x, R.y);
break;
case 1:
l += Pe(R.x);
break;
}
l += "|";
}
return l;
}
}
// Accumulate the vertex data in the given attribute arrays
getVertexData(e, t, s) {
const { barycoord: n, indices: i } = this, r = le[e], o = n[r], { attributes: l } = t;
for (const c in l) {
if (!s[c])
continue;
const u = l[c], h = s[c];
switch (us(u, i.a, i.b, i.c, o, R), (c === "normal" || c === "tangent" || c === "bitangent") && R.normalize(), u.itemSize) {
case 4:
h.push(R.x, R.y, R.z, R.w);
break;
case 3:
h.push(R.x, R.y, R.z);
break;
case 2:
h.push(R.x, R.y);
break;
case 1:
h.push(R.x);
break;
}
}
}
// Copy the indices from a target triangle
initFromTriangle(e) {
return this.initFromIndices(
e.indices.a,
e.indices.b,
e.indices.c
);
}
// Set the indices for the given
initFromIndices(e, t, s) {
return this.indices.a = e, this.indices.b = t, this.indices.c = s, this.clipValues.a = -1, this.clipValues.b = -1, this.clipValues.c = -1, this.barycoord.a.set(1, 0, 0), this.barycoord.b.set(0, 1, 0), this.barycoord.c.set(0, 0, 1), this;
}
// Lerp the given vertex along to the provided edge of the provided triangle
lerpVertexFromEdge(e, t, s, n, i) {
this.clipValues[i] = M.lerp(e.clipValues[t], e.clipValues[s], n), this.barycoord[i].lerpVectors(e.barycoord[t], e.barycoord[s], n);
}
// Copy a vertex from the provided triangle
copyVertex(e, t, s) {
this.clipValues[s] = e.clipValues[t], this.barycoord[s].copy(e.barycoord[t]);
}
}
function us(a, e, t, s, n, i) {
switch (as.fromBufferAttribute(a, e), ls.fromBufferAttribute(a, t), cs.fromBufferAttribute(a, s), i.set(0, 0, 0, 0).addScaledVector(as, n.x).addScaledVector(ls, n.y).addScaledVector(cs, n.z), a.itemSize) {
case 3:
R.w = 0;
break;
case 2:
R.w = 0, R.z = 0;
break;
case 1:
R.w = 0, R.z = 0, R.y = 0;
break;
}
return i;
}
function Pe(...a) {
let s = "";
for (let n = 0, i = a.length; n < i; n++)
s += ~~(a[n] * 1e5 + 0.5), n !== i - 1 && (s += "_");
return s;
}
const hs = {}, Li = /* @__PURE__ */ new E(), gt = /* @__PURE__ */ new E(), yt = /* @__PURE__ */ new E(), Ii = /* @__PURE__ */ new E(), Ei = /* @__PURE__ */ new E(), Y = /* @__PURE__ */ new E(), Me = /* @__PURE__ */ new E(), X = /* @__PURE__ */ new q(), ae = /* @__PURE__ */ new q(), ds = /* @__PURE__ */ new q();
class wi extends xn {
constructor() {
super(), this.ellipsoid = new un(), this.skirtLength = 1e3, this.smoothSkirtNormals = !0, this.solid = !1, this.minLat = -Math.PI / 2, this.maxLat = Math.PI / 2, this.minLon = -Math.PI, this.maxLon = Math.PI, this.attributeList = ["position", "normal", "uv"];
}
clipToQuadrant(e, t, s) {
const { solid: n, skirtLength: i, ellipsoid: r, smoothSkirtNormals: o } = this;
this.clearSplitOperations(), this.addSplitOperation(ps("x"), !t), this.addSplitOperation(ps("y"), !s);
let l, c;
const u = e.geometry.groups[0], h = this.getClippedData(e, u);
if (this.adjustVertices(h, e.position, 0), n) {
l = {
index: h.index.slice().reverse(),
attributes: {}
};
for (const S in h.attributes)
l.attributes[S] = h.attributes[S].slice();
const _ = l.attributes.normal;
if (_)
for (let S = 0; S < _.length; S += 3)
_[S + 0] *= -1, _[S + 1] *= -1, _[S + 2] *= -1;
this.adjustVertices(l, e.position, -i);
}
if (i > 0) {
c = {
index: [],
attributes: {
position: [],
normal: [],
uv: []
}
};
let _ = 0;
const S = {}, b = (B, W, $) => {
const z = Pe(...B, ...$, ...W);
z in S || (S[z] = _, _++, c.attributes.position.push(...B), c.attributes.normal.push(...$), c.attributes.uv.push(...W)), c.index.push(S[z]);
}, C = h.index, A = h.attributes.uv, w = h.attributes.position, P = h.attributes.normal, U = h.index.length / 3;
for (let B = 0; B < U; B++) {
const W = 3 * B;
for (let $ = 0; $ < 3; $++) {
const z = ($ + 1) % 3, L = C[W + $], v = C[W + z];
if (X.fromArray(A, L * 2), ae.fromArray(A, v * 2), X.x === ae.x && (X.x === 0 || X.x === 0.5 || X.x === 1) || X.y === ae.y && (X.y === 0 || X.y === 0.5 || X.y === 1)) {
gt.fromArray(w, L * 3), yt.fromArray(w, v * 3);
const D = gt, V = yt, I = Ii.copy(gt), N = Ei.copy(yt);
Y.copy(I).add(e.position), r.getPositionToNormal(Y, Y), I.addScaledVector(Y, -i), Y.copy(N).add(e.position), r.getPositionToNormal(Y, Y), N.addScaledVector(Y, -i), o && P ? (Y.fromArray(P, L * 3), Me.fromArray(P, v * 3)) : (Y.subVectors(D, V), Me.subVectors(D, I).cross(Y).normalize(), Y.copy(Me)), b(V, ae, Me), b(D, X, Y), b(I, X, Y), b(V, ae, Me), b(I, X, Y), b(N, ae, Me);
}
}
}
}
const d = h.index.length, m = h;
if (l) {
const { index: _, attributes: S } = l, b = m.attributes.position.length / 3;
for (let C = 0, A = _.length; C < A; C++)
m.index.push(_[C] + b);
for (const C in h.attributes)
m.attributes[C].push(...S[C]);
}
if (c) {
const { index: _, attributes: S } = c, b = m.attributes.position.length / 3;
for (let C = 0, A = _.length; C < A; C++)
m.index.push(_[C] + b);
for (const C in h.attributes)
m.attributes[C].push(...S[C]);
}
const f = t ? 0 : -0.5, p = s ? 0 : -0.5, g = m.attributes.uv;
for (let _ = 0, S = g.length; _ < S; _ += 2)
g[_] = (g[_] + f) * 2, g[_ + 1] = (g[_ + 1] + p) * 2;
const y = this.constructMesh(m.attributes, m.index, e);
y.userData.minHeight = e.userData.minHeight, y.userData.maxHeight = e.userData.maxHeight;
let x = 0, T = 0;
return y.geometry.addGroup(T, d, x), T += d, x++, l && (y.geometry.addGroup(T, l.index.length, x), T += l.index.length, x++), c && (y.geometry.addGroup(T, c.index.length, x), T += c.index.length, x++), y;
}
adjustVertices(e, t, s) {
const { ellipsoid: n, minLat: i, maxLat: r, minLon: o, maxLon: l } = this, { attributes: c, vertexIsClipped: u } = e, h = c.position, d = c.uv, m = h.length / 3;
for (let f = 0; f < m; f++) {
const p = X.fromArray(d, f * 2);
u && u[f] && (Math.abs(p.x - 0.5) < 1e-10 && (p.x = 0.5), Math.abs(p.y - 0.5) < 1e-10 && (p.y = 0.5), X.toArray(d, f * 2));
const g = M.lerp(i, r, p.y), y = M.lerp(o, l, p.x), x = Li.fromArray(h, f * 3).add(t);
n.getPositionToCartographic(x, hs), n.getCartographicToPosition(g, y, hs.height + s, x), x.sub(t), x.toArray(h, f * 3);
}
}
}
function ps(a) {
return (e, t, s, n, i) => {
const r = e.attributes.uv;
return X.fromBufferAttribute(r, t), ae.fromBufferAttribute(r, s), ds.fromBufferAttribute(r, n), X[a] * i.x + ae[a] * i.y + ds[a] * i.z - 0.5;
};
}
const fs = Symbol("TILE_X"), ms = Symbol("TILE_Y"), Re = Symbol("TILE_LEVEL"), me = Symbol("TILE_AVAILABLE"), He = 1e4, gs = /* @__PURE__ */ new E();
function Pi(a, e, t, s) {
if (a && e < a.length) {
const n = a[e];
for (let i = 0, r = n.length; i < r; i++) {
const { startX: o, startY: l, endX: c, endY: u } = n[i];
if (t >= o && t <= c && s >= l && s <= u)
return !0;
}
}
return !1;
}
function Tn(a) {
const { available: e = null, maxzoom: t = null } = a;
return t === null ? e.length - 1 : t;
}
function Ri(a) {
const { metadataAvailability: e = -1 } = a;
return e;
}
function xt(a, e) {
const t = a[Re], s = Ri(e), n = Tn(e);
return t < n && s !== -1 && t % s === 0;
}
function Bi(a, e, t, s, n) {
return n.tiles[0].replace(/{\s*z\s*}/g, t).replace(/{\s*x\s*}/g, a).replace(/{\s*y\s*}/g, e).replace(/{\s*version\s*}/g, s);
}
class Di {
constructor(e = {}) {
const {
useRecommendedSettings: t = !0,
skirtLength: s = null,
smoothSkirtNormals: n = !0,
generateNormals: i = !0,
solid: r = !1
} = e;
this.name = "QUANTIZED_MESH_PLUGIN", this.priority = -1e3, this.tiles = null, this.layer = null, this.useRecommendedSettings = t, this.skirtLength = s, this.smoothSkirtNormals = n, this.solid = r, this.generateNormals = i, this.attribution = null, this.tiling = new mn(), this.projection = new de();
}
// Plugin function
init(e) {
e.fetchOptions.headers = e.fetchOptions.headers || {}, e.fetchOptions.headers.Accept = "application/vnd.quantized-mesh,application/octet-stream;q=0.9", this.useRecommendedSettings && (e.errorTarget = 2), this.tiles = e;
}
loadRootTileset() {
const { tiles: e } = this;
let t = new URL("layer.json", new URL(e.rootURL, location.href));
return e.invokeAllPlugins((s) => t = s.preprocessURL ? s.preprocessURL(t, null) : t), e.invokeOnePlugin((s) => s.fetchData && s.fetchData(t, this.tiles.fetchOptions)).then((s) => s.json()).then((s) => {
this.layer = s;
const {
projection: n = "EPSG:4326",
extensions: i = [],
attribution: r = "",
available: o = null
} = s, {
tiling: l,
tiles: c,
projection: u
} = this;
r && (this.attribution = {
value: r,
type: "string",
collapsible: !0
}), i.length > 0 && (c.fetchOptions.headers.Accept += `;extensions=${i.join("-")}`), u.setScheme(n);
const { tileCountX: h, tileCountY: d } = u;
l.setProjection(u), l.generateLevels(Tn(s) + 1, h, d);
const m = [];
for (let g = 0; g < h; g++) {
const y = this.createChild(0, g, 0, o);
y && m.push(y);
}
const f = {
asset: {
version: "1.1"
},
geometricError: 1 / 0,
root: {
refine: "REPLACE",
geometricError: 1 / 0,
boundingVolume: {
region: [...this.tiling.getContentBounds(), -He, He]
},
children: m,
[me]: o,
[Re]: -1
}
};
let p = c.rootURL;
return c.invokeAllPlugins((g) => p = g.preprocessURL ? g.preprocessURL(p, null) : p), c.preprocessTileset(f, p), f;
});
}
parseToMesh(e, t, s, n) {
const {
skirtLength: i,
solid: r,
smoothSkirtNormals: o,
generateNormals: l,
tiles: c
} = this, u = c.ellipsoid;
let h;
if (s === "quantized_tile_split") {
const p = new URL(n).searchParams, g = p.get("left") === "true", y = p.get("bottom") === "true", x = new wi();
x.ellipsoid.copy(u), x.solid = r, x.smoothSkirtNormals = o, x.skirtLength = i === null ? t.geometricError : i;
const [T, _, S, b] = t.parent.boundingVolume.region;
x.minLat = _, x.maxLat = b, x.minLon = T, x.maxLon = S, h = x.clipToQuadrant(t.parent.cached.scene, g, y);
} else if (s === "terrain") {
const p = new Ci(c.manager);
p.ellipsoid.copy(u), p.solid = r, p.smoothSkirtNormals = o, p.generateNormals = l, p.skirtLength = i === null ? t.geometricError : i;
const [g, y, x, T] = t.boundingVolume.region;
p.minLat = y, p.maxLat = T, p.minLon = g, p.maxLon = x, h = p.parse(e);
} else
return;
const { minHeight: d, maxHeight: m, metadata: f } = h.userData;
return t.boundingVolume.region[4] = d, t.boundingVolume.region[5] = m, t.cached.boundingVolume.setRegionData(u, ...t.boundingVolume.region), f && ("geometricerror" in f && (t.geometricError = f.geometricerror), xt(t, this.layer) && "available" in f && t.children.length === 0 && (t[me] = [
...new Array(t[Re] + 1).fill(null),
...f.available
])), this.expandChildren(t), h;
}
getAttributions(e) {
this.attribution && e.push(this.attribution);
}
// Local functions
createChild(e, t, s, n) {
const { tiles: i, layer: r, tiling: o, projection: l } = this, c = i.ellipsoid, u = n === null && e === 0 || Pi(n, e, t, s), h = Bi(t, s, e, 1, r), d = [...o.getTileBounds(t, s, e), -He, He], [
/* west */
,
m,
/* east */
,
f,
/* minHeight */
,
p
] = d, g = m > 0 != f > 0 ? 0 : Math.min(Math.abs(m), Math.abs(f));
c.getCartographicToPosition(g, 0, p, gs), gs.z = 0;
const y = l.tileCountX, _ = Math.max(...c.radius) * 2 * Math.PI * 0.25 / (65 * y) / 2 ** e, S = {
[me]: null,
[Re]: e,
[fs]: t,
[ms]: s,
refine: "REPLACE",
geometricError: _,
boundingVolume: { region: d },
content: u ? { uri: h } : null,
children: []
};
return xt(S, r) || (S[me] = n), S;
}
expandChildren(e) {
const t = e[Re], s = e[fs], n = e[ms], i = e[me];
if (t >= this.tiling.maxLevel)
return;
let r = !1;
for (let o = 0; o < 2; o++)
for (let l = 0; l < 2; l++) {
const c = this.createChild(t + 1, 2 * s + o, 2 * n + l, i);
c.content !== null ? (e.children.push(c), r = !0) : (e.children.push(c), c.content = { uri: `tile.quantized_tile_split?bottom=${l === 0}&left=${o === 0}` });
}
r || (e.children.length = 0);
}
fetchData(e, t) {
if (/quantized_tile_split/.test(e))
return new ArrayBuffer();
}
disposeTile(e) {
xt(e, this.layer) && (e[me] = null), me in e && (e.children.forEach((t) => {
this.tiles.processNodeQueue.remove(t);
}), e.children.length = 0, e.__childrenProcessed = 0);
}
}
let oo = class extends Vn {
constructor(e = {}) {
super({
assetTypeHandler: (t, s, n) => {
t === "TERRAIN" && s.getPluginByName("QUANTIZED_MESH_PLUGIN") === null ? (console.warn(
'CesiumIonAuthPlugin: CesiumIonAuthPlugin plugin auto-registration has been deprecated. Please implement a custom "assetTypeHandler" for "TERRAIN" using "QuantizedMeshPlugin", instead.'
), s.registerPlugin(new Di({
useRecommendedSettings: this.useRecommendedSettings
}))) : t === "IMAGERY" && s.getPluginByName("TMS_TILES_PLUGIN") === null ? (console.warn(
'CesiumIonAuthPlugin: CesiumIonAuthPlugin plugin auto-registration has been deprecated. Please implement a custom "assetTypeHandler" for "IMAGERY" using "TMSTilesPlugin", instead.'
), s.registerPlugin(new Si({
useRecommendedSettings: this.useRecommendedSettings,
shape: "ellipsoid"
}))) : console.warn(`CesiumIonAuthPlugin: Cesium Ion asset type "${t}" unhandled.`);
},
...e
}), e.__suppress_warning__ && console.warn(
'CesiumIonAuthPlugin: Plugin has been moved to "3d-tiles-renderer/core/plugins".'
);
}
};
const Tt = /* @__PURE__ */ new K();
class lo {
constructor() {
this.name = "UPDATE_ON_CHANGE_PLUGIN", this.tiles = null, this.needsUpdate = !1, this.cameraMatrices = /* @__PURE__ */ new Map();
}
init(e) {
this.tiles = e, this._needsUpdateCallback = () => {
this.needsUpdate = !0;
}, this._onCameraAdd = ({ camera: t }) => {
this.needsUpdate = !0, this.cameraMatrices.set(t, new K());
}, this._onCameraDelete = ({ camera: t }) => {
this.needsUpdate = !0, this.cameraMatrices.delete(t);
}, e.addEventListener("needs-update", this._needsUpdateCallback), e.addEventListener("add-camera", this._onCameraAdd), e.addEventListener("delete-camera", this._onCameraDelete), e.addEventListener("camera-resolution-change", this._needsUpdateCallback), e.cameras.forEach((t) => {
this._onCameraAdd({ camera: t });
});
}
doTilesNeedUpdate() {
const e = this.tiles;
let t = !1;
this.cameraMatrices.forEach((n, i) => {
Tt.copy(e.group.matrixWorld).premultiply(i.matrixWorldInverse).premultiply(i.projectionMatrixInverse), t = t || !Tt.equals(n), n.copy(Tt);
});
const s = this.needsUpdate;
return this.needsUpdate = !1, s || t;
}
preprocessNode() {
this.needsUpdate = !0;
}
dispose() {
const e = this.tiles;
e.removeEventListener("camera-resolution-change", this._needsUpdateCallback), e.removeEventListener("needs-update", this._needsUpdateCallback), e.removeEventListener("add-camera", this._onCameraAdd), e.removeEventListener("delete-camera", this._onCameraDelete);
}
}
const ys = /* @__PURE__ */ new E();
function Le(a, e) {
if (a.isInterleavedBufferAttribute || a.array instanceof e)
return a;
const s = e === Int8Array || e === Int16Array || e === Int32Array ? -1 : 0, n = new e(a.count * a.itemSize), i = new J(n, a.itemSize, !0), r = a.itemSize, o = a.count;
for (let l = 0; l < o; l++)
for (let c = 0; c < r; c++) {
const u = M.clamp(a.getComponent(l, c), s, 1);
i.setComponent(l, c, u);
}
return i;
}
function Oi(a, e = Int16Array) {
const t = a.geometry, s = t.attributes, n = s.position;
if (n.isInterleavedBufferAttribute || n.array instanceof e)
return n;
const i = new e(n.count * n.itemSize), r = new J(i, n.itemSize, !1), o = n.itemSize, l = n.count;
t.computeBoundingBox();
const c = t.boundingBox, { min: u, max: h } = c, d = 2 ** (8 * e.BYTES_PER_ELEMENT - 1) - 1, m = -d;
for (let f = 0; f < l; f++)
for (let p = 0; p < o; p++) {
const g = p === 0 ? "x" : p === 1 ? "y" : "z", y = u[g], x = h[g], T = M.mapLinear(
n.getComponent(f, p),
y,
x,
m,
d
);
r.setComponent(f, p, T);
}
c.getCenter(ys).multiply(a.scale).applyQuaternion(a.quaternion), a.position.add(ys), a.scale.x *= 0.5 * (h.x - u.x) / d, a.scale.y *= 0.5 * (h.y - u.y) / d, a.scale.z *= 0.5 * (h.z - u.z) / d, s.position = r, a.geometry.boundingBox = null, a.geometry.boundingSphere = null, a.updateMatrixWorld();
}
class co {
constructor(e) {
this._options = {
// whether to generate normals if they don't already exist.
generateNormals: !1,
// whether to disable use of mipmaps since they are typically not necessary
// with something like 3d tiles.
disableMipmaps: !0,
// whether to compress certain attributes
compressIndex: !0,
compressNormals: !1,
compressUvs: !1,
compressPosition: !1,
// the TypedArray type to use when compressing the attributes
uvType: Int8Array,
normalType: Int8Array,
positionType: Int16Array,
...e
}, this.name = "TILES_COMPRESSION_PLUGIN", this.priority = -100;
}
processTileModel(e, t) {
const {
generateNormals: s,
disableMipmaps: n,
compressIndex: i,
compressUvs: r,
compressNormals: o,
compressPosition: l,
uvType: c,
normalType: u,
positionType: h
} = this._options;
e.traverse((d) => {
if (d.material && n) {
const m = d.material;
for (const f in m) {
const p = m[f];
p && p.isTexture && p.generateMipmaps && (p.generateMipmaps = !1, p.minFilter = nn);
}
}
if (d.geometry) {
const m = d.geometry, f = m.attributes;
if (r) {
const { uv: p, uv1: g, uv2: y, uv3: x } = f;
p && (f.uv = Le(p, c)), g && (f.uv1 = Le(g, c)), y && (f.uv2 = Le(y, c)), x && (f.uv3 = Le(x, c));
}
if (s && !f.normals && m.computeVertexNormals(), o && f.normals && (f.normals = Le(f.normals, u)), l && Oi(d, h), i && m.index) {
const p = f.position.count, g = m.index, y = p > 65535 ? Uint32Array : p > 255 ? Uint16Array : Uint8Array;
if (!(g.array instanceof y)) {
const x = new y(m.index.count);
x.set(g.array);
const T = new J(x, 1);
m.setIndex(T);
}
}
}
});
}
}
function H(a, e, t) {
return a && e in a ? a[e] : t;
}
function bn(a) {
return a !== "BOOLEAN" && a !== "STRING" && a !== "ENUM";
}
function Ui(a) {
return /^FLOAT/.test(a);
}
function Ne(a) {
return /^VEC/.test(a);
}
function ke(a) {
return /^MAT/.test(a);
}
function _n(a, e, t, s = null) {
return ke(t) || Ne(t) ? s.fromArray(a, e) : a[e];
}
function Nt(a) {
const { type: e, componentType: t } = a;
switch (e) {
case "SCALAR":
return t === "INT64" ? 0n : 0;
case "VEC2":
return new q();
case "VEC3":
return new E();
case "VEC4":
return new Ve();
case "MAT2":
return new qn();
case "MAT3":
return new Hn();
case "MAT4":
return new K();
case "BOOLEAN":
return !1;
case "STRING":
return "";
// the final value for enums is a string but are represented as integers
// during intermediate steps
case "ENUM":
return 0;
}
}
function xs(a, e) {
if (e == null)
return !1;
switch (a) {
case "SCALAR":
return typeof e == "number" || typeof e == "bigint";
case "VEC2":
return e.isVector2;
case "VEC3":
return e.isVector3;
case "VEC4":
return e.isVector4;
case "MAT2":
return e.isMatrix2;
case "MAT3":
return e.isMatrix3;
case "MAT4":
return e.isMatrix4;
case "BOOLEAN":
return typeof e == "boolean";
case "STRING":
return typeof e == "string";
case "ENUM":
return typeof e == "number" || typeof e == "bigint";
}
throw new Error("ClassProperty: invalid type.");
}
function De(a, e = null) {
switch (a) {
case "INT8":
return Int8Array;
case "INT16":
return Int16Array;
case "INT32":
return Int32Array;
case "INT64":
return BigInt64Array;
case "UINT8":
return Uint8Array;
case "UINT16":
return Uint16Array;
case "UINT32":
return Uint32Array;
case "UINT64":
return BigUint64Array;
case "FLOAT32":
return Float32Array;
case "FLOAT64":
return Float64Array;
}
switch (e) {
case "BOOLEAN":
return Uint8Array;
case "STRING":
return Uint8Array;
}
throw new Error("ClassProperty: invalid type.");
}
function Vi(a, e = null) {
if (a.array) {
e = e && Array.isArray(e) ? e : [], e.length = a.count;
for (let s = 0, n = e.length; s < n; s++)
e[s] = tt(a, e[s]);
} else
e = tt(a, e);
return e;
}
function tt(a, e = null) {
const t = a.default, s = a.type;
if (e = e || Nt(a), t === null) {
switch (s) {
case "SCALAR":
return 0;
case "VEC2":
return e.set(0, 0);
case "VEC3":
return e.set(0, 0, 0);
case "VEC4":
return e.set(0, 0, 0, 0);
case "MAT2":
return e.identity();
case "MAT3":
return e.identity();
case "MAT4":
return e.identity();
case "BOOLEAN":
return !1;
case "STRING":
return "";
case "ENUM":
return "";
}
throw new Error("ClassProperty: invalid type.");
} else if (ke(s))
e.fromArray(t);
else if (Ne(s))
e.fromArray(t);
else
return t;
}
function Fi(a, e) {
if (a.noData === null)
return e;
const t = a.noData, s = a.type;
if (Array.isArray(e))
for (let r = 0, o = e.length; r < o; r++)
e[r] = n(e[r]);
else
e = n(e);
return e;
function n(r) {
return i(r) && (r = tt(a, r)), r;
}
function i(r) {
if (ke(s)) {
const o = r.elements;
for (let l = 0, c = t.length; l < c; l++)
if (t[l] !== o[l])
return !1;
return !0;
} else if (Ne(s)) {
for (let o = 0, l = t.length; o < l; o++)
if (t[o] !== r.getComponent(o))
return !1;
return !0;
} else
return t === r;
}
}
function Ni(a, e) {
switch (a) {
case "INT8":
return Math.max(e / 127, -1);
case "INT16":
return Math.max(e, 32767, -1);
case "INT32":
return Math.max(e / 2147483647, -1);
case "INT64":
return Math.max(Number(e) / 9223372036854776e3, -1);
// eslint-disable-line no-loss-of-precision
case "UINT8":
return e / 255;
case "UINT16":
return e / 65535;
case "UINT32":
return e / 4294967295;
case "UINT64":
return Number(e) / 18446744073709552e3;
}
}
function ki(a, e) {
const {
type: t,
componentType: s,
scale: n,
offset: i,
normalized: r
} = a;
if (Array.isArray(e))
for (let h = 0, d = e.length; h < d; h++)
e[h] = o(e[h]);
else
e = o(e);
return e;
function o(h) {
return ke(t) ? h = c(h) : Ne(t) ? h = l(h) : h = u(h), h;
}
function l(h) {
return h.x = u(h.x), h.y = u(h.y), "z" in h && (h.z = u(h.z)), "w" in h && (h.w = u(h.w)), h;
}
function c(h) {
const d = h.elements;
for (let m = 0, f = d.length; m < f; m++)
d[m] = u(d[m]);
return h;
}
function u(h) {
return r && (h = Ni(s, h)), (r || Ui(s)) && (h = h * n + i), h;
}
}
function Qt(a, e, t = null) {
if (a.array) {
Array.isArray(e) || (e = new Array(a.count || 0)), e.length = t !== null ? t : a.count;
for (let s = 0, n = e.length; s < n; s++)
xs(a.type, e[s]) || (e[s] = Nt(a));
} else
xs(a.type, e) || (e = Nt(a));
return e;
}
function st(a, e) {
for (const t in e)
t in a || delete e[t];
for (const t in a) {
const s = a[t];
e[t] = Qt(s, e[t]);
}
}
function Gi(a) {
switch (a) {
case "ENUM":
return 1;
case "SCALAR":
return 1;
case "VEC2":
return 2;
case "VEC3":
return 3;
case "VEC4":
return 4;
case "MAT2":
return 4;
case "MAT3":
return 9;
case "MAT4":
return 16;
// unused
case "BOOLEAN":
return -1;
case "STRING":
return -1;
default:
return -1;
}
}
class ut {
constructor(e, t, s = null) {
this.name = t.name || null, this.description = t.description || null, this.type = t.type, this.componentType = t.componentType || null, this.enumType = t.enumType || null, this.array = t.array || !1, this.count = t.count || 0, this.normalized = t.normalized || !1, this.offset = t.offset || 0, this.scale = H(t, "scale", 1), this.max = H(t, "max", 1 / 0), this.min = H(t, "min", -1 / 0), this.required = t.required || !1, this.noData = H(t, "noData", null), this.default = H(t, "default", null), this.semantic = H(t, "semantic", null), this.enumSet = null, this.accessorProperty = s, s && (this.offset = H(s, "offset", this.offset), this.scale = H(s, "scale", this.scale), this.max = H(s, "max", this.max), this.min = H(s, "min", this.min)), t.type === "ENUM" && (this.enumSet = e[this.enumType], this.componentType === null && (this.componentType = H(this.enumSet, "valueType", "UINT16")));
}
// shape the given target to match the data type of the property
// enums are set to their integer value
shapeToProperty(e, t = null) {
return Qt(this, e, t);
}
// resolve the given object to the default value for the property for a single element
// enums are set to a default string
resolveDefaultElement(e) {
return tt(this, e);
}
// resolve the target to the default value for the property for every element if it's an array
// enums are set to a default string
resolveDefault(e) {
return Vi(this, e);
}
// converts any instances of no data to the default value
resolveNoData(e) {
return Fi(this, e);
}
// converts enums integers in the given target to strings
resolveEnumsToStrings(e) {
const t = this.enumSet;
if (this.type === "ENUM")
if (Array.isArray(e))
for (let n = 0, i = e.length; n < i; n++)
e[n] = s(e[n]);
else
e = s(e);
return e;
function s(n) {
const i = t.values.find((r) => r.value === n);
return i === null ? "" : i.name;
}
}
// apply scales
adjustValueScaleOffset(e) {
return bn(this.type) ? ki(this, e) : e;
}
}
class Zt {
constructor(e, t = {}, s = {}, n = null) {
this.definition = e, this.class = t[e.class], this.className = e.class, this.enums = s, this.data = n, this.name = "name" in e ? e.name : null, this.properties = null;
}
getPropertyNames() {
return Object.keys(this.class.properties);
}
includesData(e) {
return !!this.definition.properties[e];
}
dispose() {
}
_initProperties(e = ut) {
const t = {};
for (const s in this.class.properties)
t[s] = new e(this.enums, this.class.properties[s], this.definition.properties[s]);
this.properties = t;
}
}
class ji extends ut {
constructor(e, t, s = null) {
super(e, t, s), this.attribute = (s == null ? void 0 : s.attribute) ?? null;
}
}
class zi extends Zt {
constructor(...e) {
super(...e), this.isPropertyAttributeAccessor = !0, this._initProperties(ji);
}
getData(e, t, s = {}) {
const n = this.properties;
st(n, s);
for (const i in n)
s[i] = this.getPropertyValue(i, e, t, s[i]);
return s;
}
getPropertyValue(e, t, s, n = null) {
if (t >= this.count)
throw new Error("PropertyAttributeAccessor: Requested index is outside the range of the buffer.");
const i = this.properties[e], r = i.type;
if (i) {
if (!this.definition.properties[e])
return i.resolveDefault(n);
} else throw new Error("PropertyAttributeAccessor: Requested class property does not exist.");
n = i.shapeToProperty(n);
const o = s.getAttribute(i.attribute.toLowerCase());
if (ke(r)) {
const l = n.elements;
for (let c = 0, u = l.length; c < u; c < u)
l[c] = o.getComponent(t, c);
} else if (Ne(r))
n.fromBufferAttribute(o, t);
else if (r === "SCALAR" || r === "ENUM")
n = o.getX(t);
else
throw new Error("StructuredMetadata.PropertyAttributeAccessor: BOOLEAN and STRING types are not supported by property attributes.");
return n = i.adjustValueScaleOffset(n), n = i.resolveEnumsToStrings(n), n = i.resolveNoData(n), n;
}
}
class Hi extends ut {
constructor(e, t, s = null) {
super(e, t, s), this.values = (s == null ? void 0 : s.values) ?? null, this.valueLength = Gi(this.type), this.arrayOffsets = H(s, "arrayOffsets", null), this.stringOffsets = H(s, "stringOffsets", null), this.arrayOffsetType = H(s, "arrayOffsetType", "UINT32"), this.stringOffsetType = H(s, "stringOffsetType", "UINT32");
}
// returns the necessary array length based on the array offsets if present
getArrayLengthFromId(e, t) {
let s = this.count;
if (this.arrayOffsets !== null) {
const { arrayOffsets: n, arrayOffsetType: i } = this, r = De(i), o = new r(e[n]);
s = o[t + 1] - o[t];
}
return s;
}
// returns the index offset into the data buffer for the given id based on the
// the array offsets if present
getIndexOffsetFromId(e, t) {
let s = t;
if (this.arrayOffsets) {
const { arrayOffsets: n, arrayOffsetType: i } = this, r = De(i);
s = new r(e[n])[s];
} else this.array && (s *= this.count);
return s;
}
}
class qi extends Zt {
constructor(...e) {
super(...e), this.isPropertyTableAccessor = !0, this.count = this.definition.count, this._initProperties(Hi);
}
getData(e, t = {}) {
const s = this.properties;
st(s, t);
for (const n in s)
t[n] = this.getPropertyValue(n, e, t[n]);
return t;
}
// reads an individual element
_readValueAtIndex(e, t, s, n = null) {
const i = this.properties[e], { componentType: r, type: o } = i, l = this.data, c = l[i.values], u = De(r, o), h = new u(c), d = i.getIndexOffsetFromId(l, t);
if (bn(o) || o === "ENUM")
return _n(h, (d + s) * i.valueLength, o, n);
if (o === "STRING") {
let m = d + s, f = 0;
if (i.stringOffsets !== null) {
const { stringOffsets: g, stringOffsetType: y } = i, x = De(y), T = new x(l[g]);
f = T[m + 1] - T[m], m = T[m];
}
const p = new Uint8Array(h.buffer, m, f);
n = new TextDecoder().decode(p);
} else if (o === "BOOLEAN") {
const m = d + s, f = Math.floor(m / 8), p = m % 8;
n = (h[f] >> p & 1) === 1;
}
return n;
}
// Reads the data for the given table index
getPropertyValue(e, t, s = null) {
if (t >= this.count)
throw new Error("PropertyTableAccessor: Requested index is outside the range of the table.");
const n = this.properties[e];
if (n) {
if (!this.definition.properties[e])
return n.resolveDefault(s);
} else throw new Error("PropertyTableAccessor: Requested property does not exist.");
const i = n.array, r = this.data, o = n.getArrayLengthFromId(r, t);
if (s = n.shapeToProperty(s, o), i)
for (let l = 0, c = s.length; l < c; l++)
s[l] = this._readValueAtIndex(e, t, l, s[l]);
else
s = this._readValueAtIndex(e, t, 0, s);
return s = n.adjustValueScaleOffset(s), s = n.resolveEnumsToStrings(s), s = n.resolveNoData(s), s;
}
}
const Ie = /* @__PURE__ */ new Qn();
class Ts {
constructor() {
this._renderer = new Wn(), this._target = new Ft(1, 1), this._texTarget = new Ft(), this._quad = new hn(new rn({
blending: $n,
blendDst: Yn,
blendSrc: Xn,
uniforms: {
map: { value: null },
pixel: { value: new q() }
},
vertexShader: (
/* glsl */
`
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
),
fragmentShader: (
/* glsl */
`
uniform sampler2D map;
uniform ivec2 pixel;
void main() {
gl_FragColor = texelFetch( map, pixel, 0 );
}
`
)
}));
}
// increases the width of the target render target to support more data
increaseSizeTo(e) {
this._target.setSize(Math.max(this._target.width, e), 1);
}
// read data from the rendered texture asynchronously
readDataAsync(e) {
const { _renderer: t, _target: s } = this;
return t.readRenderTargetPixelsAsync(s, 0, 0, e.length / 4, 1, e);
}
// read data from the rendered texture
readData(e) {
const { _renderer: t, _target: s } = this;
t.readRenderTargetPixels(s, 0, 0, e.length / 4, 1, e);
}
// render a single pixel from the source at the destination point on the render target
// takes the texture, pixel to read from, and pixel to render in to
renderPixelToTarget(e, t, s) {
const { _renderer: n, _target: i } = this;
Ie.min.copy(t), Ie.max.copy(t), Ie.max.x += 1, Ie.max.y += 1, n.initRenderTarget(i), n.copyTextureToTexture(e, i.texture, Ie, s, 0);
}
}
const ue = /* @__PURE__ */ new class {
constructor() {
let a = null;
Object.getOwnPropertyNames(Ts.prototype).forEach((e) => {
e !== "constructor" && (this[e] = (...t) => (a = a || new Ts(), a[e](...t)));
});
}
}(), bs = /* @__PURE__ */ new q(), _s = /* @__PURE__ */ new q(), Ms = /* @__PURE__ */ new q();
function Wi(a, e) {
return e === 0 ? a.getAttribute("uv") : a.getAttribute(`uv${e}`);
}
function Mn(a, e, t = new Array(3)) {
let s = 3 * e, n = 3 * e + 1, i = 3 * e + 2;
return a.index && (s = a.index.getX(s), n = a.index.getX(n), i = a.index.getX(i)), t[0] = s, t[1] = n, t[2] = i, t;
}
function Sn(a, e, t, s, n) {
const [i, r, o] = s, l = Wi(a, e);
bs.fromBufferAttribute(l, i), _s.fromBufferAttribute(l, r), Ms.fromBufferAttribute(l, o), n.set(0, 0, 0).addScaledVector(bs, t.x).addScaledVector(_s, t.y).addScaledVector(Ms, t.z);
}
function Cn(a, e, t, s) {
const n = a.x - Math.floor(a.x), i = a.y - Math.floor(a.y), r = Math.floor(n * e % e), o = Math.floor(i * t % t);
return s.set(r, o), s;
}
const Ss = /* @__PURE__ */ new q(), Cs = /* @__PURE__ */ new q(), As = /* @__PURE__ */ new q();
class Xi extends ut {
constructor(e, t, s = null) {
super(e, t, s), this.channels = H(s, "channels", [0]), this.index = H(s, "index", null), this.texCoord = H(s, "texCoord", null), this.valueLength = parseInt(this.type.replace(/[^0-9]/g, "")) || 1;
}
// takes the buffer to read from and the value index to read
readDataFromBuffer(e, t, s = null) {
const n = this.type;
if (n === "BOOLEAN" || n === "STRING")
throw new Error("PropertyTextureAccessor: BOOLEAN and STRING types not supported.");
return _n(e, t * this.valueLength, n, s);
}
}
class Yi extends Zt {
constructor(...e) {
super(...e), this.isPropertyTextureAccessor = !0, this._asyncRead = !1, this._initProperties(Xi);
}
// Reads the full set of property data
getData(e, t, s, n = {}) {
const i = this.properties;
st(i, n);
const r = Object.keys(i), o = r.map((l) => n[l]);
return this.getPropertyValuesAtTexel(r, e, t, s, o), r.forEach((l, c) => n[l] = o[c]), n;
}
// Reads the full set of property data asynchronously
async getDataAsync(e, t, s, n = {}) {
const i = this.properties;
st(i, n);
const r = Object.keys(i), o = r.map((l) => n[l]);
return await this.getPropertyValuesAtTexelAsync(r, e, t, s, o), r.forEach((l, c) => n[l] = o[c]), n;
}
// Reads values asynchronously
getPropertyValuesAtTexelAsync(...e) {
this._asyncRead = !0;
const t = this.getPropertyValuesAtTexel(...e);
return this._asyncRead = !1, t;
}
// Reads values from the textures synchronously
getPropertyValuesAtTexel(e, t, s, n, i = []) {
for (; i.length < e.length; ) i.push(null);
i.length = e.length, ue.increaseSizeTo(i.length);
const r = this.data, o = this.definition.properties, l = this.properties, c = Mn(n, t);
for (let d = 0, m = e.length; d < m; d++) {
const f = e[d];
if (!o[f])
continue;
const p = l[f], g = r[p.index];
Sn(n, p.texCoord, s, c, Ss), Cn(Ss, g.image.width, g.image.height, Cs), As.set(d, 0), ue.renderPixelToTarget(g, Cs, As);
}
const u = new Uint8Array(e.length * 4);
if (this._asyncRead)
return ue.readDataAsync(u).then(() => (h.call(this), i));
return ue.readData(u), h.call(this), i;
function h() {
for (let d = 0, m = e.length; d < m; d++) {
const f = e[d], p = l[f], g = p.type;
if (i[d] = Qt(p, i[d]), p) {
if (!o[f]) {
i[d] = p.resolveDefault(i);
continue;
}
} else throw new Error("PropertyTextureAccessor: Requested property does not exist.");
const y = p.valueLength * (p.count || 1), x = p.channels.map((b) => u[4 * d + b]), T = p.componentType, _ = De(T, g), S = new _(y);
if (new Uint8Array(S.buffer).set(x), p.array) {
const b = i[d];
for (let C = 0, A = b.length; C < A; C++)
b[C] = p.readDataFromBuffer(S, C, b[C]);
} else
i[d] = p.readDataFromBuffer(S, 0, i[d]);
i[d] = p.adjustValueScaleOffset(i[d]), i[d] = p.resolveEnumsToStrings(i[d]), i[d] = p.resolveNoData(i[d]);
}
}
}
// dispose all of the texture data used
dispose() {
this.data.forEach((e) => {
e && (e.dispose(), e.image instanceof ImageBitmap && e.image.close());
});
}
}
class vs {
constructor(e, t, s, n = null, i = null) {
const {
schema: r,
propertyTables: o = [],
propertyTextures: l = [],
propertyAttributes: c = []
} = e, { enums: u, classes: h } = r, d = o.map((p) => new qi(p, h, u, s));
let m = [], f = [];
n && (n.propertyTextures && (m = n.propertyTextures.map((p) => new Yi(l[p], h, u, t))), n.propertyAttributes && (f = n.propertyAttributes.map((p) => new zi(c[p], h, u)))), this.schema = r, this.tableAccessors = d, this.textureAccessors = m, this.attributeAccessors = f, this.object = i, this.textures = t, this.nodeMetadata = n;
}
// Property Tables
getPropertyTableData(e, t, s = null) {
if (!Array.isArray(e) || !Array.isArray(t))
s = s || {}, s = this.tableAccessors[e].getData(t, s);
else {
s = s || [];
const n = Math.min(e.length, t.length);
s.length = n;
for (let i = 0; i < n; i++) {
const r = this.tableAccessors[e[i]];
s[i] = r.getData(t[i], s[i]);
}
}
return s;
}
getPropertyTableInfo(e = null) {
if (e === null && (e = this.tableAccessors.map((t, s) => s)), Array.isArray(e))
return e.map((t) => {
const s = this.tableAccessors[t];
return {
name: s.name,
className: s.definition.class
};
});
{
const t = this.tableAccessors[e];
return {
name: t.name,
className: t.definition.class
};
}
}
// Property Textures
getPropertyTextureData(e, t, s = []) {
const n = this.textureAccessors;
s.length = n.length;
for (let i = 0; i < n.length; i++) {
const r = n[i];
s[i] = r.getData(e, t, this.object.geometry, s[i]);
}
return s;
}
async getPropertyTextureDataAsync(e, t, s = []) {
const n = this.textureAccessors;
s.length = n.length;
const i = [];
for (let r = 0; r < n.length; r++) {
const l = n[r].getDataAsync(e, t, this.object.geometry, s[r]).then((c) => {
s[r] = c;
});
i.push(l);
}
return await Promise.all(i), s;
}
getPropertyTextureInfo() {
return this.textureAccessors;
}
// Property Attributes
getPropertyAttributeData(e, t = []) {
const s = this.attributeAccessors;
t.length = s.length;
for (let n = 0; n < s.length; n++) {
const i = s[n];
t[n] = i.getData(e, this.object.geometry, t[n]);
}
return t;
}
getPropertyAttributeInfo() {
return this.attributeAccessors.map((e) => ({
name: e.name,
className: e.definition.class
}));
}
dispose() {
this.textureAccessors.forEach((e) => e.dispose()), this.tableAccessors.forEach((e) => e.dispose()), this.attributeAccessors.forEach((e) => e.dispose());
}
}
const Ee = "EXT_structural_metadata";
function $i(a, e = []) {
var n;
const t = ((n = a.json.textures) == null ? void 0 : n.length) || 0, s = new Array(t).fill(null);
return e.forEach(({ properties: i }) => {
for (const r in i) {
const { index: o } = i[r];
s[o] === null && (s[o] = a.loadTexture(o));
}
}), Promise.all(s);
}
function Qi(a, e = []) {
var n;
const t = ((n = a.json.bufferViews) == null ? void 0 : n.length) || 0, s = new Array(t).fill(null);
return e.forEach(({ properties: i }) => {
for (const r in i) {
const { values: o, arrayOffsets: l, stringOffsets: c } = i[r];
s[o] === null && (s[o] = a.loadBufferView(o)), s[l] === null && (s[l] = a.loadBufferView(l)), s[c] === null && (s[c] = a.loadBufferView(c));
}
}), Promise.all(s);
}
class Zi {
constructor(e) {
this.parser = e, this.name = Ee;
}
async afterRoot({ scene: e, parser: t }) {
const s = t.json.extensionsUsed;
if (!s || !s.includes(Ee))
return;
let n = null, i = t.json.extensions[Ee];
if (i.schemaUri) {
const { manager: c, path: u, requestHeader: h, crossOrigin: d } = t.options, m = new URL(i.schemaUri, u).toString(), f = new Zn(c);
f.setCrossOrigin(d), f.setResponseType("json"), f.setRequestHeader(h), n = f.loadAsync(m).then((p) => {
i = { ...i, schema: p };
});
}
const [r, o] = await Promise.all([
$i(t, i.propertyTextures),
Qi(t, i.propertyTables),
n
]), l = new vs(i, r, o);
e.userData.structuralMetadata = l, e.traverse((c) => {
var u;
if (t.associations.has(c)) {
const { meshes: h, primitives: d } = t.associations.get(c), m = (u = t.json.meshes[h]) == null ? void 0 : u.primitives[d];
if (m && m.extensions && m.extensions[Ee]) {
const f = m.extensions[Ee];
c.userData.structuralMetadata = new vs(i, r, o, f, c);
} else
c.userData.structuralMetadata = l;
}
});
}
}
const Ls = /* @__PURE__ */ new q(), Is = /* @__PURE__ */ new q(), Es = /* @__PURE__ */ new q();
function Ji(a) {
return a.x > a.y && a.x > a.z ? 0 : a.y > a.z ? 1 : 2;
}
class Ki {
constructor(e, t, s) {
this.geometry = e, this.textures = t, this.data = s, this._asyncRead = !1, this.featureIds = s.featureIds.map((n) => {
const { texture: i, ...r } = n, o = {
label: null,
propertyTable: null,
nullFeatureId: null,
...r
};
return i && (o.texture = {
texCoord: 0,
channels: [0],
...i
}), o;
});
}
// returns list of textures
getTextures() {
return this.textures;
}
// returns a set of info for each feature
getFeatureInfo() {
return this.featureIds;
}
// performs texture data read back asynchronously
getFeaturesAsync(...e) {
this._asyncRead = !0;
const t = this.getFeatures(...e);
return this._asyncRead = !1, t;
}
// returns all features for the given point on the given triangle
getFeatures(e, t) {
const { geometry: s, textures: n, featureIds: i } = this, r = new Array(i.length).fill(null), o = i.length;
ue.increaseSizeTo(o);
const l = Mn(s, e), c = l[Ji(t)];
for (let d = 0, m = i.length; d < m; d++) {
const f = i[d], p = "nullFeatureId" in f ? f.nullFeatureId : null;
if ("texture" in f) {
const g = n[f.texture.index];
Sn(s, f.texture.texCoord, t, l, Ls), Cn(Ls, g.image.width, g.image.height, Is), Es.set(d, 0), ue.renderPixelToTarget(n[f.texture.index], Is, Es);
} else if ("attribute" in f) {
const y = s.getAttribute(`_feature_id_${f.attribute}`).getX(c);
y !== p && (r[d] = y);
} else {
const g = c;
g !== p && (r[d] = g);
}
}
const u = new Uint8Array(o * 4);
if (this._asyncRead)
return ue.readDataAsync(u).then(() => (h(), r));
return ue.readData(u), h(), r;
function h() {
const d = new Uint32Array(1);
for (let m = 0, f = i.length; m < f; m++) {
const p = i[m], g = "nullFeatureId" in p ? p.nullFeatureId : null;
if ("texture" in p) {
const { channels: y } = p.texture, x = y.map((_) => u[4 * m + _]);
new Uint8Array(d.buffer).set(x);
const T = d[0];
T !== g && (r[m] = T);
}
}
}
}
// dispose all of the texture data used
dispose() {
this.textures.forEach((e) => {
e && (e.dispose(), e.image instanceof ImageBitmap && e.image.close());
});
}
}
const nt = "EXT_mesh_features";
function ws(a, e, t) {
a.traverse((s) => {
var n;
if (e.associations.has(s)) {
const { meshes: i, primitives: r } = e.associations.get(s), o = (n = e.json.meshes[i]) == null ? void 0 : n.primitives[r];
o && o.extensions && o.extensions[nt] && t(s, o.extensions[nt]);
}
});
}
class er {
constructor(e) {
this.parser = e, this.name = nt;
}
async afterRoot({ scene: e, parser: t }) {
var o;
const s = t.json.extensionsUsed;
if (!s || !s.includes(nt))
return;
const n = ((o = t.json.textures) == null ? void 0 : o.length) || 0, i = new Array(n).fill(null);
ws(e, t, (l, { featureIds: c }) => {
c.forEach((u) => {
if (u.texture && i[u.texture.index] === null) {
const h = u.texture.index;
i[h] = t.loadTexture(h);
}
});
});
const r = await Promise.all(i);
ws(e, t, (l, c) => {
l.userData.meshFeatures = new Ki(l.geometry, r, c);
});
}
}
class tr {
constructor() {
this.name = "CESIUM_RTC";
}
afterRoot(e) {
if (e.parser.json.extensions && e.parser.json.extensions.CESIUM_RTC) {
const { center: t } = e.parser.json.extensions.CESIUM_RTC;
t && (e.scene.position.x += t[0], e.scene.position.y += t[1], e.scene.position.z += t[2]);
}
}
}
class uo {
constructor(e) {
e = {
metadata: !0,
rtc: !0,
plugins: [],
dracoLoader: null,
ktxLoader: null,
meshoptDecoder: null,
autoDispose: !0,
...e
}, this.tiles = null, this.metadata = e.metadata, this.rtc = e.rtc, this.plugins = e.plugins, this.dracoLoader = e.dracoLoader, this.ktxLoader = e.ktxLoader, this.meshoptDecoder = e.meshoptDecoder, this._gltfRegex = /\.(gltf|glb)$/g, this._dracoRegex = /\.drc$/g, this._loader = null;
}
init(e) {
const t = new fi(e.manager);
this.dracoLoader && (t.setDRACOLoader(this.dracoLoader), e.manager.addHandler(this._dracoRegex, this.dracoLoader)), this.ktxLoader && t.setKTX2Loader(this.ktxLoader), this.meshoptDecoder && t.setMeshoptDecoder(this.meshoptDecoder), this.rtc && t.register(() => new tr()), this.metadata && (t.register(() => new Zi()), t.register(() => new er())), this.plugins.forEach((s) => t.register(s)), e.manager.addHandler(this._gltfRegex, t), this.tiles = e, this._loader = t;
}
dispose() {
this.tiles.manager.removeHandler(this._gltfRegex), this.tiles.manager.removeHandler(this._dracoRegex), this.autoDispose && (this.ktxLoader.dispose(), this.dracoLoader.dispose());
}
}
const qe = /* @__PURE__ */ new he();
class ho {
constructor(e) {
e = {
up: "+z",
recenter: !0,
lat: null,
lon: null,
height: 0,
azimuth: 0,
elevation: 0,
roll: 0,
...e
}, this.tiles = null, this.up = e.up.toLowerCase().replace(/\s+/, ""), this.lat = e.lat, this.lon = e.lon, this.height = e.height, this.azimuth = e.azimuth, this.elevation = e.elevation, this.roll = e.roll, this.recenter = e.recenter, this._callback = null;
}
init(e) {
this.tiles = e, this._callback = () => {
const { up: t, lat: s, lon: n, height: i, azimuth: r, elevation: o, roll: l, recenter: c } = this;
if (s !== null && n !== null)
this.transformLatLonHeightToOrigin(s, n, i, r, o, l);
else {
const { ellipsoid: u } = e, h = Math.min(...u.radius);
if (e.getBoundingSphere(qe), qe.center.length() > h * 0.5) {
const d = {};
u.getPositionToCartographic(qe.center, d), this.transformLatLonHeightToOrigin(d.lat, d.lon, d.height);
} else {
const d = e.group;
switch (d.rotation.set(0, 0, 0), t) {
case "x":
case "+x":
d.rotation.z = Math.PI / 2;
break;
case "-x":
d.rotation.z = -Math.PI / 2;
break;
case "y":
case "+y":
break;
case "-y":
d.rotation.z = Math.PI;
break;
case "z":
case "+z":
d.rotation.x = -Math.PI / 2;
break;
case "-z":
d.rotation.x = Math.PI / 2;
break;
}
e.group.position.copy(qe.center).applyEuler(d.rotation).multiplyScalar(-1);
}
}
c || e.group.position.setScalar(0), e.removeEventListener("load-root-tileset", this._callback);
}, e.addEventListener("load-root-tileset", this._callback), e.root && this._callback();
}
transformLatLonHeightToOrigin(e, t, s = 0, n = 0, i = 0, r = 0) {
const { group: o, ellipsoid: l } = this.tiles;
l.getObjectFrame(e, t, s, n, i, r, o.matrix, ci), o.matrix.invert().decompose(o.position, o.quaternion, o.scale), o.updateMatrixWorld();
}
dispose() {
const { group: e } = this.tiles;
e.position.setScalar(0), e.quaternion.identity(), e.scale.set(1, 1, 1), this.tiles.removeEventListener("load-root-tileset", this._callback);
}
}
class po {
set delay(e) {
this.deferCallbacks.delay = e;
}
get delay() {
return this.deferCallbacks.delay;
}
set bytesTarget(e) {
this.lruCache.minBytesSize = e;
}
get bytesTarget() {
return this.lruCache.minBytesSize;
}
get estimatedGpuBytes() {
return this.lruCache.cachedBytes;
}
constructor(e = {}) {
const {
delay: t = 0,
bytesTarget: s = 0
} = e;
this.name = "UNLOAD_TILES_PLUGIN", this.tiles = null, this.lruCache = new mi(), this.deferCallbacks = new sr(), this.delay = t, this.bytesTarget = s;
}
init(e) {
this.tiles = e;
const { lruCache: t, deferCallbacks: s } = this;
s.callback = (i) => {
t.markUnused(i), t.scheduleUnload(!1);
};
const n = (i) => {
const r = i.cached.scene;
e.visibleTiles.has(i) || e.invokeOnePlugin((l) => l.unloadTileFromGPU && l.unloadTileFromGPU(r, i));
};
this._onUpdateBefore = () => {
t.unloadPriorityCallback = e.lruCache.unloadPriorityCallback, t.computeMemoryUsageCallback = e.lruCache.computeMemoryUsageCallback, t.minSize = 1 / 0, t.maxSize = 1 / 0, t.maxBytesSize = 1 / 0, t.unloadPercent = 1, t.autoMarkUnused = !1;
}, this._onVisibilityChangeCallback = ({ tile: i, visible: r }) => {
r ? (t.add(i, n), e.markTileUsed(i), s.cancel(i)) : s.run(i);
}, e.forEachLoadedModel((i, r) => {
const o = e.visibleTiles.has(r);
this._onVisibilityChangeCallback({ scene: i, visible: o });
}), e.addEventListener("tile-visibility-change", this._onVisibilityChangeCallback), e.addEventListener("update-before", this._onUpdateBefore);
}
unloadTileFromGPU(e, t) {
e && e.traverse((s) => {
if (s.material) {
const n = s.material;
n.dispose();
for (const i in n) {
const r = n[i];
r && r.isTexture && r.dispose();
}
}
s.geometry && s.geometry.dispose();
});
}
dispose() {
this.tiles.removeEventListener("tile-visibility-change", this._onVisibilityChangeCallback), this.tiles.removeEventListener("update-before", this._onUpdateBefore), this.deferCallbacks.cancelAll();
}
}
class sr {
constructor(e = () => {
}) {
this.map = /* @__PURE__ */ new Map(), this.callback = e, this.delay = 0;
}
run(e) {
const { map: t, delay: s } = this;
if (t.has(e))
throw new Error("DeferCallbackManager: Callback already initialized.");
s === 0 ? this.callback(e) : t.set(e, setTimeout(() => this.callback(e), s));
}
cancel(e) {
const { map: t } = this;
t.has(e) && (clearTimeout(t.get(e)), t.delete(e));
}
cancelAll() {
this.map.forEach((e, t) => {
this.cancel(t);
});
}
}
const { clamp: bt } = M;
class nr {
constructor() {
this.duration = 250, this.fadeCount = 0, this._lastTick = -1, this._fadeState = /* @__PURE__ */ new Map(), this.onFadeComplete = null, this.onFadeStart = null, this.onFadeSetComplete = null, this.onFadeSetStart = null;
}
// delete the object from the fade, reset the material data
deleteObject(e) {
e && this.completeFade(e);
}
// Ensure we're storing a fade timer for the provided object
// Returns whether a new state had to be added
guaranteeState(e) {
const t = this._fadeState;
if (t.has(e))
return !1;
const s = {
fadeInTarget: 0,
fadeOutTarget: 0,
fadeIn: 0,
fadeOut: 0
};
return t.set(e, s), !0;
}
// Force the fade to complete in the direction it is already trending
completeFade(e) {
const t = this._fadeState;
if (!t.has(e))
return;
const s = t.get(e).fadeOutTarget === 0;
t.delete(e), this.fadeCount--, this.onFadeComplete && this.onFadeComplete(e, s), this.fadeCount === 0 && this.onFadeSetComplete && this.onFadeSetComplete();
}
completeAllFades() {
this._fadeState.forEach((e, t) => {
this.completeFade(t);
});
}
forEachObject(e) {
this._fadeState.forEach((t, s) => {
e(s, t);
});
}
// Fade the object in
fadeIn(e) {
const t = this.guaranteeState(e), s = this._fadeState.get(e);
s.fadeInTarget = 1, s.fadeOutTarget = 0, s.fadeOut = 0, t && (this.fadeCount++, this.fadeCount === 1 && this.onFadeSetStart && this.onFadeSetStart(), this.onFadeStart && this.onFadeStart(e));
}
// Fade the object out
fadeOut(e) {
const t = this.guaranteeState(e), s = this._fadeState.get(e);
s.fadeOutTarget = 1, t && (s.fadeInTarget = 1, s.fadeIn = 1, this.fadeCount++, this.fadeCount === 1 && this.onFadeSetStart && this.onFadeSetStart(), this.onFadeStart && this.onFadeStart(e));
}
isFading(e) {
return this._fadeState.has(e);
}
isFadingOut(e) {
const t = this._fadeState.get(e);
return t && t.fadeOutTarget === 1;
}
// Tick the fade timer for each actively fading object
update() {
const e = window.performance.now();
this._lastTick === -1 && (this._lastTick = e);
const t = bt((e - this._lastTick) / this.duration, 0, 1);
this._lastTick = e, this._fadeState.forEach((n, i) => {
const {
fadeOutTarget: r,
fadeInTarget: o
} = n;
let {
fadeOut: l,
fadeIn: c
} = n;
const u = Math.sign(o - c);
c = bt(c + u * t, 0, 1);
const h = Math.sign(r - l);
l = bt(l + h * t, 0, 1), n.fadeIn = c, n.fadeOut = l, ((l === 1 || l === 0) && (c === 1 || c === 0) || l >= c) && this.completeFade(i);
});
}
}
const _t = Symbol("FADE_PARAMS");
function An(a, e) {
if (a[_t])
return a[_t];
const t = {
fadeIn: { value: 0 },
fadeOut: { value: 0 },
fadeTexture: { value: null }
};
return a[_t] = t, a.defines = {
...a.defines || {},
FEATURE_FADE: 0
}, a.onBeforeCompile = (s) => {
e && e(s), s.uniforms = {
...s.uniforms,
...t
}, s.vertexShader = s.vertexShader.replace(
/void\s+main\(\)\s+{/,
(n) => (
/* glsl */
`
#ifdef USE_BATCHING_FRAG
varying float vBatchId;
#endif
${n}
#ifdef USE_BATCHING_FRAG
// add 0.5 to the value to avoid floating error that may cause flickering
vBatchId = getIndirectIndex( gl_DrawID ) + 0.5;
#endif
`
)
), s.fragmentShader = s.fragmentShader.replace(/void main\(/, (n) => (
/* glsl */
`
#if FEATURE_FADE
// adapted from https://www.shadertoy.com/view/Mlt3z8
float bayerDither2x2( vec2 v ) {
return mod( 3.0 * v.y + 2.0 * v.x, 4.0 );
}
float bayerDither4x4( vec2 v ) {
vec2 P1 = mod( v, 2.0 );
vec2 P2 = floor( 0.5 * mod( v, 4.0 ) );
return 4.0 * bayerDither2x2( P1 ) + bayerDither2x2( P2 );
}
// the USE_BATCHING define is not available in fragment shaders
#ifdef USE_BATCHING_FRAG
// functions for reading the fade state of a given batch id
uniform sampler2D fadeTexture;
varying float vBatchId;
vec2 getFadeValues( const in float i ) {
int size = textureSize( fadeTexture, 0 ).x;
int j = int( i );
int x = j % size;
int y = j / size;
return texelFetch( fadeTexture, ivec2( x, y ), 0 ).rg;
}
#else
uniform float fadeIn;
uniform float fadeOut;
#endif
#endif
${n}
`
)).replace(/#include <dithering_fragment>/, (n) => (
/* glsl */
`
${n}
#if FEATURE_FADE
#ifdef USE_BATCHING_FRAG
vec2 fadeValues = getFadeValues( vBatchId );
float fadeIn = fadeValues.r;
float fadeOut = fadeValues.g;
#endif
float bayerValue = bayerDither4x4( floor( mod( gl_FragCoord.xy, 4.0 ) ) );
float bayerBins = 16.0;
float dither = ( 0.5 + bayerValue ) / bayerBins;
if ( dither >= fadeIn ) {
discard;
}
if ( dither < fadeOut ) {
discard;
}
#endif
`
));
}, t;
}
class ir {
constructor() {
this._fadeParams = /* @__PURE__ */ new WeakMap(), this.fading = 0;
}
// Set the fade parameters for the given scene
setFade(e, t, s) {
if (!e)
return;
const n = this._fadeParams;
e.traverse((i) => {
const r = i.material;
if (r && n.has(r)) {
const o = n.get(r);
o.fadeIn.value = t, o.fadeOut.value = s;
const u = +(!(t === 0 || t === 1) || !(s === 0 || s === 1));
r.defines.FEATURE_FADE !== u && (this.fading += u === 1 ? 1 : -1, r.defines.FEATURE_FADE = u, r.needsUpdate = !0);
}
});
}
// initialize materials in the object
prepareScene(e) {
e.traverse((t) => {
t.material && this.prepareMaterial(t.material);
});
}
// delete the object from the fade, reset the material data
deleteScene(e) {
if (!e)
return;
this.setFade(e, 1, 0);
const t = this._fadeParams;
e.traverse((s) => {
const n = s.material;
n && t.delete(n);
});
}
// initialize the material
prepareMaterial(e) {
const t = this._fadeParams;
t.has(e) || t.set(e, An(e, e.onBeforeCompile));
}
}
class rr {
constructor(e, t = new Ue()) {
this.other = e, this.material = t, this.visible = !0, this.parent = null, this._instanceInfo = [], this._visibilityChanged = !0;
const s = new Proxy(this, {
get(n, i) {
if (i in n)
return n[i];
{
const r = e[i];
return r instanceof Function ? (...o) => (n.syncInstances(), r.call(s, ...o)) : e[i];
}
},
set(n, i, r) {
return i in n ? n[i] = r : e[i] = r, !0;
},
deleteProperty(n, i) {
return i in n ? delete n[i] : delete e[i];
}
// ownKeys() {},
// has(target, key) {},
// defineProperty(target, key, descriptor) {},
// getOwnPropertyDescriptor(target, key) {},
});
return s;
}
syncInstances() {
const e = this._instanceInfo, t = this.other._instanceInfo;
for (; t.length > e.length; ) {
const s = e.length;
e.push(new Proxy({ visible: !1 }, {
get(n, i) {
return i in n ? n[i] : t[s][i];
},
set(n, i, r) {
return i in n ? n[i] = r : t[s][i] = r, !0;
}
}));
}
}
}
class or extends rr {
constructor(...e) {
super(...e);
const t = this.material, s = An(t, t.onBeforeCompile);
t.defines.FEATURE_FADE = 1, t.defines.USE_BATCHING_FRAG = 1, t.needsUpdate = !0, this.fadeTexture = null, this._fadeParams = s;
}
// Set the fade state
setFadeAt(e, t, s) {
this._initFadeTexture(), this.fadeTexture.setValueAt(e, t * 255, s * 255);
}
// initialize the texture and resize it if needed
_initFadeTexture() {
let e = Math.sqrt(this._maxInstanceCount);
e = Math.ceil(e);
const t = e * e * 2, s = this.fadeTexture;
if (!s || s.image.data.length !== t) {
const n = new Uint8Array(t), i = new ar(n, e, e, tn, sn);
if (s) {
s.dispose();
const r = s.image.data, o = this.fadeTexture.image.data, l = Math.min(r.length, o.length);
o.set(new r.constructor(r.buffer, 0, l));
}
this.fadeTexture = i, this._fadeParams.fadeTexture.value = i, i.needsUpdate = !0;
}
}
// dispose the fade texture. Super cannot be used here due to proxy
dispose() {
this.fadeTexture && this.fadeTexture.dispose();
}
}
class ar extends Wt {
setValueAt(e, ...t) {
const { data: s, width: n, height: i } = this.image, r = Math.floor(s.length / (n * i));
let o = !1;
for (let l = 0; l < r; l++) {
const c = e * r + l, u = s[c], h = t[l] || 0;
u !== h && (s[c] = h, o = !0);
}
o && (this.needsUpdate = !0);
}
}
const Ps = Symbol("HAS_POPPED_IN"), Rs = /* @__PURE__ */ new E(), Bs = /* @__PURE__ */ new E(), Ds = /* @__PURE__ */ new on(), Os = /* @__PURE__ */ new on(), Us = /* @__PURE__ */ new E();
function lr() {
const a = this._fadeManager, e = this.tiles;
this._fadingBefore = a.fadeCount, this._displayActiveTiles = e.displayActiveTiles, e.displayActiveTiles = !0;
}
function cr() {
const a = this._fadeManager, e = this._fadeMaterialManager, t = this._displayActiveTiles, s = this._fadingBefore, n = this._prevCameraTransforms, { tiles: i, maximumFadeOutTiles: r, batchedMesh: o } = this, { cameras: l } = i;
i.displayActiveTiles = t, a.update();
const c = a.fadeCount;
if (s !== 0 && c !== 0 && (i.dispatchEvent({ type: "fade-change" }), i.dispatchEvent({ type: "needs-render" })), t || i.visibleTiles.forEach((u) => {
const h = u.cached.scene;
h && (h.visible = u.__inFrustum), this.forEachBatchIds(u, (d, m, f) => {
m.setVisibleAt(d, u.__inFrustum), f.batchedMesh.setVisibleAt(d, u.__inFrustum);
});
}), r < this._fadingOutCount) {
let u = !0;
l.forEach((h) => {
if (!n.has(h))
return;
const d = h.matrixWorld, m = n.get(h);
d.decompose(Bs, Os, Us), m.decompose(Rs, Ds, Us);
const f = Os.angleTo(Ds), p = Bs.distanceTo(Rs);
u = u && (f > 0.25 || p > 0.1);
}), u && a.completeAllFades();
}
if (l.forEach((u) => {
n.get(u).copy(u.matrixWorld);
}), a.forEachObject((u, { fadeIn: h, fadeOut: d }) => {
const m = u.cached.scene, f = a.isFadingOut(u);
i.markTileUsed(u), m && (e.setFade(m, h, d), f && (m.visible = !0)), this.forEachBatchIds(u, (p, g, y) => {
g.setFadeAt(p, h, d), g.setVisibleAt(p, !0), y.batchedMesh.setVisibleAt(p, !1);
});
}), o) {
const u = i.getPluginByName("BATCHED_TILES_PLUGIN").batchedMesh.material;
o.material.map = u.map;
}
}
class fo {
get fadeDuration() {
return this._fadeManager.duration;
}
set fadeDuration(e) {
this._fadeManager.duration = Number(e);
}
get fadingTiles() {
return this._fadeManager.fadeCount;
}
constructor(e) {
e = {
maximumFadeOutTiles: 50,
fadeRootTiles: !1,
fadeDuration: 250,
...e
}, this.name = "FADE_TILES_PLUGIN", this.priority = -2, this.tiles = null, this.batchedMesh = null, this._quickFadeTiles = /* @__PURE__ */ new Set(), this._fadeManager = new nr(), this._fadeMaterialManager = new ir(), this._prevCameraTransforms = null, this._fadingOutCount = 0, this.maximumFadeOutTiles = e.maximumFadeOutTiles, this.fadeRootTiles = e.fadeRootTiles, this.fadeDuration = e.fadeDuration;
}
init(e) {
this._onLoadModel = ({ scene: n }) => {
this._fadeMaterialManager.prepareScene(n);
}, this._onDisposeModel = ({ tile: n, scene: i }) => {
this.tiles.visibleTiles.has(n) && this._quickFadeTiles.add(n.parent), this._fadeManager.deleteObject(n), this._fadeMaterialManager.deleteScene(i);
}, this._onAddCamera = ({ camera: n }) => {
this._prevCameraTransforms.set(n, new K());
}, this._onDeleteCamera = ({ camera: n }) => {
this._prevCameraTransforms.delete(n);
}, this._onTileVisibilityChange = ({ tile: n, visible: i }) => {
const r = n.cached.scene;
r && (r.visible = !0), this.forEachBatchIds(n, (o, l, c) => {
l.setFadeAt(o, 0, 0), l.setVisibleAt(o, !1), c.batchedMesh.setVisibleAt(o, !1);
});
}, this._onUpdateBefore = () => {
lr.call(this);
}, this._onUpdateAfter = () => {
cr.call(this);
}, e.addEventListener("load-model", this._onLoadModel), e.addEventListener("dispose-model", this._onDisposeModel), e.addEventListener("add-camera", this._onAddCamera), e.addEventListener("delete-camera", this._onDeleteCamera), e.addEventListener("update-before", this._onUpdateBefore), e.addEventListener("update-after", this._onUpdateAfter), e.addEventListener("tile-visibility-change", this._onTileVisibilityChange);
const t = this._fadeManager;
t.onFadeSetStart = () => {
e.dispatchEvent({ type: "fade-start" }), e.dispatchEvent({ type: "needs-render" });
}, t.onFadeSetComplete = () => {
e.dispatchEvent({ type: "fade-end" }), e.dispatchEvent({ type: "needs-render" });
}, t.onFadeComplete = (n, i) => {
this._fadeMaterialManager.setFade(n.cached.scene, 0, 0), this.forEachBatchIds(n, (r, o, l) => {
o.setFadeAt(r, 0, 0), o.setVisibleAt(r, !1), l.batchedMesh.setVisibleAt(r, i);
}), i || (e.invokeOnePlugin((r) => r !== this && r.setTileVisible && r.setTileVisible(n, !1)), this._fadingOutCount--);
};
const s = /* @__PURE__ */ new Map();
e.cameras.forEach((n) => {
s.set(n, new K());
}), e.forEachLoadedModel((n, i) => {
this._onLoadModel({ scene: n });
}), this.tiles = e, this._fadeManager = t, this._prevCameraTransforms = s;
}
// initializes the batched mesh if it needs to be, dispose if it it's no longer needed
initBatchedMesh() {
var t;
const e = (t = this.tiles.getPluginByName("BATCHED_TILES_PLUGIN")) == null ? void 0 : t.batchedMesh;
if (e) {
if (this.batchedMesh === null) {
this._onBatchedMeshDispose = () => {
this.batchedMesh.dispose(), this.batchedMesh.removeFromParent(), this.batchedMesh = null, e.removeEventListener("dispose", this._onBatchedMeshDispose);
};
const s = e.material.clone();
s.onBeforeCompile = e.material.onBeforeCompile, this.batchedMesh = new or(e, s), this.tiles.group.add(this.batchedMesh);
}
} else
this.batchedMesh !== null && (this._onBatchedMeshDispose(), this._onBatchedMeshDispose = null);
}
// callback for fading to prevent tiles from being removed until the fade effect has completed
setTileVisible(e, t) {
const s = this._fadeManager, n = s.isFading(e);
if (s.isFadingOut(e) && this._fadingOutCount--, t ? e.__depthFromRenderedParent === 1 ? ((e[Ps] || this.fadeRootTiles) && this._fadeManager.fadeIn(e), e[Ps] = !0) : this._fadeManager.fadeIn(e) : (this._fadingOutCount++, s.fadeOut(e)), this._quickFadeTiles.has(e) && (this._fadeManager.completeFade(e), this._quickFadeTiles.delete(e)), n)
return !0;
const i = this._fadeManager.isFading(e);
return !!(!t && i);
}
dispose() {
const e = this.tiles;
this._fadeManager.completeAllFades(), this.batchedMesh !== null && this._onBatchedMeshDispose(), e.removeEventListener("load-model", this._onLoadModel), e.removeEventListener("dispose-model", this._onDisposeModel), e.removeEventListener("add-camera", this._onAddCamera), e.removeEventListener("delete-camera", this._onDeleteCamera), e.removeEventListener("update-before", this._onUpdateBefore), e.removeEventListener("update-after", this._onUpdateAfter), e.removeEventListener("tile-visibility-change", this._onTileVisibilityChange), e.forEachLoadedModel((t, s) => {
this._fadeManager.deleteObject(s), t && (t.visible = !0);
});
}
// helper for iterating over the batch ids for a given tile
forEachBatchIds(e, t) {
if (this.initBatchedMesh(), this.batchedMesh) {
const s = this.tiles.getPluginByName("BATCHED_TILES_PLUGIN"), n = s.getTileBatchIds(e);
n && n.forEach((i) => {
t(i, this.batchedMesh, s);
});
}
}
}
const Mt = /* @__PURE__ */ new K(), Vs = /* @__PURE__ */ new E(), Fs = /* @__PURE__ */ new E();
class ur extends Jn {
constructor(...e) {
super(...e), this.resetDistance = 1e4, this._matricesTextureHandle = null, this._lastCameraPos = new K(), this._forceUpdate = !0, this._matrices = [];
}
setMatrixAt(e, t) {
super.setMatrixAt(e, t), this._forceUpdate = !0;
const s = this._matrices;
for (; s.length <= e; )
s.push(new K());
s[e].copy(t);
}
setInstanceCount(...e) {
super.setInstanceCount(...e);
const t = this._matrices;
for (; t.length > this.instanceCount; )
t.pop();
}
onBeforeRender(e, t, s, n, i, r) {
super.onBeforeRender(e, t, s, n, i, r), Vs.setFromMatrixPosition(s.matrixWorld), Fs.setFromMatrixPosition(this._lastCameraPos);
const o = this._matricesTexture;
let l = this._modelViewMatricesTexture;
if ((!l || l.image.width !== o.image.width || l.image.height !== o.image.height) && (l && l.dispose(), l = o.clone(), l.source = new Kn({
...l.image,
data: l.image.data.slice()
}), this._modelViewMatricesTexture = l), this._forceUpdate || Vs.distanceTo(Fs) > this.resetDistance) {
const c = this._matrices, u = l.image.data;
for (let h = 0; h < this.maxInstanceCount; h++) {
const d = c[h];
d ? Mt.copy(d) : Mt.identity(), Mt.premultiply(this.matrixWorld).premultiply(s.matrixWorldInverse).toArray(u, h * 16);
}
l.needsUpdate = !0, this._lastCameraPos.copy(s.matrixWorld), this._forceUpdate = !1;
}
this._matricesTextureHandle = this._matricesTexture, this._matricesTexture = this._modelViewMatricesTexture, this.matrixWorld.copy(this._lastCameraPos);
}
onAfterRender() {
this.updateMatrixWorld(), this._matricesTexture = this._matricesTextureHandle, this._matricesTextureHandle = null;
}
onAfterShadow(e, t, s, n, i, r) {
this.onAfterRender(e, null, n, i, r);
}
dispose() {
super.dispose(), this._modelViewMatricesTexture && this._modelViewMatricesTexture.dispose();
}
}
const ee = /* @__PURE__ */ new Oe(), We = [];
class hr extends ur {
constructor(...e) {
super(...e), this.expandPercent = 0.25, this.maxInstanceExpansionSize = 1 / 0, this._freeGeometryIds = [];
}
// Finds a free id that can fit the geometry with the requested ranges. Returns -1 if it could not be found.
findFreeId(e, t, s) {
const n = !!this.geometry.index, i = Math.max(n ? e.index.count : -1, s), r = Math.max(e.attributes.position.count, t);
let o = -1, l = 1 / 0;
const c = this._freeGeometryIds;
if (c.forEach((u, h) => {
const d = this.getGeometryRangeAt(u), { reservedIndexCount: m, reservedVertexCount: f } = d;
if (m >= i && f >= r) {
const p = i - m + (r - f);
p < l && (o = h, l = p);
}
}), o !== -1) {
const u = c[o];
return c.splice(o, 1), u;
} else
return -1;
}
// Overrides addGeometry to find an option geometry slot, expand, or optimized if needed
addGeometry(e, t, s) {
const n = !!this.geometry.index;
s = Math.max(n ? e.index.count : -1, s), t = Math.max(e.attributes.position.count, t);
const { expandPercent: i, _freeGeometryIds: r } = this;
let o = this.findFreeId(e, t, s);
if (o !== -1)
this.setGeometryAt(o, e);
else {
const l = () => {
const h = this.unusedVertexCount < t, d = this.unusedIndexCount < s;
return h || d;
}, c = e.index, u = e.attributes.position;
if (t = Math.max(t, u.count), s = Math.max(s, c ? c.count : 0), l() && (r.forEach((h) => this.deleteGeometry(h)), r.length = 0, this.optimize(), l())) {
const h = this.geometry.index, d = this.geometry.attributes.position;
let m, f;
if (h) {
const p = Math.ceil(i * h.count);
m = Math.max(p, s, c.count) + h.count;
} else
m = Math.max(this.unusedIndexCount, s);
if (d) {
const p = Math.ceil(i * d.count);
f = Math.max(p, t, u.count) + d.count;
} else
f = Math.max(this.unusedVertexCount, t);
this.setGeometrySize(f, m);
}
o = super.addGeometry(e, t, s);
}
return o;
}
// add an instance and automatically expand the number of instances if necessary
addInstance(e) {
if (this.maxInstanceCount === this.instanceCount) {
const t = Math.ceil(this.maxInstanceCount * (1 + this.expandPercent));
this.setInstanceCount(Math.min(t, this.maxInstanceExpansionSize));
}
return super.addInstance(e);
}
// delete an instance, keeping note that the geometry id is now unused
deleteInstance(e) {
const t = this.getGeometryIdAt(e);
return t !== -1 && this._freeGeometryIds.push(t), super.deleteInstance(e);
}
// add a function for raycasting per tile
raycastInstance(e, t, s) {
const n = this.geometry, i = this.getGeometryIdAt(e);
ee.material = this.material, ee.geometry.index = n.index, ee.geometry.attributes = n.attributes;
const r = this.getGeometryRangeAt(i);
ee.geometry.setDrawRange(r.start, r.count), ee.geometry.boundingBox === null && (ee.geometry.boundingBox = new lt()), ee.geometry.boundingSphere === null && (ee.geometry.boundingSphere = new he()), this.getMatrixAt(e, ee.matrixWorld).premultiply(this.matrixWorld), this.getBoundingBoxAt(i, ee.geometry.boundingBox), this.getBoundingSphereAt(i, ee.geometry.boundingSphere), ee.raycast(t, We);
for (let o = 0, l = We.length; o < l; o++) {
const c = We[o];
c.object = this, c.batchId = e, s.push(c);
}
We.length = 0;
}
}
function dr(a) {
return a.r === 1 && a.g === 1 && a.b === 1;
}
function pr(a) {
a.needsUpdate = !0, a.onBeforeCompile = (e) => {
e.vertexShader = e.vertexShader.replace(
"#include <common>",
/* glsl */
`
#include <common>
varying float texture_index;
`
).replace(
"#include <uv_vertex>",
/* glsl */
`
#include <uv_vertex>
texture_index = getIndirectIndex( gl_DrawID );
`
), e.fragmentShader = e.fragmentShader.replace(
"#include <map_pars_fragment>",
/* glsl */
`
#ifdef USE_MAP
precision highp sampler2DArray;
uniform sampler2DArray map;
varying float texture_index;
#endif
`
).replace(
"#include <map_fragment>",
/* glsl */
`
#ifdef USE_MAP
diffuseColor *= texture( map, vec3( vMapUv, texture_index ) );
#endif
`
);
};
}
const St = new hn(new Ue()), kt = new Wt(new Uint8Array([255, 255, 255, 255]), 1, 1);
kt.needsUpdate = !0;
class mo {
constructor(e = {}) {
if (parseInt(ei) < 170)
throw new Error("BatchedTilesPlugin: Three.js revision 170 or higher required.");
e = {
instanceCount: 500,
vertexCount: 750,
indexCount: 2e3,
expandPercent: 0.25,
maxInstanceCount: 1 / 0,
discardOriginalContent: !0,
textureSize: null,
material: null,
renderer: null,
...e
}, this.name = "BATCHED_TILES_PLUGIN", this.priority = -1;
const t = e.renderer.getContext();
this.instanceCount = e.instanceCount, this.vertexCount = e.vertexCount, this.indexCount = e.indexCount, this.material = e.material ? e.material.clone() : null, this.expandPercent = e.expandPercent, this.maxInstanceCount = Math.min(e.maxInstanceCount, t.getParameter(t.MAX_3D_TEXTURE_SIZE)), this.renderer = e.renderer, this.discardOriginalContent = e.discardOriginalContent, this.textureSize = e.textureSize, this.batchedMesh = null, this.arrayTarget = null, this.tiles = null, this._onLoadModel = null, this._onDisposeModel = null, this._onVisibilityChange = null, this._tileToInstanceId = /* @__PURE__ */ new Map();
}
init(e) {
this._onDisposeModel = ({ scene: t, tile: s }) => {
this.removeSceneFromBatchedMesh(t, s);
}, e.addEventListener("dispose-model", this._onDisposeModel), this.tiles = e;
}
initTextureArray(e) {
if (this.arrayTarget !== null || e.material.map === null)
return;
const { instanceCount: t, renderer: s, textureSize: n, batchedMesh: i } = this, r = e.material.map, o = {
colorSpace: r.colorSpace,
wrapS: r.wrapS,
wrapT: r.wrapT,
wrapR: r.wrapS,
// TODO: Generating mipmaps for the volume every time a new texture is added is extremely slow
// generateMipmaps: map.generateMipmaps,
// minFilter: map.minFilter,
magFilter: r.magFilter
}, l = new ss(n || r.image.width, n || r.image.height, t);
Object.assign(l.texture, o), s.initRenderTarget(l), i.material.map = l.texture, this.arrayTarget = l, this._tileToInstanceId.forEach((c) => {
c.forEach((u) => {
this.assignTextureToLayer(kt, u);
});
});
}
// init the batched mesh if it's not ready
initBatchedMesh(e) {
if (this.batchedMesh !== null)
return;
const { instanceCount: t, vertexCount: s, indexCount: n, tiles: i } = this, r = this.material ? this.material : new e.material.constructor(), o = new hr(t, t * s, t * n, r);
o.name = "BatchTilesPlugin", o.frustumCulled = !1, i.group.add(o), o.updateMatrixWorld(), pr(o.material), this.batchedMesh = o;
}
setTileVisible(e, t) {
const s = e.cached.scene;
if (t && this.addSceneToBatchedMesh(s, e), this._tileToInstanceId.has(e)) {
this._tileToInstanceId.get(e).forEach((r) => {
this.batchedMesh.setVisibleAt(r, t);
});
const i = this.tiles;
return t ? i.visibleTiles.add(e) : i.visibleTiles.delete(e), i.dispatchEvent({
type: "tile-visibility-change",
scene: s,
tile: e,
visible: t
}), !0;
}
return !1;
}
unloadTileFromGPU(e, t) {
return !this.discardOriginalContent && this._tileToInstanceId.has(t) ? (this.removeSceneFromBatchedMesh(e, t), !0) : !1;
}
// render the given into the given layer
assignTextureToLayer(e, t) {
if (!this.arrayTarget)
return;
this.expandArrayTargetIfNeeded();
const { renderer: s } = this, n = s.getRenderTarget();
s.setRenderTarget(this.arrayTarget, t), St.material.map = e, St.render(s), s.setRenderTarget(n), St.material.map = null, e.dispose();
}
// check if the array texture target needs to be expanded
expandArrayTargetIfNeeded() {
const { batchedMesh: e, arrayTarget: t, renderer: s } = this, n = Math.min(e.maxInstanceCount, this.maxInstanceCount);
if (n > t.depth) {
const i = {
colorSpace: t.texture.colorSpace,
wrapS: t.texture.wrapS,
wrapT: t.texture.wrapT,
generateMipmaps: t.texture.generateMipmaps,
minFilter: t.texture.minFilter,
magFilter: t.texture.magFilter
}, r = new ss(t.width, t.height, n);
Object.assign(r.texture, i), s.initRenderTarget(r), s.copyTextureToTexture(t.texture, r.texture), t.dispose(), e.material.map = r.texture, this.arrayTarget = r;
}
}
removeSceneFromBatchedMesh(e, t) {
if (this._tileToInstanceId.has(t)) {
const s = this._tileToInstanceId.get(t);
this._tileToInstanceId.delete(t), s.forEach((n) => {
this.batchedMesh.deleteInstance(n);
});
}
}
addSceneToBatchedMesh(e, t) {
if (this._tileToInstanceId.has(t))
return;
const s = [];
e.traverse((r) => {
r.isMesh && s.push(r);
});
let n = !0;
s.forEach((r) => {
if (this.batchedMesh && n) {
const o = r.geometry.attributes, l = this.batchedMesh.geometry.attributes;
for (const c in l)
if (!(c in o)) {
n = !1;
return;
}
}
});
const i = !this.batchedMesh || this.batchedMesh.instanceCount + s.length <= this.maxInstanceCount;
if (n && i) {
e.updateMatrixWorld();
const r = [];
this._tileToInstanceId.set(t, r), s.forEach((o) => {
this.initBatchedMesh(o), this.initTextureArray(o);
const { geometry: l, material: c } = o, { batchedMesh: u, expandPercent: h } = this;
u.expandPercent = h;
const d = u.addGeometry(l, this.vertexCount, this.indexCount), m = u.addInstance(d);
r.push(m), u.setMatrixAt(m, o.matrixWorld), u.setVisibleAt(m, !1), dr(c.color) || (c.color.setHSL(Math.random(), 0.5, 0.5), u.setColorAt(m, c.color));
const f = c.map;
f ? this.assignTextureToLayer(f, m) : this.assignTextureToLayer(kt, m);
}), this.discardOriginalContent && (t.cached.textures.forEach((o) => {
o.image instanceof ImageBitmap && o.image.close();
}), t.cached.scene = null, t.cached.materials = [], t.cached.geometries = [], t.cached.textures = []);
}
}
// Override raycasting per tile to defer to the batched mesh
raycastTile(e, t, s, n) {
return this._tileToInstanceId.has(e) ? (this._tileToInstanceId.get(e).forEach((r) => {
this.batchedMesh.raycastInstance(r, s, n);
}), !0) : !1;
}
dispose() {
const { arrayTarget: e, tiles: t, batchedMesh: s } = this;
e && e.dispose(), s && (s.material.dispose(), s.geometry.dispose(), s.dispose(), s.removeFromParent()), t.removeEventListener("dispose-model", this._onDisposeModel);
}
getTileBatchIds(e) {
return this._tileToInstanceId.get(e);
}
}
const Ct = /* @__PURE__ */ new he(), Xe = /* @__PURE__ */ new E(), we = /* @__PURE__ */ new K(), Ns = /* @__PURE__ */ new K(), At = /* @__PURE__ */ new ti(), fr = /* @__PURE__ */ new Ue({ side: an }), ks = /* @__PURE__ */ new lt(), vt = 1e5;
function Gs(a, e) {
return a.isBufferGeometry ? (a.boundingSphere === null && a.computeBoundingSphere(), e.copy(a.boundingSphere)) : (ks.setFromObject(a), ks.getBoundingSphere(e), e);
}
class go {
constructor() {
this.name = "TILE_FLATTENING_PLUGIN", this.priority = -100, this.tiles = null, this.shapes = /* @__PURE__ */ new Map(), this.positionsMap = /* @__PURE__ */ new Map(), this.positionsUpdated = /* @__PURE__ */ new Set(), this.needsUpdate = !1;
}
init(e) {
this.tiles = e, this.needsUpdate = !0, this._updateBeforeCallback = () => {
this.needsUpdate && (this._updateTiles(), this.needsUpdate = !1);
}, this._disposeModelCallback = ({ tile: t }) => {
this.positionsMap.delete(t), this.positionsUpdated.delete(t);
}, e.addEventListener("update-before", this._updateBeforeCallback), e.addEventListener("dispose-model", this._disposeModelCallback);
}
// update tile flattening state if it has not been made visible, yet
setTileActive(e, t) {
t && !this.positionsUpdated.has(e) && this._updateTile(e);
}
_updateTile(e) {
const { positionsUpdated: t, positionsMap: s, shapes: n, tiles: i } = this;
t.add(e);
const r = e.cached.scene;
if (s.has(e)) {
const o = s.get(e);
r.traverse((l) => {
if (l.geometry) {
const c = o.get(l.geometry);
c && (l.geometry.attributes.position.array.set(c), l.geometry.attributes.position.needsUpdate = !0);
}
});
} else {
const o = /* @__PURE__ */ new Map();
s.set(e, o), r.traverse((l) => {
l.geometry && o.set(l.geometry, l.geometry.attributes.position.array.slice());
});
}
r.updateMatrixWorld(!0), r.traverse((o) => {
const { geometry: l } = o;
l && (we.copy(o.matrixWorld), r.parent !== null && we.premultiply(i.group.matrixWorldInverse), Ns.copy(we).invert(), Gs(l, Ct).applyMatrix4(we), n.forEach(({
shape: c,
direction: u,
sphere: h,
thresholdMode: d,
threshold: m,
flattenRange: f
}) => {
Xe.subVectors(Ct.center, h.center), Xe.addScaledVector(u, -u.dot(Xe));
const p = (Ct.radius + h.radius) ** 2;
if (Xe.lengthSq() > p)
return;
const { position: g } = l.attributes, { ray: y } = At;
y.direction.copy(u).multiplyScalar(-1);
for (let x = 0, T = g.count; x < T; x++) {
y.origin.fromBufferAttribute(g, x).applyMatrix4(we).addScaledVector(u, vt), At.far = vt;
const _ = At.intersectObject(c)[0];
if (_) {
let S = (vt - _.distance) / m;
const b = S >= 1;
(!b || b && d === "flatten") && (S = Math.min(S, 1), _.point.addScaledVector(y.direction, M.mapLinear(S, 0, 1, -f, 0)), _.point.applyMatrix4(Ns), g.setXYZ(x, ..._.point));
}
}
}));
}), this.tiles.dispatchEvent({ type: "needs-render" });
}
_updateTiles() {
this.positionsUpdated.clear(), this.tiles.activeTiles.forEach((e) => this._updateTile(e));
}
// API for updating and shapes to flatten the vertices
hasShape(e) {
return this.shapes.has(e);
}
addShape(e, t = new E(0, 0, -1), s = {}) {
if (this.hasShape(e))
throw new Error("TileFlatteningPlugin: Shape is already used.");
typeof s == "number" && (console.warn('TileFlatteningPlugin: "addShape" function signature has changed. Please use an options object, instead.'), s = {
threshold: s
}), this.needsUpdate = !0;
const n = e.clone();
n.updateMatrixWorld(!0), n.traverse((r) => {
r.material && (r.material = fr);
});
const i = Gs(n, new he());
this.shapes.set(e, {
shape: n,
direction: t.clone(),
sphere: i,
// "flatten": Flattens the vertices above the shape
// "none": leaves the vertices above the shape as they are
thresholdMode: "none",
// only flatten within this range above the object
threshold: 1 / 0,
// the range to flatten vertices in to. 0 is completely flat
// while 0.1 means a 10cm range.
flattenRange: 0,
...s
});
}
updateShape(e) {
if (!this.hasShape(e))
throw new Error("TileFlatteningPlugin: Shape is not present.");
const { direction: t, threshold: s, thresholdMode: n, flattenRange: i } = this.shapes.get(e);
this.deleteShape(e), this.addShape(e, t, {
threshold: s,
thresholdMode: n,
flattenRange: i
});
}
deleteShape(e) {
return this.needsUpdate = !0, this.shapes.delete(e);
}
clearShapes() {
this.shapes.size !== 0 && (this.needsUpdate = !0, this.shapes.clear());
}
// reset the vertex positions and remove the update callback
dispose() {
this.tiles.removeEventListener("before-update", this._updateBeforeCallback), this.tiles.removeEventListener("dispose-model", this._disposeModelCallback), this.positionsMap.forEach((e) => {
e.forEach((t, s) => {
const { position: n } = s.attributes;
n.array.set(t), n.needsUpdate = !0;
});
});
}
}
const mr = /* @__PURE__ */ new si(), gr = /* @__PURE__ */ new Yt();
class yr {
constructor(e) {
this.renderer = e, this.renderTarget = null, this.range = [0, 0, 1, 1], this.quad = new Oe(new qt(), new xr());
}
// set the target render texture and the range that represents the full span
setRenderTarget(e, t) {
this.renderTarget = e, this.range = [...t];
}
// draw the given texture at the given span with the provided projection
draw(e, t) {
const { range: s, renderer: n, quad: i, renderTarget: r } = this, o = i.material;
o.map = e, o.minRange.x = M.mapLinear(t[0], s[0], s[2], -1, 1), o.minRange.y = M.mapLinear(t[1], s[1], s[3], -1, 1), o.maxRange.x = M.mapLinear(t[2], s[0], s[2], -1, 1), o.maxRange.y = M.mapLinear(t[3], s[1], s[3], -1, 1);
const l = n.getRenderTarget(), c = n.autoClear;
n.autoClear = !1, n.setRenderTarget(r), n.render(i, mr), n.setRenderTarget(l), n.autoClear = c, o.map = null;
}
// clear the set target
clear(e, t = 1) {
const { renderer: s, renderTarget: n } = this, i = s.getRenderTarget(), r = s.getClearColor(gr), o = s.getClearAlpha();
s.setClearColor(e, t), s.setRenderTarget(n), s.clear(), s.setRenderTarget(i), s.setClearColor(r, o);
}
dispose() {
this.quad.material.dispose(), this.quad.geometry.dispose();
}
}
class xr extends rn {
// the [ - 1, 1 ] NDC ranges to draw the texture at
get minRange() {
return this.uniforms.minRange.value;
}
get maxRange() {
return this.uniforms.maxRange.value;
}
// access the map being drawn
get map() {
return this.uniforms.map.value;
}
set map(e) {
this.uniforms.map.value = e;
}
constructor() {
super({
depthWrite: !1,
depthTest: !1,
transparent: !1,
side: an,
premultipliedAlpha: !0,
uniforms: {
map: { value: null },
// the normalized [0, 1] range of the target to draw to
minRange: { value: new q() },
maxRange: { value: new q() }
},
vertexShader: (
/* glsl */
`
uniform vec2 minRange;
uniform vec2 maxRange;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4( mix( minRange, maxRange, uv ), 0, 1 );
}
`
),
fragmentShader: (
/* glsl */
`
uniform sampler2D map;
uniform vec2 minRange;
uniform vec2 maxRange;
varying vec2 vUv;
void main() {
// sample the texture
gl_FragColor = texture( map, vUv );
#include <premultiplied_alpha_fragment>
}
`
)
});
}
}
class Tr extends Fe {
constructor(e = {}) {
const {
subdomains: t = ["t0"],
...s
} = e;
super(s), this.subdomains = t, this.subDomainIndex = 0;
}
getUrl(e, t, s) {
return this.url.replace(/{\s*subdomain\s*}/gi, this._getSubdomain()).replace(/{\s*quadkey\s*}/gi, this._tileToQuadKey(e, t, s));
}
_tileToQuadKey(e, t, s) {
let n = "";
for (let i = s; i > 0; i--) {
let r = 0;
const o = 1 << i - 1;
(e & o) !== 0 && (r += 1), (t & o) !== 0 && (r += 2), n += r.toString();
}
return n;
}
_getSubdomain() {
return this.subDomainIndex = (this.subDomainIndex + 1) % this.subdomains.length, this.subdomains[this.subDomainIndex];
}
}
function it(a, e, t, s) {
let [n, i, r, o] = a;
i += 1e-8, n += 1e-8, o -= 1e-8, r -= 1e-8;
const l = Math.max(Math.min(e, t.maxLevel), t.minLevel), [c, u, h, d] = t.getTilesInRange(n, i, r, o, l, !0);
for (let m = c; m <= h; m++)
for (let f = u; f <= d; f++)
s(m, f, l);
}
function br(a, e, t) {
const s = new E(), n = {}, i = [], r = a.getAttribute("position");
a.computeBoundingBox(), a.boundingBox.getCenter(s).applyMatrix4(e), t.getPositionToCartographic(s, n);
const o = n.lat, l = n.lon;
let c = 1 / 0, u = 1 / 0, h = 1 / 0, d = -1 / 0, m = -1 / 0, f = -1 / 0;
for (let y = 0; y < r.count; y++)
s.fromBufferAttribute(r, y).applyMatrix4(e), t.getPositionToCartographic(s, n), Math.abs(Math.abs(n.lat) - Math.PI / 2) < 1e-5 && (n.lon = l), Math.abs(l - n.lon) > Math.PI && (n.lon += Math.sign(l - n.lon) * Math.PI * 2), Math.abs(o - n.lat) > Math.PI && (n.lat += Math.sign(o - n.lat) * Math.PI * 2), i.push(n.lon, n.lat, n.height), c = Math.min(c, n.lat), d = Math.max(d, n.lat), u = Math.min(u, n.lon), m = Math.max(m, n.lon), h = Math.min(h, n.height), f = Math.max(f, n.height);
const p = [u, c, m, d], g = [...p, h, f];
return {
uv: i,
range: p,
region: g
};
}
function js(a, e, t = null, s = null) {
let n = 1 / 0, i = 1 / 0, r = 1 / 0, o = -1 / 0, l = -1 / 0, c = -1 / 0;
const u = [], h = new K();
a.forEach((m) => {
h.copy(m.matrixWorld), t && h.premultiply(t);
const { uv: f, region: p } = br(m.geometry, h, e);
u.push(f), n = Math.min(n, p[1]), o = Math.max(o, p[3]), i = Math.min(i, p[0]), l = Math.max(l, p[2]), r = Math.min(r, p[4]), c = Math.max(c, p[5]);
});
let d = [i, n, l, o];
if (s !== null) {
d = s.clampToProjectionBounds([i, n, l, o]);
const [m, f, p, g] = s.toNormalizedRange(d);
u.forEach((y) => {
for (let x = 0, T = y.length; x < T; x += 3) {
const _ = y[x + 0], S = y[x + 1], b = y[x + 2], [C, A] = s.toNormalizedPoint(_, S);
y[x + 0] = M.mapLinear(C, m, p, 0, 1), y[x + 1] = M.mapLinear(A, f, g, 0, 1), y[x + 2] = M.mapLinear(b, r, c, 0, 1);
}
});
}
return {
uvs: u,
range: d,
region: [i, n, l, o, r, c]
};
}
function _r(a, e, t) {
const s = new E(), n = [], i = a.getAttribute("position");
let r = 1 / 0, o = 1 / 0, l = 1 / 0, c = -1 / 0, u = -1 / 0, h = -1 / 0;
for (let m = 0; m < i.count; m++)
s.fromBufferAttribute(i, m).applyMatrix4(e), s.x /= t, n.push(s.x, s.y, s.z), r = Math.min(r, s.x), c = Math.max(c, s.x), o = Math.min(o, s.y), u = Math.max(u, s.y), l = Math.min(l, s.z), h = Math.max(h, s.z);
return {
uv: n,
range: [r, o, c, u],
heightRange: [l, h]
};
}
function Mr(a, e, t) {
let s = 1 / 0, n = 1 / 0, i = 1 / 0, r = -1 / 0, o = -1 / 0, l = -1 / 0;
const c = [], u = new K();
return a.forEach((h) => {
u.copy(h.matrixWorld), e && u.premultiply(e);
const { uv: d, range: m, heightRange: f } = _r(h.geometry, u, t.aspectRatio);
c.push(d), s = Math.min(s, m[0]), r = Math.max(r, m[2]), n = Math.min(n, m[1]), o = Math.max(o, m[3]), i = Math.min(i, f[0]), l = Math.max(l, f[1]);
}), c.forEach((h) => {
for (let d = 0, m = h.length; d < m; d += 3) {
const f = h[d + 0], p = h[d + 1];
h[d + 0] = M.mapLinear(f, s, r, 0, 1), h[d + 1] = M.mapLinear(p, n, o, 0, 1);
}
}), {
uvs: c,
range: [s, n, r, o],
heightRange: [i, l]
};
}
const Lt = Symbol("OVERLAY_PARAMS");
function Sr(a, e) {
if (a[Lt])
return a[Lt];
const t = {
layerMaps: { value: [] },
layerInfo: { value: [] }
};
return a[Lt] = t, a.defines = {
...a.defines || {},
LAYER_COUNT: 0
}, a.onBeforeCompile = (s) => {
e && e(s), s.uniforms = {
...s.uniforms,
...t
}, s.vertexShader = s.vertexShader.replace(/void main\(\s*\)\s*{/, (n) => (
/* glsl */
`
#pragma unroll_loop_start
for ( int i = 0; i < 10; i ++ ) {
#if UNROLLED_LOOP_INDEX < LAYER_COUNT
attribute vec3 layer_uv_UNROLLED_LOOP_INDEX;
varying vec3 v_layer_uv_UNROLLED_LOOP_INDEX;
#endif
}
#pragma unroll_loop_end
${n}
#pragma unroll_loop_start
for ( int i = 0; i < 10; i ++ ) {
#if UNROLLED_LOOP_INDEX < LAYER_COUNT
v_layer_uv_UNROLLED_LOOP_INDEX = layer_uv_UNROLLED_LOOP_INDEX;
#endif
}
#pragma unroll_loop_end
`
)), s.fragmentShader = s.fragmentShader.replace(/void main\(/, (n) => (
/* glsl */
`
#if LAYER_COUNT != 0
struct LayerInfo {
vec3 color;
float opacity;
int alphaMask;
int alphaInvert;
};
uniform sampler2D layerMaps[ LAYER_COUNT ];
uniform LayerInfo layerInfo[ LAYER_COUNT ];
#endif
#pragma unroll_loop_start
for ( int i = 0; i < 10; i ++ ) {
#if UNROLLED_LOOP_INDEX < LAYER_COUNT
varying vec3 v_layer_uv_UNROLLED_LOOP_INDEX;
#endif
}
#pragma unroll_loop_end
${n}
`
)).replace(/#include <color_fragment>/, (n) => (
/* glsl */
`
${n}
#if LAYER_COUNT != 0
{
vec4 tint;
vec3 layerUV;
float layerOpacity;
float wOpacity;
float wDelta;
#pragma unroll_loop_start
for ( int i = 0; i < 10; i ++ ) {
#if UNROLLED_LOOP_INDEX < LAYER_COUNT
layerUV = v_layer_uv_UNROLLED_LOOP_INDEX;
tint = texture( layerMaps[ i ], layerUV.xy );
// discard texture outside 0, 1 on w - offset the stepped value by an epsilon to avoid cases
// where wDelta is near 0 (eg a flat surface) at the w boundary, resulting in artifacts on some
// hardware.
wDelta = max( fwidth( layerUV.z ), 1e-7 );
wOpacity =
smoothstep( - wDelta, 0.0, layerUV.z ) *
smoothstep( 1.0 + wDelta, 1.0, layerUV.z );
// apply tint & opacity
tint.rgb *= layerInfo[ i ].color;
tint.rgba *= layerInfo[ i ].opacity * wOpacity;
// invert the alpha
if ( layerInfo[ i ].alphaInvert > 0 ) {
tint.a = 1.0 - tint.a;
}
// apply the alpha across all existing layers if alpha mask is true
if ( layerInfo[ i ].alphaMask > 0 ) {
diffuseColor.a *= tint.a;
} else {
// premultiplied alpha equation
diffuseColor = tint + diffuseColor * ( 1.0 - tint.a );
}
#endif
}
#pragma unroll_loop_end
}
#endif
`
));
}, t;
}
const It = /* @__PURE__ */ new E(), Ye = /* @__PURE__ */ new E();
function Cr(a, e, t) {
a.getCartographicToPosition(e, t, 0, It), a.getCartographicToPosition(e + 0.01, t, 0, Ye);
const n = It.distanceTo(Ye);
return a.getCartographicToPosition(e, t + 0.01, 0, Ye), It.distanceTo(Ye) / n;
}
class Ar extends Ae {
constructor({
geojson: e = null,
url: t = null,
// URL or GeoJson object can be provided
tileDimension: s = 256,
levels: n = 20,
pointRadius: i = 6,
strokeStyle: r = "white",
strokeWidth: o = 2,
fillStyle: l = "rgba( 255, 255, 255, 0.5 )",
...c
} = {}) {
super(c), this.geojson = e, this.url = t, this.tileDimension = s, this.levels = n, this.pointRadius = i, this.strokeStyle = r, this.strokeWidth = o, this.fillStyle = l;
}
async init() {
const { tiling: e, levels: t, tileDimension: s, geojson: n, url: i } = this, r = new de();
if (e.setProjection(r), e.setContentBounds(...r.getBounds()), e.generateLevels(
t,
r.tileCountX,
r.tileCountY,
{
tilePixelWidth: s,
tilePixelHeight: s
}
), !n && i) {
const l = await this.fetchData(i);
this.geojson = await l.json();
}
const o = this._geoJSONBounds(50).map((l) => l * M.DEG2RAD);
this.tiling.setContentBounds(...o);
}
// main fetch per tile - > returns .Texture
async fetchItem(e, t) {
return this.drawCanvasImage(e);
}
drawCanvasImage(e) {
const { tiling: t, tileDimension: s, geojson: n } = this, [i, r, o] = e, l = t.getTileBounds(i, r, o, !1, !1).map((m) => M.RAD2DEG * m), c = document.createElement("canvas");
c.width = s, c.height = s;
const u = c.getContext("2d"), h = this._featuresFromGeoJSON(n);
for (let m = 0; m < h.length; m++) {
const f = h[m];
this._featureIntersectsTile(f, l) && this._drawFeatureOnCanvas(u, f, l, c.width, c.height);
}
const d = new ln(c);
return d.needsUpdate = !0, d;
}
// bbox quick test in projected units
_featureIntersectsTile(e, t) {
const s = this._getFeatureBounds(e);
if (!s)
return !1;
const [n, i, r, o] = s, [l, c, u, h] = t;
return !(r < l || n > u || o < c || i > h);
}
_getFeatureBounds(e) {
const { geometry: t } = e;
if (!t)
return null;
const { type: s, coordinates: n } = t;
let i = 1 / 0, r = 1 / 0, o = -1 / 0, l = -1 / 0;
const c = (u, h) => {
i = Math.min(i, u), o = Math.max(o, u), r = Math.min(r, h), l = Math.max(l, h);
};
return s === "Point" ? c(n[0], n[1]) : s === "MultiPoint" || s === "LineString" ? n.forEach((u) => c(u[0], u[1])) : s === "MultiLineString" || s === "Polygon" ? n.forEach((u) => u.forEach((h) => c(h[0], h[1]))) : s === "MultiPolygon" && n.forEach(
(u) => u.forEach((h) => h.forEach((d) => c(d[0], d[1])))
), [i, r, o, l];
}
// Normalize top-level geojson into an array of Feature objects
_featuresFromGeoJSON(e) {
const t = e.type, s = /* @__PURE__ */ new Set(["Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon"]);
return t === "FeatureCollection" ? e.features : t === "Feature" ? [e] : t === "GeometryCollection" ? e.geometries.map((n) => ({ type: "Feature", geometry: n, properties: {} })) : s.has(t) ? [{ type: "Feature", geometry: e, properties: {} }] : [];
}
// draw feature on canvas ( assumes intersects already )
_drawFeatureOnCanvas(e, t, s, n, i) {
const { geometry: r = null, properties: o = {} } = t;
if (!r)
return;
const [l, c, u, h] = s, d = o.strokeStyle || this.strokeStyle, m = o.fillStyle || this.fillStyle, f = o.pointRadius || this.pointRadius, p = o.strokeWidth || this.strokeWidth;
e.save(), e.strokeStyle = d, e.fillStyle = m, e.lineWidth = p;
const g = new Array(2), y = (_, S, b = g) => {
const C = M.mapLinear(_, l, u, 0, n), A = i - M.mapLinear(S, c, h, 0, i);
return b[0] = Math.round(C), b[1] = Math.round(A), b;
}, x = (_, S) => {
const b = S * M.DEG2RAD, C = _ * M.DEG2RAD, A = (h - c) / i;
return (u - l) / n / A * Cr(ui, b, C);
}, T = r.type;
if (T === "Point") {
const [_, S] = r.coordinates, [b, C] = y(_, S), A = x(_, S);
e.beginPath(), e.ellipse(b, C, f / A, f, 0, 0, Math.PI * 2), e.fill(), e.stroke();
} else T === "MultiPoint" ? r.coordinates.forEach(([_, S]) => {
const [b, C] = y(_, S), A = x(_, S);
e.beginPath(), e.ellipse(b, C, f / A, f, 0, 0, Math.PI * 2), e.fill(), e.stroke();
}) : T === "LineString" ? (e.beginPath(), r.coordinates.forEach(([_, S], b) => {
const [C, A] = y(_, S);
b === 0 ? e.moveTo(C, A) : e.lineTo(C, A);
}), e.stroke()) : T === "MultiLineString" ? (e.beginPath(), r.coordinates.forEach((_) => {
_.forEach(([S, b], C) => {
const [A, w] = y(S, b);
C === 0 ? e.moveTo(A, w) : e.lineTo(A, w);
});
}), e.stroke()) : T === "Polygon" ? (e.beginPath(), r.coordinates.forEach((_, S) => {
_.forEach(([b, C], A) => {
const [w, P] = y(b, C);
A === 0 ? e.moveTo(w, P) : e.lineTo(w, P);
}), e.closePath();
}), e.fill("evenodd"), e.stroke()) : T === "MultiPolygon" && r.coordinates.forEach((_) => {
e.beginPath(), _.forEach((S, b) => {
S.forEach(([C, A], w) => {
const [P, U] = y(C, A);
w === 0 ? e.moveTo(P, U) : e.lineTo(P, U);
}), e.closePath();
}), e.fill("evenodd"), e.stroke();
});
e.restore();
}
// Compute geographic bounds in degrees from current geojson.
_geoJSONBounds() {
const e = this._featuresFromGeoJSON(this.geojson);
let t = 1 / 0, s = 1 / 0, n = -1 / 0, i = -1 / 0;
return e.forEach((r) => {
const [o, l, c, u] = this._getFeatureBounds(r);
t = Math.min(t, o), s = Math.min(s, l), n = Math.max(n, c), i = Math.max(i, u);
}), [t, s, n, i];
}
}
const Se = /* @__PURE__ */ new K(), $e = /* @__PURE__ */ new E(), Et = /* @__PURE__ */ new E(), wt = /* @__PURE__ */ new E(), se = /* @__PURE__ */ new E(), vr = /* @__PURE__ */ new lt(), zs = Symbol("SPLIT_TILE_DATA"), Qe = Symbol("SPLIT_HASH");
function ye(a, e, t, s) {
if (Array.isArray(t)) {
const i = t.map((r) => ye(a, e, r, s)).filter((r) => r !== null);
return i.length === 0 ? null : Promise.all(i);
}
if (t.isReady)
return n();
return t.whenReady().then(n);
function n() {
const i = [], { imageSource: r, tiling: o } = t;
it(a, e, o, (c, u, h) => {
s ? r.release(c, u, h) : i.push(r.lock(c, u, h));
});
const l = i.filter((c) => c instanceof Promise);
return l.length !== 0 ? Promise.all(l) : null;
}
}
function Lr(a, e, t) {
let s = 0;
return it(a, e, t.tiling, (n, i, r) => {
s++;
}), s;
}
class yo {
get enableTileSplitting() {
return this._enableTileSplitting;
}
set enableTileSplitting(e) {
this._enableTileSplitting !== e && (this._enableTileSplitting = e, this._markNeedsUpdate());
}
constructor(e = {}) {
const {
overlays: t = [],
resolution: s = 256,
renderer: n = null,
enableTileSplitting: i = !0
} = e;
this.name = "IMAGE_OVERLAY_PLUGIN", this.priority = -15, this.renderer = n, this.resolution = s, this._enableTileSplitting = i, this.overlays = [], this.needsUpdate = !1, this.tiles = null, this.tileComposer = null, this.tileControllers = /* @__PURE__ */ new Map(), this.overlayInfo = /* @__PURE__ */ new Map(), this.usedTextures = /* @__PURE__ */ new Set(), this.meshParams = /* @__PURE__ */ new WeakMap(), this.pendingTiles = /* @__PURE__ */ new Map(), this.processedTiles = /* @__PURE__ */ new Set(), this.processQueue = null, this._onUpdateAfter = null, this._onTileDownloadStart = null, this._cleanupScheduled = !1, this._virtualChildResetId = 0, this._bytesUsed = /* @__PURE__ */ new WeakMap(), t.forEach((r) => {
this.addOverlay(r);
});
}
// plugin functions
init(e) {
if (!this.renderer)
throw new Error('ImageOverlayPlugin: "renderer" instance must be provided.');
const t = new yr(this.renderer), s = new gi();
s.maxJobs = 10, s.priorityCallback = (n, i) => {
const r = n.tile, o = i.tile, l = e.visibleTiles.has(r), c = e.visibleTiles.has(o);
return l !== c ? l ? 1 : -1 : e.downloadQueue.priorityCallback(r, o);
}, this.tiles = e, this.tileComposer = t, this.processQueue = s, e.forEachLoadedModel((n, i) => {
this._processTileModel(n, i, !0);
}), this._onUpdateAfter = async () => {
let n = !1;
if (this.overlayInfo.forEach((i, r) => {
if (!!r.frame != !!i.frame || r.frame && i.frame && !i.frame.equals(r.frame)) {
const o = i.order;
this.deleteOverlay(r), this.addOverlay(r, o), n = !0;
}
}), n) {
const i = s.maxJobs;
let r = 0;
s.items.forEach((o) => {
e.visibleTiles.has(o.tile) && r++;
}), s.maxJobs = r + s.currJobs, s.tryRunJobs(), s.maxJobs = i, this.needsUpdate = !0;
}
if (this.needsUpdate) {
this.needsUpdate = !1;
const { overlays: i, overlayInfo: r } = this;
i.sort((o, l) => r.get(o).order - r.get(l).order), e.forEachLoadedModel((o, l) => {
this._updateLayers(l);
}), this.resetVirtualChildren(!this.enableTileSplitting), e.recalculateBytesUsed(), e.dispatchEvent({ type: "needs-rerender" });
}
}, this._onTileDownloadStart = ({ tile: n, url: i }) => {
!/\.json$/i.test(i) && !/\.subtree/i.test(i) && (this.processedTiles.add(n), this._initTileOverlayInfo(n));
}, e.addEventListener("update-after", this._onUpdateAfter), e.addEventListener("tile-download-start", this._onTileDownloadStart), this.overlays.forEach((n) => {
this._initOverlay(n);
});
}
disposeTile(e) {
const { overlayInfo: t, tileControllers: s, processQueue: n, pendingTiles: i, processedTiles: r } = this;
r.delete(e), s.has(e) && (s.get(e).abort(), s.delete(e), i.delete(e)), t.forEach((({ tileInfo: o }, l) => {
if (o.has(e)) {
const { meshInfo: c, range: u, meshRange: h, level: d, target: m, meshRangeMarked: f, rangeMarked: p } = o.get(e);
h !== null && f && ye(h, d, l, !0), u !== null && p && ye(u, d, l, !0), m !== null && m.dispose(), o.delete(e), c.clear();
}
})), n.removeByFilter((o) => o.tile === e);
}
calculateBytesUsed(e) {
const { overlayInfo: t } = this, s = this._bytesUsed;
let n = null;
return t.forEach(({ tileInfo: i }, r) => {
if (i.has(e)) {
const { target: o } = i.get(e);
n = n || 0, n += hi(o == null ? void 0 : o.texture);
}
}), n !== null ? (s.set(e, n), n) : s.has(e) ? s.get(e) : 0;
}
processTileModel(e, t) {
return this._processTileModel(e, t);
}
async _processTileModel(e, t, s = !1) {
const { tileControllers: n, processedTiles: i, pendingTiles: r } = this;
n.set(t, new AbortController()), s || r.set(t, e), i.add(t), this._wrapMaterials(e), this._initTileOverlayInfo(t), await this._initTileSceneOverlayInfo(e, t), this.expandVirtualChildren(e, t), this._updateLayers(t), r.delete(t);
}
dispose() {
const { tileComposer: e, tiles: t } = this;
e.dispose(), [...this.overlays].forEach((n) => {
this.deleteOverlay(n);
}), t.forEachLoadedModel((n, i) => {
this._updateLayers(i), this.disposeTile(i), delete i[Qe];
}), t.removeEventListener("update-after", this._onUpdateAfter), this.resetVirtualChildren(!0);
}
getAttributions(e) {
this.overlays.forEach((t) => {
t.opacity > 0 && t.getAttributions(e);
});
}
parseToMesh(e, t, s, n) {
if (s === "image_overlay_tile_split")
return t[zs];
}
async resetVirtualChildren(e = !1) {
this._virtualChildResetId++;
const t = this._virtualChildResetId;
if (await Promise.all(this.overlays.map((r) => r.whenReady())), t !== this._virtualChildResetId)
return;
const { tiles: s } = this, n = /* @__PURE__ */ new Set();
s.forEachLoadedModel((r, o) => {
Qe in o && n.add(o);
}), n.forEach((r) => {
if (r.parent === null)
return;
const o = r.cached.scene.clone();
o.updateMatrixWorld();
const { hash: l } = this._getSplitVectors(o, r);
if (r[Qe] !== l || e) {
const c = i(r);
c.sort((u, h) => (h.__depth || 0) - (u.__depth || 0)), c.forEach((u) => {
s.processNodeQueue.remove(u), s.lruCache.remove(u), u.parent = null;
}), r.children.length = 0, r.__childrenProcessed = 0;
}
}), e || s.forEachLoadedModel((r, o) => {
this.expandVirtualChildren(r, o);
});
function i(r, o = []) {
return r.children.forEach((l) => {
o.push(l), i(l, o);
}), o;
}
}
_getSplitVectors(e, t, s = Et) {
const { tiles: n, overlayInfo: i } = this, r = new lt();
r.setFromObject(e), r.getCenter(s);
const o = [], l = [];
i.forEach(({ tileInfo: u }, h) => {
const d = u.get(t);
if (d && d.target && h.tiling.maxLevel > d.level) {
h.frame ? se.set(0, 0, 1).transformDirection(h.frame) : (n.ellipsoid.getPositionToNormal(s, se), se.length() < 1e-6 && se.set(1, 0, 0));
const m = `${se.x.toFixed(3)},${se.y.toFixed(3)},${se.z.toFixed(3)}_`;
l.includes(m) || l.push(m);
const f = $e.set(0, 0, 1);
Math.abs(se.dot(f)) > 1 - 1e-4 && f.set(1, 0, 0);
const p = new E().crossVectors(se, f).normalize(), g = new E().crossVectors(se, p).normalize();
o.push(p, g);
}
});
const c = [];
for (; o.length !== 0; ) {
const u = o.pop().clone(), h = u.clone();
for (let d = 0; d < o.length; d++) {
const m = o[d], f = u.dot(m);
Math.abs(f) > Math.cos(Math.PI / 8) && (h.addScaledVector(m, Math.sign(f)), u.copy(h).normalize(), o.splice(d, 1), d--);
}
c.push(h.normalize());
}
return { directions: c, hash: l.join("") };
}
async expandVirtualChildren(e, t) {
if (t.children.length !== 0 || this.enableTileSplitting === !1)
return;
const s = e.clone();
s.updateMatrixWorld();
const { directions: n, hash: i } = this._getSplitVectors(s, t, Et);
if (t[Qe] = i, n.length === 0)
return;
const r = new xn();
r.attributeList = (l) => !/^layer_uv_\d+/.test(l), n.map((l) => {
r.addSplitOperation((c, u, h, d, m, f) => (Xt.getInterpolatedAttribute(c.attributes.position, u, h, d, m, $e), $e.applyMatrix4(f).sub(Et).dot(l)));
});
const o = [];
r.forEachSplitPermutation(() => {
const l = r.clipObject(s);
l.matrix.premultiply(t.cached.transformInverse).decompose(l.position, l.quaternion, l.scale);
const c = [];
if (l.traverse((h) => {
if (h.isMesh) {
const d = h.material.clone();
h.material = d;
for (const m in d) {
const f = d[m];
if (f && f.isTexture && f.source.data instanceof ImageBitmap) {
const p = document.createElement("canvas");
p.width = f.image.width, p.height = f.image.height;
const g = p.getContext("2d");
g.scale(1, -1), g.drawImage(f.source.data, 0, 0, p.width, -p.height);
const y = new ln(p);
y.mapping = f.mapping, y.wrapS = f.wrapS, y.wrapT = f.wrapT, y.minFilter = f.minFilter, y.magFilter = f.magFilter, y.format = f.format, y.type = f.type, y.anisotropy = f.anisotropy, y.colorSpace = f.colorSpace, y.generateMipmaps = f.generateMipmaps, d[m] = y;
}
}
c.push(h);
}
}), c.length === 0)
return;
const u = {};
if (t.boundingVolume.region && (u.region = js(c, this.tiles.ellipsoid).region), t.boundingVolume.box || t.boundingVolume.sphere) {
vr.setFromObject(l, !0).getCenter(wt);
let h = 0;
l.traverse((d) => {
const m = d.geometry;
if (m) {
const f = m.attributes.position;
for (let p = 0, g = f.count; p < g; p++) {
const y = $e.fromBufferAttribute(f, p).applyMatrix4(d.matrixWorld).distanceToSquared(wt);
h = Math.max(h, y);
}
}
}), u.sphere = [...wt, Math.sqrt(h)];
}
o.push({
refine: "REPLACE",
geometricError: t.geometricError * 0.5,
boundingVolume: u,
content: { uri: "./child.image_overlay_tile_split" },
children: [],
[zs]: l
});
}), t.refine = "REPLACE", t.children.push(...o);
}
fetchData(e, t) {
if (/image_overlay_tile_split/.test(e))
return new ArrayBuffer();
}
// public
addOverlay(e, t = null) {
const { tiles: s, overlays: n, overlayInfo: i } = this;
t === null && (t = n.reduce((o, l) => Math.max(o, l.order + 1), 0));
const r = new AbortController();
n.push(e), i.set(e, {
order: t,
uniforms: {},
tileInfo: /* @__PURE__ */ new Map(),
controller: r,
frame: e.frame ? e.frame.clone() : null
}), s !== null && this._initOverlay(e);
}
setOverlayOrder(e, t) {
this.overlays.indexOf(e) !== -1 && (this.overlayInfo.get(e).order = t, this._markNeedsUpdate());
}
deleteOverlay(e) {
const { overlays: t, overlayInfo: s, processQueue: n, processedTiles: i } = this, r = t.indexOf(e);
if (r !== -1) {
const { tileInfo: o, controller: l } = s.get(e);
i.forEach((c) => {
if (!o.has(c))
return;
const {
meshInfo: u,
range: h,
meshRange: d,
level: m,
target: f,
meshRangeMarked: p,
rangeMarked: g
} = o.get(c);
d !== null && p && ye(d, m, e, !0), h !== null && g && ye(h, m, e, !0), f !== null && f.dispose(), o.delete(c), u.clear();
}), o.clear(), s.delete(e), l.abort(), n.removeByFilter((c) => c.overlay === e), t.splice(r, 1), this._markNeedsUpdate();
}
}
// internal
_calculateLevelFromOverlay(e, t, s) {
if (e.isPlanarProjection) {
const { resolution: n } = this, { tiling: i } = e, [r, o, l, c] = t, u = l - r, h = c - o;
let d = 0;
const { maxLevel: m } = i;
for (; d < m; d++) {
const f = n / u, p = n / h, { pixelWidth: g, pixelHeight: y } = i.getLevel(d);
if (g >= f || y >= p)
break;
}
return d;
} else
return s.__depthFromRenderedParent - 1;
}
// initialize the overlay to use the right fetch options, load all data for existing tiles
_initOverlay(e) {
const { tiles: t } = this;
e.isInitialized || (e.init(), e.whenReady().then(() => {
e.imageSource.fetchData = (...i) => t.downloadQueue.add({ priority: -performance.now() }, () => e.fetch(...i));
}));
const s = [], n = async (i, r) => {
this._initTileOverlayInfo(r, e);
const o = this._initTileSceneOverlayInfo(i, r, e);
s.push(o), await o, this._updateLayers(r);
};
t.forEachLoadedModel(n), this.pendingTiles.forEach((i, r) => {
n(i, r);
}), Promise.all(s).then(() => {
this._markNeedsUpdate();
});
}
// wrap all materials in the given scene wit the overlay material shader
_wrapMaterials(e) {
e.traverse((t) => {
if (t.material) {
const s = Sr(t.material, t.material.onBeforeCompile);
this.meshParams.set(t, s);
}
});
}
// Initialize per-tile overlay information. This function triggers an async function but
// does not need to be awaited for use since it's just locking textures which are awaited later.
_initTileOverlayInfo(e, t = this.overlays) {
if (Array.isArray(t)) {
t.forEach((r) => this._initTileOverlayInfo(e, r));
return;
}
const { overlayInfo: s, processQueue: n } = this;
if (s.get(t).tileInfo.has(e))
return;
const i = {
range: null,
meshRange: null,
level: null,
target: null,
meshInfo: /* @__PURE__ */ new Map(),
rangeMarked: !1,
meshRangeMarked: !1
};
if (s.get(t).tileInfo.set(e, i), t.isReady && !t.isPlanarProjection) {
if (e.boundingVolume.region) {
const [r, o, l, c] = e.boundingVolume.region, u = t.tiling.toNormalizedRange([r, o, l, c]);
i.range = u, i.level = this._calculateLevelFromOverlay(t, u, e), n.add({ tile: e, overlay: t }, () => (i.rangeMarked = !0, ye(u, i.level, t, !1))).catch((h) => {
if (!(h instanceof ns))
throw h;
});
}
}
}
// initialize the scene meshes
async _initTileSceneOverlayInfo(e, t, s = this.overlays) {
if (Array.isArray(s))
return Promise.all(s.map((C) => this._initTileSceneOverlayInfo(e, t, C)));
const { tiles: n, overlayInfo: i, resolution: r, tileComposer: o, tileControllers: l, usedTextures: c, processQueue: u } = this, { ellipsoid: h } = n, { controller: d, tileInfo: m } = i.get(s), f = l.get(t);
if (s.isReady || await s.whenReady(), d.signal.aborted || f.signal.aborted)
return;
const p = [];
e.updateMatrixWorld(), e.traverse((C) => {
C.isMesh && p.push(C);
});
const { tiling: g, imageSource: y } = s, x = m.get(t);
let T, _, S;
if (s.isPlanarProjection) {
Se.copy(s.frame), e.parent !== null && Se.multiply(n.group.matrixWorldInverse);
let C;
({ range: T, uvs: _, heightRange: C } = Mr(p, Se, g)), S = !(C[0] > 1 || C[1] < 0);
} else
Se.identity(), e.parent !== null && Se.copy(n.group.matrixWorldInverse), { range: T, uvs: _ } = js(p, h, Se, g), T = g.toNormalizedRange(T), S = !0;
x.level === null && (x.level = this._calculateLevelFromOverlay(s, T, t));
let b = null;
S && Lr(T, x.level, s) !== 0 && (b = new Ft(r, r, {
depthBuffer: !1,
stencilBuffer: !1,
generateMipmaps: !1,
colorSpace: Ks
})), x.meshRange = T, x.target = b, p.forEach((C, A) => {
const w = new Float32Array(_[A]), P = new J(w, 3);
x.meshInfo.set(C, { attribute: P });
}), b !== null && await u.add({ tile: t, overlay: s }, async () => {
x.meshRangeMarked = !0;
const C = ye(T, x.level, s, !1);
if (C) {
o.setRenderTarget(b, T), o.clear(16777215, 0), it(T, x.level - 1, g, (A, w, P) => {
const U = g.getTileBounds(A, w, P, !0, !1), B = y.get(A, w, P);
B && !(B instanceof Promise) && (o.draw(B, U), c.add(B), this._scheduleCleanup());
});
try {
await C;
} catch {
return;
}
}
d.signal.aborted || f.signal.aborted || (o.setRenderTarget(b, T), o.clear(16777215, 0), it(T, x.level, g, (A, w, P) => {
const U = g.getTileBounds(A, w, P, !0, !1), B = y.get(A, w, P);
o.draw(B, U), c.add(B), this._scheduleCleanup();
}));
}).catch((C) => {
if (!(C instanceof ns))
throw C;
});
}
_updateLayers(e) {
const { overlayInfo: t, overlays: s, tileControllers: n } = this, i = n.get(e);
this.tiles.recalculateBytesUsed(e), !(!i || i.signal.aborted) && s.forEach((r, o) => {
const { tileInfo: l } = t.get(r), { meshInfo: c, target: u } = l.get(e);
c.forEach(({ attribute: h }, d) => {
const { geometry: m, material: f } = d, p = this.meshParams.get(d), g = `layer_uv_${o}`;
m.getAttribute(g) !== h && (m.setAttribute(g, h), m.dispose()), p.layerMaps.length = s.length, p.layerInfo.length = s.length, p.layerMaps.value[o] = u !== null ? u.texture : null, p.layerInfo.value[o] = r, f.defines[`LAYER_${o}_EXISTS`] = +(u !== null), f.defines[`LAYER_${o}_ALPHA_INVERT`] = Number(r.alphaInvert), f.defines[`LAYER_${o}_ALPHA_MASK`] = Number(r.alphaMask), f.defines.LAYER_COUNT = s.length, f.needsUpdate = !0;
});
});
}
_scheduleCleanup() {
this._cleanupScheduled || (this._cleanupScheduled = !0, requestAnimationFrame(() => {
const { usedTextures: e } = this;
e.forEach((t) => {
t.dispose();
}), e.clear(), this._cleanupScheduled = !1;
}));
}
_markNeedsUpdate() {
this.needsUpdate === !1 && (this.needsUpdate = !0, this.tiles !== null && this.tiles.dispatchEvent({ type: "needs-update" }));
}
}
class be {
get tiling() {
return this.imageSource.tiling;
}
get projection() {
return this.tiling.projection;
}
get isPlanarProjection() {
return !!this.frame;
}
get aspectRatio() {
return this.tiling && this.isReady ? this.tiling.aspectRatio : 1;
}
get fetchOptions() {
return this.imageSource.fetchOptions;
}
set fetchOptions(e) {
this.imageSource.fetchOptions = e;
}
constructor(e = {}) {
const {
opacity: t = 1,
color: s = 16777215,
frame: n = null,
preprocessURL: i = null,
alphaMask: r = !1,
alphaInvert: o = !1
} = e;
this.imageSource = null, this.preprocessURL = i, this.opacity = t, this.color = new Yt(s), this.frame = n !== null ? n.clone() : null, this.alphaMask = r, this.alphaInvert = o, this.isReady = !1, this.isInitialized = !1;
}
init() {
this.isInitialized = !0, this.whenReady().then(() => {
this.isReady = !0;
});
}
fetch(e, t = {}) {
return this.preprocessURL && (e = this.preprocessURL(e)), fetch(e, t);
}
whenReady() {
}
getAttributions(e) {
}
dispose() {
this.imageSource.dispose();
}
}
class xo extends be {
constructor(e = {}) {
super(e), this.imageSource = new Fe(e), this.imageSource.fetchData = (...t) => this.fetch(...t);
}
init() {
this._whenReady = this.imageSource.init(), super.init();
}
whenReady() {
return this._whenReady;
}
}
class To extends be {
constructor(e = {}) {
super(e), this.imageSource = new Ar(e), this.imageSource.fetchData = (...t) => this.fetch(...t);
}
init() {
this._whenReady = this.imageSource.init(), super.init();
}
whenReady() {
return this._whenReady;
}
}
class bo extends be {
constructor(e = {}) {
super(e), this.imageSource = new yn(e), this.imageSource.fetchData = (...t) => this.fetch(...t);
}
init() {
this._whenReady = this.imageSource.init(), super.init();
}
whenReady() {
return this._whenReady;
}
}
class _o extends be {
constructor(e = {}) {
super(e), this.imageSource = new gn(e), this.imageSource.fetchData = (...t) => this.fetch(...t);
}
init() {
this._whenReady = this.imageSource.init(), super.init();
}
whenReady() {
return this._whenReady;
}
}
class Mo extends be {
constructor(e = {}) {
super(e), this.imageSource = new $t(e), this.imageSource.fetchData = (...t) => this.fetch(...t), this.url = e.url;
}
init() {
this._whenReady = this.imageSource.init(), super.init();
}
whenReady() {
return this._whenReady;
}
}
class So extends be {
constructor(e = {}) {
super(e);
const { apiToken: t, autoRefreshToken: s, assetId: n } = e;
this.options = e, this.assetId = n, this.auth = new Fn({ apiToken: t, autoRefreshToken: s }), this.auth.authURL = `https://api.cesium.com/v1/assets/${n}/endpoint`, this._attributions = [], this.externalType = !1;
}
init() {
this._whenReady = this.auth.refreshToken().then(async (e) => {
if (this._attributions = e.attributions.map((t) => ({
value: t.html,
type: "html",
collapsible: t.collapsible
})), e.type !== "IMAGERY")
throw new Error("CesiumIonOverlay: Only IMAGERY is supported as overlay type.");
switch (this.externalType = !!e.externalType, e.externalType) {
case "GOOGLE_2D_MAPS": {
const { url: t, session: s, key: n, tileWidth: i } = e.options, r = `${t}/v1/2dtiles/{z}/{x}/{y}?session=${s}&key=${n}`;
this.imageSource = new Fe({
...this.options,
url: r,
tileDimension: i,
// Google maps tiles have a fixed depth of 22
// https://developers.google.com/maps/documentation/tile/2d-tiles-overview
levels: 22
});
break;
}
case "BING": {
const { url: t, mapStyle: s, key: n } = e.options, i = `${t}/REST/v1/Imagery/Metadata/${s}?incl=ImageryProviders&key=${n}&uriScheme=https`, o = (await fetch(i).then((l) => l.json())).resourceSets[0].resources[0];
this.imageSource = new Tr({
...this.options,
url: o.imageUrl,
subdomains: o.imageUrlSubdomains,
tileDimension: o.tileWidth,
levels: o.zoomMax
});
break;
}
default:
this.imageSource = new $t({
...this.options,
url: e.url
});
}
return this.imageSource.fetchData = (...t) => this.fetch(...t), this.imageSource.init();
}), super.init();
}
fetch(...e) {
return this.externalType ? super.fetch(...e) : this.auth.fetch(...e);
}
whenReady() {
return this._whenReady;
}
getAttributions(e) {
e.push(...this._attributions);
}
}
class Co extends be {
constructor(e = {}) {
super(e);
const { apiToken: t, sessionOptions: s, autoRefreshToken: n, logoUrl: i } = e;
this.logoUrl = i, this.auth = new Nn({ apiToken: t, sessionOptions: s, autoRefreshToken: n }), this.imageSource = new Fe(), this.imageSource.fetchData = (...r) => this.fetch(...r), this._logoAttribution = {
value: "",
type: "image",
collapsible: !1
};
}
init() {
this._whenReady = this.auth.refreshToken().then((e) => (this.imageSource.tileDimension = e.tileWidth, this.imageSource.url = "https://tile.googleapis.com/v1/2dtiles/{z}/{x}/{y}", this.imageSource.init())), super.init();
}
fetch(...e) {
return this.auth.fetch(...e);
}
whenReady() {
return this._whenReady;
}
getAttributions(e) {
this.logoUrl && (this._logoAttribution.value = this.logoUrl, e.push(this._logoAttribution));
}
}
class Ao {
constructor() {
this.name = "LOAD_REGION_PLUGIN", this.regions = [], this.tiles = null;
}
init(e) {
this.tiles = e;
}
addRegion(e) {
this.regions.indexOf(e) === -1 && this.regions.push(e);
}
removeRegion(e) {
const t = this.regions.indexOf(e);
t !== -1 && this.regions.splice(t, 1);
}
hasRegion(e) {
return this.regions.indexOf(e) !== -1;
}
clearRegions() {
this.regions = [];
}
// Calculates shape intersections and associated error values to use. If "mask" shapes are present then
// tiles are only loaded if they are within those shapes.
calculateTileViewError(e, t) {
const s = e.cached.boundingVolume, { regions: n, tiles: i } = this;
let r = !1, o = null, l = -1 / 0;
for (const c of n) {
const u = c.intersectsTile(s, e, i);
r = r || u, l = Math.max(c.calculateError(e, i), l), c.mask && (o = o || u);
}
return t.inView = r && o !== !1, t.error = l, t.inView || o !== null;
}
dispose() {
this.regions = [];
}
}
class Jt {
constructor(e = {}) {
typeof e == "number" && (console.warn("LoadRegionPlugin: Region constructor has been changed to take options as an object."), e = { errorTarget: e });
const {
errorTarget: t = 10,
mask: s = !1
} = e;
this.errorTarget = t, this.mask = s;
}
intersectsTile() {
}
calculateError(e, t) {
return e.geometricError - this.errorTarget + t.errorTarget;
}
}
class vo extends Jt {
constructor(e = {}) {
typeof e == "number" && (console.warn("SphereRegion: Region constructor has been changed to take options as an object."), e = {
errorTarget: arguments[0],
sphere: arguments[1]
});
const { sphere: t = new he() } = e;
super(e), this.sphere = t.clone();
}
intersectsTile(e) {
return e.intersectsSphere(this.sphere);
}
}
class Lo extends Jt {
constructor(e = {}) {
typeof e == "number" && (console.warn("RayRegion: Region constructor has been changed to take options as an object."), e = {
errorTarget: arguments[0],
ray: arguments[1]
});
const { ray: t = new ni() } = e;
super(e), this.ray = t.clone();
}
intersectsTile(e) {
return e.intersectsRay(this.ray);
}
}
class Io extends Jt {
constructor(e = {}) {
typeof e == "number" && (console.warn("RayRegion: Region constructor has been changed to take options as an object."), e = {
errorTarget: arguments[0],
obb: arguments[1]
});
const { obb: t = new di() } = e;
super(e), this.obb = t.clone(), this.obb.update();
}
intersectsTile(e) {
return e.intersectsOBB(this.obb);
}
}
const te = /* @__PURE__ */ new E(), Hs = ["x", "y", "z"];
class Ir extends cn {
constructor(e, t = 16776960, s = 40) {
const n = new et(), i = [];
for (let r = 0; r < 3; r++) {
const o = Hs[r], l = Hs[(r + 1) % 3];
te.set(0, 0, 0);
for (let c = 0; c < s; c++) {
let u;
u = 2 * Math.PI * c / (s - 1), te[o] = Math.sin(u), te[l] = Math.cos(u), i.push(te.x, te.y, te.z), u = 2 * Math.PI * (c + 1) / (s - 1), te[o] = Math.sin(u), te[l] = Math.cos(u), i.push(te.x, te.y, te.z);
}
}
n.setAttribute("position", new J(new Float32Array(i), 3)), n.computeBoundingSphere(), super(n, new ii({ color: t, toneMapped: !1 })), this.sphere = e, this.type = "SphereHelper";
}
updateMatrixWorld(e) {
const t = this.sphere;
this.position.copy(t.center), this.scale.setScalar(t.radius), super.updateMatrixWorld(e);
}
}
const Pt = /* @__PURE__ */ new E(), Ze = /* @__PURE__ */ new E(), ne = /* @__PURE__ */ new E();
function Er(a, { computeNormals: e = !1 } = {}) {
const {
latStart: t = -Math.PI / 2,
latEnd: s = Math.PI / 2,
lonStart: n = 0,
lonEnd: i = 2 * Math.PI,
heightStart: r = 0,
heightEnd: o = 0
} = a, l = new oi(1, 1, 1, 32, 32), { normal: c, position: u } = l.attributes, h = u.clone();
for (let d = 0, m = u.count; d < m; d++) {
ne.fromBufferAttribute(u, d);
const f = M.mapLinear(ne.x, -0.5, 0.5, t, s), p = M.mapLinear(ne.y, -0.5, 0.5, n, i);
let g = r;
a.getCartographicToNormal(f, p, Pt), ne.z < 0 && (g = o), a.getCartographicToPosition(f, p, g, ne), u.setXYZ(d, ...ne);
}
e && l.computeVertexNormals();
for (let d = 0, m = h.count; d < m; d++) {
ne.fromBufferAttribute(h, d);
const f = M.mapLinear(ne.x, -0.5, 0.5, t, s), p = M.mapLinear(ne.y, -0.5, 0.5, n, i);
Pt.fromBufferAttribute(c, d), a.getCartographicToNormal(f, p, Ze), Math.abs(Pt.dot(Ze)) > 0.1 && (ne.z > 0 && Ze.multiplyScalar(-1), c.setXYZ(d, ...Ze));
}
return l;
}
class wr extends cn {
constructor(e = new pi(), t = 16776960) {
super(), this.ellipsoidRegion = e, this.material.color.set(t), this.update();
}
update() {
const e = Er(this.ellipsoidRegion);
this.geometry.dispose(), this.geometry = new ri(e, 80);
}
dispose() {
this.geometry.dispose(), this.material.dispose();
}
}
const qs = Symbol("ORIGINAL_MATERIAL"), Rt = Symbol("HAS_RANDOM_COLOR"), Bt = Symbol("HAS_RANDOM_NODE_COLOR"), Dt = Symbol("LOAD_TIME"), ge = Symbol("PARENT_BOUND_REF_COUNT"), Ws = /* @__PURE__ */ new he(), Ot = () => {
}, Ut = {};
function Vt(a) {
if (!Ut[a]) {
const e = Math.random(), t = 0.5 + Math.random() * 0.5, s = 0.375 + Math.random() * 0.25;
Ut[a] = new Yt().setHSL(e, t, s);
}
return Ut[a];
}
const Be = 0, vn = 1, Ln = 2, In = 3, En = 4, wn = 5, Pn = 6, Je = 7, Ke = 8, Rn = 9, Gt = 10, Pr = Object.freeze({
NONE: Be,
SCREEN_ERROR: vn,
GEOMETRIC_ERROR: Ln,
DISTANCE: In,
DEPTH: En,
RELATIVE_DEPTH: wn,
IS_LEAF: Pn,
RANDOM_COLOR: Je,
RANDOM_NODE_COLOR: Ke,
CUSTOM_COLOR: Rn,
LOAD_ORDER: Gt
});
class Eo {
static get ColorModes() {
return Pr;
}
get unlit() {
return this._unlit;
}
set unlit(e) {
e !== this._unlit && (this._unlit = e, this.materialsNeedUpdate = !0);
}
get colorMode() {
return this._colorMode;
}
set colorMode(e) {
e !== this._colorMode && (this._colorMode = e, this.materialsNeedUpdate = !0);
}
get enabled() {
return this._enabled;
}
set enabled(e) {
e !== this._enabled && this.tiles !== null && (e ? this.init(this.tiles) : this.dispose()), this._enabled = e;
}
get displayParentBounds() {
return this._displayParentBounds;
}
set displayParentBounds(e) {
this._displayParentBounds !== e && (this._displayParentBounds = e, e ? this.tiles.traverse((t) => {
t.__visible && this._onTileVisibilityChange(t, !0);
}) : this.tiles.traverse((t) => {
t[ge] = null, this._onTileVisibilityChange(t, t.__visible);
}));
}
constructor(e) {
e = {
displayParentBounds: !1,
displayBoxBounds: !1,
displaySphereBounds: !1,
displayRegionBounds: !1,
colorMode: Be,
maxDebugDepth: -1,
maxDebugDistance: -1,
maxDebugError: -1,
customColorCallback: null,
unlit: !1,
enabled: !0,
...e
}, this.name = "DEBUG_TILES_PLUGIN", this.tiles = null, this._colorMode = null, this._unlit = null, this.materialsNeedUpdate = !1, this.extremeDebugDepth = -1, this.extremeDebugError = -1, this.boxGroup = null, this.sphereGroup = null, this.regionGroup = null, this._enabled = e.enabled, this._displayParentBounds = e.displayParentBounds, this.displayBoxBounds = e.displayBoxBounds, this.displaySphereBounds = e.displaySphereBounds, this.displayRegionBounds = e.displayRegionBounds, this.colorMode = e.colorMode, this.maxDebugDepth = e.maxDebugDepth, this.maxDebugDistance = e.maxDebugDistance, this.maxDebugError = e.maxDebugError, this.customColorCallback = e.customColorCallback, this.unlit = e.unlit, this.getDebugColor = (t, s) => {
s.setRGB(t, t, t);
};
}
// initialize the groups for displaying helpers, register events, and initialize existing tiles
init(e) {
this.tiles = e;
const t = e.group;
this.boxGroup = new Ge(), this.boxGroup.name = "DebugTilesRenderer.boxGroup", t.add(this.boxGroup), this.boxGroup.updateMatrixWorld(), this.sphereGroup = new Ge(), this.sphereGroup.name = "DebugTilesRenderer.sphereGroup", t.add(this.sphereGroup), this.sphereGroup.updateMatrixWorld(), this.regionGroup = new Ge(), this.regionGroup.name = "DebugTilesRenderer.regionGroup", t.add(this.regionGroup), this.regionGroup.updateMatrixWorld(), this._onLoadTilesetCB = () => {
this._initExtremes();
}, this._onLoadModelCB = ({ scene: s, tile: n }) => {
this._onLoadModel(s, n);
}, this._onDisposeModelCB = ({ tile: s }) => {
this._onDisposeModel(s);
}, this._onUpdateAfterCB = () => {
this._onUpdateAfter();
}, this._onTileVisibilityChangeCB = ({ scene: s, tile: n, visible: i }) => {
this._onTileVisibilityChange(n, i);
}, e.addEventListener("load-tileset", this._onLoadTilesetCB), e.addEventListener("load-model", this._onLoadModelCB), e.addEventListener("dispose-model", this._onDisposeModelCB), e.addEventListener("update-after", this._onUpdateAfterCB), e.addEventListener("tile-visibility-change", this._onTileVisibilityChangeCB), this._initExtremes(), e.traverse((s) => {
s.cached.scene && this._onLoadModel(s.cached.scene, s);
}), e.visibleTiles.forEach((s) => {
this._onTileVisibilityChange(s, !0);
});
}
getTileInformationFromActiveObject(e) {
let t = null;
return this.tiles.activeTiles.forEach((n) => {
if (t)
return !0;
const i = n.cached.scene;
i && i.traverse((r) => {
r === e && (t = n);
});
}), t ? {
distanceToCamera: t.__distanceFromCamera,
geometricError: t.geometricError,
screenSpaceError: t.__error,
depth: t.__depth,
isLeaf: t.__isLeaf
} : null;
}
_initExtremes() {
if (!(this.tiles && this.tiles.root))
return;
let e = -1, t = -1;
this.tiles.traverse(null, (s, n, i) => {
e = Math.max(e, i), t = Math.max(t, s.geometricError);
}, !1), this.extremeDebugDepth = e, this.extremeDebugError = t;
}
_onUpdateAfter() {
const { tiles: e, colorMode: t } = this;
if (!e.root)
return;
this.materialsNeedUpdate && (e.forEachLoadedModel((c) => {
this._updateMaterial(c);
}), this.materialsNeedUpdate = !1), this.boxGroup.visible = this.displayBoxBounds, this.sphereGroup.visible = this.displaySphereBounds, this.regionGroup.visible = this.displayRegionBounds;
let s = -1;
this.maxDebugDepth === -1 ? s = this.extremeDebugDepth : s = this.maxDebugDepth;
let n = -1;
this.maxDebugError === -1 ? n = this.extremeDebugError : n = this.maxDebugError;
let i = -1;
this.maxDebugDistance === -1 ? (e.getBoundingSphere(Ws), i = Ws.radius) : i = this.maxDebugDistance;
const { errorTarget: r, visibleTiles: o } = e;
let l;
t === Gt && (l = Array.from(o).sort((c, u) => c[Dt] - u[Dt])), o.forEach((c) => {
const u = c.cached.scene;
let h, d, m;
t === Je && (h = Math.random(), d = 0.5 + Math.random() * 0.5, m = 0.375 + Math.random() * 0.25), u.traverse((f) => {
if (t === Ke && (h = Math.random(), d = 0.5 + Math.random() * 0.5, m = 0.375 + Math.random() * 0.25), f.material)
switch (t !== Je && delete f.material[Rt], t !== Ke && delete f.material[Bt], t) {
case En: {
const p = c.__depth / s;
this.getDebugColor(p, f.material.color);
break;
}
case wn: {
const p = c.__depthFromRenderedParent / s;
this.getDebugColor(p, f.material.color);
break;
}
case vn: {
const p = c.__error / r;
p > 1 ? f.material.color.setRGB(1, 0, 0) : this.getDebugColor(p, f.material.color);
break;
}
case Ln: {
const p = Math.min(c.geometricError / n, 1);
this.getDebugColor(p, f.material.color);
break;
}
case In: {
const p = Math.min(c.__distanceFromCamera / i, 1);
this.getDebugColor(p, f.material.color);
break;
}
case Pn: {
!c.children || c.children.length === 0 ? this.getDebugColor(1, f.material.color) : this.getDebugColor(0, f.material.color);
break;
}
case Ke: {
f.material[Bt] || (f.material.color.setHSL(h, d, m), f.material[Bt] = !0);
break;
}
case Je: {
f.material[Rt] || (f.material.color.setHSL(h, d, m), f.material[Rt] = !0);
break;
}
case Rn: {
this.customColorCallback ? this.customColorCallback(c, f) : console.warn("DebugTilesRenderer: customColorCallback not defined");
break;
}
case Gt: {
const p = l.indexOf(c);
this.getDebugColor(p / (l.length - 1), f.material.color);
break;
}
}
});
});
}
_onTileVisibilityChange(e, t) {
this.displayParentBounds ? yi(e, (s) => {
s[ge] == null && (s[ge] = 0), t ? s[ge]++ : s[ge] > 0 && s[ge]--;
const n = s === e && t || this.displayParentBounds && s[ge] > 0;
this._updateBoundHelper(s, n);
}) : this._updateBoundHelper(e, t);
}
_createBoundHelper(e) {
const t = this.tiles, s = e.cached, { sphere: n, obb: i, region: r } = s.boundingVolume;
if (i) {
const o = new Ge();
o.name = "DebugTilesRenderer.boxHelperGroup", o.matrix.copy(i.transform), o.matrixAutoUpdate = !1;
const l = new ai(i.box, Vt(e.__depth));
l.raycast = Ot, o.add(l), s.boxHelperGroup = o, t.visibleTiles.has(e) && this.displayBoxBounds && (this.boxGroup.add(o), o.updateMatrixWorld(!0));
}
if (n) {
const o = new Ir(n, Vt(e.__depth));
o.raycast = Ot, s.sphereHelper = o, t.visibleTiles.has(e) && this.displaySphereBounds && (this.sphereGroup.add(o), o.updateMatrixWorld(!0));
}
if (r) {
const o = new wr(r, Vt(e.__depth));
o.raycast = Ot;
const l = new he();
r.getBoundingSphere(l), o.position.copy(l.center), l.center.multiplyScalar(-1), o.geometry.translate(...l.center), s.regionHelper = o, t.visibleTiles.has(e) && this.displayRegionBounds && (this.regionGroup.add(o), o.updateMatrixWorld(!0));
}
}
_updateHelperMaterial(e, t) {
e.__visible || !this.displayParentBounds ? t.opacity = 1 : t.opacity = 0.2;
const s = t.transparent;
t.transparent = t.opacity < 1, t.transparent !== s && (t.needsUpdate = !0);
}
_updateBoundHelper(e, t) {
const s = e.cached;
if (!s)
return;
const n = this.sphereGroup, i = this.boxGroup, r = this.regionGroup;
t && s.boxHelperGroup == null && s.sphereHelper == null && s.regionHelper == null && this._createBoundHelper(e);
const o = s.boxHelperGroup, l = s.sphereHelper, c = s.regionHelper;
t ? (o && (i.add(o), o.updateMatrixWorld(!0), this._updateHelperMaterial(e, o.children[0].material)), l && (n.add(l), l.updateMatrixWorld(!0), this._updateHelperMaterial(e, l.material)), c && (r.add(c), c.updateMatrixWorld(!0), this._updateHelperMaterial(e, c.material))) : (o && i.remove(o), l && n.remove(l), c && r.remove(c));
}
_updateMaterial(e) {
const { colorMode: t, unlit: s } = this;
e.traverse((n) => {
if (!n.material)
return;
const i = n.material, r = n[qs];
if (i !== r && i.dispose(), t !== Be || s) {
if (n.isPoints) {
const o = new li();
o.size = r.size, o.sizeAttenuation = r.sizeAttenuation, n.material = o;
} else s ? n.material = new Ue() : (n.material = new en(), n.material.flatShading = !0);
t === Be && (n.material.map = r.map, n.material.color.set(r.color));
} else
n.material = r;
});
}
_onLoadModel(e, t) {
t[Dt] = performance.now(), e.traverse((s) => {
const n = s.material;
n && (s[qs] = n);
}), this._updateMaterial(e);
}
_onDisposeModel(e) {
const t = e.cached;
t.boxHelperGroup && (t.boxHelperGroup.children[0].geometry.dispose(), delete t.boxHelperGroup), t.sphereHelper && (t.sphereHelper.geometry.dispose(), delete t.sphereHelper), t.regionHelper && (t.regionHelper.geometry.dispose(), delete t.regionHelper);
}
dispose() {
var t, s, n;
const e = this.tiles;
e.removeEventListener("load-tileset", this._onLoadTilesetCB), e.removeEventListener("load-model", this._onLoadModelCB), e.removeEventListener("dispose-model", this._onDisposeModelCB), e.removeEventListener("update-after", this._onUpdateAfterCB), e.removeEventListener("tile-visibility-change", this._onTileVisibilityChangeCB), this.colorMode = Be, this.unlit = !1, e.forEachLoadedModel((i) => {
this._updateMaterial(i);
}), e.traverse((i) => {
this._onDisposeModel(i);
}), (t = this.boxGroup) == null || t.removeFromParent(), (s = this.sphereGroup) == null || s.removeFromParent(), (n = this.regionGroup) == null || n.removeFromParent();
}
}
class Rr extends Ae {
constructor(e = {}) {
const { url: t = null, ...s } = e;
super(s), this.url = t, this.format = null, this.stem = null;
}
getUrl(e, t, s) {
return `${this.stem}_files/${s}/${e}_${t}.${this.format}`;
}
init() {
const { url: e } = this;
return this.fetchData(e, this.fetchOptions).then((t) => t.text()).then((t) => {
const s = new DOMParser().parseFromString(t, "text/xml");
if (s.querySelector("DisplayRects") || s.querySelector("Collection"))
throw new Error("DeepZoomImagesPlugin: DisplayRect and Collection DZI files not supported.");
const n = s.querySelector("Image"), i = n.querySelector("Size"), r = parseInt(i.getAttribute("Width")), o = parseInt(i.getAttribute("Height")), l = parseInt(n.getAttribute("TileSize")), c = parseInt(n.getAttribute("Overlap")), u = n.getAttribute("Format");
this.format = u, this.stem = e.split(/\.[^.]+$/g)[0];
const { tiling: h } = this, d = Math.ceil(Math.log2(Math.max(r, o))) + 1;
h.flipY = !0, h.pixelOverlap = c, h.generateLevels(d, 1, 1, {
tilePixelWidth: l,
tilePixelHeight: l,
pixelWidth: r,
pixelHeight: o
});
});
}
}
class wo extends fn {
constructor(e = {}) {
const { url: t, ...s } = e;
super(s), this.name = "DZI_TILES_PLUGIN", this.imageSource = new Rr({ url: t });
}
}
const rt = dn * Math.PI * 2, Xs = /* @__PURE__ */ new de("EPSG:3857");
function Br(a) {
return /:4326$/i.test(a);
}
function Bn(a) {
return /:3857$/i.test(a);
}
function jt(a) {
return a.trim().split(/\s+/).map((e) => parseFloat(e));
}
function zt(a, e) {
Br(e) && ([a[1], a[0]] = [a[0], a[1]]);
}
function ot(a, e) {
if (Bn(e))
return a[0] = Xs.convertProjectionToLongitude(0.5 + a[0] / rt), a[1] = Xs.convertProjectionToLatitude(0.5 + a[1] / rt), a[0] *= M.RAD2DEG, a[1] *= M.RAD2DEG, a;
}
function at(a) {
a[0] *= M.DEG2RAD, a[1] *= M.DEG2RAD;
}
class Po extends pn {
parse(e) {
const t = new TextDecoder("utf-8").decode(new Uint8Array(e)), s = new DOMParser().parseFromString(t, "text/xml"), n = s.querySelector("Contents"), i = ce(n, "TileMatrixSet").map((l) => Nr(l)), r = ce(n, "Layer").map((l) => Or(l)), o = Dr(s.querySelector("ServiceIdentification"));
return r.forEach((l) => {
l.tileMatrixSets = l.tileMatrixSetLinks.map((c) => i.find((u) => u.identifier === c));
}), {
serviceIdentification: o,
tileMatrixSets: i,
layers: r
};
}
}
function Dr(a) {
var i;
const e = a.querySelector("Title").textContent, t = ((i = a.querySelector("Abstract")) == null ? void 0 : i.textContent) || "", s = a.querySelector("ServiceType").textContent, n = a.querySelector("ServiceTypeVersion").textContent;
return {
title: e,
abstract: t,
serviceType: s,
serviceTypeVersion: n
};
}
function Or(a) {
const e = a.querySelector("Title").textContent, t = a.querySelector("Identifier").textContent, s = a.querySelector("Format").textContent, n = ce(a, "ResourceURL").map((c) => Ur(c)), i = ce(a, "TileMatrixSetLink").map((c) => ce(c, "TileMatrixSet")[0].textContent), r = ce(a, "Style").map((c) => Fr(c)), o = ce(a, "Dimension").map((c) => Vr(c));
let l = Ys(a.querySelector("WGS84BoundingBox"));
return l || (l = Ys(a.querySelector("BoundingBox"))), {
title: e,
identifier: t,
format: s,
dimensions: o,
tileMatrixSetLinks: i,
styles: r,
boundingBox: l,
resourceUrls: n
};
}
function Ur(a) {
const e = a.getAttribute("template"), t = a.getAttribute("format"), s = a.getAttribute("resourceType");
return {
template: e,
format: t,
resourceType: s
};
}
function Vr(a) {
var r, o;
const e = a.querySelector("Identifier").textContent, t = ((r = a.querySelector("UOM")) == null ? void 0 : r.textContent) || "", s = a.querySelector("Default").textContent, n = ((o = a.querySelector("Current")) == null ? void 0 : o.textContent) === "true", i = ce(a, "Value").map((l) => l.textContent);
return {
identifier: e,
uom: t,
defaultValue: s,
current: n,
values: i
};
}
function Ys(a) {
if (!a)
return null;
const e = a.nodeName.endsWith("WGS84BoundingBox") ? "urn:ogc:def:crs:CRS::84" : a.getAttribute("crs"), t = jt(a.querySelector("LowerCorner").textContent), s = jt(a.querySelector("UpperCorner").textContent);
return zt(t, e), zt(s, e), ot(t, e), ot(s, e), at(t), at(s), {
crs: e,
lowerCorner: t,
upperCorner: s,
bounds: [...t, ...s]
};
}
function Fr(a) {
var n;
const e = ((n = a.querySelector("Title")) == null ? void 0 : n.textContent) || null, t = a.querySelector("Identifier").textContent, s = a.getAttribute("isDefault") === "true";
return {
title: e,
identifier: t,
isDefault: s
};
}
function Nr(a) {
var r, o;
const e = a.querySelector("SupportedCRS").textContent, t = ((r = a.querySelector("Title")) == null ? void 0 : r.textContent) || "", s = a.querySelector("Identifier").textContent, n = ((o = a.querySelector("Abstract")) == null ? void 0 : o.textContent) || "", i = [];
return a.querySelectorAll("TileMatrix").forEach((l, c) => {
const u = kr(l), h = 28e-5 * u.scaleDenominator, d = u.tileWidth * u.matrixWidth * h, m = u.tileHeight * u.matrixHeight * h;
let f;
zt(u.topLeftCorner, e), Bn(e) ? f = [
u.topLeftCorner[0] + d,
u.topLeftCorner[1] - m
] : f = [
u.topLeftCorner[0] + 360 * d / rt,
u.topLeftCorner[1] - 360 * m / rt
], ot(f, e), ot(u.topLeftCorner, e), at(f), at(u.topLeftCorner), u.bounds = [...u.topLeftCorner, ...f], [u.bounds[1], u.bounds[3]] = [u.bounds[3], u.bounds[1]], i.push(u);
}), {
title: t,
identifier: s,
abstract: n,
supportedCRS: e,
tileMatrices: i
};
}
function kr(a) {
const e = a.querySelector("Identifier").textContent, t = parseFloat(a.querySelector("TileWidth").textContent), s = parseFloat(a.querySelector("TileHeight").textContent), n = parseFloat(a.querySelector("MatrixWidth").textContent), i = parseFloat(a.querySelector("MatrixHeight").textContent), r = parseFloat(a.querySelector("ScaleDenominator").textContent), o = jt(a.querySelector("TopLeftCorner").textContent);
return {
identifier: e,
tileWidth: t,
tileHeight: s,
matrixWidth: n,
matrixHeight: i,
scaleDenominator: r,
topLeftCorner: o,
bounds: null
};
}
function ce(a, e) {
return [...a.children].filter((t) => t.tagName === e);
}
const $s = dn * Math.PI * 2, Qs = /* @__PURE__ */ new de("EPSG:3857");
function Gr(a) {
return /:4326$/i.test(a);
}
function jr(a) {
return /:3857$/i.test(a);
}
function Zs(a, e) {
return jr(e) && (a[0] = Qs.convertProjectionToLongitude(0.5 + a[0] / (Math.PI * 2 * $s)), a[1] = Qs.convertProjectionToLatitude(0.5 + a[1] / (Math.PI * 2 * $s)), a[0] *= M.RAD2DEG, a[1] *= M.RAD2DEG), a;
}
function Js(a, e, t) {
const [s, n] = t.split(".").map((r) => parseInt(r)), i = s === 1 && n < 3 || s < 1;
Gr(e) && i && ([a[0], a[1]] = [a[1], a[0]]);
}
function Ce(a) {
a[0] *= M.DEG2RAD, a[1] *= M.DEG2RAD;
}
function zr(a, e) {
if (!a)
return null;
const t = a.getAttribute("CRS") || a.getAttribute("crs") || a.getAttribute("SRS") || "", s = parseFloat(a.getAttribute("minx")), n = parseFloat(a.getAttribute("miny")), i = parseFloat(a.getAttribute("maxx")), r = parseFloat(a.getAttribute("maxy")), o = [s, n], l = [i, r];
return Js(o, t, e), Js(l, t, e), Zs(o, t), Zs(l, t), Ce(o), Ce(l), { crs: t, bounds: [...o, ...l] };
}
function Hr(a) {
const e = parseFloat(a.querySelector("westBoundLongitude").textContent), t = parseFloat(a.querySelector("eastBoundLongitude").textContent), s = parseFloat(a.querySelector("southBoundLatitude").textContent), n = parseFloat(a.querySelector("northBoundLatitude").textContent), i = [e, s], r = [t, n];
return Ce(i), Ce(r), [...i, ...r];
}
function qr(a) {
const e = parseFloat(a.getAttribute("minx").textContent), t = parseFloat(a.getAttribute("maxx").textContent), s = parseFloat(a.getAttribute("miny").textContent), n = parseFloat(a.getAttribute("maxy").textContent), i = [e, s], r = [t, n];
return Ce(i), Ce(r), [...i, ...r];
}
function Wr(a) {
const e = a.querySelector("Name").textContent, t = a.querySelector("Title").textContent, s = [...a.querySelectorAll("LegendURL")].map((n) => {
const i = parseInt(n.getAttribute("width")), r = parseInt(n.getAttribute("height")), o = n.querySelector("Format").textContent, l = n.querySelector("OnlineResource"), c = Ht(l);
return {
width: i,
height: r,
format: o,
url: c
};
});
return {
name: e,
title: t,
legends: s
};
}
function Dn(a, e, t = {}) {
var p, g, y;
let {
styles: s = [],
crs: n = [],
contentBoundingBox: i = null,
queryable: r = !1,
opaque: o = !1
} = t;
const l = ((p = a.querySelector(":scope > Name")) == null ? void 0 : p.textContent) || null, c = ((g = a.querySelector(":scope > Title")) == null ? void 0 : g.textContent) || "", u = ((y = a.querySelector(":scope > Abstract")) == null ? void 0 : y.textContent) || "", h = [...a.querySelectorAll(":scope > Keyword")].map((x) => x.textContent), m = [...a.querySelectorAll(":scope > BoundingBox")].map((x) => zr(x, e));
n = [
...n,
...Array.from(a.querySelectorAll("CRS")).map((x) => x.textContent)
], s = [
...s,
...Array.from(a.querySelectorAll(":scope > Style")).map((x) => Wr(x))
], a.hasAttribute("queryable") && (r = a.getAttribute("queryable") === "1"), a.hasAttribute("opaque") && (o = a.getAttribute("opaque") === "1"), a.querySelector("EX_GeographicBoundingBox") ? i = Hr(a.querySelector("EX_GeographicBoundingBox")) : a.querySelector("LatLonBoundingBox") && (i = qr(a.querySelector("LatLonBoundingBox")));
const f = Array.from(a.querySelectorAll(":scope > Layer")).map((x) => Dn(x, e, {
// add
styles: s,
crs: n,
// replace
contentBoundingBox: i,
queryable: r,
opaque: o
}));
return {
name: l,
title: c,
abstract: u,
queryable: r,
opaque: o,
keywords: h,
crs: n,
boundingBoxes: m,
contentBoundingBox: i,
styles: s,
subLayers: f
};
}
function Xr(a) {
var e, t, s;
return {
name: ((e = a.querySelector("Name")) == null ? void 0 : e.textContent) || "",
title: ((t = a.querySelector("Title")) == null ? void 0 : t.textContent) || "",
abstract: ((s = a.querySelector("Abstract")) == null ? void 0 : s.textContent) || "",
keywords: Array.from(a.querySelectorAll("Keyword")).map((n) => n.textContent),
maxWidth: parseFloat(a.querySelector("MaxWidth")) || null,
maxHeight: parseFloat(a.querySelector("MaxHeight")) || null,
layerLimit: parseFloat(a.querySelector("LayerLimit")) || null
};
}
function Ht(a) {
return a ? (a.getAttribute("xlink:href") || a.getAttributeNS("http://www.w3.org/1999/xlink", "href") || "").trim() : "";
}
function Yr(a) {
const e = Array.from(a.querySelectorAll("Format")).map((s) => s.textContent.trim()), t = Array.from(a.querySelectorAll("DCPType")).map((s) => {
const n = s.querySelector("HTTP"), i = n.querySelector("Get OnlineResource") || n.querySelector("Get > OnlineResource") || n.querySelector("Get"), r = n.querySelector("Post OnlineResource") || n.querySelector("Post > OnlineResource") || n.querySelector("Post"), o = Ht(i), l = Ht(r);
return { type: "HTTP", get: o, post: l };
});
return { formats: e, dcp: t, href: t[0].get };
}
function $r(a) {
const e = {};
return Array.from(a.querySelectorAll(":scope > *")).forEach((t) => {
const s = t.localName;
e[s] = Yr(t);
}), e;
}
function On(a, e = []) {
return a.forEach((t) => {
t.name !== null && e.push(t), On(t.subLayers, e);
}), e;
}
class Ro extends pn {
parse(e) {
const t = new TextDecoder("utf-8").decode(new Uint8Array(e)), s = new DOMParser().parseFromString(t, "text/xml"), i = (s.querySelector("WMS_Capabilities") || s.querySelector("WMT_MS_Capabilities")).getAttribute("version"), r = s.querySelector("Capability"), o = Xr(s.querySelector(":scope > Service")), l = $r(r.querySelector(":scope > Request")), c = Array.from(r.querySelectorAll(":scope > Layer")).map((h) => Dn(h, i)), u = On(c);
return { version: i, service: o, layers: u, request: l };
}
}
export {
mo as B,
oo as C,
Eo as D,
uo as G,
yo as I,
Ao as L,
Io as O,
Di as Q,
ho as R,
vo as S,
co as T,
lo as U,
bo as W,
xo as X,
po as a,
fo as b,
go as c,
To as d,
_o as e,
Mo as f,
So as g,
Co as h,
Jt as i,
Lo as j,
wo as k,
no as l,
Si as m,
io as n,
ro as o,
tr as p,
Zi as q,
er as r,
Po as s,
Ro as t
};
//# sourceMappingURL=WMSCapabilitiesLoader-DgQmEDMc.js.map