3d-tiles-renderer
Version:
https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/specification
1,686 lines • 78.4 kB
JavaScript
import { B3DMLoaderBase as Ve, PNTSLoaderBase as Le, I3DMLoaderBase as We, CMPTLoaderBase as Ne, TilesRendererBase as ke } from "./index.core.js";
import { g as Be, r as He } from "./LoaderBase-CfTLVHyZ.js";
import { DefaultLoadingManager as At, Matrix4 as O, Vector3 as y, Vector2 as F, MathUtils as v, PointsMaterial as je, BufferGeometry as Ge, BufferAttribute as st, Color as Ze, Points as qe, InstancedMesh as Qe, Quaternion as it, Group as Pt, Ray as Ft, Sphere as $e, Frustum as Ye, Matrix3 as Xe, LoadingManager as Ke, EventDispatcher as mt, Euler as Je, Mesh as ti, PlaneGeometry as ei, ShaderMaterial as ii, Plane as ve, Raycaster as si, Clock as Te, PerspectiveCamera as Kt, OrthographicCamera as we } from "three";
import { GLTFLoader as Xt } from "three/examples/jsm/loaders/GLTFLoader.js";
import { W as vt, c as Jt, b as oi, e as ni, a as ri } from "./MemoryUtils-R1TfIs9h.js";
class De extends Ve {
constructor(t = At) {
super(), this.manager = t, this.adjustmentTransform = new O();
}
parse(t) {
const e = super.parse(t), i = e.glbBytes.slice().buffer;
return new Promise((s, o) => {
const r = this.manager, n = this.fetchOptions, a = r.getHandler("path.gltf") || new Xt(r);
n.credentials === "include" && n.mode === "cors" && a.setCrossOrigin("use-credentials"), "credentials" in n && a.setWithCredentials(n.credentials === "include"), n.headers && a.setRequestHeader(n.headers);
let l = this.workingPath;
!/[\\/]$/.test(l) && l.length && (l += "/");
const h = this.adjustmentTransform;
a.parse(i, l, (c) => {
const { batchTable: p, featureTable: m } = e, { scene: u } = c, d = m.getData("RTC_CENTER", 1, "FLOAT", "VEC3");
d && (u.position.x += d[0], u.position.y += d[1], u.position.z += d[2]), c.scene.updateMatrix(), c.scene.matrix.multiply(h), c.scene.matrix.decompose(c.scene.position, c.scene.quaternion, c.scene.scale), c.batchTable = p, c.featureTable = m, u.batchTable = p, u.featureTable = m, s(c);
}, o);
});
}
}
function ai(f) {
const t = f >> 11, e = f >> 5 & 63, i = f & 31, s = Math.round(t / 31 * 255), o = Math.round(e / 63 * 255), r = Math.round(i / 31 * 255);
return [s, o, r];
}
const gt = /* @__PURE__ */ new F();
function ci(f, t, e = new y()) {
gt.set(f, t).divideScalar(256).multiplyScalar(2).subScalar(1), e.set(gt.x, gt.y, 1 - Math.abs(gt.x) - Math.abs(gt.y));
const i = v.clamp(-e.z, 0, 1);
return e.x >= 0 ? e.setX(e.x - i) : e.setX(e.x + i), e.y >= 0 ? e.setY(e.y - i) : e.setY(e.y + i), e.normalize(), e;
}
const te = {
RGB: "color",
POSITION: "position"
};
class Ce extends Le {
constructor(t = At) {
super(), this.manager = t;
}
parse(t) {
return super.parse(t).then(async (e) => {
const { featureTable: i, batchTable: s } = e, o = new je(), r = i.header.extensions, n = new y();
let a;
if (r && r["3DTILES_draco_point_compression"]) {
const { byteOffset: c, byteLength: p, properties: m } = r["3DTILES_draco_point_compression"], u = this.manager.getHandler("draco.drc");
if (u == null)
throw new Error("PNTSLoader: dracoLoader not available.");
const d = {};
for (const _ in m)
if (_ in te && _ in m) {
const U = te[_];
d[U] = m[_];
}
const x = {
attributeIDs: d,
attributeTypes: {
position: "Float32Array",
color: "Uint8Array"
},
useUniqueIDs: !0
}, E = i.getBuffer(c, p);
a = await u.decodeGeometry(E, x), a.attributes.color && (o.vertexColors = !0);
} else {
const c = i.getData("POINTS_LENGTH"), p = i.getData("POSITION", c, "FLOAT", "VEC3"), m = i.getData("NORMAL", c, "FLOAT", "VEC3"), u = i.getData("NORMAL", c, "UNSIGNED_BYTE", "VEC2"), d = i.getData("RGB", c, "UNSIGNED_BYTE", "VEC3"), x = i.getData("RGBA", c, "UNSIGNED_BYTE", "VEC4"), E = i.getData("RGB565", c, "UNSIGNED_SHORT", "SCALAR"), _ = i.getData("CONSTANT_RGBA", c, "UNSIGNED_BYTE", "VEC4"), U = i.getData("POSITION_QUANTIZED", c, "UNSIGNED_SHORT", "VEC3"), g = i.getData("QUANTIZED_VOLUME_SCALE", c, "FLOAT", "VEC3"), C = i.getData("QUANTIZED_VOLUME_OFFSET", c, "FLOAT", "VEC3");
if (a = new Ge(), U) {
const S = new Float32Array(c * 3);
for (let T = 0; T < c; T++)
for (let V = 0; V < 3; V++) {
const z = 3 * T + V;
S[z] = U[z] / 65535 * g[V];
}
n.x = C[0], n.y = C[1], n.z = C[2], a.setAttribute("position", new st(S, 3, !1));
} else
a.setAttribute("position", new st(p, 3, !1));
if (m !== null)
a.setAttribute("normal", new st(m, 3, !1));
else if (u !== null) {
const S = new Float32Array(c * 3), T = new y();
for (let V = 0; V < c; V++) {
const z = u[V * 2], J = u[V * 2 + 1], at = ci(z, J, T);
S[V * 3] = at.x, S[V * 3 + 1] = at.y, S[V * 3 + 2] = at.z;
}
a.setAttribute("normal", new st(S, 3, !1));
}
if (x !== null)
a.setAttribute("color", new st(x, 4, !0)), o.vertexColors = !0, o.transparent = !0, o.depthWrite = !1;
else if (d !== null)
a.setAttribute("color", new st(d, 3, !0)), o.vertexColors = !0;
else if (E !== null) {
const S = new Uint8Array(c * 3);
for (let T = 0; T < c; T++) {
const V = ai(E[T]);
for (let z = 0; z < 3; z++) {
const J = 3 * T + z;
S[J] = V[z];
}
}
a.setAttribute("color", new st(S, 3, !0)), o.vertexColors = !0;
} else if (_ !== null) {
const S = new Ze(_[0], _[1], _[2]);
o.color = S;
const T = _[3] / 255;
T < 1 && (o.opacity = T, o.transparent = !0, o.depthWrite = !1);
}
}
const l = new qe(a, o);
l.position.copy(n), e.scene = l, e.scene.featureTable = i, e.scene.batchTable = s;
const h = i.getData("RTC_CENTER", 1, "FLOAT", "VEC3");
return h && (e.scene.position.x += h[0], e.scene.position.y += h[1], e.scene.position.z += h[2]), e;
});
}
}
const ee = /* @__PURE__ */ new y(), Vt = /* @__PURE__ */ new y(), Lt = /* @__PURE__ */ new y(), Wt = /* @__PURE__ */ new y(), Nt = /* @__PURE__ */ new it(), Tt = /* @__PURE__ */ new y(), wt = /* @__PURE__ */ new O(), ie = /* @__PURE__ */ new O(), se = /* @__PURE__ */ new y(), oe = /* @__PURE__ */ new O(), kt = /* @__PURE__ */ new it(), Bt = {};
class Se extends We {
constructor(t = At) {
super(), this.manager = t, this.adjustmentTransform = new O(), this.ellipsoid = vt.clone();
}
resolveExternalURL(t) {
return this.manager.resolveURL(super.resolveExternalURL(t));
}
parse(t) {
return super.parse(t).then((e) => {
const { featureTable: i, batchTable: s } = e, o = e.glbBytes.slice().buffer;
return new Promise((r, n) => {
const a = this.fetchOptions, l = this.manager, h = l.getHandler("path.gltf") || new Xt(l);
a.credentials === "include" && a.mode === "cors" && h.setCrossOrigin("use-credentials"), "credentials" in a && h.setWithCredentials(a.credentials === "include"), a.headers && h.setRequestHeader(a.headers);
let c = e.gltfWorkingPath ?? this.workingPath;
/[\\/]$/.test(c) || (c += "/");
const p = this.adjustmentTransform;
h.parse(o, c, (m) => {
const u = i.getData("INSTANCES_LENGTH");
let d = i.getData("POSITION", u, "FLOAT", "VEC3");
const x = i.getData("POSITION_QUANTIZED", u, "UNSIGNED_SHORT", "VEC3"), E = i.getData("QUANTIZED_VOLUME_OFFSET", 1, "FLOAT", "VEC3"), _ = i.getData("QUANTIZED_VOLUME_SCALE", 1, "FLOAT", "VEC3"), U = i.getData("NORMAL_UP", u, "FLOAT", "VEC3"), g = i.getData("NORMAL_RIGHT", u, "FLOAT", "VEC3"), C = i.getData("SCALE_NON_UNIFORM", u, "FLOAT", "VEC3"), S = i.getData("SCALE", u, "FLOAT", "SCALAR"), T = i.getData("RTC_CENTER", 1, "FLOAT", "VEC3"), V = i.getData("EAST_NORTH_UP");
if ([
"NORMAL_UP_OCT32P",
"NORMAL_RIGHT_OCT32P"
].forEach((b) => {
b in i.header && console.warn(`I3DMLoader: Unsupported FeatureTable feature "${b}" detected.`);
}), !d && x) {
d = new Float32Array(u * 3);
for (let b = 0; b < u; b++)
d[b * 3 + 0] = E[0] + x[b * 3 + 0] / 65535 * _[0], d[b * 3 + 1] = E[1] + x[b * 3 + 1] / 65535 * _[1], d[b * 3 + 2] = E[2] + x[b * 3 + 2] / 65535 * _[2];
}
const z = new y();
for (let b = 0; b < u; b++)
z.x += d[b * 3 + 0] / u, z.y += d[b * 3 + 1] / u, z.z += d[b * 3 + 2] / u;
const J = [], at = [];
m.scene.updateMatrixWorld(), m.scene.traverse((b) => {
if (b.isMesh) {
at.push(b);
const { geometry: ct, material: Ut } = b, Z = new Qe(ct, Ut, u);
Z.position.copy(z), T && (Z.position.x += T[0], Z.position.y += T[1], Z.position.z += T[2]), J.push(Z);
}
});
for (let b = 0; b < u; b++) {
Wt.set(
d[b * 3 + 0] - z.x,
d[b * 3 + 1] - z.y,
d[b * 3 + 2] - z.z
), Nt.identity(), U && (Vt.set(
U[b * 3 + 0],
U[b * 3 + 1],
U[b * 3 + 2]
), Lt.set(
g[b * 3 + 0],
g[b * 3 + 1],
g[b * 3 + 2]
), ee.crossVectors(Lt, Vt).normalize(), wt.makeBasis(
Lt,
Vt,
ee
), Nt.setFromRotationMatrix(wt)), Tt.set(1, 1, 1), C && Tt.set(
C[b * 3 + 0],
C[b * 3 + 1],
C[b * 3 + 2]
), S && Tt.multiplyScalar(S[b]);
for (let ct = 0, Ut = J.length; ct < Ut; ct++) {
const Z = J[ct];
kt.copy(Nt), V && (Z.updateMatrixWorld(), se.copy(Wt).applyMatrix4(Z.matrixWorld), this.ellipsoid.getPositionToCartographic(se, Bt), this.ellipsoid.getEastNorthUpFrame(Bt.lat, Bt.lon, oe), kt.setFromRotationMatrix(oe)), wt.compose(Wt, kt, Tt).multiply(p);
const Ue = at[ct];
ie.multiplyMatrices(wt, Ue.matrixWorld), Z.setMatrixAt(b, ie);
}
}
m.scene.clear(), m.scene.add(...J), m.batchTable = s, m.featureTable = i, m.scene.batchTable = s, m.scene.featureTable = i, r(m);
}, n);
});
});
}
}
class li extends Ne {
constructor(t = At) {
super(), this.manager = t, this.adjustmentTransform = new O(), this.ellipsoid = vt.clone();
}
parse(t) {
const e = super.parse(t), { manager: i, ellipsoid: s, adjustmentTransform: o } = this, r = [];
for (const n in e.tiles) {
const { type: a, buffer: l } = e.tiles[n];
switch (a) {
case "b3dm": {
const h = l.slice(), c = new De(i);
c.workingPath = this.workingPath, c.fetchOptions = this.fetchOptions, c.adjustmentTransform.copy(o);
const p = c.parse(h.buffer);
r.push(p);
break;
}
case "pnts": {
const h = l.slice(), c = new Ce(i);
c.workingPath = this.workingPath, c.fetchOptions = this.fetchOptions;
const p = c.parse(h.buffer);
r.push(p);
break;
}
case "i3dm": {
const h = l.slice(), c = new Se(i);
c.workingPath = this.workingPath, c.fetchOptions = this.fetchOptions, c.ellipsoid.copy(s), c.adjustmentTransform.copy(o);
const p = c.parse(h.buffer);
r.push(p);
break;
}
}
}
return Promise.all(r).then((n) => {
const a = new Pt();
return n.forEach((l) => {
a.add(l.scene);
}), {
tiles: n,
scene: a
};
});
}
}
const yt = /* @__PURE__ */ new O();
class hi extends Pt {
constructor(t) {
super(), this.isTilesGroup = !0, this.name = "TilesRenderer.TilesGroup", this.tilesRenderer = t, this.matrixWorldInverse = new O();
}
raycast(t, e) {
return this.tilesRenderer.optimizeRaycast ? (this.tilesRenderer.raycast(t, e), !1) : !0;
}
updateMatrixWorld(t) {
if (this.matrixAutoUpdate && this.updateMatrix(), this.matrixWorldNeedsUpdate || t) {
this.parent === null ? yt.copy(this.matrix) : yt.multiplyMatrices(this.parent.matrixWorld, this.matrix), this.matrixWorldNeedsUpdate = !1;
const e = yt.elements, i = this.matrixWorld.elements;
let s = !1;
for (let o = 0; o < 16; o++) {
const r = e[o], n = i[o];
if (Math.abs(r - n) > Number.EPSILON) {
s = !0;
break;
}
}
if (s) {
this.matrixWorld.copy(yt), this.matrixWorldInverse.copy(yt).invert();
const o = this.children;
for (let r = 0, n = o.length; r < n; r++)
o[r].updateMatrixWorld();
}
}
}
updateWorldMatrix(t, e) {
this.parent && t && this.parent.updateWorldMatrix(t, !1), this.updateMatrixWorld(!0);
}
}
const Ee = /* @__PURE__ */ new Ft(), Ht = /* @__PURE__ */ new y(), Dt = [];
function Ie(f, t) {
return f.distance - t.distance;
}
function Oe(f, t, e, i) {
const { scene: s } = f.cached;
e.invokeOnePlugin((r) => r.raycastTile && r.raycastTile(f, s, t, i)) || t.intersectObject(s, !0, i);
}
function pi(f, t, e) {
Oe(f, t, e, Dt), Dt.sort(Ie);
const i = Dt[0] || null;
return Dt.length = 0, i;
}
function Re(f) {
return "__used" in f;
}
function ze(f, t, e, i = null) {
const { group: s, activeTiles: o } = f;
i === null && (i = Ee, i.copy(e.ray).applyMatrix4(s.matrixWorldInverse));
const r = [], n = t.children;
for (let h = 0, c = n.length; h < c; h++) {
const p = n[h];
if (!Re(p) || !p.__used)
continue;
p.cached.boundingVolume.intersectRay(i, Ht) !== null && (Ht.applyMatrix4(s.matrixWorld), r.push({
distance: Ht.distanceToSquared(e.ray.origin),
tile: p
}));
}
r.sort(Ie);
let a = null, l = 1 / 0;
if (o.has(t)) {
const h = pi(t, e, f);
h && (a = h, l = h.distance * h.distance);
}
for (let h = 0, c = r.length; h < c; h++) {
const p = r[h], m = p.distance, u = p.tile;
if (m > l)
break;
const d = ze(f, u, e, i);
if (d) {
const x = d.distance * d.distance;
x < l && (a = d, l = x);
}
}
return a;
}
function Ae(f, t, e, i, s = null) {
if (!Re(t))
return;
const { group: o, activeTiles: r } = f, { boundingVolume: n } = t.cached;
if (s === null && (s = Ee, s.copy(e.ray).applyMatrix4(o.matrixWorldInverse)), !t.__used || !n.intersectsRay(s))
return;
r.has(t) && Oe(t, e, f, i);
const a = t.children;
for (let l = 0, h = a.length; l < h; l++)
Ae(f, a[l], e, i, s);
}
const q = /* @__PURE__ */ new y(), Q = /* @__PURE__ */ new y(), $ = /* @__PURE__ */ new y(), ne = /* @__PURE__ */ new y(), re = /* @__PURE__ */ new y();
class di {
constructor() {
this.sphere = null, this.obb = null, this.region = null, this.regionObb = null;
}
intersectsRay(t) {
const e = this.sphere, i = this.obb || this.regionObb;
return !(e && !t.intersectsSphere(e) || i && !i.intersectsRay(t));
}
intersectRay(t, e = null) {
const i = this.sphere, s = this.obb || this.regionObb;
let o = -1 / 0, r = -1 / 0;
i && t.intersectSphere(i, ne) && (o = i.containsPoint(t.origin) ? 0 : t.origin.distanceToSquared(ne)), s && s.intersectRay(t, re) && (r = s.containsPoint(t.origin) ? 0 : t.origin.distanceToSquared(re));
const n = Math.max(o, r);
return n === -1 / 0 ? null : (t.at(Math.sqrt(n), e), e);
}
distanceToPoint(t) {
const e = this.sphere, i = this.obb || this.regionObb;
let s = -1 / 0, o = -1 / 0;
return e && (s = Math.max(e.distanceToPoint(t), 0)), i && (o = i.distanceToPoint(t)), s > o ? s : o;
}
intersectsFrustum(t) {
const e = this.obb || this.regionObb, i = this.sphere;
return i && !t.intersectsSphere(i) || e && !e.intersectsFrustum(t) ? !1 : !!(i || e);
}
intersectsSphere(t) {
const e = this.obb || this.regionObb, i = this.sphere;
return i && !i.intersectsSphere(t) || e && !e.intersectsSphere(t) ? !1 : !!(i || e);
}
intersectsOBB(t) {
const e = this.obb || this.regionObb, i = this.sphere;
return i && !t.intersectsSphere(i) || e && !e.intersectsOBB(t) ? !1 : !!(i || e);
}
getOBB(t, e) {
const i = this.obb || this.regionObb;
i ? (t.copy(i.box), e.copy(i.transform)) : (this.getAABB(t), e.identity());
}
getAABB(t) {
if (this.sphere)
this.sphere.getBoundingBox(t);
else {
const e = this.obb || this.regionObb;
t.copy(e.box).applyMatrix4(e.transform);
}
}
getSphere(t) {
if (this.sphere)
t.copy(this.sphere);
else if (this.region)
this.region.getBoundingSphere(t);
else {
const e = this.obb || this.regionObb;
e.box.getBoundingSphere(t), t.applyMatrix4(e.transform);
}
}
setObbData(t, e) {
const i = new Jt();
q.set(t[3], t[4], t[5]), Q.set(t[6], t[7], t[8]), $.set(t[9], t[10], t[11]);
const s = q.length(), o = Q.length(), r = $.length();
q.normalize(), Q.normalize(), $.normalize(), s === 0 && q.crossVectors(Q, $), o === 0 && Q.crossVectors(q, $), r === 0 && $.crossVectors(q, Q), i.transform.set(
q.x,
Q.x,
$.x,
t[0],
q.y,
Q.y,
$.y,
t[1],
q.z,
Q.z,
$.z,
t[2],
0,
0,
0,
1
).premultiply(e), i.box.min.set(-s, -o, -r), i.box.max.set(s, o, r), i.update(), this.obb = i;
}
setSphereData(t, e, i, s, o) {
const r = new $e();
r.center.set(t, e, i), r.radius = s, r.applyMatrix4(o), this.sphere = r;
}
setRegionData(t, e, i, s, o, r, n) {
const a = new oi(
...t.radius,
i,
o,
e,
s,
r,
n
), l = new Jt();
a.getBoundingBox(l.box, l.transform), l.update(), this.region = a, this.regionObb = l;
}
}
const ui = /* @__PURE__ */ new Xe();
function mi(f, t, e, i) {
const s = ui.set(
f.normal.x,
f.normal.y,
f.normal.z,
t.normal.x,
t.normal.y,
t.normal.z,
e.normal.x,
e.normal.y,
e.normal.z
);
return i.set(-f.constant, -t.constant, -e.constant), i.applyMatrix3(s.invert()), i;
}
class fi extends Ye {
constructor() {
super(), this.points = Array(8).fill().map(() => new y());
}
setFromProjectionMatrix(t, e) {
return super.setFromProjectionMatrix(t, e), this.calculateFrustumPoints(), this;
}
calculateFrustumPoints() {
const { planes: t, points: e } = this;
[
[t[0], t[3], t[4]],
// Near top left
[t[1], t[3], t[4]],
// Near top right
[t[0], t[2], t[4]],
// Near bottom left
[t[1], t[2], t[4]],
// Near bottom right
[t[0], t[3], t[5]],
// Far top left
[t[1], t[3], t[5]],
// Far top right
[t[0], t[2], t[5]],
// Far bottom left
[t[1], t[2], t[5]]
// Far bottom right
].forEach((s, o) => {
mi(s[0], s[1], s[2], e[o]);
});
}
}
const ae = /* @__PURE__ */ new O(), ce = /* @__PURE__ */ new Je(), Fe = Symbol("INITIAL_FRUSTUM_CULLED"), Ct = /* @__PURE__ */ new O(), xt = /* @__PURE__ */ new y(), jt = /* @__PURE__ */ new F(), lt = {
inView: !1,
error: 1 / 0
}, gi = /* @__PURE__ */ new y(1, 0, 0), yi = /* @__PURE__ */ new y(0, 1, 0);
function le(f, t) {
f.traverse((e) => {
e.frustumCulled = e[Fe] && t;
});
}
class Ai extends ke {
get autoDisableRendererCulling() {
return this._autoDisableRendererCulling;
}
set autoDisableRendererCulling(t) {
this._autoDisableRendererCulling !== t && (super._autoDisableRendererCulling = t, this.forEachLoadedModel((e) => {
le(e, !t);
}));
}
get optimizeRaycast() {
return this._optimizeRaycast;
}
set optimizeRaycast(t) {
console.warn('TilesRenderer: The "optimizeRaycast" option has been deprecated.'), this._optimizeRaycast = t;
}
constructor(...t) {
super(...t), this.group = new hi(this), this.ellipsoid = vt.clone(), this.cameras = [], this.cameraMap = /* @__PURE__ */ new Map(), this.cameraInfo = [], this._optimizeRaycast = !0, this._upRotationMatrix = new O(), this._bytesUsed = /* @__PURE__ */ new WeakMap(), this._autoDisableRendererCulling = !0, this.manager = new Ke(), this._listeners = {};
}
addEventListener(t, e) {
t === "load-tile-set" && (console.warn('TilesRenderer: "load-tile-set" event has been deprecated. Use "load-tileset" instead.'), t = "load-tileset"), mt.prototype.addEventListener.call(this, t, e);
}
hasEventListener(t, e) {
return t === "load-tile-set" && (console.warn('TilesRenderer: "load-tile-set" event has been deprecated. Use "load-tileset" instead.'), t = "load-tileset"), mt.prototype.hasEventListener.call(this, t, e);
}
removeEventListener(t, e) {
t === "load-tile-set" && (console.warn('TilesRenderer: "load-tile-set" event has been deprecated. Use "load-tileset" instead.'), t = "load-tileset"), mt.prototype.removeEventListener.call(this, t, e);
}
dispatchEvent(t) {
"tileset" in t && Object.defineProperty(t, "tileSet", {
get() {
return console.warn('TilesRenderer: "event.tileSet" has been deprecated. Use "event.tileset" instead.'), t.tileset;
},
enumerable: !1,
configurable: !0
}), mt.prototype.dispatchEvent.call(this, t);
}
/* Public API */
getBoundingBox(t) {
if (!this.root)
return !1;
const e = this.root.cached.boundingVolume;
return e ? (e.getAABB(t), !0) : !1;
}
getOrientedBoundingBox(t, e) {
if (!this.root)
return !1;
const i = this.root.cached.boundingVolume;
return i ? (i.getOBB(t, e), !0) : !1;
}
getBoundingSphere(t) {
if (!this.root)
return !1;
const e = this.root.cached.boundingVolume;
return e ? (e.getSphere(t), !0) : !1;
}
forEachLoadedModel(t) {
this.traverse((e) => {
const i = e.cached && e.cached.scene;
i && t(i, e);
}, null, !1);
}
raycast(t, e) {
if (this.root)
if (t.firstHitOnly) {
const i = ze(this, this.root, t);
i && e.push(i);
} else
Ae(this, this.root, t, e);
}
hasCamera(t) {
return this.cameraMap.has(t);
}
setCamera(t) {
const e = this.cameras, i = this.cameraMap;
return i.has(t) ? !1 : (i.set(t, new F()), e.push(t), this.dispatchEvent({ type: "add-camera", camera: t }), !0);
}
setResolution(t, e, i) {
const s = this.cameraMap;
if (!s.has(t))
return !1;
const o = e.isVector2 ? e.x : e, r = e.isVector2 ? e.y : i, n = s.get(t);
return (n.width !== o || n.height !== r) && (n.set(o, r), this.dispatchEvent({ type: "camera-resolution-change" })), !0;
}
setResolutionFromRenderer(t, e) {
return e.getSize(jt), this.setResolution(t, jt.x, jt.y);
}
deleteCamera(t) {
const e = this.cameras, i = this.cameraMap;
if (i.has(t)) {
const s = e.indexOf(t);
return e.splice(s, 1), i.delete(t), this.dispatchEvent({ type: "delete-camera", camera: t }), !0;
}
return !1;
}
/* Overriden */
loadRootTileset(...t) {
return super.loadRootTileset(...t).then((e) => {
const { asset: i, extensions: s = {} } = e;
switch ((i && i.gltfUpAxis || "y").toLowerCase()) {
case "x":
this._upRotationMatrix.makeRotationAxis(yi, -Math.PI / 2);
break;
case "y":
this._upRotationMatrix.makeRotationAxis(gi, Math.PI / 2);
break;
}
if ("3DTILES_ellipsoid" in s) {
const r = s["3DTILES_ellipsoid"], { ellipsoid: n } = this;
n.name = r.body, r.radii ? n.radius.set(...r.radii) : n.radius.set(1, 1, 1);
}
return e;
});
}
update() {
let t = null;
if (this.invokeAllPlugins((r) => {
if (r.doTilesNeedUpdate) {
const n = r.doTilesNeedUpdate();
t === null ? t = n : t = !!(t || n);
}
}), t === !1) {
this.dispatchEvent({ type: "update-before" }), this.dispatchEvent({ type: "update-after" });
return;
}
this.dispatchEvent({ type: "update-before" });
const e = this.group, i = this.cameras, s = this.cameraMap, o = this.cameraInfo;
for (; o.length > i.length; )
o.pop();
for (; o.length < i.length; )
o.push({
frustum: new fi(),
isOrthographic: !1,
sseDenominator: -1,
// used if isOrthographic:false
position: new y(),
invScale: -1,
pixelSize: 0
// used if isOrthographic:true
});
xt.setFromMatrixScale(e.matrixWorldInverse), Math.abs(Math.max(xt.x - xt.y, xt.x - xt.z)) > 1e-6 && console.warn("ThreeTilesRenderer : Non uniform scale used for tile which may cause issues when calculating screen space error.");
for (let r = 0, n = o.length; r < n; r++) {
const a = i[r], l = o[r], h = l.frustum, c = l.position, p = s.get(a);
(p.width === 0 || p.height === 0) && console.warn("TilesRenderer: resolution for camera error calculation is not set.");
const m = a.projectionMatrix.elements;
if (l.isOrthographic = m[15] === 1, l.isOrthographic) {
const u = 2 / m[0], d = 2 / m[5];
l.pixelSize = Math.max(d / p.height, u / p.width);
} else
l.sseDenominator = 2 / m[5] / p.height;
Ct.copy(e.matrixWorld), Ct.premultiply(a.matrixWorldInverse), Ct.premultiply(a.projectionMatrix), h.setFromProjectionMatrix(Ct), c.set(0, 0, 0), c.applyMatrix4(a.matrixWorld), c.applyMatrix4(e.matrixWorldInverse);
}
if (super.update(), this.dispatchEvent({ type: "update-after" }), i.length === 0 && this.root) {
let r = !1;
this.invokeAllPlugins((n) => r = r || !!(n !== this && n.calculateTileViewError)), r === !1 && console.warn("TilesRenderer: no cameras defined. Cannot update 3d tiles.");
}
}
preprocessNode(t, e, i = null) {
super.preprocessNode(t, e, i);
const s = new O();
if (t.transform) {
const n = t.transform;
for (let a = 0; a < 16; a++)
s.elements[a] = n[a];
}
i && s.premultiply(i.cached.transform);
const o = new O().copy(s).invert(), r = new di();
"sphere" in t.boundingVolume && r.setSphereData(...t.boundingVolume.sphere, s), "box" in t.boundingVolume && r.setObbData(t.boundingVolume.box, s), "region" in t.boundingVolume && r.setRegionData(this.ellipsoid, ...t.boundingVolume.region), t.cached = {
transform: s,
transformInverse: o,
active: !1,
boundingVolume: r,
metadata: null,
scene: null,
geometry: null,
materials: null,
textures: null
};
}
async parseTile(t, e, i, s, o) {
const r = e.cached, n = Be(s), a = this.fetchOptions, l = this.manager;
let h = null;
const c = r.transform, p = this._upRotationMatrix, m = (He(t) || i).toLowerCase();
switch (m) {
case "b3dm": {
const g = new De(l);
g.workingPath = n, g.fetchOptions = a, g.adjustmentTransform.copy(p), h = g.parse(t);
break;
}
case "pnts": {
const g = new Ce(l);
g.workingPath = n, g.fetchOptions = a, h = g.parse(t);
break;
}
case "i3dm": {
const g = new Se(l);
g.workingPath = n, g.fetchOptions = a, g.adjustmentTransform.copy(p), g.ellipsoid.copy(this.ellipsoid), h = g.parse(t);
break;
}
case "cmpt": {
const g = new li(l);
g.workingPath = n, g.fetchOptions = a, g.adjustmentTransform.copy(p), g.ellipsoid.copy(this.ellipsoid), h = g.parse(t).then((C) => C.scene);
break;
}
// 3DTILES_content_gltf
case "gltf":
case "glb": {
const g = l.getHandler("path.gltf") || l.getHandler("path.glb") || new Xt(l);
g.setWithCredentials(a.credentials === "include"), g.setRequestHeader(a.headers || {}), a.credentials === "include" && a.mode === "cors" && g.setCrossOrigin("use-credentials");
let C = g.resourcePath || g.path || n;
!/[\\/]$/.test(C) && C.length && (C += "/"), h = g.parseAsync(t, C).then((S) => {
S.scene = S.scene || new Pt();
const { scene: T } = S;
return T.updateMatrix(), T.matrix.multiply(p).decompose(T.position, T.quaternion, T.scale), S;
});
break;
}
default: {
h = this.invokeOnePlugin((g) => g.parseToMesh && g.parseToMesh(t, e, i, s, o));
break;
}
}
const u = await h;
if (u === null)
throw new Error(`TilesRenderer: Content type "${m}" not supported.`);
let d, x;
u.isObject3D ? (d = u, x = null) : (d = u.scene, x = u), d.updateMatrix(), d.matrix.premultiply(c), d.matrix.decompose(d.position, d.quaternion, d.scale), await this.invokeAllPlugins((g) => g.processTileModel && g.processTileModel(d, e)), d.traverse((g) => {
g[Fe] = g.frustumCulled;
}), le(d, !this.autoDisableRendererCulling);
const E = [], _ = [], U = [];
if (d.traverse((g) => {
if (g.geometry && _.push(g.geometry), g.material) {
const C = g.material;
E.push(g.material);
for (const S in C) {
const T = C[S];
T && T.isTexture && U.push(T);
}
}
}), o.aborted) {
for (let g = 0, C = U.length; g < C; g++) {
const S = U[g];
S.image instanceof ImageBitmap && S.image.close(), S.dispose();
}
return;
}
r.materials = E, r.geometry = _, r.textures = U, r.scene = d, r.metadata = x;
}
disposeTile(t) {
super.disposeTile(t);
const e = t.cached;
if (e.scene) {
const i = e.materials, s = e.geometry, o = e.textures, r = e.scene.parent;
e.scene.traverse((n) => {
n.userData.meshFeatures && n.userData.meshFeatures.dispose(), n.userData.structuralMetadata && n.userData.structuralMetadata.dispose();
});
for (let n = 0, a = s.length; n < a; n++)
s[n].dispose();
for (let n = 0, a = i.length; n < a; n++)
i[n].dispose();
for (let n = 0, a = o.length; n < a; n++) {
const l = o[n];
l.image instanceof ImageBitmap && l.image.close(), l.dispose();
}
r && r.remove(e.scene), this.dispatchEvent({
type: "dispose-model",
scene: e.scene,
tile: t
}), e.scene = null, e.materials = null, e.textures = null, e.geometry = null, e.metadata = null;
}
}
setTileVisible(t, e) {
const i = t.cached.scene, s = this.group;
e ? i && (s.add(i), i.updateMatrixWorld(!0)) : i && s.remove(i), super.setTileVisible(t, e), this.dispatchEvent({
type: "tile-visibility-change",
scene: i,
tile: t,
visible: e
});
}
calculateBytesUsed(t, e) {
const i = this._bytesUsed;
return !i.has(t) && e && i.set(t, ni(e)), i.get(t) ?? null;
}
calculateTileViewError(t, e) {
const i = t.cached, s = this.cameras, o = this.cameraInfo, r = i.boundingVolume;
let n = !1, a = -1 / 0, l = 1 / 0, h = -1 / 0, c = 1 / 0;
for (let p = 0, m = s.length; p < m; p++) {
const u = o[p];
let d, x;
if (u.isOrthographic) {
const _ = u.pixelSize;
d = t.geometricError / _, x = 1 / 0;
} else {
const _ = u.sseDenominator;
x = r.distanceToPoint(u.position), d = x === 0 ? 1 / 0 : t.geometricError / (x * _);
}
const E = o[p].frustum;
r.intersectsFrustum(E) && (n = !0, a = Math.max(a, d), l = Math.min(l, x)), h = Math.max(h, d), c = Math.min(c, x);
}
this.invokeAllPlugins((p) => {
p !== this && p.calculateTileViewError && p.calculateTileViewError(t, lt) && (n = n && lt.inView, h = Math.max(h, lt.error), lt.inView && (a = Math.max(a, lt.error)));
}), n ? (e.inView = !0, e.error = a, e.distanceFromCamera = l) : (e.inView = lt.inView, e.error = h, e.distanceFromCamera = c);
}
// adjust the rotation of the group such that Y is altitude, X is North, and Z is East
setLatLonToYUp(t, e) {
console.warn("TilesRenderer: setLatLonToYUp is deprecated. Use the ReorientationPlugin, instead.");
const { ellipsoid: i, group: s } = this;
ce.set(Math.PI / 2, Math.PI / 2, 0), ae.makeRotationFromEuler(ce), i.getEastNorthUpFrame(t, e, 0, s.matrix).multiply(ae).invert().decompose(
s.position,
s.quaternion,
s.scale
), s.updateMatrixWorld(!0);
}
dispose() {
super.dispose(), this.group.removeFromParent();
}
}
class xi extends ti {
constructor() {
super(new ei(0, 0), new bi()), this.renderOrder = 1 / 0;
}
onBeforeRender(t) {
const e = this.material.uniforms;
t.getSize(e.resolution.value);
}
updateMatrixWorld() {
this.matrixWorld.makeTranslation(this.position);
}
dispose() {
this.geometry.dispose(), this.material.dispose();
}
}
class bi extends ii {
constructor() {
super({
depthWrite: !1,
depthTest: !1,
transparent: !0,
uniforms: {
resolution: { value: new F() },
size: { value: 15 },
thickness: { value: 2 },
opacity: { value: 1 }
},
vertexShader: (
/* glsl */
`
uniform float pixelRatio;
uniform float size;
uniform float thickness;
uniform vec2 resolution;
varying vec2 vUv;
void main() {
vUv = uv;
float aspect = resolution.x / resolution.y;
vec2 offset = uv * 2.0 - vec2( 1.0 );
offset.y *= aspect;
vec4 screenPoint = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
screenPoint.xy += offset * ( size + thickness ) * screenPoint.w / resolution.x;
gl_Position = screenPoint;
}
`
),
fragmentShader: (
/* glsl */
`
uniform float size;
uniform float thickness;
uniform float opacity;
varying vec2 vUv;
void main() {
float ht = 0.5 * thickness;
float planeDim = size + thickness;
float offset = ( planeDim - ht - 2.0 ) / planeDim;
float texelThickness = ht / planeDim;
vec2 vec = vUv * 2.0 - vec2( 1.0 );
float dist = abs( length( vec ) - offset );
float fw = fwidth( dist ) * 0.5;
float a = smoothstep( texelThickness - fw, texelThickness + fw, dist );
gl_FragColor = vec4( 1, 1, 1, opacity * ( 1.0 - a ) );
}
`
)
});
}
}
const he = /* @__PURE__ */ new F(), pe = /* @__PURE__ */ new F();
class Mi {
constructor() {
this.domElement = null, this.buttons = 0, this.pointerType = null, this.pointerOrder = [], this.previousPositions = {}, this.pointerPositions = {}, this.startPositions = {}, this.pointerSetThisFrame = {}, this.hoverPosition = new F(), this.hoverSet = !1;
}
reset() {
this.buttons = 0, this.pointerType = null, this.pointerOrder = [], this.previousPositions = {}, this.pointerPositions = {}, this.startPositions = {}, this.pointerSetThisFrame = {}, this.hoverPosition = new F(), this.hoverSet = !1;
}
// The pointers can be set multiple times per frame so track whether the pointer has
// been set this frame or not so we don't overwrite the previous position and lose information
// about pointer movement
updateFrame() {
const { previousPositions: t, pointerPositions: e } = this;
for (const i in e)
t[i].copy(e[i]);
}
setHoverEvent(t) {
(t.pointerType === "mouse" || t.type === "wheel") && (this.getAdjustedPointer(t, this.hoverPosition), this.hoverSet = !0);
}
getLatestPoint(t) {
return this.pointerType !== null ? (this.getCenterPoint(t), t) : this.hoverSet ? (t.copy(this.hoverPosition), t) : null;
}
// get the pointer position in the coordinate system of the target element
getAdjustedPointer(t, e) {
const s = (this.domElement ? this.domElement : t.target).getBoundingClientRect(), o = t.clientX - s.left, r = t.clientY - s.top;
e.set(o, r);
}
addPointer(t) {
const e = t.pointerId, i = new F();
this.getAdjustedPointer(t, i), this.pointerOrder.push(e), this.pointerPositions[e] = i, this.previousPositions[e] = i.clone(), this.startPositions[e] = i.clone(), this.getPointerCount() === 1 && (this.pointerType = t.pointerType, this.buttons = t.buttons);
}
updatePointer(t) {
const e = t.pointerId;
return e in this.pointerPositions ? (this.getAdjustedPointer(t, this.pointerPositions[e]), !0) : !1;
}
deletePointer(t) {
const e = t.pointerId, i = this.pointerOrder;
i.splice(i.indexOf(e), 1), delete this.pointerPositions[e], delete this.previousPositions[e], delete this.startPositions[e], this.getPointerCount() === 0 && (this.buttons = 0, this.pointerType = null);
}
getPointerCount() {
return this.pointerOrder.length;
}
getCenterPoint(t, e = this.pointerPositions) {
const i = this.pointerOrder;
if (this.getPointerCount() === 1 || this.getPointerType() === "mouse") {
const s = i[0];
return t.copy(e[s]), t;
} else if (this.getPointerCount() === 2) {
const s = this.pointerOrder[0], o = this.pointerOrder[1], r = e[s], n = e[o];
return t.addVectors(r, n).multiplyScalar(0.5), t;
}
return null;
}
getPreviousCenterPoint(t) {
return this.getCenterPoint(t, this.previousPositions);
}
getStartCenterPoint(t) {
return this.getCenterPoint(t, this.startPositions);
}
getMoveDistance() {
return this.getCenterPoint(he), this.getPreviousCenterPoint(pe), he.sub(pe).length();
}
getTouchPointerDistance(t = this.pointerPositions) {
if (this.getPointerCount() <= 1 || this.getPointerType() === "mouse")
return 0;
const { pointerOrder: e } = this, i = e[0], s = e[1], o = t[i], r = t[s];
return o.distanceTo(r);
}
getPreviousTouchPointerDistance() {
return this.getTouchPointerDistance(this.previousPositions);
}
getStartTouchPointerDistance() {
return this.getTouchPointerDistance(this.startPositions);
}
getPointerType() {
return this.pointerType;
}
isPointerTouch() {
return this.getPointerType() === "touch";
}
getPointerButtons() {
return this.buttons;
}
isLeftClicked() {
return !!(this.buttons & 1);
}
isRightClicked() {
return !!(this.buttons & 2);
}
}
const St = /* @__PURE__ */ new O();
function ft(f, t, e) {
return e.makeTranslation(-f.x, -f.y, -f.z), St.makeRotationFromQuaternion(t), e.premultiply(St), St.makeTranslation(f.x, f.y, f.z), e.premultiply(St), e;
}
function dt(f, t, e, i) {
i.x = (f - e.offsetLeft) / e.clientWidth * 2 - 1, i.y = -((t - e.offsetTop) / e.clientHeight) * 2 + 1, i.isVector3 && (i.z = 0);
}
function H(f, t, e) {
const i = f instanceof Ft ? f : f.ray, { origin: s, direction: o } = i;
s.set(t.x, t.y, -1).unproject(e), o.set(t.x, t.y, 1).unproject(e).sub(s), f.isRay || (f.near = 0, f.far = o.length(), f.camera = e), o.normalize();
}
const G = 0, et = 1, Y = 2, ut = 3, Gt = 4, Zt = 0.05, qt = 0.025, tt = /* @__PURE__ */ new O(), Et = /* @__PURE__ */ new O(), W = /* @__PURE__ */ new y(), M = /* @__PURE__ */ new y(), It = /* @__PURE__ */ new y(), Ot = /* @__PURE__ */ new y(), A = /* @__PURE__ */ new y(), B = /* @__PURE__ */ new y(), Qt = /* @__PURE__ */ new y(), Rt = /* @__PURE__ */ new y(), j = /* @__PURE__ */ new it(), de = /* @__PURE__ */ new ve(), I = /* @__PURE__ */ new y(), zt = /* @__PURE__ */ new y(), $t = /* @__PURE__ */ new y(), _i = /* @__PURE__ */ new it(), w = /* @__PURE__ */ new Ft(), bt = /* @__PURE__ */ new F(), R = /* @__PURE__ */ new F(), ue = /* @__PURE__ */ new F(), Mt = /* @__PURE__ */ new F(), Yt = /* @__PURE__ */ new F(), me = /* @__PURE__ */ new F(), fe = { type: "change" }, ge = { type: "start" }, ye = { type: "end" };
class Pi extends mt {
get enabled() {
return this._enabled;
}
set enabled(t) {
t !== this.enabled && (this._enabled = t, this.resetState(), this.pointerTracker.reset(), this.enabled || (this.dragInertia.set(0, 0, 0), this.rotationInertia.set(0, 0)));
}
constructor(t = null, e = null, i = null, s = null) {
super(), this.isEnvironmentControls = !0, this.domElement = null, this.camera = null, this.scene = null, this.tilesRenderer = null, this._enabled = !0, this.cameraRadius = 5, this.rotationSpeed = 1, this.minAltitude = 0, this.maxAltitude = 0.45 * Math.PI, this.minDistance = 10, this.maxDistance = 1 / 0, this.minZoom = 0, this.maxZoom = 1 / 0, this.zoomSpeed = 1, this.adjustHeight = !0, this.enableDamping = !1, this.dampingFactor = 0.15, this.fallbackPlane = new ve(new y(0, 1, 0), 0), this.useFallbackPlane = !0, this.scaleZoomOrientationAtEdges = !1, this.autoAdjustCameraRotation = !0, this.state = G, this.pointerTracker = new Mi(), this.needsUpdate = !1, this.actionHeightOffset = 0, this.pivotPoint = new y(), this.zoomDirectionSet = !1, this.zoomPointSet = !1, this.zoomDirection = new y(), this.zoomPoint = new y(), this.zoomDelta = 0, this.rotationInertiaPivot = new y(), this.rotationInertia = new F(), this.dragInertia = new y(), this.inertiaTargetDistance = 1 / 0, this.inertiaStableFrames = 0, this.pivotMesh = new xi(), this.pivotMesh.raycast = () => {
}, this.pivotMesh.scale.setScalar(0.25), this.raycaster = new si(), this.raycaster.firstHitOnly = !0, this.up = new y(0, 1, 0), this.clock = new Te(), this._detachCallback = null, this._upInitialized = !1, this._lastUsedState = G, this._zoomPointWasSet = !1, this._tilesOnChangeCallback = () => this.zoomPointSet = !1, i && this.attach(i), e && this.setCamera(e), t && this.setScene(t), s && this.setTilesRenderer(s);
}
setScene(t) {
this.scene = t;
}
setCamera(t) {
this.camera = t, this._upInitialized = !1, this.zoomDirectionSet = !1, this.zoomPointSet = !1, this.needsUpdate = !0, this.raycaster.camera = t, this.resetState();
}
setTilesRenderer(t) {
console.warn('EnvironmentControls: "setTilesRenderer" has been deprecated. Use "setScene" and "setEllipsoid", instead.'), this.tilesRenderer = t, this.tilesRenderer !== null && this.setScene(this.tilesRenderer.group);
}
attach(t) {
if (this.domElement)
throw new Error("EnvironmentControls: Controls already attached to element");
this.domElement = t, this.pointerTracker.domElement = t, t.style.touchAction = "none";
const e = (h) => {
this.enabled && h.preventDefault();
}, i = (h) => {
if (!this.enabled)
return;
h.preventDefault();
const {
camera: c,
raycaster: p,
domElement: m,
up: u,
pivotMesh: d,
pointerTracker: x,
scene: E,
pivotPoint: _,
enabled: U
} = this;
if (x.addPointer(h), this.needsUpdate = !0, x.isPointerTouch()) {
if (d.visible = !1, x.getPointerCount() === 0)
m.setPointerCapture(h.pointerId);
else if (x.getPointerCount() > 2) {
this.resetState();
return;
}
}
x.getCenterPoint(R), dt(R.x, R.y, m, R), H(p, R, c);
const g = Math.abs(p.ray.direction.dot(u));
if (g < Zt || g < qt)
return;
const C = this._raycast(p);
C && (x.getPointerCount() === 2 || x.isRightClicked() || x.isLeftClicked() && h.shiftKey ? (this.setState(x.isPointerTouch() ? Gt : Y), _.copy(C.point), d.position.copy(C.point), d.visible = x.isPointerTouch() ? !1 : U, d.updateMatrixWorld(), E.add(d)) : x.isLeftClicked() && (this.setState(et), _.copy(C.point), d.position.copy(C.point), d.updateMatrixWorld(), E.add(d)));
};
let s = !1;
const o = (h) => {
const { pointerTracker: c } = this;
if (!this.enabled)
return;
h.preventDefault();
const {
pivotMesh: p,
enabled: m
} = this;
this.zoomDirectionSet = !1, this.zoomPointSet = !1, this.state !== G && (this.needsUpdate = !0), c.setHoverEvent(h), c.updatePointer(h) && (c.isPointerTouch() && c.getPointerCount() === 2 && (s || (s = !0, queueMicrotask(() => {
s = !1, c.getCenterPoint(Yt);
const u = c.getStartTouchPointerDistance(), d = c.getTouchPointerDistance(), x = d - u;
if (this.state === G || this.state === Gt) {
c.getCenterPoint(Yt), c.getStartCenterPoint(me);
const E = 2 * window.devicePixelRatio, _ = Yt.distanceTo(me);
(Math.abs(x) > E || _ > E) && (Math.abs(x) > _ ? (this.setState(ut), this.zoomDirectionSet = !1) : this.setState(Y));
}
if (this.state === ut) {
const E = c.getPreviousTouchPointerDistance();
this.zoomDelta += d - E, p.visible = !1;
} else this.state === Y && (p.visible = m);
}))), this.dispatchEvent(fe));
}, r = (h) => {
const { pointerTracker: c } = this;
!this.enabled || c.getPointerCount() === 0 || (c.deletePointer(h), c.getPointerType() === "touch" && c.getPointerCount() === 0 && t.releasePointerCapture(h.pointerId), this.resetState(), this.needsUpdate = !0);
}, n = (h) => {
if (!this.enabled)
return;
h.preventDefault();
const { pointerTracker: c } = this;
c.setHoverEvent(h), c.updatePointer(h), this.dispatchEvent(ge);
let p;
switch (h.deltaMode) {
case 2:
p = h.deltaY * 800;
break;
case 1:
p = h.deltaY * 40;
break;
case 0:
p = h.deltaY;
break;
}
const m = Math.sign(p), u = Math.abs(p);
this.zoomDelta -= 0.25 * m * u, this.needsUpdate = !0, this._lastUsedState = ut, this.dispatchEvent(ye);
}, a = (h) => {
this.enabled && this.resetState();
};
t.addEventListener("contextmenu", e), t.addEventListener("pointerdown", i), t.addEventListener("wheel", n, { passive: !1 });
const l = t.getRootNode();
l.addEventListener("pointermove", o), l.addEventListener("pointerup", r), l.addEventListener("pointerleave", a), this._detachCallback = () => {
t.removeEventListener("contextmenu", e), t.removeEventListener("pointerdown", i), t.removeEventListener("wheel", n), l.removeEventListener("pointermove", o), l.removeEventListener("pointerup", r), l.removeEventListener("pointerleave", a);
};
}
detach() {
this.domElement = null, this._detachCallback && (this._detachCallback(), this._detachCallback = null, this.pointerTracker.reset());
}
// override-able functions for retrieving the up direction at a point
getUpDirection(t, e) {
e.copy(this.up);
}
getCameraUpDirection(t) {
this.getUpDirection(this.camera.position, t);
}
// returns the active / last used pivot point for the scene
getPivotPoint(t) {
let e = null;
this._lastUsedState === ut ? this._zoomPointWasSet && (e = t.copy(this.zoomPoint)) : (this._lastUsedState === Y || this._lastUsedState === et) && (e = t.copy(this.pivotPoint));
const { camera: i, raycaster: s } = this;
e !== null && (M.copy(e).project(i), (M.x < -1 || M.x > 1 || M.y < -1 || M.y > 1) && (e = null)), H(s, { x: 0, y: 0 }, i);
const o = this._raycast(s);
return o && (e === null || o.distance < e.distanceTo(s.ray.origin)) && (e = t.copy(o.point)), e;
}
resetState() {
this.state !== G && this.dispatchEvent(ye), this.state = G, this.pivotMesh.removeFromParent(), this.pivotMesh.visible = this.enabled, this.actionHeightOffset = 0, this.pointerTracker.reset();
}
setState(t = this.state, e = !0) {
this.state !== t && (this.state === G && e && this.dispatchEvent(ge), this.pivotMesh.visible = this.enabled, this.dragInertia.set(0, 0, 0), this.rotationInertia.set(0, 0), this.inertiaStableFrames = 0, this.state = t, t !== G && t !== Gt && (this._lastUsedState = t));
}
update(t = Math.min(this.clock.getDelta(), 64 / 1e3)) {
if (!this.enabled || !this.camera || t === 0)
return;
const {
camera: e,
cameraRadius: i,
pivotPoint: s,
up: o,
state: r,
adjustHeight: n,
autoAdjustCameraRotation: a
} = this;
e.updateMatrixWorld(), this.getCameraUpDirection(I), this._upInitialized || (this._upInitialized = !0, this.up.copy(I)), this.zoomPointSet = !1;
const l = this._inertiaNeedsUpdate(), h = this.needsUpdate || l;
if (this.needsUpdate || l) {
const p = this.zoomDelta;
this._updateZoom(), this._updatePosition(t), this._updateRotation(t), r === et || r === Y ? (A.set(0, 0, -1).transformDirection(e.matrixWorld), this.inertiaTargetDistance = M.copy(s).sub(e.position).dot(A)) : r === G && this._updateInertia(t), (r !== G || p !== 0 || l) && this.dispatchEvent(fe), this.needsUpdate = !1;
}
const c = e.isOrthographicCamera ? null : n && this._getPointBelowCamera() || null;
if (this.getCameraUpDirection(I), this._setFrame(I), (this.state === et || this.state === Y) && this.actionHeightOffset !== 0) {
const { actionHeightOffset: p } = this;
e.position.addScaledVector(o, -p), s.addScaledVector(o, -p), c && (c.distance -= p);
}
if (this.actionHeightOffset = 0, c) {
const p = c.distance;
if (p < i) {
const m = i - p;
e.position.addScaledVector(o, m), s.addScaledVector(o, m), this.actionHeightOffset = m;
}
}
this.pointerTracker.updateFrame(), h && a && (this.getCameraUpDirection(I), this._alignCameraUp(I, 1), this.getCameraUpDirection(I), this._clampRotation(I));
}
// updates the camera to position it based on the constraints of the controls
adjustCamera(t) {
const { adjustHeight: e, cameraRadius: i } = this;
if (t.isPerspectiveCamera) {
this.getUpDirection(t.position, I);
const s = e && this._getPointBelowCamera(t.position, I) || null;
if (s) {
const o = s.distance;
o < i && t.position.addScaledVector(I, i - o);
}
}
}
dispose() {
this.detach();
}
// private
_updateInertia(t) {
const {
rotationInertia: e,
pivotPoint: i,
dragInertia: s,
enableDamping: o,
dampingFactor: r,
camera: n,
cameraRadius: a,
minDistance: l,
inertiaTargetDistance: h
} = this;
if (!this.enableDamping || this.inertiaStableFrames > 1) {
s.set(0, 0, 0), e.set(0, 0, 0);
return;
}
const c = Math.pow(2, -t / r), p = Math.max(n.near, a, l, h), d = 0.25 * (2 / (2 * 1e3));
if (e.lengthSq() > 0) {
H(w, M.set(0, 0, -1), n), w.applyMatrix4(n.matrixWorldInverse), w.direction.normalize(), w.recast(-w.direction.dot(w.origin)).at(p / w.direction.z, M), M.applyMatrix4(n.matrixWorld), H(w, W.set(d, d, -1), n), w.applyMatrix4(n.matrixWorldInverse), w.direction.normalize(), w.recast(-w.direction.dot(w.origin)).at(p / w.direction.z, W), W.applyMatrix4(n.matrixWorld), M.sub(i).normalize(), W.sub(i).normalize();
const x = M.angleTo(W) / t;
e.multiplyScalar(c), (e.lengthSq() < x ** 2 || !o) && e.set(0, 0);
}
if (s.lengthSq() > 0) {
H(w, M.set(0, 0, -1), n), w.applyMatrix4(n.matrixWorldInverse), w.direction.normalize(), w.recast(-w.direction.dot(w.origin)).at(p / w.direction.z, M), M.applyMatrix4(n.matrixWorld), H(w, W.set(d, d, -1), n), w.applyMatrix4(n.matrixWorldInverse), w.direction.normalize(), w.recast(-w.direction.dot(w.origin)).at(p / w.direction.z, W), W.applyMatrix4(n.matrixWorld);
const x = M.distanceTo(W) / t;
s.multiplyScalar(c), (s.lengthSq() < x ** 2 || !o) && s.set(0, 0, 0);
}
e.lengthSq() > 0 && this._applyRotation(e.x * t, e.y * t, i), s.lengthSq() > 0 && (n.position.addScaledVector(s, t), n.updateMatrixWorld());
}
_inertiaNeedsUpdate() {
const { rotationInertia: t, dragInertia: e } = this;
return t.lengthSq() !== 0 || e.lengthSq() !== 0;
}
_updateZoom() {
const {
zoomPoint: t,
zoomDirection: e,
camera: i,
minDistance: s,
maxDistance: o,
pointerTracker: r,
domElement: n,
minZoom: a,
maxZoom: l,
zoomSpeed: h,
state: c
} = this;
let p = this.zoomDelta;
if (this.zoomDelta = 0, !(!r.getLatestPoint(R) || p === 0 && c !== ut))
if (this.rotationInertia.set(0, 0), this.dragInertia.set(0, 0, 0), i.isOrthographicCamera) {
this._updateZoomDirection();
const m = this.zoomPointSet || this._updateZoomPoint();
zt.unproject(i);
const u = Math.pow(0.95, Math.abs(p * 0.05));
let d = p > 0 ? 1 / Math.abs(u) : u;
d *= h, d > 1 ? l < i.zoom * d && (d = 1) : a > i.zoom * d && (d = 1), i.zoom *= d, i.updateProjectionMatrix(), m && (dt(R.x, R.y, n, $t), $t.unproject(i), i.position.sub($t).add(zt), i.updateMatrixWorld());
} else {
this._updateZoomDirection();
const m = M.copy(e);
if (this.zoomPointSet || this._updateZoomPoint()) {
const u = t.distanceTo(i.position);
if (p < 0) {
const d = Math.min(0, u - o);
p = p * u * h * 25e-4, p = Math.max(p, d);
} else {
const d = Math.max(0, u - s);
p = p * Math.max(u - s, 0) * h * 25e-4, p = Math.min(p, d);
}
i.position.addScaledVector(e, p), i.updateMatrixWorld();
} else {
const u = this._getPointBelowCamera();
if (u) {
const d = u.distance;
m.set(0, 0, -1).transformDirection(i.matrixWorld), i.position.addScaledVector(m, p * d * 0.01), i.updateMatrixWorld();
}
}
}
}
_updateZoomDirection() {
if (this.zoomDirectionSet)
return;
const { domElement: t, raycaster: e, camera: i, zoomDirection: s, pointerTracker: o } = this;
o.getLatestPoint(R), dt(R.x, R.y, t, zt), H(e, zt, i), s.copy(e.ray.direction).normalize(), this.zoomDirectionSet = !0;
}
// update the point being zoomed in to based on the zoom direction
_updateZoomPoint() {
const {
camera: t,
zoomDirectionSet: e,
zoomDirection: i,
raycaster: s,
zoomPoint: o,
pointerTracker: r,
domElement: n
} = this;
if (this._zoomPointWasSet = !1, !e)
return !1;
t.isOrthographicCamera && r.getLatestPoint(bt) ? (dt(bt.x, bt.y, n, bt), H(s, bt, t)) : (s.ray.origin.copy(t.position), s.ray.direction.copy(i), s.near = 0, s.far = 1 / 0);
const a = this._raycast(s);
return a ? (o.copy(a.point), this.zoomPointSet = !0, this._zoomPointWasSet = !0, !0) : !1;
}
// returns the point below the camera
_getPointBelowCamera(t = this.camera.position, e = this.up) {
const { raycaster: i } = this;
i.ray.direction.copy(e).multiplyScalar(-1), i.ray.origin.copy(t).addScaledVector(e, 1e5), i.near = 0, i.far = 1 / 0;
const s = this._raycast(i);
return s && (s.distance -= 1e5), s;
}
// update the drag action
_updatePosition(t) {
const {
raycaster: e,
camera: i,
pivotPoint: s,
up: o,
pointerTracker: r,
domElement: n,
state: a,
dragInertia: l
} = this;
if (a === et) {
if (r.getCenterPoint(R), dt(R.x, R.y, n, R), de.setFromNormalAndCoplanarPoint(o, s), H(e, R, i), Math.abs(e.ray.direction.dot(o)) < Zt) {
const h = Math.acos(Zt);
Rt.crossVectors(e.ray.direction, o).normalize(), e.ray.direction.copy(o).applyAxisAngle(Rt, h).multiplyScalar(-1);
}
if (this.getUpDirection(s, I), Math.abs(e.ray.direction.dot(I)) < qt) {
const h = Math.acos(qt);
Rt.crossVectors(e.ray.direction, I).normalize(), e.ray.direction.copy(I).applyAxisAngle(Rt, h).multiplyScalar(-1);
}
e.ray.intersectPlane(de, M) && (W.subVectors(s, M), i.position.add(W), i.updateMatrixWorld(), W.multiplyScalar(1 / t), r.getMoveDistance() / t < 2 * window.devicePixelRatio ? this.inertiaStableFrames++ : (l.copy(W), this.inertiaStableFrames = 0));
}
}
_updateRotation(t) {
const {
pivotPoint: e,
pointerTracker: i,
domElement: s,
state: o,
rotationInertia: r
} = this;
o === Y && (i.getCenterPoint(R), i.getPreviousCenterPoint(ue), Mt.subVectors(R, ue).multiplyScalar(2 * Math.PI / s.clientHeight), this._applyRotation(Mt.x, Mt.y, e), Mt.multiplyScalar(1 / t), i.getMoveDistance() / t < 2 * window.devicePixelRatio ? this.inertiaStableFrames++ : (r.copy(Mt), this.inertiaStableFrames = 0));
}
_applyRotation(t, e, i) {
if (t === 0 && e === 0)
return;
const {
camera: s,
minAltitude: o,
maxAltitude: r,
rotationSpeed: n
} = this, a = -t * n;
let l = e * n;
A.set(0, 0, 1).transformDirection(s.matrixWorld), B.set(1, 0, 0).transformDirection(s.matrixWorld), this.getUpDirection(i, I);
let h;
I.dot(A) > 1 - 1e-10 ? h = 0 : (M.crossVectors(I, A).normalize(), h = Math.sign(M.dot(B)) * I.angleTo(A)), l > 0 ? (l = Math.min(h - o, l), l = Math.max(0, l)) : (l = Math.max(h - r, l), l = Math.min(0, l)), j.setFromAxisAngle(I, a), ft(i, j, tt), s.matrixWorld.premultiply(tt), B.set(1, 0, 0).transformDirection(s.matrixWorld), j.setFromAxisAngle(B, -l), ft(i, j, tt), s.matrixWorld.premultiply(tt), s.matrixWorld.decompose(s.position, s.quaternion, M);
}
// sets the "up" axis for the current surface of the tileset
_setFrame(t) {
const {
up: e,
camera: i,
zoomPoint: s,
zoomDirectionSet: o,
zoomPointSet: r,
scaleZoomOrientationAtEdges: n
} = this;
if (o && (r || this._updateZoomPoint())) {
if (j.setFromUnitVectors(e, t), n) {
this.getUpDirection(s, M);
let a = Math.max(M.dot(e) - 0.6, 0) / 0.4;
a = v.mapLinear(a, 0, 0.5, 0, 1), a = Math.min(a, 1), i.isOrthographicCamera && (a *= 0.1), j.slerp(_i, 1 - a);
}
ft(s, j, tt), i.updateMatrixWorld(), i.matrixWorld.premultiply(tt), i.matrixWorld.decompose(i.position, i.quaternion, M), this.zoomDirectionSet = !1, this._updateZoomDirection();
}
e.copy(t), i.updateMatrixWorld();
}
_raycast(t) {
const { scene: e, useFallbackPlane: i, fallbackPlane: s } = this, o = t.intersectObject(e)[0] || null;
if (o)
return o;
if (i) {
const r = s;
if (t.ray.intersectPlane(r, M))
return {
point: M.clone(),
distance: t.ray.origin.distanceTo(M)
};
}
return null;
}
// tilt the camera to align with the provided "up" value
_alignCameraUp(t, e = 1) {
const { camera: i, state: s, pivotPoint: o, zoomPoint: r, zoomPointSet: n } = this;
i.updateMatrixWorld(), A.set(0, 0, -1).transformDirection(i.matrixWorld), B.set(-1, 0, 0).transformDirection(i.matrixWorld);
let a = v.mapLinear(1 - Math.abs(A.dot(t)), 0, 0.2, 0, 1);
a = v.clamp(a, 0, 1), e *= a, Qt.crossVectors(t, A), Qt.lerp(B, 1 - e).normalize(), j.setFromUnitVectors(B, Qt), i.quaternion.premultiply(j);
let l = null;
s === et || s === Y ? l = It.copy(o) : n && (l = It.copy(r)), l && (Et.copy(i.matrixWorld).invert(), M.copy(l).applyMatrix4(Et), i.updateMatrixWorld(), M.applyMatrix4(i.matrixWorld), Ot.subVectors(l, M), i.position.add(Ot)), i.updateMatrixWorld();
}
// clamp rotation to the given "up" vector
_clampRotation(t) {
const { camera: e, minAltitude: i, maxAltitude: s, state: o, pivotPoint: r, zoomPoint: n, zoomPointSet: a } = this;
e.updateMatrixWorld(), A.set(0, 0, 1).transformDirection(e.matrixWorld), B.set(1, 0, 0).transformDirection(e.matrixWorld);
let l;
t.dot(A) > 1 - 1e-10 ? l = 0 : (M.crossVectors(t, A), l = Math.sign(M.dot(B)) * t.angleTo(A));
let h;
if (l > s)
h = s;
else if (l < i)
h = i;
else
return;
A.copy(t), j.setFromAxisAngle(B, h), A.applyQuaternion(j).normalize(), M.crossVectors(A, B).normalize(), tt.makeBasis(B, M, A), e.quaternion.setFromRotationMatrix(tt);
let c = null;
o === et || o === Y ? c = It.copy(r) : a && (c = It.copy(n)), c && (Et.copy(e.matrixWorld).invert(), M.copy(c).applyMatrix4(Et), e.updateMatrixWorld(), M.applyMatrix4(e.matrixWorld), Ot.subVectors(c, M), e.position.add(Ot)), e.updateMatrixWorld();
}
}
const xe = /* @__PURE__ */ new O(), ht = /* @__PURE__ */ new O(), N = /* @__PURE__ */ new y(), P = /* @__PURE__ */ new y(), X = /* @__PURE__ */ new y(), k = /* @__PURE__ */ new y(), vi = /* @__PURE__ */ new y(), pt = /* @__PURE__ */ new y(), K = /* @__PURE__ */ new it(), be = /* @__PURE__ */ new y(), ot = /* @__PURE__ */ new y(), D = /* @__PURE__ */ new Ft(), Me = /* @__PURE__ */ new ri(), _t = /* @__PURE__ */ new F(), _e = {}, Ti = 2550;
class Fi extends Pi {
get tilesGroup() {
return console.warn('GlobeControls: "tilesGroup" has been deprecated. Use "ellipsoidGroup", instead.'), this.ellipsoidFrame;
}
get ellipsoidFrame() {
return this.ellipsoidGroup.matrixWorld;
}
get ellipsoidFrameInverse() {
const { ellipsoidGroup: t, ellipsoidFrame: e, _ellipsoidFrameInverse: i } = this;
return t.matrixWorldInverse ? t.matrixWorldInverse : i.copy(e).invert();
}
constructor(t = null, e = null, i = null, s = null) {
super(t, e, i), this.isGlobeControls = !0, this._dragMode = 0, this._rotationMode = 0, this.maxZoom = 0.01, this.nearMargin = 0.25, this.farMargin = 0, this.useFallbackPlane = !1, this.autoAdjustCameraRotation = !1, this.globeInertia = new it(), this.globeInertiaFactor = 0, this.ellipsoid = vt.clone(), this.ellipsoidGroup = new Pt(), this._ellipsoidFrameInverse = new O(), s !== null && this.setTilesRenderer(s);
}
setTilesRenderer(t) {
super.setTilesRenderer(t), t !== null && this.setEllipsoid(t.ellipsoid, t.group);
}
setEllipsoid(t, e) {
this.ellipsoid = t || vt.clone(), this.ellipsoidGroup = e || new Pt();
}
getPivotPoint(t) {
const { camera: e, ellipsoidFrame: i, ellipsoidFrameInverse: s, ellipsoid: o } = this;
return k.set(0, 0, -1).transformDirection(e.matrixWorld), D.origin.copy(e.position), D.direction.copy(k), D.applyMatrix4(s), o.closestPointToRayEstimate(D, P).applyMatrix4(i), (super.getPivotPoint(t) === null || N.subVectors(t, D.origin).dot(D.direction) > N.subVectors(P, D.origin).dot(D.direction)) && t.copy(P), t;
}
// get the vector to the center of the provided globe
getVectorToCenter(t) {
const { ellipsoidFrame: e, camera: i } = this;
return t.setFromMatrixPosition(e).sub(i.position);
}
// get the distance to the center of the globe
getDistanceToCenter() {
return this.getVectorToCenter(P).length();
}
getUpDirection(t, e) {
const { ellipsoidFrame: i, ellipsoidFrameInverse: s, ellipsoid: o } = this;
P.copy(t).applyMatrix4(s), o.getPositionToNormal(P, e), e.transformDirection(i);
}
getCameraUpDirection(t) {
const { ellipsoidFrame: e, ellipsoidFrameInverse: i, ellipsoid: s, camera: o } = this;
o.isOrthographicCamera ? (this._getVirtualOrthoCameraPosition(P), P.applyMatrix4(i), s.getPositionToNormal(P, t), t.transformDirection(e)) : this.getUpDirection(o.position, t);
}
update(t = Math.min(this.clock.getDelta(), 64 / 1e3)) {
if (!this.enabled || !this.camera || t === 0)
return;
const { camera: e, pivotMesh: i } = this;
this._isNearControls() ? this.scaleZoomOrientationAtEdges = this.zoomDelta < 0 : (this.state !== G && this._dragMode !== 1 && this._rotationMode !== 1 && (i.visible = !1), this.scaleZoomOrientationAtEdges = !1);
const s = this.needsUpdate || this._inertiaNeedsUpdate();
super.update(t), this.adjustCamera(e), s && this._isNearControls() && (this.getCameraUpDirection(pt), this._alignCameraUp(pt, 1), this.getCameraUpDirection(pt), this._clampRotation(pt));
}
// Updates the passed camera near and far clip planes to encapsulate the ellipsoid from the
// current position in addition to adjusting the height.
adjustCamera(t) {
super.adjustCamera(t);
const { ellipsoidFrame: e, ellipsoidFrameInverse: i, ellipsoid: s, nearMargin: o, farMargin: r } = this, n = Math.max(...s.radius);
if (t.isPerspectiveCamera) {
const a = P.setFromMatrixPosition(e).sub(t.position).length(), l = o * n, h = v.clamp((a - n) / l, 0, 1), c = v.lerp(1, 1e3, h);
t.near = Math.max(c, a - n - l), N.copy(t.position).applyMatrix4(i), s.getPositionToCartographic(N, _e);
const p = Math.max(s.getPositionElevation(N), Ti), m = s.calculateHorizonDistance(_e.lat, p);
t.far = m + 0.1 + n * r, t.updateProjectionMatrix();
} else {
this._getVirtualOrthoCameraPosition(t.position, t), t.updateMatrixWorld(), xe.copy(t.matrixWorld).invert(), P.setFromMatrixPosition(e).applyMatrix4(xe);
const a = -P.z;
t.near = a - n * (1 + o), t.far = a + 0.1 + n * r, t.position.addScaledVector(k, t.near), t.far -= t.near, t.near = 0, t.updateProjectionMatrix(), t.updateMatrixWorld();
}
}
// resets the "stuck" drag modes
setState(...t) {
super.setState(...t), this._dragMode = 0, this._rotationMode = 0;
}
_updateInertia(t) {
super._updateInertia(t);
const {
globeInertia: e,
enableDamping: i,
dampingFactor: s,
camera: o,
cameraRadius: r,
minDistance: n,
inertiaTargetDistance: a,
ellipsoidFrame: l
} = this;
if (!this.enableDamping || this.inertiaStableFrames > 1) {
this.globeInertiaFactor = 0, this.globeInertia.identity();
return;
}
const h = Math.pow(2, -t / s), c = Math.max(o.near, r, n, a), u = 0.25 * (2 / (2 * 1e3));
if (X.setFromMatrixPosition(l), this.globeInertiaFactor !== 0) {
H(D, P.set(0, 0, -1), o), D.applyMatrix4(o.matrixWorldInverse), D.direction.normalize(), D.recast(-D.direction.dot(D.origin)).at(c / D.direction.z, P), P.applyMatrix4(o.matrixWorld), H(D, N.set(u, u, -1), o), D.applyMatrix4(o.matrixWorldInverse), D.direction.normalize(), D.recast(-D.direction.dot(D.origin)).at(c / D.direction.z, N), N.applyMatrix4(o.matrixWorld), P.sub(X).normalize(), N.sub(X).normalize(), this.globeInertiaFactor *= h;
const d = P.angleTo(N) / t;
(2 * Math.acos(e.w) * this.globeInertiaFactor < d || !i) && (this.globeInertiaFactor = 0, e.identity());
}
this.globeInertiaFactor !== 0 && (e.w === 1 && (e.x !== 0 || e.y !== 0 || e.z !== 0) && (e.w = Math.min(e.w, 1 - 1e-9)), X.setFromMatrixPosition(l), K.identity().slerp(e, this.globeInertiaFactor * t), ft(X, K, ht), o.matrixWorld.premultiply(ht), o.matrixWorld.decompose(o.position, o.quaternion, P));
}
_inertiaNeedsUpdate() {
return super._inertiaNeedsUpdate() || this.globeInertiaFactor !== 0;
}
_updatePosition(t) {
if (this.state === et) {
this._dragMode === 0 && (this._dragMode = this._isNearControls() ? 1 : -1);
const {
raycaster: e,
camera: i,
pivotPoint: s,
pointerTracker: o,
domElement: r,
ellipsoidFrame: n,
ellipsoidFrameInverse: a
} = this, l = N, h = vi;
o.getCenterPoint(_t), dt(_t.x, _t.y, r, _t), H(e, _t, i), e.ray.applyMatrix4(a);
const c = P.copy(s).applyMatrix4(a).length();
if (Me.radius.setScalar(c), !Me.intersectRay(e.ray, P)) {
this.resetState(), this._updateInertia(t);
return;
}
P.applyMatrix4(n), X.setFromMatrixPosition(n), l.subVectors(s, X).normalize(), h.subVectors(P, X).normalize(), K.setFromUnitVectors(h, l), ft(X, K, ht), i.matrixWorld.premultiply(ht), i.matrixWorld.decompose(i.position, i.quaternion, P), o.getMoveDistance() / t < 2 * window.devicePixelRatio ? this.inertiaStableFrames++ : (this.globeInertia.copy(K), this.globeInertiaFactor = 1 / t, this.inertiaStableFrames = 0);
}
}
// disable rotation once we're outside the control transition
_updateRotation(...t) {
this._rotationMode === 1 || this._isNearControls() ? (this._rotationMode = 1, super._updateRotation(...t)) : (this.pivotMesh.visible = !1, this._rotationMode = -1);
}
_updateZoom() {
const { zoomDelta: t, ellipsoid: e, zoomSpeed: i, zoomPoint: s, camera: o, maxZoom: r, state: n } = this;
if (n !== ut && t === 0)
return;
this.rotationInertia.set(0, 0), this.dragInertia.set(0, 0, 0), this.globeInertia.identity(), this.globeInertiaFactor = 0;
const a = v.clamp(v.mapLinear(Math.abs(t), 0, 20, 0, 1), 0, 1);
if (this._isNearControls() || t > 0) {
if (this._updateZoomDirection(), t < 0 && (this.zoomPointSet || this._updateZoomPoint())) {
k.set(0, 0, -1).transformDirection(o.matrixWorld).normalize(), ot.copy(this.up).multiplyScalar(-1), this.getUpDirection(s, be);
const l = v.clamp(v.mapLinear(-be.dot(ot), 1, 0.95, 0, 1), 0, 1), h = 1 - k.dot(ot), c = o.isOrthographicCamera ? 0.05 : 1, p = v.clamp(a * 3, 0, 1), m = Math.min(l * h * c * p, 0.1);
ot.lerpVectors(k, ot, m).normalize(), K.setFromUnitVectors(k, ot), ft(s, K, ht), o.matrixWorld.premultiply(ht), o.matrixWorld.decompose(o.position, o.quaternion, ot), this.zoomDirection.subVectors(s, o.position).normalize();
}
super._updateZoom();
} else if (o.isPerspectiveCamera) {
const l = this._getPerspectiveTransitionDistance(), h = this._getMaxPerspectiveDistance(), c = v.mapLinear(this.getDistanceToCenter(), l, h, 0, 1);
this._tiltTowardsCenter(v.lerp(0, 0.4, c * a)), this._alignCameraUpToNorth(v.lerp(0, 0.2, c * a));
const p = this.getDistanceToCenter() - e.radius.x, m = t * p * i * 25e-4, u = Math.max(m, Math.min(this.getDistanceToCenter() - h, 0));
this.getVectorToCenter(P).normalize(), this.camera.position.addScaledVector(P, u), this.camera.updateMatrixWorld(), this.zoomDelta = 0;
} else {
const l = this._getOrthographicTransitionZoom(), h = this._getMinOrthographicZoom(), c = v.mapLinear(o.zoom, l, h, 0, 1);
this._tiltTowardsCenter(v.lerp(0, 0.4, c * a)), this._alignCameraUpToNorth(v.lerp(0, 0.2, c * a));
const p = this.zoomDelta, m = Math.pow(0.95, Math.abs(p * 0.05)), u = p > 0 ? 1 / Math.abs(m) : m, d = h / o.zoom, x = Math.max(u * i, Math.min(d, 1));
o.zoom = Math.min(r, o.zoom * x), o.updateProjectionMatrix(), this.zoomDelta = 0, this.zoomDirectionSet = !1;
}
}
// tilt the camera to align with north
_alignCameraUpToNorth(t) {
const { ellipsoidFrame: e } = this;
pt.set(0, 0, 1).transformDirection(e), this._alignCameraUp(pt, t);
}
// tilt the camera to look at the center of the globe
_tiltTowardsCenter(t) {
const {
camera: e,
ellipsoidFrame: i
} = this;
k.set(0, 0, -1).transformDirection(e.matrixWorld).normalize(), P.setFromMatrixPosition(i).sub(e.position).normalize(), P.lerp(k, 1 - t).normalize(), K.setFromUnitVectors(k, P), e.quaternion.premultiply(K), e.updateMatrixWorld();
}
// returns the perspective camera transition distance can move to based on globe size and fov
_getPerspectiveTransitionDistance() {
const { camera: t, ellipsoid: e } = this;
if (!t.isPerspectiveCamera)
throw new Error();
const i = Math.max(...e.radius), s = 2 * Math.atan(Math.tan(v.DEG2RAD * t.fov * 0.5) * t.aspect), o = i / Math.tan(v.DEG2RAD * t.fov * 0.5), r = i / Math.tan(s * 0.5);
return Math.max(o, r);
}
// returns the max distance the perspective camera can move to based on globe size and fov
_getMaxPerspectiveDistance() {
const { camera: t, ellipsoid: e } = this;
if (!t.isPerspectiveCamera)
throw new Error();
const i = Math.max(...e.radius), s = 2 * Math.atan(Math.tan(v.DEG2RAD * t.fov * 0.5) * t.aspect), o = i / Math.tan(v.DEG2RAD * t.fov * 0.5), r = i / Math.tan(s * 0.5);
return 2 * Math.max(o, r);
}
// returns the transition threshold for orthographic zoom based on the globe size and camera settings
_getOrthographicTransitionZoom() {
const { camera: t, ellipsoid: e } = this;
if (!t.isOrthographicCamera)
throw new Error();
const i = t.top - t.bottom, s = t.right - t.left, o = Math.max(i, s), n = 2 * Math.max(...e.radius);
return 2 * o / n;
}
// returns the minimum allowed orthographic zoom based on the globe size and camera settings
_getMinOrthographicZoom() {
const { camera: t, ellipsoid: e } = this;
if (!t.isOrthographicCamera)
throw new Error();
const i = t.top - t.bottom, s = t.right - t.left, o = Math.min(i, s), n = 2 * Math.max(...e.radius);
return 0.7 * o / n;
}
// returns the "virtual position" of the orthographic based on where it is and
// where it's looking primarily so we can reasonably position the camera object
// in space and derive a reasonable "up" value.
_getVirtualOrthoCameraPosition(t, e = this.camera) {
const { ellipsoidFrame: i, ellipsoidFrameInverse: s, ellipsoid: o } = this;
if (!e.isOrthographicCamera)
throw new Error();
D.origin.copy(e.position), D.direction.set(0, 0, -1).transformDirection(e.matrixWorld), D.applyMatrix4(s), o.closestPointToRayEstimate(D, N).applyMatrix4(i);
const r = e.top - e.bottom, n = e.right - e.left, a = Math.max(r, n) / e.zoom;
k.set(0, 0, -1).transformDirection(e.matrixWorld);
const l = N.sub(e.position).dot(k);
t.copy(e.position).addScaledVector(k, l - a * 4);
}
_isNearControls() {
const { camera: t } = this;
return t.isPerspectiveCamera ? this.getDistanceToCenter() < this._getPerspectiveTransitionDistance() : t.zoom > this._getOrthographicTransitionZoom();
}
_raycast(t) {
const e = super._raycast(t);
if (e === null) {
const { ellipsoid: i, ellipsoidFrame: s, ellipsoidFrameInverse: o } = this;
D.copy(t.ray).applyMatrix4(o);
const r = i.intersectRay(D, P);
return r !== null ? (r.applyMatrix4(s), {
point: r.clone(),
distance: r.distanceTo(t.ray.origin)
}) : null;
} else
return e;
}
}
const L = /* @__PURE__ */ new y(), nt = /* @__PURE__ */ new y(), rt = /* @__PURE__ */ new we(), wi = /* @__PURE__ */ new y(), Di = /* @__PURE__ */ new y(), Ci = /* @__PURE__ */ new y(), Pe = /* @__PURE__ */ new it(), Si = /* @__PURE__ */ new it();
class Ui extends mt {
get animating() {
return this._alpha !== 0 && this._alpha !== 1;
}
get alpha() {
return this._target === 0 ? 1 - this._alpha : this._alpha;
}
get camera() {
return this._alpha === 0 ? this.perspectiveCamera : this._alpha === 1 ? this.orthographicCamera : this.transitionCamera;
}
get mode() {
return this._target === 0 ? "perspective" : "orthographic";
}
set mode(t) {
if (t === this.mode)
return;
const e = this.camera;
t === "perspective" ? (this._target = 0, this._alpha = 0) : (this._target = 1, this._alpha = 1), this.dispatchEvent({ type: "camera-change", camera: this.camera, prevCamera: e });
}
constructor(t = new Kt(), e = new we()) {
super(), this.perspectiveCamera = t, this.orthographicCamera = e, this.transitionCamera = new Kt(), this.orthographicPositionalZoom = !0, this.orthographicOffset = 50, this.fixedPoint = new y(), this.duration = 200, this.autoSync = !0, this.easeFunction = (i) => i, this._target = 0, this._alpha = 0, this._clock = new Te();
}
toggle() {
this._target = this._target === 1 ? 0 : 1, this._clock.getDelta(), this.dispatchEvent({ type: "toggle" });
}
update(t = Math.min(this._clock.getDelta(), 64 / 1e3)) {
this.autoSync && this.syncCameras();
const { perspectiveCamera: e, orthographicCamera: i, transitionCamera: s, camera: o } = this, r = t * 1e3;
if (this._alpha !== this._target) {
const h = Math.sign(this._target - this._alpha) * r / this.duration;
this._alpha = v.clamp(this._alpha + h, 0, 1), this.dispatchEvent({ type: "change", alpha: this.alpha });
}
const n = o;
let a = null;
this._alpha === 0 ? a = e : this._alpha === 1 ? a = i : (a = s, this._updateTransitionCamera()), n !== a && (a === s && this.dispatchEvent({ type: "transition-start" }), this.dispatchEvent({ type: "camera-change", camera: a, prevCamera: n }), n === s && this.dispatchEvent({ type: "transition-end" }));
}
syncCameras() {
const t = this._getFromCamera(), { perspectiveCamera: e, orthographicCamera: i, transitionCamera: s, fixedPoint: o } = this;
if (L.set(0, 0, -1).transformDirection(t.matrixWorld).normalize(), t.isPerspectiveCamera) {
if (this.orthographicPositionalZoom)
i.position.copy(e.position).addScaledVector(L, -this.orthographicOffset), i.rotation.copy(e.rotation), i.updateMatrixWorld();
else {
const l = nt.subVectors(o, i.position).dot(L), h = nt.subVectors(o, e.position).dot(L);
nt.copy(e.position).addScaledVector(L, h), i.rotation.copy(e.rotation), i.position.copy(nt).addScaledVector(L, -l), i.updateMatrixWorld();
}
const r = Math.abs(nt.subVectors(e.position, o).dot(L)), n = 2 * Math.tan(v.DEG2RAD * e.fov * 0.5) * r, a = i.top - i.bottom;
i.zoom = a / n, i.updateProjectionMatrix();
} else {
const r = Math.abs(nt.subVectors(i.position, o).dot(L)), a = (i.top - i.bottom) / i.zoom * 0.5 / Math.tan(v.DEG2RAD * e.fov * 0.5);
e.rotation.copy(i.rotation), e.position.copy(i.position).addScaledVector(L, r).addScaledVector(L, -a), e.updateMatrixWorld(), this.orthographicPositionalZoom && (i.position.copy(e.position).addScaledVector(L, -this.orthographicOffset), i.updateMatrixWorld());
}
s.position.copy(e.position), s.rotation.copy(e.rotation);
}
_getTransitionDirection() {
return Math.sign(this._target - this._alpha);
}
_getToCamera() {
const t = this._getTransitionDirection();
return t === 0 ? this._target === 0 ? this.perspectiveCamera : this.orthographicCamera : t > 0 ? this.orthographicCamera : this.perspectiveCamera;
}
_getFromCamera() {
const t = this._getTransitionDirection();
return t === 0 ? this._target === 0 ? this.perspectiveCamera : this.orthographicCamera : t > 0 ? this.perspectiveCamera : this.orthographicCamera;
}
_updateTransitionCamera() {
const { perspectiveCamera: t, orthographicCamera: e, transitionCamera: i, fixedPoint: s } = this, o = this.easeFunction(this._alpha);
L.set(0, 0, -1).transformDirection(e.matrixWorld).normalize(), rt.copy(e), rt.position.addScaledVector(L, e.near), e.far -= e.near, e.near = 0, L.set(0, 0, -1).transformDirection(t.matrixWorld).normalize();
const r = Math.abs(nt.subVectors(t.position, s).dot(L)), n = 2 * Math.tan(v.DEG2RAD * t.fov * 0.5) * r, a = Si.slerpQuaternions(t.quaternion, rt.quaternion, o), l = v.lerp(t.fov, 1, o), h = n * 0.5 / Math.tan(v.DEG2RAD * l * 0.5), c = Ci.copy(rt.position).sub(s).applyQuaternion(Pe.copy(rt.quaternion).invert()), p = Di.copy(t.position).sub(s).applyQuaternion(Pe.copy(t.quaternion).invert()), m = wi.lerpVectors(p, c, o);
m.z -= Math.abs(m.z) - h;
const u = -(p.z - m.z), d = -(c.z - m.z), x = v.lerp(u + t.near, d + rt.near, o), E = v.lerp(u + t.far, d + rt.far, o), _ = Math.max(E, 0) - Math.max(x, 0);
i.aspect = t.aspect, i.fov = l, i.near = Math.max(x, _ * 1e-5), i.far = E, i.position.copy(m).applyQuaternion(a).add(s), i.quaternion.copy(a), i.updateProjectionMatrix(), i.updateMatrixWorld();
}
}
export {
De as B,
li as C,
Pi as E,
Fi as G,
Se as I,
Ce as P,
Ai as T,
Ui as a
};
//# sourceMappingURL=CameraTransitionManager-SvgW6Pmv.js.map