spacemap 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -1
- package/dist/spacemap.iife.js +387 -303
- package/dist/spacemap.js +387 -303
- package/index.d.ts +28 -8
- package/index.js +2201 -833
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/*! spacemap SDK — https://spacemap.co — Mozilla Public License 2.0. Bundles MIT and ISC libraries: THIRD_PARTY_NOTICES.txt in the spacemap npm package. */
|
|
2
|
-
import { ACESFilmicToneMapping, AdditiveBlending, AmbientLight, ArrowHelper, BackSide, Box3, BufferAttribute, BufferGeometry, CanvasTexture, Color, CubeTexture, CustomBlending, DataArrayTexture, DataTexture, DepthTexture, DirectionalLight, DoubleSide, Euler, Float32BufferAttribute, FloatType, FrontSide, Group, HalfFloatType, InstancedBufferAttribute, InstancedMesh, Line, LineBasicMaterial, LineLoop, LinearFilter, LinearMipmapLinearFilter, LinearSRGBColorSpace, MathUtils, Matrix4, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshStandardMaterial, NoBlending, NoColorSpace, NormalBlending, OneFactor, OneMinusSrcAlphaFactor, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, PerspectiveCamera, PlaneGeometry, PointLight, Points, PointsMaterial, Quaternion, RGBAFormat, RGFormat, RawShaderMaterial, Raycaster, RedFormat, RepeatWrapping, RingGeometry, SRGBColorSpace, Scene, ShaderChunk, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry, ShapeUtils, SphereGeometry, Sprite, SpriteMaterial, TOUCH, Texture, TextureLoader, Uint16BufferAttribute, UnsignedByteType, Vector2, Vector3, Vector4, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
2
|
+
import { ACESFilmicToneMapping, AdditiveBlending, AmbientLight, ArrowHelper, BackSide, Box3, BufferAttribute, BufferGeometry, CanvasTexture, ClampToEdgeWrapping, Color, CubeTexture, CustomBlending, DataArrayTexture, DataTexture, DataUtils, DepthTexture, DirectionalLight, DoubleSide, Euler, Float32BufferAttribute, FloatType, FrontSide, Group, HalfFloatType, InstancedBufferAttribute, InstancedMesh, Line, LineBasicMaterial, LineLoop, LinearFilter, LinearMipmapLinearFilter, LinearSRGBColorSpace, MathUtils, Matrix4, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshStandardMaterial, NoBlending, NoColorSpace, NormalBlending, OneFactor, OneMinusSrcAlphaFactor, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, PerspectiveCamera, PlaneGeometry, PointLight, Points, PointsMaterial, Quaternion, RGBAFormat, RGFormat, RawShaderMaterial, Raycaster, RedFormat, RepeatWrapping, RingGeometry, SRGBColorSpace, Scene, ShaderChunk, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry, ShapeUtils, SphereGeometry, Sprite, SpriteMaterial, TOUCH, Texture, TextureLoader, Uint16BufferAttribute, UnsignedByteType, Vector2, Vector3, Vector4, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
3
|
+
import { RoomEnvironment } from "three/addons/environments/RoomEnvironment.js";
|
|
3
4
|
import { CSS2DObject } from "three/addons/renderers/CSS2DRenderer.js";
|
|
4
5
|
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
|
5
6
|
import { MeshoptDecoder } from "three/addons/libs/meshopt_decoder.module.js";
|
|
@@ -8,7 +9,6 @@ import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
|
|
|
8
9
|
import { RenderPass } from "three/addons/postprocessing/RenderPass.js";
|
|
9
10
|
import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js";
|
|
10
11
|
import { OutputPass } from "three/addons/postprocessing/OutputPass.js";
|
|
11
|
-
import { RoomEnvironment } from "three/addons/environments/RoomEnvironment.js";
|
|
12
12
|
import { FullScreenQuad } from "three/addons/postprocessing/Pass.js";
|
|
13
13
|
|
|
14
14
|
//#region src/lib/host.ts
|
|
@@ -110,7 +110,7 @@ var noop = () => {};
|
|
|
110
110
|
function run_all(arr) {
|
|
111
111
|
for (var i = 0; i < arr.length; i++) arr[i]();
|
|
112
112
|
}
|
|
113
|
-
function deferred() {
|
|
113
|
+
function deferred$1() {
|
|
114
114
|
var resolve;
|
|
115
115
|
var reject;
|
|
116
116
|
return {
|
|
@@ -902,7 +902,7 @@ var Batch = class Batch {
|
|
|
902
902
|
this.#discard_callbacks.add(fn);
|
|
903
903
|
}
|
|
904
904
|
settled() {
|
|
905
|
-
return (this.#deferred ??= deferred()).promise;
|
|
905
|
+
return (this.#deferred ??= deferred$1()).promise;
|
|
906
906
|
}
|
|
907
907
|
static ensure() {
|
|
908
908
|
if (current_batch === null) {
|
|
@@ -2986,6 +2986,9 @@ var versions = {};
|
|
|
2986
2986
|
function setDataVersions(v) {
|
|
2987
2987
|
versions = v ?? {};
|
|
2988
2988
|
}
|
|
2989
|
+
function getDataVersions() {
|
|
2990
|
+
return versions;
|
|
2991
|
+
}
|
|
2989
2992
|
function versionedUrl(path, cls) {
|
|
2990
2993
|
return buildVersionedUrl(dataBase(), path, cls);
|
|
2991
2994
|
}
|
|
@@ -5314,13 +5317,392 @@ function equatorialToScene(xEq, yEq, zEq, out) {
|
|
|
5314
5317
|
}
|
|
5315
5318
|
|
|
5316
5319
|
//#endregion
|
|
5317
|
-
//#region src/lib/
|
|
5318
|
-
var
|
|
5319
|
-
var
|
|
5320
|
-
var SIN_EPS$4 = Math.sin(EARTH_OBLIQUITY_DEG * DEG2RAD$9);
|
|
5320
|
+
//#region src/lib/time/jd.ts
|
|
5321
|
+
var J2000_JD$1 = 2451545;
|
|
5322
|
+
var SECONDS_PER_DAY$2 = 86400;
|
|
5321
5323
|
var JD_UNIX_EPOCH$1 = 2440587.5;
|
|
5324
|
+
var MS_PER_DAY = 864e5;
|
|
5325
|
+
function unixMsToJD(ms) {
|
|
5326
|
+
return ms / MS_PER_DAY + JD_UNIX_EPOCH$1;
|
|
5327
|
+
}
|
|
5328
|
+
function dateToJD(date) {
|
|
5329
|
+
return unixMsToJD(date.getTime());
|
|
5330
|
+
}
|
|
5331
|
+
function jdToDate(jd) {
|
|
5332
|
+
return new Date((jd - JD_UNIX_EPOCH$1) * MS_PER_DAY);
|
|
5333
|
+
}
|
|
5334
|
+
var TT_MINUS_TAI = 32.184;
|
|
5335
|
+
var LEAP_SECONDS = [
|
|
5336
|
+
[2441317.5, 10],
|
|
5337
|
+
[2441499.5, 11],
|
|
5338
|
+
[2441683.5, 12],
|
|
5339
|
+
[2442048.5, 13],
|
|
5340
|
+
[2442413.5, 14],
|
|
5341
|
+
[2442778.5, 15],
|
|
5342
|
+
[2443144.5, 16],
|
|
5343
|
+
[2443509.5, 17],
|
|
5344
|
+
[2443874.5, 18],
|
|
5345
|
+
[2444239.5, 19],
|
|
5346
|
+
[2444786.5, 20],
|
|
5347
|
+
[2445151.5, 21],
|
|
5348
|
+
[2445516.5, 22],
|
|
5349
|
+
[2446247.5, 23],
|
|
5350
|
+
[2447161.5, 24],
|
|
5351
|
+
[2447892.5, 25],
|
|
5352
|
+
[2448257.5, 26],
|
|
5353
|
+
[2448804.5, 27],
|
|
5354
|
+
[2449169.5, 28],
|
|
5355
|
+
[2449534.5, 29],
|
|
5356
|
+
[2450083.5, 30],
|
|
5357
|
+
[2450630.5, 31],
|
|
5358
|
+
[2451179.5, 32],
|
|
5359
|
+
[2453736.5, 33],
|
|
5360
|
+
[2454832.5, 34],
|
|
5361
|
+
[2456109.5, 35],
|
|
5362
|
+
[2457204.5, 36],
|
|
5363
|
+
[2457754.5, 37]
|
|
5364
|
+
];
|
|
5365
|
+
function taiMinusUtc(jdUtc) {
|
|
5366
|
+
for (let k = LEAP_SECONDS.length - 1; k >= 0; k--) if (jdUtc >= LEAP_SECONDS[k][0]) return LEAP_SECONDS[k][1];
|
|
5367
|
+
return LEAP_SECONDS[0][1] - 1;
|
|
5368
|
+
}
|
|
5369
|
+
function tdbMinusTt(jd) {
|
|
5370
|
+
const m = 6.239996 + 1.99096871e-7 * (jd - J2000_JD$1) * SECONDS_PER_DAY$2;
|
|
5371
|
+
return .001657 * Math.sin(m + .01671 * Math.sin(m));
|
|
5372
|
+
}
|
|
5373
|
+
function utcToTdb(jd) {
|
|
5374
|
+
if (!Number.isFinite(jd)) return jd;
|
|
5375
|
+
const tt = jd + (taiMinusUtc(jd) + TT_MINUS_TAI) / SECONDS_PER_DAY$2;
|
|
5376
|
+
return tt + tdbMinusTt(tt) / SECONDS_PER_DAY$2;
|
|
5377
|
+
}
|
|
5378
|
+
function tdbToUtc(jd) {
|
|
5379
|
+
if (!Number.isFinite(jd)) return jd;
|
|
5380
|
+
const tt = jd - tdbMinusTt(jd) / SECONDS_PER_DAY$2;
|
|
5381
|
+
return tt - (taiMinusUtc(tt - (taiMinusUtc(tt) + TT_MINUS_TAI) / SECONDS_PER_DAY$2) + TT_MINUS_TAI) / SECONDS_PER_DAY$2;
|
|
5382
|
+
}
|
|
5383
|
+
function jdToEt(jd) {
|
|
5384
|
+
return (utcToTdb(jd) - J2000_JD$1) * SECONDS_PER_DAY$2;
|
|
5385
|
+
}
|
|
5386
|
+
function etToTdbJd(et) {
|
|
5387
|
+
return J2000_JD$1 + et / SECONDS_PER_DAY$2;
|
|
5388
|
+
}
|
|
5389
|
+
function tdbJdToEt(jd) {
|
|
5390
|
+
return (jd - J2000_JD$1) * SECONDS_PER_DAY$2;
|
|
5391
|
+
}
|
|
5392
|
+
|
|
5393
|
+
//#endregion
|
|
5394
|
+
//#region src/lib/math/orbit/teme.ts
|
|
5395
|
+
var DEG$10 = Math.PI / 180;
|
|
5396
|
+
var ARCSEC = DEG$10 / 3600;
|
|
5397
|
+
var NUT_UNIT = 1e-4 * ARCSEC;
|
|
5398
|
+
var REUSE_DAYS = .01;
|
|
5399
|
+
var NUTATION = [
|
|
5400
|
+
[
|
|
5401
|
+
0,
|
|
5402
|
+
0,
|
|
5403
|
+
0,
|
|
5404
|
+
0,
|
|
5405
|
+
1,
|
|
5406
|
+
-171996,
|
|
5407
|
+
-174.2,
|
|
5408
|
+
92025,
|
|
5409
|
+
8.9
|
|
5410
|
+
],
|
|
5411
|
+
[
|
|
5412
|
+
0,
|
|
5413
|
+
0,
|
|
5414
|
+
2,
|
|
5415
|
+
-2,
|
|
5416
|
+
2,
|
|
5417
|
+
-13187,
|
|
5418
|
+
-1.6,
|
|
5419
|
+
5736,
|
|
5420
|
+
-3.1
|
|
5421
|
+
],
|
|
5422
|
+
[
|
|
5423
|
+
0,
|
|
5424
|
+
0,
|
|
5425
|
+
2,
|
|
5426
|
+
0,
|
|
5427
|
+
2,
|
|
5428
|
+
-2274,
|
|
5429
|
+
-.2,
|
|
5430
|
+
977,
|
|
5431
|
+
-.5
|
|
5432
|
+
],
|
|
5433
|
+
[
|
|
5434
|
+
0,
|
|
5435
|
+
0,
|
|
5436
|
+
0,
|
|
5437
|
+
0,
|
|
5438
|
+
2,
|
|
5439
|
+
2062,
|
|
5440
|
+
.2,
|
|
5441
|
+
-895,
|
|
5442
|
+
.5
|
|
5443
|
+
],
|
|
5444
|
+
[
|
|
5445
|
+
0,
|
|
5446
|
+
1,
|
|
5447
|
+
0,
|
|
5448
|
+
0,
|
|
5449
|
+
0,
|
|
5450
|
+
1426,
|
|
5451
|
+
-3.4,
|
|
5452
|
+
54,
|
|
5453
|
+
-.1
|
|
5454
|
+
],
|
|
5455
|
+
[
|
|
5456
|
+
1,
|
|
5457
|
+
0,
|
|
5458
|
+
0,
|
|
5459
|
+
0,
|
|
5460
|
+
0,
|
|
5461
|
+
712,
|
|
5462
|
+
.1,
|
|
5463
|
+
-7,
|
|
5464
|
+
0
|
|
5465
|
+
],
|
|
5466
|
+
[
|
|
5467
|
+
0,
|
|
5468
|
+
1,
|
|
5469
|
+
2,
|
|
5470
|
+
-2,
|
|
5471
|
+
2,
|
|
5472
|
+
-517,
|
|
5473
|
+
1.2,
|
|
5474
|
+
224,
|
|
5475
|
+
-.6
|
|
5476
|
+
],
|
|
5477
|
+
[
|
|
5478
|
+
0,
|
|
5479
|
+
0,
|
|
5480
|
+
2,
|
|
5481
|
+
0,
|
|
5482
|
+
1,
|
|
5483
|
+
-386,
|
|
5484
|
+
-.4,
|
|
5485
|
+
200,
|
|
5486
|
+
0
|
|
5487
|
+
],
|
|
5488
|
+
[
|
|
5489
|
+
1,
|
|
5490
|
+
0,
|
|
5491
|
+
2,
|
|
5492
|
+
0,
|
|
5493
|
+
2,
|
|
5494
|
+
-301,
|
|
5495
|
+
0,
|
|
5496
|
+
129,
|
|
5497
|
+
-.1
|
|
5498
|
+
],
|
|
5499
|
+
[
|
|
5500
|
+
0,
|
|
5501
|
+
-1,
|
|
5502
|
+
2,
|
|
5503
|
+
-2,
|
|
5504
|
+
2,
|
|
5505
|
+
217,
|
|
5506
|
+
-.5,
|
|
5507
|
+
-95,
|
|
5508
|
+
.3
|
|
5509
|
+
],
|
|
5510
|
+
[
|
|
5511
|
+
1,
|
|
5512
|
+
0,
|
|
5513
|
+
0,
|
|
5514
|
+
-2,
|
|
5515
|
+
0,
|
|
5516
|
+
-158,
|
|
5517
|
+
0,
|
|
5518
|
+
-1,
|
|
5519
|
+
0
|
|
5520
|
+
],
|
|
5521
|
+
[
|
|
5522
|
+
0,
|
|
5523
|
+
0,
|
|
5524
|
+
2,
|
|
5525
|
+
-2,
|
|
5526
|
+
1,
|
|
5527
|
+
129,
|
|
5528
|
+
.1,
|
|
5529
|
+
-70,
|
|
5530
|
+
0
|
|
5531
|
+
],
|
|
5532
|
+
[
|
|
5533
|
+
-1,
|
|
5534
|
+
0,
|
|
5535
|
+
2,
|
|
5536
|
+
0,
|
|
5537
|
+
2,
|
|
5538
|
+
123,
|
|
5539
|
+
0,
|
|
5540
|
+
-53,
|
|
5541
|
+
0
|
|
5542
|
+
],
|
|
5543
|
+
[
|
|
5544
|
+
1,
|
|
5545
|
+
0,
|
|
5546
|
+
0,
|
|
5547
|
+
0,
|
|
5548
|
+
1,
|
|
5549
|
+
63,
|
|
5550
|
+
.1,
|
|
5551
|
+
-33,
|
|
5552
|
+
0
|
|
5553
|
+
],
|
|
5554
|
+
[
|
|
5555
|
+
0,
|
|
5556
|
+
0,
|
|
5557
|
+
0,
|
|
5558
|
+
2,
|
|
5559
|
+
0,
|
|
5560
|
+
63,
|
|
5561
|
+
0,
|
|
5562
|
+
-2,
|
|
5563
|
+
0
|
|
5564
|
+
],
|
|
5565
|
+
[
|
|
5566
|
+
-1,
|
|
5567
|
+
0,
|
|
5568
|
+
2,
|
|
5569
|
+
2,
|
|
5570
|
+
2,
|
|
5571
|
+
-59,
|
|
5572
|
+
0,
|
|
5573
|
+
26,
|
|
5574
|
+
0
|
|
5575
|
+
],
|
|
5576
|
+
[
|
|
5577
|
+
-1,
|
|
5578
|
+
0,
|
|
5579
|
+
0,
|
|
5580
|
+
0,
|
|
5581
|
+
1,
|
|
5582
|
+
-58,
|
|
5583
|
+
-.1,
|
|
5584
|
+
32,
|
|
5585
|
+
0
|
|
5586
|
+
],
|
|
5587
|
+
[
|
|
5588
|
+
1,
|
|
5589
|
+
0,
|
|
5590
|
+
2,
|
|
5591
|
+
0,
|
|
5592
|
+
1,
|
|
5593
|
+
-51,
|
|
5594
|
+
0,
|
|
5595
|
+
27,
|
|
5596
|
+
0
|
|
5597
|
+
]
|
|
5598
|
+
];
|
|
5599
|
+
function mul(a, b) {
|
|
5600
|
+
const out = new Array(9);
|
|
5601
|
+
for (let r = 0; r < 3; r++) for (let c = 0; c < 3; c++) out[3 * r + c] = a[3 * r] * b[c] + a[3 * r + 1] * b[3 + c] + a[3 * r + 2] * b[6 + c];
|
|
5602
|
+
return out;
|
|
5603
|
+
}
|
|
5604
|
+
function rx(a) {
|
|
5605
|
+
const c = Math.cos(a);
|
|
5606
|
+
const s = Math.sin(a);
|
|
5607
|
+
return [
|
|
5608
|
+
1,
|
|
5609
|
+
0,
|
|
5610
|
+
0,
|
|
5611
|
+
0,
|
|
5612
|
+
c,
|
|
5613
|
+
s,
|
|
5614
|
+
0,
|
|
5615
|
+
-s,
|
|
5616
|
+
c
|
|
5617
|
+
];
|
|
5618
|
+
}
|
|
5619
|
+
function ry(a) {
|
|
5620
|
+
const c = Math.cos(a);
|
|
5621
|
+
const s = Math.sin(a);
|
|
5622
|
+
return [
|
|
5623
|
+
c,
|
|
5624
|
+
0,
|
|
5625
|
+
-s,
|
|
5626
|
+
0,
|
|
5627
|
+
1,
|
|
5628
|
+
0,
|
|
5629
|
+
s,
|
|
5630
|
+
0,
|
|
5631
|
+
c
|
|
5632
|
+
];
|
|
5633
|
+
}
|
|
5634
|
+
function rz(a) {
|
|
5635
|
+
const c = Math.cos(a);
|
|
5636
|
+
const s = Math.sin(a);
|
|
5637
|
+
return [
|
|
5638
|
+
c,
|
|
5639
|
+
s,
|
|
5640
|
+
0,
|
|
5641
|
+
-s,
|
|
5642
|
+
c,
|
|
5643
|
+
0,
|
|
5644
|
+
0,
|
|
5645
|
+
0,
|
|
5646
|
+
1
|
|
5647
|
+
];
|
|
5648
|
+
}
|
|
5649
|
+
function temeToEclipticAt(jd) {
|
|
5650
|
+
const T = (jd - J2000_JD$1) / 36525;
|
|
5651
|
+
const zeta = (2306.2181 * T + .30188 * T * T + .017998 * T ** 3) * ARCSEC;
|
|
5652
|
+
const theta = (2004.3109 * T - .42665 * T * T - .041833 * T ** 3) * ARCSEC;
|
|
5653
|
+
const z = (2306.2181 * T + 1.09468 * T * T + .018203 * T ** 3) * ARCSEC;
|
|
5654
|
+
const l = 134.96298139 + 477198.8673981 * T + .0086972 * T * T;
|
|
5655
|
+
const lp = 357.52772333 + 35999.05034 * T - 1603e-7 * T * T;
|
|
5656
|
+
const F = 93.27191028 + 483202.0175381 * T - .0036825 * T * T;
|
|
5657
|
+
const D = 297.85036306 + 445267.11148 * T - .0019142 * T * T;
|
|
5658
|
+
const om = 125.04452222 - 1934.1362608 * T + .0020708 * T * T;
|
|
5659
|
+
let dpsi = 0;
|
|
5660
|
+
let deps = 0;
|
|
5661
|
+
for (const [kl, klp, kF, kD, kOm, a, b, c, d] of NUTATION) {
|
|
5662
|
+
const arg = (kl * l + klp * lp + kF * F + kD * D + kOm * om) * DEG$10;
|
|
5663
|
+
dpsi += (a + b * T) * Math.sin(arg);
|
|
5664
|
+
deps += (c + d * T) * Math.cos(arg);
|
|
5665
|
+
}
|
|
5666
|
+
dpsi *= NUT_UNIT;
|
|
5667
|
+
deps *= NUT_UNIT;
|
|
5668
|
+
const epsMean = (84381.448 - 46.815 * T - 59e-5 * T * T + .001813 * T ** 3) * ARCSEC;
|
|
5669
|
+
const eqEquinoxes = dpsi * Math.cos(epsMean);
|
|
5670
|
+
const toJ2000 = mul(mul(mul(mul(rz(zeta), ry(-theta)), rz(z)), mul(mul(rx(-epsMean), rz(dpsi)), rx(epsMean + deps))), rz(-eqEquinoxes));
|
|
5671
|
+
return mul(rx(EARTH_OBLIQUITY_DEG * DEG$10), toJ2000);
|
|
5672
|
+
}
|
|
5673
|
+
var cachedJd = NaN;
|
|
5674
|
+
var cached = [
|
|
5675
|
+
1,
|
|
5676
|
+
0,
|
|
5677
|
+
0,
|
|
5678
|
+
0,
|
|
5679
|
+
1,
|
|
5680
|
+
0,
|
|
5681
|
+
0,
|
|
5682
|
+
0,
|
|
5683
|
+
1
|
|
5684
|
+
];
|
|
5685
|
+
function temeToEclipticMatrix(jd) {
|
|
5686
|
+
if (!(Math.abs(jd - cachedJd) <= REUSE_DAYS)) {
|
|
5687
|
+
cached = temeToEclipticAt(jd);
|
|
5688
|
+
cachedJd = jd;
|
|
5689
|
+
}
|
|
5690
|
+
return cached;
|
|
5691
|
+
}
|
|
5692
|
+
function temeToEcliptic(x, y, z, jd) {
|
|
5693
|
+
const m = temeToEclipticMatrix(jd);
|
|
5694
|
+
return [
|
|
5695
|
+
m[0] * x + m[1] * y + m[2] * z,
|
|
5696
|
+
m[3] * x + m[4] * y + m[5] * z,
|
|
5697
|
+
m[6] * x + m[7] * y + m[8] * z
|
|
5698
|
+
];
|
|
5699
|
+
}
|
|
5700
|
+
|
|
5701
|
+
//#endregion
|
|
5702
|
+
//#region src/lib/math/orbit/sgp4.ts
|
|
5703
|
+
var JD_UNIX_EPOCH = 2440587.5;
|
|
5322
5704
|
function jdToIso(jd) {
|
|
5323
|
-
return (/* @__PURE__ */ new Date((jd - JD_UNIX_EPOCH
|
|
5705
|
+
return (/* @__PURE__ */ new Date((jd - JD_UNIX_EPOCH) * 864e5)).toISOString();
|
|
5324
5706
|
}
|
|
5325
5707
|
function buildSatrec(inputs, name) {
|
|
5326
5708
|
const satrec = json2satrec({
|
|
@@ -5358,25 +5740,19 @@ function sgp4PositionTEME(satrec, jd) {
|
|
|
5358
5740
|
z
|
|
5359
5741
|
];
|
|
5360
5742
|
}
|
|
5361
|
-
function temeKmToThreeJS(x, y, z) {
|
|
5743
|
+
function temeKmToThreeJS(x, y, z, jd) {
|
|
5362
5744
|
const scale = 10 / AU_KM;
|
|
5363
|
-
const
|
|
5364
|
-
let ys = y * scale;
|
|
5365
|
-
let zs = z * scale;
|
|
5366
|
-
const yEcl = ys * COS_EPS$4 + zs * SIN_EPS$4;
|
|
5367
|
-
const zEcl = -ys * SIN_EPS$4 + zs * COS_EPS$4;
|
|
5368
|
-
ys = yEcl;
|
|
5369
|
-
zs = zEcl;
|
|
5745
|
+
const [xe, ye, ze] = temeToEcliptic(x, y, z, jd);
|
|
5370
5746
|
return [
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
-
|
|
5747
|
+
xe * scale,
|
|
5748
|
+
ze * scale,
|
|
5749
|
+
-ye * scale
|
|
5374
5750
|
];
|
|
5375
5751
|
}
|
|
5376
5752
|
function sgp4PositionScene(satrec, jd) {
|
|
5377
5753
|
const teme = sgp4PositionTEME(satrec, jd);
|
|
5378
5754
|
if (!teme) return null;
|
|
5379
|
-
return temeKmToThreeJS(teme[0], teme[1], teme[2]);
|
|
5755
|
+
return temeKmToThreeJS(teme[0], teme[1], teme[2], jd);
|
|
5380
5756
|
}
|
|
5381
5757
|
|
|
5382
5758
|
//#endregion
|
|
@@ -5445,32 +5821,109 @@ function yieldToMain() {
|
|
|
5445
5821
|
}
|
|
5446
5822
|
|
|
5447
5823
|
//#endregion
|
|
5448
|
-
//#region src/lib/
|
|
5449
|
-
var
|
|
5450
|
-
var
|
|
5451
|
-
var
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5824
|
+
//#region src/lib/math/orbit/position.ts
|
|
5825
|
+
var DEG2RAD$8 = Math.PI / 180;
|
|
5826
|
+
var COS_EPS$2 = Math.cos(EARTH_OBLIQUITY_DEG * DEG2RAD$8);
|
|
5827
|
+
var SIN_EPS$2 = Math.sin(EARTH_OBLIQUITY_DEG * DEG2RAD$8);
|
|
5828
|
+
function orbitalToThreeJS(xOrb, yOrb, w, i, om, equatorial = false) {
|
|
5829
|
+
const cosW = Math.cos(w * DEG2RAD$8);
|
|
5830
|
+
const sinW = Math.sin(w * DEG2RAD$8);
|
|
5831
|
+
const cosI = Math.cos(i * DEG2RAD$8);
|
|
5832
|
+
const sinI = Math.sin(i * DEG2RAD$8);
|
|
5833
|
+
const cosOm = Math.cos(om * DEG2RAD$8);
|
|
5834
|
+
const sinOm = Math.sin(om * DEG2RAD$8);
|
|
5835
|
+
const x = (cosOm * cosW - sinOm * sinW * cosI) * xOrb + (-cosOm * sinW - sinOm * cosW * cosI) * yOrb;
|
|
5836
|
+
let y = (sinOm * cosW + cosOm * sinW * cosI) * xOrb + (-sinOm * sinW + cosOm * cosW * cosI) * yOrb;
|
|
5837
|
+
let z = sinW * sinI * xOrb + cosW * sinI * yOrb;
|
|
5838
|
+
if (equatorial) {
|
|
5839
|
+
const yEcl = y * COS_EPS$2 + z * SIN_EPS$2;
|
|
5840
|
+
const zEcl = -y * SIN_EPS$2 + z * COS_EPS$2;
|
|
5841
|
+
y = yEcl;
|
|
5842
|
+
z = zEcl;
|
|
5843
|
+
}
|
|
5844
|
+
return [
|
|
5845
|
+
x * 10,
|
|
5846
|
+
z * 10,
|
|
5847
|
+
-y * 10
|
|
5848
|
+
];
|
|
5455
5849
|
}
|
|
5456
|
-
function
|
|
5457
|
-
return
|
|
5850
|
+
function elementsJd(el, jd) {
|
|
5851
|
+
return el.equatorial ? jd : utcToTdb(jd);
|
|
5458
5852
|
}
|
|
5459
|
-
function
|
|
5460
|
-
return
|
|
5853
|
+
function clockJd(el, t) {
|
|
5854
|
+
return el.equatorial ? t : tdbToUtc(t);
|
|
5461
5855
|
}
|
|
5462
|
-
function
|
|
5463
|
-
return (
|
|
5856
|
+
function propagateOrbitAngles(el, jd) {
|
|
5857
|
+
return anglesAt(el, elementsJd(el, jd));
|
|
5464
5858
|
}
|
|
5465
|
-
function
|
|
5466
|
-
|
|
5859
|
+
function anglesAt(el, t) {
|
|
5860
|
+
const { omDot, wDot, om, w, epoch } = el;
|
|
5861
|
+
if (!omDot && !wDot) return el;
|
|
5862
|
+
const dt = t - epoch;
|
|
5863
|
+
return {
|
|
5864
|
+
...el,
|
|
5865
|
+
om: omDot ? om + omDot * dt : om,
|
|
5866
|
+
w: wDot ? w + wDot * dt : w
|
|
5867
|
+
};
|
|
5868
|
+
}
|
|
5869
|
+
function orbitalElementsToPositionJD(el, jd) {
|
|
5870
|
+
const { a, e, i, ma, n, epoch } = el;
|
|
5871
|
+
if (!isFinite(a) || !isFinite(e) || !isFinite(ma) || !isFinite(n)) {
|
|
5872
|
+
console.warn(`NaN in orbital elements: a=${a} e=${e} ma=${ma} n=${n}`);
|
|
5873
|
+
return null;
|
|
5874
|
+
}
|
|
5875
|
+
const t = elementsJd(el, jd);
|
|
5876
|
+
const M = (ma + n * (t - epoch)) * DEG2RAD$8;
|
|
5877
|
+
const { om: omPropagated, w: wPropagated } = anglesAt(el, t);
|
|
5878
|
+
let nu;
|
|
5879
|
+
let r;
|
|
5880
|
+
if (e < 1 || a > 0) {
|
|
5881
|
+
const eClamped = Math.min(e, .9999999);
|
|
5882
|
+
const E = solveKepler(M, eClamped);
|
|
5883
|
+
const sinNu = Math.sqrt(1 - eClamped * eClamped) * Math.sin(E) / (1 - eClamped * Math.cos(E));
|
|
5884
|
+
const cosNu = (Math.cos(E) - eClamped) / (1 - eClamped * Math.cos(E));
|
|
5885
|
+
nu = Math.atan2(sinNu, cosNu);
|
|
5886
|
+
r = a * (1 - eClamped * Math.cos(E));
|
|
5887
|
+
} else {
|
|
5888
|
+
const H = solveKeplerHyperbolic(M, e);
|
|
5889
|
+
if (!isFinite(H)) {
|
|
5890
|
+
console.warn(`solveKeplerHyperbolic overflow: M=${M} e=${e}`);
|
|
5891
|
+
return null;
|
|
5892
|
+
}
|
|
5893
|
+
const denom = e * Math.cosh(H) - 1;
|
|
5894
|
+
if (Math.abs(denom) < 1e-15) {
|
|
5895
|
+
console.warn(`Hyperbolic denom near zero: H=${H} e=${e} denom=${denom}`);
|
|
5896
|
+
return null;
|
|
5897
|
+
}
|
|
5898
|
+
const sinNu = Math.sqrt(e * e - 1) * Math.sinh(H) / denom;
|
|
5899
|
+
const cosNu = (e - Math.cosh(H)) / denom;
|
|
5900
|
+
nu = Math.atan2(sinNu, cosNu);
|
|
5901
|
+
r = a * (1 - e * Math.cosh(H));
|
|
5902
|
+
}
|
|
5903
|
+
const xOrb = r * Math.cos(nu);
|
|
5904
|
+
const yOrb = r * Math.sin(nu);
|
|
5905
|
+
if (!isFinite(xOrb) || !isFinite(yOrb)) {
|
|
5906
|
+
console.warn(`Non-finite orbital position: r=${r} nu=${nu} xOrb=${xOrb} yOrb=${yOrb} a=${a} e=${e}`);
|
|
5907
|
+
return null;
|
|
5908
|
+
}
|
|
5909
|
+
return orbitalToThreeJS(xOrb, yOrb, wPropagated, i, omPropagated, el.equatorial);
|
|
5910
|
+
}
|
|
5911
|
+
function parabolicToPositionJD(el, jd) {
|
|
5912
|
+
const { q, tp, i, om, w } = el;
|
|
5913
|
+
if (q == null || tp == null || !isFinite(q) || !isFinite(tp)) return null;
|
|
5914
|
+
const result = solveBarker(q, tp, elementsJd(el, jd));
|
|
5915
|
+
if (!result) return null;
|
|
5916
|
+
const xOrb = result.r * Math.cos(result.nu);
|
|
5917
|
+
const yOrb = result.r * Math.sin(result.nu);
|
|
5918
|
+
if (!isFinite(xOrb) || !isFinite(yOrb)) return null;
|
|
5919
|
+
return orbitalToThreeJS(xOrb, yOrb, w, i, om, el.equatorial);
|
|
5467
5920
|
}
|
|
5468
5921
|
|
|
5469
5922
|
//#endregion
|
|
5470
5923
|
//#region src/lib/math/orbit/soa.ts
|
|
5471
|
-
var DEG2RAD$
|
|
5472
|
-
var COS_EPS$
|
|
5473
|
-
var SIN_EPS$
|
|
5924
|
+
var DEG2RAD$7 = Math.PI / 180;
|
|
5925
|
+
var COS_EPS$1 = Math.cos(EARTH_OBLIQUITY_DEG * DEG2RAD$7);
|
|
5926
|
+
var SIN_EPS$1 = Math.sin(EARTH_OBLIQUITY_DEG * DEG2RAD$7);
|
|
5474
5927
|
var KM_TO_SCENE = 10 / AU_KM;
|
|
5475
5928
|
var KIND_SKIP = 0;
|
|
5476
5929
|
var KIND_KEPLER = 1;
|
|
@@ -5529,8 +5982,10 @@ async function packBodiesSliced(bodies, skip, applyFlagFilter = false) {
|
|
|
5529
5982
|
}
|
|
5530
5983
|
if (!packRowInto(cols, idx, bodies[idx], skip)) continue;
|
|
5531
5984
|
const d = bodies[idx].data;
|
|
5532
|
-
|
|
5533
|
-
|
|
5985
|
+
const s = clockJd(d, d.validityStart);
|
|
5986
|
+
const e = clockJd(d, d.validityEnd);
|
|
5987
|
+
if (s < start) start = s;
|
|
5988
|
+
if (e > end) end = e;
|
|
5534
5989
|
}
|
|
5535
5990
|
cols.validityStart = start === Infinity ? -Infinity : start;
|
|
5536
5991
|
cols.validityEnd = end === -Infinity ? Infinity : end;
|
|
@@ -5870,6 +6325,11 @@ var TYPE_COLOR_PROBE = "#d5cfe7";
|
|
|
5870
6325
|
var SUN_ID = "naif-10";
|
|
5871
6326
|
var EARTH_ID = "naif-399";
|
|
5872
6327
|
var SSB_ID = "naif-0";
|
|
6328
|
+
function naifId(objectId) {
|
|
6329
|
+
if (!objectId.startsWith("naif-")) return null;
|
|
6330
|
+
const value = Number.parseInt(objectId.slice(5), 10);
|
|
6331
|
+
return Number.isFinite(value) ? value : null;
|
|
6332
|
+
}
|
|
5873
6333
|
function dominantPlanetId(id) {
|
|
5874
6334
|
const m = /^naif-([1-9])$/.exec(id);
|
|
5875
6335
|
return m ? `naif-${m[1]}99` : null;
|
|
@@ -5937,10 +6397,6 @@ function resolveBodyColor(data) {
|
|
|
5937
6397
|
}
|
|
5938
6398
|
return DEFAULT_BODY_COLOR;
|
|
5939
6399
|
}
|
|
5940
|
-
var UNKNOWN_SURFACE_COLOR = "#6b6b6b";
|
|
5941
|
-
function bodyMeshColor(data) {
|
|
5942
|
-
return data.color ?? UNKNOWN_SURFACE_COLOR;
|
|
5943
|
-
}
|
|
5944
6400
|
|
|
5945
6401
|
//#endregion
|
|
5946
6402
|
//#region src/lib/math/orbit/partition.ts
|
|
@@ -6202,6 +6658,8 @@ var MinorBucket = class {
|
|
|
6202
6658
|
keys: new Float64Array(counts[b]).fill(NO_KEY)
|
|
6203
6659
|
});
|
|
6204
6660
|
}
|
|
6661
|
+
const clockStarts = this.chunks.map((chunk) => tdbToUtc(chunk.validityStart));
|
|
6662
|
+
const clockEnds = this.chunks.map((chunk) => tdbToUtc(chunk.validityEnd));
|
|
6205
6663
|
const starts = new Array(k).fill(Infinity);
|
|
6206
6664
|
const ends = new Array(k).fill(-Infinity);
|
|
6207
6665
|
const writeIdx = new Array(k).fill(0);
|
|
@@ -6222,8 +6680,11 @@ var MinorBucket = class {
|
|
|
6222
6680
|
const key = rowKey(cols, i);
|
|
6223
6681
|
g.keys[outIdx] = key;
|
|
6224
6682
|
if (fillOrbitColumnRow(cols, i, g.cols, outIdx, key, skip)) {
|
|
6225
|
-
|
|
6226
|
-
|
|
6683
|
+
const tle = g.cols.equatorial[outIdx] === 1;
|
|
6684
|
+
const start = tle ? cols.validityStart : clockStarts[c];
|
|
6685
|
+
const end = tle ? cols.validityEnd : clockEnds[c];
|
|
6686
|
+
if (start < starts[b]) starts[b] = start;
|
|
6687
|
+
if (end > ends[b]) ends[b] = end;
|
|
6227
6688
|
}
|
|
6228
6689
|
if (g.colors && tmp) {
|
|
6229
6690
|
const data = materializeBodyData(cols, i, this.labels, this.parentIdType);
|
|
@@ -6618,17 +7079,23 @@ async function fetchWithTimeout(input, init = {}, timeoutMs = BOOT_FETCH_TIMEOUT
|
|
|
6618
7079
|
|
|
6619
7080
|
//#endregion
|
|
6620
7081
|
//#region src/lib/fetch/systems-global.ts
|
|
6621
|
-
var
|
|
7082
|
+
var phases = /* @__PURE__ */ new Map();
|
|
6622
7083
|
var gmKm3s2 = /* @__PURE__ */ new Map();
|
|
6623
7084
|
var loadPromise$1 = null;
|
|
6624
7085
|
function loadSystemsGlobal() {
|
|
6625
7086
|
if (loadPromise$1) return loadPromise$1;
|
|
6626
7087
|
const p = (async () => {
|
|
6627
7088
|
const r = await fetchWithTimeout(`${dataBase()}/v1/systems/global.json`);
|
|
6628
|
-
if (!r.ok)
|
|
7089
|
+
if (!r.ok) throw new Error(`systems/global.json: ${r.status}`);
|
|
6629
7090
|
const raw = await r.json();
|
|
6630
7091
|
if (raw.gm) for (const [k, v] of Object.entries(raw.gm)) gmKm3s2.set(parseInt(k, 10), v);
|
|
6631
|
-
if (raw.nut_prec_angles) for (const [k, v] of Object.entries(raw.nut_prec_angles))
|
|
7092
|
+
if (raw.nut_prec_angles) for (const [k, v] of Object.entries(raw.nut_prec_angles)) {
|
|
7093
|
+
const phaseDegree = raw.nut_prec_phase_degree?.[k] ?? 1;
|
|
7094
|
+
phases.set(parseInt(k, 10), {
|
|
7095
|
+
angles: v,
|
|
7096
|
+
phaseDegree
|
|
7097
|
+
});
|
|
7098
|
+
}
|
|
6632
7099
|
})();
|
|
6633
7100
|
p.catch(() => {
|
|
6634
7101
|
if (loadPromise$1 === p) loadPromise$1 = null;
|
|
@@ -6636,11 +7103,14 @@ function loadSystemsGlobal() {
|
|
|
6636
7103
|
loadPromise$1 = p;
|
|
6637
7104
|
return p;
|
|
6638
7105
|
}
|
|
6639
|
-
function
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
return
|
|
7106
|
+
function nutPrecFor(id, sums) {
|
|
7107
|
+
const naif = naifId(id);
|
|
7108
|
+
if (naif === null || !sums) return void 0;
|
|
7109
|
+
const owned = phases.get(naif >= 100 ? Math.trunc(naif / 100) : naif);
|
|
7110
|
+
return owned && {
|
|
7111
|
+
...sums,
|
|
7112
|
+
...owned
|
|
7113
|
+
};
|
|
6644
7114
|
}
|
|
6645
7115
|
function getGmKm3s2(naifId) {
|
|
6646
7116
|
return gmKm3s2.get(naifId);
|
|
@@ -7433,7 +7903,7 @@ function parseProbesPayload(buffer, startJd, endJd, float64Coeffs) {
|
|
|
7433
7903
|
const probeCount = view.getUint32(24, true);
|
|
7434
7904
|
const subchunkDays = view.getFloat32(28, true);
|
|
7435
7905
|
const subchunkS = subchunkDays * SECONDS_PER_DAY$2;
|
|
7436
|
-
const chunkStartEt =
|
|
7906
|
+
const chunkStartEt = tdbJdToEt(startJd);
|
|
7437
7907
|
const probes = [];
|
|
7438
7908
|
let offset = HEADER_SIZE$2;
|
|
7439
7909
|
for (let p = 0; p < probeCount; p++) {
|
|
@@ -7558,11 +8028,12 @@ function findSegmentIndex(starts, ends, jd) {
|
|
|
7558
8028
|
return jd < ends[lo] ? lo : -1;
|
|
7559
8029
|
}
|
|
7560
8030
|
function chebyshevPositionKm(body, jd) {
|
|
7561
|
-
const
|
|
8031
|
+
const tdb = utcToTdb(jd);
|
|
8032
|
+
const idx = findSegmentIndex(body.startJds, body.endJds, tdb);
|
|
7562
8033
|
if (idx < 0) return null;
|
|
7563
8034
|
const start = body.startJds[idx];
|
|
7564
8035
|
const end = body.endJds[idx];
|
|
7565
|
-
const tau = 2 * (
|
|
8036
|
+
const tau = 2 * (tdb - start) / (end - start) - 1;
|
|
7566
8037
|
const N = body.coeffsPerAxis;
|
|
7567
8038
|
const coeffs = body.coeffs;
|
|
7568
8039
|
const base = idx * 3 * N;
|
|
@@ -7599,11 +8070,12 @@ function chebyshevPositionScene(body, jd) {
|
|
|
7599
8070
|
];
|
|
7600
8071
|
}
|
|
7601
8072
|
function chebyshevStateKm(body, jd) {
|
|
7602
|
-
const
|
|
8073
|
+
const tdb = utcToTdb(jd);
|
|
8074
|
+
const idx = findSegmentIndex(body.startJds, body.endJds, tdb);
|
|
7603
8075
|
if (idx < 0) return null;
|
|
7604
8076
|
const start = body.startJds[idx];
|
|
7605
8077
|
const end = body.endJds[idx];
|
|
7606
|
-
const tau = 2 * (
|
|
8078
|
+
const tau = 2 * (tdb - start) / (end - start) - 1;
|
|
7607
8079
|
const dTauDt = 2 / (end - start);
|
|
7608
8080
|
const N = body.coeffsPerAxis;
|
|
7609
8081
|
const coeffs = body.coeffs;
|
|
@@ -7651,7 +8123,7 @@ function chebyshevStateKm(body, jd) {
|
|
|
7651
8123
|
|
|
7652
8124
|
//#endregion
|
|
7653
8125
|
//#region src/lib/math/orbit/state.ts
|
|
7654
|
-
var DEG2RAD$
|
|
8126
|
+
var DEG2RAD$6 = Math.PI / 180;
|
|
7655
8127
|
var RAD2DEG$1 = 180 / Math.PI;
|
|
7656
8128
|
var SEC_PER_DAY = 86400;
|
|
7657
8129
|
var AU_PER_DAY_TO_KM_PER_SEC = AU_KM / SEC_PER_DAY;
|
|
@@ -7920,7 +8392,7 @@ var RAD2DEG = 180 / Math.PI;
|
|
|
7920
8392
|
function keplerPureElements(sub, subStartEt, muKm3S2) {
|
|
7921
8393
|
if (muKm3S2 <= 0) return null;
|
|
7922
8394
|
const nRadS = Math.sqrt(muKm3S2 / (sub.aKm * sub.aKm * sub.aKm));
|
|
7923
|
-
const epoch =
|
|
8395
|
+
const epoch = etToTdbJd(subStartEt + sub.tAnchorOffsetS);
|
|
7924
8396
|
return {
|
|
7925
8397
|
a: sub.aKm / AU_KM,
|
|
7926
8398
|
e: sub.e,
|
|
@@ -7934,7 +8406,7 @@ function keplerPureElements(sub, subStartEt, muKm3S2) {
|
|
|
7934
8406
|
};
|
|
7935
8407
|
}
|
|
7936
8408
|
function keplerDriftElements(sub, subStartEt) {
|
|
7937
|
-
const epoch =
|
|
8409
|
+
const epoch = etToTdbJd(subStartEt + sub.tAnchorOffsetS);
|
|
7938
8410
|
return {
|
|
7939
8411
|
a: sub.aKm / AU_KM,
|
|
7940
8412
|
e: sub.e,
|
|
@@ -7962,7 +8434,7 @@ function chebyshevElements(probe, jd, muKm3S2) {
|
|
|
7962
8434
|
state.velocity[0] * KM_DAY_TO_AU_DAY,
|
|
7963
8435
|
state.velocity[1] * KM_DAY_TO_AU_DAY,
|
|
7964
8436
|
state.velocity[2] * KM_DAY_TO_AU_DAY
|
|
7965
|
-
], muAuDay2, jd);
|
|
8437
|
+
], muAuDay2, utcToTdb(jd));
|
|
7966
8438
|
}
|
|
7967
8439
|
function probeOsculatingElements(probe, jd, muKm3S2) {
|
|
7968
8440
|
const idx = findSubChunkIndex(probe, jdToEt(jd));
|
|
@@ -8351,7 +8823,7 @@ function chebyshevOsculatingElements(body, parentId, jd, origin) {
|
|
|
8351
8823
|
(state.velocity[0] - (from?.velocity[0] ?? 0)) * KM_DAY_TO_AU_DAY,
|
|
8352
8824
|
(state.velocity[1] - (from?.velocity[1] ?? 0)) * KM_DAY_TO_AU_DAY,
|
|
8353
8825
|
(state.velocity[2] - (from?.velocity[2] ?? 0)) * KM_DAY_TO_AU_DAY
|
|
8354
|
-
], muAuDay2, jd);
|
|
8826
|
+
], muAuDay2, utcToTdb(jd));
|
|
8355
8827
|
}
|
|
8356
8828
|
function chebyshevHelioElements(body, jd, sun) {
|
|
8357
8829
|
if (!sun || body.parentId !== SSB_NAIF_ID || body.naifId === SUN_NAIF_ID) return null;
|
|
@@ -8845,7 +9317,7 @@ function isChebyshev(zoom) {
|
|
|
8845
9317
|
return zoom.shape === "chunked";
|
|
8846
9318
|
}
|
|
8847
9319
|
function chunkIndexForJd(zone, jd) {
|
|
8848
|
-
const idx = Math.floor((jd - zone.start_jd) / zone.chunk_days);
|
|
9320
|
+
const idx = Math.floor((utcToTdb(jd) - zone.start_jd) / zone.chunk_days);
|
|
8849
9321
|
return Math.max(0, Math.min(zone.chunks - 1, idx));
|
|
8850
9322
|
}
|
|
8851
9323
|
function isProbeZone(entry) {
|
|
@@ -9184,8 +9656,8 @@ var ChebyshevStore = class extends ChunkWindow {
|
|
|
9184
9656
|
const params = this.zoneParams.get(zone);
|
|
9185
9657
|
if (!params) return null;
|
|
9186
9658
|
return {
|
|
9187
|
-
start: params.start_jd,
|
|
9188
|
-
end: params.end_jd
|
|
9659
|
+
start: tdbToUtc(params.start_jd),
|
|
9660
|
+
end: tdbToUtc(params.end_jd)
|
|
9189
9661
|
};
|
|
9190
9662
|
}
|
|
9191
9663
|
isAwaited(objectId, jd) {
|
|
@@ -9504,6 +9976,28 @@ function rowsFor(chunk, id) {
|
|
|
9504
9976
|
return index.get(id) ?? NO_ROWS;
|
|
9505
9977
|
}
|
|
9506
9978
|
|
|
9979
|
+
//#endregion
|
|
9980
|
+
//#region src/lib/fetch/version-check.ts
|
|
9981
|
+
var CHECK_TIMEOUT_MS = 15e3;
|
|
9982
|
+
async function dataVersionChanged() {
|
|
9983
|
+
try {
|
|
9984
|
+
const res = await fetch(`${dataBase()}/v1/metadata.json`, {
|
|
9985
|
+
cache: "no-store",
|
|
9986
|
+
signal: AbortSignal.timeout(CHECK_TIMEOUT_MS)
|
|
9987
|
+
});
|
|
9988
|
+
if (!res.ok) return false;
|
|
9989
|
+
const meta = await res.json();
|
|
9990
|
+
const live = getDataVersions();
|
|
9991
|
+
if (Object.keys(live).length === 0) return false;
|
|
9992
|
+
const next = meta.versions ?? {};
|
|
9993
|
+
const keys = new Set([...Object.keys(live), ...Object.keys(next)]);
|
|
9994
|
+
for (const k of keys) if (live[k] !== next[k]) return true;
|
|
9995
|
+
return false;
|
|
9996
|
+
} catch {
|
|
9997
|
+
return false;
|
|
9998
|
+
}
|
|
9999
|
+
}
|
|
10000
|
+
|
|
9507
10001
|
//#endregion
|
|
9508
10002
|
//#region src/lib/fetch/gz.ts
|
|
9509
10003
|
function gunzip(res) {
|
|
@@ -9537,12 +10031,12 @@ function memoizedGzJson(url, opts = {}) {
|
|
|
9537
10031
|
//#endregion
|
|
9538
10032
|
//#region src/lib/fetch/bundle-cache.ts
|
|
9539
10033
|
var MAX_BUNDLES = 24;
|
|
9540
|
-
var cache$
|
|
10034
|
+
var cache$3 = /* @__PURE__ */ new Map();
|
|
9541
10035
|
function fetchGzipBundle(url, init) {
|
|
9542
|
-
let p = cache$
|
|
10036
|
+
let p = cache$3.get(url);
|
|
9543
10037
|
if (p) {
|
|
9544
|
-
cache$
|
|
9545
|
-
cache$
|
|
10038
|
+
cache$3.delete(url);
|
|
10039
|
+
cache$3.set(url, p);
|
|
9546
10040
|
}
|
|
9547
10041
|
if (!p) {
|
|
9548
10042
|
p = (async () => {
|
|
@@ -9553,13 +10047,13 @@ function fetchGzipBundle(url, init) {
|
|
|
9553
10047
|
}
|
|
9554
10048
|
return gunzipJson(res);
|
|
9555
10049
|
})();
|
|
9556
|
-
cache$
|
|
10050
|
+
cache$3.set(url, p);
|
|
9557
10051
|
p.catch(() => {
|
|
9558
|
-
if (cache$
|
|
10052
|
+
if (cache$3.get(url) === p) cache$3.delete(url);
|
|
9559
10053
|
});
|
|
9560
|
-
for (const key of cache$
|
|
9561
|
-
if (cache$
|
|
9562
|
-
cache$
|
|
10054
|
+
for (const key of cache$3.keys()) {
|
|
10055
|
+
if (cache$3.size <= MAX_BUNDLES) break;
|
|
10056
|
+
cache$3.delete(key);
|
|
9563
10057
|
}
|
|
9564
10058
|
}
|
|
9565
10059
|
return p;
|
|
@@ -9653,9 +10147,11 @@ async function earthZoneEndJd() {
|
|
|
9653
10147
|
return zoom && isDateSegmented(zoom) ? unixMsToJD(lastCoveredMs(zoom)) : Infinity;
|
|
9654
10148
|
}
|
|
9655
10149
|
async function coverageOf(id) {
|
|
9656
|
-
const
|
|
9657
|
-
const
|
|
9658
|
-
|
|
10150
|
+
const detail = await fetchObjectDetail(id, false);
|
|
10151
|
+
const windows = detail.global?.coverage?.windows ?? [];
|
|
10152
|
+
const tle = detail.global?.orbit?.scale === "planet";
|
|
10153
|
+
const openEnd = tle ? await earthZoneEndJd() : Infinity;
|
|
10154
|
+
return windows.map(([start, end]) => [start ?? -Infinity, end == null ? openEnd : tle ? end : tdbToUtc(end)]).filter(([start, end]) => end > start);
|
|
9659
10155
|
}
|
|
9660
10156
|
function nearestCoveredJd(windows, jd) {
|
|
9661
10157
|
let best = null;
|
|
@@ -9731,7 +10227,7 @@ function bodyDataFromGlobal(id, detail) {
|
|
|
9731
10227
|
validityStart: omm ? orbit.epoch_jd - SGP4_VALIDITY_SLACK_DAYS : -Infinity,
|
|
9732
10228
|
validityEnd: omm ? orbit.epoch_jd + SGP4_VALIDITY_SLACK_DAYS : Infinity,
|
|
9733
10229
|
orbitalSource: parseOrbitalSource(orbit.source),
|
|
9734
|
-
...coverageStart != null ? { visibleFromDays: coverageStart - J2000_JD$
|
|
10230
|
+
...coverageStart != null ? { visibleFromDays: coverageStart - J2000_JD$1 } : {},
|
|
9735
10231
|
...isParabolic ? {
|
|
9736
10232
|
q: orbit.q,
|
|
9737
10233
|
tp: orbit.tp
|
|
@@ -9829,34 +10325,44 @@ async function ensureTargetStreamed(ctx, targetId) {
|
|
|
9829
10325
|
|
|
9830
10326
|
//#endregion
|
|
9831
10327
|
//#region src/lib/math/orientation.ts
|
|
9832
|
-
var DEG2RAD$
|
|
9833
|
-
var J2000_JD$1 = 2451545;
|
|
10328
|
+
var DEG2RAD$5 = Math.PI / 180;
|
|
9834
10329
|
var DAYS_PER_CENTURY = 36525;
|
|
9835
|
-
function
|
|
9836
|
-
const dt = currentJd - J2000_JD$1;
|
|
10330
|
+
function iauAngles(orientation, currentJd, nutPrec) {
|
|
10331
|
+
const dt = utcToTdb(currentJd) - J2000_JD$1;
|
|
9837
10332
|
const T = dt / DAYS_PER_CENTURY;
|
|
9838
10333
|
let raDeg = orientation.pole_ra_0 + orientation.pole_ra_1 * T;
|
|
9839
10334
|
let decDeg = orientation.pole_dec_0 + orientation.pole_dec_1 * T;
|
|
9840
10335
|
let wDeg = orientation.w0 + orientation.w1 * dt + orientation.w2 * dt * dt;
|
|
9841
10336
|
if (nutPrec) {
|
|
9842
10337
|
const { ra, dec, pm, angles } = nutPrec;
|
|
9843
|
-
const
|
|
10338
|
+
const k = nutPrec.phaseDegree + 1;
|
|
10339
|
+
const n = Math.min(Math.floor(angles.length / k), Math.max(ra.length, dec.length, pm.length));
|
|
9844
10340
|
for (let i = 0; i < n; i++) {
|
|
9845
|
-
|
|
10341
|
+
let thetaDeg = 0;
|
|
10342
|
+
for (let j = k - 1; j >= 0; j--) thetaDeg = thetaDeg * T + angles[k * i + j];
|
|
10343
|
+
const theta = thetaDeg * DEG2RAD$5;
|
|
9846
10344
|
const s = Math.sin(theta);
|
|
9847
10345
|
if (i < ra.length) raDeg += ra[i] * s;
|
|
9848
10346
|
if (i < dec.length) decDeg += dec[i] * Math.cos(theta);
|
|
9849
10347
|
if (i < pm.length) wDeg += pm[i] * s;
|
|
9850
10348
|
}
|
|
9851
10349
|
}
|
|
9852
|
-
|
|
9853
|
-
|
|
10350
|
+
return {
|
|
10351
|
+
ra: raDeg,
|
|
10352
|
+
dec: decDeg,
|
|
10353
|
+
w: wDeg
|
|
10354
|
+
};
|
|
10355
|
+
}
|
|
10356
|
+
function bodyQuaternion(orientation, currentJd, nutPrec) {
|
|
10357
|
+
const { ra: raDeg, dec: decDeg, w: wDeg } = iauAngles(orientation, currentJd, nutPrec);
|
|
10358
|
+
const ra = raDeg * DEG2RAD$5;
|
|
10359
|
+
const dec = decDeg * DEG2RAD$5;
|
|
9854
10360
|
const cosDec = Math.cos(dec);
|
|
9855
10361
|
const pole = equatorialToScene(cosDec * Math.cos(ra), cosDec * Math.sin(ra), Math.sin(dec), new Vector3()).normalize();
|
|
9856
10362
|
const node = equatorialToScene(-Math.sin(ra), Math.cos(ra), 0, new Vector3()).normalize();
|
|
9857
10363
|
const third = new Vector3().crossVectors(node, pole).normalize();
|
|
9858
10364
|
const tiltQuat = new Quaternion().setFromRotationMatrix(new Matrix4().makeBasis(node, pole, third));
|
|
9859
|
-
return new Quaternion().setFromAxisAngle(pole, wDeg * DEG2RAD$
|
|
10365
|
+
return new Quaternion().setFromAxisAngle(pole, wDeg * DEG2RAD$5).multiply(tiltQuat);
|
|
9860
10366
|
}
|
|
9861
10367
|
function applyOrientation(obj, orientation, currentJd, nutPrec) {
|
|
9862
10368
|
obj.quaternion.copy(bodyQuaternion(orientation, currentJd, nutPrec));
|
|
@@ -9975,6 +10481,434 @@ function chainShaderHook(material, mod, patch) {
|
|
|
9975
10481
|
material.needsUpdate = true;
|
|
9976
10482
|
}
|
|
9977
10483
|
|
|
10484
|
+
//#endregion
|
|
10485
|
+
//#region src/lib/scene/lighting.ts
|
|
10486
|
+
var AMBIENT_INTENSITY = .01;
|
|
10487
|
+
var SUN_LIGHT_INTENSITY = 3.5;
|
|
10488
|
+
var ENV_BASE_INTENSITY = .04;
|
|
10489
|
+
function sunIrradianceFactor(sunDistScene) {
|
|
10490
|
+
const au = Math.max(sunDistScene / 10, .01);
|
|
10491
|
+
return 1 / (au * au);
|
|
10492
|
+
}
|
|
10493
|
+
function applySunPointLightMode(light, realistic, scale = 1) {
|
|
10494
|
+
light.decay = realistic ? 2 : 0;
|
|
10495
|
+
light.intensity = (realistic ? SUN_LIGHT_INTENSITY * 10 * 10 : SUN_LIGHT_INTENSITY) * scale;
|
|
10496
|
+
}
|
|
10497
|
+
function makeEnvMap(renderer) {
|
|
10498
|
+
const pmrem = new PMREMGenerator(renderer);
|
|
10499
|
+
const tex = pmrem.fromScene(new RoomEnvironment()).texture;
|
|
10500
|
+
pmrem.dispose();
|
|
10501
|
+
return tex;
|
|
10502
|
+
}
|
|
10503
|
+
|
|
10504
|
+
//#endregion
|
|
10505
|
+
//#region src/lib/scene/objects/surface/ring-light.ts
|
|
10506
|
+
var UNLIT_TINT = [
|
|
10507
|
+
1,
|
|
10508
|
+
.97075,
|
|
10509
|
+
.952
|
|
10510
|
+
];
|
|
10511
|
+
var FORWARD_TINT_BIAS = [
|
|
10512
|
+
1.02,
|
|
10513
|
+
.99,
|
|
10514
|
+
.97
|
|
10515
|
+
];
|
|
10516
|
+
var PROFILE_MU = Math.sin(8 * Math.PI / 180);
|
|
10517
|
+
function oneMinusExp(x) {
|
|
10518
|
+
return x < .001 ? x * (1 - .5 * x) : 1 - Math.exp(-x);
|
|
10519
|
+
}
|
|
10520
|
+
function reflectionGain(mu0, mu, tau) {
|
|
10521
|
+
const a = Math.max(mu0, 1e-4);
|
|
10522
|
+
const b = Math.max(mu, 1e-4);
|
|
10523
|
+
const t = Math.max(tau, 1e-6);
|
|
10524
|
+
return mu0 / (a + b) * oneMinusExp(t * (1 / a + 1 / b)) / (.5 * oneMinusExp(2 * t / PROFILE_MU));
|
|
10525
|
+
}
|
|
10526
|
+
var RINGSHINE_BANDS = 3;
|
|
10527
|
+
var SECTORS = 12;
|
|
10528
|
+
var RINGSHINE_PATCHES = RINGSHINE_BANDS * (SECTORS / 2 + 1);
|
|
10529
|
+
var RINGSHINE_MIN_MU0 = 1e-4;
|
|
10530
|
+
var PROFILE_BINS = 256;
|
|
10531
|
+
var _litGain = new Float64Array(PROFILE_BINS);
|
|
10532
|
+
var SECTOR_STEPS = 6;
|
|
10533
|
+
var PLANET_LIGHT_AZIMUTHS = 19;
|
|
10534
|
+
var PLANET_LIGHT_RADII = 8;
|
|
10535
|
+
var PLANET_ROWS = 24;
|
|
10536
|
+
var PLANET_COLUMNS = 48;
|
|
10537
|
+
function luminance$2(r, g, b) {
|
|
10538
|
+
return .2126 * r + .7152 * g + .0722 * b;
|
|
10539
|
+
}
|
|
10540
|
+
var SRGB_TO_LINEAR = Float64Array.from({ length: 256 }, (_, i) => {
|
|
10541
|
+
const c = i / 255;
|
|
10542
|
+
return c <= .04045 ? c / 12.92 : ((c + .055) / 1.055) ** 2.4;
|
|
10543
|
+
});
|
|
10544
|
+
function ringProfile(pixels, width, rows, inner, outer, intensity) {
|
|
10545
|
+
const back = new Float64Array(PROFILE_BINS);
|
|
10546
|
+
const forward = new Float64Array(PROFILE_BINS);
|
|
10547
|
+
const unlit = new Float64Array(PROFILE_BINS);
|
|
10548
|
+
const transmission = new Float64Array(PROFILE_BINS);
|
|
10549
|
+
const unlitLuminance = luminance$2(...UNLIT_TINT);
|
|
10550
|
+
const [br, bg, bb] = FORWARD_TINT_BIAS;
|
|
10551
|
+
const tint = [
|
|
10552
|
+
0,
|
|
10553
|
+
0,
|
|
10554
|
+
0
|
|
10555
|
+
];
|
|
10556
|
+
const at = (row, i) => (row * width + i) * 4;
|
|
10557
|
+
for (let k = 0; k < PROFILE_BINS; k++) {
|
|
10558
|
+
const from = Math.floor(k * width / PROFILE_BINS);
|
|
10559
|
+
const to = Math.max(from + 1, Math.floor((k + 1) * width / PROFILE_BINS));
|
|
10560
|
+
const r = inner + (k + .5) / PROFILE_BINS * (outer - inner);
|
|
10561
|
+
for (let i = from; i < to; i++) {
|
|
10562
|
+
const c = at(rows.color, i);
|
|
10563
|
+
const red = SRGB_TO_LINEAR[pixels[c]];
|
|
10564
|
+
const green = SRGB_TO_LINEAR[pixels[c + 1]];
|
|
10565
|
+
const blue = SRGB_TO_LINEAR[pixels[c + 2]];
|
|
10566
|
+
const opacity = Math.min(1, (1 - pixels[at(rows.transparency, i)] / 255) * intensity);
|
|
10567
|
+
const backscatter = pixels[at(rows.backscattered, i)] / 255 * intensity;
|
|
10568
|
+
back[k] += backscatter * luminance$2(red, green, blue);
|
|
10569
|
+
forward[k] += pixels[at(rows.forwardscattered, i)] / 255 * opacity * intensity * luminance$2(red * br, green * bg, blue * bb);
|
|
10570
|
+
unlit[k] += pixels[at(rows.unlitside, i)] / 255 * opacity * intensity * unlitLuminance;
|
|
10571
|
+
transmission[k] += 1 - opacity;
|
|
10572
|
+
tint[0] += backscatter * red * r;
|
|
10573
|
+
tint[1] += backscatter * green * r;
|
|
10574
|
+
tint[2] += backscatter * blue * r;
|
|
10575
|
+
}
|
|
10576
|
+
const n = to - from;
|
|
10577
|
+
back[k] /= n;
|
|
10578
|
+
forward[k] /= n;
|
|
10579
|
+
unlit[k] /= n;
|
|
10580
|
+
transmission[k] /= n;
|
|
10581
|
+
}
|
|
10582
|
+
const tintLuminance = luminance$2(tint[0], tint[1], tint[2]);
|
|
10583
|
+
return {
|
|
10584
|
+
inner,
|
|
10585
|
+
outer,
|
|
10586
|
+
back,
|
|
10587
|
+
forward,
|
|
10588
|
+
unlit,
|
|
10589
|
+
transmission,
|
|
10590
|
+
litTint: tintLuminance > 0 ? new Color(tint[0], tint[1], tint[2]).multiplyScalar(1 / tintLuminance) : new Color(1, 1, 1),
|
|
10591
|
+
bands: equalLightBands(back, unlit, inner, outer)
|
|
10592
|
+
};
|
|
10593
|
+
}
|
|
10594
|
+
function equalLightBands(back, unlit, inner, outer) {
|
|
10595
|
+
const cumulative = new Float64Array(PROFILE_BINS + 1);
|
|
10596
|
+
for (let k = 0; k < PROFILE_BINS; k++) {
|
|
10597
|
+
const r = inner + (k + .5) / PROFILE_BINS * (outer - inner);
|
|
10598
|
+
cumulative[k + 1] = cumulative[k] + (back[k] + unlit[k]) / r;
|
|
10599
|
+
}
|
|
10600
|
+
const total = cumulative[PROFILE_BINS];
|
|
10601
|
+
const edges = new Int32Array(RINGSHINE_BANDS + 1);
|
|
10602
|
+
edges[RINGSHINE_BANDS] = PROFILE_BINS;
|
|
10603
|
+
for (let b = 1; b < RINGSHINE_BANDS; b++) {
|
|
10604
|
+
let k = edges[b - 1] + 1;
|
|
10605
|
+
while (k < PROFILE_BINS - (RINGSHINE_BANDS - b) && cumulative[k] < total * b / RINGSHINE_BANDS) k++;
|
|
10606
|
+
edges[b] = k;
|
|
10607
|
+
}
|
|
10608
|
+
return edges;
|
|
10609
|
+
}
|
|
10610
|
+
function forwardWeight(cosPhase) {
|
|
10611
|
+
const t = Math.min(Math.max((cosPhase + 1) / 2, 0), 1);
|
|
10612
|
+
return 1 - t * t * (3 - 2 * t);
|
|
10613
|
+
}
|
|
10614
|
+
var PARTICLE_PHASE_EXPONENT = 3.09;
|
|
10615
|
+
function particlePhase(cosPhase) {
|
|
10616
|
+
return (1 - Math.acos(Math.min(Math.max(cosPhase, -1), 1)) / Math.PI) ** PARTICLE_PHASE_EXPONENT;
|
|
10617
|
+
}
|
|
10618
|
+
function inPlanetShadow(x, y, cosB, sinB, planet) {
|
|
10619
|
+
const ox = x / planet.equatorial;
|
|
10620
|
+
const oy = y / planet.equatorial;
|
|
10621
|
+
const dx = cosB / planet.equatorial;
|
|
10622
|
+
const dz = sinB / planet.polar;
|
|
10623
|
+
const b = ox * dx;
|
|
10624
|
+
if (b >= 0) return false;
|
|
10625
|
+
return ox * ox + oy * oy - b * b / (dx * dx + dz * dz) < 1;
|
|
10626
|
+
}
|
|
10627
|
+
function ringshinePatches(out, profile, sinB, planet) {
|
|
10628
|
+
const cosB = Math.sqrt(Math.max(0, 1 - sinB * sinB));
|
|
10629
|
+
const mu0 = Math.abs(sinB);
|
|
10630
|
+
const sunAbove = sinB >= 0;
|
|
10631
|
+
const { inner, outer, back, forward, unlit, transmission, bands } = profile;
|
|
10632
|
+
for (let i = 0; i < PROFILE_BINS; i++) _litGain[i] = reflectionGain(mu0, mu0, -Math.log(Math.max(transmission[i], 1e-6)));
|
|
10633
|
+
const dr = (outer - inner) / PROFILE_BINS;
|
|
10634
|
+
const sector = 2 * Math.PI / SECTORS;
|
|
10635
|
+
const dPhi = sector / SECTOR_STEPS;
|
|
10636
|
+
let p = 0;
|
|
10637
|
+
for (let band = 0; band < RINGSHINE_BANDS; band++) for (let k = 0; k <= SECTORS / 2; k++, p++) {
|
|
10638
|
+
let above = 0;
|
|
10639
|
+
let below = 0;
|
|
10640
|
+
let weight = 0;
|
|
10641
|
+
let wx = 0;
|
|
10642
|
+
let wy = 0;
|
|
10643
|
+
for (let s = 0; s < SECTOR_STEPS; s++) {
|
|
10644
|
+
const phi = (k - .5) * sector + (s + .5) * dPhi;
|
|
10645
|
+
const c = Math.cos(phi);
|
|
10646
|
+
const sn = Math.sin(phi);
|
|
10647
|
+
const w = forwardWeight(-cosB * c);
|
|
10648
|
+
const phase = particlePhase(-cosB * c);
|
|
10649
|
+
for (let i = bands[band]; i < bands[band + 1]; i++) {
|
|
10650
|
+
const r = inner + (i + .5) * dr;
|
|
10651
|
+
if (inPlanetShadow(r * c, r * sn, cosB, sinB, planet)) continue;
|
|
10652
|
+
const area = r * dr * dPhi;
|
|
10653
|
+
const lit = (back[i] * phase + (forward[i] - back[i] * phase) * w) * _litGain[i] * area;
|
|
10654
|
+
const through = unlit[i] * area;
|
|
10655
|
+
above += sunAbove ? lit : through;
|
|
10656
|
+
below += sunAbove ? through : lit;
|
|
10657
|
+
const light = lit + through;
|
|
10658
|
+
weight += light;
|
|
10659
|
+
wx += light * r * c;
|
|
10660
|
+
wy += light * r * Math.abs(sn);
|
|
10661
|
+
}
|
|
10662
|
+
}
|
|
10663
|
+
const share = k === 0 || k === SECTORS / 2 ? .5 : 1;
|
|
10664
|
+
if (weight > 0) {
|
|
10665
|
+
out[4 * p] = wx / weight;
|
|
10666
|
+
out[4 * p + 1] = wy / weight;
|
|
10667
|
+
} else {
|
|
10668
|
+
const r = inner + (bands[band] + bands[band + 1]) / 2 * dr;
|
|
10669
|
+
out[4 * p] = r * Math.cos(k * sector);
|
|
10670
|
+
out[4 * p + 1] = r * Math.abs(Math.sin(k * sector));
|
|
10671
|
+
}
|
|
10672
|
+
out[4 * p + 2] = above * share;
|
|
10673
|
+
out[4 * p + 3] = below * share;
|
|
10674
|
+
}
|
|
10675
|
+
}
|
|
10676
|
+
function ringshineAt(patches, mu0, qx, qy, qz, nx, ny, nz) {
|
|
10677
|
+
const above = qz >= 0;
|
|
10678
|
+
const height = Math.abs(qz);
|
|
10679
|
+
const qq = qx * qx + qy * qy + qz * qz;
|
|
10680
|
+
const nq = nx * qx + ny * qy + nz * qz;
|
|
10681
|
+
let sum = 0;
|
|
10682
|
+
for (let i = 0; i < 21; i++) {
|
|
10683
|
+
const px = patches[4 * i];
|
|
10684
|
+
const py = patches[4 * i + 1];
|
|
10685
|
+
const light = above ? patches[4 * i + 2] : patches[4 * i + 3];
|
|
10686
|
+
const base = qq + px * px + py * py - 2 * px * qx;
|
|
10687
|
+
const across = 2 * py * qy;
|
|
10688
|
+
const facingBase = px * nx - nq;
|
|
10689
|
+
const facingAcross = py * ny;
|
|
10690
|
+
for (const sign of [1, -1]) {
|
|
10691
|
+
const d2 = base - sign * across;
|
|
10692
|
+
const d = Math.sqrt(d2);
|
|
10693
|
+
const facing = Math.max(facingBase + sign * facingAcross, 0);
|
|
10694
|
+
sum += light * facing / (d2 * d * (mu0 * d + height));
|
|
10695
|
+
}
|
|
10696
|
+
}
|
|
10697
|
+
return 2 * mu0 * height * sum;
|
|
10698
|
+
}
|
|
10699
|
+
function ringTransmission(profile, x, y, z, cosB, sinB) {
|
|
10700
|
+
if (Math.abs(sinB) < 1e-6) return 1;
|
|
10701
|
+
const t = -z / sinB;
|
|
10702
|
+
if (t < 0) return 1;
|
|
10703
|
+
const u = (Math.hypot(x + t * cosB, y) - profile.inner) / (profile.outer - profile.inner);
|
|
10704
|
+
if (u < 0 || u > 1) return 1;
|
|
10705
|
+
const bin = Math.min(Math.floor(u * PROFILE_BINS), PROFILE_BINS - 1);
|
|
10706
|
+
return Math.max(profile.transmission[bin], 1e-4) ** (1 / Math.max(Math.abs(sinB), .02));
|
|
10707
|
+
}
|
|
10708
|
+
var _cells = {
|
|
10709
|
+
x: new Float64Array(PLANET_ROWS * PLANET_COLUMNS),
|
|
10710
|
+
y: new Float64Array(PLANET_ROWS * PLANET_COLUMNS),
|
|
10711
|
+
z: new Float64Array(PLANET_ROWS * PLANET_COLUMNS),
|
|
10712
|
+
nx: new Float64Array(PLANET_ROWS * PLANET_COLUMNS),
|
|
10713
|
+
ny: new Float64Array(PLANET_ROWS * PLANET_COLUMNS),
|
|
10714
|
+
nz: new Float64Array(PLANET_ROWS * PLANET_COLUMNS),
|
|
10715
|
+
light: new Float64Array(PLANET_ROWS * PLANET_COLUMNS)
|
|
10716
|
+
};
|
|
10717
|
+
function planetLightOnRing(out, inner, outer, sinB, planet, caster, patches) {
|
|
10718
|
+
const cosB = Math.sqrt(Math.max(0, 1 - sinB * sinB));
|
|
10719
|
+
const mu0 = Math.abs(sinB);
|
|
10720
|
+
const { equatorial: a, polar: c } = planet;
|
|
10721
|
+
const cells = _cells;
|
|
10722
|
+
const dBeta = Math.PI / PLANET_ROWS;
|
|
10723
|
+
const dLambda = 2 * Math.PI / PLANET_COLUMNS;
|
|
10724
|
+
for (let row = 0; row < PLANET_ROWS; row++) {
|
|
10725
|
+
const beta = -Math.PI / 2 + (row + .5) * dBeta;
|
|
10726
|
+
const cb = Math.cos(beta);
|
|
10727
|
+
const sb = Math.sin(beta);
|
|
10728
|
+
const area = a * cb * Math.sqrt(c * c * cb * cb + a * a * sb * sb) * dBeta * dLambda;
|
|
10729
|
+
for (let col = 0; col < PLANET_COLUMNS; col++) {
|
|
10730
|
+
const lambda = (col + .5) * dLambda;
|
|
10731
|
+
const cl = Math.cos(lambda);
|
|
10732
|
+
const sl = Math.sin(lambda);
|
|
10733
|
+
const i = row * PLANET_COLUMNS + col;
|
|
10734
|
+
const x = a * cb * cl;
|
|
10735
|
+
const y = a * cb * sl;
|
|
10736
|
+
const z = c * sb;
|
|
10737
|
+
let nx = cb * cl / a;
|
|
10738
|
+
let ny = cb * sl / a;
|
|
10739
|
+
let nz = sb / c;
|
|
10740
|
+
const len = Math.hypot(nx, ny, nz);
|
|
10741
|
+
nx /= len;
|
|
10742
|
+
ny /= len;
|
|
10743
|
+
nz /= len;
|
|
10744
|
+
const cosSun = nx * cosB + nz * sinB;
|
|
10745
|
+
const day = cosSun > 0 ? cosSun * ringTransmission(caster, x, y, z, cosB, sinB) : 0;
|
|
10746
|
+
const night = mu0 < RINGSHINE_MIN_MU0 ? 0 : ringshineAt(patches, mu0, x, y, z, nx, ny, nz) / SUN_LIGHT_INTENSITY;
|
|
10747
|
+
cells.x[i] = x;
|
|
10748
|
+
cells.y[i] = y;
|
|
10749
|
+
cells.z[i] = z;
|
|
10750
|
+
cells.nx[i] = nx;
|
|
10751
|
+
cells.ny[i] = ny;
|
|
10752
|
+
cells.nz[i] = nz;
|
|
10753
|
+
cells.light[i] = (day + night) / Math.PI * area;
|
|
10754
|
+
}
|
|
10755
|
+
}
|
|
10756
|
+
for (let j = 0; j < 8; j++) {
|
|
10757
|
+
const r = inner + j / (8 - 1) * (outer - inner);
|
|
10758
|
+
for (let k = 0; k < 19; k++) {
|
|
10759
|
+
const cosPhi = 1 - 2 * k / (19 - 1);
|
|
10760
|
+
const px = r * cosPhi;
|
|
10761
|
+
const py = r * Math.sqrt(1 - cosPhi * cosPhi);
|
|
10762
|
+
let above = 0;
|
|
10763
|
+
let below = 0;
|
|
10764
|
+
let aboveMu = 0;
|
|
10765
|
+
let belowMu = 0;
|
|
10766
|
+
for (let i = 0; i < PLANET_ROWS * PLANET_COLUMNS; i++) {
|
|
10767
|
+
const vx = px - cells.x[i];
|
|
10768
|
+
const vy = py - cells.y[i];
|
|
10769
|
+
const vz = -cells.z[i];
|
|
10770
|
+
const d2 = vx * vx + vy * vy + vz * vz;
|
|
10771
|
+
const facing = cells.nx[i] * vx + cells.ny[i] * vy + cells.nz[i] * vz;
|
|
10772
|
+
if (facing <= 0) continue;
|
|
10773
|
+
const d = Math.sqrt(d2);
|
|
10774
|
+
const e = cells.light[i] * facing / (d2 * d);
|
|
10775
|
+
const mu = Math.abs(vz) / d;
|
|
10776
|
+
if (cells.z[i] > 0) {
|
|
10777
|
+
above += e;
|
|
10778
|
+
aboveMu += e * mu;
|
|
10779
|
+
} else {
|
|
10780
|
+
below += e;
|
|
10781
|
+
belowMu += e * mu;
|
|
10782
|
+
}
|
|
10783
|
+
}
|
|
10784
|
+
const node = 4 * (j * 19 + k);
|
|
10785
|
+
out[node] = above;
|
|
10786
|
+
out[node + 1] = below;
|
|
10787
|
+
out[node + 2] = above > 0 ? aboveMu / above : 0;
|
|
10788
|
+
out[node + 3] = below > 0 ? belowMu / below : 0;
|
|
10789
|
+
}
|
|
10790
|
+
}
|
|
10791
|
+
}
|
|
10792
|
+
var _grid = new Float32Array(4 * 19 * 8);
|
|
10793
|
+
function makeRingLight(profile) {
|
|
10794
|
+
const texture = new DataTexture(new Uint16Array(4 * 19 * 8), 19, 8, RGBAFormat, HalfFloatType);
|
|
10795
|
+
texture.minFilter = LinearFilter;
|
|
10796
|
+
texture.magFilter = LinearFilter;
|
|
10797
|
+
texture.wrapS = ClampToEdgeWrapping;
|
|
10798
|
+
texture.wrapT = ClampToEdgeWrapping;
|
|
10799
|
+
texture.needsUpdate = true;
|
|
10800
|
+
return {
|
|
10801
|
+
profile,
|
|
10802
|
+
planet: {
|
|
10803
|
+
equatorial: 0,
|
|
10804
|
+
polar: 0
|
|
10805
|
+
},
|
|
10806
|
+
planetLight: texture,
|
|
10807
|
+
planetLightSinB: NaN,
|
|
10808
|
+
patches: new Float64Array(4 * 21),
|
|
10809
|
+
patchesSinB: NaN
|
|
10810
|
+
};
|
|
10811
|
+
}
|
|
10812
|
+
function fillPlanetLight(light, sinB, caster) {
|
|
10813
|
+
planetLightOnRing(_grid, light.profile.inner, light.profile.outer, sinB, light.planet, caster.profile, caster.patches);
|
|
10814
|
+
const data = light.planetLight.image.data;
|
|
10815
|
+
for (let i = 0; i < _grid.length; i++) data[i] = DataUtils.toHalfFloat(_grid[i]);
|
|
10816
|
+
light.planetLight.needsUpdate = true;
|
|
10817
|
+
light.planetLightSinB = sinB;
|
|
10818
|
+
}
|
|
10819
|
+
function peakRingshine(profile, planet) {
|
|
10820
|
+
const patches = new Float64Array(4 * 21);
|
|
10821
|
+
ringshinePatches(patches, profile, 1, planet);
|
|
10822
|
+
let peak = 0;
|
|
10823
|
+
for (let deg = 2; deg < 90; deg += 2) {
|
|
10824
|
+
const beta = deg * Math.PI / 180;
|
|
10825
|
+
const cb = Math.cos(beta);
|
|
10826
|
+
const sb = Math.sin(beta);
|
|
10827
|
+
const nx = cb / planet.equatorial;
|
|
10828
|
+
const nz = sb / planet.polar;
|
|
10829
|
+
const len = Math.hypot(nx, nz);
|
|
10830
|
+
const e = ringshineAt(patches, 1, planet.equatorial * cb, 0, planet.polar * sb, nx / len, 0, nz / len);
|
|
10831
|
+
peak = Math.max(peak, e / SUN_LIGHT_INTENSITY);
|
|
10832
|
+
}
|
|
10833
|
+
return peak;
|
|
10834
|
+
}
|
|
10835
|
+
var RINGSHINE_PARS = `
|
|
10836
|
+
#define RINGSHINE_PATCHES ${21}
|
|
10837
|
+
uniform vec4 uRingshinePatch[RINGSHINE_PATCHES];
|
|
10838
|
+
uniform vec3 uRingshineAxis;
|
|
10839
|
+
uniform vec3 uRingshineTint[2];
|
|
10840
|
+
`;
|
|
10841
|
+
var RINGSHINE_LIGHT = `
|
|
10842
|
+
if (uRingshineTint[0].g + uRingshineTint[1].g > 0.0) {
|
|
10843
|
+
vec3 q = vRingShadowWorldPos - uRingShadowCenter;
|
|
10844
|
+
vec3 axisY = cross(uRingShadowPoleDir, uRingshineAxis);
|
|
10845
|
+
float height = dot(q, uRingShadowPoleDir);
|
|
10846
|
+
float mu0 = abs(dot(uRingShadowSunDir, uRingShadowPoleDir));
|
|
10847
|
+
vec3 n = inverseTransformDirection(geometryNormal, viewMatrix);
|
|
10848
|
+
float qx = dot(q, uRingshineAxis);
|
|
10849
|
+
float qy = dot(q, axisY);
|
|
10850
|
+
float qq = dot(q, q);
|
|
10851
|
+
float nx = dot(n, uRingshineAxis);
|
|
10852
|
+
float ny = dot(n, axisY);
|
|
10853
|
+
float nq = dot(n, q);
|
|
10854
|
+
float above = step(0.0, height);
|
|
10855
|
+
float absHeight = abs(height);
|
|
10856
|
+
float sum = 0.0;
|
|
10857
|
+
for (int i = 0; i < RINGSHINE_PATCHES; i++) {
|
|
10858
|
+
vec4 p = uRingshinePatch[i];
|
|
10859
|
+
float light = mix(p.w, p.z, above);
|
|
10860
|
+
float base = qq + dot(p.xy, p.xy) - 2.0 * p.x * qx;
|
|
10861
|
+
float across = 2.0 * p.y * qy;
|
|
10862
|
+
float facingBase = p.x * nx - nq;
|
|
10863
|
+
float facingAcross = p.y * ny;
|
|
10864
|
+
// The patch and its mirror at -y.
|
|
10865
|
+
vec2 d2 = vec2(base - across, base + across);
|
|
10866
|
+
vec2 d = sqrt(d2);
|
|
10867
|
+
vec2 facing = max(vec2(facingBase + facingAcross, facingBase - facingAcross), 0.0);
|
|
10868
|
+
sum += light * dot(facing, 1.0 / (d2 * d * (mu0 * d + absHeight)));
|
|
10869
|
+
}
|
|
10870
|
+
vec3 tint = mix(uRingshineTint[1], uRingshineTint[0], above);
|
|
10871
|
+
reflectedLight.indirectDiffuse +=
|
|
10872
|
+
tint * (2.0 * mu0 * absHeight * sum) * BRDF_Lambert(material.diffuseContribution);
|
|
10873
|
+
}
|
|
10874
|
+
`;
|
|
10875
|
+
function attachRingshine(material) {
|
|
10876
|
+
const carrier = material.userData;
|
|
10877
|
+
if (carrier.ringshine) return carrier.ringshine;
|
|
10878
|
+
const uniforms = {
|
|
10879
|
+
uRingshinePatch: { value: Array.from({ length: 21 }, () => new Vector4()) },
|
|
10880
|
+
uRingshineAxis: { value: new Vector3(1, 0, 0) },
|
|
10881
|
+
uRingshineTint: { value: [new Vector3(), new Vector3()] },
|
|
10882
|
+
disable: () => {
|
|
10883
|
+
for (const tint of uniforms.uRingshineTint.value) tint.set(0, 0, 0);
|
|
10884
|
+
}
|
|
10885
|
+
};
|
|
10886
|
+
chainShaderHook(material, "ringshine", (shader) => {
|
|
10887
|
+
shader.uniforms.uRingshinePatch = uniforms.uRingshinePatch;
|
|
10888
|
+
shader.uniforms.uRingshineAxis = uniforms.uRingshineAxis;
|
|
10889
|
+
shader.uniforms.uRingshineTint = uniforms.uRingshineTint;
|
|
10890
|
+
shader.fragmentShader = shader.fragmentShader.replace("#include <common>", `#include <common>\n${RINGSHINE_PARS}`).replace("#include <lights_fragment_end>", `#include <lights_fragment_end>\n${RINGSHINE_LIGHT}`);
|
|
10891
|
+
});
|
|
10892
|
+
carrier.ringshine = uniforms;
|
|
10893
|
+
return uniforms;
|
|
10894
|
+
}
|
|
10895
|
+
function writeRingshine(uniforms, light, axis, sinB, lightScale) {
|
|
10896
|
+
const patches = uniforms.uRingshinePatch.value;
|
|
10897
|
+
for (let i = 0; i < 21; i++) patches[i].fromArray(light.patches, 4 * i);
|
|
10898
|
+
uniforms.uRingshineAxis.value.copy(axis);
|
|
10899
|
+
const [above, below] = uniforms.uRingshineTint.value;
|
|
10900
|
+
if (Math.abs(sinB) < RINGSHINE_MIN_MU0) {
|
|
10901
|
+
above.set(0, 0, 0);
|
|
10902
|
+
below.set(0, 0, 0);
|
|
10903
|
+
return;
|
|
10904
|
+
}
|
|
10905
|
+
const lit = light.profile.litTint;
|
|
10906
|
+
const unlitLuminance = luminance$2(...UNLIT_TINT);
|
|
10907
|
+
const [litFace, unlitFace] = sinB >= 0 ? [above, below] : [below, above];
|
|
10908
|
+
litFace.set(lit.r, lit.g, lit.b).multiplyScalar(lightScale);
|
|
10909
|
+
unlitFace.set(...UNLIT_TINT).multiplyScalar(lightScale / unlitLuminance);
|
|
10910
|
+
}
|
|
10911
|
+
|
|
9978
10912
|
//#endregion
|
|
9979
10913
|
//#region src/lib/scene/objects/surface/rings.ts
|
|
9980
10914
|
var RING_ANGULAR_SEGMENTS = 256;
|
|
@@ -9986,30 +10920,47 @@ async function loadStripTextures(url, rows, maxTextureSize) {
|
|
|
9986
10920
|
if (!response.ok) throw new Error(`Failed to load ${url}: ${response.status} ${response.statusText}`);
|
|
9987
10921
|
const blob = await response.blob();
|
|
9988
10922
|
const bitmap = await createImageBitmap(blob);
|
|
9989
|
-
const
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
const
|
|
9993
|
-
|
|
10923
|
+
const width = bitmap.width;
|
|
10924
|
+
const targetWidth = Math.min(width, maxTextureSize);
|
|
10925
|
+
if (targetWidth < width) console.info(`Ring strip ${url}: downscaling ${width}px → ${targetWidth}px to fit GL MAX_TEXTURE_SIZE.`);
|
|
10926
|
+
const pixels = readStripPixels(bitmap, url, maxTextureSize);
|
|
10927
|
+
bitmap.close();
|
|
10928
|
+
const line = (row) => boxFilterRow(pixels, width, row, targetWidth);
|
|
10929
|
+
const texture = (data, srgb = false) => {
|
|
9994
10930
|
const canvas = document.createElement("canvas");
|
|
9995
10931
|
canvas.width = targetWidth;
|
|
9996
10932
|
canvas.height = 2;
|
|
9997
10933
|
const ctx = canvas.getContext("2d");
|
|
9998
10934
|
if (!ctx) throw new Error(`Failed to acquire 2D context for ring strip ${url}`);
|
|
9999
|
-
|
|
10000
|
-
ctx.putImageData(
|
|
10001
|
-
ctx.putImageData(line, 0, 1);
|
|
10935
|
+
ctx.putImageData(data, 0, 0);
|
|
10936
|
+
ctx.putImageData(data, 0, 1);
|
|
10002
10937
|
const tex = new CanvasTexture(canvas);
|
|
10003
|
-
if (
|
|
10938
|
+
if (srgb) tex.colorSpace = SRGBColorSpace;
|
|
10004
10939
|
tex.minFilter = LinearMipmapLinearFilter;
|
|
10005
10940
|
tex.magFilter = LinearFilter;
|
|
10006
10941
|
tex.generateMipmaps = true;
|
|
10007
10942
|
tex.anisotropy = 16;
|
|
10008
10943
|
tex.needsUpdate = true;
|
|
10009
|
-
|
|
10944
|
+
return tex;
|
|
10945
|
+
};
|
|
10946
|
+
const scatter = line(rows.backscattered);
|
|
10947
|
+
const forward = line(rows.forwardscattered);
|
|
10948
|
+
const unlit = line(rows.unlitside);
|
|
10949
|
+
for (let d = 0; d < scatter.data.length; d += 4) {
|
|
10950
|
+
scatter.data[d + 1] = forward.data[d];
|
|
10951
|
+
scatter.data[d + 2] = unlit.data[d];
|
|
10010
10952
|
}
|
|
10011
|
-
|
|
10012
|
-
|
|
10953
|
+
const textures = {
|
|
10954
|
+
color: texture(line(rows.color), true),
|
|
10955
|
+
scatter: texture(scatter),
|
|
10956
|
+
transparency: texture(line(rows.transparency))
|
|
10957
|
+
};
|
|
10958
|
+
if (rows.thickness !== void 0) textures.thickness = texture(line(rows.thickness));
|
|
10959
|
+
return {
|
|
10960
|
+
textures,
|
|
10961
|
+
pixels,
|
|
10962
|
+
width
|
|
10963
|
+
};
|
|
10013
10964
|
}
|
|
10014
10965
|
function readStripPixels(bitmap, url, maxTextureSize) {
|
|
10015
10966
|
const out = new Uint8ClampedArray(bitmap.width * bitmap.height * 4);
|
|
@@ -10090,9 +11041,7 @@ var FRAGMENT_SHADER$2 = `
|
|
|
10090
11041
|
#include <common>
|
|
10091
11042
|
#include <logdepthbuf_pars_fragment>
|
|
10092
11043
|
|
|
10093
|
-
uniform sampler2D
|
|
10094
|
-
uniform sampler2D uForwardscattered;
|
|
10095
|
-
uniform sampler2D uUnlitside;
|
|
11044
|
+
uniform sampler2D uScatter;
|
|
10096
11045
|
uniform sampler2D uTransparency;
|
|
10097
11046
|
uniform sampler2D uColor;
|
|
10098
11047
|
uniform float uInnerScene;
|
|
@@ -10114,18 +11063,56 @@ var FRAGMENT_SHADER$2 = `
|
|
|
10114
11063
|
// 1/layerCount: opacity is split across the vertical layer instances so
|
|
10115
11064
|
// the composited stack reproduces the strip's alpha.
|
|
10116
11065
|
uniform float uLayerAlphaExp;
|
|
11066
|
+
// Light of the planet on the +Y and the -Y face over the Sun's, per unit of the
|
|
11067
|
+
// planet's albedo, and the mean sine of its incidence on each, by the cosine
|
|
11068
|
+
// of the azimuth from the Sun (x) and radius (y).
|
|
11069
|
+
uniform sampler2D uPlanetLight;
|
|
11070
|
+
// Lambert albedo of the planet, linear RGB.
|
|
11071
|
+
uniform vec3 uPlanetAlbedo;
|
|
11072
|
+
// Unit direction of the Sun in the local XZ plane.
|
|
11073
|
+
uniform vec2 uSunAzimuth;
|
|
10117
11074
|
|
|
10118
11075
|
varying vec3 vLocalPos;
|
|
10119
11076
|
varying vec3 vWorldPos;
|
|
10120
11077
|
varying vec3 vWorldNormal;
|
|
10121
11078
|
|
|
10122
|
-
|
|
10123
|
-
|
|
10124
|
-
const
|
|
11079
|
+
const vec3 UNLIT_TINT = vec3(${UNLIT_TINT.join(", ")});
|
|
11080
|
+
const vec3 FORWARD_TINT_BIAS = vec3(${FORWARD_TINT_BIAS.join(", ")});
|
|
11081
|
+
const float PROFILE_MU = ${PROFILE_MU};
|
|
11082
|
+
|
|
11083
|
+
float oneMinusExp(float x) {
|
|
11084
|
+
return x < 1e-3 ? x * (1.0 - 0.5 * x) : 1.0 - exp(-x);
|
|
11085
|
+
}
|
|
11086
|
+
|
|
11087
|
+
float reflectionGain(float mu0, float mu, float tau) {
|
|
11088
|
+
float a = max(mu0, 1e-4);
|
|
11089
|
+
float b = max(mu, 1e-4);
|
|
11090
|
+
return mu0 / (a + b) * oneMinusExp(tau * (1.0 / a + 1.0 / b))
|
|
11091
|
+
/ (0.5 * oneMinusExp(2.0 * tau / PROFILE_MU));
|
|
11092
|
+
}
|
|
11093
|
+
|
|
11094
|
+
float unlitGain(float mu0, float mu) {
|
|
11095
|
+
return 2.0 * mu0 / max(mu0 + mu, 1e-4);
|
|
11096
|
+
}
|
|
10125
11097
|
|
|
10126
|
-
//
|
|
10127
|
-
|
|
10128
|
-
|
|
11098
|
+
// Weight of forward scatter: 0 at phase 0, 1 at phase 180 deg, 0.5 edge-on.
|
|
11099
|
+
float forwardWeight(float cosPhase) {
|
|
11100
|
+
return 1.0 - smoothstep(-1.0, 1.0, cosPhase);
|
|
11101
|
+
}
|
|
11102
|
+
|
|
11103
|
+
float particlePhase(float cosPhase) {
|
|
11104
|
+
return pow(1.0 - acos(clamp(cosPhase, -1.0, 1.0)) / PI, ${PARTICLE_PHASE_EXPONENT});
|
|
11105
|
+
}
|
|
11106
|
+
|
|
11107
|
+
// The lit face at a phase and a gain: the backscatter profile under the
|
|
11108
|
+
// phase function of the particles, blended into the forward-scatter profile.
|
|
11109
|
+
vec3 litLight(vec3 back, vec3 forward, float cosPhase, float gain) {
|
|
11110
|
+
return mix(
|
|
11111
|
+
back * particlePhase(cosPhase) * gain,
|
|
11112
|
+
forward * min(gain, 1.0),
|
|
11113
|
+
forwardWeight(cosPhase)
|
|
11114
|
+
);
|
|
11115
|
+
}
|
|
10129
11116
|
|
|
10130
11117
|
// Ray-march from the fragment toward the sun against the planet's oblate
|
|
10131
11118
|
// spheroid: warp into the pole-aligned frame so the spheroid becomes a
|
|
@@ -10166,40 +11153,49 @@ var FRAGMENT_SHADER$2 = `
|
|
|
10166
11153
|
// the outward direction of the face actually being viewed.
|
|
10167
11154
|
vec3 N = gl_FrontFacing ? vWorldNormal : -vWorldNormal;
|
|
10168
11155
|
|
|
10169
|
-
|
|
11156
|
+
float sunMu = dot(uSunDir, N);
|
|
11157
|
+
bool lit = sunMu > 0.0;
|
|
11158
|
+
float mu0 = abs(sunMu);
|
|
10170
11159
|
|
|
10171
|
-
// cosAlpha = cos(phase angle): +1 low phase, -1 high phase.
|
|
10172
11160
|
vec3 viewDir = normalize(cameraPosition - vWorldPos);
|
|
10173
|
-
float
|
|
10174
|
-
|
|
10175
|
-
vec3 finalAlbedo;
|
|
10176
|
-
if (lit) {
|
|
10177
|
-
// Blend backscatter → forward scatter with phase angle; smoothstep
|
|
10178
|
-
// over [-1, 1] centers the transition on edge-on viewing (α = 90°).
|
|
10179
|
-
// Both branches share the Cassini color profile (calibrated for
|
|
10180
|
-
// backscatter only) plus a small red bias on the forward branch,
|
|
10181
|
-
// since dropping color entirely visibly loses the ring's tan/gold
|
|
10182
|
-
// hue seen in forward-scattered Cassini imagery.
|
|
10183
|
-
vec3 colorTint = texture2D(uColor, uv).rgb;
|
|
10184
|
-
vec3 forwardTint = colorTint * FORWARD_TINT_BIAS;
|
|
10185
|
-
vec3 back = texture2D(uBackscattered, uv).rgb * colorTint;
|
|
10186
|
-
vec3 forward = texture2D(uForwardscattered, uv).rgb * forwardTint;
|
|
10187
|
-
float wForward = 1.0 - smoothstep(-1.0, 1.0, cosAlpha);
|
|
10188
|
-
finalAlbedo = mix(back, forward, wForward);
|
|
10189
|
-
} else {
|
|
10190
|
-
// unlitside already is the transmitted-light appearance; no
|
|
10191
|
-
// phase-angle blend needed.
|
|
10192
|
-
finalAlbedo = texture2D(uUnlitside, uv).rgb * UNLIT_TINT;
|
|
10193
|
-
}
|
|
11161
|
+
float mu = abs(dot(viewDir, N));
|
|
10194
11162
|
// Transparency convention: 1.0 = empty space, 0.0 = opaque.
|
|
10195
|
-
float
|
|
10196
|
-
|
|
10197
|
-
|
|
10198
|
-
|
|
11163
|
+
float opacity = clamp((1.0 - texture2D(uTransparency, uv).r) * uIntensityScale, 0.0, 1.0);
|
|
11164
|
+
float tau = max(-log(max(1.0 - opacity, 1e-6)), 1e-6);
|
|
11165
|
+
|
|
11166
|
+
vec3 colorTint = texture2D(uColor, uv).rgb;
|
|
11167
|
+
vec3 scatter = texture2D(uScatter, uv).rgb;
|
|
11168
|
+
vec3 back = scatter.r * colorTint;
|
|
11169
|
+
vec3 forward = scatter.g * opacity * colorTint * FORWARD_TINT_BIAS;
|
|
11170
|
+
vec3 unlit = scatter.b * opacity * UNLIT_TINT;
|
|
11171
|
+
vec3 sunLit = lit
|
|
11172
|
+
? litLight(back, forward, dot(uSunDir, viewDir), reflectionGain(mu0, mu, tau))
|
|
11173
|
+
: unlit * min(unlitGain(mu0, mu), 1.0);
|
|
11174
|
+
|
|
11175
|
+
// The light is the same at plus and minus an azimuth, so the texture holds its cosine.
|
|
11176
|
+
float azimuth = 0.5 - 0.5 * dot(vLocalPos.xz, uSunAzimuth) / radius;
|
|
11177
|
+
const vec2 NODES = vec2(${19}.0, ${8}.0);
|
|
11178
|
+
vec4 planet = texture2D(uPlanetLight, (vec2(azimuth, t) * (NODES - 1.0) + 0.5) / NODES);
|
|
11179
|
+
vec2 near = gl_FrontFacing ? planet.xz : planet.yw;
|
|
11180
|
+
vec2 far = gl_FrontFacing ? planet.yw : planet.xz;
|
|
11181
|
+
float planetPhase = dot(normalize(uPlanetCenter - vWorldPos), viewDir);
|
|
11182
|
+
vec3 planetLit = uPlanetAlbedo * (
|
|
11183
|
+
near.x * litLight(back, forward, planetPhase, reflectionGain(near.y, mu, tau))
|
|
11184
|
+
+ far.x * min(unlitGain(far.y, mu), 1.0) * unlit);
|
|
11185
|
+
|
|
11186
|
+
// The slant path hides more of the background.
|
|
11187
|
+
float alpha = oneMinusExp(tau / max(mu, 0.02));
|
|
11188
|
+
// Split the opacity across the sheets of the stack so that it composites
|
|
11189
|
+
// to the layer's. Each sheet adds its share of the light.
|
|
11190
|
+
float layerAlpha = 1.0 - pow(1.0 - alpha, uLayerAlphaExp);
|
|
11191
|
+
float share = alpha > 1e-4 ? layerAlpha / alpha : uLayerAlphaExp;
|
|
10199
11192
|
|
|
10200
11193
|
float shadow = planetShadow();
|
|
10201
11194
|
|
|
10202
|
-
gl_FragColor = vec4(
|
|
11195
|
+
gl_FragColor = vec4(
|
|
11196
|
+
(sunLit * shadow + planetLit) * uIntensityScale * uLightScale * share,
|
|
11197
|
+
layerAlpha
|
|
11198
|
+
);
|
|
10203
11199
|
#include <logdepthbuf_fragment>
|
|
10204
11200
|
}
|
|
10205
11201
|
`;
|
|
@@ -10306,8 +11302,11 @@ async function loadRingNode(bodyId, meta, maxTextureSize) {
|
|
|
10306
11302
|
const outerScene = kmToScene(meta.outer_radius_km);
|
|
10307
11303
|
const intensityScale = meta.intensity_scale ?? 1;
|
|
10308
11304
|
let textures;
|
|
11305
|
+
let light;
|
|
10309
11306
|
try {
|
|
10310
|
-
|
|
11307
|
+
const strip = await loadStripTextures(versionedUrl(`/v1/rings/${bodyId}/${meta.strip}`, "rings"), meta.strip_rows, maxTextureSize);
|
|
11308
|
+
textures = strip.textures;
|
|
11309
|
+
light = makeRingLight(ringProfile(strip.pixels, strip.width, meta.strip_rows, innerScene, outerScene, intensityScale));
|
|
10311
11310
|
} catch (err) {
|
|
10312
11311
|
console.warn(`Failed to load ring strip for ${bodyId}:`, err);
|
|
10313
11312
|
return null;
|
|
@@ -10316,9 +11315,7 @@ async function loadRingNode(bodyId, meta, maxTextureSize) {
|
|
|
10316
11315
|
const layers = thicknessScene > 0 ? 48 : 1;
|
|
10317
11316
|
const material = new ShaderMaterial({
|
|
10318
11317
|
uniforms: {
|
|
10319
|
-
|
|
10320
|
-
uForwardscattered: { value: textures.forwardscattered },
|
|
10321
|
-
uUnlitside: { value: textures.unlitside },
|
|
11318
|
+
uScatter: { value: textures.scatter },
|
|
10322
11319
|
uTransparency: { value: textures.transparency },
|
|
10323
11320
|
uColor: { value: textures.color },
|
|
10324
11321
|
uThickness: { value: textures.thickness ?? textures.transparency },
|
|
@@ -10334,13 +11331,17 @@ async function loadRingNode(bodyId, meta, maxTextureSize) {
|
|
|
10334
11331
|
uPlanetEquatorialScene: { value: 0 },
|
|
10335
11332
|
uPlanetPolarScene: { value: 0 },
|
|
10336
11333
|
uLightScale: { value: 1 },
|
|
10337
|
-
uIntensityScale: { value: intensityScale }
|
|
11334
|
+
uIntensityScale: { value: intensityScale },
|
|
11335
|
+
uPlanetLight: { value: light.planetLight },
|
|
11336
|
+
uPlanetAlbedo: { value: new Color(0, 0, 0) },
|
|
11337
|
+
uSunAzimuth: { value: new Vector2(1, 0) }
|
|
10338
11338
|
},
|
|
10339
11339
|
vertexShader: VERTEX_SHADER$2,
|
|
10340
11340
|
fragmentShader: FRAGMENT_SHADER$2,
|
|
10341
11341
|
transparent: true,
|
|
10342
11342
|
depthWrite: false,
|
|
10343
11343
|
blending: NormalBlending,
|
|
11344
|
+
premultipliedAlpha: true,
|
|
10344
11345
|
side: DoubleSide
|
|
10345
11346
|
});
|
|
10346
11347
|
const geometry = new RingGeometry(innerScene, outerScene * (1 / Math.cos(Math.PI / RING_ANGULAR_SEGMENTS)), RING_ANGULAR_SEGMENTS, layers > 1 ? RING_RADIAL_SEGMENTS : 1);
|
|
@@ -10371,19 +11372,20 @@ async function loadRingNode(bodyId, meta, maxTextureSize) {
|
|
|
10371
11372
|
innerScene,
|
|
10372
11373
|
outerScene,
|
|
10373
11374
|
planetShadow: null,
|
|
10374
|
-
planetShadowOnRing
|
|
11375
|
+
planetShadowOnRing,
|
|
11376
|
+
light,
|
|
11377
|
+
ringshine: null
|
|
10375
11378
|
};
|
|
10376
11379
|
}
|
|
10377
11380
|
function disposeRingNode(ring) {
|
|
10378
11381
|
ring.mesh.geometry.dispose();
|
|
10379
11382
|
const uniforms = ring.material.uniforms;
|
|
10380
11383
|
for (const key of [
|
|
10381
|
-
"
|
|
10382
|
-
"uForwardscattered",
|
|
10383
|
-
"uUnlitside",
|
|
11384
|
+
"uScatter",
|
|
10384
11385
|
"uTransparency",
|
|
10385
11386
|
"uColor",
|
|
10386
|
-
"uThickness"
|
|
11387
|
+
"uThickness",
|
|
11388
|
+
"uPlanetLight"
|
|
10387
11389
|
]) (uniforms[key]?.value)?.dispose();
|
|
10388
11390
|
ring.mesh.material.dispose();
|
|
10389
11391
|
}
|
|
@@ -10627,6 +11629,14 @@ var SHARED = {
|
|
|
10627
11629
|
uOccluders: { value: Array.from({ length: 32 }, () => new Vector4()) },
|
|
10628
11630
|
uOccluderLeak: { value: Array.from({ length: 32 }, () => new Vector4()) }
|
|
10629
11631
|
};
|
|
11632
|
+
var POOL = {
|
|
11633
|
+
occluders: [],
|
|
11634
|
+
leaks: [],
|
|
11635
|
+
count: 0
|
|
11636
|
+
};
|
|
11637
|
+
function getOccluderPool() {
|
|
11638
|
+
return POOL;
|
|
11639
|
+
}
|
|
10630
11640
|
var ECLIPSE_FACTOR_GLSL = `
|
|
10631
11641
|
#define ECLIPSE_MAX_OCCLUDERS ${32}
|
|
10632
11642
|
uniform float uSunAngularRadius;
|
|
@@ -10712,13 +11722,18 @@ function makeEclipseSelfUniforms() {
|
|
|
10712
11722
|
uOccluderCount: { value: 0 }
|
|
10713
11723
|
};
|
|
10714
11724
|
}
|
|
11725
|
+
var _kept = new Int32Array(0);
|
|
11726
|
+
var _size = new Float64Array(0);
|
|
11727
|
+
var largestFirst = (a, b) => _size[b] - _size[a];
|
|
10715
11728
|
function cullOccludersFor(dst, center, radius, sunDir, leakDst) {
|
|
10716
11729
|
const aSun = SHARED.uSunAngularRadius.value;
|
|
10717
|
-
const src =
|
|
10718
|
-
|
|
10719
|
-
|
|
11730
|
+
const src = POOL.occluders;
|
|
11731
|
+
if (_kept.length < POOL.count) {
|
|
11732
|
+
_kept = new Int32Array(POOL.count);
|
|
11733
|
+
_size = new Float64Array(POOL.count);
|
|
11734
|
+
}
|
|
10720
11735
|
let n = 0;
|
|
10721
|
-
for (let i = 0; i <
|
|
11736
|
+
for (let i = 0; i < POOL.count; i++) {
|
|
10722
11737
|
const oc = src[i];
|
|
10723
11738
|
const ox = oc.x - center.x;
|
|
10724
11739
|
const oy = oc.y - center.y;
|
|
@@ -10729,8 +11744,17 @@ function cullOccludersFor(dst, center, radius, sunDir, leakDst) {
|
|
|
10729
11744
|
if (t < -(radius + oc.w)) continue;
|
|
10730
11745
|
const reach = radius + oc.w + aSun * (t + radius) * 1.5;
|
|
10731
11746
|
if (d2 - t * t > reach * reach) continue;
|
|
10732
|
-
|
|
10733
|
-
|
|
11747
|
+
_size[i] = oc.w * oc.w / d2;
|
|
11748
|
+
_kept[n++] = i;
|
|
11749
|
+
}
|
|
11750
|
+
if (n > 32) {
|
|
11751
|
+
_kept.subarray(0, n).sort(largestFirst);
|
|
11752
|
+
n = 32;
|
|
11753
|
+
}
|
|
11754
|
+
for (let k = 0; k < n; k++) {
|
|
11755
|
+
const i = _kept[k];
|
|
11756
|
+
leakDst?.[k].copy(POOL.leaks[i]);
|
|
11757
|
+
dst[k].copy(src[i]);
|
|
10734
11758
|
}
|
|
10735
11759
|
return n;
|
|
10736
11760
|
}
|
|
@@ -11616,6 +12640,96 @@ function disposeAtmosphereNode(node) {
|
|
|
11616
12640
|
node.mesh.material.dispose();
|
|
11617
12641
|
}
|
|
11618
12642
|
|
|
12643
|
+
//#endregion
|
|
12644
|
+
//#region src/lib/scene/objects/surface/planetshine.ts
|
|
12645
|
+
var MAX_SHINERS = 2;
|
|
12646
|
+
var SHINE_FLOOR = 1e-4;
|
|
12647
|
+
function lambertSpherePhase(a) {
|
|
12648
|
+
return (Math.sin(a) + (Math.PI - a) * Math.cos(a)) / Math.PI;
|
|
12649
|
+
}
|
|
12650
|
+
function planetshineFraction(radius, distance, a) {
|
|
12651
|
+
const k = radius / distance;
|
|
12652
|
+
return 2 / 3 * lambertSpherePhase(a) * k * k;
|
|
12653
|
+
}
|
|
12654
|
+
var PLANETSHINE_GLSL = `
|
|
12655
|
+
#define PLANETSHINE_SHINERS ${2}
|
|
12656
|
+
uniform vec4 uShineDir[PLANETSHINE_SHINERS];
|
|
12657
|
+
uniform vec3 uShineLight[PLANETSHINE_SHINERS];
|
|
12658
|
+
|
|
12659
|
+
float sphereLightCosine(float cosTheta, float sinAlpha) {
|
|
12660
|
+
float t = max(cosTheta + sinAlpha, 0.0);
|
|
12661
|
+
return cosTheta >= sinAlpha ? cosTheta : t * t / (4.0 * sinAlpha);
|
|
12662
|
+
}
|
|
12663
|
+
`;
|
|
12664
|
+
var PLANETSHINE_LIGHT = `
|
|
12665
|
+
for (int i = 0; i < PLANETSHINE_SHINERS; i++) {
|
|
12666
|
+
vec4 shiner = uShineDir[i];
|
|
12667
|
+
// The slots fill in order, so the first empty slot ends the list.
|
|
12668
|
+
if (shiner.w <= 0.0) break;
|
|
12669
|
+
float cosine = sphereLightCosine(dot(geometryNormal, mat3(viewMatrix) * shiner.xyz), shiner.w);
|
|
12670
|
+
reflectedLight.indirectDiffuse += uShineLight[i] * cosine * BRDF_Lambert(material.diffuseContribution);
|
|
12671
|
+
}
|
|
12672
|
+
`;
|
|
12673
|
+
function makePlanetshineUniforms() {
|
|
12674
|
+
return {
|
|
12675
|
+
uShineDir: { value: Array.from({ length: 2 }, () => new Vector4(0, 0, 0, 0)) },
|
|
12676
|
+
uShineLight: { value: Array.from({ length: 2 }, () => new Vector3()) }
|
|
12677
|
+
};
|
|
12678
|
+
}
|
|
12679
|
+
function attachPlanetshine(material, uniforms) {
|
|
12680
|
+
const self = uniforms ?? makePlanetshineUniforms();
|
|
12681
|
+
chainShaderHook(material, "planetshine", (shader) => {
|
|
12682
|
+
Object.assign(shader.uniforms, self);
|
|
12683
|
+
shader.fragmentShader = shader.fragmentShader.replace("#include <common>", `#include <common>\n${PLANETSHINE_GLSL}`).replace("#include <lights_fragment_end>", `#include <lights_fragment_end>\n${PLANETSHINE_LIGHT}`);
|
|
12684
|
+
});
|
|
12685
|
+
return self;
|
|
12686
|
+
}
|
|
12687
|
+
var _strength = new Float64Array(2);
|
|
12688
|
+
var _swapDir = new Vector4();
|
|
12689
|
+
var _swapLight = new Vector3();
|
|
12690
|
+
function selectShiners(out, x, y, z, shiners, count) {
|
|
12691
|
+
const dirs = out.uShineDir.value;
|
|
12692
|
+
const lights = out.uShineLight.value;
|
|
12693
|
+
let kept = 0;
|
|
12694
|
+
for (let i = 0; i < count; i++) {
|
|
12695
|
+
const s = shiners[i];
|
|
12696
|
+
const dx = s.x - x;
|
|
12697
|
+
const dy = s.y - y;
|
|
12698
|
+
const dz = s.z - z;
|
|
12699
|
+
const d2 = dx * dx + dy * dy + dz * dz;
|
|
12700
|
+
if (2 / 3 * s.radius * s.radius < 1e-4 * d2) continue;
|
|
12701
|
+
const d = Math.sqrt(d2);
|
|
12702
|
+
if (d <= s.radius) continue;
|
|
12703
|
+
const k = s.radius / d;
|
|
12704
|
+
const cosPhase = -(dx * s.sunX + dy * s.sunY + dz * s.sunZ) / d;
|
|
12705
|
+
const fraction = planetshineFraction(s.radius, d, Math.acos(Math.max(-1, Math.min(1, cosPhase))));
|
|
12706
|
+
const strength = fraction * (.2126 * s.albedo.r + .7152 * s.albedo.g + .0722 * s.albedo.b);
|
|
12707
|
+
if (strength < 1e-4) continue;
|
|
12708
|
+
let slot = kept;
|
|
12709
|
+
if (kept < 2) kept++;
|
|
12710
|
+
else if (strength > _strength[2 - 1]) slot = 2 - 1;
|
|
12711
|
+
else continue;
|
|
12712
|
+
_strength[slot] = strength;
|
|
12713
|
+
dirs[slot].set(dx / d, dy / d, dz / d, k);
|
|
12714
|
+
lights[slot].set(s.albedo.r, s.albedo.g, s.albedo.b).multiplyScalar(s.sunlight * fraction);
|
|
12715
|
+
for (; slot > 0 && _strength[slot - 1] < strength; slot--) {
|
|
12716
|
+
_strength[slot] = _strength[slot - 1];
|
|
12717
|
+
_strength[slot - 1] = strength;
|
|
12718
|
+
_swapDir.copy(dirs[slot - 1]);
|
|
12719
|
+
dirs[slot - 1].copy(dirs[slot]);
|
|
12720
|
+
dirs[slot].copy(_swapDir);
|
|
12721
|
+
_swapLight.copy(lights[slot - 1]);
|
|
12722
|
+
lights[slot - 1].copy(lights[slot]);
|
|
12723
|
+
lights[slot].copy(_swapLight);
|
|
12724
|
+
}
|
|
12725
|
+
}
|
|
12726
|
+
for (let i = kept; i < 2; i++) {
|
|
12727
|
+
dirs[i].set(0, 0, 0, 0);
|
|
12728
|
+
lights[i].set(0, 0, 0);
|
|
12729
|
+
}
|
|
12730
|
+
return kept;
|
|
12731
|
+
}
|
|
12732
|
+
|
|
11619
12733
|
//#endregion
|
|
11620
12734
|
//#region src/lib/scene/objects/surface/ring-attach.ts
|
|
11621
12735
|
function attachRingBundles(bodyId, systemId, rings, radii, bo, scene, maxTextureSize, ctx) {
|
|
@@ -11635,12 +12749,15 @@ function attachRingBundles(bodyId, systemId, rings, radii, bo, scene, maxTexture
|
|
|
11635
12749
|
return;
|
|
11636
12750
|
}
|
|
11637
12751
|
node.mesh.userData.ringBundle = ringMeta.bundle;
|
|
12752
|
+
node.light.planet = ringPlanet(radii, bo.radiusScene);
|
|
11638
12753
|
const host = bo.mesh ?? bo.model;
|
|
11639
12754
|
if (host) node.mesh.quaternion.copy(host.quaternion);
|
|
11640
12755
|
bo.rings.push(node);
|
|
11641
12756
|
bo.root.add(node.mesh);
|
|
11642
12757
|
if (bo.mesh && ringMeta === shadowCaster) {
|
|
11643
|
-
|
|
12758
|
+
const material = bo.mesh.material;
|
|
12759
|
+
node.planetShadow = attachRingShadowToPlanet(material, node.innerScene, node.outerScene, node.transparency, node.intensityScale);
|
|
12760
|
+
if (peakRingshine(node.light.profile, node.light.planet) >= 1e-4) node.ringshine = attachRingshine(material);
|
|
11644
12761
|
if (bo.atmosphere) attachRingShadowToAtmosphere(bo.atmosphere, node.planetShadow, node.transparency, node.innerScene, node.outerScene);
|
|
11645
12762
|
}
|
|
11646
12763
|
if (radii) {
|
|
@@ -11651,6 +12768,15 @@ function attachRingBundles(bodyId, systemId, rings, radii, bo, scene, maxTexture
|
|
|
11651
12768
|
}
|
|
11652
12769
|
return promises;
|
|
11653
12770
|
}
|
|
12771
|
+
function ringPlanet(radii, radiusScene) {
|
|
12772
|
+
return radii ? {
|
|
12773
|
+
equatorial: kmToScene((radii.a + radii.b) / 2),
|
|
12774
|
+
polar: kmToScene(radii.c)
|
|
12775
|
+
} : {
|
|
12776
|
+
equatorial: radiusScene,
|
|
12777
|
+
polar: radiusScene
|
|
12778
|
+
};
|
|
12779
|
+
}
|
|
11654
12780
|
|
|
11655
12781
|
//#endregion
|
|
11656
12782
|
//#region src/lib/fetch/nomenclature/parse.ts
|
|
@@ -11685,7 +12811,7 @@ function parseNomenclature(buffer) {
|
|
|
11685
12811
|
|
|
11686
12812
|
//#endregion
|
|
11687
12813
|
//#region src/lib/fetch/nomenclature/fetch.ts
|
|
11688
|
-
var cache$
|
|
12814
|
+
var cache$2 = /* @__PURE__ */ new Map();
|
|
11689
12815
|
async function fetchPositions(bodyId) {
|
|
11690
12816
|
const url = versionedUrl(`/v1/nomenclature/positions/${bodyId}.bin.gz`, "nomenclature");
|
|
11691
12817
|
const res = await fetch(url);
|
|
@@ -11713,16 +12839,16 @@ function nameFeatures(records, labelText) {
|
|
|
11713
12839
|
}
|
|
11714
12840
|
function fetchBodyNomenclature(bodyId, lang = getLocale()) {
|
|
11715
12841
|
const key = `${bodyId}:${lang}`;
|
|
11716
|
-
let p = cache$
|
|
12842
|
+
let p = cache$2.get(key);
|
|
11717
12843
|
if (!p) {
|
|
11718
12844
|
p = (async () => {
|
|
11719
12845
|
await fetchMetadata();
|
|
11720
12846
|
const [records, labels] = await Promise.all([fetchPositions(bodyId), fetchLabelText(bodyId, lang)]);
|
|
11721
12847
|
return nameFeatures(records, labels);
|
|
11722
12848
|
})();
|
|
11723
|
-
cache$
|
|
12849
|
+
cache$2.set(key, p);
|
|
11724
12850
|
p.catch(() => {
|
|
11725
|
-
if (cache$
|
|
12851
|
+
if (cache$2.get(key) === p) cache$2.delete(key);
|
|
11726
12852
|
});
|
|
11727
12853
|
}
|
|
11728
12854
|
return p;
|
|
@@ -11765,6 +12891,100 @@ function attachCanvasForwarders(el, canvas) {
|
|
|
11765
12891
|
});
|
|
11766
12892
|
}
|
|
11767
12893
|
|
|
12894
|
+
//#endregion
|
|
12895
|
+
//#region src/lib/scene/relief/worker.ts?worker&inline
|
|
12896
|
+
var jsContent$1 = "function e(e,t,n,r){return`${e&&`${e}/`}${t}/${n}/${r}.webp`}function t(e,t,n,r,i=1){let a=t.length,o=n.length,s=new Float32Array(a*o*3),c=new Float32Array(a*o*3),l=new Float32Array(a*o*2),u=Float64Array.from(n,Math.sin),d=Float64Array.from(n,Math.cos);for(let f=0;f<a;f++){let a=t[f],p=Math.sin(a),m=Math.cos(a);for(let t=0;t<o;t++){let h=f*o+t,g=-d[t]*p,_=m,v=u[t]*p,y=e+(r?r[h]*i:0),b=h*3;s[b]=y*g,s[b+1]=y*_,s[b+2]=y*v,c[b]=g,c[b+1]=_,c[b+2]=v;let x=h*2;l[x]=n[t]/(2*Math.PI),l[x+1]=1-a/Math.PI}}let f=new Uint32Array((a-1)*(o-1)*6),p=0;for(let e=0;e<a-1;e++){let n=t[e]<=0,r=t[e+1]>=Math.PI;for(let t=0;t<o-1;t++){let i=e*o+t+1,a=e*o+t,s=(e+1)*o+t,c=(e+1)*o+t+1;n||(f[p++]=i,f[p++]=a,f[p++]=c),r||(f[p++]=a,f[p++]=s,f[p++]=c)}}return{positions:s,normals:c,uvs:l,indices:f.subarray(0,p)}}const n=[``,`north`,`south`],r=Math.SQRT2-1;function i(e,t){return e===0?2<<t:1<<t-1}function a(e,t){return e===0?1<<t:1<<t-1}function o(e,t,n,i){if(e===0){let e=Math.atan2(i,-t)/(2*Math.PI);return{x:e<0?e+1:e,y:Math.acos(Math.min(Math.max(n,-1),1))/Math.PI}}let a=e===1?1:-1,o=.5/(r*(1+a*n));return{x:.5+t*o,y:.5+a*i*o}}function s(e,t,n,r){let i=e.max_level-t;return i>=0&&n>=e.x[0]>>i&&n<=e.x[1]>>i&&r>=e.y[0]>>i&&r<=e.y[1]>>i}function c(e,t,n,r){return e?.find(e=>s(e,t,n,r))}const l=Math.sin(60*Math.PI/180),u=2**18,d=2**17;function f(e,t,n,r){return((e*32+t)*u+n)*d+r}function p(e){let t=e%d,n=Math.floor(e/d)%u,r=Math.floor(e/(d*u));return{chart:Math.floor(r/32),level:r%32,x:n,y:t}}const m={chart:0,level:0,x0:0,x1:0,y0:0,y1:0,fx:0,fy:0};function h(e,t,n,r,s){let c=e<1||Math.abs(n)<=l?0:n>0?1:2,u=i(c,e)*s,d=a(c,e)*s,f=o(c,t,n,r),p=f.x*u-.5,h=f.y*d-.5,g=Math.floor(p),_=Math.floor(h),v=e=>Math.min(Math.max(e,0),u-1),y=e=>Math.min(Math.max(e,0),d-1);return m.chart=c,m.level=e,m.fx=p-g,m.fy=h-_,m.x0=c===0?(g+u)%u:v(g),m.x1=c===0?(g+1)%u:v(g+1),m.y0=y(_),m.y1=y(_+1),m}function g(e,t,n){let r=Float64Array.from(t.at,Math.sin),i=Float64Array.from(t.at,Math.cos),a=t.at.length;for(let o=0;o<e.at.length;o++){let s=Math.sin(e.at[o]),c=Math.cos(e.at[o]);for(let l=0;l<a;l++){let u=Math.min(e.level[o],t.level[l]);n(o*a+l,u,-i[l]*s,c,r[l]*s)}}}function _(e,t,n,r=1/0,i=()=>!0){let a=new Set([f(0,0,0,0),f(0,0,1,0)]);return g(e,t,(e,t,o,s,c)=>{for(let e=t;;e--){let t=h(e,o,s,c,n),l=Math.floor(t.x0/n),u=Math.floor(t.x1/n),d=Math.floor(t.y0/n),p=Math.floor(t.y1/n);if(!(e>r&&!(i(t.chart,e,l,d)&&i(t.chart,e,u,d)&&i(t.chart,e,l,p)&&i(t.chart,e,u,p)))){a.add(f(t.chart,e,l,d)),u!==l&&a.add(f(t.chart,e,u,d)),p!==d&&(a.add(f(t.chart,e,l,p)),u!==l&&a.add(f(t.chart,e,u,p)));return}}}),a}function v(e,t,n,r,i,a){for(let o=t;o>=0;o--){let t=h(o,n,r,i,a),s=(n,r)=>{let i=e(f(t.chart,o,Math.floor(n/a),Math.floor(r/a)));return i&&i[r%a*a+n%a]},c=s(t.x0,t.y0),l=s(t.x1,t.y0),u=s(t.x0,t.y1),d=s(t.x1,t.y1);if(c===void 0||l===void 0||u===void 0||d===void 0)continue;let p=c+(l-c)*t.fx;return p+(u+(d-u)*t.fx-p)*t.fy}}function y(e,t,n,r,i,a){let o=new Float32Array(e.at.length*t.at.length),s=!1;return g(e,t,(e,t,c,l,u)=>{let d=v(n,t,c,l,u,r);d===void 0?s=!0:o[e]=a+i*d/65535}),s?null:o}function b(e,t){let n=new Uint8Array(t*t*2);for(let r=0;r<t;r++){let i=(t-1-r)*t*4,a=r*t*2;for(let r=0;r<t;r++,i+=4,a+=2)n[a]=e[i],n[a+1]=e[i+1]}return n}function x(e,t){let n=new Float32Array(t*t);for(let r=0;r<t;r++){let i=(t-1-r)*t*4,a=(r+1)*t;for(let o=r*t;o<a;o++,i+=4)n[o]=(e[i]<<8|e[i+1])+e[i+2]/256}return n}function S(e,t,n){let r=n?new Float32Array(t*t):new Uint16Array(t*t);for(let t=0,i=0;t<r.length;t++,i+=4){let a=e[i]<<8|e[i+1];r[t]=n?a+e[i+2]/256:a}return r}const C=self,w=new Map;let T;async function E(e,t){let n=await fetch(e,{signal:t});if(!n.ok)throw Error(`tile ${n.status}`);let r=await createImageBitmap(await n.blob(),{premultiplyAlpha:`none`,colorSpaceConversion:`none`}),i=r.width;T?.width!==i&&(T=new OffscreenCanvas(i,i));let a=T.getContext(`2d`,{willReadFrequently:!0});if(!a)throw Error(`no 2d canvas in this worker`);return a.globalCompositeOperation=`copy`,a.drawImage(r,0,0),r.close(),{rgba:a.getImageData(0,0,i,i).data,size:i}}async function D(e,t){let{rgba:n,size:r}=await E(e.url,t),i=e.fine?x(n,r):b(n,r);C.postMessage({type:`tile`,id:e.id,size:r,heights:i},[i.buffer])}const O=new Map;let k=``;async function A(r,i){let{rows:a,columns:o,tileSize:s,maxLevel:l,patches:u}=r,d=[r.version,...u.map(e=>e.version)],f=`${r.root}?${d.join()}`;f!==k&&O.clear(),k=f;let m=(e,t,n,r)=>e===0?c(u,t,n,r):void 0,h=_(a,o,s,l,(e,t,n,r)=>m(e,t,n,r)!==void 0),g=[...h].filter(e=>!O.has(e));await Promise.all(Array.from({length:6},async()=>{for(let t=g.pop();t!==void 0;t=g.pop()){let{chart:a,level:o,x:s,y:c}=p(t),u=o>l,d=u?m(a,o,s,c)?.version:r.version,f=`${r.root}${e(n[a],o,s,c)}?v=${d}`;try{let{rgba:e,size:n}=await E(f,i);O.set(t,S(e,n,u))}catch{if(i.aborted)return}}})),i.throwIfAborted();let v=y(a,o,e=>O.get(e),s,r.scaleKm,r.biasKm);for(let e of[...O.keys()])h.has(e)||O.delete(e);if(!v)throw Error(`no height tiles for the grid`);let b=t(r.radius,a.at,o.at,v,r.unitsPerKm),x=b.indices.slice();C.postMessage({type:`grid`,id:r.id,...b,indices:x,riseKm:v},[b.positions.buffer,b.normals.buffer,b.uvs.buffer,x.buffer,v.buffer])}async function j(e){let t=new AbortController;w.set(e.id,t);try{e.type===`tile`?await D(e,t.signal):await A(e,t.signal)}catch{C.postMessage({type:`failed`,id:e.id})}finally{w.delete(e.id)}}self.onmessage=e=>{let t=e.data;t.type===`abort`?w.get(t.id)?.abort():j(t)};";
|
|
12897
|
+
var blob$1 = typeof self !== "undefined" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", jsContent$1], { type: "text/javascript;charset=utf-8" });
|
|
12898
|
+
function WorkerWrapper$1(options) {
|
|
12899
|
+
let objURL;
|
|
12900
|
+
try {
|
|
12901
|
+
objURL = blob$1 && (self.URL || self.webkitURL).createObjectURL(blob$1);
|
|
12902
|
+
if (!objURL) throw "";
|
|
12903
|
+
const worker = new Worker(objURL, {
|
|
12904
|
+
type: "module",
|
|
12905
|
+
name: options?.name
|
|
12906
|
+
});
|
|
12907
|
+
worker.addEventListener("error", () => {
|
|
12908
|
+
(self.URL || self.webkitURL).revokeObjectURL(objURL);
|
|
12909
|
+
});
|
|
12910
|
+
return worker;
|
|
12911
|
+
} catch (e) {
|
|
12912
|
+
return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(jsContent$1), {
|
|
12913
|
+
type: "module",
|
|
12914
|
+
name: options?.name
|
|
12915
|
+
});
|
|
12916
|
+
}
|
|
12917
|
+
}
|
|
12918
|
+
|
|
12919
|
+
//#endregion
|
|
12920
|
+
//#region src/lib/scene/relief/client.ts
|
|
12921
|
+
var worker = null;
|
|
12922
|
+
var nextId = 1;
|
|
12923
|
+
var pending$1 = /* @__PURE__ */ new Map();
|
|
12924
|
+
function drop(reason) {
|
|
12925
|
+
worker?.terminate();
|
|
12926
|
+
worker = null;
|
|
12927
|
+
const lost = [...pending$1.values()];
|
|
12928
|
+
pending$1.clear();
|
|
12929
|
+
for (const { reject } of lost) reject(new Error(reason));
|
|
12930
|
+
}
|
|
12931
|
+
function ensureWorker() {
|
|
12932
|
+
if (worker) return worker;
|
|
12933
|
+
worker = new WorkerWrapper$1();
|
|
12934
|
+
worker.onmessage = (ev) => {
|
|
12935
|
+
const msg = ev.data;
|
|
12936
|
+
const request = pending$1.get(msg.id);
|
|
12937
|
+
pending$1.delete(msg.id);
|
|
12938
|
+
if (!request) return;
|
|
12939
|
+
if (msg.type === "failed") request.reject(/* @__PURE__ */ new Error("relief worker could not answer"));
|
|
12940
|
+
else request.resolve(msg);
|
|
12941
|
+
};
|
|
12942
|
+
worker.onerror = (ev) => drop(`relief worker error: ${ev.message || "unknown"}`);
|
|
12943
|
+
worker.onmessageerror = () => drop("relief worker sent a message that could not be read");
|
|
12944
|
+
return worker;
|
|
12945
|
+
}
|
|
12946
|
+
function ask(build, signal) {
|
|
12947
|
+
return new Promise((resolve, reject) => {
|
|
12948
|
+
if (typeof Worker === "undefined") {
|
|
12949
|
+
reject(/* @__PURE__ */ new Error("no workers here"));
|
|
12950
|
+
return;
|
|
12951
|
+
}
|
|
12952
|
+
const id = nextId++;
|
|
12953
|
+
pending$1.set(id, {
|
|
12954
|
+
resolve,
|
|
12955
|
+
reject
|
|
12956
|
+
});
|
|
12957
|
+
signal.addEventListener("abort", () => {
|
|
12958
|
+
if (!pending$1.delete(id)) return;
|
|
12959
|
+
ensureWorker().postMessage({
|
|
12960
|
+
type: "abort",
|
|
12961
|
+
id
|
|
12962
|
+
});
|
|
12963
|
+
reject(new DOMException("aborted", "AbortError"));
|
|
12964
|
+
}, { once: true });
|
|
12965
|
+
ensureWorker().postMessage(build(id));
|
|
12966
|
+
});
|
|
12967
|
+
}
|
|
12968
|
+
function absolute(url) {
|
|
12969
|
+
return new URL(url, location.href).href;
|
|
12970
|
+
}
|
|
12971
|
+
function loadHeightTile(url, fine, signal) {
|
|
12972
|
+
return ask((id) => ({
|
|
12973
|
+
type: "tile",
|
|
12974
|
+
id,
|
|
12975
|
+
url: absolute(url),
|
|
12976
|
+
fine
|
|
12977
|
+
}), signal);
|
|
12978
|
+
}
|
|
12979
|
+
function buildTerrainGrid(spec, signal) {
|
|
12980
|
+
return ask((id) => ({
|
|
12981
|
+
...spec,
|
|
12982
|
+
type: "grid",
|
|
12983
|
+
id,
|
|
12984
|
+
root: absolute(spec.root)
|
|
12985
|
+
}), signal);
|
|
12986
|
+
}
|
|
12987
|
+
|
|
11768
12988
|
//#endregion
|
|
11769
12989
|
//#region src/lib/scene/lod/tile-window.ts
|
|
11770
12990
|
var WINDOW_TILES = 4;
|
|
@@ -11919,100 +13139,6 @@ function slotTile(placement, sx, sy) {
|
|
|
11919
13139
|
};
|
|
11920
13140
|
}
|
|
11921
13141
|
|
|
11922
|
-
//#endregion
|
|
11923
|
-
//#region src/lib/scene/relief/worker.ts?worker&inline
|
|
11924
|
-
var jsContent$1 = "function e(e,t,n,r){return`${e&&`${e}/`}${t}/${n}/${r}.webp`}function t(e,t,n,r,i=1){let a=t.length,o=n.length,s=new Float32Array(a*o*3),c=new Float32Array(a*o*3),l=new Float32Array(a*o*2),u=Float64Array.from(n,Math.sin),d=Float64Array.from(n,Math.cos);for(let f=0;f<a;f++){let a=t[f],p=Math.sin(a),m=Math.cos(a);for(let t=0;t<o;t++){let h=f*o+t,g=-d[t]*p,_=m,v=u[t]*p,y=e+(r?r[h]*i:0),b=h*3;s[b]=y*g,s[b+1]=y*_,s[b+2]=y*v,c[b]=g,c[b+1]=_,c[b+2]=v;let x=h*2;l[x]=n[t]/(2*Math.PI),l[x+1]=1-a/Math.PI}}let f=new Uint32Array((a-1)*(o-1)*6),p=0;for(let e=0;e<a-1;e++){let n=t[e]<=0,r=t[e+1]>=Math.PI;for(let t=0;t<o-1;t++){let i=e*o+t+1,a=e*o+t,s=(e+1)*o+t,c=(e+1)*o+t+1;n||(f[p++]=i,f[p++]=a,f[p++]=c),r||(f[p++]=a,f[p++]=s,f[p++]=c)}}return{positions:s,normals:c,uvs:l,indices:f.subarray(0,p)}}const n=[``,`north`,`south`],r=Math.SQRT2-1;function i(e,t){return e===0?2<<t:1<<t-1}function a(e,t){return e===0?1<<t:1<<t-1}function o(e,t,n,i){if(e===0){let e=Math.atan2(i,-t)/(2*Math.PI);return{x:e<0?e+1:e,y:Math.acos(Math.min(Math.max(n,-1),1))/Math.PI}}let a=e===1?1:-1,o=.5/(r*(1+a*n));return{x:.5+t*o,y:.5+a*i*o}}function s(e,t,n,r){let i=e.max_level-t;return i>=0&&n>=e.x[0]>>i&&n<=e.x[1]>>i&&r>=e.y[0]>>i&&r<=e.y[1]>>i}function c(e,t,n,r){return e?.find(e=>s(e,t,n,r))}const l=Math.sin(60*Math.PI/180),u=2**18,d=2**17;function f(e,t,n,r){return((e*32+t)*u+n)*d+r}function p(e){let t=e%d,n=Math.floor(e/d)%u,r=Math.floor(e/(d*u));return{chart:Math.floor(r/32),level:r%32,x:n,y:t}}const m={chart:0,level:0,x0:0,x1:0,y0:0,y1:0,fx:0,fy:0};function h(e,t,n,r,s){let c=e<1||Math.abs(n)<=l?0:n>0?1:2,u=i(c,e)*s,d=a(c,e)*s,f=o(c,t,n,r),p=f.x*u-.5,h=f.y*d-.5,g=Math.floor(p),_=Math.floor(h),v=e=>Math.min(Math.max(e,0),u-1),y=e=>Math.min(Math.max(e,0),d-1);return m.chart=c,m.level=e,m.fx=p-g,m.fy=h-_,m.x0=c===0?(g+u)%u:v(g),m.x1=c===0?(g+1)%u:v(g+1),m.y0=y(_),m.y1=y(_+1),m}function g(e,t,n){let r=Float64Array.from(t.at,Math.sin),i=Float64Array.from(t.at,Math.cos),a=t.at.length;for(let o=0;o<e.at.length;o++){let s=Math.sin(e.at[o]),c=Math.cos(e.at[o]);for(let l=0;l<a;l++){let u=Math.min(e.level[o],t.level[l]);n(o*a+l,u,-i[l]*s,c,r[l]*s)}}}function _(e,t,n,r=1/0,i=()=>!0){let a=new Set([f(0,0,0,0),f(0,0,1,0)]);return g(e,t,(e,t,o,s,c)=>{for(let e=t;;e--){let t=h(e,o,s,c,n),l=Math.floor(t.x0/n),u=Math.floor(t.x1/n),d=Math.floor(t.y0/n),p=Math.floor(t.y1/n);if(!(e>r&&!(i(t.chart,e,l,d)&&i(t.chart,e,u,d)&&i(t.chart,e,l,p)&&i(t.chart,e,u,p)))){a.add(f(t.chart,e,l,d)),u!==l&&a.add(f(t.chart,e,u,d)),p!==d&&(a.add(f(t.chart,e,l,p)),u!==l&&a.add(f(t.chart,e,u,p)));return}}}),a}function v(e,t,n,r,i,a){for(let o=t;o>=0;o--){let t=h(o,n,r,i,a),s=(n,r)=>{let i=e(f(t.chart,o,Math.floor(n/a),Math.floor(r/a)));return i&&i[r%a*a+n%a]},c=s(t.x0,t.y0),l=s(t.x1,t.y0),u=s(t.x0,t.y1),d=s(t.x1,t.y1);if(c===void 0||l===void 0||u===void 0||d===void 0)continue;let p=c+(l-c)*t.fx;return p+(u+(d-u)*t.fx-p)*t.fy}}function y(e,t,n,r,i,a){let o=new Float32Array(e.at.length*t.at.length),s=!1;return g(e,t,(e,t,c,l,u)=>{let d=v(n,t,c,l,u,r);d===void 0?s=!0:o[e]=a+i*d/65535}),s?null:o}function b(e,t){let n=new Uint8Array(t*t*2);for(let r=0;r<t;r++){let i=(t-1-r)*t*4,a=r*t*2;for(let r=0;r<t;r++,i+=4,a+=2)n[a]=e[i],n[a+1]=e[i+1]}return n}function x(e,t){let n=new Float32Array(t*t);for(let r=0;r<t;r++){let i=(t-1-r)*t*4,a=(r+1)*t;for(let o=r*t;o<a;o++,i+=4)n[o]=(e[i]<<8|e[i+1])+e[i+2]/256}return n}function S(e,t,n){let r=n?new Float32Array(t*t):new Uint16Array(t*t);for(let t=0,i=0;t<r.length;t++,i+=4){let a=e[i]<<8|e[i+1];r[t]=n?a+e[i+2]/256:a}return r}const C=self,w=new Map;let T;async function E(e,t){let n=await fetch(e,{signal:t});if(!n.ok)throw Error(`tile ${n.status}`);let r=await createImageBitmap(await n.blob(),{premultiplyAlpha:`none`,colorSpaceConversion:`none`}),i=r.width;T?.width!==i&&(T=new OffscreenCanvas(i,i));let a=T.getContext(`2d`,{willReadFrequently:!0});if(!a)throw Error(`no 2d canvas in this worker`);return a.globalCompositeOperation=`copy`,a.drawImage(r,0,0),r.close(),{rgba:a.getImageData(0,0,i,i).data,size:i}}async function D(e,t){let{rgba:n,size:r}=await E(e.url,t),i=e.fine?x(n,r):b(n,r);C.postMessage({type:`tile`,id:e.id,size:r,heights:i},[i.buffer])}const O=new Map;let k=``;async function A(r,i){let{rows:a,columns:o,tileSize:s,maxLevel:l,patches:u}=r,d=[r.version,...u.map(e=>e.version)],f=`${r.root}?${d.join()}`;f!==k&&O.clear(),k=f;let m=(e,t,n,r)=>e===0?c(u,t,n,r):void 0,h=_(a,o,s,l,(e,t,n,r)=>m(e,t,n,r)!==void 0),g=[...h].filter(e=>!O.has(e));await Promise.all(Array.from({length:6},async()=>{for(let t=g.pop();t!==void 0;t=g.pop()){let{chart:a,level:o,x:s,y:c}=p(t),u=o>l,d=u?m(a,o,s,c)?.version:r.version,f=`${r.root}${e(n[a],o,s,c)}?v=${d}`;try{let{rgba:e,size:n}=await E(f,i);O.set(t,S(e,n,u))}catch{if(i.aborted)return}}})),i.throwIfAborted();let v=y(a,o,e=>O.get(e),s,r.scaleKm,r.biasKm);for(let e of[...O.keys()])h.has(e)||O.delete(e);if(!v)throw Error(`no height tiles for the grid`);let b=t(r.radius,a.at,o.at,v,r.unitsPerKm),x=b.indices.slice();C.postMessage({type:`grid`,id:r.id,...b,indices:x,riseKm:v},[b.positions.buffer,b.normals.buffer,b.uvs.buffer,x.buffer,v.buffer])}async function j(e){let t=new AbortController;w.set(e.id,t);try{e.type===`tile`?await D(e,t.signal):await A(e,t.signal)}catch{C.postMessage({type:`failed`,id:e.id})}finally{w.delete(e.id)}}self.onmessage=e=>{let t=e.data;t.type===`abort`?w.get(t.id)?.abort():j(t)};";
|
|
11925
|
-
var blob$1 = typeof self !== "undefined" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", jsContent$1], { type: "text/javascript;charset=utf-8" });
|
|
11926
|
-
function WorkerWrapper$1(options) {
|
|
11927
|
-
let objURL;
|
|
11928
|
-
try {
|
|
11929
|
-
objURL = blob$1 && (self.URL || self.webkitURL).createObjectURL(blob$1);
|
|
11930
|
-
if (!objURL) throw "";
|
|
11931
|
-
const worker = new Worker(objURL, {
|
|
11932
|
-
type: "module",
|
|
11933
|
-
name: options?.name
|
|
11934
|
-
});
|
|
11935
|
-
worker.addEventListener("error", () => {
|
|
11936
|
-
(self.URL || self.webkitURL).revokeObjectURL(objURL);
|
|
11937
|
-
});
|
|
11938
|
-
return worker;
|
|
11939
|
-
} catch (e) {
|
|
11940
|
-
return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(jsContent$1), {
|
|
11941
|
-
type: "module",
|
|
11942
|
-
name: options?.name
|
|
11943
|
-
});
|
|
11944
|
-
}
|
|
11945
|
-
}
|
|
11946
|
-
|
|
11947
|
-
//#endregion
|
|
11948
|
-
//#region src/lib/scene/relief/client.ts
|
|
11949
|
-
var worker = null;
|
|
11950
|
-
var nextId = 1;
|
|
11951
|
-
var pending$1 = /* @__PURE__ */ new Map();
|
|
11952
|
-
function drop(reason) {
|
|
11953
|
-
worker?.terminate();
|
|
11954
|
-
worker = null;
|
|
11955
|
-
const lost = [...pending$1.values()];
|
|
11956
|
-
pending$1.clear();
|
|
11957
|
-
for (const { reject } of lost) reject(new Error(reason));
|
|
11958
|
-
}
|
|
11959
|
-
function ensureWorker() {
|
|
11960
|
-
if (worker) return worker;
|
|
11961
|
-
worker = new WorkerWrapper$1();
|
|
11962
|
-
worker.onmessage = (ev) => {
|
|
11963
|
-
const msg = ev.data;
|
|
11964
|
-
const request = pending$1.get(msg.id);
|
|
11965
|
-
pending$1.delete(msg.id);
|
|
11966
|
-
if (!request) return;
|
|
11967
|
-
if (msg.type === "failed") request.reject(/* @__PURE__ */ new Error("relief worker could not answer"));
|
|
11968
|
-
else request.resolve(msg);
|
|
11969
|
-
};
|
|
11970
|
-
worker.onerror = (ev) => drop(`relief worker error: ${ev.message || "unknown"}`);
|
|
11971
|
-
worker.onmessageerror = () => drop("relief worker sent a message that could not be read");
|
|
11972
|
-
return worker;
|
|
11973
|
-
}
|
|
11974
|
-
function ask(build, signal) {
|
|
11975
|
-
return new Promise((resolve, reject) => {
|
|
11976
|
-
if (typeof Worker === "undefined") {
|
|
11977
|
-
reject(/* @__PURE__ */ new Error("no workers here"));
|
|
11978
|
-
return;
|
|
11979
|
-
}
|
|
11980
|
-
const id = nextId++;
|
|
11981
|
-
pending$1.set(id, {
|
|
11982
|
-
resolve,
|
|
11983
|
-
reject
|
|
11984
|
-
});
|
|
11985
|
-
signal.addEventListener("abort", () => {
|
|
11986
|
-
if (!pending$1.delete(id)) return;
|
|
11987
|
-
ensureWorker().postMessage({
|
|
11988
|
-
type: "abort",
|
|
11989
|
-
id
|
|
11990
|
-
});
|
|
11991
|
-
reject(new DOMException("aborted", "AbortError"));
|
|
11992
|
-
}, { once: true });
|
|
11993
|
-
ensureWorker().postMessage(build(id));
|
|
11994
|
-
});
|
|
11995
|
-
}
|
|
11996
|
-
function absolute(url) {
|
|
11997
|
-
return new URL(url, location.href).href;
|
|
11998
|
-
}
|
|
11999
|
-
function loadHeightTile(url, fine, signal) {
|
|
12000
|
-
return ask((id) => ({
|
|
12001
|
-
type: "tile",
|
|
12002
|
-
id,
|
|
12003
|
-
url: absolute(url),
|
|
12004
|
-
fine
|
|
12005
|
-
}), signal);
|
|
12006
|
-
}
|
|
12007
|
-
function buildTerrainGrid(spec, signal) {
|
|
12008
|
-
return ask((id) => ({
|
|
12009
|
-
...spec,
|
|
12010
|
-
type: "grid",
|
|
12011
|
-
id,
|
|
12012
|
-
root: absolute(spec.root)
|
|
12013
|
-
}), signal);
|
|
12014
|
-
}
|
|
12015
|
-
|
|
12016
13142
|
//#endregion
|
|
12017
13143
|
//#region src/lib/scene/render-tier.ts
|
|
12018
13144
|
var RENDER_TIER_PRESETS = {
|
|
@@ -12103,37 +13229,28 @@ var TILE_CHAIN_GLSL = `
|
|
|
12103
13229
|
#ifndef TILE_CHAIN
|
|
12104
13230
|
#define TILE_CHAIN
|
|
12105
13231
|
|
|
12106
|
-
//
|
|
12107
|
-
//
|
|
12108
|
-
// the cap is from the chart's north-west corner. The place on the map is from
|
|
12109
|
-
// the point that the maker of the charts counts from.
|
|
12110
|
-
struct TileCharts {
|
|
12111
|
-
vec2 mapAt;
|
|
12112
|
-
vec2 mapDx;
|
|
12113
|
-
vec2 mapDy;
|
|
12114
|
-
vec2 capAt;
|
|
12115
|
-
vec2 capDx;
|
|
12116
|
-
vec2 capDy;
|
|
12117
|
-
float side;
|
|
12118
|
-
};
|
|
13232
|
+
// A fragment on one chart is a mat3x2: its place, as a fraction of the
|
|
13233
|
+
// chart, then what a screen pixel adds to that along x and along y.
|
|
12119
13234
|
|
|
12120
|
-
// The cap of the hemisphere of dir, seen from above its pole
|
|
12121
|
-
// what a screen pixel
|
|
12122
|
-
|
|
13235
|
+
// The cap of the hemisphere of dir, seen from above its pole: the place is
|
|
13236
|
+
// from the chart's north-west corner. ddx and ddy are what a screen pixel
|
|
13237
|
+
// adds to dir.
|
|
13238
|
+
void tileCap( vec3 dir, vec3 ddx, vec3 ddy, out float side, out mat3x2 cap ) {
|
|
12123
13239
|
side = dir.y < 0.0 ? - 1.0 : 1.0;
|
|
12124
13240
|
float fold = 1.0 + side * dir.y;
|
|
12125
13241
|
vec2 plane = vec2( dir.x, side * dir.z );
|
|
12126
13242
|
float capScale = 0.5 / ( ${CAP_EDGE.toFixed(8)} * fold );
|
|
12127
|
-
|
|
12128
|
-
|
|
12129
|
-
|
|
13243
|
+
cap = mat3x2(
|
|
13244
|
+
0.5 + plane * capScale,
|
|
13245
|
+
( vec2( ddx.x, side * ddx.z ) - plane * ( side * ddx.y / fold ) ) * capScale,
|
|
13246
|
+
( vec2( ddy.x, side * ddy.z ) - plane * ( side * ddy.y / fold ) ) * capScale
|
|
13247
|
+
);
|
|
12130
13248
|
}
|
|
12131
13249
|
|
|
12132
|
-
// The
|
|
12133
|
-
//
|
|
12134
|
-
// the offset keeps its own.
|
|
12135
|
-
|
|
12136
|
-
TileCharts charts;
|
|
13250
|
+
// The point at + off on the map, counted from at, and on the cap of its own
|
|
13251
|
+
// hemisphere, which side gives. A position on the sphere has seven digits,
|
|
13252
|
+
// and a tile index of a patch takes them all; the offset keeps its own.
|
|
13253
|
+
void tileChartsFrom( vec3 at, vec3 off, out mat3x2 map, out mat3x2 cap, out float side ) {
|
|
12137
13254
|
vec3 pos = at + off;
|
|
12138
13255
|
vec3 ox = dFdx( off );
|
|
12139
13256
|
vec3 oy = dFdy( off );
|
|
@@ -12146,19 +13263,20 @@ TileCharts tileChartsFrom( vec3 at, vec3 off ) {
|
|
|
12146
13263
|
float turn = atan( at.z * off.x - at.x * off.z, at.x * pos.x + at.z * pos.z );
|
|
12147
13264
|
float out1 = ( 2.0 * ( at.x * off.x + at.z * off.z ) + off.x * off.x + off.z * off.z ) / ( flat1 + flat0 );
|
|
12148
13265
|
float drop = atan( out1 * at.y - off.y * flat0, pos.y * at.y + flat1 * flat0 );
|
|
12149
|
-
charts.mapAt = vec2( turn / ( 2.0 * PI ), drop / PI );
|
|
12150
13266
|
float east = 1.0 / ( 2.0 * PI * flat2 );
|
|
12151
13267
|
float south = 1.0 / ( PI * dot( pos, pos ) );
|
|
12152
|
-
|
|
12153
|
-
|
|
13268
|
+
map = mat3x2(
|
|
13269
|
+
turn / ( 2.0 * PI ), drop / PI,
|
|
13270
|
+
( pos.z * ox.x - pos.x * ox.z ) * east, ( pos.y * ( pos.x * ox.x + pos.z * ox.z ) / flat1 - flat1 * ox.y ) * south,
|
|
13271
|
+
( pos.z * oy.x - pos.x * oy.z ) * east, ( pos.y * ( pos.x * oy.x + pos.z * oy.z ) / flat1 - flat1 * oy.y ) * south
|
|
13272
|
+
);
|
|
12154
13273
|
|
|
12155
13274
|
// A cap goes no deeper than the pyramid, so the direction itself will do.
|
|
12156
13275
|
float range = length( pos );
|
|
12157
13276
|
vec3 dir = pos / range;
|
|
12158
13277
|
vec3 ddx = ( ox - dir * dot( dir, ox ) ) / range;
|
|
12159
13278
|
vec3 ddy = ( oy - dir * dot( dir, oy ) ) / range;
|
|
12160
|
-
tileCap( dir, ddx, ddy,
|
|
12161
|
-
return charts;
|
|
13279
|
+
tileCap( dir, ddx, ddy, side, cap );
|
|
12162
13280
|
}
|
|
12163
13281
|
|
|
12164
13282
|
// Long and short half-axes of the footprint whose sides are fx and fy. The
|
|
@@ -12182,12 +13300,13 @@ void tileAxes( vec2 fx, vec2 fy, out vec2 major, out vec2 minor ) {
|
|
|
12182
13300
|
// home is the point that the charts count the map from, in tiles from the
|
|
12183
13301
|
// window's north-west corner. Gives the fragment's place in the window's
|
|
12184
13302
|
// texture, in tiles, and the axes of its footprint, in the window's pixels.
|
|
12185
|
-
float tileWindowWeight(
|
|
13303
|
+
float tileWindowWeight( mat3x2 map, mat3x2 cap, float side, vec4 window, vec4 grid, vec2 home, vec2 tileFilter, out vec2 spot, out vec2 major, out vec2 minor ) {
|
|
12186
13304
|
bool onMap = window.x < 0.5;
|
|
12187
13305
|
// The other pole's cap.
|
|
12188
|
-
if ( ! onMap && ( window.x < 1.5 ) != (
|
|
12189
|
-
|
|
12190
|
-
vec2
|
|
13306
|
+
if ( ! onMap && ( window.x < 1.5 ) != ( side > 0.0 ) ) return 0.0;
|
|
13307
|
+
mat3x2 chart = onMap ? map : cap;
|
|
13308
|
+
vec2 dx = chart[ 1 ] * grid.xy * tileFilter.y;
|
|
13309
|
+
vec2 dy = chart[ 2 ] * grid.xy * tileFilter.y;
|
|
12191
13310
|
|
|
12192
13311
|
// Level this fragment asks of the window, from the short axis of its
|
|
12193
13312
|
// footprint in the window's pixels: the long axis is the anisotropic
|
|
@@ -12200,7 +13319,7 @@ float tileWindowWeight( TileCharts charts, vec4 window, vec4 grid, vec2 home, ve
|
|
|
12200
13319
|
|
|
12201
13320
|
float rows = ${4 .toFixed(1)};
|
|
12202
13321
|
// Offset from the window's north-west corner, in tiles.
|
|
12203
|
-
vec2 rel = onMap ? home +
|
|
13322
|
+
vec2 rel = onMap ? home + chart[ 0 ] * grid.xy : chart[ 0 ] * grid.xy - grid.zw;
|
|
12204
13323
|
if ( onMap ) {
|
|
12205
13324
|
// Half a pixel in from a pole of the map: past it the filter would
|
|
12206
13325
|
// read the far row. The map's longitude wraps.
|
|
@@ -12398,6 +13517,11 @@ function disposeChain(chain) {
|
|
|
12398
13517
|
chain.uniforms.map.value = null;
|
|
12399
13518
|
chain.uniforms.mask.value = null;
|
|
12400
13519
|
}
|
|
13520
|
+
function chainSettled(chain, tiles) {
|
|
13521
|
+
const store = chain.store;
|
|
13522
|
+
if (!store || chain.dead || chain.uniforms.window.value[0].w === 0) return true;
|
|
13523
|
+
return store.windows.every((win) => settled(chain, store, tiles, win));
|
|
13524
|
+
}
|
|
12401
13525
|
function restChain(chain, now) {
|
|
12402
13526
|
switchOff(chain);
|
|
12403
13527
|
if (now - chain.lastUsed > IDLE_DISPOSE_S * 1e3) disposeChain(chain);
|
|
@@ -12511,40 +13635,35 @@ float reliefValue( vec4 texel ) {
|
|
|
12511
13635
|
return dot( texel, uReliefRead );
|
|
12512
13636
|
}
|
|
12513
13637
|
|
|
12514
|
-
// How the coordinates of each chart change along the sphere at a direction
|
|
12515
|
-
//
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
vec3 mapY;
|
|
12519
|
-
vec3 capX;
|
|
12520
|
-
vec3 capY;
|
|
12521
|
-
};
|
|
12522
|
-
|
|
12523
|
-
ReliefRates reliefRates( vec3 dir, float side ) {
|
|
12524
|
-
ReliefRates rates;
|
|
13638
|
+
// How the coordinates of each chart change along the sphere at a direction,
|
|
13639
|
+
// as a mat2x3 per chart: a step along the sphere times it is that step on the
|
|
13640
|
+
// chart, and it times a step on the chart is that step along the sphere.
|
|
13641
|
+
void reliefRates( vec3 dir, float side, out mat2x3 map, out mat2x3 cap ) {
|
|
12525
13642
|
float flat2 = max( dir.x * dir.x + dir.z * dir.z, 1e-12 );
|
|
12526
|
-
|
|
12527
|
-
|
|
13643
|
+
map = mat2x3(
|
|
13644
|
+
vec3( dir.z, 0.0, - dir.x ) / ( 2.0 * PI * flat2 ),
|
|
13645
|
+
( dir * dir.y - vec3( 0.0, 1.0, 0.0 ) ) / ( PI * sqrt( flat2 ) )
|
|
13646
|
+
);
|
|
12528
13647
|
float fold = 1.0 + side * dir.y;
|
|
12529
13648
|
float capScale = 0.5 / ( ${CAP_EDGE.toFixed(8)} * fold );
|
|
12530
13649
|
vec2 plane = vec2( dir.x, side * dir.z ) * side / fold;
|
|
12531
|
-
|
|
12532
|
-
|
|
12533
|
-
|
|
12534
|
-
rates.capY -= dir * dot( rates.capY, dir );
|
|
12535
|
-
return rates;
|
|
13650
|
+
vec3 capX = vec3( 1.0, - plane.x, 0.0 ) * capScale;
|
|
13651
|
+
vec3 capY = vec3( 0.0, - plane.y, side ) * capScale;
|
|
13652
|
+
cap = mat2x3( capX - dir * dot( capX, dir ), capY - dir * dot( capY, dir ) );
|
|
12536
13653
|
}
|
|
12537
13654
|
|
|
12538
13655
|
// Slope of the ground at a direction of the body's frame: a vector along the
|
|
12539
13656
|
// unit sphere that points uphill, as long as the rise over the run. Also
|
|
12540
13657
|
// gives the part of the fragment that the tiles answer for, and the finest
|
|
12541
13658
|
// window that does, or -1.
|
|
12542
|
-
vec3 reliefTileSlope( vec3 dir,
|
|
13659
|
+
vec3 reliefTileSlope( vec3 dir, mat3x2 map, mat3x2 cap, float side, out float covered, out int first ) {
|
|
12543
13660
|
covered = 0.0;
|
|
12544
13661
|
first = - 1;
|
|
12545
13662
|
vec3 slope = vec3( 0.0 );
|
|
12546
13663
|
if ( uReliefWindow[ 0 ].w < 0.5 ) return slope;
|
|
12547
|
-
|
|
13664
|
+
mat2x3 mapRates;
|
|
13665
|
+
mat2x3 capRates;
|
|
13666
|
+
reliefRates( dir, side, mapRates, capRates );
|
|
12548
13667
|
|
|
12549
13668
|
float rows = ${4 .toFixed(1)};
|
|
12550
13669
|
for ( int i = 0; i < ${7}; i ++ ) {
|
|
@@ -12554,7 +13673,7 @@ vec3 reliefTileSlope( vec3 dir, TileCharts charts, out float covered, out int fi
|
|
|
12554
13673
|
vec2 spot;
|
|
12555
13674
|
vec2 major;
|
|
12556
13675
|
vec2 minor;
|
|
12557
|
-
float alpha = tileWindowWeight(
|
|
13676
|
+
float alpha = tileWindowWeight( map, cap, side, window, grid, uReliefHome[ i ], uReliefFilter, spot, major, minor );
|
|
12558
13677
|
if ( alpha <= 0.0 ) continue;
|
|
12559
13678
|
// Filtered, the mask falls towards a missing tile. The pixels beside
|
|
12560
13679
|
// one are left out: their slope would read its blank slot.
|
|
@@ -12573,8 +13692,7 @@ vec3 reliefTileSlope( vec3 dir, TileCharts charts, out float covered, out int fi
|
|
|
12573
13692
|
reliefValue( textureGrad( uReliefMap, st + east, gx, gy ) ) - reliefValue( textureGrad( uReliefMap, st - east, gx, gy ) ),
|
|
12574
13693
|
reliefValue( textureGrad( uReliefMap, st + south, gx, gy ) ) - reliefValue( textureGrad( uReliefMap, st - south, gx, gy ) )
|
|
12575
13694
|
) * 0.5 * grid.xy * uReliefFilter.y;
|
|
12576
|
-
|
|
12577
|
-
vec3 uphill = rise.x * ( onMap ? rates.mapX : rates.capX ) + rise.y * ( onMap ? rates.mapY : rates.capY );
|
|
13695
|
+
vec3 uphill = ( window.x < 0.5 ? mapRates : capRates ) * rise;
|
|
12578
13696
|
slope += ( 1.0 - covered ) * alpha * uphill;
|
|
12579
13697
|
covered += ( 1.0 - covered ) * alpha;
|
|
12580
13698
|
if ( covered > 0.995 ) break;
|
|
@@ -12586,25 +13704,14 @@ function shadowGlsl(steps) {
|
|
|
12586
13704
|
return `
|
|
12587
13705
|
// One window as a shadow ray reads it. The ray is a line on the window's
|
|
12588
13706
|
// chart, so where it is inside the window is worked out once, not at each
|
|
12589
|
-
// sample.
|
|
12590
|
-
|
|
12591
|
-
|
|
12592
|
-
|
|
12593
|
-
|
|
12594
|
-
|
|
12595
|
-
|
|
12596
|
-
|
|
12597
|
-
float leaves;
|
|
12598
|
-
// The longest step that the window's pixels still hold, and the step from
|
|
12599
|
-
// which the ray reads the next window.
|
|
12600
|
-
float widest;
|
|
12601
|
-
float hands;
|
|
12602
|
-
// How far from the fragment the next window can be read at all.
|
|
12603
|
-
float beyond;
|
|
12604
|
-
int loaded;
|
|
12605
|
-
};
|
|
12606
|
-
|
|
12607
|
-
ReliefSight reliefSight( int i, TileCharts charts, vec2 mapStep, vec2 capStep ) {
|
|
13707
|
+
// sample. 'sight' holds what a sample reads, as a mat2x4 and not a struct
|
|
13708
|
+
// (see the chain code): the fragment's place in the window's texture and how
|
|
13709
|
+
// far the ray goes there in a radian; then the part of the ray inside the
|
|
13710
|
+
// window, in radians along it, the window's layer and its tiles that are in,
|
|
13711
|
+
// a bit each. 'widest' is the longest step that the window's pixels still
|
|
13712
|
+
// hold, 'hands' the step from which the ray reads the next window, and
|
|
13713
|
+
// 'beyond' how far from the fragment the next window can be read at all.
|
|
13714
|
+
void reliefSight( int i, mat3x2 map, mat3x2 cap, float side, vec2 mapStep, vec2 capStep, out mat2x4 sight, out float widest, out float hands, out float beyond ) {
|
|
12608
13715
|
vec4 window = uReliefWindow[ i ];
|
|
12609
13716
|
vec4 grid = uReliefGrid[ i ];
|
|
12610
13717
|
bool onMap = window.x < 0.5;
|
|
@@ -12612,7 +13719,7 @@ ReliefSight reliefSight( int i, TileCharts charts, vec2 mapStep, vec2 capStep )
|
|
|
12612
13719
|
// In tiles from the window's north-west corner. The map is counted from
|
|
12613
13720
|
// the point under the camera, so the fragment is on the side of the globe
|
|
12614
13721
|
// nearest the window.
|
|
12615
|
-
vec2 rel = onMap ? uReliefHome[ i ] +
|
|
13722
|
+
vec2 rel = onMap ? uReliefHome[ i ] + map[ 0 ] * grid.xy : cap[ 0 ] * grid.xy - grid.zw;
|
|
12616
13723
|
vec2 rate = ( onMap ? mapStep : capStep ) * grid.xy;
|
|
12617
13724
|
|
|
12618
13725
|
// Half a pixel in from the window's sides: past it the filter reads the
|
|
@@ -12624,51 +13731,50 @@ ReliefSight reliefSight( int i, TileCharts charts, vec2 mapStep, vec2 capStep )
|
|
|
12624
13731
|
vec2 near = min( a, b );
|
|
12625
13732
|
vec2 far = max( a, b );
|
|
12626
13733
|
|
|
12627
|
-
ReliefSight sight;
|
|
12628
13734
|
// The texture repeats every window. The tile index of a patch alone takes
|
|
12629
13735
|
// all the digits of a float: only its place in the window is added.
|
|
12630
13736
|
vec2 slot = rel + mod( grid.zw, rows );
|
|
12631
|
-
|
|
12632
|
-
sight.rate = vec2( rate.x, - rate.y ) / rows;
|
|
12633
|
-
sight.enters = max( near.x, near.y );
|
|
12634
|
-
sight.leaves = min( far.x, far.y );
|
|
13737
|
+
float leaves = min( far.x, far.y );
|
|
12635
13738
|
// The other pole's cap holds none of the ray.
|
|
12636
|
-
if ( ! onMap && ( window.x < 1.5 ) != (
|
|
12637
|
-
sight
|
|
13739
|
+
if ( ! onMap && ( window.x < 1.5 ) != ( side > 0.0 ) ) leaves = - 1.0;
|
|
13740
|
+
sight = mat2x4(
|
|
13741
|
+
slot.x / rows, - slot.y / rows, rate.x / rows, - rate.y / rows,
|
|
13742
|
+
max( near.x, near.y ), leaves, window.y, float( uReliefLoaded[ i ] )
|
|
13743
|
+
);
|
|
13744
|
+
widest = ${STEP_PIXELS.toFixed(2)} * PI / ( uReliefFilter.y * exp2( window.z ) );
|
|
12638
13745
|
// Near a patch the next window can be some levels coarser. The ray then
|
|
12639
13746
|
// stays here until its step is half of what that window holds: too wide
|
|
12640
13747
|
// for these pixels, but they are the same ground as the fragment's. The
|
|
12641
13748
|
// pyramid around a patch is not: it has none of the hills that only the
|
|
12642
13749
|
// patch resolves, and close to the fragment it would stand in the ray.
|
|
12643
|
-
|
|
12644
|
-
|
|
13750
|
+
hands = widest;
|
|
13751
|
+
beyond = 0.0;
|
|
12645
13752
|
if ( i + 1 < ${7} ) {
|
|
12646
13753
|
float next = PI / ( uReliefFilter.y * exp2( uReliefWindow[ i + 1 ].z ) );
|
|
12647
|
-
|
|
13754
|
+
hands = max( hands, 0.5 * ${STEP_PIXELS.toFixed(2)} * next );
|
|
12648
13755
|
// Within half a pixel of a window, its height is that of the fragment's
|
|
12649
13756
|
// own pixel, and the fragment stands above or below that by all the
|
|
12650
13757
|
// relief that the pixel averages away.
|
|
12651
|
-
|
|
13758
|
+
beyond = 0.5 * next;
|
|
12652
13759
|
}
|
|
12653
|
-
sight.loaded = uReliefLoaded[ i ];
|
|
12654
|
-
return sight;
|
|
12655
13760
|
}
|
|
12656
13761
|
|
|
12657
13762
|
// Height of the ground 't' radians along the ray, as a part of the pyramid's
|
|
12658
13763
|
// range. Negative where the window does not hold that ground.
|
|
12659
|
-
float reliefSightValue(
|
|
12660
|
-
if ( t < sight.
|
|
12661
|
-
vec2 st = sight.
|
|
13764
|
+
float reliefSightValue( mat2x4 sight, float t ) {
|
|
13765
|
+
if ( t < sight[ 1 ].x || t > sight[ 1 ].y ) return - 1.0;
|
|
13766
|
+
vec2 st = sight[ 0 ].xy + t * sight[ 0 ].zw;
|
|
12662
13767
|
// Both tiles that the filter can read must be in.
|
|
12663
|
-
if ( sight.
|
|
13768
|
+
if ( sight[ 1 ].w != ${((1 << 4 * 4) - 1).toFixed(1)} ) {
|
|
13769
|
+
int loaded = int( sight[ 1 ].w );
|
|
12664
13770
|
vec2 tile = vec2( st.x, - st.y ) * ${4 .toFixed(1)};
|
|
12665
13771
|
float inset = 0.5 / uReliefFilter.y;
|
|
12666
13772
|
ivec2 a = ivec2( floor( tile - inset ) ) & ${4 - 1};
|
|
12667
13773
|
ivec2 b = ivec2( floor( tile + inset ) ) & ${4 - 1};
|
|
12668
|
-
int both = (
|
|
13774
|
+
int both = ( loaded >> ( a.x + ${4} * a.y ) ) & ( loaded >> ( b.x + ${4} * b.y ) );
|
|
12669
13775
|
if ( ( both & 1 ) == 0 ) return - 1.0;
|
|
12670
13776
|
}
|
|
12671
|
-
return reliefValue( textureLod( uReliefMap, vec3( st, sight.
|
|
13777
|
+
return reliefValue( textureLod( uReliefMap, vec3( st, sight[ 1 ].z ), 0.0 ) );
|
|
12672
13778
|
}
|
|
12673
13779
|
|
|
12674
13780
|
// Part of the Sun's disc that the ground leaves in sight of the fragment at
|
|
@@ -12681,23 +13787,28 @@ float reliefSightValue( ReliefSight sight, float t ) {
|
|
|
12681
13787
|
// read from the window whose pixels are about as wide as the step. A shadow
|
|
12682
13788
|
// is then sharp beside what casts it, at a cost that does not grow with its
|
|
12683
13789
|
// length.
|
|
12684
|
-
float reliefTileShadow( vec3 dir,
|
|
12685
|
-
|
|
12686
|
-
|
|
12687
|
-
|
|
13790
|
+
float reliefTileShadow( vec3 dir, mat3x2 map, mat3x2 cap, float side, vec3 toSun, float tanElev, float sunSize, int first ) {
|
|
13791
|
+
mat2x3 mapRates;
|
|
13792
|
+
mat2x3 capRates;
|
|
13793
|
+
reliefRates( dir, side, mapRates, capRates );
|
|
13794
|
+
vec2 mapStep = toSun * mapRates;
|
|
13795
|
+
vec2 capStep = toSun * capRates;
|
|
12688
13796
|
|
|
12689
13797
|
int drawn = 0;
|
|
12690
13798
|
for ( int i = 0; i < ${7}; i ++ ) {
|
|
12691
13799
|
if ( uReliefWindow[ i ].w > 0.5 ) drawn = i + 1;
|
|
12692
13800
|
}
|
|
12693
13801
|
int w = first;
|
|
12694
|
-
|
|
13802
|
+
mat2x4 sight;
|
|
13803
|
+
float widest;
|
|
13804
|
+
float hands;
|
|
13805
|
+
float beyond;
|
|
12695
13806
|
float own = - 1.0;
|
|
12696
13807
|
for ( int i = 0; i < ${7}; i ++ ) {
|
|
12697
13808
|
if ( i < first ) continue;
|
|
12698
13809
|
if ( i >= drawn ) break;
|
|
12699
13810
|
w = i;
|
|
12700
|
-
|
|
13811
|
+
reliefSight( i, map, cap, side, mapStep, capStep, sight, widest, hands, beyond );
|
|
12701
13812
|
own = reliefSightValue( sight, 0.0 );
|
|
12702
13813
|
if ( own >= 0.0 ) break;
|
|
12703
13814
|
}
|
|
@@ -12714,7 +13825,7 @@ float reliefTileShadow( vec3 dir, TileCharts charts, vec3 toSun, float tanElev,
|
|
|
12714
13825
|
// The ratio that takes steps from one pixel to the reach: 'rate' is its
|
|
12715
13826
|
// logarithm times the count, and solves rate / ( exp( rate ) - 1 ) = part.
|
|
12716
13827
|
float count = ${steps.toFixed(1)};
|
|
12717
|
-
float pixel =
|
|
13828
|
+
float pixel = widest / ${STEP_PIXELS.toFixed(2)};
|
|
12718
13829
|
float part = count * pixel / reach;
|
|
12719
13830
|
float rate = 0.0;
|
|
12720
13831
|
if ( part < 1.0 ) {
|
|
@@ -12738,16 +13849,16 @@ float reliefTileShadow( vec3 dir, TileCharts charts, vec3 toSun, float tanElev,
|
|
|
12738
13849
|
for ( int i = 1; i <= ${steps}; i ++ ) {
|
|
12739
13850
|
float before = t;
|
|
12740
13851
|
t = t * ratio + head;
|
|
12741
|
-
if ( w + 1 < drawn && t - before >
|
|
13852
|
+
if ( w + 1 < drawn && t - before > hands ) {
|
|
12742
13853
|
w ++;
|
|
12743
|
-
|
|
13854
|
+
reliefSight( w, map, cap, side, mapStep, capStep, sight, widest, hands, beyond );
|
|
12744
13855
|
}
|
|
12745
13856
|
float value = reliefSightValue( sight, t );
|
|
12746
13857
|
// The ray left this window, or a tile of it is missing.
|
|
12747
13858
|
if ( value < 0.0 && w + 1 < drawn ) {
|
|
12748
|
-
if ( t <
|
|
13859
|
+
if ( t < beyond ) continue;
|
|
12749
13860
|
w ++;
|
|
12750
|
-
|
|
13861
|
+
reliefSight( w, map, cap, side, mapStep, capStep, sight, widest, hands, beyond );
|
|
12751
13862
|
value = reliefSightValue( sight, t );
|
|
12752
13863
|
}
|
|
12753
13864
|
if ( value < 0.0 ) continue;
|
|
@@ -12769,19 +13880,19 @@ float reliefTileShadow( vec3 dir, TileCharts charts, vec3 toSun, float tanElev,
|
|
|
12769
13880
|
float crest = ${(STEEPEST * .5).toFixed(2)} * around / max( worst, 1e-9 ) * perDisc;
|
|
12770
13881
|
if ( hidden < 1.0 && hidden + crest > - 1.0 ) {
|
|
12771
13882
|
w = worstWindow;
|
|
12772
|
-
|
|
13883
|
+
reliefSight( w, map, cap, side, mapStep, capStep, sight, widest, hands, beyond );
|
|
12773
13884
|
for ( int k = 0; k < ${REFINE_STEPS}; k ++ ) {
|
|
12774
13885
|
around *= 0.5;
|
|
12775
|
-
if ( w > start && around <
|
|
13886
|
+
if ( w > start && around < widest ) {
|
|
12776
13887
|
w --;
|
|
12777
|
-
|
|
13888
|
+
reliefSight( w, map, cap, side, mapStep, capStep, sight, widest, hands, beyond );
|
|
12778
13889
|
}
|
|
12779
13890
|
float centre = worst;
|
|
12780
13891
|
for ( int e = 0; e < 2; e ++ ) {
|
|
12781
13892
|
float at = centre + ( e == 0 ? - around : around );
|
|
12782
13893
|
// Nearer than a pixel, the window holds no crest: only the slope
|
|
12783
13894
|
// of the fragment's own ground, which is the normal's to light.
|
|
12784
|
-
if ( at <
|
|
13895
|
+
if ( at < widest * ${(1 / STEP_PIXELS).toFixed(4)} ) continue;
|
|
12785
13896
|
float value = reliefSightValue( sight, at );
|
|
12786
13897
|
if ( value < 0.0 ) continue;
|
|
12787
13898
|
float stands = ( ( value - own ) * uReliefScale / at - tanElev - 0.5 * at ) * perDisc;
|
|
@@ -12895,7 +14006,7 @@ var TILE_LIGHT = `
|
|
|
12895
14006
|
float up = dot(sunward, selfDir);
|
|
12896
14007
|
vec3 along = sunward - selfDir * up;
|
|
12897
14008
|
float run = length(along);
|
|
12898
|
-
if (run > 1e-4) tileLight = reliefTileShadow(selfDir,
|
|
14009
|
+
if (run > 1e-4) tileLight = reliefTileShadow(selfDir, selfMap, selfCap, selfSide, along / run, up / run, uSelfSunSize, selfFirst);
|
|
12899
14010
|
if (tileLight < 0.0) byTiles = 0.0;
|
|
12900
14011
|
}`;
|
|
12901
14012
|
function attachSelfShadowToBody(material, heightMap, scaleScene, sunDir, tiles) {
|
|
@@ -13029,10 +14140,10 @@ function attachSelfShadowToBody(material, heightMap, scaleScene, sunDir, tiles)
|
|
|
13029
14140
|
vec3 selfDir = normalize(vSelfDir);
|
|
13030
14141
|
// The part of the fragment that the tiles answer for.
|
|
13031
14142
|
float selfCovered = 0.0;
|
|
13032
|
-
${tiles ? "
|
|
14143
|
+
${tiles ? "mat3x2 selfMap;\n mat3x2 selfCap;\n float selfSide;\n tileChartsFrom(uReliefAnchor, vReliefOff, selfMap, selfCap, selfSide);\n int selfFirst = -1;" : ""}
|
|
13033
14144
|
{
|
|
13034
14145
|
vec3 slope = vec3(0.0);
|
|
13035
|
-
${tiles ? "slope = reliefTileSlope(selfDir,
|
|
14146
|
+
${tiles ? "slope = reliefTileSlope(selfDir, selfMap, selfCap, selfSide, selfCovered, selfFirst);" : ""}
|
|
13036
14147
|
if (selfCovered < 0.995 && uSelfScale > 0.0) slope += (1.0 - selfCovered) * selfMapSlope(selfDir);
|
|
13037
14148
|
float steep = length(slope);
|
|
13038
14149
|
if (steep > ${SLOPE_CLAMP.toFixed(3)}) slope *= ${SLOPE_CLAMP.toFixed(3)} / steep;
|
|
@@ -13125,34 +14236,23 @@ async function readHeightRows(bitmap, y0, y1) {
|
|
|
13125
14236
|
}
|
|
13126
14237
|
return out;
|
|
13127
14238
|
}
|
|
14239
|
+
var PYRAMID_TIER = "pyramid";
|
|
14240
|
+
var pyramidFailed = /* @__PURE__ */ new WeakSet();
|
|
14241
|
+
function pyramidHeightsServe(bo, renderer) {
|
|
14242
|
+
const tiles = bo.displacementMeta?.tiles;
|
|
14243
|
+
return !!tiles && tiles.scale_km !== void 0 && tilesBase() !== "" && textureAllowed(tiles.distribution) && renderer.extensions.has("OES_texture_float_linear") && !pyramidFailed.has(bo);
|
|
14244
|
+
}
|
|
13128
14245
|
async function swapDisplacementTier(bo, tier) {
|
|
13129
14246
|
const meta = bo.displacementMeta;
|
|
13130
14247
|
if (!meta || !bo.mesh || bo.displacementLoading || bo.displacementTier === tier) return;
|
|
13131
14248
|
bo.displacementLoading = true;
|
|
13132
14249
|
try {
|
|
13133
|
-
const
|
|
13134
|
-
if (!
|
|
13135
|
-
|
|
13136
|
-
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
if (!rows) return;
|
|
13140
|
-
if (!bo.mesh || !bo.displacementMap) return;
|
|
13141
|
-
const tmp = new Uint8Array(w);
|
|
13142
|
-
for (let y = 0; y < h >> 1; y++) {
|
|
13143
|
-
const top = rows.subarray(y * w, (y + 1) * w);
|
|
13144
|
-
const bottom = rows.subarray((h - 1 - y) * w, (h - y) * w);
|
|
13145
|
-
tmp.set(top);
|
|
13146
|
-
top.set(bottom);
|
|
13147
|
-
bottom.set(tmp);
|
|
13148
|
-
}
|
|
13149
|
-
const tex = new DataTexture(rows, w, h, RedFormat, UnsignedByteType);
|
|
13150
|
-
tex.colorSpace = NoColorSpace;
|
|
13151
|
-
tex.magFilter = LinearFilter;
|
|
13152
|
-
tex.minFilter = LinearFilter;
|
|
13153
|
-
tex.generateMipmaps = false;
|
|
13154
|
-
tex.unpackAlignment = 1;
|
|
13155
|
-
tex.needsUpdate = true;
|
|
14250
|
+
const tex = tier === "pyramid" ? await pyramidMap(bo, meta) : await tierMap(meta, tier);
|
|
14251
|
+
if (!tex) return;
|
|
14252
|
+
if (!bo.mesh || !bo.displacementMap) {
|
|
14253
|
+
tex.dispose();
|
|
14254
|
+
return;
|
|
14255
|
+
}
|
|
13156
14256
|
const material = bo.mesh.material;
|
|
13157
14257
|
const old = material.displacementMap;
|
|
13158
14258
|
material.displacementMap = tex;
|
|
@@ -13164,6 +14264,96 @@ async function swapDisplacementTier(bo, tier) {
|
|
|
13164
14264
|
bo.displacementLoading = false;
|
|
13165
14265
|
}
|
|
13166
14266
|
}
|
|
14267
|
+
async function tierMap(meta, tier) {
|
|
14268
|
+
const bitmap = await fetchHeightBitmap(displacementTierUrl(meta, tier));
|
|
14269
|
+
if (!bitmap) return null;
|
|
14270
|
+
const w = bitmap.width;
|
|
14271
|
+
const h = bitmap.height;
|
|
14272
|
+
const rows = await readHeightRows(bitmap, 0, h - 1);
|
|
14273
|
+
bitmap.close();
|
|
14274
|
+
if (!rows) return null;
|
|
14275
|
+
const tmp = new Uint8Array(w);
|
|
14276
|
+
for (let y = 0; y < h >> 1; y++) {
|
|
14277
|
+
const top = rows.subarray(y * w, (y + 1) * w);
|
|
14278
|
+
const bottom = rows.subarray((h - 1 - y) * w, (h - y) * w);
|
|
14279
|
+
tmp.set(top);
|
|
14280
|
+
top.set(bottom);
|
|
14281
|
+
bottom.set(tmp);
|
|
14282
|
+
}
|
|
14283
|
+
const tex = new DataTexture(rows, w, h, RedFormat, UnsignedByteType);
|
|
14284
|
+
tex.colorSpace = NoColorSpace;
|
|
14285
|
+
tex.magFilter = LinearFilter;
|
|
14286
|
+
tex.minFilter = LinearFilter;
|
|
14287
|
+
tex.generateMipmaps = false;
|
|
14288
|
+
tex.unpackAlignment = 1;
|
|
14289
|
+
tex.needsUpdate = true;
|
|
14290
|
+
return tex;
|
|
14291
|
+
}
|
|
14292
|
+
async function pyramidMap(bo, meta) {
|
|
14293
|
+
if (!meta.tiles) return null;
|
|
14294
|
+
try {
|
|
14295
|
+
return await pyramidHeights(meta, meta.tiles);
|
|
14296
|
+
} catch (err) {
|
|
14297
|
+
console.warn(`Failed to load the height pyramid of ${meta.id}:`, err);
|
|
14298
|
+
pyramidFailed.add(bo);
|
|
14299
|
+
return null;
|
|
14300
|
+
}
|
|
14301
|
+
}
|
|
14302
|
+
async function pyramidHeights(meta, tiles) {
|
|
14303
|
+
const signal = new AbortController().signal;
|
|
14304
|
+
const halves = await Promise.all([0, 1].map((x) => loadHeightTile(tileUrl(tiles, "", 0, x, 0), true, signal)));
|
|
14305
|
+
const size = halves[0].size;
|
|
14306
|
+
const width = 2 * size;
|
|
14307
|
+
const data = new Float32Array(width * size);
|
|
14308
|
+
const gain = (tiles.scale_km ?? 0) / 65535 / meta.scale_km;
|
|
14309
|
+
const offset = ((tiles.bias_km ?? 0) - meta.bias_km) / meta.scale_km;
|
|
14310
|
+
halves.forEach(({ heights }, x) => {
|
|
14311
|
+
for (let row = 0; row < size; row++) {
|
|
14312
|
+
const src = row * size;
|
|
14313
|
+
const dst = row * width + x * size;
|
|
14314
|
+
for (let i = 0; i < size; i++) data[dst + i] = heights[src + i] * gain + offset;
|
|
14315
|
+
}
|
|
14316
|
+
});
|
|
14317
|
+
const tex = new DataTexture(data, width, size, RedFormat, FloatType);
|
|
14318
|
+
tex.colorSpace = NoColorSpace;
|
|
14319
|
+
tex.magFilter = LinearFilter;
|
|
14320
|
+
tex.minFilter = LinearMipmapLinearFilter;
|
|
14321
|
+
tex.generateMipmaps = false;
|
|
14322
|
+
tex.mipmaps = mipChain(data, width, size);
|
|
14323
|
+
tex.needsUpdate = true;
|
|
14324
|
+
return tex;
|
|
14325
|
+
}
|
|
14326
|
+
function mipChain(data, width, height) {
|
|
14327
|
+
const chain = [{
|
|
14328
|
+
data,
|
|
14329
|
+
width,
|
|
14330
|
+
height
|
|
14331
|
+
}];
|
|
14332
|
+
while (width > 1 || height > 1) {
|
|
14333
|
+
const w = Math.max(1, width >> 1);
|
|
14334
|
+
const h = Math.max(1, height >> 1);
|
|
14335
|
+
const sx = width / w;
|
|
14336
|
+
const sy = height / h;
|
|
14337
|
+
const out = new Float32Array(w * h);
|
|
14338
|
+
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
14339
|
+
let sum = 0;
|
|
14340
|
+
for (let dy = 0; dy < sy; dy++) {
|
|
14341
|
+
const row = (y * sy + dy) * width + x * sx;
|
|
14342
|
+
for (let dx = 0; dx < sx; dx++) sum += data[row + dx];
|
|
14343
|
+
}
|
|
14344
|
+
out[y * w + x] = sum / (sx * sy);
|
|
14345
|
+
}
|
|
14346
|
+
chain.push({
|
|
14347
|
+
data: out,
|
|
14348
|
+
width: w,
|
|
14349
|
+
height: h
|
|
14350
|
+
});
|
|
14351
|
+
data = out;
|
|
14352
|
+
width = w;
|
|
14353
|
+
height = h;
|
|
14354
|
+
}
|
|
14355
|
+
return chain;
|
|
14356
|
+
}
|
|
13167
14357
|
function bilinearHeightTexel(data, w, h, fx, fy) {
|
|
13168
14358
|
const x0 = Math.floor(fx);
|
|
13169
14359
|
const y0 = Math.floor(fy);
|
|
@@ -13177,7 +14367,8 @@ function bilinearHeightTexel(data, w, h, fx, fy) {
|
|
|
13177
14367
|
const r1 = clampRow(y0 + 1) * w;
|
|
13178
14368
|
const top = data[r0 + c0] * (1 - tx) + data[r0 + c1] * tx;
|
|
13179
14369
|
const bot = data[r1 + c0] * (1 - tx) + data[r1 + c1] * tx;
|
|
13180
|
-
|
|
14370
|
+
const texel = top * (1 - ty) + bot * ty;
|
|
14371
|
+
return data instanceof Float32Array ? texel : texel / 255;
|
|
13181
14372
|
}
|
|
13182
14373
|
function disposeDisplacementFromMaterial(material) {
|
|
13183
14374
|
if (!material.displacementMap) return;
|
|
@@ -13367,8 +14558,9 @@ function loadLowField(bodyId, meta) {
|
|
|
13367
14558
|
function heightFieldFor(bo, bodyId) {
|
|
13368
14559
|
const image = bo.displacementMap?.image;
|
|
13369
14560
|
if (!image) return null;
|
|
13370
|
-
|
|
13371
|
-
|
|
14561
|
+
const data = image.data;
|
|
14562
|
+
if ((data instanceof Uint8Array || data instanceof Float32Array) && image.width && image.height) return {
|
|
14563
|
+
data,
|
|
13372
14564
|
width: image.width,
|
|
13373
14565
|
height: image.height,
|
|
13374
14566
|
bottomUp: true
|
|
@@ -13864,20 +15056,24 @@ var AttitudeTrack = class {
|
|
|
13864
15056
|
this.files = manifest.files;
|
|
13865
15057
|
}
|
|
13866
15058
|
covers(jd) {
|
|
13867
|
-
return
|
|
15059
|
+
return this.coversTdb(utcToTdb(jd));
|
|
15060
|
+
}
|
|
15061
|
+
coversTdb(tdb) {
|
|
15062
|
+
return tdb >= this.startJd && tdb <= this.endJd && this.files.length > 0;
|
|
13868
15063
|
}
|
|
13869
15064
|
orientationAt(jd, out) {
|
|
13870
|
-
|
|
13871
|
-
|
|
15065
|
+
const tdb = utcToTdb(jd);
|
|
15066
|
+
if (!this.coversTdb(tdb)) return false;
|
|
15067
|
+
const ci = this.fileIndexFor(tdb);
|
|
13872
15068
|
const chunk = this.ensure(ci);
|
|
13873
15069
|
if (!chunk) return false;
|
|
13874
15070
|
this.ensure(ci - 1);
|
|
13875
15071
|
this.ensure(ci + 1);
|
|
13876
|
-
this.sampleChunk(
|
|
15072
|
+
this.sampleChunk(tdb, ci, chunk);
|
|
13877
15073
|
const baseline = this.baselines?.[this.files[ci].baseline_index ?? 0];
|
|
13878
15074
|
if (baseline) {
|
|
13879
15075
|
const { axis, rate_rad_s, anchor, anchor_jd } = baseline;
|
|
13880
|
-
const tSeconds = (
|
|
15076
|
+
const tSeconds = (tdb - anchor_jd) * SECONDS_PER_DAY;
|
|
13881
15077
|
_baselineAxis.set(axis[0], axis[1], axis[2]);
|
|
13882
15078
|
_qBaseline.setFromAxisAngle(_baselineAxis, rate_rad_s * tSeconds);
|
|
13883
15079
|
_qb.set(anchor[1], anchor[2], anchor[3], anchor[0]);
|
|
@@ -14152,29 +15348,6 @@ function setSurfaceMap(material, map, tintHex) {
|
|
|
14152
15348
|
material.needsUpdate = true;
|
|
14153
15349
|
}
|
|
14154
15350
|
|
|
14155
|
-
//#endregion
|
|
14156
|
-
//#region src/lib/scene/objects/body/shape-model-policy.ts
|
|
14157
|
-
var PREFER_MODEL_OVER_DEM = /* @__PURE__ */ new Set([]);
|
|
14158
|
-
function shapeModelSkipReason(global) {
|
|
14159
|
-
if (!global?.model_name) return "no-bundle";
|
|
14160
|
-
if (isLowEndDevice() && global.render_quality !== "high") return "low-end-device";
|
|
14161
|
-
if (global.displacement && !PREFER_MODEL_OVER_DEM.has(global.id)) return "dem-preferred";
|
|
14162
|
-
return null;
|
|
14163
|
-
}
|
|
14164
|
-
|
|
14165
|
-
//#endregion
|
|
14166
|
-
//#region src/lib/scene/objects/body/orientation-apply.ts
|
|
14167
|
-
function applyBodyOrientation(body, orientation, ctx, systemId) {
|
|
14168
|
-
body.orientation = orientation;
|
|
14169
|
-
if (ctx) ctx.bodies.dataVersion++;
|
|
14170
|
-
ctx?.credits.registerOrientation({
|
|
14171
|
-
bodyId: body.data.id,
|
|
14172
|
-
systemId: systemId ?? body.data.id,
|
|
14173
|
-
source: orientation.source,
|
|
14174
|
-
reference: orientation.reference
|
|
14175
|
-
});
|
|
14176
|
-
}
|
|
14177
|
-
|
|
14178
15351
|
//#endregion
|
|
14179
15352
|
//#region src/lib/scene/objects/surface/photometry.ts
|
|
14180
15353
|
var WEIGHT_POLY = [
|
|
@@ -14184,16 +15357,24 @@ var WEIGHT_POLY = [
|
|
|
14184
15357
|
];
|
|
14185
15358
|
var GRAZE_FLOOR = .05;
|
|
14186
15359
|
var LUNAR_LAMBERT_GLSL = `
|
|
14187
|
-
float lunarLambertWeight(float phaseDeg) {
|
|
14188
|
-
return clamp(1.0 + phaseDeg * (${WEIGHT_POLY[0].toFixed(8)} + phaseDeg * (${WEIGHT_POLY[1].toFixed(8)} + phaseDeg * ${WEIGHT_POLY[2].toFixed(8)})), 0.0, 1.0);
|
|
15360
|
+
float lunarLambertWeight(float phaseDeg, float scale) {
|
|
15361
|
+
return min(scale * clamp(1.0 + phaseDeg * (${WEIGHT_POLY[0].toFixed(8)} + phaseDeg * (${WEIGHT_POLY[1].toFixed(8)} + phaseDeg * ${WEIGHT_POLY[2].toFixed(8)})), 0.0, 1.0), 1.0);
|
|
14189
15362
|
}
|
|
14190
15363
|
|
|
14191
|
-
float lunarLambertGain(float phaseDeg, float mu0, float mu) {
|
|
14192
|
-
float weight = lunarLambertWeight(phaseDeg);
|
|
15364
|
+
float lunarLambertGain(float phaseDeg, float mu0, float mu, float scale) {
|
|
15365
|
+
float weight = lunarLambertWeight(phaseDeg, scale);
|
|
14193
15366
|
float sun = max(mu0, 0.0);
|
|
14194
15367
|
return 2.0 * weight / max(sun + max(mu, sun), ${GRAZE_FLOOR.toFixed(3)}) + 1.0 - weight;
|
|
14195
15368
|
}
|
|
14196
15369
|
`;
|
|
15370
|
+
function makePhotometryUniforms(scale) {
|
|
15371
|
+
return { uLunarWeightScale: { value: scale ?? 1 } };
|
|
15372
|
+
}
|
|
15373
|
+
function lunarLambertWeight(phaseDeg, scale) {
|
|
15374
|
+
const [a, b, c] = WEIGHT_POLY;
|
|
15375
|
+
const moon = Math.min(1, Math.max(0, 1 + phaseDeg * (a + phaseDeg * (b + phaseDeg * c))));
|
|
15376
|
+
return Math.min(1, scale * moon);
|
|
15377
|
+
}
|
|
14197
15378
|
var DRY_GROUND = `
|
|
14198
15379
|
#ifdef USE_ROUGHNESSMAP
|
|
14199
15380
|
reflectedLight.directSpecular *= texelRoughness.g;
|
|
@@ -14212,18 +15393,20 @@ var LUNAR_LAMBERT = `
|
|
|
14212
15393
|
reflectedLight.directDiffuse *= lunarLambertGain(
|
|
14213
15394
|
phaseDeg,
|
|
14214
15395
|
dot(geometryNormal, sunView),
|
|
14215
|
-
dot(geometryNormal, geometryViewDir)
|
|
15396
|
+
dot(geometryNormal, geometryViewDir),
|
|
15397
|
+
uLunarWeightScale
|
|
14216
15398
|
);
|
|
14217
15399
|
}
|
|
14218
15400
|
`;
|
|
14219
|
-
function attachSurfacePhotometry(material, bodyId, sunDir) {
|
|
15401
|
+
function attachSurfacePhotometry(material, bodyId, uniforms, sunDir) {
|
|
14220
15402
|
const airless = !getAtmosphereParams(bodyId);
|
|
14221
15403
|
chainShaderHook(material, airless ? "photometryAirless" : "photometry", (shader) => {
|
|
14222
15404
|
let pars = "";
|
|
14223
15405
|
let light = DRY_GROUND;
|
|
14224
15406
|
if (airless) {
|
|
14225
15407
|
shader.uniforms.uPhotometrySunDir = sunDir ?? getEclipseSceneUniforms().uSunDir;
|
|
14226
|
-
|
|
15408
|
+
Object.assign(shader.uniforms, uniforms);
|
|
15409
|
+
pars = `uniform vec3 uPhotometrySunDir;\nuniform float uLunarWeightScale;\n${LUNAR_LAMBERT_GLSL}`;
|
|
14227
15410
|
light += LUNAR_LAMBERT;
|
|
14228
15411
|
}
|
|
14229
15412
|
shader.fragmentShader = shader.fragmentShader.replace("#include <common>", `#include <common>\n${pars}`).replace("#include <lights_fragment_end>", `#include <lights_fragment_end>\n${light}`);
|
|
@@ -14231,92 +15414,60 @@ function attachSurfacePhotometry(material, bodyId, sunDir) {
|
|
|
14231
15414
|
}
|
|
14232
15415
|
|
|
14233
15416
|
//#endregion
|
|
14234
|
-
//#region src/lib/scene/objects/surface
|
|
14235
|
-
var
|
|
14236
|
-
|
|
14237
|
-
|
|
14238
|
-
|
|
14239
|
-
|
|
14240
|
-
|
|
14241
|
-
|
|
14242
|
-
|
|
15417
|
+
//#region src/lib/scene/objects/body/surface-albedo.ts
|
|
15418
|
+
var UNKNOWN_SURFACE_COLOR = "#6b6b6b";
|
|
15419
|
+
function luminance$1(c) {
|
|
15420
|
+
return .2126 * c.r + .7152 * c.g + .0722 * c.b;
|
|
15421
|
+
}
|
|
15422
|
+
function discAlbedoPerColour(airless, lunarWeightScale) {
|
|
15423
|
+
if (!airless) return 2 / 3;
|
|
15424
|
+
return (2 + lunarLambertWeight(0, lunarWeightScale ?? 1)) / 3;
|
|
15425
|
+
}
|
|
15426
|
+
var _hex = new Color();
|
|
15427
|
+
function surfaceAlbedoTarget(body) {
|
|
15428
|
+
if (!body.color) return null;
|
|
15429
|
+
return (body.geometricAlbedo ?? luminance$1(_hex.set(body.color))) / discAlbedoPerColour(!getAtmosphereParams(body.id), body.lunarWeightScale);
|
|
15430
|
+
}
|
|
15431
|
+
function untexturedSurfaceColour(body, out = new Color()) {
|
|
15432
|
+
const target = surfaceAlbedoTarget(body);
|
|
15433
|
+
if (target === null) return out.set(UNKNOWN_SURFACE_COLOR);
|
|
15434
|
+
out.set(body.color);
|
|
15435
|
+
return out.multiplyScalar(target / luminance$1(out));
|
|
15436
|
+
}
|
|
15437
|
+
function shinerAlbedo(body, map, out) {
|
|
15438
|
+
if (body.color) out.set(body.color);
|
|
15439
|
+
else if (body.geometricAlbedo === void 0) return null;
|
|
15440
|
+
else {
|
|
15441
|
+
const mean = map && meanMapColor(map);
|
|
15442
|
+
if (mean) out.copy(mean);
|
|
15443
|
+
else out.setRGB(1, 1, 1);
|
|
15444
|
+
}
|
|
15445
|
+
const albedo = body.geometricAlbedo ?? luminance$1(out);
|
|
15446
|
+
return out.multiplyScalar(1.5 * albedo / luminance$1(out));
|
|
14243
15447
|
}
|
|
14244
|
-
var PLANETSHINE_GLSL = `
|
|
14245
|
-
#define PLANETSHINE_SHINERS ${2}
|
|
14246
|
-
uniform vec4 uShineDir[PLANETSHINE_SHINERS];
|
|
14247
|
-
uniform vec3 uShineLight[PLANETSHINE_SHINERS];
|
|
14248
15448
|
|
|
14249
|
-
|
|
14250
|
-
|
|
14251
|
-
|
|
14252
|
-
|
|
14253
|
-
|
|
14254
|
-
|
|
14255
|
-
|
|
14256
|
-
|
|
14257
|
-
// The slots fill in order, so the first empty slot ends the list.
|
|
14258
|
-
if (shiner.w <= 0.0) break;
|
|
14259
|
-
float cosine = sphereLightCosine(dot(geometryNormal, mat3(viewMatrix) * shiner.xyz), shiner.w);
|
|
14260
|
-
reflectedLight.indirectDiffuse += uShineLight[i] * cosine * BRDF_Lambert(material.diffuseContribution);
|
|
14261
|
-
}
|
|
14262
|
-
`;
|
|
14263
|
-
function makePlanetshineUniforms() {
|
|
14264
|
-
return {
|
|
14265
|
-
uShineDir: { value: Array.from({ length: 2 }, () => new Vector4(0, 0, 0, 0)) },
|
|
14266
|
-
uShineLight: { value: Array.from({ length: 2 }, () => new Vector3()) }
|
|
14267
|
-
};
|
|
15449
|
+
//#endregion
|
|
15450
|
+
//#region src/lib/scene/objects/body/shape-model-policy.ts
|
|
15451
|
+
var PREFER_MODEL_OVER_DEM = /* @__PURE__ */ new Set([]);
|
|
15452
|
+
function shapeModelSkipReason(global) {
|
|
15453
|
+
if (!global?.model_name) return "no-bundle";
|
|
15454
|
+
if (isLowEndDevice() && global.render_quality !== "high") return "low-end-device";
|
|
15455
|
+
if (global.displacement && !PREFER_MODEL_OVER_DEM.has(global.id)) return "dem-preferred";
|
|
15456
|
+
return null;
|
|
14268
15457
|
}
|
|
14269
|
-
|
|
14270
|
-
|
|
14271
|
-
|
|
14272
|
-
|
|
14273
|
-
|
|
15458
|
+
|
|
15459
|
+
//#endregion
|
|
15460
|
+
//#region src/lib/scene/objects/body/orientation-apply.ts
|
|
15461
|
+
function applyBodyOrientation(body, orientation, nutPrec, ctx, systemId) {
|
|
15462
|
+
body.orientation = orientation;
|
|
15463
|
+
body.nutPrec = nutPrecFor(body.data.id, nutPrec);
|
|
15464
|
+
if (ctx) ctx.bodies.dataVersion++;
|
|
15465
|
+
ctx?.credits.registerOrientation({
|
|
15466
|
+
bodyId: body.data.id,
|
|
15467
|
+
systemId: systemId ?? body.data.id,
|
|
15468
|
+
source: orientation.source,
|
|
15469
|
+
reference: orientation.reference
|
|
14274
15470
|
});
|
|
14275
|
-
return self;
|
|
14276
|
-
}
|
|
14277
|
-
var _strength = new Float64Array(2);
|
|
14278
|
-
var _swapDir = new Vector4();
|
|
14279
|
-
var _swapLight = new Vector3();
|
|
14280
|
-
function selectShiners(out, x, y, z, shiners, count) {
|
|
14281
|
-
const dirs = out.uShineDir.value;
|
|
14282
|
-
const lights = out.uShineLight.value;
|
|
14283
|
-
let kept = 0;
|
|
14284
|
-
for (let i = 0; i < count; i++) {
|
|
14285
|
-
const s = shiners[i];
|
|
14286
|
-
const dx = s.x - x;
|
|
14287
|
-
const dy = s.y - y;
|
|
14288
|
-
const dz = s.z - z;
|
|
14289
|
-
const d = Math.hypot(dx, dy, dz);
|
|
14290
|
-
if (d <= s.radius) continue;
|
|
14291
|
-
const k = s.radius / d;
|
|
14292
|
-
if (2 / 3 * k * k < 1e-4) continue;
|
|
14293
|
-
const cosPhase = -(dx * s.sunX + dy * s.sunY + dz * s.sunZ) / d;
|
|
14294
|
-
const fraction = planetshineFraction(s.radius, d, Math.acos(Math.max(-1, Math.min(1, cosPhase))));
|
|
14295
|
-
const strength = fraction * (.2126 * s.albedo.r + .7152 * s.albedo.g + .0722 * s.albedo.b);
|
|
14296
|
-
if (strength < 1e-4) continue;
|
|
14297
|
-
let slot = kept;
|
|
14298
|
-
if (kept < 2) kept++;
|
|
14299
|
-
else if (strength > _strength[2 - 1]) slot = 2 - 1;
|
|
14300
|
-
else continue;
|
|
14301
|
-
_strength[slot] = strength;
|
|
14302
|
-
dirs[slot].set(dx / d, dy / d, dz / d, k);
|
|
14303
|
-
lights[slot].set(s.albedo.r, s.albedo.g, s.albedo.b).multiplyScalar(s.sunlight * fraction);
|
|
14304
|
-
for (; slot > 0 && _strength[slot - 1] < strength; slot--) {
|
|
14305
|
-
_strength[slot] = _strength[slot - 1];
|
|
14306
|
-
_strength[slot - 1] = strength;
|
|
14307
|
-
_swapDir.copy(dirs[slot - 1]);
|
|
14308
|
-
dirs[slot - 1].copy(dirs[slot]);
|
|
14309
|
-
dirs[slot].copy(_swapDir);
|
|
14310
|
-
_swapLight.copy(lights[slot - 1]);
|
|
14311
|
-
lights[slot - 1].copy(lights[slot]);
|
|
14312
|
-
lights[slot].copy(_swapLight);
|
|
14313
|
-
}
|
|
14314
|
-
}
|
|
14315
|
-
for (let i = kept; i < 2; i++) {
|
|
14316
|
-
dirs[i].set(0, 0, 0, 0);
|
|
14317
|
-
lights[i].set(0, 0, 0);
|
|
14318
|
-
}
|
|
14319
|
-
return kept;
|
|
14320
15471
|
}
|
|
14321
15472
|
|
|
14322
15473
|
//#endregion
|
|
@@ -14647,7 +15798,11 @@ async function loadSpacecraftModel(bo, modelScene, ctx) {
|
|
|
14647
15798
|
bo.body.modelBaseFrame = baseFrame ?? void 0;
|
|
14648
15799
|
const root = withBaseFrame(gltf.scene, baseFrame);
|
|
14649
15800
|
const anchor = meta.model_anchor ? new Vector3(...meta.model_anchor) : null;
|
|
14650
|
-
fitToUnitRadius(root, anchor && baseFrame ? anchor.applyQuaternion(baseFrame) : anchor)
|
|
15801
|
+
if (!fitToUnitRadius(root, anchor && baseFrame ? anchor.applyQuaternion(baseFrame) : anchor)) {
|
|
15802
|
+
disposeGltf(gltf.scene);
|
|
15803
|
+
bo.noPhysical = "model";
|
|
15804
|
+
return;
|
|
15805
|
+
}
|
|
14651
15806
|
enableShadows(root);
|
|
14652
15807
|
modelScene.add(root);
|
|
14653
15808
|
root.visible = !bo.isCrashed;
|
|
@@ -14683,7 +15838,7 @@ async function loadNaturalBodyModel(bo, ctx) {
|
|
|
14683
15838
|
console.info(`Skipping ${detail.global?.render_quality ?? "unrated"} shape mesh for ${bo.body.data.id}: ${skip}`);
|
|
14684
15839
|
return;
|
|
14685
15840
|
}
|
|
14686
|
-
if (detail.global?.orientation && !bo.body.orientation) applyBodyOrientation(bo.body, detail.global.orientation, ctx);
|
|
15841
|
+
if (detail.global?.orientation && !bo.body.orientation) applyBodyOrientation(bo.body, detail.global.orientation, detail.global.nut_prec, ctx);
|
|
14687
15842
|
const metaPromise = fetchBundleMeta(slug);
|
|
14688
15843
|
const gltf = await _loader.loadAsync(versionedUrl(`/v1/models/${slug}/high.glb`, "models"));
|
|
14689
15844
|
if ((bo.modelLoadEpoch ?? 0) !== epoch) {
|
|
@@ -14703,14 +15858,18 @@ async function loadNaturalBodyModel(bo, ctx) {
|
|
|
14703
15858
|
return;
|
|
14704
15859
|
}
|
|
14705
15860
|
const root = gltf.scene;
|
|
14706
|
-
fitToUnitRadius(root)
|
|
15861
|
+
if (!fitToUnitRadius(root)) {
|
|
15862
|
+
disposeGltf(gltf.scene);
|
|
15863
|
+
return;
|
|
15864
|
+
}
|
|
14707
15865
|
root.userData.radialIndex = buildRadialIndex(root);
|
|
14708
|
-
const material = makeShapeModelMaterial(
|
|
14709
|
-
|
|
15866
|
+
const material = makeShapeModelMaterial(untexturedSurfaceColour(bo.body.data));
|
|
15867
|
+
bo.photometry ??= makePhotometryUniforms(bo.body.data.lunarWeightScale);
|
|
15868
|
+
attachSurfacePhotometry(material, bo.body.data.id, bo.photometry);
|
|
14710
15869
|
bo.planetshine = attachPlanetshine(material, bo.planetshine ?? void 0);
|
|
14711
15870
|
applyShapeModelMaterial(root, material);
|
|
14712
15871
|
const sphereMap = bo.mesh ? bo.mesh.material.map : null;
|
|
14713
|
-
if (sphereMap) setShapeModelMap(root, sphereMap,
|
|
15872
|
+
if (sphereMap) setShapeModelMap(root, sphereMap, untexturedSurfaceColour(bo.body.data), bo.body.data.color);
|
|
14714
15873
|
enableShadows(root);
|
|
14715
15874
|
attachModelEclipse(bo, root);
|
|
14716
15875
|
if (meta.true_scale) {
|
|
@@ -14796,7 +15955,7 @@ function fitToUnitRadius(root, anchor = null) {
|
|
|
14796
15955
|
const size = bbox.getSize(new Vector3());
|
|
14797
15956
|
const center = bbox.getCenter(new Vector3());
|
|
14798
15957
|
const maxDim = Math.max(size.x, size.y, size.z);
|
|
14799
|
-
if (maxDim <= 0) return;
|
|
15958
|
+
if (maxDim <= 0) return false;
|
|
14800
15959
|
const k = 2 / maxDim;
|
|
14801
15960
|
root.userData.boxCenter = center.clone().multiplyScalar(k);
|
|
14802
15961
|
if (anchor) center.addScaledVector(anchor, maxDim / 2);
|
|
@@ -14811,6 +15970,7 @@ function fitToUnitRadius(root, anchor = null) {
|
|
|
14811
15970
|
const offset = root.userData.centerOffset.length();
|
|
14812
15971
|
root.userData.minRadius = Math.max(0, fit.minRadius - offset);
|
|
14813
15972
|
root.userData.maxRadius = root.userData.halfExtents.length() + offset;
|
|
15973
|
+
return true;
|
|
14814
15974
|
}
|
|
14815
15975
|
var OCCLUDER_SLICES = 8;
|
|
14816
15976
|
var OCCLUDER_SAMPLE_TARGET = 4096;
|
|
@@ -14963,7 +16123,7 @@ function nomenclatureBodyId(focused, bodyObjects) {
|
|
|
14963
16123
|
if (bodyObjects.get(focused.data.id)?.isLanded) return focused.data.parentId;
|
|
14964
16124
|
return focused.data.id;
|
|
14965
16125
|
}
|
|
14966
|
-
var DEG2RAD$
|
|
16126
|
+
var DEG2RAD$4 = Math.PI / 180;
|
|
14967
16127
|
var MIN_BODY_SCREEN_RADIUS_PX = 128;
|
|
14968
16128
|
var LABEL_DISC_FRACTION = .9;
|
|
14969
16129
|
var MIN_FEATURE_PX = 24;
|
|
@@ -15016,8 +16176,8 @@ async function attachNomenclatureLabels(bo, canvas, onFeatureSelect) {
|
|
|
15016
16176
|
let dispKm = null;
|
|
15017
16177
|
if (detail.global.displacement) {
|
|
15018
16178
|
dispKm = await displacementsKmAt(bo, bo.body.data.id, detail.global.displacement, effectiveRadiusKm(bo.body.data), renderable.map((f) => ({
|
|
15019
|
-
latRad: f.lat * DEG2RAD$
|
|
15020
|
-
lonRad: f.lon * DEG2RAD$
|
|
16179
|
+
latRad: f.lat * DEG2RAD$4,
|
|
16180
|
+
lonRad: f.lon * DEG2RAD$4
|
|
15021
16181
|
})));
|
|
15022
16182
|
if (bo.nomenclatureLabels || !bo.mesh) return;
|
|
15023
16183
|
}
|
|
@@ -15041,7 +16201,7 @@ async function attachNomenclatureLabels(bo, canvas, onFeatureSelect) {
|
|
|
15041
16201
|
el.dataset.featureId = String(feature.featureId);
|
|
15042
16202
|
attachCanvasForwarders(el, canvas);
|
|
15043
16203
|
if (onFeatureSelect) onTapNotDrag(el, () => onFeatureSelect(feature.featureId, feature.lat, feature.lon, effDiam));
|
|
15044
|
-
const [ux, uy, uz] = bodyFixedUnit(feature.lat * DEG2RAD$
|
|
16204
|
+
const [ux, uy, uz] = bodyFixedUnit(feature.lat * DEG2RAD$4, feature.lon * DEG2RAD$4);
|
|
15045
16205
|
const rf = radial[i];
|
|
15046
16206
|
const obj = new CSS2DObject(el);
|
|
15047
16207
|
obj.position.set(rf * ux, rf * uy, rf * uz);
|
|
@@ -15066,8 +16226,8 @@ async function sampleModelSurface(model, features) {
|
|
|
15066
16226
|
const he = model.userData.halfExtents;
|
|
15067
16227
|
for (let i = 0; i < n; i++) {
|
|
15068
16228
|
if (i > 0 && i % MODEL_CAST_CHUNK === 0) await new Promise((r) => setTimeout(r));
|
|
15069
|
-
const latRad = features[i].lat * DEG2RAD$
|
|
15070
|
-
const lonRad = features[i].lon * DEG2RAD$
|
|
16229
|
+
const latRad = features[i].lat * DEG2RAD$4;
|
|
16230
|
+
const lonRad = features[i].lon * DEG2RAD$4;
|
|
15071
16231
|
const r = castModelRadius(model, latRad, lonRad, _castNormal);
|
|
15072
16232
|
if (r !== null) radii[i] = r;
|
|
15073
16233
|
else {
|
|
@@ -16240,7 +17400,10 @@ uniform vec2 uTileFilter;
|
|
|
16240
17400
|
${TILE_CHAIN_GLSL}
|
|
16241
17401
|
vec3 tileColour( vec3 below ) {
|
|
16242
17402
|
if ( uTileWindow[ 0 ].w < 0.5 ) return below;
|
|
16243
|
-
|
|
17403
|
+
mat3x2 map;
|
|
17404
|
+
mat3x2 cap;
|
|
17405
|
+
float side;
|
|
17406
|
+
tileChartsFrom( uTileAnchor, vTileOff, map, cap, side );
|
|
16244
17407
|
|
|
16245
17408
|
float rows = ${4 .toFixed(1)};
|
|
16246
17409
|
vec3 colour = vec3( 0.0 );
|
|
@@ -16251,7 +17414,7 @@ vec3 tileColour( vec3 below ) {
|
|
|
16251
17414
|
vec2 spot;
|
|
16252
17415
|
vec2 major;
|
|
16253
17416
|
vec2 minor;
|
|
16254
|
-
float alpha = tileWindowWeight(
|
|
17417
|
+
float alpha = tileWindowWeight( map, cap, side, window, uTileGrid[ i ], uTileHome[ i ], uTileFilter, spot, major, minor );
|
|
16255
17418
|
if ( alpha <= 0.0 ) continue;
|
|
16256
17419
|
ivec3 slot = ivec3( int( mod( spot.x, rows ) ), int( mod( spot.y, rows ) ), int( window.y ) );
|
|
16257
17420
|
alpha *= texelFetch( uTileMask, slot, 0 ).r;
|
|
@@ -16394,8 +17557,9 @@ async function swapBodyTexture(bo, tier, frame, textureLoader) {
|
|
|
16394
17557
|
return;
|
|
16395
17558
|
}
|
|
16396
17559
|
const material = bo.mesh.material;
|
|
16397
|
-
|
|
16398
|
-
|
|
17560
|
+
const data = bo.body.data;
|
|
17561
|
+
setSurfaceMap(material, texture, data.color);
|
|
17562
|
+
if (bo.model) setShapeModelMap(bo.model, texture, untexturedSurfaceColour(data), data.color);
|
|
16399
17563
|
bo.textureTier = tier;
|
|
16400
17564
|
bo.textureFrame = frame;
|
|
16401
17565
|
} catch (err) {
|
|
@@ -16404,6 +17568,13 @@ async function swapBodyTexture(bo, tier, frame, textureLoader) {
|
|
|
16404
17568
|
bo.textureLoading = false;
|
|
16405
17569
|
}
|
|
16406
17570
|
}
|
|
17571
|
+
function applySurfaceColour(bo) {
|
|
17572
|
+
if (!bo.mesh || !bo.photometry || isModelBearing(bo.body) || bo.appearance?.surfaceOwned) return;
|
|
17573
|
+
const material = bo.mesh.material;
|
|
17574
|
+
if (material.map) return;
|
|
17575
|
+
untexturedSurfaceColour(bo.body.data, material.color);
|
|
17576
|
+
if (bo.model) setShapeModelMap(bo.model, null, material.color);
|
|
17577
|
+
}
|
|
16407
17578
|
function applyRadiiToMesh(bo, radii) {
|
|
16408
17579
|
if (!bo.mesh) return;
|
|
16409
17580
|
const { a, b, c } = radii;
|
|
@@ -16415,6 +17586,11 @@ function applyRadiiToMesh(bo, radii) {
|
|
|
16415
17586
|
kmToScene(c),
|
|
16416
17587
|
kmToScene(b)
|
|
16417
17588
|
];
|
|
17589
|
+
bo.body.drawnRadii = {
|
|
17590
|
+
a,
|
|
17591
|
+
b,
|
|
17592
|
+
c
|
|
17593
|
+
};
|
|
16418
17594
|
if (bo.atmosphere) {
|
|
16419
17595
|
const eqKm = Math.max(a, b);
|
|
16420
17596
|
syncAtmosphereEllipsoid(bo.atmosphere, eqKm, c, kmToScene(eqKm));
|
|
@@ -16427,14 +17603,15 @@ async function loadBodyTexture(bo, textureLoader, currentJd, scene, maxTextureSi
|
|
|
16427
17603
|
const detail = await fetchObjectDetail(bo.body.data.id, false);
|
|
16428
17604
|
ctx?.bodies.orientationRead.add(bo.body.data.id);
|
|
16429
17605
|
if (!detail.global) return;
|
|
16430
|
-
if (detail.global.orientation && !bo.body.orientation) applyBodyOrientation(bo.body, detail.global.orientation, ctx);
|
|
17606
|
+
if (detail.global.orientation && !bo.body.orientation) applyBodyOrientation(bo.body, detail.global.orientation, detail.global.nut_prec, ctx);
|
|
16431
17607
|
if (detail.global.radii && bo.radiusScene > 0 && !bo.radiiApplied && !detail.global.displacement?.absolute_radius) applyRadiiToMesh(bo, detail.global.radii);
|
|
16432
17608
|
if (detail.global.rings?.length) await Promise.allSettled(attachRingBundles(bo.body.data.id, bo.body.data.id, detail.global.rings, detail.global.radii, bo, scene, maxTextureSize, ctx));
|
|
16433
|
-
const
|
|
16434
|
-
|
|
16435
|
-
|
|
16436
|
-
|
|
16437
|
-
|
|
17609
|
+
const data = bo.body.data;
|
|
17610
|
+
data.color = detail.global.sbdb?.color ?? detail.global.color;
|
|
17611
|
+
data.geometricAlbedo = detail.global.sbdb?.geometric_albedo ?? detail.global.geometric_albedo;
|
|
17612
|
+
data.lunarWeightScale = detail.global.lunar_weight_scale;
|
|
17613
|
+
if (bo.photometry) bo.photometry.uLunarWeightScale.value = data.lunarWeightScale ?? 1;
|
|
17614
|
+
applySurfaceColour(bo);
|
|
16438
17615
|
if (!detail.global.map_texture_available) return;
|
|
16439
17616
|
const bodyId = bo.body.data.id;
|
|
16440
17617
|
const surface = pickTexture([detail.global.texture && {
|
|
@@ -16476,9 +17653,9 @@ function unloadBodyTexture(bo) {
|
|
|
16476
17653
|
if (!material.map) return;
|
|
16477
17654
|
material.map.dispose();
|
|
16478
17655
|
material.map = null;
|
|
16479
|
-
|
|
17656
|
+
untexturedSurfaceColour(bo.body.data, material.color);
|
|
16480
17657
|
material.needsUpdate = true;
|
|
16481
|
-
if (bo.model) setShapeModelMap(bo.model, null,
|
|
17658
|
+
if (bo.model) setShapeModelMap(bo.model, null, material.color);
|
|
16482
17659
|
bo.textureTier = void 0;
|
|
16483
17660
|
}
|
|
16484
17661
|
async function loadBodyTextureTier(bo, tier, frame, textureLoader) {
|
|
@@ -16505,17 +17682,6 @@ async function downloadSystemMeta(barycenterId) {
|
|
|
16505
17682
|
if (!resp.ok) throw new Error(`systems/${barycenterId}.json: ${resp.status}`);
|
|
16506
17683
|
return resp.json();
|
|
16507
17684
|
}
|
|
16508
|
-
function adoptSystemSpin(body, orientation, nutPrec, ctx, barycenterId) {
|
|
16509
|
-
applyBodyOrientation(body, orientation, ctx, barycenterId);
|
|
16510
|
-
if (!nutPrec) return;
|
|
16511
|
-
const naifMatch = body.data.id.match(/^naif-(-?\d+)$/);
|
|
16512
|
-
const naifId = naifMatch ? parseInt(naifMatch[1], 10) : null;
|
|
16513
|
-
const angles = naifId !== null ? getNutPrecAngles(ownerIdFor(naifId)) : void 0;
|
|
16514
|
-
if (angles) body.nutPrec = {
|
|
16515
|
-
...nutPrec,
|
|
16516
|
-
angles
|
|
16517
|
-
};
|
|
16518
|
-
}
|
|
16519
17685
|
async function readSpin(body, ctx) {
|
|
16520
17686
|
const id = body.data.id;
|
|
16521
17687
|
const known = () => !!body.orientation || ctx.bodies.orientationRead.has(id);
|
|
@@ -16526,8 +17692,8 @@ async function readSpin(body, ctx) {
|
|
|
16526
17692
|
const record = barycenterId ? (await fetchSystemMeta(barycenterId))?.[id] : void 0;
|
|
16527
17693
|
const detail = record?.orientation ? null : await fetchObjectDetail(id, false);
|
|
16528
17694
|
if (known()) return;
|
|
16529
|
-
if (record?.orientation)
|
|
16530
|
-
else if (detail?.global?.orientation) applyBodyOrientation(body, detail.global.orientation, ctx);
|
|
17695
|
+
if (record?.orientation) applyBodyOrientation(body, record.orientation, record.nut_prec, ctx, barycenterId);
|
|
17696
|
+
else if (detail?.global?.orientation) applyBodyOrientation(body, detail.global.orientation, detail.global.nut_prec, ctx);
|
|
16531
17697
|
ctx.bodies.orientationRead.add(id);
|
|
16532
17698
|
if (body.orientation) ctx.bodies.orientationVersion++;
|
|
16533
17699
|
}
|
|
@@ -16550,8 +17716,14 @@ async function loadSystemData(barycenterId, bodyObjects, scene, textureLoader, c
|
|
|
16550
17716
|
const bo = bodyObjects.get(bodyId);
|
|
16551
17717
|
if (!bo?.mesh) continue;
|
|
16552
17718
|
ctx?.bodies.orientationRead.add(bodyId);
|
|
17719
|
+
const data = bo.body.data;
|
|
17720
|
+
data.color ??= bodyMeta.color;
|
|
17721
|
+
data.geometricAlbedo ??= bodyMeta.geometric_albedo;
|
|
17722
|
+
data.lunarWeightScale ??= bodyMeta.lunar_weight_scale;
|
|
17723
|
+
if (bo.photometry) bo.photometry.uLunarWeightScale.value = data.lunarWeightScale ?? 1;
|
|
17724
|
+
applySurfaceColour(bo);
|
|
16553
17725
|
if (bodyMeta.orientation) {
|
|
16554
|
-
|
|
17726
|
+
applyBodyOrientation(bo.body, bodyMeta.orientation, bodyMeta.nut_prec, ctx, barycenterId);
|
|
16555
17727
|
applyOrientation(bo.mesh, bodyMeta.orientation, currentJd, bo.body.nutPrec);
|
|
16556
17728
|
}
|
|
16557
17729
|
if (bodyMeta.radii && bo.radiusScene > 0 && !bo.radiiApplied && !bodyMeta.displacement?.absolute_radius) applyRadiiToMesh(bo, bodyMeta.radii);
|
|
@@ -16589,6 +17761,7 @@ function unloadSystemTextures(barycenterId, bodyObjects, scene, ctx) {
|
|
|
16589
17761
|
}
|
|
16590
17762
|
for (const ring of bo.rings) {
|
|
16591
17763
|
ring.planetShadow?.disable();
|
|
17764
|
+
ring.ringshine?.disable();
|
|
16592
17765
|
ring.mesh.removeFromParent();
|
|
16593
17766
|
disposeRingNode(ring);
|
|
16594
17767
|
}
|
|
@@ -16609,6 +17782,7 @@ var ZoneRefresher = class {
|
|
|
16609
17782
|
latestDate;
|
|
16610
17783
|
failureStreak = 0;
|
|
16611
17784
|
staleNotified = false;
|
|
17785
|
+
staleCheckRunning = false;
|
|
16612
17786
|
retries = new RetryBackoff(() => this.wakes++);
|
|
16613
17787
|
wakes = 0;
|
|
16614
17788
|
wakeTimer;
|
|
@@ -16664,10 +17838,17 @@ var ZoneRefresher = class {
|
|
|
16664
17838
|
recordFailure(key) {
|
|
16665
17839
|
this.retries.fail(key);
|
|
16666
17840
|
this.failureStreak++;
|
|
16667
|
-
if (this.failureStreak
|
|
17841
|
+
if (this.failureStreak < STALE_FAILURE_STREAK || this.staleNotified || this.staleCheckRunning) return;
|
|
17842
|
+
this.staleCheckRunning = true;
|
|
17843
|
+
dataVersionChanged().then((changed) => {
|
|
17844
|
+
this.staleCheckRunning = false;
|
|
17845
|
+
if (!changed) {
|
|
17846
|
+
this.failureStreak = 0;
|
|
17847
|
+
return;
|
|
17848
|
+
}
|
|
16668
17849
|
this.staleNotified = true;
|
|
16669
17850
|
this.ctx.onDataStale?.();
|
|
16670
|
-
}
|
|
17851
|
+
});
|
|
16671
17852
|
}
|
|
16672
17853
|
wakeIn(ms) {
|
|
16673
17854
|
this.wakeTimer ??= setTimeout(() => {
|
|
@@ -17636,7 +18817,7 @@ var SimClock = class {
|
|
|
17636
18817
|
//#region src/lib/math/spherical.ts
|
|
17637
18818
|
var { PI, sin, cos, asin, atan2, sqrt } = Math;
|
|
17638
18819
|
var DEG$9 = 180 / PI;
|
|
17639
|
-
var RAD$
|
|
18820
|
+
var RAD$4 = PI / 180;
|
|
17640
18821
|
function applyQuat(v, q, inverse) {
|
|
17641
18822
|
const [x, y, z] = v;
|
|
17642
18823
|
const [qx, qy, qz, qw] = inverse ? [
|
|
@@ -17672,8 +18853,8 @@ function cartesianToSpherical(cam, target, bodyQuat) {
|
|
|
17672
18853
|
};
|
|
17673
18854
|
}
|
|
17674
18855
|
function sphericalToCartesian(target, lat, lon, distance, bodyQuat) {
|
|
17675
|
-
const latR = lat * RAD$
|
|
17676
|
-
const lonR = lon * RAD$
|
|
18856
|
+
const latR = lat * RAD$4;
|
|
18857
|
+
const lonR = lon * RAD$4;
|
|
17677
18858
|
let ox;
|
|
17678
18859
|
let oy;
|
|
17679
18860
|
let oz;
|
|
@@ -17706,7 +18887,7 @@ function offsetFacing(focus, toward, elevationDeg, distance) {
|
|
|
17706
18887
|
hx = 0;
|
|
17707
18888
|
hz = 1;
|
|
17708
18889
|
}
|
|
17709
|
-
const e = elevationDeg * RAD$
|
|
18890
|
+
const e = elevationDeg * RAD$4;
|
|
17710
18891
|
const c = cos(e);
|
|
17711
18892
|
return [
|
|
17712
18893
|
distance * c * hx,
|
|
@@ -18041,26 +19222,6 @@ function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM, dash) {
|
|
|
18041
19222
|
});
|
|
18042
19223
|
}
|
|
18043
19224
|
|
|
18044
|
-
//#endregion
|
|
18045
|
-
//#region src/lib/scene/lighting.ts
|
|
18046
|
-
var AMBIENT_INTENSITY = .01;
|
|
18047
|
-
var SUN_LIGHT_INTENSITY = 3.5;
|
|
18048
|
-
var ENV_BASE_INTENSITY = .04;
|
|
18049
|
-
function sunIrradianceFactor(sunDistScene) {
|
|
18050
|
-
const au = Math.max(sunDistScene / 10, .01);
|
|
18051
|
-
return 1 / (au * au);
|
|
18052
|
-
}
|
|
18053
|
-
function applySunPointLightMode(light, realistic, scale = 1) {
|
|
18054
|
-
light.decay = realistic ? 2 : 0;
|
|
18055
|
-
light.intensity = (realistic ? SUN_LIGHT_INTENSITY * 10 * 10 : SUN_LIGHT_INTENSITY) * scale;
|
|
18056
|
-
}
|
|
18057
|
-
function makeEnvMap(renderer) {
|
|
18058
|
-
const pmrem = new PMREMGenerator(renderer);
|
|
18059
|
-
const tex = pmrem.fromScene(new RoomEnvironment()).texture;
|
|
18060
|
-
pmrem.dispose();
|
|
18061
|
-
return tex;
|
|
18062
|
-
}
|
|
18063
|
-
|
|
18064
19225
|
//#endregion
|
|
18065
19226
|
//#region src/lib/scene/setup/bloom-high-pass.ts
|
|
18066
19227
|
var MAX_SPAN = 16;
|
|
@@ -18106,6 +19267,26 @@ function installBloomHighPass(pass) {
|
|
|
18106
19267
|
});
|
|
18107
19268
|
}
|
|
18108
19269
|
|
|
19270
|
+
//#endregion
|
|
19271
|
+
//#region src/lib/scene/setup/output-dither.ts
|
|
19272
|
+
var DITHER_GLSL = `
|
|
19273
|
+
vec3 outputDither(vec3 color) {
|
|
19274
|
+
// ES 1.00 gives gl_FragCoord at medium precision. Copy it before the arithmetic.
|
|
19275
|
+
vec3 p3 = gl_FragCoord.xyx;
|
|
19276
|
+
p3 = fract(p3 * vec3(0.1031, 0.1030, 0.0973));
|
|
19277
|
+
p3 += dot(p3, p3.yxz + 33.33);
|
|
19278
|
+
vec3 u = fract((p3.xxy + p3.yzz) * p3.zyx);
|
|
19279
|
+
// The difference of two uniform samples has a triangular distribution on (-1, 1).
|
|
19280
|
+
vec3 noise = u - u.yzx;
|
|
19281
|
+
// The noise goes to 0 in the last step at each end. Thus black stays black and no value clips.
|
|
19282
|
+
vec3 amplitude = clamp(min(color, 1.0 - color) * 255.0, 0.0, 1.0);
|
|
19283
|
+
return color + noise * amplitude / 255.0;
|
|
19284
|
+
}
|
|
19285
|
+
`;
|
|
19286
|
+
function installOutputDither(pass) {
|
|
19287
|
+
pass.material.fragmentShader = pass.material.fragmentShader.replace("#include <colorspace_pars_fragment>", `#include <colorspace_pars_fragment>\n${DITHER_GLSL}`).replace(/}\s*$/, "gl_FragColor.rgb = outputDither(gl_FragColor.rgb);\n}");
|
|
19288
|
+
}
|
|
19289
|
+
|
|
18109
19290
|
//#endregion
|
|
18110
19291
|
//#region src/lib/scene/setup/three-boot.ts
|
|
18111
19292
|
var CAMERA_FAR_DEFAULT = 1e5;
|
|
@@ -18178,6 +19359,7 @@ function bootThree(canvas, labelContainer, ctx) {
|
|
|
18178
19359
|
installBloomHighPass(bloomPass);
|
|
18179
19360
|
composer.addPass(bloomPass);
|
|
18180
19361
|
const outputPass = new OutputPass();
|
|
19362
|
+
installOutputDither(outputPass);
|
|
18181
19363
|
outputPass.needsSwap = false;
|
|
18182
19364
|
composer.addPass(outputPass);
|
|
18183
19365
|
return {
|
|
@@ -18186,7 +19368,7 @@ function bootThree(canvas, labelContainer, ctx) {
|
|
|
18186
19368
|
scene,
|
|
18187
19369
|
camera,
|
|
18188
19370
|
composer,
|
|
18189
|
-
maxSceneSamples: sampleCounts[0] ?? 0,
|
|
19371
|
+
maxSceneSamples: sampleCounts?.[0] ?? 0,
|
|
18190
19372
|
bloomPass,
|
|
18191
19373
|
ambientLight,
|
|
18192
19374
|
shadowLight
|
|
@@ -18855,7 +20037,7 @@ gl_Position = projectionMatrix * mvPosition;
|
|
|
18855
20037
|
`;
|
|
18856
20038
|
var anchors = /* @__PURE__ */ new WeakMap();
|
|
18857
20039
|
var _modelView = new Matrix4();
|
|
18858
|
-
var _inverse = new Matrix4();
|
|
20040
|
+
var _inverse$1 = new Matrix4();
|
|
18859
20041
|
var _eye = new Vector3();
|
|
18860
20042
|
function patch(material, anchor) {
|
|
18861
20043
|
chainShaderHook(material, "cameraRelative", (shader) => {
|
|
@@ -18873,7 +20055,7 @@ function attachCameraRelative(mesh, material) {
|
|
|
18873
20055
|
patch(material, anchor);
|
|
18874
20056
|
mesh.onBeforeRender = (_renderer, _scene, camera) => {
|
|
18875
20057
|
_modelView.multiplyMatrices(camera.matrixWorldInverse, mesh.matrixWorld);
|
|
18876
|
-
_eye.setFromMatrixPosition(_inverse.copy(_modelView).invert());
|
|
20058
|
+
_eye.setFromMatrixPosition(_inverse$1.copy(_modelView).invert());
|
|
18877
20059
|
anchor.local.value.set(Math.fround(_eye.x), Math.fround(_eye.y), Math.fround(_eye.z));
|
|
18878
20060
|
anchor.view.value.copy(anchor.local.value).applyMatrix4(_modelView);
|
|
18879
20061
|
};
|
|
@@ -18911,19 +20093,21 @@ function buildMajorBodies(bodies, scene, clickables, meshToBody, bodyObjects, re
|
|
|
18911
20093
|
let starExtras = null;
|
|
18912
20094
|
let eclipseShadow = null;
|
|
18913
20095
|
let planetshine = null;
|
|
20096
|
+
let photometry = null;
|
|
18914
20097
|
let atmosphere = null;
|
|
18915
20098
|
let sunTint;
|
|
18916
20099
|
if (!isVirtual && !noPhysical) {
|
|
18917
20100
|
if (isStar) starExtras = buildStarExtras(root, radius, color);
|
|
18918
20101
|
const segments = isStar ? STAR_SPHERE_SEGMENTS : BODY_SPHERE_SEGMENTS;
|
|
18919
20102
|
const geometry = new SphereGeometry(radius, segments, segments);
|
|
18920
|
-
const material = isStar ? makeStarSurfaceMaterial() : new MeshStandardMaterial({ color:
|
|
20103
|
+
const material = isStar ? makeStarSurfaceMaterial() : new MeshStandardMaterial({ color: untexturedSurfaceColour(body.data) });
|
|
18921
20104
|
mesh = new Mesh(geometry, material);
|
|
18922
20105
|
if (modelBearing) mesh.visible = false;
|
|
18923
20106
|
if (!isStar) {
|
|
18924
20107
|
eclipseShadow = attachEclipseShadowToBody(material);
|
|
18925
20108
|
attachCameraRelative(mesh, material);
|
|
18926
|
-
|
|
20109
|
+
photometry = makePhotometryUniforms(body.data.lunarWeightScale);
|
|
20110
|
+
attachSurfacePhotometry(material, id, photometry);
|
|
18927
20111
|
if (!modelBearing) planetshine = attachPlanetshine(material);
|
|
18928
20112
|
}
|
|
18929
20113
|
root.add(mesh);
|
|
@@ -18974,6 +20158,7 @@ function buildMajorBodies(bodies, scene, clickables, meshToBody, bodyObjects, re
|
|
|
18974
20158
|
selfShadow: null,
|
|
18975
20159
|
eclipseShadow,
|
|
18976
20160
|
planetshine,
|
|
20161
|
+
photometry,
|
|
18977
20162
|
nomenclatureLabels: null,
|
|
18978
20163
|
model: null
|
|
18979
20164
|
});
|
|
@@ -18992,10 +20177,9 @@ function upgradeBodyMesh(bo, scene, clickables, meshToBody) {
|
|
|
18992
20177
|
bo.noPhysical = "radius";
|
|
18993
20178
|
return;
|
|
18994
20179
|
}
|
|
18995
|
-
const color = bodyMeshColor(body.data);
|
|
18996
20180
|
const segments = BODY_SPHERE_SEGMENTS;
|
|
18997
20181
|
const geometry = new SphereGeometry(radiusScene, segments, segments);
|
|
18998
|
-
const material = new MeshStandardMaterial({ color });
|
|
20182
|
+
const material = new MeshStandardMaterial({ color: untexturedSurfaceColour(body.data) });
|
|
18999
20183
|
const mesh = new Mesh(geometry, material);
|
|
19000
20184
|
if (modelBearing) mesh.visible = false;
|
|
19001
20185
|
bo.root.add(mesh);
|
|
@@ -19004,7 +20188,8 @@ function upgradeBodyMesh(bo, scene, clickables, meshToBody) {
|
|
|
19004
20188
|
meshToBody.set(mesh, body);
|
|
19005
20189
|
bo.eclipseShadow = attachEclipseShadowToBody(material);
|
|
19006
20190
|
attachCameraRelative(mesh, material);
|
|
19007
|
-
|
|
20191
|
+
bo.photometry = makePhotometryUniforms(body.data.lunarWeightScale);
|
|
20192
|
+
attachSurfacePhotometry(material, body.data.id, bo.photometry);
|
|
19008
20193
|
if (!modelBearing) bo.planetshine = attachPlanetshine(material);
|
|
19009
20194
|
bo.currentSegments = segments;
|
|
19010
20195
|
const atmoParams = getAtmosphereParams(body.data.id);
|
|
@@ -19041,6 +20226,7 @@ function downgradeBodyMesh(bo, scene, clickables, meshToBody) {
|
|
|
19041
20226
|
bo.currentSegments = void 0;
|
|
19042
20227
|
bo.eclipseShadow = null;
|
|
19043
20228
|
bo.planetshine = null;
|
|
20229
|
+
bo.photometry = null;
|
|
19044
20230
|
bo.sunTint = void 0;
|
|
19045
20231
|
bo.radiiApplied = false;
|
|
19046
20232
|
bo.semiAxesScene = void 0;
|
|
@@ -19191,9 +20377,9 @@ function revert(bo, appearance) {
|
|
|
19191
20377
|
if (applied.surfaceOwned && appearance?.surface === void 0) {
|
|
19192
20378
|
applied.surfaceMap?.dispose();
|
|
19193
20379
|
material.map = null;
|
|
19194
|
-
|
|
20380
|
+
untexturedSurfaceColour(bo.body.data, material.color);
|
|
19195
20381
|
material.needsUpdate = true;
|
|
19196
|
-
if (bo.model) setShapeModelMap(bo.model, null,
|
|
20382
|
+
if (bo.model) setShapeModelMap(bo.model, null, material.color);
|
|
19197
20383
|
applied.surfaceOwned = void 0;
|
|
19198
20384
|
applied.surfaceUrl = void 0;
|
|
19199
20385
|
applied.surfaceMap = void 0;
|
|
@@ -19245,7 +20431,7 @@ async function applyToBody(bo, appearance, textureLoader, current) {
|
|
|
19245
20431
|
const live = liveMaterial(bo);
|
|
19246
20432
|
if (texture && live) {
|
|
19247
20433
|
setSurfaceMap(live, texture);
|
|
19248
|
-
if (bo.model) setShapeModelMap(bo.model, texture,
|
|
20434
|
+
if (bo.model) setShapeModelMap(bo.model, texture, untexturedSurfaceColour(bo.body.data));
|
|
19249
20435
|
applied.surfaceUrl = appearance.surface;
|
|
19250
20436
|
applied.surfaceMap = texture;
|
|
19251
20437
|
}
|
|
@@ -19465,95 +20651,6 @@ function makePointCloudFromBuffer(positions, drawCount, texture, color, size = 4
|
|
|
19465
20651
|
return points;
|
|
19466
20652
|
}
|
|
19467
20653
|
|
|
19468
|
-
//#endregion
|
|
19469
|
-
//#region src/lib/math/orbit/position.ts
|
|
19470
|
-
var DEG2RAD$4 = Math.PI / 180;
|
|
19471
|
-
var COS_EPS$2 = Math.cos(EARTH_OBLIQUITY_DEG * DEG2RAD$4);
|
|
19472
|
-
var SIN_EPS$2 = Math.sin(EARTH_OBLIQUITY_DEG * DEG2RAD$4);
|
|
19473
|
-
function orbitalToThreeJS(xOrb, yOrb, w, i, om, equatorial = false) {
|
|
19474
|
-
const cosW = Math.cos(w * DEG2RAD$4);
|
|
19475
|
-
const sinW = Math.sin(w * DEG2RAD$4);
|
|
19476
|
-
const cosI = Math.cos(i * DEG2RAD$4);
|
|
19477
|
-
const sinI = Math.sin(i * DEG2RAD$4);
|
|
19478
|
-
const cosOm = Math.cos(om * DEG2RAD$4);
|
|
19479
|
-
const sinOm = Math.sin(om * DEG2RAD$4);
|
|
19480
|
-
const x = (cosOm * cosW - sinOm * sinW * cosI) * xOrb + (-cosOm * sinW - sinOm * cosW * cosI) * yOrb;
|
|
19481
|
-
let y = (sinOm * cosW + cosOm * sinW * cosI) * xOrb + (-sinOm * sinW + cosOm * cosW * cosI) * yOrb;
|
|
19482
|
-
let z = sinW * sinI * xOrb + cosW * sinI * yOrb;
|
|
19483
|
-
if (equatorial) {
|
|
19484
|
-
const yEcl = y * COS_EPS$2 + z * SIN_EPS$2;
|
|
19485
|
-
const zEcl = -y * SIN_EPS$2 + z * COS_EPS$2;
|
|
19486
|
-
y = yEcl;
|
|
19487
|
-
z = zEcl;
|
|
19488
|
-
}
|
|
19489
|
-
return [
|
|
19490
|
-
x * 10,
|
|
19491
|
-
z * 10,
|
|
19492
|
-
-y * 10
|
|
19493
|
-
];
|
|
19494
|
-
}
|
|
19495
|
-
function propagateOrbitAngles(el, jd) {
|
|
19496
|
-
const { omDot, wDot, om, w, epoch } = el;
|
|
19497
|
-
if (!omDot && !wDot) return el;
|
|
19498
|
-
const dt = jd - epoch;
|
|
19499
|
-
return {
|
|
19500
|
-
...el,
|
|
19501
|
-
om: omDot ? om + omDot * dt : om,
|
|
19502
|
-
w: wDot ? w + wDot * dt : w
|
|
19503
|
-
};
|
|
19504
|
-
}
|
|
19505
|
-
function orbitalElementsToPositionJD(el, jd) {
|
|
19506
|
-
const { a, e, i, ma, n, epoch } = el;
|
|
19507
|
-
if (!isFinite(a) || !isFinite(e) || !isFinite(ma) || !isFinite(n)) {
|
|
19508
|
-
console.warn(`NaN in orbital elements: a=${a} e=${e} ma=${ma} n=${n}`);
|
|
19509
|
-
return null;
|
|
19510
|
-
}
|
|
19511
|
-
const M = (ma + n * (jd - epoch)) * DEG2RAD$4;
|
|
19512
|
-
const { om: omPropagated, w: wPropagated } = propagateOrbitAngles(el, jd);
|
|
19513
|
-
let nu;
|
|
19514
|
-
let r;
|
|
19515
|
-
if (e < 1 || a > 0) {
|
|
19516
|
-
const eClamped = Math.min(e, .9999999);
|
|
19517
|
-
const E = solveKepler(M, eClamped);
|
|
19518
|
-
const sinNu = Math.sqrt(1 - eClamped * eClamped) * Math.sin(E) / (1 - eClamped * Math.cos(E));
|
|
19519
|
-
const cosNu = (Math.cos(E) - eClamped) / (1 - eClamped * Math.cos(E));
|
|
19520
|
-
nu = Math.atan2(sinNu, cosNu);
|
|
19521
|
-
r = a * (1 - eClamped * Math.cos(E));
|
|
19522
|
-
} else {
|
|
19523
|
-
const H = solveKeplerHyperbolic(M, e);
|
|
19524
|
-
if (!isFinite(H)) {
|
|
19525
|
-
console.warn(`solveKeplerHyperbolic overflow: M=${M} e=${e}`);
|
|
19526
|
-
return null;
|
|
19527
|
-
}
|
|
19528
|
-
const denom = e * Math.cosh(H) - 1;
|
|
19529
|
-
if (Math.abs(denom) < 1e-15) {
|
|
19530
|
-
console.warn(`Hyperbolic denom near zero: H=${H} e=${e} denom=${denom}`);
|
|
19531
|
-
return null;
|
|
19532
|
-
}
|
|
19533
|
-
const sinNu = Math.sqrt(e * e - 1) * Math.sinh(H) / denom;
|
|
19534
|
-
const cosNu = (e - Math.cosh(H)) / denom;
|
|
19535
|
-
nu = Math.atan2(sinNu, cosNu);
|
|
19536
|
-
r = a * (1 - e * Math.cosh(H));
|
|
19537
|
-
}
|
|
19538
|
-
const xOrb = r * Math.cos(nu);
|
|
19539
|
-
const yOrb = r * Math.sin(nu);
|
|
19540
|
-
if (!isFinite(xOrb) || !isFinite(yOrb)) {
|
|
19541
|
-
console.warn(`Non-finite orbital position: r=${r} nu=${nu} xOrb=${xOrb} yOrb=${yOrb} a=${a} e=${e}`);
|
|
19542
|
-
return null;
|
|
19543
|
-
}
|
|
19544
|
-
return orbitalToThreeJS(xOrb, yOrb, wPropagated, i, omPropagated, el.equatorial);
|
|
19545
|
-
}
|
|
19546
|
-
function parabolicToPositionJD(el, jd) {
|
|
19547
|
-
const { q, tp, i, om, w } = el;
|
|
19548
|
-
if (q == null || tp == null || !isFinite(q) || !isFinite(tp)) return null;
|
|
19549
|
-
const result = solveBarker(q, tp, jd);
|
|
19550
|
-
if (!result) return null;
|
|
19551
|
-
const xOrb = result.r * Math.cos(result.nu);
|
|
19552
|
-
const yOrb = result.r * Math.sin(result.nu);
|
|
19553
|
-
if (!isFinite(xOrb) || !isFinite(yOrb)) return null;
|
|
19554
|
-
return orbitalToThreeJS(xOrb, yOrb, w, i, om, el.equatorial);
|
|
19555
|
-
}
|
|
19556
|
-
|
|
19557
20654
|
//#endregion
|
|
19558
20655
|
//#region src/lib/math/orbit/curves.ts
|
|
19559
20656
|
function orbitalElementsToParabola(el, numPoints = 512, rMaxAU = 50) {
|
|
@@ -19797,6 +20894,10 @@ function commitTrail(line, posArr, trailArr, fullArr, n, isOpenCurve, useTrail)
|
|
|
19797
20894
|
|
|
19798
20895
|
//#endregion
|
|
19799
20896
|
//#region src/lib/scene/objects/trail/builder.ts
|
|
20897
|
+
var FAT_TRAIL_MIN_PIXEL_RATIO = 1.5;
|
|
20898
|
+
function drawsFat(lineWidth) {
|
|
20899
|
+
return lineWidth > 1 || renderPixelRatio() >= FAT_TRAIL_MIN_PIXEL_RATIO;
|
|
20900
|
+
}
|
|
19800
20901
|
function writeBufferVerticesWithLiveHead(body, buffer, posArr, cx, cy, cz, basisPos, transform) {
|
|
19801
20902
|
const head = body.trailAnchor ?? body.position;
|
|
19802
20903
|
if (!head) return 0;
|
|
@@ -19820,7 +20921,7 @@ function makeBufferTrail(body, trailBuffer, color, basisPos, lineWidth) {
|
|
|
19820
20921
|
const fullAlphas = new Float32Array(geomCap);
|
|
19821
20922
|
const trailAlphas = new Float32Array(geomCap);
|
|
19822
20923
|
if (total > 0) writeTrailAlphas(fullAlphas.subarray(0, total), trailAlphas.subarray(0, total), true, useTrail);
|
|
19823
|
-
const isFat = lineWidth
|
|
20924
|
+
const isFat = drawsFat(lineWidth);
|
|
19824
20925
|
const obj = isFat ? buildFatLineFromThin(geomCap, posArr, trailAlphas, fullAlphas, total, color, lineWidth) : buildThinLineFromArrays(posArr, trailAlphas, fullAlphas, total, color);
|
|
19825
20926
|
obj.frustumCulled = false;
|
|
19826
20927
|
obj.visible = false;
|
|
@@ -19871,7 +20972,7 @@ function makeTrail(body, color, basisPos = [
|
|
|
19871
20972
|
posArr[k * 3 + 1] = validPoints[k][1] + by;
|
|
19872
20973
|
posArr[k * 3 + 2] = validPoints[k][2] + bz;
|
|
19873
20974
|
}
|
|
19874
|
-
const isFat = lineWidth
|
|
20975
|
+
const isFat = drawsFat(lineWidth);
|
|
19875
20976
|
const obj = isFat ? buildFatLineFromThin(bufferCapacity, posArr, trailAlphas, fullAlphas, validPoints.length, color, lineWidth) : buildThinLineFromArrays(posArr, trailAlphas, fullAlphas, validPoints.length, color);
|
|
19876
20977
|
obj.frustumCulled = false;
|
|
19877
20978
|
obj.visible = false;
|
|
@@ -20004,6 +21105,7 @@ var SystemDataLoader = class {
|
|
|
20004
21105
|
lastBaryId = null;
|
|
20005
21106
|
pendingUnloads = /* @__PURE__ */ new Set();
|
|
20006
21107
|
prefetched = /* @__PURE__ */ new Set();
|
|
21108
|
+
loads = 0;
|
|
20007
21109
|
constructor(scene, ctx, renderer, textureLoader, bodyObjects, clock, onLoaded) {
|
|
20008
21110
|
this.scene = scene;
|
|
20009
21111
|
this.ctx = ctx;
|
|
@@ -20049,10 +21151,14 @@ var SystemDataLoader = class {
|
|
|
20049
21151
|
return isTopLevelParent(baryId) ? null : baryId;
|
|
20050
21152
|
}
|
|
20051
21153
|
load(baryId) {
|
|
21154
|
+
this.loads++;
|
|
20052
21155
|
loadSystemData(baryId, this.bodyObjects, this.scene, this.textureLoader, this.clock.jd, this.renderer.capabilities.maxTextureSize, this.ctx).then(() => {
|
|
20053
21156
|
this.onLoaded();
|
|
20054
21157
|
this.ctx.bodies.orientationVersion++;
|
|
20055
|
-
});
|
|
21158
|
+
}).finally(() => this.loads--);
|
|
21159
|
+
}
|
|
21160
|
+
isLoading() {
|
|
21161
|
+
return this.loads > 0;
|
|
20056
21162
|
}
|
|
20057
21163
|
drainPendingUnloads() {
|
|
20058
21164
|
if (this.pendingUnloads.size === 0) return;
|
|
@@ -20765,7 +21871,7 @@ function collectDebugStats(params) {
|
|
|
20765
21871
|
|
|
20766
21872
|
//#endregion
|
|
20767
21873
|
//#region src/lib/math/orbit/worker.ts?worker&inline
|
|
20768
|
-
var jsContent = "function e(e,t,n=1e-10,r=50){let i=e;for(let a=0;a<r;a++){let r=(i-t*Math.sin(i)-e)/(1-t*Math.cos(i));if(i-=Math.max(-1,Math.min(1,r)),Math.abs(r)<n)break}return i}function t(e,t,n=1e-10,r=50){if(e===0)return 0;let i=e<0?-1:1,a=Math.abs(e),o=0,s=1;for(;t*Math.sinh(s)-s<a;)if(s*=2,s>700)return NaN;let c=.5*(o+s);for(let e=0;e<r;e++){let e=t*Math.sinh(c)-c-a;e>0?s=c:o=c;let r=c-e/(t*Math.cosh(c)-1);r>o&&r<s||(r=.5*(o+s));let i=Math.abs(r-c);if(c=r,i<n)break}return i*c}function n(e,t,n){let r=.01720209895*(n-t)/(Math.sqrt(2)*e**1.5),i=Math.cbrt(3*r+Math.sqrt(1+9*r*r)),a=i-1/i,o=2*Math.atan(a),s=e*(1+a*a);return!isFinite(o)||!isFinite(s)||s<=0?null:{nu:o,r:s}}const r=149597870.7,i=23.4392911;86400**2/r**3,1/r,Math.cos(Math.PI/180*i),Math.sin(Math.PI/180*i);const a=Math.PI,o=a*2,s=a/180;180/a;const c=6378.135,l=60/Math.sqrt(c*c*c/398600.8),u=c*l/60,d=1/l,f=.001082616,p=-253881e-11/f,m=2/3,ee=1440/(2*a);function te(e,t){let n=[31,e%4==0?29:28,31,30,31,30,31,31,30,31,30,31],r=Math.floor(t),i=1,a=0;for(;r>a+n[i-1]&&i<12;)a+=n[i-1],i+=1;let o=i,s=r-a,c=(t-r)*24,l=Math.floor(c);c=(c-l)*60;let u=Math.floor(c);return{mon:o,day:s,hr:l,minute:u,sec:(c-u)*60}}function h(e,t,n,r,i,a,o=0){return 367*e-Math.floor(7*(e+Math.floor((t+9)/12))*.25)+Math.floor(275*t/9)+n+1721013.5+((o/6e4+a/60+i)/60+r)/24}function g(e,t,n,r,i,a,o=0){if(e instanceof Date){let t=e;return h(t.getUTCFullYear(),t.getUTCMonth()+1,t.getUTCDate(),t.getUTCHours(),t.getUTCMinutes(),t.getUTCSeconds(),t.getUTCMilliseconds())}return h(e,t,n,r,i,a,o)}function ne(e,t){let{e3:n,ee2:r,peo:i,pgho:s,pho:c,pinco:l,plo:u,se2:d,se3:f,sgh2:p,sgh3:m,sgh4:ee,sh2:te,sh3:h,si2:g,si3:ne,sl2:_,sl3:v,sl4:y,t:b,xgh2:re,xgh3:ie,xgh4:x,xh2:ae,xh3:S,xi2:C,xi3:w,xl2:T,xl3:E,xl4:D,zmol:O,zmos:k}=e,{init:A,opsmode:j}=t,{ep:oe,inclp:M,nodep:N,argpp:se,mp:P}=t,F,I,L,R,ce,z,B,V,H,U,W,G,K,q,J,le,Y,ue,de,X,fe;fe=k+119459e-10*b,A===`y`&&(fe=k),X=fe+2*.01675*Math.sin(fe),Y=Math.sin(X),U=.5*Y*Y-.25,W=-.5*Y*Math.cos(X);let pe=d*U+f*W,me=g*U+ne*W,he=_*U+v*W+y*Y,ge=p*U+m*W+ee*Y,Z=te*U+h*W;fe=O+.00015835218*b,A===`y`&&(fe=O),X=fe+2*.0549*Math.sin(fe),Y=Math.sin(X),U=.5*Y*Y-.25,W=-.5*Y*Math.cos(X);let _e=r*U+n*W,ve=C*U+w*W,ye=T*U+E*W+D*Y,be=re*U+ie*W+x*Y,xe=ae*U+S*W;return G=pe+_e,J=me+ve,le=he+ye,K=ge+be,q=Z+xe,A===`n`&&(G-=i,J-=l,le-=u,K-=s,q-=c,M+=J,oe+=G,R=Math.sin(M),L=Math.cos(M),M>=.2?(q/=R,K-=L*q,se+=K,N+=q,P+=le):(z=Math.sin(N),ce=Math.cos(N),F=R*z,I=R*ce,B=q*ce+J*L*z,V=-q*z+J*L*ce,F+=B,I+=V,N%=o,N<0&&j===`a`&&(N+=o),ue=P+se+L*N,H=le+K-J*N*R,ue+=H,de=N,N=Math.atan2(F,I),N<0&&j===`a`&&(N+=o),Math.abs(de-N)>a&&(N<de?N+=o:N-=o),P+=le,se=ue-P-L*N)),{ep:oe,inclp:M,nodep:N,argpp:se,mp:P}}function _(e){let{epoch:t,ep:n,argpp:r,tc:i,inclp:a,nodep:s,np:c}=e,l,u,d,f,p,m,ee,te,h,g,ne,_,v,y,b,re,ie,x,ae,S,C,w,T,E,D,O,k,A,j,oe,M,N,se,P,F,I,L,R,ce,z,B,V,H,U,W,G,K,q,J,le,Y,ue,de,X,fe,pe,me,he,ge,Z,_e,ve,ye,be=.01675,xe=.0549,Se=c,Ce=n,we=Math.sin(s),Te=Math.cos(s),Ee=Math.sin(r),Q=Math.cos(r),De=Math.sin(a),Oe=Math.cos(a),$=Ce*Ce,ke=1-$,Ae=Math.sqrt(ke),je=t+18261.5+i/1440,Me=(4.523602-.00092422029*je)%o,Ne=Math.sin(Me),Pe=Math.cos(Me),Fe=.91375164-.03568096*Pe,Ie=Math.sqrt(1-Fe*Fe),Le=.089683511*Ne/Ie,Re=Math.sqrt(1-Le*Le),ze=5.8351514+.001944368*je,Be=.39785416*Ne/Ie,Ve=Re*Pe+.91744867*Le*Ne;Be=Math.atan2(Be,Ve),Be+=ze-Me;let He=Math.cos(Be),Ue=Math.sin(Be);S=.1945905,C=-.98088458,E=.91744867,D=.39785416,w=Te,T=we,ne=29864797e-13;let We=1/Se,Ge=0;for(;Ge<2;)Ge+=1,l=S*w+C*E*T,d=-C*w+S*E*T,ee=-S*T+C*E*w,te=C*D,h=C*T+S*E*w,g=S*D,u=Oe*ee+De*te,f=Oe*h+De*g,p=-De*ee+Oe*te,m=-De*h+Oe*g,_=l*Q+u*Ee,v=d*Q+f*Ee,y=-l*Ee+u*Q,b=-d*Ee+f*Q,re=p*Ee,ie=m*Ee,x=p*Q,ae=m*Q,_e=12*_*_-3*y*y,ve=24*_*v-6*y*b,ye=12*v*v-3*b*b,ue=3*(l*l+u*u)+_e*$,de=6*(l*d+u*f)+ve*$,X=3*(d*d+f*f)+ye*$,fe=-6*l*p+$*(-24*_*x-6*y*re),pe=-6*(l*m+d*p)+$*(-24*(v*x+_*ae)+-6*(y*ie+b*re)),me=-6*d*m+$*(-24*v*ae-6*b*ie),he=6*u*p+$*(24*_*re-6*y*x),ge=6*(f*p+u*m)+$*(24*(v*re+_*ie)-6*(b*x+y*ae)),Z=6*f*m+$*(24*v*ie-6*b*ae),ue=ue+ue+ke*_e,de=de+de+ke*ve,X=X+X+ke*ye,K=ne*We,G=-.5*K/Ae,q=K*Ae,W=-15*Ce*q,J=_*y+v*b,le=v*y+_*b,Y=v*b-_*y,Ge===1&&(O=W,k=G,A=K,j=q,oe=J,M=le,N=Y,se=ue,P=de,F=X,I=fe,L=pe,R=me,ce=he,z=ge,B=Z,V=_e,H=ve,U=ye,S=He,C=Ue,E=Fe,D=Ie,w=Re*Te+Le*we,T=we*Re-Te*Le,ne=4.7968065e-7);let Ke=(4.7199672+(.2299715*je-ze))%o,qe=(6.2565837+.017201977*je)%o,Je=2*O*M,Ye=2*O*N,Xe=2*k*L,Ze=2*k*(R-I),Qe=-2*A*P,$e=-2*A*(F-se),et=-2*A*(-21-9*$)*be,tt=2*j*H,nt=2*j*(U-V),rt=-18*j*be,it=-2*k*z,at=-2*k*(B-ce),ot=2*W*le,st=2*W*Y,ct=2*G*pe,lt=2*G*(me-fe),ut=-2*K*de,dt=-2*K*(X-ue),ft=-2*K*(-21-9*$)*xe,pt=2*q*ve,mt=2*q*(ye-_e),ht=-18*q*xe,gt=-2*G*ge,_t=-2*G*(Z-he);return{snodm:we,cnodm:Te,sinim:De,cosim:Oe,sinomm:Ee,cosomm:Q,day:je,e3:st,ee2:ot,em:Ce,emsq:$,gam:ze,peo:0,pgho:0,pho:0,pinco:0,plo:0,rtemsq:Ae,se2:Je,se3:Ye,sgh2:tt,sgh3:nt,sgh4:rt,sh2:it,sh3:at,si2:Xe,si3:Ze,sl2:Qe,sl3:$e,sl4:et,s1:W,s2:G,s3:K,s4:q,s5:J,s6:le,s7:Y,ss1:O,ss2:k,ss3:A,ss4:j,ss5:oe,ss6:M,ss7:N,sz1:se,sz2:P,sz3:F,sz11:I,sz12:L,sz13:R,sz21:ce,sz22:z,sz23:B,sz31:V,sz32:H,sz33:U,xgh2:pt,xgh3:mt,xgh4:ht,xh2:gt,xh3:_t,xi2:ct,xi3:lt,xl2:ut,xl3:dt,xl4:ft,nm:Se,z1:ue,z2:de,z3:X,z11:fe,z12:pe,z13:me,z21:he,z22:ge,z23:Z,z31:_e,z32:ve,z33:ye,zmol:Ke,zmos:qe}}function v(e){let{cosim:t,argpo:n,s1:r,s2:i,s3:s,s4:c,s5:u,sinim:d,ss1:f,ss2:p,ss3:ee,ss4:te,ss5:h,sz1:g,sz3:ne,sz11:_,sz13:v,sz21:y,sz23:b,sz31:re,sz33:ie,t:x,tc:ae,gsto:S,mo:C,mdot:w,no:T,nodeo:E,nodedot:D,xpidot:O,z1:k,z3:A,z11:j,z13:oe,z21:M,z23:N,z31:se,z33:P,ecco:F,eccsq:I}=e,{emsq:L,em:R,argpm:ce,inclm:z,mm:B,nm:V,nodem:H,irez:U,atime:W,d2201:G,d2211:K,d3210:q,d3222:J,d4410:le,d4422:Y,d5220:ue,d5232:de,d5421:X,d5433:fe,dedt:pe,didt:me,dmdt:he,dnodt:ge,domdt:Z,del1:_e,del2:ve,del3:ye,xfact:be,xlamo:xe,xli:Se,xni:Ce}=e,we,Te,Ee,Q,De,Oe,$,ke,Ae,je,Me,Ne,Pe,Fe,Ie,Le,Re,ze,Be,Ve,He,Ue,We,Ge,Ke,qe,Je,Ye,Xe,Ze,Qe,$e,et=.0043752690880113,tt=.00015835218,nt=119459e-10;U=0,V<.0052359877&&V>.0034906585&&(U=1),V>=.00826&&V<=.00924&&R>=.5&&(U=2);let rt=f*nt*h,it=p*nt*(_+v),at=-nt*ee*(g+ne-14-6*L),ot=te*nt*(re+ie-6),st=-nt*p*(y+b);(z<.052359877||z>a-.052359877)&&(st=0),d!==0&&(st/=d);let ct=ot-t*st;pe=rt+r*tt*u,me=it+i*tt*(j+oe),he=at-tt*s*(k+A-14-6*L);let lt=c*tt*(se+P-6),ut=-tt*i*(M+N);(z<.052359877||z>a-.052359877)&&(ut=0),Z=ct+lt,ge=st,d!==0&&(Z-=t/d*ut,ge+=ut/d);let dt=(S+ae*et)%o;if(R+=pe*x,z+=me*x,ce+=Z*x,H+=ge*x,B+=he*x,U!==0){if(Ze=(V/l)**m,U===2){Qe=t*t;let e=R;R=F;let n=L;L=I,$e=R*L,Fe=-.306-(R-.64)*.44,R<=.65?(Ie=3.616-13.247*R+16.29*L,Re=-19.302+117.39*R-228.419*L+156.591*$e,ze=-18.9068+109.7927*R-214.6334*L+146.5816*$e,Be=-41.122+242.694*R-471.094*L+313.953*$e,Ve=-146.407+841.88*R-1629.014*L+1083.435*$e,He=-532.114+3017.977*R-5740.032*L+3708.276*$e):(Ie=-72.099+331.819*R-508.738*L+266.724*$e,Re=-346.844+1582.851*R-2415.925*L+1246.113*$e,ze=-342.585+1554.908*R-2366.899*L+1215.972*$e,Be=-1052.797+4758.686*R-7193.992*L+3651.957*$e,Ve=-3581.69+16178.11*R-24462.77*L+12422.52*$e,He=R>.715?-5149.66+29936.92*R-54087.36*L+31324.56*$e:1464.74-4664.75*R+3763.64*L),R<.7?(Ge=-919.2277+4988.61*R-9064.77*L+5542.21*$e,Ue=-822.71072+4568.6173*R-8491.4146*L+5337.524*$e,We=-853.666+4690.25*R-8624.77*L+5341.4*$e):(Ge=-37995.78+161616.52*R-229838.2*L+109377.94*$e,Ue=-51752.104+218913.95*R-309468.16*L+146349.42*$e,We=-40023.88+170470.89*R-242699.48*L+115605.82*$e),Ke=d*d,we=.75*(1+2*t+Qe),Te=1.5*Ke,Q=1.875*d*(1-2*t-3*Qe),De=-1.875*d*(1+2*t-3*Qe),$=35*Ke*we,ke=39.375*Ke*Ke,Ae=9.84375*d*(Ke*(1-2*t-5*Qe)+.33333333*(-2+4*t+6*Qe)),je=d*(4.92187512*Ke*(-2-4*t+10*Qe)+6.56250012*(1+2*t-3*Qe)),Me=29.53125*d*(2-8*t+Qe*(-12+8*t+10*Qe)),Ne=29.53125*d*(-2-8*t+Qe*(12+8*t-10*Qe)),Ye=V*V,Xe=Ze*Ze,Je=3*Ye*Xe,qe=Je*17891679e-13,G=qe*we*Fe,K=qe*Te*Ie,Je*=Ze,qe=Je*3.7393792e-7,q=qe*Q*Re,J=qe*De*ze,Je*=Ze,qe=2*Je*7.3636953e-9,le=qe*$*Be,Y=qe*ke*Ve,Je*=Ze,qe=Je*1.1428639e-7,ue=qe*Ae*He,de=qe*je*We,qe=2*Je*2.1765803e-9,X=qe*Me*Ue,fe=qe*Ne*Ge,xe=(C+E+E-(dt+dt))%o,be=w+he+2*(D+ge-et)-T,R=e,L=n}U===1&&(Pe=1+L*(-2.5+.8125*L),Re=1+2*L,Le=1+L*(-6+6.60937*L),we=.75*(1+t)*(1+t),Ee=.9375*d*d*(1+3*t)-.75*(1+t),Oe=1+t,Oe*=1.875*Oe*Oe,_e=3*V*V*Ze*Ze,ve=2*_e*we*Pe*17891679e-13,ye=3*_e*Oe*Le*2.2123015e-7*Ze,_e=_e*Ee*Re*21460748e-13*Ze,xe=(C+E+n-dt)%o,be=w+O+he+Z+ge-(T+et)),Se=xe,Ce=T,W=0,V=T+0}return{em:R,argpm:ce,inclm:z,mm:B,nm:V,nodem:H,irez:U,atime:W,d2201:G,d2211:K,d3210:q,d3222:J,d4410:le,d4422:Y,d5220:ue,d5232:de,d5421:X,d5433:fe,dedt:pe,didt:me,dmdt:he,dndt:0,dnodt:ge,domdt:Z,del1:_e,del2:ve,del3:ye,xfact:be,xlamo:xe,xli:Se,xni:Ce}}function y(e){let t=(e-2451545)/36525,n=-62e-7*t*t*t+.093104*t*t+3164400184.812866*t+67310.54841;return n=n*s/240%o,n<0&&(n+=o),n}function b(e,t,n,r,i,a,o){return e instanceof Date?y(g(e)):y(t===void 0?e:g(e,t,n,r,i,a,o))}function re(e){let{ecco:t,epoch:n,inclo:r,opsmode:i}=e,{no:a}=e,s=t*t,c=1-s,u=Math.sqrt(c),d=Math.cos(r),p=d*d,ee=(l/a)**m,te=.75*f*(3*p-1)/(u*c),h=te/(ee*ee),g=ee*(1-h*h-h*(1/3+134*h*h/81));h=te/(g*g),a/=1+h;let ne=(l/a)**m,_=Math.sin(r),v=ne*c,y=1-5*p,re=-y-p-p,ie=1/ne,x=v*v,ae=ne*(1-t),S;if(i===`a`){let e=n-7305,t=Math.floor(e+1e-8),r=e-t,i=.017202791694070362,a=i+o;S=(1.7321343856509375+i*t+a*r+e*e*5075514194322695e-30)%o,S<0&&(S+=o)}else S=b(n+2433281.5);return{no:a,method:`n`,ainv:ie,ao:ne,con41:re,con42:y,cosio:d,cosio2:p,eccsq:s,omeosq:c,posq:x,rp:ae,rteosq:u,sinio:_,gsto:S}}function ie(e){let{irez:t,d2201:n,d2211:r,d3210:i,d3222:a,d4410:s,d4422:c,d5220:l,d5232:u,d5421:d,d5433:f,dedt:p,del1:m,del2:ee,del3:te,didt:h,dmdt:g,dnodt:ne,domdt:_,argpo:v,argpdot:y,t:b,tc:re,gsto:ie,xfact:x,xlamo:ae,no:S}=e,{atime:C,em:w,argpm:T,inclm:E,xli:D,mm:O,xni:k,nodem:A,nm:j}=e,oe=.13130908,M=2.8843198,N=.37448087,se=5.7686396,P=.95240898,F=1.8014998,I=1.050833,L=4.4108898,R=259200,ce,z,B,V,H,U,W,G,K=0,q=0,J=(ie+re*.0043752690880113)%o;if(w+=p*b,E+=h*b,T+=_*b,A+=ne*b,O+=g*b,t!==0){(C===0||b*C<=0||Math.abs(b)<Math.abs(C))&&(C=0,k=S,D=ae),ce=b>0?720:-720;let e=381;for(;e===381;)t===2?(G=v+y*C,B=G+G,z=D+D,W=n*Math.sin(B+D-se)+r*Math.sin(D-se)+i*Math.sin(G+D-P)+a*Math.sin(-G+D-P)+s*Math.sin(B+z-F)+c*Math.sin(z-F)+l*Math.sin(G+D-I)+u*Math.sin(-G+D-I)+d*Math.sin(G+z-L)+f*Math.sin(-G+z-L),H=k+x,U=n*Math.cos(B+D-se)+r*Math.cos(D-se)+i*Math.cos(G+D-P)+a*Math.cos(-G+D-P)+l*Math.cos(G+D-I)+u*Math.cos(-G+D-I)+2*(s*Math.cos(B+z-F)+c*Math.cos(z-F)+d*Math.cos(G+z-L)+f*Math.cos(-G+z-L)),U*=H):(W=m*Math.sin(D-oe)+ee*Math.sin(2*(D-M))+te*Math.sin(3*(D-N)),H=k+x,U=m*Math.cos(D-oe)+2*ee*Math.cos(2*(D-M))+3*te*Math.cos(3*(D-N)),U*=H),Math.abs(b-C)>=720?e=381:(q=b-C,e=0),e===381&&(D+=H*ce+W*R,k+=W*ce+U*R,C+=ce);j=k+W*q+U*q*q*.5,V=D+H*q+W*q*q*.5,t===1?(O=V-A-T+J,K=j-S):(O=V-2*A+2*J,K=j-S),j=S+K}return{atime:C,em:w,argpm:T,inclm:E,xli:D,mm:O,xni:k,nodem:A,dndt:K,nm:j}}var x;(function(e){e[e.None=0]=`None`,e[e.MeanEccentricityOutOfRange=1]=`MeanEccentricityOutOfRange`,e[e.MeanMotionBelowZero=2]=`MeanMotionBelowZero`,e[e.PerturbedEccentricityOutOfRange=3]=`PerturbedEccentricityOutOfRange`,e[e.SemiLatusRectumBelowZero=4]=`SemiLatusRectumBelowZero`,e[e.Decayed=6]=`Decayed`})(x||={});function ae(e,t){let n,r,i,s,d,ee,te,h,g,_,v,y,b,re,ae,S,C,w,T,E,D,O,k,A,j,oe,M;e.t=t,e.error=x.None;let N=e.mo+e.mdot*e.t,se=e.argpo+e.argpdot*e.t,P=e.nodeo+e.nodedot*e.t;g=se,D=N;let F=e.t*e.t;if(k=P+e.nodecf*F,C=1-e.cc1*e.t,w=e.bstar*e.cc4*e.t,T=e.t2cof*F,e.isimp!==1){te=e.omgcof*e.t;let t=1+e.eta*Math.cos(N);ee=e.xmcof*(t*t*t-e.delmo),S=te+ee,D=N+S,g=se-S,y=F*e.t,b=y*e.t,C=C-e.d2*F-e.d3*y-e.d4*b,w+=e.bstar*e.cc5*(Math.sin(D)-e.sinmao),T=T+e.t3cof*y+b*(e.t4cof+e.t*e.t5cof)}O=e.no;let I=e.ecco;if(E=e.inclo,e.method===`d`){re=e.t;let t=ie({irez:e.irez,d2201:e.d2201,d2211:e.d2211,d3210:e.d3210,d3222:e.d3222,d4410:e.d4410,d4422:e.d4422,d5220:e.d5220,d5232:e.d5232,d5421:e.d5421,d5433:e.d5433,dedt:e.dedt,del1:e.del1,del2:e.del2,del3:e.del3,didt:e.didt,dmdt:e.dmdt,dnodt:e.dnodt,domdt:e.domdt,argpo:e.argpo,argpdot:e.argpdot,t:e.t,tc:re,gsto:e.gsto,xfact:e.xfact,xlamo:e.xlamo,no:e.no,atime:e.atime,em:I,argpm:g,inclm:E,xli:e.xli,mm:D,xni:e.xni,nodem:k,nm:O});({em:I,argpm:g,inclm:E,mm:D,nodem:k,nm:O}=t)}if(O<=0)return e.error=x.MeanMotionBelowZero,null;let L=(l/O)**m*C*C;if(O=l/L**1.5,I-=w,I>=1||I<-.001)return e.error=x.MeanEccentricityOutOfRange,null;I<1e-6&&(I=1e-6),D+=e.no*T,j=D+g+k,k%=o,g%=o,j%=o,D=(j-g-k)%o;let R={am:L,em:I,im:E,Om:k,om:g,mm:D,nm:O},ce=Math.sin(E),z=Math.cos(E),B=I;if(A=E,_=g,M=k,oe=D,s=ce,i=z,e.method===`d`){let t=ne(e,{inclo:e.inclo,init:`n`,ep:B,inclp:A,nodep:M,argpp:_,mp:oe,opsmode:e.operationmode});if({ep:B,nodep:M,argpp:_,mp:oe}=t,A=t.inclp,A<0&&(A=-A,M+=a,_-=a),B<0||B>1)return e.error=x.PerturbedEccentricityOutOfRange,null}e.method===`d`&&(s=Math.sin(A),i=Math.cos(A),e.aycof=-.5*p*s,Math.abs(i+1)>15e-13?e.xlcof=-.25*p*s*(3+5*i)/(1+i):e.xlcof=-.25*p*s*(3+5*i)/15e-13);let V=B*Math.cos(_);S=1/(L*(1-B*B));let H=B*Math.sin(_)+S*e.aycof,U=(oe+_+M+S*e.xlcof*V-M)%o;h=U,ae=9999.9;let W=1;for(;Math.abs(ae)>=1e-12&&W<=10;)r=Math.sin(h),n=Math.cos(h),ae=1-n*V-r*H,ae=(U-H*n+V*r-h)/ae,Math.abs(ae)>=.95&&(ae=ae>0?.95:-.95),h+=ae,W+=1;let G=V*n+H*r,K=V*r-H*n,q=V*V+H*H,J=L*(1-q);if(J<0)return e.error=x.SemiLatusRectumBelowZero,null;let le=L*(1-G),Y=Math.sqrt(L)*K/le,ue=Math.sqrt(J)/le,de=Math.sqrt(1-q);S=K/(1+de);let X=L/le*(r-H-V*S),fe=L/le*(n-V+H*S);v=Math.atan2(X,fe);let pe=(fe+fe)*X,me=1-2*X*X;S=1/J;let he=.5*f*S,ge=he*S;e.method===`d`&&(d=i*i,e.con41=3*d-1,e.x1mth2=1-d,e.x7thm1=7*d-1);let Z=le*(1-1.5*ge*de*e.con41)+.5*he*e.x1mth2*me;if(Z<1)return e.error=x.Decayed,null;v-=.25*ge*e.x7thm1*pe;let _e=M+1.5*ge*i*pe,ve=A+1.5*ge*i*s*me,ye=Y-O*he*e.x1mth2*pe/l,be=ue+O*he*(e.x1mth2*me+1.5*e.con41)/l,xe=Math.sin(v),Se=Math.cos(v),Ce=Math.sin(_e),we=Math.cos(_e),Te=Math.sin(ve),Ee=Math.cos(ve),Q=-Ce*Ee,De=we*Ee,Oe=Q*xe+we*Se,$=De*xe+Ce*Se,ke=Te*xe,Ae=Q*Se-we*xe,je=De*Se-Ce*xe,Me=Te*Se;return{position:{x:Z*Oe*c,y:Z*$*c,z:Z*ke*c},velocity:{x:(ye*Oe+be*Ae)*u,y:(ye*$+be*je)*u,z:(ye*ke+be*Me)*u},meanElements:R}}function S(e,t){let{opsmode:n,satn:r,epoch:i,xbstar:o,xecco:s,xargpo:l,xinclo:u,xmo:ee,xno:te,xnodeo:h}=t,g,y,b,ie,x,S,C,w,T,E,D,O,k,A,j,oe,M,N,se,P,F,I,L,R,ce,z,B,V,H,U,W,G,K,q,J,le,Y,ue,de,X,fe,pe,me,he,ge,Z,_e,ve,ye,be,xe,Se,Ce,we,Te,Ee,Q=e;Q.isimp=0,Q.method=`n`,Q.aycof=0,Q.con41=0,Q.cc1=0,Q.cc4=0,Q.cc5=0,Q.d2=0,Q.d3=0,Q.d4=0,Q.delmo=0,Q.eta=0,Q.argpdot=0,Q.omgcof=0,Q.sinmao=0,Q.t=0,Q.t2cof=0,Q.t3cof=0,Q.t4cof=0,Q.t5cof=0,Q.x1mth2=0,Q.x7thm1=0,Q.mdot=0,Q.nodedot=0,Q.xlcof=0,Q.xmcof=0,Q.nodecf=0,Q.irez=0,Q.d2201=0,Q.d2211=0,Q.d3210=0,Q.d3222=0,Q.d4410=0,Q.d4422=0,Q.d5220=0,Q.d5232=0,Q.d5421=0,Q.d5433=0,Q.dedt=0,Q.del1=0,Q.del2=0,Q.del3=0,Q.didt=0,Q.dmdt=0,Q.dnodt=0,Q.domdt=0,Q.e3=0,Q.ee2=0,Q.peo=0,Q.pgho=0,Q.pho=0,Q.pinco=0,Q.plo=0,Q.se2=0,Q.se3=0,Q.sgh2=0,Q.sgh3=0,Q.sgh4=0,Q.sh2=0,Q.sh3=0,Q.si2=0,Q.si3=0,Q.sl2=0,Q.sl3=0,Q.sl4=0,Q.gsto=0,Q.xfact=0,Q.xgh2=0,Q.xgh3=0,Q.xgh4=0,Q.xh2=0,Q.xh3=0,Q.xi2=0,Q.xi3=0,Q.xl2=0,Q.xl3=0,Q.xl4=0,Q.xlamo=0,Q.zmol=0,Q.zmos=0,Q.atime=0,Q.xli=0,Q.xni=0,Q.bstar=o,Q.ecco=s,Q.argpo=l,Q.inclo=u,Q.mo=ee,Q.no=te,Q.nodeo=h,Q.operationmode=n,78/c+1;let De=42/c;De*De*De*De,Q.init=`y`,Q.t=0;let Oe=re({satn:r,ecco:Q.ecco,epoch:i,inclo:Q.inclo,no:Q.no,method:Q.method,opsmode:Q.operationmode}),{ao:$,con42:ke,cosio:Ae,cosio2:je,eccsq:Me,omeosq:Ne,posq:Pe,rp:Fe,rteosq:Ie,sinio:Le}=Oe;if(Q.no=Oe.no,Q.con41=Oe.con41,Q.gsto=Oe.gsto,Q.a=(Q.no*d)**(-2/3),Q.alta=Q.a*(1+Q.ecco)-1,Q.altp=Q.a*(1-Q.ecco)-1,Q.error=0,Ne>=0||Q.no>=0){if(Q.isimp=0,Fe<1.034492841559484&&(Q.isimp=1),B=1.0122292801892716,F=1.880279159015271e-9,N=(Fe-1)*c,N<156){B=N-78,N<98&&(B=20);let e=(120-B)/c;F=e*e*e*e,B=B/c+1}se=1/Pe,Z=1/($-B),Q.eta=$*Q.ecco*Z,O=Q.eta*Q.eta,D=Q.ecco*Q.eta,P=Math.abs(1-O),S=F*Z**4,C=S/P**3.5,ie=C*Q.no*($*(1+1.5*O+D*(4+O))+.375*f*Z/P*Q.con41*(8+3*O*(8+O))),Q.cc1=Q.bstar*ie,x=0,Q.ecco>1e-4&&(x=-2*S*Z*p*Q.no*Le/Q.ecco),Q.x1mth2=1-je,Q.cc4=2*Q.no*C*$*Ne*(Q.eta*(2+.5*O)+Q.ecco*(.5+2*O)-f*Z/($*P)*(-3*Q.con41*(1-2*D+O*(1.5-.5*D))+.75*Q.x1mth2*(2*O-D*(1+O))*Math.cos(2*Q.argpo))),Q.cc5=2*C*$*Ne*(1+2.75*(O+D)+D*O),w=je*je,me=1.5*f*se*Q.no,he=.5*me*f*se,ge=-.46875*-165597e-11*se*se*Q.no,Q.mdot=Q.no+.5*me*Ie*Q.con41+.0625*he*Ie*(13-78*je+137*w),Q.argpdot=-.5*me*ke+.0625*he*(7-114*je+395*w)+ge*(3-36*je+49*w),ve=-me*Ae,Q.nodedot=ve+(.5*he*(4-19*je)+2*ge*(3-7*je))*Ae,_e=Q.argpdot+Q.nodedot,Q.omgcof=Q.bstar*x*Math.cos(Q.argpo),Q.xmcof=0,Q.ecco>1e-4&&(Q.xmcof=-m*S*Q.bstar/D),Q.nodecf=3.5*Ne*ve*Q.cc1,Q.t2cof=1.5*Q.cc1,Math.abs(Ae+1)>15e-13?Q.xlcof=-.25*p*Le*(3+5*Ae)/(1+Ae):Q.xlcof=-.25*p*Le*(3+5*Ae)/15e-13,Q.aycof=-.5*p*Le;let e=1+Q.eta*Math.cos(Q.mo);if(Q.delmo=e*e*e,Q.sinmao=Math.sin(Q.mo),Q.x7thm1=7*je-1,2*a/Q.no>=225){Q.method=`d`,Q.isimp=1,fe=0,j=Q.inclo;let e=_({epoch:i,ep:Q.ecco,argpp:Q.argpo,tc:fe,inclp:Q.inclo,nodep:Q.nodeo,np:Q.no,e3:Q.e3,ee2:Q.ee2,peo:Q.peo,pgho:Q.pgho,pho:Q.pho,pinco:Q.pinco,plo:Q.plo,se2:Q.se2,se3:Q.se3,sgh2:Q.sgh2,sgh3:Q.sgh3,sgh4:Q.sgh4,sh2:Q.sh2,sh3:Q.sh3,si2:Q.si2,si3:Q.si3,sl2:Q.sl2,sl3:Q.sl3,sl4:Q.sl4,xgh2:Q.xgh2,xgh3:Q.xgh3,xgh4:Q.xgh4,xh2:Q.xh2,xh3:Q.xh3,xi2:Q.xi2,xi3:Q.xi3,xl2:Q.xl2,xl3:Q.xl3,xl4:Q.xl4,zmol:Q.zmol,zmos:Q.zmos});Q.e3=e.e3,Q.ee2=e.ee2,Q.peo=e.peo,Q.pgho=e.pgho,Q.pho=e.pho,Q.pinco=e.pinco,Q.plo=e.plo,Q.se2=e.se2,Q.se3=e.se3,Q.sgh2=e.sgh2,Q.sgh3=e.sgh3,Q.sgh4=e.sgh4,Q.sh2=e.sh2,Q.sh3=e.sh3,Q.si2=e.si2,Q.si3=e.si3,Q.sl2=e.sl2,Q.sl3=e.sl3,Q.sl4=e.sl4,{sinim:y,cosim:g,em:T,emsq:E,s1:I,s2:L,s3:R,s4:ce,s5:z,ss1:V,ss2:H,ss3:U,ss4:W,ss5:G,sz1:K,sz3:q,sz11:J,sz13:le,sz21:Y,sz23:ue,sz31:de,sz33:X}=e,Q.xgh2=e.xgh2,Q.xgh3=e.xgh3,Q.xgh4=e.xgh4,Q.xh2=e.xh2,Q.xh3=e.xh3,Q.xi2=e.xi2,Q.xi3=e.xi3,Q.xl2=e.xl2,Q.xl3=e.xl3,Q.xl4=e.xl4,Q.zmol=e.zmol,Q.zmos=e.zmos,{nm:M,z1:ye,z3:be,z11:xe,z13:Se,z21:Ce,z23:we,z31:Te,z33:Ee}=e;let t=ne(Q,{inclo:j,init:Q.init,ep:Q.ecco,inclp:Q.inclo,nodep:Q.nodeo,argpp:Q.argpo,mp:Q.mo,opsmode:Q.operationmode});Q.ecco=t.ep,Q.inclo=t.inclp,Q.nodeo=t.nodep,Q.argpo=t.argpp,Q.mo=t.mp,k=0,A=0,oe=0;let n=v({cosim:g,emsq:E,argpo:Q.argpo,s1:I,s2:L,s3:R,s4:ce,s5:z,sinim:y,ss1:V,ss2:H,ss3:U,ss4:W,ss5:G,sz1:K,sz3:q,sz11:J,sz13:le,sz21:Y,sz23:ue,sz31:de,sz33:X,t:Q.t,tc:fe,gsto:Q.gsto,mo:Q.mo,mdot:Q.mdot,no:Q.no,nodeo:Q.nodeo,nodedot:Q.nodedot,xpidot:_e,z1:ye,z3:be,z11:xe,z13:Se,z21:Ce,z23:we,z31:Te,z33:Ee,ecco:Q.ecco,eccsq:Me,em:T,argpm:k,inclm:j,mm:oe,nm:M,nodem:A,irez:Q.irez,atime:Q.atime,d2201:Q.d2201,d2211:Q.d2211,d3210:Q.d3210,d3222:Q.d3222,d4410:Q.d4410,d4422:Q.d4422,d5220:Q.d5220,d5232:Q.d5232,d5421:Q.d5421,d5433:Q.d5433,dedt:Q.dedt,didt:Q.didt,dmdt:Q.dmdt,dnodt:Q.dnodt,domdt:Q.domdt,del1:Q.del1,del2:Q.del2,del3:Q.del3,xfact:Q.xfact,xlamo:Q.xlamo,xli:Q.xli,xni:Q.xni});Q.irez=n.irez,Q.atime=n.atime,Q.d2201=n.d2201,Q.d2211=n.d2211,Q.d3210=n.d3210,Q.d3222=n.d3222,Q.d4410=n.d4410,Q.d4422=n.d4422,Q.d5220=n.d5220,Q.d5232=n.d5232,Q.d5421=n.d5421,Q.d5433=n.d5433,Q.dedt=n.dedt,Q.didt=n.didt,Q.dmdt=n.dmdt,Q.dnodt=n.dnodt,Q.domdt=n.domdt,Q.del1=n.del1,Q.del2=n.del2,Q.del3=n.del3,Q.xfact=n.xfact,Q.xlamo=n.xlamo,Q.xli=n.xli,Q.xni=n.xni}Q.isimp!==1&&(b=Q.cc1*Q.cc1,Q.d2=4*$*Z*b,pe=Q.d2*Z*Q.cc1/3,Q.d3=(17*$+B)*pe,Q.d4=.5*pe*$*Z*(221*$+31*B)*Q.cc1,Q.t3cof=Q.d2+2*b,Q.t4cof=.25*(3*Q.d3+Q.cc1*(12*Q.d2+10*b)),Q.t5cof=.2*(3*Q.d4+12*Q.cc1*Q.d3+6*Q.d2*Q.d2+15*b*(2*Q.d2+b)))}ae(Q,0),Q.init=`n`}function C(e,t=`i`){let n=e.NORAD_CAT_ID.toString(),r=new Date(e.EPOCH.endsWith(`Z`)?e.EPOCH:`${e.EPOCH}Z`),i=r.getUTCFullYear(),a=Number(i.toString().slice(-2)),o=(r.valueOf()-new Date(Date.UTC(i,0,1,0,0,0)).valueOf())/(86400*1e3)+1,c=Number(e.MEAN_MOTION_DOT),l=Number(e.MEAN_MOTION_DDOT);c/=ee*1440,l/=ee*1440*1440;let u=Number(e.BSTAR),d=Number(e.INCLINATION)*s,f=Number(e.RA_OF_ASC_NODE)*s,p=Number(e.ECCENTRICITY),m=Number(e.ARG_OF_PERICENTER)*s,h=Number(e.MEAN_ANOMALY)*s,ne=Number(e.MEAN_MOTION)/ee,{mon:_,day:v,hr:y,minute:b,sec:re}=te(i,o),ie=g(i,_,v,y,b,re),x={error:0,satnum:n,epochyr:a,epochdays:o,ndot:c,nddot:l,bstar:u,inclo:d,nodeo:f,ecco:p,argpo:m,mo:h,no:ne,jdsatepoch:ie};return S(x,{opsmode:t,satn:x.satnum,epoch:x.jdsatepoch-2433281.5,xbstar:x.bstar,xecco:x.ecco,xargpo:x.argpo,xinclo:x.inclo,xmo:x.mo,xno:x.no,xnodeo:x.nodeo}),x}3*Float64Array.BYTES_PER_ELEMENT;const w=Math.PI/180;Math.cos(i*w),Math.sin(i*w);function T(e){return new Date((e-2440587.5)*864e5).toISOString()}function E(e,t){let n=C({OBJECT_NAME:t??String(e.noradCatId),OBJECT_ID:String(e.noradCatId),EPOCH:T(e.epochJd),MEAN_MOTION:e.meanMotion,ECCENTRICITY:e.eccentricity,INCLINATION:e.inclination,RA_OF_ASC_NODE:e.raOfAscNode,ARG_OF_PERICENTER:e.argOfPericenter,MEAN_ANOMALY:e.meanAnomaly,EPHEMERIS_TYPE:0,CLASSIFICATION_TYPE:`U`,NORAD_CAT_ID:e.noradCatId,ELEMENT_SET_NO:e.elementSetNo,REV_AT_EPOCH:e.revAtEpoch,BSTAR:e.bstar,MEAN_MOTION_DOT:e.meanMotionDot,MEAN_MOTION_DDOT:e.meanMotionDdot});return n.error===x.None?n:(console.warn(`buildSatrec: SGP4 init failed for NORAD ${e.noradCatId} (error=${n.error})`),null)}const D=Math.PI/180,O=Math.cos(i*D),k=Math.sin(i*D),A=10/r;function j(e,t,n,r,i){return!isFinite(Math.fround(n))||!isFinite(Math.fround(r))||!isFinite(Math.fround(i))?!1:(e[t*3]=n,e[t*3+1]=r,e[t*3+2]=i,!0)}function oe(r,i,a,o,s,c,l,u,d,f=null,p=0){if(i<r.validityStart||i>r.validityEnd)return 0;let{count:m,kind:ee,equatorial:te,a:h,e:g,i:ne,om:_,w:v,ma:y,n:b,epoch:re,q:ie,tp:S,satrec:C,flags:w,visibleFromDays:T}=r,oe=p!==0&&r.applyFlagFilter,M=r.pickBase,N=d.length/3|0,se=i-2451545,P=0;for(let F=0;F<m&&!(P>=N);F++){let m=ee[F];if(m===0||T[F]>se||oe&&(w[F]&p)!==p)continue;if(m===3){let e=C[F];if(!e){if(e=E({noradCatId:r.satnum[F],epochJd:re[F],meanMotion:b[F]/360,eccentricity:g[F],inclination:ne[F],raOfAscNode:_[F],argOfPericenter:v[F],meanAnomaly:y[F],bstar:r.bstar[F],meanMotionDot:r.ndot[F],meanMotionDdot:r.nddot[F],elementSetNo:0,revAtEpoch:0}),!e){ee[F]=0;continue}C[F]=e}let t=(i-e.jdsatepoch)*1440,n=ae(e,t);if(!n||e.error!==x.None)continue;let p=n.position.x,m=n.position.y,te=n.position.z,h=p*A,ie=m*A,S=te*A,w=ie*O+S*k,T=-ie*k+S*O,D=h,oe=T,N=-w;if(!j(d,P,a+D-c,o+oe-l,s+N-u))continue;if(f){let e=M+F,t=P*4;f[t]=e&255,f[t+1]=e>>>8&255,f[t+2]=e>>>16&255,f[t+3]=e>>>24&255}P++;continue}let N,I,L=g[F],R=ne[F],ce=_[F],z=v[F];if(m===2){let e=n(ie[F],S[F],i);if(!e)continue;N=e.r*Math.cos(e.nu),I=e.r*Math.sin(e.nu)}else{let n=h[F];if(!isFinite(n)||!isFinite(L)||!isFinite(y[F])||!isFinite(b[F]))continue;let r=i-re[F],a=(y[F]+b[F]*r)*D,o,s;if(L<1||n>0){let t=Math.min(L,.9999999),r=e(a,t),i=Math.sqrt(1-t*t)*Math.sin(r)/(1-t*Math.cos(r)),c=(Math.cos(r)-t)/(1-t*Math.cos(r));o=Math.atan2(i,c),s=n*(1-t*Math.cos(r))}else{let e=t(a,L);if(!isFinite(e))continue;let r=L*Math.cosh(e)-1;if(Math.abs(r)<1e-15)continue;let i=Math.sqrt(L*L-1)*Math.sinh(e)/r,c=(L-Math.cosh(e))/r;o=Math.atan2(i,c),s=n*(1-L*Math.cosh(e))}N=s*Math.cos(o),I=s*Math.sin(o)}if(!isFinite(N)||!isFinite(I))continue;let B=Math.cos(z*D),V=Math.sin(z*D),H=Math.cos(R*D),U=Math.sin(R*D),W=Math.cos(ce*D),G=Math.sin(ce*D),K=(W*B-G*V*H)*N+(-W*V-G*B*H)*I,q=(G*B+W*V*H)*N+(-G*V+W*B*H)*I,J=V*U*N+B*U*I;if(te[F]){let e=q*O+J*k,t=-q*k+J*O;q=e,J=t}let le=K*10,Y=J*10,ue=-q*10;if(j(d,P,a+le-c,o+Y-l,s+ue-u)){if(f){let e=M+F,t=P*4;f[t]=e&255,f[t+1]=e>>>8&255,f[t+2]=e>>>16&255,f[t+3]=e>>>24&255}P++}}return P}const M=new Map;self.onmessage=e=>{let t=e.data;if(t.type===`ping`){self.postMessage({type:`pong`});return}if(t.type===`rewireDelta`){if(t.remove)for(let e of t.remove)M.delete(e);for(let e of t.set)M.set(e.id,e.cols);return}if(t.type===`tick`){let e=[],n=[],[r,i,a]=t.basis;for(let o of t.groups){let s=M.get(o.id);if(!s){e.push({id:o.id,count:0,buf:o.out.buffer,idbuf:o.outIds.buffer}),n.push(o.out.buffer,o.outIds.buffer);continue}let c=oe(s,t.jd,o.parent[0],o.parent[1],o.parent[2],r,i,a,o.out,o.outIds,t.requiredFlags??0);e.push({id:o.id,count:c,buf:o.out.buffer,idbuf:o.outIds.buffer}),n.push(o.out.buffer,o.outIds.buffer)}self.postMessage({type:`tickResult`,groups:e},n);return}};";
|
|
21874
|
+
var jsContent = "function e(e,t,n=1e-10,r=50){let i=e;for(let a=0;a<r;a++){let r=(i-t*Math.sin(i)-e)/(1-t*Math.cos(i));if(i-=Math.max(-1,Math.min(1,r)),Math.abs(r)<n)break}return i}function t(e,t,n=1e-10,r=50){if(e===0)return 0;let i=e<0?-1:1,a=Math.abs(e),o=0,s=1;for(;t*Math.sinh(s)-s<a;)if(s*=2,s>700)return NaN;let c=.5*(o+s);for(let e=0;e<r;e++){let e=t*Math.sinh(c)-c-a;e>0?s=c:o=c;let r=c-e/(t*Math.cosh(c)-1);r>o&&r<s||(r=.5*(o+s));let i=Math.abs(r-c);if(c=r,i<n)break}return i*c}function n(e,t,n){let r=.01720209895*(n-t)/(Math.sqrt(2)*e**1.5),i=Math.cbrt(3*r+Math.sqrt(1+9*r*r)),a=i-1/i,o=2*Math.atan(a),s=e*(1+a*a);return!isFinite(o)||!isFinite(s)||s<=0?null:{nu:o,r:s}}const r=149597870.7,i=23.4392911;86400**2/r**3,1/r,Math.cos(Math.PI/180*i),Math.sin(Math.PI/180*i);const a=Math.PI,o=a*2,s=a/180;180/a;const c=6378.135,l=60/Math.sqrt(c*c*c/398600.8),u=c*l/60,d=1/l,f=.001082616,p=-253881e-11/f,m=2/3,ee=1440/(2*a);function te(e,t){let n=[31,e%4==0?29:28,31,30,31,30,31,31,30,31,30,31],r=Math.floor(t),i=1,a=0;for(;r>a+n[i-1]&&i<12;)a+=n[i-1],i+=1;let o=i,s=r-a,c=(t-r)*24,l=Math.floor(c);c=(c-l)*60;let u=Math.floor(c);return{mon:o,day:s,hr:l,minute:u,sec:(c-u)*60}}function h(e,t,n,r,i,a,o=0){return 367*e-Math.floor(7*(e+Math.floor((t+9)/12))*.25)+Math.floor(275*t/9)+n+1721013.5+((o/6e4+a/60+i)/60+r)/24}function g(e,t,n,r,i,a,o=0){if(e instanceof Date){let t=e;return h(t.getUTCFullYear(),t.getUTCMonth()+1,t.getUTCDate(),t.getUTCHours(),t.getUTCMinutes(),t.getUTCSeconds(),t.getUTCMilliseconds())}return h(e,t,n,r,i,a,o)}function ne(e,t){let{e3:n,ee2:r,peo:i,pgho:s,pho:c,pinco:l,plo:u,se2:d,se3:f,sgh2:p,sgh3:m,sgh4:ee,sh2:te,sh3:h,si2:g,si3:ne,sl2:_,sl3:v,sl4:y,t:b,xgh2:re,xgh3:ie,xgh4:x,xh2:ae,xh3:S,xi2:C,xi3:w,xl2:T,xl3:E,xl4:D,zmol:O,zmos:k}=e,{init:A,opsmode:j}=t,{ep:oe,inclp:M,nodep:N,argpp:P,mp:se}=t,F,I,L,R,ce,z,B,V,H,U,W,G,K,q,J,Y,X,le,ue,de,fe;fe=k+119459e-10*b,A===`y`&&(fe=k),de=fe+2*.01675*Math.sin(fe),X=Math.sin(de),U=.5*X*X-.25,W=-.5*X*Math.cos(de);let pe=d*U+f*W,me=g*U+ne*W,he=_*U+v*W+y*X,ge=p*U+m*W+ee*X,Z=te*U+h*W;fe=O+.00015835218*b,A===`y`&&(fe=O),de=fe+2*.0549*Math.sin(fe),X=Math.sin(de),U=.5*X*X-.25,W=-.5*X*Math.cos(de);let _e=r*U+n*W,ve=C*U+w*W,ye=T*U+E*W+D*X,be=re*U+ie*W+x*X,xe=ae*U+S*W;return G=pe+_e,J=me+ve,Y=he+ye,K=ge+be,q=Z+xe,A===`n`&&(G-=i,J-=l,Y-=u,K-=s,q-=c,M+=J,oe+=G,R=Math.sin(M),L=Math.cos(M),M>=.2?(q/=R,K-=L*q,P+=K,N+=q,se+=Y):(z=Math.sin(N),ce=Math.cos(N),F=R*z,I=R*ce,B=q*ce+J*L*z,V=-q*z+J*L*ce,F+=B,I+=V,N%=o,N<0&&j===`a`&&(N+=o),le=se+P+L*N,H=Y+K-J*N*R,le+=H,ue=N,N=Math.atan2(F,I),N<0&&j===`a`&&(N+=o),Math.abs(ue-N)>a&&(N<ue?N+=o:N-=o),se+=Y,P=le-se-L*N)),{ep:oe,inclp:M,nodep:N,argpp:P,mp:se}}function _(e){let{epoch:t,ep:n,argpp:r,tc:i,inclp:a,nodep:s,np:c}=e,l,u,d,f,p,m,ee,te,h,g,ne,_,v,y,b,re,ie,x,ae,S,C,w,T,E,D,O,k,A,j,oe,M,N,P,se,F,I,L,R,ce,z,B,V,H,U,W,G,K,q,J,Y,X,le,ue,de,fe,pe,me,he,ge,Z,_e,ve,ye,be=.01675,xe=.0549,Se=c,Ce=n,we=Math.sin(s),Te=Math.cos(s),Ee=Math.sin(r),Q=Math.cos(r),De=Math.sin(a),Oe=Math.cos(a),$=Ce*Ce,ke=1-$,Ae=Math.sqrt(ke),je=t+18261.5+i/1440,Me=(4.523602-.00092422029*je)%o,Ne=Math.sin(Me),Pe=Math.cos(Me),Fe=.91375164-.03568096*Pe,Ie=Math.sqrt(1-Fe*Fe),Le=.089683511*Ne/Ie,Re=Math.sqrt(1-Le*Le),ze=5.8351514+.001944368*je,Be=.39785416*Ne/Ie,Ve=Re*Pe+.91744867*Le*Ne;Be=Math.atan2(Be,Ve),Be+=ze-Me;let He=Math.cos(Be),Ue=Math.sin(Be);S=.1945905,C=-.98088458,E=.91744867,D=.39785416,w=Te,T=we,ne=29864797e-13;let We=1/Se,Ge=0;for(;Ge<2;)Ge+=1,l=S*w+C*E*T,d=-C*w+S*E*T,ee=-S*T+C*E*w,te=C*D,h=C*T+S*E*w,g=S*D,u=Oe*ee+De*te,f=Oe*h+De*g,p=-De*ee+Oe*te,m=-De*h+Oe*g,_=l*Q+u*Ee,v=d*Q+f*Ee,y=-l*Ee+u*Q,b=-d*Ee+f*Q,re=p*Ee,ie=m*Ee,x=p*Q,ae=m*Q,_e=12*_*_-3*y*y,ve=24*_*v-6*y*b,ye=12*v*v-3*b*b,le=3*(l*l+u*u)+_e*$,ue=6*(l*d+u*f)+ve*$,de=3*(d*d+f*f)+ye*$,fe=-6*l*p+$*(-24*_*x-6*y*re),pe=-6*(l*m+d*p)+$*(-24*(v*x+_*ae)+-6*(y*ie+b*re)),me=-6*d*m+$*(-24*v*ae-6*b*ie),he=6*u*p+$*(24*_*re-6*y*x),ge=6*(f*p+u*m)+$*(24*(v*re+_*ie)-6*(b*x+y*ae)),Z=6*f*m+$*(24*v*ie-6*b*ae),le=le+le+ke*_e,ue=ue+ue+ke*ve,de=de+de+ke*ye,K=ne*We,G=-.5*K/Ae,q=K*Ae,W=-15*Ce*q,J=_*y+v*b,Y=v*y+_*b,X=v*b-_*y,Ge===1&&(O=W,k=G,A=K,j=q,oe=J,M=Y,N=X,P=le,se=ue,F=de,I=fe,L=pe,R=me,ce=he,z=ge,B=Z,V=_e,H=ve,U=ye,S=He,C=Ue,E=Fe,D=Ie,w=Re*Te+Le*we,T=we*Re-Te*Le,ne=4.7968065e-7);let Ke=(4.7199672+(.2299715*je-ze))%o,qe=(6.2565837+.017201977*je)%o,Je=2*O*M,Ye=2*O*N,Xe=2*k*L,Ze=2*k*(R-I),Qe=-2*A*se,$e=-2*A*(F-P),et=-2*A*(-21-9*$)*be,tt=2*j*H,nt=2*j*(U-V),rt=-18*j*be,it=-2*k*z,at=-2*k*(B-ce),ot=2*W*Y,st=2*W*X,ct=2*G*pe,lt=2*G*(me-fe),ut=-2*K*ue,dt=-2*K*(de-le),ft=-2*K*(-21-9*$)*xe,pt=2*q*ve,mt=2*q*(ye-_e),ht=-18*q*xe,gt=-2*G*ge,_t=-2*G*(Z-he);return{snodm:we,cnodm:Te,sinim:De,cosim:Oe,sinomm:Ee,cosomm:Q,day:je,e3:st,ee2:ot,em:Ce,emsq:$,gam:ze,peo:0,pgho:0,pho:0,pinco:0,plo:0,rtemsq:Ae,se2:Je,se3:Ye,sgh2:tt,sgh3:nt,sgh4:rt,sh2:it,sh3:at,si2:Xe,si3:Ze,sl2:Qe,sl3:$e,sl4:et,s1:W,s2:G,s3:K,s4:q,s5:J,s6:Y,s7:X,ss1:O,ss2:k,ss3:A,ss4:j,ss5:oe,ss6:M,ss7:N,sz1:P,sz2:se,sz3:F,sz11:I,sz12:L,sz13:R,sz21:ce,sz22:z,sz23:B,sz31:V,sz32:H,sz33:U,xgh2:pt,xgh3:mt,xgh4:ht,xh2:gt,xh3:_t,xi2:ct,xi3:lt,xl2:ut,xl3:dt,xl4:ft,nm:Se,z1:le,z2:ue,z3:de,z11:fe,z12:pe,z13:me,z21:he,z22:ge,z23:Z,z31:_e,z32:ve,z33:ye,zmol:Ke,zmos:qe}}function v(e){let{cosim:t,argpo:n,s1:r,s2:i,s3:s,s4:c,s5:u,sinim:d,ss1:f,ss2:p,ss3:ee,ss4:te,ss5:h,sz1:g,sz3:ne,sz11:_,sz13:v,sz21:y,sz23:b,sz31:re,sz33:ie,t:x,tc:ae,gsto:S,mo:C,mdot:w,no:T,nodeo:E,nodedot:D,xpidot:O,z1:k,z3:A,z11:j,z13:oe,z21:M,z23:N,z31:P,z33:se,ecco:F,eccsq:I}=e,{emsq:L,em:R,argpm:ce,inclm:z,mm:B,nm:V,nodem:H,irez:U,atime:W,d2201:G,d2211:K,d3210:q,d3222:J,d4410:Y,d4422:X,d5220:le,d5232:ue,d5421:de,d5433:fe,dedt:pe,didt:me,dmdt:he,dnodt:ge,domdt:Z,del1:_e,del2:ve,del3:ye,xfact:be,xlamo:xe,xli:Se,xni:Ce}=e,we,Te,Ee,Q,De,Oe,$,ke,Ae,je,Me,Ne,Pe,Fe,Ie,Le,Re,ze,Be,Ve,He,Ue,We,Ge,Ke,qe,Je,Ye,Xe,Ze,Qe,$e,et=.0043752690880113,tt=.00015835218,nt=119459e-10;U=0,V<.0052359877&&V>.0034906585&&(U=1),V>=.00826&&V<=.00924&&R>=.5&&(U=2);let rt=f*nt*h,it=p*nt*(_+v),at=-nt*ee*(g+ne-14-6*L),ot=te*nt*(re+ie-6),st=-nt*p*(y+b);(z<.052359877||z>a-.052359877)&&(st=0),d!==0&&(st/=d);let ct=ot-t*st;pe=rt+r*tt*u,me=it+i*tt*(j+oe),he=at-tt*s*(k+A-14-6*L);let lt=c*tt*(P+se-6),ut=-tt*i*(M+N);(z<.052359877||z>a-.052359877)&&(ut=0),Z=ct+lt,ge=st,d!==0&&(Z-=t/d*ut,ge+=ut/d);let dt=(S+ae*et)%o;if(R+=pe*x,z+=me*x,ce+=Z*x,H+=ge*x,B+=he*x,U!==0){if(Ze=(V/l)**m,U===2){Qe=t*t;let e=R;R=F;let n=L;L=I,$e=R*L,Fe=-.306-(R-.64)*.44,R<=.65?(Ie=3.616-13.247*R+16.29*L,Re=-19.302+117.39*R-228.419*L+156.591*$e,ze=-18.9068+109.7927*R-214.6334*L+146.5816*$e,Be=-41.122+242.694*R-471.094*L+313.953*$e,Ve=-146.407+841.88*R-1629.014*L+1083.435*$e,He=-532.114+3017.977*R-5740.032*L+3708.276*$e):(Ie=-72.099+331.819*R-508.738*L+266.724*$e,Re=-346.844+1582.851*R-2415.925*L+1246.113*$e,ze=-342.585+1554.908*R-2366.899*L+1215.972*$e,Be=-1052.797+4758.686*R-7193.992*L+3651.957*$e,Ve=-3581.69+16178.11*R-24462.77*L+12422.52*$e,He=R>.715?-5149.66+29936.92*R-54087.36*L+31324.56*$e:1464.74-4664.75*R+3763.64*L),R<.7?(Ge=-919.2277+4988.61*R-9064.77*L+5542.21*$e,Ue=-822.71072+4568.6173*R-8491.4146*L+5337.524*$e,We=-853.666+4690.25*R-8624.77*L+5341.4*$e):(Ge=-37995.78+161616.52*R-229838.2*L+109377.94*$e,Ue=-51752.104+218913.95*R-309468.16*L+146349.42*$e,We=-40023.88+170470.89*R-242699.48*L+115605.82*$e),Ke=d*d,we=.75*(1+2*t+Qe),Te=1.5*Ke,Q=1.875*d*(1-2*t-3*Qe),De=-1.875*d*(1+2*t-3*Qe),$=35*Ke*we,ke=39.375*Ke*Ke,Ae=9.84375*d*(Ke*(1-2*t-5*Qe)+.33333333*(-2+4*t+6*Qe)),je=d*(4.92187512*Ke*(-2-4*t+10*Qe)+6.56250012*(1+2*t-3*Qe)),Me=29.53125*d*(2-8*t+Qe*(-12+8*t+10*Qe)),Ne=29.53125*d*(-2-8*t+Qe*(12+8*t-10*Qe)),Ye=V*V,Xe=Ze*Ze,Je=3*Ye*Xe,qe=Je*17891679e-13,G=qe*we*Fe,K=qe*Te*Ie,Je*=Ze,qe=Je*3.7393792e-7,q=qe*Q*Re,J=qe*De*ze,Je*=Ze,qe=2*Je*7.3636953e-9,Y=qe*$*Be,X=qe*ke*Ve,Je*=Ze,qe=Je*1.1428639e-7,le=qe*Ae*He,ue=qe*je*We,qe=2*Je*2.1765803e-9,de=qe*Me*Ue,fe=qe*Ne*Ge,xe=(C+E+E-(dt+dt))%o,be=w+he+2*(D+ge-et)-T,R=e,L=n}U===1&&(Pe=1+L*(-2.5+.8125*L),Re=1+2*L,Le=1+L*(-6+6.60937*L),we=.75*(1+t)*(1+t),Ee=.9375*d*d*(1+3*t)-.75*(1+t),Oe=1+t,Oe*=1.875*Oe*Oe,_e=3*V*V*Ze*Ze,ve=2*_e*we*Pe*17891679e-13,ye=3*_e*Oe*Le*2.2123015e-7*Ze,_e=_e*Ee*Re*21460748e-13*Ze,xe=(C+E+n-dt)%o,be=w+O+he+Z+ge-(T+et)),Se=xe,Ce=T,W=0,V=T+0}return{em:R,argpm:ce,inclm:z,mm:B,nm:V,nodem:H,irez:U,atime:W,d2201:G,d2211:K,d3210:q,d3222:J,d4410:Y,d4422:X,d5220:le,d5232:ue,d5421:de,d5433:fe,dedt:pe,didt:me,dmdt:he,dndt:0,dnodt:ge,domdt:Z,del1:_e,del2:ve,del3:ye,xfact:be,xlamo:xe,xli:Se,xni:Ce}}function y(e){let t=(e-2451545)/36525,n=-62e-7*t*t*t+.093104*t*t+3164400184.812866*t+67310.54841;return n=n*s/240%o,n<0&&(n+=o),n}function b(e,t,n,r,i,a,o){return e instanceof Date?y(g(e)):y(t===void 0?e:g(e,t,n,r,i,a,o))}function re(e){let{ecco:t,epoch:n,inclo:r,opsmode:i}=e,{no:a}=e,s=t*t,c=1-s,u=Math.sqrt(c),d=Math.cos(r),p=d*d,ee=(l/a)**m,te=.75*f*(3*p-1)/(u*c),h=te/(ee*ee),g=ee*(1-h*h-h*(1/3+134*h*h/81));h=te/(g*g),a/=1+h;let ne=(l/a)**m,_=Math.sin(r),v=ne*c,y=1-5*p,re=-y-p-p,ie=1/ne,x=v*v,ae=ne*(1-t),S;if(i===`a`){let e=n-7305,t=Math.floor(e+1e-8),r=e-t,i=.017202791694070362,a=i+o;S=(1.7321343856509375+i*t+a*r+e*e*5075514194322695e-30)%o,S<0&&(S+=o)}else S=b(n+2433281.5);return{no:a,method:`n`,ainv:ie,ao:ne,con41:re,con42:y,cosio:d,cosio2:p,eccsq:s,omeosq:c,posq:x,rp:ae,rteosq:u,sinio:_,gsto:S}}function ie(e){let{irez:t,d2201:n,d2211:r,d3210:i,d3222:a,d4410:s,d4422:c,d5220:l,d5232:u,d5421:d,d5433:f,dedt:p,del1:m,del2:ee,del3:te,didt:h,dmdt:g,dnodt:ne,domdt:_,argpo:v,argpdot:y,t:b,tc:re,gsto:ie,xfact:x,xlamo:ae,no:S}=e,{atime:C,em:w,argpm:T,inclm:E,xli:D,mm:O,xni:k,nodem:A,nm:j}=e,oe=.13130908,M=2.8843198,N=.37448087,P=5.7686396,se=.95240898,F=1.8014998,I=1.050833,L=4.4108898,R=259200,ce,z,B,V,H,U,W,G,K=0,q=0,J=(ie+re*.0043752690880113)%o;if(w+=p*b,E+=h*b,T+=_*b,A+=ne*b,O+=g*b,t!==0){(C===0||b*C<=0||Math.abs(b)<Math.abs(C))&&(C=0,k=S,D=ae),ce=b>0?720:-720;let e=381;for(;e===381;)t===2?(G=v+y*C,B=G+G,z=D+D,W=n*Math.sin(B+D-P)+r*Math.sin(D-P)+i*Math.sin(G+D-se)+a*Math.sin(-G+D-se)+s*Math.sin(B+z-F)+c*Math.sin(z-F)+l*Math.sin(G+D-I)+u*Math.sin(-G+D-I)+d*Math.sin(G+z-L)+f*Math.sin(-G+z-L),H=k+x,U=n*Math.cos(B+D-P)+r*Math.cos(D-P)+i*Math.cos(G+D-se)+a*Math.cos(-G+D-se)+l*Math.cos(G+D-I)+u*Math.cos(-G+D-I)+2*(s*Math.cos(B+z-F)+c*Math.cos(z-F)+d*Math.cos(G+z-L)+f*Math.cos(-G+z-L)),U*=H):(W=m*Math.sin(D-oe)+ee*Math.sin(2*(D-M))+te*Math.sin(3*(D-N)),H=k+x,U=m*Math.cos(D-oe)+2*ee*Math.cos(2*(D-M))+3*te*Math.cos(3*(D-N)),U*=H),Math.abs(b-C)>=720?e=381:(q=b-C,e=0),e===381&&(D+=H*ce+W*R,k+=W*ce+U*R,C+=ce);j=k+W*q+U*q*q*.5,V=D+H*q+W*q*q*.5,t===1?(O=V-A-T+J,K=j-S):(O=V-2*A+2*J,K=j-S),j=S+K}return{atime:C,em:w,argpm:T,inclm:E,xli:D,mm:O,xni:k,nodem:A,dndt:K,nm:j}}var x;(function(e){e[e.None=0]=`None`,e[e.MeanEccentricityOutOfRange=1]=`MeanEccentricityOutOfRange`,e[e.MeanMotionBelowZero=2]=`MeanMotionBelowZero`,e[e.PerturbedEccentricityOutOfRange=3]=`PerturbedEccentricityOutOfRange`,e[e.SemiLatusRectumBelowZero=4]=`SemiLatusRectumBelowZero`,e[e.Decayed=6]=`Decayed`})(x||={});function ae(e,t){let n,r,i,s,d,ee,te,h,g,_,v,y,b,re,ae,S,C,w,T,E,D,O,k,A,j,oe,M;e.t=t,e.error=x.None;let N=e.mo+e.mdot*e.t,P=e.argpo+e.argpdot*e.t,se=e.nodeo+e.nodedot*e.t;g=P,D=N;let F=e.t*e.t;if(k=se+e.nodecf*F,C=1-e.cc1*e.t,w=e.bstar*e.cc4*e.t,T=e.t2cof*F,e.isimp!==1){te=e.omgcof*e.t;let t=1+e.eta*Math.cos(N);ee=e.xmcof*(t*t*t-e.delmo),S=te+ee,D=N+S,g=P-S,y=F*e.t,b=y*e.t,C=C-e.d2*F-e.d3*y-e.d4*b,w+=e.bstar*e.cc5*(Math.sin(D)-e.sinmao),T=T+e.t3cof*y+b*(e.t4cof+e.t*e.t5cof)}O=e.no;let I=e.ecco;if(E=e.inclo,e.method===`d`){re=e.t;let t=ie({irez:e.irez,d2201:e.d2201,d2211:e.d2211,d3210:e.d3210,d3222:e.d3222,d4410:e.d4410,d4422:e.d4422,d5220:e.d5220,d5232:e.d5232,d5421:e.d5421,d5433:e.d5433,dedt:e.dedt,del1:e.del1,del2:e.del2,del3:e.del3,didt:e.didt,dmdt:e.dmdt,dnodt:e.dnodt,domdt:e.domdt,argpo:e.argpo,argpdot:e.argpdot,t:e.t,tc:re,gsto:e.gsto,xfact:e.xfact,xlamo:e.xlamo,no:e.no,atime:e.atime,em:I,argpm:g,inclm:E,xli:e.xli,mm:D,xni:e.xni,nodem:k,nm:O});({em:I,argpm:g,inclm:E,mm:D,nodem:k,nm:O}=t)}if(O<=0)return e.error=x.MeanMotionBelowZero,null;let L=(l/O)**m*C*C;if(O=l/L**1.5,I-=w,I>=1||I<-.001)return e.error=x.MeanEccentricityOutOfRange,null;I<1e-6&&(I=1e-6),D+=e.no*T,j=D+g+k,k%=o,g%=o,j%=o,D=(j-g-k)%o;let R={am:L,em:I,im:E,Om:k,om:g,mm:D,nm:O},ce=Math.sin(E),z=Math.cos(E),B=I;if(A=E,_=g,M=k,oe=D,s=ce,i=z,e.method===`d`){let t=ne(e,{inclo:e.inclo,init:`n`,ep:B,inclp:A,nodep:M,argpp:_,mp:oe,opsmode:e.operationmode});if({ep:B,nodep:M,argpp:_,mp:oe}=t,A=t.inclp,A<0&&(A=-A,M+=a,_-=a),B<0||B>1)return e.error=x.PerturbedEccentricityOutOfRange,null}e.method===`d`&&(s=Math.sin(A),i=Math.cos(A),e.aycof=-.5*p*s,Math.abs(i+1)>15e-13?e.xlcof=-.25*p*s*(3+5*i)/(1+i):e.xlcof=-.25*p*s*(3+5*i)/15e-13);let V=B*Math.cos(_);S=1/(L*(1-B*B));let H=B*Math.sin(_)+S*e.aycof,U=(oe+_+M+S*e.xlcof*V-M)%o;h=U,ae=9999.9;let W=1;for(;Math.abs(ae)>=1e-12&&W<=10;)r=Math.sin(h),n=Math.cos(h),ae=1-n*V-r*H,ae=(U-H*n+V*r-h)/ae,Math.abs(ae)>=.95&&(ae=ae>0?.95:-.95),h+=ae,W+=1;let G=V*n+H*r,K=V*r-H*n,q=V*V+H*H,J=L*(1-q);if(J<0)return e.error=x.SemiLatusRectumBelowZero,null;let Y=L*(1-G),X=Math.sqrt(L)*K/Y,le=Math.sqrt(J)/Y,ue=Math.sqrt(1-q);S=K/(1+ue);let de=L/Y*(r-H-V*S),fe=L/Y*(n-V+H*S);v=Math.atan2(de,fe);let pe=(fe+fe)*de,me=1-2*de*de;S=1/J;let he=.5*f*S,ge=he*S;e.method===`d`&&(d=i*i,e.con41=3*d-1,e.x1mth2=1-d,e.x7thm1=7*d-1);let Z=Y*(1-1.5*ge*ue*e.con41)+.5*he*e.x1mth2*me;if(Z<1)return e.error=x.Decayed,null;v-=.25*ge*e.x7thm1*pe;let _e=M+1.5*ge*i*pe,ve=A+1.5*ge*i*s*me,ye=X-O*he*e.x1mth2*pe/l,be=le+O*he*(e.x1mth2*me+1.5*e.con41)/l,xe=Math.sin(v),Se=Math.cos(v),Ce=Math.sin(_e),we=Math.cos(_e),Te=Math.sin(ve),Ee=Math.cos(ve),Q=-Ce*Ee,De=we*Ee,Oe=Q*xe+we*Se,$=De*xe+Ce*Se,ke=Te*xe,Ae=Q*Se-we*xe,je=De*Se-Ce*xe,Me=Te*Se;return{position:{x:Z*Oe*c,y:Z*$*c,z:Z*ke*c},velocity:{x:(ye*Oe+be*Ae)*u,y:(ye*$+be*je)*u,z:(ye*ke+be*Me)*u},meanElements:R}}function S(e,t){let{opsmode:n,satn:r,epoch:i,xbstar:o,xecco:s,xargpo:l,xinclo:u,xmo:ee,xno:te,xnodeo:h}=t,g,y,b,ie,x,S,C,w,T,E,D,O,k,A,j,oe,M,N,P,se,F,I,L,R,ce,z,B,V,H,U,W,G,K,q,J,Y,X,le,ue,de,fe,pe,me,he,ge,Z,_e,ve,ye,be,xe,Se,Ce,we,Te,Ee,Q=e;Q.isimp=0,Q.method=`n`,Q.aycof=0,Q.con41=0,Q.cc1=0,Q.cc4=0,Q.cc5=0,Q.d2=0,Q.d3=0,Q.d4=0,Q.delmo=0,Q.eta=0,Q.argpdot=0,Q.omgcof=0,Q.sinmao=0,Q.t=0,Q.t2cof=0,Q.t3cof=0,Q.t4cof=0,Q.t5cof=0,Q.x1mth2=0,Q.x7thm1=0,Q.mdot=0,Q.nodedot=0,Q.xlcof=0,Q.xmcof=0,Q.nodecf=0,Q.irez=0,Q.d2201=0,Q.d2211=0,Q.d3210=0,Q.d3222=0,Q.d4410=0,Q.d4422=0,Q.d5220=0,Q.d5232=0,Q.d5421=0,Q.d5433=0,Q.dedt=0,Q.del1=0,Q.del2=0,Q.del3=0,Q.didt=0,Q.dmdt=0,Q.dnodt=0,Q.domdt=0,Q.e3=0,Q.ee2=0,Q.peo=0,Q.pgho=0,Q.pho=0,Q.pinco=0,Q.plo=0,Q.se2=0,Q.se3=0,Q.sgh2=0,Q.sgh3=0,Q.sgh4=0,Q.sh2=0,Q.sh3=0,Q.si2=0,Q.si3=0,Q.sl2=0,Q.sl3=0,Q.sl4=0,Q.gsto=0,Q.xfact=0,Q.xgh2=0,Q.xgh3=0,Q.xgh4=0,Q.xh2=0,Q.xh3=0,Q.xi2=0,Q.xi3=0,Q.xl2=0,Q.xl3=0,Q.xl4=0,Q.xlamo=0,Q.zmol=0,Q.zmos=0,Q.atime=0,Q.xli=0,Q.xni=0,Q.bstar=o,Q.ecco=s,Q.argpo=l,Q.inclo=u,Q.mo=ee,Q.no=te,Q.nodeo=h,Q.operationmode=n,78/c+1;let De=42/c;De*De*De*De,Q.init=`y`,Q.t=0;let Oe=re({satn:r,ecco:Q.ecco,epoch:i,inclo:Q.inclo,no:Q.no,method:Q.method,opsmode:Q.operationmode}),{ao:$,con42:ke,cosio:Ae,cosio2:je,eccsq:Me,omeosq:Ne,posq:Pe,rp:Fe,rteosq:Ie,sinio:Le}=Oe;if(Q.no=Oe.no,Q.con41=Oe.con41,Q.gsto=Oe.gsto,Q.a=(Q.no*d)**(-2/3),Q.alta=Q.a*(1+Q.ecco)-1,Q.altp=Q.a*(1-Q.ecco)-1,Q.error=0,Ne>=0||Q.no>=0){if(Q.isimp=0,Fe<1.034492841559484&&(Q.isimp=1),B=1.0122292801892716,F=1.880279159015271e-9,N=(Fe-1)*c,N<156){B=N-78,N<98&&(B=20);let e=(120-B)/c;F=e*e*e*e,B=B/c+1}P=1/Pe,Z=1/($-B),Q.eta=$*Q.ecco*Z,O=Q.eta*Q.eta,D=Q.ecco*Q.eta,se=Math.abs(1-O),S=F*Z**4,C=S/se**3.5,ie=C*Q.no*($*(1+1.5*O+D*(4+O))+.375*f*Z/se*Q.con41*(8+3*O*(8+O))),Q.cc1=Q.bstar*ie,x=0,Q.ecco>1e-4&&(x=-2*S*Z*p*Q.no*Le/Q.ecco),Q.x1mth2=1-je,Q.cc4=2*Q.no*C*$*Ne*(Q.eta*(2+.5*O)+Q.ecco*(.5+2*O)-f*Z/($*se)*(-3*Q.con41*(1-2*D+O*(1.5-.5*D))+.75*Q.x1mth2*(2*O-D*(1+O))*Math.cos(2*Q.argpo))),Q.cc5=2*C*$*Ne*(1+2.75*(O+D)+D*O),w=je*je,me=1.5*f*P*Q.no,he=.5*me*f*P,ge=-.46875*-165597e-11*P*P*Q.no,Q.mdot=Q.no+.5*me*Ie*Q.con41+.0625*he*Ie*(13-78*je+137*w),Q.argpdot=-.5*me*ke+.0625*he*(7-114*je+395*w)+ge*(3-36*je+49*w),ve=-me*Ae,Q.nodedot=ve+(.5*he*(4-19*je)+2*ge*(3-7*je))*Ae,_e=Q.argpdot+Q.nodedot,Q.omgcof=Q.bstar*x*Math.cos(Q.argpo),Q.xmcof=0,Q.ecco>1e-4&&(Q.xmcof=-m*S*Q.bstar/D),Q.nodecf=3.5*Ne*ve*Q.cc1,Q.t2cof=1.5*Q.cc1,Math.abs(Ae+1)>15e-13?Q.xlcof=-.25*p*Le*(3+5*Ae)/(1+Ae):Q.xlcof=-.25*p*Le*(3+5*Ae)/15e-13,Q.aycof=-.5*p*Le;let e=1+Q.eta*Math.cos(Q.mo);if(Q.delmo=e*e*e,Q.sinmao=Math.sin(Q.mo),Q.x7thm1=7*je-1,2*a/Q.no>=225){Q.method=`d`,Q.isimp=1,fe=0,j=Q.inclo;let e=_({epoch:i,ep:Q.ecco,argpp:Q.argpo,tc:fe,inclp:Q.inclo,nodep:Q.nodeo,np:Q.no,e3:Q.e3,ee2:Q.ee2,peo:Q.peo,pgho:Q.pgho,pho:Q.pho,pinco:Q.pinco,plo:Q.plo,se2:Q.se2,se3:Q.se3,sgh2:Q.sgh2,sgh3:Q.sgh3,sgh4:Q.sgh4,sh2:Q.sh2,sh3:Q.sh3,si2:Q.si2,si3:Q.si3,sl2:Q.sl2,sl3:Q.sl3,sl4:Q.sl4,xgh2:Q.xgh2,xgh3:Q.xgh3,xgh4:Q.xgh4,xh2:Q.xh2,xh3:Q.xh3,xi2:Q.xi2,xi3:Q.xi3,xl2:Q.xl2,xl3:Q.xl3,xl4:Q.xl4,zmol:Q.zmol,zmos:Q.zmos});Q.e3=e.e3,Q.ee2=e.ee2,Q.peo=e.peo,Q.pgho=e.pgho,Q.pho=e.pho,Q.pinco=e.pinco,Q.plo=e.plo,Q.se2=e.se2,Q.se3=e.se3,Q.sgh2=e.sgh2,Q.sgh3=e.sgh3,Q.sgh4=e.sgh4,Q.sh2=e.sh2,Q.sh3=e.sh3,Q.si2=e.si2,Q.si3=e.si3,Q.sl2=e.sl2,Q.sl3=e.sl3,Q.sl4=e.sl4,{sinim:y,cosim:g,em:T,emsq:E,s1:I,s2:L,s3:R,s4:ce,s5:z,ss1:V,ss2:H,ss3:U,ss4:W,ss5:G,sz1:K,sz3:q,sz11:J,sz13:Y,sz21:X,sz23:le,sz31:ue,sz33:de}=e,Q.xgh2=e.xgh2,Q.xgh3=e.xgh3,Q.xgh4=e.xgh4,Q.xh2=e.xh2,Q.xh3=e.xh3,Q.xi2=e.xi2,Q.xi3=e.xi3,Q.xl2=e.xl2,Q.xl3=e.xl3,Q.xl4=e.xl4,Q.zmol=e.zmol,Q.zmos=e.zmos,{nm:M,z1:ye,z3:be,z11:xe,z13:Se,z21:Ce,z23:we,z31:Te,z33:Ee}=e;let t=ne(Q,{inclo:j,init:Q.init,ep:Q.ecco,inclp:Q.inclo,nodep:Q.nodeo,argpp:Q.argpo,mp:Q.mo,opsmode:Q.operationmode});Q.ecco=t.ep,Q.inclo=t.inclp,Q.nodeo=t.nodep,Q.argpo=t.argpp,Q.mo=t.mp,k=0,A=0,oe=0;let n=v({cosim:g,emsq:E,argpo:Q.argpo,s1:I,s2:L,s3:R,s4:ce,s5:z,sinim:y,ss1:V,ss2:H,ss3:U,ss4:W,ss5:G,sz1:K,sz3:q,sz11:J,sz13:Y,sz21:X,sz23:le,sz31:ue,sz33:de,t:Q.t,tc:fe,gsto:Q.gsto,mo:Q.mo,mdot:Q.mdot,no:Q.no,nodeo:Q.nodeo,nodedot:Q.nodedot,xpidot:_e,z1:ye,z3:be,z11:xe,z13:Se,z21:Ce,z23:we,z31:Te,z33:Ee,ecco:Q.ecco,eccsq:Me,em:T,argpm:k,inclm:j,mm:oe,nm:M,nodem:A,irez:Q.irez,atime:Q.atime,d2201:Q.d2201,d2211:Q.d2211,d3210:Q.d3210,d3222:Q.d3222,d4410:Q.d4410,d4422:Q.d4422,d5220:Q.d5220,d5232:Q.d5232,d5421:Q.d5421,d5433:Q.d5433,dedt:Q.dedt,didt:Q.didt,dmdt:Q.dmdt,dnodt:Q.dnodt,domdt:Q.domdt,del1:Q.del1,del2:Q.del2,del3:Q.del3,xfact:Q.xfact,xlamo:Q.xlamo,xli:Q.xli,xni:Q.xni});Q.irez=n.irez,Q.atime=n.atime,Q.d2201=n.d2201,Q.d2211=n.d2211,Q.d3210=n.d3210,Q.d3222=n.d3222,Q.d4410=n.d4410,Q.d4422=n.d4422,Q.d5220=n.d5220,Q.d5232=n.d5232,Q.d5421=n.d5421,Q.d5433=n.d5433,Q.dedt=n.dedt,Q.didt=n.didt,Q.dmdt=n.dmdt,Q.dnodt=n.dnodt,Q.domdt=n.domdt,Q.del1=n.del1,Q.del2=n.del2,Q.del3=n.del3,Q.xfact=n.xfact,Q.xlamo=n.xlamo,Q.xli=n.xli,Q.xni=n.xni}Q.isimp!==1&&(b=Q.cc1*Q.cc1,Q.d2=4*$*Z*b,pe=Q.d2*Z*Q.cc1/3,Q.d3=(17*$+B)*pe,Q.d4=.5*pe*$*Z*(221*$+31*B)*Q.cc1,Q.t3cof=Q.d2+2*b,Q.t4cof=.25*(3*Q.d3+Q.cc1*(12*Q.d2+10*b)),Q.t5cof=.2*(3*Q.d4+12*Q.cc1*Q.d3+6*Q.d2*Q.d2+15*b*(2*Q.d2+b)))}ae(Q,0),Q.init=`n`}function C(e,t=`i`){let n=e.NORAD_CAT_ID.toString(),r=new Date(e.EPOCH.endsWith(`Z`)?e.EPOCH:`${e.EPOCH}Z`),i=r.getUTCFullYear(),a=Number(i.toString().slice(-2)),o=(r.valueOf()-new Date(Date.UTC(i,0,1,0,0,0)).valueOf())/(86400*1e3)+1,c=Number(e.MEAN_MOTION_DOT),l=Number(e.MEAN_MOTION_DDOT);c/=ee*1440,l/=ee*1440*1440;let u=Number(e.BSTAR),d=Number(e.INCLINATION)*s,f=Number(e.RA_OF_ASC_NODE)*s,p=Number(e.ECCENTRICITY),m=Number(e.ARG_OF_PERICENTER)*s,h=Number(e.MEAN_ANOMALY)*s,ne=Number(e.MEAN_MOTION)/ee,{mon:_,day:v,hr:y,minute:b,sec:re}=te(i,o),ie=g(i,_,v,y,b,re),x={error:0,satnum:n,epochyr:a,epochdays:o,ndot:c,nddot:l,bstar:u,inclo:d,nodeo:f,ecco:p,argpo:m,mo:h,no:ne,jdsatepoch:ie};return S(x,{opsmode:t,satn:x.satnum,epoch:x.jdsatepoch-2433281.5,xbstar:x.bstar,xecco:x.ecco,xargpo:x.argpo,xinclo:x.inclo,xmo:x.mo,xno:x.no,xnodeo:x.nodeo}),x}3*Float64Array.BYTES_PER_ELEMENT;const w=2451545,T=86400,E=[[2441317.5,10],[2441499.5,11],[2441683.5,12],[2442048.5,13],[2442413.5,14],[2442778.5,15],[2443144.5,16],[2443509.5,17],[2443874.5,18],[2444239.5,19],[2444786.5,20],[2445151.5,21],[2445516.5,22],[2446247.5,23],[2447161.5,24],[2447892.5,25],[2448257.5,26],[2448804.5,27],[2449169.5,28],[2449534.5,29],[2450083.5,30],[2450630.5,31],[2451179.5,32],[2453736.5,33],[2454832.5,34],[2456109.5,35],[2457204.5,36],[2457754.5,37]];function D(e){for(let t=E.length-1;t>=0;t--)if(e>=E[t][0])return E[t][1];return E[0][1]-1}function O(e){let t=6.239996+1.99096871e-7*(e-w)*T;return .001657*Math.sin(t+.01671*Math.sin(t))}function k(e){if(!Number.isFinite(e))return e;let t=e+(D(e)+32.184)/T;return t+O(t)/T}const A=Math.PI/180,j=A/3600,oe=1e-4*j,M=[[0,0,0,0,1,-171996,-174.2,92025,8.9],[0,0,2,-2,2,-13187,-1.6,5736,-3.1],[0,0,2,0,2,-2274,-.2,977,-.5],[0,0,0,0,2,2062,.2,-895,.5],[0,1,0,0,0,1426,-3.4,54,-.1],[1,0,0,0,0,712,.1,-7,0],[0,1,2,-2,2,-517,1.2,224,-.6],[0,0,2,0,1,-386,-.4,200,0],[1,0,2,0,2,-301,0,129,-.1],[0,-1,2,-2,2,217,-.5,-95,.3],[1,0,0,-2,0,-158,0,-1,0],[0,0,2,-2,1,129,.1,-70,0],[-1,0,2,0,2,123,0,-53,0],[1,0,0,0,1,63,.1,-33,0],[0,0,0,2,0,63,0,-2,0],[-1,0,2,2,2,-59,0,26,0],[-1,0,0,0,1,-58,-.1,32,0],[1,0,2,0,1,-51,0,27,0]];function N(e,t){let n=Array(9);for(let r=0;r<3;r++)for(let i=0;i<3;i++)n[3*r+i]=e[3*r]*t[i]+e[3*r+1]*t[3+i]+e[3*r+2]*t[6+i];return n}function P(e){let t=Math.cos(e),n=Math.sin(e);return[1,0,0,0,t,n,0,-n,t]}function se(e){let t=Math.cos(e),n=Math.sin(e);return[t,0,-n,0,1,0,n,0,t]}function F(e){let t=Math.cos(e),n=Math.sin(e);return[t,n,0,-n,t,0,0,0,1]}function I(e){let t=(e-w)/36525,n=(2306.2181*t+.30188*t*t+.017998*t**3)*j,r=(2004.3109*t-.42665*t*t-.041833*t**3)*j,a=(2306.2181*t+1.09468*t*t+.018203*t**3)*j,o=134.96298139+477198.8673981*t+.0086972*t*t,s=357.52772333+35999.05034*t-1603e-7*t*t,c=93.27191028+483202.0175381*t-.0036825*t*t,l=297.85036306+445267.11148*t-.0019142*t*t,u=125.04452222-1934.1362608*t+.0020708*t*t,d=0,f=0;for(let[e,n,r,i,a,p,m,ee,te]of M){let h=(e*o+n*s+r*c+i*l+a*u)*A;d+=(p+m*t)*Math.sin(h),f+=(ee+te*t)*Math.cos(h)}d*=oe,f*=oe;let p=(84381.448-46.815*t-59e-5*t*t+.001813*t**3)*j,m=d*Math.cos(p),ee=N(N(N(N(F(n),se(-r)),F(a)),N(N(P(-p),F(d)),P(p+f))),F(-m));return N(P(i*A),ee)}let L=NaN,R=[1,0,0,0,1,0,0,0,1];function ce(e){return Math.abs(e-L)<=.01||(R=I(e),L=e),R}function z(e){return new Date((e-2440587.5)*864e5).toISOString()}function B(e,t){let n=C({OBJECT_NAME:t??String(e.noradCatId),OBJECT_ID:String(e.noradCatId),EPOCH:z(e.epochJd),MEAN_MOTION:e.meanMotion,ECCENTRICITY:e.eccentricity,INCLINATION:e.inclination,RA_OF_ASC_NODE:e.raOfAscNode,ARG_OF_PERICENTER:e.argOfPericenter,MEAN_ANOMALY:e.meanAnomaly,EPHEMERIS_TYPE:0,CLASSIFICATION_TYPE:`U`,NORAD_CAT_ID:e.noradCatId,ELEMENT_SET_NO:e.elementSetNo,REV_AT_EPOCH:e.revAtEpoch,BSTAR:e.bstar,MEAN_MOTION_DOT:e.meanMotionDot,MEAN_MOTION_DDOT:e.meanMotionDdot});return n.error===x.None?n:(console.warn(`buildSatrec: SGP4 init failed for NORAD ${e.noradCatId} (error=${n.error})`),null)}const V=Math.PI/180;Math.cos(i*V),Math.sin(i*V);const H=Math.PI/180,U=Math.cos(i*H),W=Math.sin(i*H),G=10/r;function K(e,t,n,r,i){return!isFinite(Math.fround(n))||!isFinite(Math.fround(r))||!isFinite(Math.fround(i))?!1:(e[t*3]=n,e[t*3+1]=r,e[t*3+2]=i,!0)}function q(r,i,a,o,s,c,l,u,d,f=null,p=0){if(i<r.validityStart||i>r.validityEnd)return 0;let{count:m,kind:ee,equatorial:te,a:h,e:g,i:ne,om:_,w:v,ma:y,n:b,epoch:re,q:ie,tp:S,satrec:C,flags:T,visibleFromDays:E}=r,D=p!==0&&r.applyFlagFilter,O=r.pickBase,A=d.length/3|0,j=i-w,oe=k(i),M=ce(i),N=0;for(let w=0;w<m&&!(N>=A);w++){let m=ee[w];if(m===0||E[w]>j||D&&(T[w]&p)!==p)continue;if(m===3){let e=C[w];if(!e){if(e=B({noradCatId:r.satnum[w],epochJd:re[w],meanMotion:b[w]/360,eccentricity:g[w],inclination:ne[w],raOfAscNode:_[w],argOfPericenter:v[w],meanAnomaly:y[w],bstar:r.bstar[w],meanMotionDot:r.ndot[w],meanMotionDdot:r.nddot[w],elementSetNo:0,revAtEpoch:0}),!e){ee[w]=0;continue}C[w]=e}let t=(i-e.jdsatepoch)*1440,n=ae(e,t);if(!n||e.error!==x.None)continue;let p=n.position.x*G,m=n.position.y*G,te=n.position.z*G,h=M[0]*p+M[1]*m+M[2]*te,ie=M[3]*p+M[4]*m+M[5]*te,S=M[6]*p+M[7]*m+M[8]*te,T=-ie;if(!K(d,N,a+h-c,o+S-l,s+T-u))continue;if(f){let e=O+w,t=N*4;f[t]=e&255,f[t+1]=e>>>8&255,f[t+2]=e>>>16&255,f[t+3]=e>>>24&255}N++;continue}let k,A,P=g[w],se=ne[w],F=_[w],I=v[w];if(m===2){let e=n(ie[w],S[w],te[w]?i:oe);if(!e)continue;k=e.r*Math.cos(e.nu),A=e.r*Math.sin(e.nu)}else{let n=h[w];if(!isFinite(n)||!isFinite(P)||!isFinite(y[w])||!isFinite(b[w]))continue;let r=(te[w]?i:oe)-re[w],a=(y[w]+b[w]*r)*H,o,s;if(P<1||n>0){let t=Math.min(P,.9999999),r=e(a,t),i=Math.sqrt(1-t*t)*Math.sin(r)/(1-t*Math.cos(r)),c=(Math.cos(r)-t)/(1-t*Math.cos(r));o=Math.atan2(i,c),s=n*(1-t*Math.cos(r))}else{let e=t(a,P);if(!isFinite(e))continue;let r=P*Math.cosh(e)-1;if(Math.abs(r)<1e-15)continue;let i=Math.sqrt(P*P-1)*Math.sinh(e)/r,c=(P-Math.cosh(e))/r;o=Math.atan2(i,c),s=n*(1-P*Math.cosh(e))}k=s*Math.cos(o),A=s*Math.sin(o)}if(!isFinite(k)||!isFinite(A))continue;let L=Math.cos(I*H),R=Math.sin(I*H),ce=Math.cos(se*H),z=Math.sin(se*H),V=Math.cos(F*H),q=Math.sin(F*H),J=(V*L-q*R*ce)*k+(-V*R-q*L*ce)*A,Y=(q*L+V*R*ce)*k+(-q*R+V*L*ce)*A,X=R*z*k+L*z*A;if(te[w]){let e=Y*U+X*W,t=-Y*W+X*U;Y=e,X=t}let le=J*10,ue=X*10,de=-Y*10;if(K(d,N,a+le-c,o+ue-l,s+de-u)){if(f){let e=O+w,t=N*4;f[t]=e&255,f[t+1]=e>>>8&255,f[t+2]=e>>>16&255,f[t+3]=e>>>24&255}N++}}return N}const J=new Map;self.onmessage=e=>{let t=e.data;if(t.type===`ping`){self.postMessage({type:`pong`});return}if(t.type===`rewireDelta`){if(t.remove)for(let e of t.remove)J.delete(e);for(let e of t.set)J.set(e.id,e.cols);return}if(t.type===`tick`){let e=[],n=[],[r,i,a]=t.basis;for(let o of t.groups){let s=J.get(o.id);if(!s){e.push({id:o.id,count:0,buf:o.out.buffer,idbuf:o.outIds.buffer}),n.push(o.out.buffer,o.outIds.buffer);continue}let c=q(s,t.jd,o.parent[0],o.parent[1],o.parent[2],r,i,a,o.out,o.outIds,t.requiredFlags??0);e.push({id:o.id,count:c,buf:o.out.buffer,idbuf:o.outIds.buffer}),n.push(o.out.buffer,o.outIds.buffer)}self.postMessage({type:`tickResult`,groups:e},n);return}};";
|
|
20769
21875
|
var blob = typeof self !== "undefined" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", jsContent], { type: "text/javascript;charset=utf-8" });
|
|
20770
21876
|
function WorkerWrapper(options) {
|
|
20771
21877
|
let objURL;
|
|
@@ -22247,8 +23353,8 @@ function between(points, jds, jd, from = 0, to = points.length) {
|
|
|
22247
23353
|
//#endregion
|
|
22248
23354
|
//#region src/lib/math/travel/state.ts
|
|
22249
23355
|
var DEG2RAD$1 = Math.PI / 180;
|
|
22250
|
-
var COS_EPS
|
|
22251
|
-
var SIN_EPS
|
|
23356
|
+
var COS_EPS = Math.cos(EARTH_OBLIQUITY_DEG * DEG2RAD$1);
|
|
23357
|
+
var SIN_EPS = Math.sin(EARTH_OBLIQUITY_DEG * DEG2RAD$1);
|
|
22252
23358
|
function planeRotation(w, i, om, equatorial) {
|
|
22253
23359
|
const cosW = Math.cos(w * DEG2RAD$1);
|
|
22254
23360
|
const sinW = Math.sin(w * DEG2RAD$1);
|
|
@@ -22271,8 +23377,8 @@ function perifocalToEcliptic(px, py, rot) {
|
|
|
22271
23377
|
let y = rot.m21 * px + rot.m22 * py;
|
|
22272
23378
|
let z = rot.m31 * px + rot.m32 * py;
|
|
22273
23379
|
if (rot.equatorial) {
|
|
22274
|
-
const yEcl = y * COS_EPS
|
|
22275
|
-
const zEcl = -y * SIN_EPS
|
|
23380
|
+
const yEcl = y * COS_EPS + z * SIN_EPS;
|
|
23381
|
+
const zEcl = -y * SIN_EPS + z * COS_EPS;
|
|
22276
23382
|
y = yEcl;
|
|
22277
23383
|
z = zEcl;
|
|
22278
23384
|
}
|
|
@@ -22292,11 +23398,12 @@ function eclipticToScene(r) {
|
|
|
22292
23398
|
}
|
|
22293
23399
|
function elementsToState(el, jd, muKm3S2) {
|
|
22294
23400
|
const { a, e, ma, n, epoch, q, tp } = el;
|
|
23401
|
+
const t = elementsJd(el, jd);
|
|
22295
23402
|
const { om, w } = propagateOrbitAngles(el, jd);
|
|
22296
23403
|
const equatorial = el.equatorial ?? false;
|
|
22297
23404
|
if (!isFinite(a) || a === 0 || !isFinite(n) || n <= 0) {
|
|
22298
23405
|
if (q == null || tp == null || !isFinite(q) || !isFinite(tp) || q <= 0) return null;
|
|
22299
|
-
const solved = solveBarker(q, tp,
|
|
23406
|
+
const solved = solveBarker(q, tp, t);
|
|
22300
23407
|
if (!solved) return null;
|
|
22301
23408
|
const mu = muKm3S2 && muKm3S2 > 0 ? muKm3S2 : GM_SUN_KM3_S2;
|
|
22302
23409
|
const rKm = solved.r * AU_KM;
|
|
@@ -22308,7 +23415,7 @@ function elementsToState(el, jd, muKm3S2) {
|
|
|
22308
23415
|
const nRadPerSec = n * DEG2RAD$1 / SEC_PER_DAY$1;
|
|
22309
23416
|
const mu = muKm3S2 && muKm3S2 > 0 ? muKm3S2 : nRadPerSec * nRadPerSec * Math.abs(aKm) * Math.abs(aKm) * Math.abs(aKm);
|
|
22310
23417
|
if (!isFinite(mu) || mu <= 0) return null;
|
|
22311
|
-
const M = (ma + n * (
|
|
23418
|
+
const M = (ma + n * (t - epoch)) * DEG2RAD$1;
|
|
22312
23419
|
let nu;
|
|
22313
23420
|
let rKm;
|
|
22314
23421
|
if (e < 1 || a > 0) {
|
|
@@ -23328,13 +24435,17 @@ function classifyLagrange(geocentric, earthToSun, massRatio = EARTH_SUN_MASS_RAT
|
|
|
23328
24435
|
function existsAt(d, jd) {
|
|
23329
24436
|
return !(d.visibleFromDays !== void 0 && jd - 2451545 < d.visibleFromDays);
|
|
23330
24437
|
}
|
|
24438
|
+
function withinValidity(d, jd) {
|
|
24439
|
+
const t = elementsJd(d, jd);
|
|
24440
|
+
return t >= d.validityStart && t <= d.validityEnd;
|
|
24441
|
+
}
|
|
23331
24442
|
function sitsOnParent(d) {
|
|
23332
24443
|
return d.a === 0 && (d.objectType === ObjectType.BARYCENTER || d.objectType === ObjectType.LAGRANGE_POINT || isMajorBody(d.objectType));
|
|
23333
24444
|
}
|
|
23334
24445
|
function elementsOffset$1(d, jd) {
|
|
23335
24446
|
if (d.pageOnly) return "never";
|
|
23336
24447
|
if (!existsAt(d, jd)) return "not-yet";
|
|
23337
|
-
if (
|
|
24448
|
+
if (!withinValidity(d, jd)) return "no-data";
|
|
23338
24449
|
let offset;
|
|
23339
24450
|
const satrec = d.satrec;
|
|
23340
24451
|
if (satrec) offset = sgp4PositionScene(satrec, jd);
|
|
@@ -23817,11 +24928,82 @@ var PositionDiagnostics = class {
|
|
|
23817
24928
|
}
|
|
23818
24929
|
};
|
|
23819
24930
|
|
|
24931
|
+
//#endregion
|
|
24932
|
+
//#region src/lib/scene/shaders/planetshine-uniforms.ts
|
|
24933
|
+
var _shiners = [];
|
|
24934
|
+
var _albedos = /* @__PURE__ */ new WeakMap();
|
|
24935
|
+
function measuredShinerAlbedo(bo, map) {
|
|
24936
|
+
const { color, geometricAlbedo } = bo.body.data;
|
|
24937
|
+
let entry = _albedos.get(bo);
|
|
24938
|
+
if (!entry || entry.color !== color || entry.geometricAlbedo !== geometricAlbedo || entry.map !== map) {
|
|
24939
|
+
entry = {
|
|
24940
|
+
color,
|
|
24941
|
+
geometricAlbedo,
|
|
24942
|
+
map,
|
|
24943
|
+
albedo: shinerAlbedo(bo.body.data, map, new Color())
|
|
24944
|
+
};
|
|
24945
|
+
_albedos.set(bo, entry);
|
|
24946
|
+
}
|
|
24947
|
+
return entry.albedo;
|
|
24948
|
+
}
|
|
24949
|
+
function shineAlbedo(bo, material, out) {
|
|
24950
|
+
const measured = measuredShinerAlbedo(bo, material.map);
|
|
24951
|
+
if (measured) return out.copy(measured);
|
|
24952
|
+
out.copy(material.color);
|
|
24953
|
+
const mean = material.map && meanMapColor(material.map);
|
|
24954
|
+
return mean ? out.multiply(mean) : out;
|
|
24955
|
+
}
|
|
24956
|
+
function updatePlanetshineUniforms(bodyObjects, occluders, realistic, sunScale) {
|
|
24957
|
+
const sunPos = bodyObjects.get(SUN_ID)?.body.position;
|
|
24958
|
+
let n = 0;
|
|
24959
|
+
if (sunPos) for (const bo of occluders) {
|
|
24960
|
+
if (!bo.mesh) continue;
|
|
24961
|
+
const material = bo.mesh.material;
|
|
24962
|
+
const [x, y, z] = bo.body.position;
|
|
24963
|
+
const sx = sunPos[0] - x;
|
|
24964
|
+
const sy = sunPos[1] - y;
|
|
24965
|
+
const sz = sunPos[2] - z;
|
|
24966
|
+
const sunDist = Math.hypot(sx, sy, sz);
|
|
24967
|
+
const s = _shiners[n++] ??= {
|
|
24968
|
+
x: 0,
|
|
24969
|
+
y: 0,
|
|
24970
|
+
z: 0,
|
|
24971
|
+
radius: 0,
|
|
24972
|
+
sunX: 0,
|
|
24973
|
+
sunY: 0,
|
|
24974
|
+
sunZ: 0,
|
|
24975
|
+
sunlight: 0,
|
|
24976
|
+
albedo: new Color()
|
|
24977
|
+
};
|
|
24978
|
+
s.x = x;
|
|
24979
|
+
s.y = y;
|
|
24980
|
+
s.z = z;
|
|
24981
|
+
s.radius = bo.radiusScene;
|
|
24982
|
+
s.sunX = sx / sunDist;
|
|
24983
|
+
s.sunY = sy / sunDist;
|
|
24984
|
+
s.sunZ = sz / sunDist;
|
|
24985
|
+
s.sunlight = SUN_LIGHT_INTENSITY * sunScale * (realistic ? sunIrradianceFactor(sunDist) : 1);
|
|
24986
|
+
shineAlbedo(bo, material, s.albedo);
|
|
24987
|
+
}
|
|
24988
|
+
for (const bo of bodyObjects.values()) {
|
|
24989
|
+
const shine = bo.planetshine;
|
|
24990
|
+
const at = bo.body.position;
|
|
24991
|
+
if (!shine || !at) continue;
|
|
24992
|
+
if (bo.cachedDist > 0 && bo.radiusScene < bo.cachedDist * 1e-4) continue;
|
|
24993
|
+
selectShiners(shine, at[0], at[1], at[2], _shiners, n);
|
|
24994
|
+
}
|
|
24995
|
+
}
|
|
24996
|
+
|
|
23820
24997
|
//#endregion
|
|
23821
24998
|
//#region src/lib/scene/shaders/ring-uniforms.ts
|
|
23822
24999
|
var SUN_RADIUS_SCENE = kmToScene(695700);
|
|
23823
25000
|
var SHEETS_PER_PX = 2;
|
|
25001
|
+
var SIN_B_STEP = 1e-4;
|
|
25002
|
+
var RING_LIGHT_MIN_PX = 2;
|
|
23824
25003
|
var tmp = new Vector3();
|
|
25004
|
+
var _axis = new Vector3();
|
|
25005
|
+
var _sunLocal = new Vector3();
|
|
25006
|
+
var _inverse = new Quaternion();
|
|
23825
25007
|
function annulusView(camPos, center, poleDir, innerScene, outerScene) {
|
|
23826
25008
|
tmp.subVectors(camPos, center);
|
|
23827
25009
|
const axial = tmp.dot(poleDir);
|
|
@@ -23874,6 +25056,35 @@ function updateRingShaders(bodyObjects, focusTruePos, realistic, overexpose, cam
|
|
|
23874
25056
|
ps.uRingShadowPoleDir.value.copy(psOnRing.uPlanetPoleDir.value);
|
|
23875
25057
|
ps.uRingShadowCenter.value.copy(psOnRing.uPlanetCenter.value);
|
|
23876
25058
|
}
|
|
25059
|
+
updateRingLight(bo, camPos, pxPerRad);
|
|
25060
|
+
}
|
|
25061
|
+
}
|
|
25062
|
+
function updateRingLight(bo, camPos, pxPerRad) {
|
|
25063
|
+
const caster = bo.rings.reduce((best, ring) => ring.intensityScale > best.intensityScale ? ring : best);
|
|
25064
|
+
const uniforms = caster.material.uniforms;
|
|
25065
|
+
const sunDir = uniforms.uSunDir.value;
|
|
25066
|
+
const pole = caster.planetShadowOnRing.uPlanetPoleDir.value;
|
|
25067
|
+
const center = caster.planetShadowOnRing.uPlanetCenter.value;
|
|
25068
|
+
const sinB = Math.min(Math.max(sunDir.dot(pole), -1), 1);
|
|
25069
|
+
const light = caster.light;
|
|
25070
|
+
const seen = caster.outerScene / Math.max(camPos.distanceTo(center), 1e-12) * pxPerRad >= RING_LIGHT_MIN_PX;
|
|
25071
|
+
if (seen && !(Math.abs(sinB - light.patchesSinB) < SIN_B_STEP)) {
|
|
25072
|
+
ringshinePatches(light.patches, light.profile, sinB, light.planet);
|
|
25073
|
+
light.patchesSinB = sinB;
|
|
25074
|
+
}
|
|
25075
|
+
_axis.copy(sunDir).addScaledVector(pole, -sinB);
|
|
25076
|
+
if (_axis.lengthSq() < 1e-12) _axis.set(Math.abs(pole.x) < .9 ? 1 : 0, Math.abs(pole.x) < .9 ? 0 : 1, 0).cross(pole);
|
|
25077
|
+
_axis.normalize();
|
|
25078
|
+
if (caster.ringshine) writeRingshine(caster.ringshine, light, _axis, sinB, uniforms.uLightScale.value);
|
|
25079
|
+
_sunLocal.copy(_axis).applyQuaternion(_inverse.copy(caster.mesh.quaternion).invert());
|
|
25080
|
+
for (const ring of bo.rings) {
|
|
25081
|
+
if (!ring.mesh.visible) continue;
|
|
25082
|
+
if (seen && ring.light.planetLightSinB !== light.patchesSinB) fillPlanetLight(ring.light, light.patchesSinB, light);
|
|
25083
|
+
const ringUniforms = ring.material.uniforms;
|
|
25084
|
+
ringUniforms.uSunAzimuth.value.set(_sunLocal.x, _sunLocal.z).normalize();
|
|
25085
|
+
const albedo = ringUniforms.uPlanetAlbedo.value;
|
|
25086
|
+
if (bo.mesh) shineAlbedo(bo, bo.mesh.material, albedo);
|
|
25087
|
+
else albedo.setRGB(0, 0, 0);
|
|
23877
25088
|
}
|
|
23878
25089
|
}
|
|
23879
25090
|
|
|
@@ -23919,15 +25130,15 @@ function seasonalAtmosphereParams(base, lsDeg) {
|
|
|
23919
25130
|
seasonal: void 0
|
|
23920
25131
|
};
|
|
23921
25132
|
}
|
|
23922
|
-
var cache = /* @__PURE__ */ new WeakMap();
|
|
25133
|
+
var cache$1 = /* @__PURE__ */ new WeakMap();
|
|
23923
25134
|
var LS_QUANTUM_DEG = .25;
|
|
23924
25135
|
function seasonalParamsForJd(base, jd) {
|
|
23925
25136
|
if (!base.seasonal) return base;
|
|
23926
25137
|
const lsQ = Math.round(marsSolarLongitudeDeg(jd) / LS_QUANTUM_DEG);
|
|
23927
|
-
const hit = cache.get(base);
|
|
25138
|
+
const hit = cache$1.get(base);
|
|
23928
25139
|
if (hit && hit.lsQ === lsQ) return hit.params;
|
|
23929
25140
|
const params = seasonalAtmosphereParams(base, lsQ * LS_QUANTUM_DEG);
|
|
23930
|
-
cache.set(base, {
|
|
25141
|
+
cache$1.set(base, {
|
|
23931
25142
|
lsQ,
|
|
23932
25143
|
params
|
|
23933
25144
|
});
|
|
@@ -24073,6 +25284,7 @@ function updateAtmosphereShaders(bodyObjects, cameraPosition, visible, realistic
|
|
|
24073
25284
|
|
|
24074
25285
|
//#endregion
|
|
24075
25286
|
//#region src/lib/scene/shaders/eclipse-uniforms.ts
|
|
25287
|
+
var FOCUS = new Vector3();
|
|
24076
25288
|
function collectOccluders(bodyObjects, out) {
|
|
24077
25289
|
let n = 0;
|
|
24078
25290
|
for (const bo of bodyObjects.values()) {
|
|
@@ -24083,19 +25295,17 @@ function collectOccluders(bodyObjects, out) {
|
|
|
24083
25295
|
out[n++] = bo;
|
|
24084
25296
|
}
|
|
24085
25297
|
out.length = n;
|
|
24086
|
-
if (n > 32) {
|
|
24087
|
-
out.sort((a, b) => b.radiusScene - a.radiusScene);
|
|
24088
|
-
out.length = 32;
|
|
24089
|
-
}
|
|
24090
25298
|
return out;
|
|
24091
25299
|
}
|
|
24092
|
-
function updateEclipseUniforms(bodyObjects, occluders, focusTruePos, air) {
|
|
25300
|
+
function updateEclipseUniforms(bodyObjects, occluders, focusTruePos, cameraDistance, air) {
|
|
24093
25301
|
const eclipse = getEclipseSceneUniforms();
|
|
25302
|
+
const pool = getOccluderPool();
|
|
24094
25303
|
const sunBo = bodyObjects.get(SUN_ID);
|
|
24095
25304
|
const sunPos = sunBo?.body.position;
|
|
24096
25305
|
if (!sunBo || !sunPos) {
|
|
24097
25306
|
eclipse.uSunAngularRadius.value = 0;
|
|
24098
25307
|
eclipse.uOccluderCount.value = 0;
|
|
25308
|
+
pool.count = 0;
|
|
24099
25309
|
return;
|
|
24100
25310
|
}
|
|
24101
25311
|
const [fx, fy, fz] = focusTruePos;
|
|
@@ -24108,17 +25318,20 @@ function updateEclipseUniforms(bodyObjects, occluders, focusTruePos, air) {
|
|
|
24108
25318
|
eclipse.uSunAngularRadius.value = Math.asin(Math.min(sunBo.radiusScene / sunDist, 1));
|
|
24109
25319
|
} else eclipse.uSunAngularRadius.value = 0;
|
|
24110
25320
|
const n = occluders.length;
|
|
24111
|
-
|
|
24112
|
-
|
|
25321
|
+
while (pool.occluders.length < n) {
|
|
25322
|
+
pool.occluders.push(new Vector4());
|
|
25323
|
+
pool.leaks.push(new Vector4());
|
|
25324
|
+
}
|
|
24113
25325
|
for (let i = 0; i < n; i++) {
|
|
24114
25326
|
const bo = occluders[i];
|
|
24115
25327
|
const [bx, by, bz] = bo.body.position;
|
|
24116
|
-
|
|
24117
|
-
if (air && bo.atmosphere) atmosphereLeak(bo.atmosphere.params, bo.atmosphere.planetRadiusKm, leaks[i]);
|
|
24118
|
-
else leaks[i].set(0, 0, 0, 0);
|
|
25328
|
+
pool.occluders[i].set(bx - fx, by - fy, bz - fz, bo.radiusScene);
|
|
25329
|
+
if (air && bo.atmosphere) atmosphereLeak(bo.atmosphere.params, bo.atmosphere.planetRadiusKm, pool.leaks[i]);
|
|
25330
|
+
else pool.leaks[i].set(0, 0, 0, 0);
|
|
24119
25331
|
}
|
|
24120
|
-
|
|
25332
|
+
pool.count = n;
|
|
24121
25333
|
const sunDir = eclipse.uSunDir.value;
|
|
25334
|
+
eclipse.uOccluderCount.value = cullOccludersFor(eclipse.uOccluders.value, FOCUS, cameraDistance, sunDir, eclipse.uOccluderLeak.value);
|
|
24122
25335
|
for (const bo of bodyObjects.values()) {
|
|
24123
25336
|
const self = bo.eclipseShadow;
|
|
24124
25337
|
const at = bo.body.position;
|
|
@@ -24130,52 +25343,6 @@ function updateEclipseUniforms(bodyObjects, occluders, focusTruePos, air) {
|
|
|
24130
25343
|
}
|
|
24131
25344
|
}
|
|
24132
25345
|
|
|
24133
|
-
//#endregion
|
|
24134
|
-
//#region src/lib/scene/shaders/planetshine-uniforms.ts
|
|
24135
|
-
var _shiners = Array.from({ length: 32 }, () => ({
|
|
24136
|
-
x: 0,
|
|
24137
|
-
y: 0,
|
|
24138
|
-
z: 0,
|
|
24139
|
-
radius: 0,
|
|
24140
|
-
sunX: 0,
|
|
24141
|
-
sunY: 0,
|
|
24142
|
-
sunZ: 0,
|
|
24143
|
-
sunlight: 0,
|
|
24144
|
-
albedo: new Color()
|
|
24145
|
-
}));
|
|
24146
|
-
function updatePlanetshineUniforms(bodyObjects, occluders, realistic, sunScale) {
|
|
24147
|
-
const sunPos = bodyObjects.get(SUN_ID)?.body.position;
|
|
24148
|
-
let n = 0;
|
|
24149
|
-
if (sunPos) for (const bo of occluders) {
|
|
24150
|
-
if (!bo.mesh) continue;
|
|
24151
|
-
const material = bo.mesh.material;
|
|
24152
|
-
const [x, y, z] = bo.body.position;
|
|
24153
|
-
const sx = sunPos[0] - x;
|
|
24154
|
-
const sy = sunPos[1] - y;
|
|
24155
|
-
const sz = sunPos[2] - z;
|
|
24156
|
-
const sunDist = Math.hypot(sx, sy, sz);
|
|
24157
|
-
const s = _shiners[n++];
|
|
24158
|
-
s.x = x;
|
|
24159
|
-
s.y = y;
|
|
24160
|
-
s.z = z;
|
|
24161
|
-
s.radius = bo.radiusScene;
|
|
24162
|
-
s.sunX = sx / sunDist;
|
|
24163
|
-
s.sunY = sy / sunDist;
|
|
24164
|
-
s.sunZ = sz / sunDist;
|
|
24165
|
-
s.sunlight = SUN_LIGHT_INTENSITY * sunScale * (realistic ? sunIrradianceFactor(sunDist) : 1);
|
|
24166
|
-
s.albedo.copy(material.color);
|
|
24167
|
-
const mean = material.map && meanMapColor(material.map);
|
|
24168
|
-
if (mean) s.albedo.multiply(mean);
|
|
24169
|
-
}
|
|
24170
|
-
for (const bo of bodyObjects.values()) {
|
|
24171
|
-
const shine = bo.planetshine;
|
|
24172
|
-
const at = bo.body.position;
|
|
24173
|
-
if (!shine || !at) continue;
|
|
24174
|
-
if (bo.cachedDist > 0 && bo.radiusScene < bo.cachedDist * 1e-4) continue;
|
|
24175
|
-
selectShiners(shine, at[0], at[1], at[2], _shiners, n);
|
|
24176
|
-
}
|
|
24177
|
-
}
|
|
24178
|
-
|
|
24179
25346
|
//#endregion
|
|
24180
25347
|
//#region src/lib/scene/shaders/sun-shadow-light.ts
|
|
24181
25348
|
var LIGHT_DIST = 10;
|
|
@@ -24414,6 +25581,10 @@ function gridGeometry(grid) {
|
|
|
24414
25581
|
return geometry;
|
|
24415
25582
|
}
|
|
24416
25583
|
var tiledStates = /* @__PURE__ */ new WeakMap();
|
|
25584
|
+
var deferred = /* @__PURE__ */ new WeakSet();
|
|
25585
|
+
function terrainSettled(bo) {
|
|
25586
|
+
return !tiledStates.get(bo)?.abort && !deferred.has(bo);
|
|
25587
|
+
}
|
|
24417
25588
|
var MAX_BUILD_FAILURES = 2;
|
|
24418
25589
|
function heightTilesOf(bo) {
|
|
24419
25590
|
const tiles = bo.displacementMeta?.tiles;
|
|
@@ -24468,7 +25639,10 @@ function updateTiledWindow(bo, mesh, tiles, altitude, centerTheta, centerPhi, in
|
|
|
24468
25639
|
if (held) {
|
|
24469
25640
|
const still = drift(centerTheta, centerPhi, held.centerTheta, held.centerPhi);
|
|
24470
25641
|
if (kept === stepLevel && still < RECENTER_FRAC * held.angRadius) return true;
|
|
24471
|
-
if (performance.now() - held.builtAt < REBUILD_MIN_MS)
|
|
25642
|
+
if (performance.now() - held.builtAt < REBUILD_MIN_MS) {
|
|
25643
|
+
deferred.add(bo);
|
|
25644
|
+
return true;
|
|
25645
|
+
}
|
|
24472
25646
|
}
|
|
24473
25647
|
const grid = planNestedGrid(centerTheta, centerPhi, altitude, .5 * meta.scale_km / radiusKm, finest, bandCells, stepLevel);
|
|
24474
25648
|
const thetas = grid.rows.at;
|
|
@@ -24530,6 +25704,7 @@ function updateTiledWindow(bo, mesh, tiles, altitude, centerTheta, centerPhi, in
|
|
|
24530
25704
|
return !!held;
|
|
24531
25705
|
}
|
|
24532
25706
|
function updateTerrainWindow(bo, camera, eligible, invalidate) {
|
|
25707
|
+
deferred.delete(bo);
|
|
24533
25708
|
const mesh = bo.mesh;
|
|
24534
25709
|
const tex = bo.displacementMap;
|
|
24535
25710
|
if (!eligible || !mesh || !tex) {
|
|
@@ -24568,7 +25743,10 @@ function updateTerrainWindow(bo, camera, eligible, invalidate) {
|
|
|
24568
25743
|
if (w.stepLevel === stepLevel) {
|
|
24569
25744
|
if (drift(centerTheta, centerPhi, w.centerTheta, w.centerPhi) < RECENTER_FRAC * w.angRadius) return true;
|
|
24570
25745
|
}
|
|
24571
|
-
if (performance.now() - w.builtAt < REBUILD_MIN_MS)
|
|
25746
|
+
if (performance.now() - w.builtAt < REBUILD_MIN_MS) {
|
|
25747
|
+
deferred.add(bo);
|
|
25748
|
+
return true;
|
|
25749
|
+
}
|
|
24572
25750
|
}
|
|
24573
25751
|
const thetaLo = Math.max(0, centerTheta - angRadius);
|
|
24574
25752
|
const thetaHi = Math.min(Math.PI, centerTheta + angRadius);
|
|
@@ -24665,6 +25843,15 @@ function desiredDemTier(altitudeRadii, current) {
|
|
|
24665
25843
|
if (tierRank(down) < tierRank(current)) return down;
|
|
24666
25844
|
return current;
|
|
24667
25845
|
}
|
|
25846
|
+
function bodyLoading(bo) {
|
|
25847
|
+
if (bo.textureLoading || bo.displacementLoading || bo.clouds?.textureLoading) return true;
|
|
25848
|
+
if (bo.appearance?.loading || bo.modelLoadPromise) return true;
|
|
25849
|
+
const surface = bo.tileOverlay;
|
|
25850
|
+
if (surface && bo.surfaceTiles && !chainSettled(surface.chain, bo.surfaceTiles)) return true;
|
|
25851
|
+
const relief = bo.reliefTiles;
|
|
25852
|
+
if (relief && !chainSettled(relief.chain, relief.tiles)) return true;
|
|
25853
|
+
return !terrainSettled(bo);
|
|
25854
|
+
}
|
|
24668
25855
|
function updateTextureLOD(bodyObjects, camera, renderer, ctx, textureLoader, focusedId, jd, appearances, invalidate) {
|
|
24669
25856
|
appearances.apply(bodyObjects, textureLoader);
|
|
24670
25857
|
const fovRad = camera.fov * Math.PI / 180;
|
|
@@ -24702,7 +25889,9 @@ function updateTextureLOD(bodyObjects, camera, renderer, ctx, textureLoader, foc
|
|
|
24702
25889
|
updateTileOverlay(bo, camera, renderer, devicePx, settings.showSurfaceTexture && !bo.appearance?.surfaceOwned, invalidate);
|
|
24703
25890
|
updateReliefTiles(bo, camera, renderer, devicePx, invalidate);
|
|
24704
25891
|
const dispTiers = bo.displacementMeta?.tiers;
|
|
24705
|
-
if (bo.displacementMap &&
|
|
25892
|
+
if (bo.displacementMap && !bo.displacementLoading && pyramidHeightsServe(bo, renderer)) {
|
|
25893
|
+
if (bo.displacementTier !== "pyramid") swapDisplacementTier(bo, PYRAMID_TIER);
|
|
25894
|
+
} else if (bo.displacementMap && dispTiers?.length && !bo.displacementLoading) {
|
|
24706
25895
|
const maxTex = renderer.capabilities.maxTextureSize;
|
|
24707
25896
|
const capRank = maxTex >= 16383 && !reliefTilesServe(bo) ? 2 : maxTex >= 8192 ? 1 : 0;
|
|
24708
25897
|
const current = bo.displacementTier ?? "low";
|
|
@@ -24717,6 +25906,13 @@ function updateTextureLOD(bodyObjects, camera, renderer, ctx, textureLoader, foc
|
|
|
24717
25906
|
}
|
|
24718
25907
|
}
|
|
24719
25908
|
|
|
25909
|
+
//#endregion
|
|
25910
|
+
//#region src/lib/scene/perf/calibration-state.svelte.ts
|
|
25911
|
+
var calibrationUi = proxy({
|
|
25912
|
+
progress: null,
|
|
25913
|
+
bootPending: false
|
|
25914
|
+
});
|
|
25915
|
+
|
|
24720
25916
|
//#endregion
|
|
24721
25917
|
//#region src/lib/scene/animation/focus.ts
|
|
24722
25918
|
var FOCUS_DURATION_MS = FOCUS_ROT_PACING.refMs;
|
|
@@ -25025,7 +26221,7 @@ function computeGroupMode(count) {
|
|
|
25025
26221
|
return "none";
|
|
25026
26222
|
}
|
|
25027
26223
|
function isCurrentlyValid(body, jd) {
|
|
25028
|
-
return body.data
|
|
26224
|
+
return withinValidity(body.data, jd);
|
|
25029
26225
|
}
|
|
25030
26226
|
var PromotionRegistry = class {
|
|
25031
26227
|
pendingDefaults = /* @__PURE__ */ new Set();
|
|
@@ -25204,7 +26400,8 @@ var PromotionRegistry = class {
|
|
|
25204
26400
|
let n = 0;
|
|
25205
26401
|
for (const body of bucket.values()) {
|
|
25206
26402
|
if (this.groupTargets && !this.groupTargets.has(body.data.id)) continue;
|
|
25207
|
-
const
|
|
26403
|
+
const validityStart = clockJd(body.data, body.data.validityStart);
|
|
26404
|
+
const validityEnd = clockJd(body.data, body.data.validityEnd);
|
|
25208
26405
|
if (validityStart <= jd) {
|
|
25209
26406
|
if (validityStart > this.countStableLo) this.countStableLo = validityStart;
|
|
25210
26407
|
} else if (validityStart < this.countStableHi) this.countStableHi = validityStart;
|
|
@@ -25744,19 +26941,45 @@ var ExtensionRegistry = class {
|
|
|
25744
26941
|
|
|
25745
26942
|
//#endregion
|
|
25746
26943
|
//#region src/lib/scene/extensions/anchor.ts
|
|
25747
|
-
var RAD$
|
|
26944
|
+
var RAD$3 = Math.PI / 180;
|
|
25748
26945
|
function isSurface(anchor) {
|
|
25749
26946
|
return "latitude" in anchor;
|
|
25750
26947
|
}
|
|
25751
|
-
function surfaceDirection(latitude, longitude) {
|
|
25752
|
-
const lat = latitude * RAD$
|
|
25753
|
-
const lon = longitude * RAD$
|
|
25754
|
-
|
|
26948
|
+
function surfaceDirection(latitude, longitude, radii) {
|
|
26949
|
+
const lat = latitude * RAD$3;
|
|
26950
|
+
const lon = longitude * RAD$3;
|
|
26951
|
+
const out = [
|
|
25755
26952
|
Math.cos(lat) * Math.cos(lon),
|
|
25756
26953
|
Math.sin(lat),
|
|
25757
26954
|
-Math.cos(lat) * Math.sin(lon)
|
|
25758
26955
|
];
|
|
26956
|
+
if (radii) onEllipsoid(radii, out, 0, out, 0);
|
|
26957
|
+
return out;
|
|
25759
26958
|
}
|
|
26959
|
+
function onEllipsoid(radii, from, at, out, to) {
|
|
26960
|
+
const x = from[at] * radii.a;
|
|
26961
|
+
const y = from[at + 1] * radii.c;
|
|
26962
|
+
const z = from[at + 2] * radii.b;
|
|
26963
|
+
const n = Math.hypot(x, y, z);
|
|
26964
|
+
out[to] = x / n;
|
|
26965
|
+
out[to + 1] = y / n;
|
|
26966
|
+
out[to + 2] = z / n;
|
|
26967
|
+
}
|
|
26968
|
+
var GroundDirections = class {
|
|
26969
|
+
source = null;
|
|
26970
|
+
radii;
|
|
26971
|
+
out = new Float64Array(0);
|
|
26972
|
+
of(dirs, radii) {
|
|
26973
|
+
if (!radii) return dirs;
|
|
26974
|
+
if (dirs !== this.source || radii !== this.radii) {
|
|
26975
|
+
if (this.out.length !== dirs.length) this.out = new Float64Array(dirs.length);
|
|
26976
|
+
for (let i = 0; i < dirs.length; i += 3) onEllipsoid(radii, dirs, i, this.out, i);
|
|
26977
|
+
this.source = dirs;
|
|
26978
|
+
this.radii = radii;
|
|
26979
|
+
}
|
|
26980
|
+
return this.out;
|
|
26981
|
+
}
|
|
26982
|
+
};
|
|
25760
26983
|
function rotateByQuaternion(q, x, y, z, out, at) {
|
|
25761
26984
|
const tx = 2 * (q.y * z - q.z * y);
|
|
25762
26985
|
const ty = 2 * (q.z * x - q.x * z);
|
|
@@ -25772,7 +26995,7 @@ function placeAnchor(anchor, body, centre, jd) {
|
|
|
25772
26995
|
const [cx, cy, cz] = centre;
|
|
25773
26996
|
if (isSurface(anchor)) {
|
|
25774
26997
|
const distance = kmToScene(effectiveRadiusKm(body.data) + (anchor.altitudeKm ?? 0));
|
|
25775
|
-
const [dx, dy, dz] = surfaceDirection(anchor.latitude, anchor.longitude);
|
|
26998
|
+
const [dx, dy, dz] = surfaceDirection(anchor.latitude, anchor.longitude, body.drawnRadii);
|
|
25776
26999
|
const q = body.orientation ? bodyQuaternion(body.orientation, jd, body.nutPrec) : null;
|
|
25777
27000
|
if (!q) return [
|
|
25778
27001
|
cx + dx * distance,
|
|
@@ -25860,9 +27083,13 @@ function resolvePose(pose, ctx, jd) {
|
|
|
25860
27083
|
//#region src/lib/scene/camera/motion-scale.ts
|
|
25861
27084
|
var MIN_TRANSLATE_SCALE = .02;
|
|
25862
27085
|
var MIN_ROTATE_SCALE = 1e-4;
|
|
27086
|
+
var DAMPING_FRAME_MS = 1e3 / 60;
|
|
25863
27087
|
function orbitDamping(reducedMotion) {
|
|
25864
27088
|
return reducedMotion ? .4 : .05;
|
|
25865
27089
|
}
|
|
27090
|
+
function frameDamping(factor, frameDtMs) {
|
|
27091
|
+
return 1 - (1 - factor) ** (frameDtMs / DAMPING_FRAME_MS);
|
|
27092
|
+
}
|
|
25866
27093
|
function cameraMotionScale(camera, focusTruePos, focused, parent, seated) {
|
|
25867
27094
|
const orbitRadius = camera.position.length();
|
|
25868
27095
|
if (!(orbitRadius > 0)) return {
|
|
@@ -25892,10 +27119,10 @@ function clamp$1(value, min) {
|
|
|
25892
27119
|
|
|
25893
27120
|
//#endregion
|
|
25894
27121
|
//#region src/lib/scene/user-location/marker.ts
|
|
25895
|
-
var RAD$
|
|
27122
|
+
var RAD$2 = Math.PI / 180;
|
|
25896
27123
|
function bodyLocalUnitVector(latitude, longitude) {
|
|
25897
|
-
const latR = latitude * RAD$
|
|
25898
|
-
const lonR = longitude * RAD$
|
|
27124
|
+
const latR = latitude * RAD$2;
|
|
27125
|
+
const lonR = longitude * RAD$2;
|
|
25899
27126
|
return [
|
|
25900
27127
|
Math.cos(latR) * Math.cos(lonR),
|
|
25901
27128
|
Math.sin(latR),
|
|
@@ -26072,6 +27299,11 @@ var SceneRenderer = class SceneRenderer {
|
|
|
26072
27299
|
lastRenderedFocusKey = "";
|
|
26073
27300
|
lastRenderedCamPos = new Vector3(NaN, NaN, NaN);
|
|
26074
27301
|
lastRenderedCamQuat = new Quaternion();
|
|
27302
|
+
restCamPos = new Vector3(NaN, NaN, NaN);
|
|
27303
|
+
restCamQuat = new Quaternion();
|
|
27304
|
+
restFocusKey = "";
|
|
27305
|
+
atRest = false;
|
|
27306
|
+
focusLoads = 0;
|
|
26075
27307
|
unsubscribeBodiesAdded = null;
|
|
26076
27308
|
_trailView = {
|
|
26077
27309
|
camX: 0,
|
|
@@ -26088,6 +27320,7 @@ var SceneRenderer = class SceneRenderer {
|
|
|
26088
27320
|
firstFrame = true;
|
|
26089
27321
|
pendingUrlWrite = false;
|
|
26090
27322
|
lastTickMs = 0;
|
|
27323
|
+
orbitDampingFactor;
|
|
26091
27324
|
static FPS_SAMPLE_FRAMES = 30;
|
|
26092
27325
|
fpsSamples = [];
|
|
26093
27326
|
fpsSampleHead = 0;
|
|
@@ -26182,7 +27415,7 @@ var SceneRenderer = class SceneRenderer {
|
|
|
26182
27415
|
this.pointClouds.setPointBudget(this.tier.pointBudget);
|
|
26183
27416
|
this.controls = new OrbitControls(this.camera, canvas);
|
|
26184
27417
|
this.controls.enableDamping = true;
|
|
26185
|
-
this.
|
|
27418
|
+
this.orbitDampingFactor = orbitDamping(sceneSettings().resolvedReducedMotion);
|
|
26186
27419
|
this.controls.minDistance = focusBody ? minCameraDistance(focusBody) : kmToScene(.01);
|
|
26187
27420
|
this.controls.maxDistance = 31620.5 * 10;
|
|
26188
27421
|
this.controls.target.set(0, 0, 0);
|
|
@@ -26473,6 +27706,7 @@ var SceneRenderer = class SceneRenderer {
|
|
|
26473
27706
|
const nowMs = performance.now();
|
|
26474
27707
|
const frameDtMs = this.lastTickMs ? nowMs - this.lastTickMs : 0;
|
|
26475
27708
|
this.lastTickMs = nowMs;
|
|
27709
|
+
this.controls.dampingFactor = frameDamping(this.orbitDampingFactor, frameDtMs || 16.666666666666668);
|
|
26476
27710
|
if (!this.holdingCamera) this.cameraUp.update(this.sceneJd);
|
|
26477
27711
|
if (this.firstFrame) {
|
|
26478
27712
|
this.firstFrame = false;
|
|
@@ -26540,7 +27774,7 @@ var SceneRenderer = class SceneRenderer {
|
|
|
26540
27774
|
refreshDeferredTrails(this.bodyObjects, this.focus, this.lastUpdatedJd, this.trailView());
|
|
26541
27775
|
updateRingShaders(this.bodyObjects, this.focus.focusTruePos, sceneSettings().realisticLighting, sceneSettings().overexposeRings, this.camera.position, this.pxPerRad());
|
|
26542
27776
|
const occluders = collectOccluders(this.bodyObjects, this._occluders);
|
|
26543
|
-
updateEclipseUniforms(this.bodyObjects, occluders, this.focus.focusTruePos, sceneSettings().showAtmospheres);
|
|
27777
|
+
updateEclipseUniforms(this.bodyObjects, occluders, this.focus.focusTruePos, this.camera.position.length(), sceneSettings().showAtmospheres);
|
|
26544
27778
|
updatePlanetshineUniforms(this.bodyObjects, occluders, sceneSettings().realisticLighting, this.sunIntensityScale);
|
|
26545
27779
|
occluders.length = 0;
|
|
26546
27780
|
const atmoState = updateAtmosphereShaders(this.bodyObjects, this.camera.position, sceneSettings().showAtmospheres, sceneSettings().realisticLighting, this.sunIntensityScale, currentAtmosphereConfig(), this.sceneJd);
|
|
@@ -26574,7 +27808,27 @@ var SceneRenderer = class SceneRenderer {
|
|
|
26574
27808
|
this.renderModelOverlay();
|
|
26575
27809
|
this.labelRenderer.render(this.scene, this.camera);
|
|
26576
27810
|
if (this.haloDebug.active) this.haloDebug.draw(this.bodyObjects, this.camera, this.focus.focusTruePos, this.focusController.current?.data.id, this.renderer.domElement.clientWidth, this.renderer.domElement.clientHeight);
|
|
26577
|
-
|
|
27811
|
+
this.checkRest(nowMs);
|
|
27812
|
+
};
|
|
27813
|
+
checkRest(nowMs) {
|
|
27814
|
+
const moved = this.cameraMovedFrom(this.restCamPos, this.restCamQuat) || this.focusKey() !== this.restFocusKey;
|
|
27815
|
+
this.restCamPos.copy(this.camera.position);
|
|
27816
|
+
this.restCamQuat.copy(this.camera.quaternion);
|
|
27817
|
+
this.restFocusKey = this.focusKey();
|
|
27818
|
+
if (moved || this.settling(nowMs)) this.atRest = false;
|
|
27819
|
+
else if (!this.atRest) {
|
|
27820
|
+
this.atRest = true;
|
|
27821
|
+
this.callbacks.onIdle?.();
|
|
27822
|
+
}
|
|
27823
|
+
}
|
|
27824
|
+
settling(nowMs) {
|
|
27825
|
+
if (this.covered || this.ctx.loading || calibrationUi.bootPending) return true;
|
|
27826
|
+
if (nowMs - this.focus.focusStartTime < this.focus.focusDurationMs) return true;
|
|
27827
|
+
if (this.jumpJd !== null || this.seekAwaitsData) return true;
|
|
27828
|
+
if (this.focusLoads > 0 || this.systemData.isLoading()) return true;
|
|
27829
|
+
for (const bo of this.bodyObjects.values()) if (bo.group.visible && bodyLoading(bo)) return true;
|
|
27830
|
+
return false;
|
|
27831
|
+
}
|
|
26578
27832
|
syncSceneSamples(insideShell) {
|
|
26579
27833
|
const target = this.composer.readBuffer;
|
|
26580
27834
|
const samples = insideShell ? 0 : Math.min(this.tier.sceneSamples, this.maxSceneSamples);
|
|
@@ -26685,7 +27939,7 @@ var SceneRenderer = class SceneRenderer {
|
|
|
26685
27939
|
surfaceRadialKm(bodyId, latitude, longitude) {
|
|
26686
27940
|
const body = this.ctx.getBody(bodyId);
|
|
26687
27941
|
if (!body) return null;
|
|
26688
|
-
const dir =
|
|
27942
|
+
const dir = surfaceDirection(latitude, longitude, body.drawnRadii);
|
|
26689
27943
|
return renderedSurfaceRadialKm(this.bodyObjects.get(bodyId), bodyId, effectiveRadiusKm(body.data), dir);
|
|
26690
27944
|
}
|
|
26691
27945
|
surfaceClamp(body, seated) {
|
|
@@ -26975,11 +28229,14 @@ var SceneRenderer = class SceneRenderer {
|
|
|
26975
28229
|
if (nowMs - this.focus.focusStartTime < this.focus.focusDurationMs || this.focusKey() !== this.lastRenderedFocusKey || this.ctx.bodies.minorStreaming || this.pointClouds.hasPendingSceneAdds() || this.systemData.hasPendingUnloads()) return true;
|
|
26976
28230
|
if (this.covered) return false;
|
|
26977
28231
|
if (this.frameIndex - this.lastRenderedFrame >= SceneRenderer.IDLE_HEARTBEAT_FRAMES) return true;
|
|
26978
|
-
|
|
26979
|
-
if (cam.position.distanceToSquared(this.lastRenderedCamPos) > cam.position.lengthSq() * 1e-10 || 8 * (1 - Math.abs(cam.quaternion.dot(this.lastRenderedCamQuat))) > 1e-8 || this.frameIndex < this.wakeUntilFrame || this.haloDebug.active) return true;
|
|
28232
|
+
if (this.cameraMovedFrom(this.lastRenderedCamPos, this.lastRenderedCamQuat) || this.frameIndex < this.wakeUntilFrame || this.haloDebug.active) return true;
|
|
26980
28233
|
if (this.clock.jd === this.lastRenderedJd) return false;
|
|
26981
28234
|
return Math.abs(this.clock.timeScale) > 1 || nowMs - this.lastRenderMs >= SceneRenderer.REALTIME_FRAME_MS;
|
|
26982
28235
|
}
|
|
28236
|
+
cameraMovedFrom(pos, quat) {
|
|
28237
|
+
const cam = this.camera;
|
|
28238
|
+
return !(cam.position.distanceToSquared(pos) <= cam.position.lengthSq() * 1e-10 && 8 * (1 - Math.abs(cam.quaternion.dot(quat))) <= 1e-8);
|
|
28239
|
+
}
|
|
26983
28240
|
onControlsEnd = () => {
|
|
26984
28241
|
this.pendingUrlWrite = true;
|
|
26985
28242
|
this.focusController.clearPendingInitialView();
|
|
@@ -26995,13 +28252,15 @@ var SceneRenderer = class SceneRenderer {
|
|
|
26995
28252
|
maybeLoadTexture(body) {
|
|
26996
28253
|
const bo = this.bodyObjects.get(body.data.id);
|
|
26997
28254
|
if (!bo) return;
|
|
28255
|
+
this.focusLoads += 2;
|
|
28256
|
+
const done = () => this.focusLoads--;
|
|
26998
28257
|
loadBodyTexture(bo, this.textureLoader, this.sceneJd, this.scene, this.renderer.capabilities.maxTextureSize, this.ctx).then(() => {
|
|
26999
28258
|
if (this.focusController.current?.data.id !== body.data.id) return;
|
|
27000
28259
|
if (body.orientation && bo.mesh) {
|
|
27001
28260
|
applyOrientation(bo.mesh, body.orientation, this.sceneJd, body.nutPrec);
|
|
27002
28261
|
this.focusController.reapplyInitialViewIfPending();
|
|
27003
28262
|
}
|
|
27004
|
-
});
|
|
28263
|
+
}).finally(done);
|
|
27005
28264
|
loadBodyModel(bo, this.modelScene, this.ctx).then(() => {
|
|
27006
28265
|
if (this.focusController.current?.data.id === bo.body.data.id) this.controls.minDistance = minCameraDistance(bo.body, modelMinRadiusKm(bo));
|
|
27007
28266
|
if (this.ctx.layers.skipped.has("nomenclature")) return;
|
|
@@ -27011,7 +28270,7 @@ var SceneRenderer = class SceneRenderer {
|
|
|
27011
28270
|
});
|
|
27012
28271
|
}).then(() => {
|
|
27013
28272
|
if (this.selectedFeatureId !== null) setActiveFeatureLabel(bo, this.selectedFeatureId);
|
|
27014
|
-
});
|
|
28273
|
+
}).finally(done);
|
|
27015
28274
|
}
|
|
27016
28275
|
reapplyBodyLayers() {
|
|
27017
28276
|
const focused = this.focusController.current;
|
|
@@ -27164,7 +28423,7 @@ var SceneRenderer = class SceneRenderer {
|
|
|
27164
28423
|
}
|
|
27165
28424
|
}
|
|
27166
28425
|
setReducedMotion(on) {
|
|
27167
|
-
this.
|
|
28426
|
+
this.orbitDampingFactor = orbitDamping(on);
|
|
27168
28427
|
}
|
|
27169
28428
|
focusOnBody(id, zoom, latitude, longitude) {
|
|
27170
28429
|
this.disarmLimits();
|
|
@@ -27469,7 +28728,8 @@ var SceneRenderer = class SceneRenderer {
|
|
|
27469
28728
|
setCovered(covered) {
|
|
27470
28729
|
if (this.covered === covered) return;
|
|
27471
28730
|
this.covered = covered;
|
|
27472
|
-
if (
|
|
28731
|
+
if (covered) this.atRest = false;
|
|
28732
|
+
else this.invalidate();
|
|
27473
28733
|
}
|
|
27474
28734
|
isContextLost() {
|
|
27475
28735
|
return this.renderer.getContext().isContextLost();
|
|
@@ -27562,13 +28822,6 @@ function disposeTexture(value) {
|
|
|
27562
28822
|
if (value && typeof value === "object" && value.isTexture) value.dispose();
|
|
27563
28823
|
}
|
|
27564
28824
|
|
|
27565
|
-
//#endregion
|
|
27566
|
-
//#region src/lib/scene/perf/calibration-state.svelte.ts
|
|
27567
|
-
var calibrationUi = proxy({
|
|
27568
|
-
progress: null,
|
|
27569
|
-
bootPending: false
|
|
27570
|
-
});
|
|
27571
|
-
|
|
27572
28825
|
//#endregion
|
|
27573
28826
|
//#region src/lib/scene/perf/atmosphere-benchmark.ts
|
|
27574
28827
|
var EARTH_RADIUS_KM = 6371;
|
|
@@ -28589,7 +29842,7 @@ var IconExtension = class extends MarkerExtension {
|
|
|
28589
29842
|
//#endregion
|
|
28590
29843
|
//#region src/lib/flatmap/projection.ts
|
|
28591
29844
|
var DEG$6 = Math.PI / 180;
|
|
28592
|
-
var RAD$
|
|
29845
|
+
var RAD$1 = 180 / Math.PI;
|
|
28593
29846
|
function wrapLon(lon) {
|
|
28594
29847
|
if (lon >= -180 && lon < 180) return lon;
|
|
28595
29848
|
return ((lon + 180) % 360 + 360) % 360 - 180;
|
|
@@ -28636,8 +29889,8 @@ function equirectangular(options) {
|
|
|
28636
29889
|
const rowInverse = (y) => {
|
|
28637
29890
|
if (Math.abs(y) > Math.PI / 2) return null;
|
|
28638
29891
|
return {
|
|
28639
|
-
lat: y * RAD$
|
|
28640
|
-
lonPerX: RAD$
|
|
29892
|
+
lat: y * RAD$1,
|
|
29893
|
+
lonPerX: RAD$1,
|
|
28641
29894
|
maxAbsX: Math.PI
|
|
28642
29895
|
};
|
|
28643
29896
|
};
|
|
@@ -28685,9 +29938,9 @@ function equalEarth(options) {
|
|
|
28685
29938
|
const theta = thetaFor(y);
|
|
28686
29939
|
const sinLat = 2 / EE_SQRT3 * Math.sin(theta);
|
|
28687
29940
|
if (Math.abs(sinLat) > 1) return null;
|
|
28688
|
-
const lonPerX = 3 * eeDy(theta) / (2 * EE_SQRT3 * Math.cos(theta)) * RAD$
|
|
29941
|
+
const lonPerX = 3 * eeDy(theta) / (2 * EE_SQRT3 * Math.cos(theta)) * RAD$1;
|
|
28689
29942
|
return {
|
|
28690
|
-
lat: Math.asin(sinLat) * RAD$
|
|
29943
|
+
lat: Math.asin(sinLat) * RAD$1,
|
|
28691
29944
|
lonPerX,
|
|
28692
29945
|
maxAbsX: 180 / lonPerX
|
|
28693
29946
|
};
|
|
@@ -28719,9 +29972,9 @@ function mollweide(options) {
|
|
|
28719
29972
|
lonPerX: 0,
|
|
28720
29973
|
maxAbsX: 0
|
|
28721
29974
|
};
|
|
28722
|
-
const lonPerX = Math.PI / (2 * MW_SQRT2 * cosTheta) * RAD$
|
|
29975
|
+
const lonPerX = Math.PI / (2 * MW_SQRT2 * cosTheta) * RAD$1;
|
|
28723
29976
|
return {
|
|
28724
|
-
lat: Math.asin(sinLat) * RAD$
|
|
29977
|
+
lat: Math.asin(sinLat) * RAD$1,
|
|
28725
29978
|
lonPerX,
|
|
28726
29979
|
maxAbsX: 180 / lonPerX
|
|
28727
29980
|
};
|
|
@@ -28768,8 +30021,8 @@ function sinusoidal(options) {
|
|
|
28768
30021
|
maxAbsX: 0
|
|
28769
30022
|
};
|
|
28770
30023
|
return {
|
|
28771
|
-
lat: y * RAD$
|
|
28772
|
-
lonPerX: RAD$
|
|
30024
|
+
lat: y * RAD$1,
|
|
30025
|
+
lonPerX: RAD$1 / cosLat,
|
|
28773
30026
|
maxAbsX: Math.PI * cosLat
|
|
28774
30027
|
};
|
|
28775
30028
|
};
|
|
@@ -28920,7 +30173,7 @@ function clamp1(v) {
|
|
|
28920
30173
|
}
|
|
28921
30174
|
function azimuthalInverse(x, y, cosC, k, lon0, sinPhi0, cosPhi0) {
|
|
28922
30175
|
const lat = Math.asin(clamp1(cosC * sinPhi0 + y * k * cosPhi0));
|
|
28923
|
-
return [wrapLon(lon0 + Math.atan2(x * k, cosC * cosPhi0 - y * k * sinPhi0) * RAD$
|
|
30176
|
+
return [wrapLon(lon0 + Math.atan2(x * k, cosC * cosPhi0 - y * k * sinPhi0) * RAD$1), lat * RAD$1];
|
|
28924
30177
|
}
|
|
28925
30178
|
function discExtent(r) {
|
|
28926
30179
|
return {
|
|
@@ -29017,7 +30270,7 @@ function createProjection(id, options = {}) {
|
|
|
29017
30270
|
var DEG$5 = Math.PI / 180;
|
|
29018
30271
|
var TAU = 2 * Math.PI;
|
|
29019
30272
|
var RIM_STEP = 2 * DEG$5;
|
|
29020
|
-
var RAD
|
|
30273
|
+
var RAD = 180 / Math.PI;
|
|
29021
30274
|
var MAX_STEPS = 512;
|
|
29022
30275
|
var DEFAULT_STEP_DEG = 2;
|
|
29023
30276
|
function angularDistance(a, b) {
|
|
@@ -29026,7 +30279,7 @@ function angularDistance(a, b) {
|
|
|
29026
30279
|
const dφ = φ2 - φ1;
|
|
29027
30280
|
const dλ = wrapLon(b.lon - a.lon) * DEG$5;
|
|
29028
30281
|
const h = Math.sin(dφ / 2) ** 2 + Math.cos(φ1) * Math.cos(φ2) * Math.sin(dλ / 2) ** 2;
|
|
29029
|
-
return 2 * Math.asin(Math.min(1, Math.sqrt(h))) * RAD
|
|
30282
|
+
return 2 * Math.asin(Math.min(1, Math.sqrt(h))) * RAD;
|
|
29030
30283
|
}
|
|
29031
30284
|
function slerp(a, b, t) {
|
|
29032
30285
|
const d = angularDistance(a, b) * DEG$5;
|
|
@@ -29042,8 +30295,8 @@ function slerp(a, b, t) {
|
|
|
29042
30295
|
const y = ka * Math.cos(φ1) * Math.sin(λ1) + kb * Math.cos(φ2) * Math.sin(λ2);
|
|
29043
30296
|
const z = ka * Math.sin(φ1) + kb * Math.sin(φ2);
|
|
29044
30297
|
return {
|
|
29045
|
-
lon: Math.atan2(y, x) * RAD
|
|
29046
|
-
lat: Math.atan2(z, Math.hypot(x, y)) * RAD
|
|
30298
|
+
lon: Math.atan2(y, x) * RAD,
|
|
30299
|
+
lat: Math.atan2(z, Math.hypot(x, y)) * RAD
|
|
29047
30300
|
};
|
|
29048
30301
|
}
|
|
29049
30302
|
function lerp(a, b, t) {
|
|
@@ -29346,8 +30599,8 @@ function smallCircle(center, radiusDeg, steps = 128) {
|
|
|
29346
30599
|
const y = c[1] * cosR + e[1] * a + n[1] * b;
|
|
29347
30600
|
const z = c[2] * cosR + e[2] * a + n[2] * b;
|
|
29348
30601
|
ring.push({
|
|
29349
|
-
lon: wrapLon(Math.atan2(y, x) * RAD
|
|
29350
|
-
lat: Math.atan2(z, Math.hypot(x, y)) * RAD
|
|
30602
|
+
lon: wrapLon(Math.atan2(y, x) * RAD),
|
|
30603
|
+
lat: Math.atan2(z, Math.hypot(x, y)) * RAD
|
|
29351
30604
|
});
|
|
29352
30605
|
}
|
|
29353
30606
|
return ring;
|
|
@@ -29400,6 +30653,8 @@ var SurfaceShapeExtension = class {
|
|
|
29400
30653
|
alphas = new Float32Array(0);
|
|
29401
30654
|
lengths = new Float32Array(0);
|
|
29402
30655
|
fanDirs = new Float64Array(0);
|
|
30656
|
+
groundDirs = new GroundDirections();
|
|
30657
|
+
groundFanDirs = new GroundDirections();
|
|
29403
30658
|
fill = null;
|
|
29404
30659
|
fillScratch = new Float32Array(0);
|
|
29405
30660
|
turned = [
|
|
@@ -29466,7 +30721,8 @@ var SurfaceShapeExtension = class {
|
|
|
29466
30721
|
centre[2] - basis[2]
|
|
29467
30722
|
];
|
|
29468
30723
|
if (this.line) {
|
|
29469
|
-
this.
|
|
30724
|
+
const dirs = this.groundDirs.of(this.dirs, body.drawnRadii);
|
|
30725
|
+
this.place(dirs, this.count, q, scale, origin, this.scratch);
|
|
29470
30726
|
writeFatTrailVertices(this.line.geometry, this.scratch, this.alphas, this.alphas, this.count);
|
|
29471
30727
|
if (this.dash) {
|
|
29472
30728
|
screenLengths(this.scratch, this.count, camera, viewportPx, this.lengths);
|
|
@@ -29476,7 +30732,8 @@ var SurfaceShapeExtension = class {
|
|
|
29476
30732
|
}
|
|
29477
30733
|
if (this.fill) {
|
|
29478
30734
|
const position = this.fill.geometry.getAttribute("position");
|
|
29479
|
-
this.
|
|
30735
|
+
const fanDirs = this.groundFanDirs.of(this.fanDirs, body.drawnRadii);
|
|
30736
|
+
this.place(fanDirs, this.fillScratch.length / 3, q, scale, origin, this.fillScratch);
|
|
29480
30737
|
position.needsUpdate = true;
|
|
29481
30738
|
this.fill.material.uniforms.uCenterOffset.value.copy(camera.position).negate();
|
|
29482
30739
|
}
|
|
@@ -30027,6 +31284,7 @@ var SpaceMap = class {
|
|
|
30027
31284
|
clock: /* @__PURE__ */ new Set(),
|
|
30028
31285
|
loading: /* @__PURE__ */ new Set(),
|
|
30029
31286
|
progress: /* @__PURE__ */ new Set(),
|
|
31287
|
+
idle: /* @__PURE__ */ new Set(),
|
|
30030
31288
|
error: /* @__PURE__ */ new Set(),
|
|
30031
31289
|
datastale: /* @__PURE__ */ new Set(),
|
|
30032
31290
|
notice: /* @__PURE__ */ new Set(),
|
|
@@ -30298,6 +31556,7 @@ var SpaceMap = class {
|
|
|
30298
31556
|
dtMs
|
|
30299
31557
|
});
|
|
30300
31558
|
},
|
|
31559
|
+
onIdle: () => this.emit("idle"),
|
|
30301
31560
|
onCameraPosition: (latitude, longitude, zoom) => {
|
|
30302
31561
|
const body = this.focusedBody?.data.id;
|
|
30303
31562
|
if (body === void 0) return;
|
|
@@ -31777,7 +33036,7 @@ async function acquireBitmap(url, decodeWidth) {
|
|
|
31777
33036
|
};
|
|
31778
33037
|
let work = pending.get(key);
|
|
31779
33038
|
if (!work) {
|
|
31780
|
-
work = decode(url, decodeWidth);
|
|
33039
|
+
work = decode$1(url, decodeWidth);
|
|
31781
33040
|
pending.set(key, work);
|
|
31782
33041
|
const done = () => pending.delete(key);
|
|
31783
33042
|
work.then(done, done);
|
|
@@ -31789,7 +33048,7 @@ async function acquireBitmap(url, decodeWidth) {
|
|
|
31789
33048
|
bitmap: bitmaps.put(key, bitmap, bitmapBytes(bitmap.width, bitmap.height))
|
|
31790
33049
|
};
|
|
31791
33050
|
}
|
|
31792
|
-
async function decode(url, decodeWidth) {
|
|
33051
|
+
async function decode$1(url, decodeWidth) {
|
|
31793
33052
|
const response = await fetch(url);
|
|
31794
33053
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
31795
33054
|
const blob = await response.blob();
|
|
@@ -33083,17 +34342,25 @@ function findPanorama(entries, at) {
|
|
|
33083
34342
|
if (!at) return null;
|
|
33084
34343
|
return entries.find((e) => panoramaAt(e) === at || legacyAt(e) === at) ?? null;
|
|
33085
34344
|
}
|
|
34345
|
+
var MIN_STEP_M = 1;
|
|
33086
34346
|
function neighboursOf(entries, current, radiusKm) {
|
|
33087
34347
|
const i = entries.findIndex((e) => e.id === current.id);
|
|
33088
|
-
const
|
|
33089
|
-
|
|
33090
|
-
|
|
33091
|
-
|
|
33092
|
-
|
|
33093
|
-
|
|
34348
|
+
const nearest = (step) => {
|
|
34349
|
+
for (let j = i + step; j >= 0 && j < entries.length; j += step) {
|
|
34350
|
+
const e = entries[j];
|
|
34351
|
+
if (e.mission !== current.mission) return null;
|
|
34352
|
+
const distanceM = groundDistanceM(current, e, radiusKm);
|
|
34353
|
+
if (distanceM >= MIN_STEP_M) return {
|
|
34354
|
+
entry: e,
|
|
34355
|
+
distanceM,
|
|
34356
|
+
bearingDeg: bearingDeg(current, e)
|
|
34357
|
+
};
|
|
34358
|
+
}
|
|
34359
|
+
return null;
|
|
34360
|
+
};
|
|
33094
34361
|
return {
|
|
33095
|
-
previous:
|
|
33096
|
-
next:
|
|
34362
|
+
previous: nearest(-1),
|
|
34363
|
+
next: nearest(1)
|
|
33097
34364
|
};
|
|
33098
34365
|
}
|
|
33099
34366
|
var DEG$1 = Math.PI / 180;
|
|
@@ -33121,7 +34388,6 @@ var ARROW_DISTANCE = 9;
|
|
|
33121
34388
|
var CLICK_SLOP_PX = 6;
|
|
33122
34389
|
var ANGLE_STEP_DEG = 10;
|
|
33123
34390
|
var ANGLE_SAMPLE_STEP_DEG = 1;
|
|
33124
|
-
var MIN_ARROW_DISTANCE_M = 1;
|
|
33125
34391
|
var GYRO_TILT = new Quaternion(-Math.SQRT1_2, 0, 0, Math.SQRT1_2);
|
|
33126
34392
|
var SCREEN_AXIS = new Vector3(0, 0, 1);
|
|
33127
34393
|
function wrapHeading(deg) {
|
|
@@ -33340,7 +34606,7 @@ var PanoramaView = class {
|
|
|
33340
34606
|
this.setArrowTargets(this.neighbours && hasHeading(entry) ? ["previous", "next"].map((key) => ({
|
|
33341
34607
|
key,
|
|
33342
34608
|
n: this.neighbours?.[key] ?? null
|
|
33343
|
-
})).filter((a) => a.n
|
|
34609
|
+
})).filter((a) => a.n).map((a) => ({
|
|
33344
34610
|
key: a.key,
|
|
33345
34611
|
bearingDeg: a.n.bearingDeg
|
|
33346
34612
|
})) : []);
|
|
@@ -33738,6 +35004,106 @@ var fetchPlanetarySystemsMap = memoizedGzJson(() => `${dataBase()}/v1/groups/__p
|
|
|
33738
35004
|
//#region src/lib/fetch/groups/solar-system-map.ts
|
|
33739
35005
|
var fetchSolarSystemMap = memoizedGzJson(() => `${dataBase()}/v1/groups/__solar_system_map__.json.gz`, { error: (res) => `Failed to fetch solar system map: ${res.status}` });
|
|
33740
35006
|
|
|
35007
|
+
//#endregion
|
|
35008
|
+
//#region src/lib/rings/strip.ts
|
|
35009
|
+
var cache = /* @__PURE__ */ new Map();
|
|
35010
|
+
function luminance(r, g, b) {
|
|
35011
|
+
return .2126 * r + .7152 * g + .0722 * b;
|
|
35012
|
+
}
|
|
35013
|
+
async function decode(bodyId, meta) {
|
|
35014
|
+
const rows = meta.strip_rows;
|
|
35015
|
+
if (rows.transparency === void 0 || rows.color === void 0) {
|
|
35016
|
+
console.warn(`Ring strip ${bodyId}/${meta.strip} has no transparency or color row, no profile drawn:`, rows);
|
|
35017
|
+
return null;
|
|
35018
|
+
}
|
|
35019
|
+
const response = await fetch(versionedUrl(`/v1/rings/${bodyId}/${meta.strip}`, "rings"));
|
|
35020
|
+
if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
|
|
35021
|
+
const bitmap = await createImageBitmap(await response.blob());
|
|
35022
|
+
const canvas = document.createElement("canvas");
|
|
35023
|
+
canvas.width = bitmap.width;
|
|
35024
|
+
canvas.height = bitmap.height;
|
|
35025
|
+
const ctx = canvas.getContext("2d", { willReadFrequently: true });
|
|
35026
|
+
if (!ctx) {
|
|
35027
|
+
console.warn(`Ring strip ${bodyId}/${meta.strip}: no 2D context, no profile drawn`);
|
|
35028
|
+
return null;
|
|
35029
|
+
}
|
|
35030
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
35031
|
+
const n = bitmap.width;
|
|
35032
|
+
const pixels = ctx.getImageData(0, 0, n, bitmap.height).data;
|
|
35033
|
+
bitmap.close();
|
|
35034
|
+
const scale = meta.intensity_scale || 1;
|
|
35035
|
+
const tau = new Float32Array(n);
|
|
35036
|
+
const rgb = new Uint8ClampedArray(n * 3);
|
|
35037
|
+
const back = rows.backscattered ?? rows.color;
|
|
35038
|
+
const brightness = new Float32Array(n);
|
|
35039
|
+
let peak = 0;
|
|
35040
|
+
for (let i = 0; i < n; i++) {
|
|
35041
|
+
const t = (rows.transparency * n + i) * 4;
|
|
35042
|
+
const b = (back * n + i) * 4;
|
|
35043
|
+
const opacity = Math.min(1, (1 - pixels[t] / 255) * scale);
|
|
35044
|
+
tau[i] = opacity >= 1 ? Infinity : -Math.log(1 - opacity);
|
|
35045
|
+
brightness[i] = luminance(pixels[b], pixels[b + 1], pixels[b + 2]) / 255;
|
|
35046
|
+
if (brightness[i] > peak) peak = brightness[i];
|
|
35047
|
+
}
|
|
35048
|
+
const FLOOR = .35;
|
|
35049
|
+
for (let i = 0; i < n; i++) {
|
|
35050
|
+
const c = (rows.color * n + i) * 4;
|
|
35051
|
+
const lit = peak > 0 ? FLOOR + (1 - FLOOR) * (brightness[i] / peak) : 1;
|
|
35052
|
+
rgb[i * 3] = pixels[c] * lit;
|
|
35053
|
+
rgb[i * 3 + 1] = pixels[c + 1] * lit;
|
|
35054
|
+
rgb[i * 3 + 2] = pixels[c + 2] * lit;
|
|
35055
|
+
}
|
|
35056
|
+
return {
|
|
35057
|
+
inner: meta.inner_radius_km,
|
|
35058
|
+
outer: meta.outer_radius_km,
|
|
35059
|
+
tau,
|
|
35060
|
+
rgb
|
|
35061
|
+
};
|
|
35062
|
+
}
|
|
35063
|
+
async function load(bodyId) {
|
|
35064
|
+
const bundles = (await fetchObjectDetail(bodyId, false)).global?.rings ?? [];
|
|
35065
|
+
if (!bundles.length) console.warn(`Ring strips for ${bodyId}: no ring bundles on the object`);
|
|
35066
|
+
const profiles = [];
|
|
35067
|
+
for (const bundle of bundles) try {
|
|
35068
|
+
const profile = await decode(bodyId, bundle);
|
|
35069
|
+
if (profile) profiles.push(profile);
|
|
35070
|
+
} catch (err) {
|
|
35071
|
+
console.warn(`Ring strip ${bodyId}/${bundle.strip} unavailable:`, err);
|
|
35072
|
+
}
|
|
35073
|
+
return profiles;
|
|
35074
|
+
}
|
|
35075
|
+
var SEEN_TAU = -Math.log1p(-.02);
|
|
35076
|
+
function visibleSpan(profiles) {
|
|
35077
|
+
let inner = Infinity;
|
|
35078
|
+
let outer = -Infinity;
|
|
35079
|
+
for (const profile of profiles) {
|
|
35080
|
+
const n = profile.tau.length;
|
|
35081
|
+
const kmPerSample = (profile.outer - profile.inner) / (n - 1);
|
|
35082
|
+
for (let i = 0; i < n; i++) {
|
|
35083
|
+
if (profile.tau[i] < SEEN_TAU) continue;
|
|
35084
|
+
const km = profile.inner + i * kmPerSample;
|
|
35085
|
+
if (km < inner) inner = km;
|
|
35086
|
+
if (km > outer) outer = km;
|
|
35087
|
+
}
|
|
35088
|
+
}
|
|
35089
|
+
return outer >= inner ? {
|
|
35090
|
+
inner,
|
|
35091
|
+
outer
|
|
35092
|
+
} : null;
|
|
35093
|
+
}
|
|
35094
|
+
function loadRingStrips(bodyId) {
|
|
35095
|
+
let pending = cache.get(bodyId);
|
|
35096
|
+
if (!pending) {
|
|
35097
|
+
pending = load(bodyId).catch((err) => {
|
|
35098
|
+
console.warn(`Ring strips for ${bodyId} unavailable:`, err);
|
|
35099
|
+
cache.delete(bodyId);
|
|
35100
|
+
return [];
|
|
35101
|
+
});
|
|
35102
|
+
cache.set(bodyId, pending);
|
|
35103
|
+
}
|
|
35104
|
+
return pending;
|
|
35105
|
+
}
|
|
35106
|
+
|
|
33741
35107
|
//#endregion
|
|
33742
35108
|
//#region src/lib/charts/scrub.ts
|
|
33743
35109
|
var DRAG_SLOP = 8;
|
|
@@ -34527,6 +35893,15 @@ function systemFromMapEntry(entry, name) {
|
|
|
34527
35893
|
moonCount: entry.moon_count
|
|
34528
35894
|
};
|
|
34529
35895
|
}
|
|
35896
|
+
function visibleRings(system, profiles) {
|
|
35897
|
+
if (!system.rings || !profiles.length) return system.rings;
|
|
35898
|
+
const span = visibleSpan(profiles);
|
|
35899
|
+
const rKm = system.planetRadiusKm;
|
|
35900
|
+
return span && {
|
|
35901
|
+
innerRp: span.inner / rKm,
|
|
35902
|
+
outerRp: span.outer / rKm
|
|
35903
|
+
};
|
|
35904
|
+
}
|
|
34530
35905
|
var TOP_MOON_R = 14;
|
|
34531
35906
|
var AT_SURFACE = 1.001;
|
|
34532
35907
|
var PX_PER_DEG = .62;
|
|
@@ -34876,11 +36251,12 @@ function buildSystemView(data, primaryId, exported, options, text, pick) {
|
|
|
34876
36251
|
name: scope.name(moon.id, exported[moon.id])
|
|
34877
36252
|
}));
|
|
34878
36253
|
const rKm = system.planetRadiusKm;
|
|
34879
|
-
const
|
|
36254
|
+
const rings = data.ringProfiles ? visibleRings(system, data.ringProfiles) : system.rings;
|
|
36255
|
+
const bands = rings ? [{
|
|
34880
36256
|
key: "rings",
|
|
34881
36257
|
label: text.rings,
|
|
34882
|
-
innerKm:
|
|
34883
|
-
outerKm:
|
|
36258
|
+
innerKm: rings.innerRp * rKm,
|
|
36259
|
+
outerKm: rings.outerRp * rKm,
|
|
34884
36260
|
tone: "amber"
|
|
34885
36261
|
}] : [];
|
|
34886
36262
|
const model = planetarySystemModel(system, {
|
|
@@ -35027,6 +36403,7 @@ var SystemMap = class {
|
|
|
35027
36403
|
names;
|
|
35028
36404
|
grouping;
|
|
35029
36405
|
zones;
|
|
36406
|
+
rings;
|
|
35030
36407
|
places;
|
|
35031
36408
|
targets = [];
|
|
35032
36409
|
extras = /* @__PURE__ */ new Map();
|
|
@@ -35038,6 +36415,7 @@ var SystemMap = class {
|
|
|
35038
36415
|
this.names = options.names ?? {};
|
|
35039
36416
|
this.grouping = options.grouping ?? "bodies";
|
|
35040
36417
|
this.zones = options.zones ?? "belts";
|
|
36418
|
+
this.rings = options.rings ?? "all";
|
|
35041
36419
|
this.places = (options.places ?? []).map(extraFromPlace);
|
|
35042
36420
|
}
|
|
35043
36421
|
mount(container) {
|
|
@@ -35104,7 +36482,14 @@ var SystemMap = class {
|
|
|
35104
36482
|
};
|
|
35105
36483
|
switch (view.kind) {
|
|
35106
36484
|
case "solar-system": return buildSolarView(data, options, text, pick);
|
|
35107
|
-
case "system":
|
|
36485
|
+
case "system": {
|
|
36486
|
+
const ringed = this.rings === "visible" && !!systemEntry(systems, view.id)?.rings;
|
|
36487
|
+
const [names, ringProfiles] = await Promise.all([this.exportedNames(view.id, systems), ringed ? loadRingStrips(view.id) : void 0]);
|
|
36488
|
+
return buildSystemView({
|
|
36489
|
+
...data,
|
|
36490
|
+
ringProfiles
|
|
36491
|
+
}, view.id, names, options, text, pick);
|
|
36492
|
+
}
|
|
35108
36493
|
case "zone": {
|
|
35109
36494
|
const ids = unplacedIds(solar, systems, this.bodies, this.places.map((place) => place.id));
|
|
35110
36495
|
const read = (await Promise.all(ids.map((id) => this.extra(id)))).filter((extra) => extra !== null);
|
|
@@ -35357,9 +36742,6 @@ var PanoramaAttributionControl = class {
|
|
|
35357
36742
|
|
|
35358
36743
|
//#endregion
|
|
35359
36744
|
//#region src/lib/scene/extensions/trajectory.ts
|
|
35360
|
-
var RAD = Math.PI / 180;
|
|
35361
|
-
var COS_EPS = Math.cos(EARTH_OBLIQUITY_DEG * RAD);
|
|
35362
|
-
var SIN_EPS = Math.sin(EARTH_OBLIQUITY_DEG * RAD);
|
|
35363
36745
|
function fixed(place) {
|
|
35364
36746
|
return place;
|
|
35365
36747
|
}
|
|
@@ -35384,17 +36766,10 @@ function tle(line1, line2) {
|
|
|
35384
36766
|
offsetKm: (jd) => {
|
|
35385
36767
|
if (satrec.error !== SatRecError.None) return null;
|
|
35386
36768
|
const teme = sgp4PositionTEME(satrec, jd);
|
|
35387
|
-
return teme && temeToEcliptic(teme[0], teme[1], teme[2]);
|
|
36769
|
+
return teme && temeToEcliptic(teme[0], teme[1], teme[2], jd);
|
|
35388
36770
|
}
|
|
35389
36771
|
};
|
|
35390
36772
|
}
|
|
35391
|
-
function temeToEcliptic(x, y, z) {
|
|
35392
|
-
return [
|
|
35393
|
-
x,
|
|
35394
|
-
y * COS_EPS + z * SIN_EPS,
|
|
35395
|
-
-y * SIN_EPS + z * COS_EPS
|
|
35396
|
-
];
|
|
35397
|
-
}
|
|
35398
36773
|
function interpolateSamples(states, jd) {
|
|
35399
36774
|
const n = states.length;
|
|
35400
36775
|
if (n < 2 || jd < states[0].jd || jd > states[n - 1].jd) return null;
|
|
@@ -35478,7 +36853,7 @@ async function moonRow(id, { jd, metadata }) {
|
|
|
35478
36853
|
}
|
|
35479
36854
|
function elementsOffset(data, jd) {
|
|
35480
36855
|
if (!discovered(data.visibleFromDays, jd)) return null;
|
|
35481
|
-
if (
|
|
36856
|
+
if (!withinValidity(data, jd)) return null;
|
|
35482
36857
|
if (data.satrec) return sgp4PositionScene(data.satrec, jd);
|
|
35483
36858
|
if (data.q != null) return parabolicToPositionJD(data, jd);
|
|
35484
36859
|
if (data.a === 0) return [
|
|
@@ -35546,16 +36921,9 @@ function neighbours(id, { parents }, at) {
|
|
|
35546
36921
|
}
|
|
35547
36922
|
async function spinOf(id) {
|
|
35548
36923
|
const [detail] = await Promise.all([fetchObjectDetail(id, false), loadSystemsGlobal()]);
|
|
35549
|
-
const orientation = detail.global?.orientation;
|
|
35550
|
-
const sums = detail.global?.nut_prec;
|
|
35551
|
-
const naif = /^naif-(-?\d+)$/.exec(id);
|
|
35552
|
-
const angles = naif ? getNutPrecAngles(ownerIdFor(parseInt(naif[1], 10))) : void 0;
|
|
35553
36924
|
return {
|
|
35554
|
-
orientation,
|
|
35555
|
-
nutPrec:
|
|
35556
|
-
...sums,
|
|
35557
|
-
angles
|
|
35558
|
-
} : void 0
|
|
36925
|
+
orientation: detail.global?.orientation,
|
|
36926
|
+
nutPrec: nutPrecFor(id, detail.global?.nut_prec)
|
|
35559
36927
|
};
|
|
35560
36928
|
}
|
|
35561
36929
|
async function resolve(anchor, at) {
|