3d-tiles-renderer
Version:
https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/specification
324 lines (323 loc) • 16.4 kB
JavaScript
import { W as ot, d as Tt } from "./constants-z3YLhXg0.js";
import { MathUtils as D, Spherical as mt, Vector3 as u, Matrix4 as R, Sphere as Et, Ray as dt, Euler as St, Box3 as yt, Plane as wt, TextureUtils as zt } from "three";
import { estimateBytesUsed as Ft } from "three/examples/jsm/utils/BufferGeometryUtils.js";
const b = /* @__PURE__ */ new mt(), et = /* @__PURE__ */ new u(), _t = {};
function xt(c) {
const { x: t, y: i, z: o } = c;
c.x = o, c.y = t, c.z = i;
}
function Ct(c) {
const { x: t, y: i, z: o } = c;
c.z = t, c.x = i, c.y = o;
}
function gt(c) {
return -(c - Math.PI / 2);
}
function J(c) {
return -c + Math.PI / 2;
}
function Rt(c, t, i = {}) {
return b.theta = t, b.phi = J(c), et.setFromSpherical(b), b.setFromVector3(et), i.lat = gt(b.phi), i.lon = b.theta, i;
}
function st(c, t = "E", i = "W") {
const o = c < 0 ? i : t;
c = Math.abs(c);
const e = ~~c, s = (c - e) * 60, n = ~~s, l = ~~((s - n) * 60);
return `${e}° ${n}' ${l}" ${o}`;
}
function bt(c, t, i = !1) {
const o = Rt(c, t, _t);
let e, s;
return i ? (e = `${(D.RAD2DEG * o.lat).toFixed(4)}°`, s = `${(D.RAD2DEG * o.lon).toFixed(4)}°`) : (e = st(D.RAD2DEG * o.lat, "N", "S"), s = st(D.RAD2DEG * o.lon, "E", "W")), `${e} ${s}`;
}
const Ut = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
latitudeToSphericalPhi: J,
sphericalPhiToLatitude: gt,
swapToGeoFrame: xt,
swapToThreeFrame: Ct,
toLatLonString: bt
}, Symbol.toStringTag, { value: "Module" })), nt = /* @__PURE__ */ new mt(), z = /* @__PURE__ */ new u(), x = /* @__PURE__ */ new u(), X = /* @__PURE__ */ new u(), P = /* @__PURE__ */ new R(), S = /* @__PURE__ */ new R(), rt = /* @__PURE__ */ new R(), Y = /* @__PURE__ */ new Et(), g = /* @__PURE__ */ new St(), at = /* @__PURE__ */ new u(), lt = /* @__PURE__ */ new u(), ct = /* @__PURE__ */ new u(), _ = /* @__PURE__ */ new u(), O = /* @__PURE__ */ new dt(), vt = 1e-12, At = 0.1, q = 0, ht = 1, U = 2;
class Mt {
constructor(t = 1, i = 1, o = 1) {
this.name = "", this.radius = new u(t, i, o);
}
intersectRay(t, i) {
return P.makeScale(...this.radius).invert(), Y.center.set(0, 0, 0), Y.radius = 1, O.copy(t).applyMatrix4(P), O.intersectSphere(Y, i) ? (P.makeScale(...this.radius), i.applyMatrix4(P), i) : null;
}
// returns a frame with Z indicating altitude, Y pointing north, X pointing east
getEastNorthUpFrame(t, i, o, e) {
return o.isMatrix4 && (e = o, o = 0, console.warn('Ellipsoid: The signature for "getEastNorthUpFrame" has changed.')), this.getEastNorthUpAxes(t, i, at, lt, ct), this.getCartographicToPosition(t, i, o, _), e.makeBasis(at, lt, ct).setPosition(_);
}
// returns a frame with z indicating altitude and az, el, roll rotation within that frame
// - azimuth: measured off of true north, increasing towards "east" (z-axis)
// - elevation: measured off of the horizon, increasing towards sky (x-axis)
// - roll: rotation around northern axis (y-axis)
getOrientedEastNorthUpFrame(t, i, o, e, s, n, a) {
return this.getObjectFrame(t, i, o, e, s, n, a, q);
}
// returns a frame similar to the ENU frame but rotated to match three.js object and camera conventions
// OBJECT_FRAME: oriented such that "+Y" is up and "+Z" is forward.
// CAMERA_FRAME: oriented such that "+Y" is up and "-Z" is forward.
getObjectFrame(t, i, o, e, s, n, a, l = U) {
return this.getEastNorthUpFrame(t, i, o, P), g.set(s, n, -e, "ZXY"), a.makeRotationFromEuler(g).premultiply(P), l === ht ? (g.set(Math.PI / 2, 0, 0, "XYZ"), S.makeRotationFromEuler(g), a.multiply(S)) : l === U && (g.set(-Math.PI / 2, 0, Math.PI, "XYZ"), S.makeRotationFromEuler(g), a.multiply(S)), a;
}
getCartographicFromObjectFrame(t, i, o = U) {
return o === ht ? (g.set(-Math.PI / 2, 0, 0, "XYZ"), S.makeRotationFromEuler(g).premultiply(t)) : o === U ? (g.set(-Math.PI / 2, 0, Math.PI, "XYZ"), S.makeRotationFromEuler(g).premultiply(t)) : S.copy(t), _.setFromMatrixPosition(S), this.getPositionToCartographic(_, i), this.getEastNorthUpFrame(i.lat, i.lon, 0, P).invert(), S.premultiply(P), g.setFromRotationMatrix(S, "ZXY"), i.azimuth = -g.z, i.elevation = g.x, i.roll = g.y, i;
}
getEastNorthUpAxes(t, i, o, e, s, n = _) {
this.getCartographicToPosition(t, i, 0, n), this.getCartographicToNormal(t, i, s), o.set(-n.y, n.x, 0).normalize(), e.crossVectors(s, o).normalize();
}
// azimuth: measured off of true north, increasing towards "east"
// elevation: measured off of the horizon, increasing towards sky
// roll: rotation around northern axis
getAzElRollFromRotationMatrix(t, i, o, e, s = q) {
return console.warn('Ellipsoid: "getAzElRollFromRotationMatrix" is deprecated. Use "getCartographicFromObjectFrame", instead.'), this.getCartographicToPosition(t, i, 0, _), rt.copy(o).setPosition(_), this.getCartographicFromObjectFrame(rt, e, s), delete e.height, delete e.lat, delete e.lon, e;
}
getRotationMatrixFromAzElRoll(t, i, o, e, s, n, a = q) {
return console.warn('Ellipsoid: "getRotationMatrixFromAzElRoll" function has been deprecated. Use "getObjectFrame", instead.'), this.getObjectFrame(t, i, 0, o, e, s, n, a), n.setPosition(0, 0, 0), n;
}
getFrame(t, i, o, e, s, n, a, l = q) {
return console.warn('Ellipsoid: "getFrame" function has been deprecated. Use "getObjectFrame", instead.'), this.getObjectFrame(t, i, n, o, e, s, a, l);
}
getCartographicToPosition(t, i, o, e) {
this.getCartographicToNormal(t, i, z);
const s = this.radius;
x.copy(z), x.x *= s.x ** 2, x.y *= s.y ** 2, x.z *= s.z ** 2;
const n = Math.sqrt(z.dot(x));
return x.divideScalar(n), e.copy(x).addScaledVector(z, o);
}
getPositionToCartographic(t, i) {
this.getPositionToSurfacePoint(t, x), this.getPositionToNormal(t, z);
const o = X.subVectors(t, x);
return i.lon = Math.atan2(z.y, z.x), i.lat = Math.asin(z.z), i.height = Math.sign(o.dot(t)) * o.length(), i;
}
getCartographicToNormal(t, i, o) {
return nt.set(1, J(t), i), o.setFromSpherical(nt).normalize(), xt(o), o;
}
getPositionToNormal(t, i) {
const o = this.radius;
return i.copy(t), i.x /= o.x ** 2, i.y /= o.y ** 2, i.z /= o.z ** 2, i.normalize(), i;
}
getPositionToSurfacePoint(t, i) {
const o = this.radius, e = 1 / o.x ** 2, s = 1 / o.y ** 2, n = 1 / o.z ** 2, a = t.x * t.x * e, l = t.y * t.y * s, p = t.z * t.z * n, h = a + l + p, w = Math.sqrt(1 / h), f = x.copy(t).multiplyScalar(w);
if (h < At)
return isFinite(w) ? i.copy(f) : null;
const E = X.set(
f.x * e * 2,
f.y * s * 2,
f.z * n * 2
);
let m = (1 - w) * t.length() / (0.5 * E.length()), y = 0, k, K, v, A, N, L, V, W, Q, tt, it;
do {
m -= y, v = 1 / (1 + m * e), A = 1 / (1 + m * s), N = 1 / (1 + m * n), L = v * v, V = A * A, W = N * N, Q = L * v, tt = V * A, it = W * N, k = a * L + l * V + p * W - 1, K = a * Q * e + l * tt * s + p * it * n;
const Pt = -2 * K;
y = k / Pt;
} while (Math.abs(k) > vt);
return i.set(
t.x * v,
t.y * A,
t.z * N
);
}
calculateHorizonDistance(t, i) {
const o = this.calculateEffectiveRadius(t);
return Math.sqrt(2 * o * i + i ** 2);
}
calculateEffectiveRadius(t) {
const i = this.radius.x, e = 1 - this.radius.z ** 2 / i ** 2, s = t * D.DEG2RAD, n = Math.sin(s) ** 2;
return i / Math.sqrt(1 - e * n);
}
getPositionElevation(t) {
this.getPositionToSurfacePoint(t, x);
const i = X.subVectors(t, x);
return Math.sign(i.dot(t)) * i.length();
}
// Returns an estimate of the closest point on the ellipsoid to the ray. Returns
// the surface intersection if they collide.
closestPointToRayEstimate(t, i) {
return this.intersectRay(t, i) ? i : (P.makeScale(...this.radius).invert(), O.copy(t).applyMatrix4(P), x.set(0, 0, 0), O.closestPointToPoint(x, i).normalize(), P.makeScale(...this.radius), i.applyMatrix4(P));
}
copy(t) {
return this.radius.copy(t.radius), this;
}
clone() {
return new this.constructor().copy(this);
}
}
const Nt = new Mt(ot, ot, Tt);
Nt.name = "WGS84 Earth";
const j = /* @__PURE__ */ new u(), $ = /* @__PURE__ */ new u(), M = /* @__PURE__ */ new u(), G = /* @__PURE__ */ new dt();
class jt {
constructor(t = new yt(), i = new R()) {
this.box = t.clone(), this.transform = i.clone(), this.inverseTransform = new R(), this.points = new Array(8).fill().map(() => new u()), this.planes = new Array(6).fill().map(() => new wt());
}
copy(t) {
return this.box.copy(t.box), this.transform.copy(t.transform), this.update(), this;
}
clone() {
return new this.constructor().copy(this);
}
/**
* Clamps the given point within the bounds of this OBB
* @param {Vector3} point
* @param {Vector3} result
* @returns {Vector3}
*/
clampPoint(t, i) {
return i.copy(t).applyMatrix4(this.inverseTransform).clamp(this.box.min, this.box.max).applyMatrix4(this.transform);
}
/**
* Returns the distance from any edge of this OBB to the specified point.
* If the point lies inside of this box, the distance will be 0.
* @param {Vector3} point
* @returns {number}
*/
distanceToPoint(t) {
return this.clampPoint(t, M).distanceTo(t);
}
containsPoint(t) {
return M.copy(t).applyMatrix4(this.inverseTransform), this.box.containsPoint(M);
}
// returns boolean indicating whether the ray has intersected the obb
intersectsRay(t) {
return G.copy(t).applyMatrix4(this.inverseTransform), G.intersectsBox(this.box);
}
// Sets "target" equal to the intersection point.
// Returns "null" if no intersection found.
intersectRay(t, i) {
return G.copy(t).applyMatrix4(this.inverseTransform), G.intersectBox(this.box, i) ? (i.applyMatrix4(this.transform), i) : null;
}
update() {
const { points: t, inverseTransform: i, transform: o, box: e } = this;
i.copy(o).invert();
const { min: s, max: n } = e;
let a = 0;
for (let l = -1; l <= 1; l += 2)
for (let p = -1; p <= 1; p += 2)
for (let h = -1; h <= 1; h += 2)
t[a].set(
l < 0 ? s.x : n.x,
p < 0 ? s.y : n.y,
h < 0 ? s.z : n.z
).applyMatrix4(o), a++;
this.updatePlanes();
}
updatePlanes() {
j.copy(this.box.min).applyMatrix4(this.transform), $.copy(this.box.max).applyMatrix4(this.transform), M.set(0, 0, 1).transformDirection(this.transform), this.planes[0].setFromNormalAndCoplanarPoint(M, j), this.planes[1].setFromNormalAndCoplanarPoint(M, $).negate(), M.set(0, 1, 0).transformDirection(this.transform), this.planes[2].setFromNormalAndCoplanarPoint(M, j), this.planes[3].setFromNormalAndCoplanarPoint(M, $).negate(), M.set(1, 0, 0).transformDirection(this.transform), this.planes[4].setFromNormalAndCoplanarPoint(M, j), this.planes[5].setFromNormalAndCoplanarPoint(M, $).negate();
}
intersectsSphere(t) {
return this.clampPoint(t.center, M), M.distanceToSquared(t.center) <= t.radius * t.radius;
}
intersectsFrustum(t) {
return this._intersectsPlaneShape(t.planes, t.points);
}
intersectsOBB(t) {
return this._intersectsPlaneShape(t.planes, t.points);
}
// takes a series of 6 planes that define and enclosed shape and the 8 points that lie at the corners
// of that shape to determine whether the OBB is intersected with.
_intersectsPlaneShape(t, i) {
const o = this.points, e = this.planes;
for (let s = 0; s < 6; s++) {
const n = t[s];
let a = -1 / 0;
for (let l = 0; l < 8; l++) {
const p = o[l], h = n.distanceToPoint(p);
a = a < h ? h : a;
}
if (a < 0)
return !1;
}
for (let s = 0; s < 6; s++) {
const n = e[s];
let a = -1 / 0;
for (let l = 0; l < 8; l++) {
const p = i[l], h = n.distanceToPoint(p);
a = a < h ? h : a;
}
if (a < 0)
return !1;
}
return !0;
}
}
const Z = 1e-13, I = Math.PI, H = I / 2, B = /* @__PURE__ */ new u(), C = /* @__PURE__ */ new u(), T = /* @__PURE__ */ new u(), r = /* @__PURE__ */ new u(), d = /* @__PURE__ */ new R(), Bt = /* @__PURE__ */ new yt(), pt = /* @__PURE__ */ new R();
function F(c, t) {
t.radius = Math.max(t.radius, c.distanceToSquared(t.center));
}
function ut(c) {
return c.x !== c.y;
}
class $t extends Mt {
constructor(t = 1, i = 1, o = 1, e = -H, s = H, n = 0, a = 2 * I, l = 0, p = 0) {
super(t, i, o), this.latStart = e, this.latEnd = s, this.lonStart = n, this.lonEnd = a, this.heightStart = l, this.heightEnd = p;
}
getBoundingBox(t, i) {
ut(this.radius) && console.warn("EllipsoidRegion: Triaxial ellipsoids are not supported.");
const {
latStart: o,
latEnd: e,
lonStart: s,
lonEnd: n,
heightStart: a,
heightEnd: l
} = this, p = (o + e) * 0.5, h = (s + n) * 0.5, w = o > 0, f = e < 0;
let E;
w ? E = o : f ? E = e : E = 0;
const { min: m, max: y } = t;
m.setScalar(1 / 0), y.setScalar(-1 / 0), n - s <= I ? (this.getCartographicToNormal(p, h, T), C.set(0, 0, 1), B.crossVectors(C, T).normalize(), C.crossVectors(T, B).normalize(), i.makeBasis(B, C, T), d.copy(i).invert(), this.getCartographicToPosition(E, s, l, r).applyMatrix4(d), y.x = Math.abs(r.x), m.x = -y.x, this.getCartographicToPosition(e, s, l, r).applyMatrix4(d), y.y = r.y, this.getCartographicToPosition(e, h, l, r).applyMatrix4(d), y.y = Math.max(r.y, y.y), this.getCartographicToPosition(o, s, l, r).applyMatrix4(d), m.y = r.y, this.getCartographicToPosition(o, h, l, r).applyMatrix4(d), m.y = Math.min(r.y, m.y), this.getCartographicToPosition(p, h, l, r).applyMatrix4(d), y.z = r.z, this.getCartographicToPosition(o, s, a, r).applyMatrix4(d), m.z = r.z, this.getCartographicToPosition(e, s, a, r).applyMatrix4(d), m.z = Math.min(r.z, m.z)) : (this.getCartographicToPosition(E, h, l, T), T.z = 0, T.length() < 1e-10 ? T.set(1, 0, 0) : T.normalize(), C.set(0, 0, 1), B.crossVectors(T, C).normalize(), i.makeBasis(B, C, T), d.copy(i).invert(), this.getCartographicToPosition(E, h + H, l, r).applyMatrix4(d), y.x = Math.abs(r.x), m.x = -y.x, this.getCartographicToPosition(e, 0, f ? a : l, r).applyMatrix4(d), y.y = r.y, this.getCartographicToPosition(o, 0, w ? a : l, r).applyMatrix4(d), m.y = r.y, this.getCartographicToPosition(E, h, l, r).applyMatrix4(d), y.z = r.z, this.getCartographicToPosition(E, n, l, r).applyMatrix4(d), m.z = r.z), t.getCenter(r), t.min.sub(r).multiplyScalar(1 + Z), t.max.sub(r).multiplyScalar(1 + Z), r.applyMatrix4(i), i.setPosition(r);
}
getBoundingSphere(t) {
ut(this.radius) && console.warn("EllipsoidRegion: Triaxial ellipsoids are not supported."), this.getBoundingBox(Bt, pt), t.center.setFromMatrixPosition(pt), t.radius = 0;
const {
latStart: i,
latEnd: o,
lonStart: e,
lonEnd: s,
heightStart: n,
heightEnd: a
} = this, l = (i + o) * 0.5, p = (e + s) * 0.5, h = i > 0, w = o < 0;
let f;
h ? f = i : w ? f = o : f = 0, this.getCartographicToPosition(f, e, a, r), F(r, t), this.getCartographicToPosition(o, e, a, r), F(r, t), this.getCartographicToPosition(o, p, a, r), F(r, t), this.getCartographicToPosition(i, e, a, r), F(r, t), this.getCartographicToPosition(i, p, a, r), F(r, t), this.getCartographicToPosition(l, p, a, r), F(r, t), this.getCartographicToPosition(i, e, n, r), F(r, t), s - e > I && (this.getCartographicToPosition(f, p + I, a, r), F(r, t)), t.radius = Math.sqrt(t.radius) * (1 + Z);
}
}
function ft(c) {
if (!c)
return 0;
const { format: t, type: i, image: o } = c, { width: e, height: s } = o;
let n = zt.getByteLength(e, s, t, i);
return n *= c.generateMipmaps ? 4 / 3 : 1, n;
}
function Dt(c) {
const t = /* @__PURE__ */ new Set();
let i = 0;
return c.traverse((o) => {
if (o.geometry && !t.has(o.geometry) && (i += Ft(o.geometry), t.add(o.geometry)), o.material) {
const e = o.material;
for (const s in e) {
const n = e[s];
n && n.isTexture && !t.has(n) && (i += ft(n), t.add(n));
}
}
}), i;
}
const Gt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
estimateBytesUsed: Dt,
getTextureByteLength: ft
}, Symbol.toStringTag, { value: "Module" }));
export {
ht as C,
q as E,
Ut as G,
Gt as M,
U as O,
Nt as W,
Mt as a,
$t as b,
jt as c,
Dt as e,
ft as g
};
//# sourceMappingURL=MemoryUtils-R1TfIs9h.js.map