@splnlss/3d-story-viewer 0.5.5 → 0.5.7
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 +32 -0
- package/build/types/src/main.d.ts +9 -1
- package/build/types/src/viewer/ContentLayer/GaussianSplatLayer.d.ts +2 -0
- package/build/types/src/viewer/TransitionControls.d.ts +6 -0
- package/build/types/src/viewer/index.d.ts +7 -2
- package/build/viewer.cjs +1 -1
- package/build/viewer.js +159 -85
- package/package.json +10 -3
package/build/viewer.js
CHANGED
|
@@ -6471,7 +6471,7 @@ const QUAD_INDICES$1 = new Uint16Array([0, 1, 2, 0, 2, 3]);
|
|
|
6471
6471
|
const workerUrl$1 = new URL("assets/viewer/spark-old-worker-932b4a2c87ca.js", import.meta.url).href;
|
|
6472
6472
|
const workerWasmUrl$1 = new URL("assets/viewer/spark-worker-015de49d2d00.wasm", import.meta.url).href;
|
|
6473
6473
|
function WorkerWrapper$1(options) {
|
|
6474
|
-
const url = new URL(workerUrl$1);
|
|
6474
|
+
const url = new URL(workerUrl$1, globalThis.location.href);
|
|
6475
6475
|
url.searchParams.set("wasm", workerWasmUrl$1);
|
|
6476
6476
|
return new Worker(url, {
|
|
6477
6477
|
name: options == null ? void 0 : options.name
|
|
@@ -8218,7 +8218,7 @@ async function withWorker(callback) {
|
|
|
8218
8218
|
const workerUrl = new URL("assets/viewer/spark-worker-5ec8a483b87c.js", import.meta.url).href;
|
|
8219
8219
|
const workerWasmUrl = new URL("assets/viewer/spark-worker-015de49d2d00.wasm", import.meta.url).href;
|
|
8220
8220
|
function WorkerWrapper$2(options) {
|
|
8221
|
-
const url = new URL(workerUrl);
|
|
8221
|
+
const url = new URL(workerUrl, globalThis.location.href);
|
|
8222
8222
|
url.searchParams.set("wasm", workerWasmUrl);
|
|
8223
8223
|
return new Worker(url, {
|
|
8224
8224
|
name: options == null ? void 0 : options.name
|
|
@@ -12111,7 +12111,7 @@ const _SplatAccumulator = class _SplatAccumulator2 {
|
|
|
12111
12111
|
this.time = 0;
|
|
12112
12112
|
this.deltaTime = 0;
|
|
12113
12113
|
this.viewToWorld = new Matrix4();
|
|
12114
|
-
this.
|
|
12114
|
+
this.renderOrigin = new Vector3();
|
|
12115
12115
|
this.viewDirection = new Vector3();
|
|
12116
12116
|
this.maxSplats = 0;
|
|
12117
12117
|
this.numSplats = 0;
|
|
@@ -12394,10 +12394,10 @@ const _SplatAccumulator = class _SplatAccumulator2 {
|
|
|
12394
12394
|
lodInstances
|
|
12395
12395
|
}) {
|
|
12396
12396
|
var _a22;
|
|
12397
|
-
|
|
12398
|
-
|
|
12397
|
+
camera.getWorldPosition(this.renderOrigin);
|
|
12398
|
+
this.viewToWorld.copy(camera.matrixWorld).setPosition(0, 0, 0);
|
|
12399
12399
|
camera.getWorldDirection(this.viewDirection);
|
|
12400
|
-
_SplatAccumulator2.viewCenterUniform.value.
|
|
12400
|
+
_SplatAccumulator2.viewCenterUniform.value.set(0, 0, 0);
|
|
12401
12401
|
_SplatAccumulator2.viewDirUniform.value.copy(this.viewDirection);
|
|
12402
12402
|
_SplatAccumulator2.sortRadialUniform.value = sortRadial;
|
|
12403
12403
|
this.time = time;
|
|
@@ -12431,6 +12431,7 @@ const _SplatAccumulator = class _SplatAccumulator2 {
|
|
|
12431
12431
|
time: this.time,
|
|
12432
12432
|
deltaTime: this.deltaTime,
|
|
12433
12433
|
viewToWorld: this.viewToWorld,
|
|
12434
|
+
renderOrigin: this.renderOrigin,
|
|
12434
12435
|
camera,
|
|
12435
12436
|
renderSize,
|
|
12436
12437
|
globalEdits,
|
|
@@ -12695,6 +12696,14 @@ const _SparkRenderer = class _SparkRenderer2 extends Mesh {
|
|
|
12695
12696
|
this.sortTimeoutId = -1;
|
|
12696
12697
|
this.sortedCenter = new Vector3().setScalar(Number.NEGATIVE_INFINITY);
|
|
12697
12698
|
this.sortedDir = new Vector3().setScalar(0);
|
|
12699
|
+
this.accumToCamera = new Matrix4();
|
|
12700
|
+
this.accumToCameraScale = new Vector3();
|
|
12701
|
+
this.renderCameraToWorld = new Matrix4();
|
|
12702
|
+
this.renderCameraOrigin = new Vector3();
|
|
12703
|
+
this.lodCameraToWorld = new Matrix4();
|
|
12704
|
+
this.lodCameraScale = new Vector3();
|
|
12705
|
+
this.lodViewToObject = new Matrix4();
|
|
12706
|
+
this.lodMeshOrigin = new Vector3();
|
|
12698
12707
|
this.readback32 = new Uint32Array(0);
|
|
12699
12708
|
this.lastLodRaycastTime = 0;
|
|
12700
12709
|
this.lodWorker = null;
|
|
@@ -12936,17 +12945,14 @@ const _SparkRenderer = class _SparkRenderer2 extends Mesh {
|
|
|
12936
12945
|
this.uniforms.far.value = typedCamera.far;
|
|
12937
12946
|
const geometry = this.geometry;
|
|
12938
12947
|
geometry.instanceCount = spark.activeSplats;
|
|
12939
|
-
const
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
const cameraToWorld = camera.matrixWorld.clone();
|
|
12944
|
-
const worldToCamera = cameraToWorld.invert();
|
|
12945
|
-
const accumToCamera = worldToCamera.multiply(accumToWorld);
|
|
12948
|
+
const renderCameraToWorld = this.renderCameraToWorld.copy(camera.matrixWorld).setPosition(
|
|
12949
|
+
this.renderCameraOrigin.setFromMatrixPosition(camera.matrixWorld).sub(spark.display.renderOrigin)
|
|
12950
|
+
);
|
|
12951
|
+
const accumToCamera = this.accumToCamera.copy(renderCameraToWorld).invert();
|
|
12946
12952
|
accumToCamera.decompose(
|
|
12947
12953
|
this.uniforms.renderToViewPos.value,
|
|
12948
12954
|
this.uniforms.renderToViewQuat.value,
|
|
12949
|
-
|
|
12955
|
+
this.accumToCameraScale
|
|
12950
12956
|
);
|
|
12951
12957
|
this.uniforms.renderToViewBasis.value.setFromMatrix4(accumToCamera);
|
|
12952
12958
|
this.uniforms.maxStdDev.value = spark.maxStdDev;
|
|
@@ -13123,7 +13129,7 @@ const _SparkRenderer = class _SparkRenderer2 extends Mesh {
|
|
|
13123
13129
|
await new Promise((resolve) => setTimeout(resolve, this.readPause));
|
|
13124
13130
|
}
|
|
13125
13131
|
const current = this.current;
|
|
13126
|
-
this.sortedCenter.copy(current.
|
|
13132
|
+
this.sortedCenter.copy(current.renderOrigin);
|
|
13127
13133
|
this.sortedDir.copy(current.viewDirection);
|
|
13128
13134
|
const { numSplats, maxSplats } = current;
|
|
13129
13135
|
const rows = Math.max(1, Math.ceil(maxSplats / 16384));
|
|
@@ -13244,8 +13250,9 @@ const _SparkRenderer = class _SparkRenderer2 extends Mesh {
|
|
|
13244
13250
|
const viewPos = new Vector3();
|
|
13245
13251
|
const viewQuat = new Quaternion();
|
|
13246
13252
|
this.current.viewToWorld.decompose(viewPos, viewQuat, new Vector3());
|
|
13253
|
+
const lodPos = this.lodPosOverride ?? this.current.renderOrigin;
|
|
13247
13254
|
if (this.lodPosOverride) {
|
|
13248
|
-
viewPos.copy(this.lodPosOverride);
|
|
13255
|
+
viewPos.copy(this.lodPosOverride).sub(this.current.renderOrigin);
|
|
13249
13256
|
}
|
|
13250
13257
|
if (this.lodQuatOverride) {
|
|
13251
13258
|
viewQuat.copy(this.lodQuatOverride).normalize();
|
|
@@ -13254,7 +13261,7 @@ const _SparkRenderer = class _SparkRenderer2 extends Mesh {
|
|
|
13254
13261
|
if (this.lastLod.pixelScaleLimit !== pixelScaleLimit || this.lastLod.maxSplats !== maxSplats) {
|
|
13255
13262
|
this.lodDirty = true;
|
|
13256
13263
|
}
|
|
13257
|
-
const distance2 =
|
|
13264
|
+
const distance2 = lodPos.distanceTo(this.lastLod.pos);
|
|
13258
13265
|
const distanceRamp = Math.max(0, 1 - distance2 / 1);
|
|
13259
13266
|
const dot2 = viewQuat.dot(this.lastLod.quat);
|
|
13260
13267
|
const quatRamp = Math.max(0, 1 - (1 - dot2) / 0.01);
|
|
@@ -13354,10 +13361,10 @@ const _SparkRenderer = class _SparkRenderer2 extends Mesh {
|
|
|
13354
13361
|
const deltaPred = new Vector3();
|
|
13355
13362
|
if (this.lastLod) {
|
|
13356
13363
|
const deltaTime = Math.max(1, now22 - this.lastLod.timestamp);
|
|
13357
|
-
deltaPred.copy(
|
|
13364
|
+
deltaPred.copy(lodPos).sub(this.lastLod.pos).multiplyScalar(this.lastTraverseTime / deltaTime);
|
|
13358
13365
|
}
|
|
13359
13366
|
this.lastLod = {
|
|
13360
|
-
pos:
|
|
13367
|
+
pos: lodPos.clone(),
|
|
13361
13368
|
quat: viewQuat,
|
|
13362
13369
|
pixelScaleLimit,
|
|
13363
13370
|
maxSplats,
|
|
@@ -13369,8 +13376,10 @@ const _SparkRenderer = class _SparkRenderer2 extends Mesh {
|
|
|
13369
13376
|
deltaPred,
|
|
13370
13377
|
lodMeshes,
|
|
13371
13378
|
maxSplats,
|
|
13379
|
+
this.lastLod.pos,
|
|
13372
13380
|
viewPos,
|
|
13373
13381
|
viewQuat,
|
|
13382
|
+
this.current.renderOrigin,
|
|
13374
13383
|
pixelScaleLimit
|
|
13375
13384
|
);
|
|
13376
13385
|
this.currentLod = this.lastLod;
|
|
@@ -13395,18 +13404,20 @@ const _SparkRenderer = class _SparkRenderer2 extends Mesh {
|
|
|
13395
13404
|
this.lodIdToSplats.set(lodId, splats);
|
|
13396
13405
|
}
|
|
13397
13406
|
}
|
|
13398
|
-
async updateLodInstances(worker, deltaPred, lodMeshes, maxSplats, viewPos, viewQuat, pixelScaleLimit) {
|
|
13407
|
+
async updateLodInstances(worker, deltaPred, lodMeshes, maxSplats, lodPos, viewPos, viewQuat, renderOrigin, pixelScaleLimit) {
|
|
13399
13408
|
const uuidToMesh = /* @__PURE__ */ new Map();
|
|
13400
|
-
const cameraToWorld =
|
|
13409
|
+
const cameraToWorld = this.lodCameraToWorld.compose(
|
|
13401
13410
|
viewPos,
|
|
13402
13411
|
viewQuat,
|
|
13403
|
-
|
|
13412
|
+
this.lodCameraScale.setScalar(1)
|
|
13404
13413
|
);
|
|
13405
13414
|
const instances = lodMeshes.reduce(
|
|
13406
13415
|
(instances2, mesh) => {
|
|
13407
13416
|
var _a22, _b2;
|
|
13408
13417
|
uuidToMesh.set(mesh.uuid, mesh);
|
|
13409
|
-
const viewToObject =
|
|
13418
|
+
const viewToObject = this.lodViewToObject.copy(mesh.matrixWorld).setPosition(
|
|
13419
|
+
this.lodMeshOrigin.setFromMatrixPosition(mesh.matrixWorld).sub(renderOrigin)
|
|
13420
|
+
).invert().multiply(cameraToWorld);
|
|
13410
13421
|
const splats = ((_a22 = mesh.packedSplats) == null ? void 0 : _a22.lodSplats) ?? ((_b2 = mesh.extSplats) == null ? void 0 : _b2.lodSplats) ?? mesh.paged;
|
|
13411
13422
|
if (!splats) {
|
|
13412
13423
|
return instances2;
|
|
@@ -13422,7 +13433,7 @@ const _SparkRenderer = class _SparkRenderer2 extends Mesh {
|
|
|
13422
13433
|
instanceId: mesh.uuid,
|
|
13423
13434
|
lodId: record.lodId,
|
|
13424
13435
|
rootPage: record.rootPage,
|
|
13425
|
-
viewToObjectCols: viewToObject.elements,
|
|
13436
|
+
viewToObjectCols: viewToObject.elements.slice(),
|
|
13426
13437
|
lodScale: mesh.lodScale,
|
|
13427
13438
|
behindFoveate: mesh.behindFoveate ?? this.behindFoveate,
|
|
13428
13439
|
coneFov0: mesh.coneFov0 ?? this.coneFov0,
|
|
@@ -13457,7 +13468,7 @@ const _SparkRenderer = class _SparkRenderer2 extends Mesh {
|
|
|
13457
13468
|
const meshPosition = mesh.getWorldPosition(new Vector3());
|
|
13458
13469
|
return {
|
|
13459
13470
|
splats: mesh.paged,
|
|
13460
|
-
distance: meshPosition.distanceTo(
|
|
13471
|
+
distance: meshPosition.distanceTo(lodPos)
|
|
13461
13472
|
};
|
|
13462
13473
|
}).filter((result2) => result2 !== null);
|
|
13463
13474
|
if (!this.pageSizeWarning && pagedMeshes.length > this.pager.maxPages) {
|
|
@@ -15032,6 +15043,11 @@ const _SplatMesh = class _SplatMesh2 extends SplatGenerator {
|
|
|
15032
15043
|
this.splatRgba = null;
|
|
15033
15044
|
this.maxSh = 3;
|
|
15034
15045
|
this.showLodPageDyno = new DynoInt({ value: 0 });
|
|
15046
|
+
this.objectToRender = new Matrix4();
|
|
15047
|
+
this.objectToRenderOffset = new Vector3();
|
|
15048
|
+
this.worldToObject = new Matrix4();
|
|
15049
|
+
this.worldToView = new Matrix4();
|
|
15050
|
+
this.viewToObjectMatrix = new Matrix4();
|
|
15035
15051
|
if (options.splats) {
|
|
15036
15052
|
this.splats = options.splats;
|
|
15037
15053
|
this.numSplats = options.splats.getNumSplats();
|
|
@@ -15433,6 +15449,7 @@ const _SplatMesh = class _SplatMesh2 extends SplatGenerator {
|
|
|
15433
15449
|
time,
|
|
15434
15450
|
deltaTime,
|
|
15435
15451
|
viewToWorld,
|
|
15452
|
+
renderOrigin,
|
|
15436
15453
|
camera,
|
|
15437
15454
|
renderSize,
|
|
15438
15455
|
globalEdits,
|
|
@@ -15464,40 +15481,44 @@ const _SplatMesh = class _SplatMesh2 extends SplatGenerator {
|
|
|
15464
15481
|
this.lastSplats = this.context.splats;
|
|
15465
15482
|
this.generatorDirty = true;
|
|
15466
15483
|
}
|
|
15484
|
+
this.updateMatrixWorld();
|
|
15485
|
+
const objectToWorld = this.objectToRender.copy(this.matrixWorld);
|
|
15486
|
+
objectToWorld.setPosition(
|
|
15487
|
+
this.objectToRenderOffset.setFromMatrixPosition(this.matrixWorld).sub(renderOrigin)
|
|
15488
|
+
);
|
|
15467
15489
|
if (!this.covSplats) {
|
|
15468
|
-
if (this.context.transform.
|
|
15490
|
+
if (this.context.transform.updateFromMatrix(objectToWorld)) {
|
|
15469
15491
|
updated = true;
|
|
15470
15492
|
}
|
|
15471
15493
|
if (this.context.viewToWorld.updateFromMatrix(viewToWorld) && this.enableViewToWorld) {
|
|
15472
15494
|
updated = true;
|
|
15473
15495
|
}
|
|
15474
|
-
const worldToView =
|
|
15496
|
+
const worldToView = this.worldToView.copy(viewToWorld).invert();
|
|
15475
15497
|
if (this.context.worldToView.updateFromMatrix(worldToView) && this.enableWorldToView) {
|
|
15476
15498
|
updated = true;
|
|
15477
15499
|
}
|
|
15478
|
-
const
|
|
15479
|
-
this.
|
|
15480
|
-
|
|
15481
|
-
new Vector3().setScalar(this.context.transform.scale.value)
|
|
15500
|
+
const viewToObjectMatrix = this.viewToObjectMatrix.multiplyMatrices(
|
|
15501
|
+
this.worldToObject.copy(objectToWorld).invert(),
|
|
15502
|
+
viewToWorld
|
|
15482
15503
|
);
|
|
15483
|
-
const worldToObject = objectToWorld.invert();
|
|
15484
|
-
const viewToObjectMatrix = worldToObject.multiply(viewToWorld);
|
|
15485
15504
|
if (this.context.viewToObject.updateFromMatrix(viewToObjectMatrix) && (this.enableViewToObject || this.context.splats.hasRgbDir())) {
|
|
15486
15505
|
updated = true;
|
|
15487
15506
|
}
|
|
15488
15507
|
} else {
|
|
15489
|
-
if (this.context.covTransform.
|
|
15508
|
+
if (this.context.covTransform.updateFromMatrix(objectToWorld)) {
|
|
15490
15509
|
updated = true;
|
|
15491
15510
|
}
|
|
15492
15511
|
if (this.context.covViewToWorld.updateFromMatrix(viewToWorld) && this.enableViewToWorld) {
|
|
15493
15512
|
updated = true;
|
|
15494
15513
|
}
|
|
15495
|
-
const worldToView =
|
|
15514
|
+
const worldToView = this.worldToView.copy(viewToWorld).invert();
|
|
15496
15515
|
if (this.context.covWorldToView.updateFromMatrix(worldToView) && this.enableWorldToView) {
|
|
15497
15516
|
updated = true;
|
|
15498
15517
|
}
|
|
15499
|
-
const
|
|
15500
|
-
|
|
15518
|
+
const viewToObjectMatrix = this.viewToObjectMatrix.multiplyMatrices(
|
|
15519
|
+
this.worldToObject.copy(objectToWorld).invert(),
|
|
15520
|
+
viewToWorld
|
|
15521
|
+
);
|
|
15501
15522
|
if (this.context.covViewToObject.updateFromMatrix(viewToObjectMatrix) && (this.enableViewToObject || this.context.splats.hasRgbDir())) {
|
|
15502
15523
|
updated = true;
|
|
15503
15524
|
}
|
|
@@ -17694,6 +17715,7 @@ const _OldSparkRenderer = class _OldSparkRenderer2 extends Mesh {
|
|
|
17694
17715
|
this.lastUpdateTime = null;
|
|
17695
17716
|
this.defaultCameras = [];
|
|
17696
17717
|
this.lastStochastic = null;
|
|
17718
|
+
this.renderOrigin = new Vector3();
|
|
17697
17719
|
this.pendingUpdate = {
|
|
17698
17720
|
scene: null,
|
|
17699
17721
|
originToWorld: new Matrix4(),
|
|
@@ -18033,6 +18055,7 @@ const _OldSparkRenderer = class _OldSparkRenderer2 extends Mesh {
|
|
|
18033
18055
|
originToWorld = this.active.toWorld;
|
|
18034
18056
|
}
|
|
18035
18057
|
viewToWorld = viewToWorld ?? originToWorld.clone();
|
|
18058
|
+
this.renderOrigin.setFromMatrixPosition(originToWorld);
|
|
18036
18059
|
const time = this.time ?? this.clock.getElapsedTime();
|
|
18037
18060
|
const deltaTime = time - (this.lastUpdateTime ?? time);
|
|
18038
18061
|
this.lastUpdateTime = time;
|
|
@@ -18048,6 +18071,7 @@ const _OldSparkRenderer = class _OldSparkRenderer2 extends Mesh {
|
|
|
18048
18071
|
time,
|
|
18049
18072
|
deltaTime,
|
|
18050
18073
|
viewToWorld,
|
|
18074
|
+
renderOrigin: this.renderOrigin,
|
|
18051
18075
|
globalEdits
|
|
18052
18076
|
});
|
|
18053
18077
|
}
|
|
@@ -26706,20 +26730,28 @@ class TransitionControls extends EventDispatcher {
|
|
|
26706
26730
|
this.lookAt = new Vector3();
|
|
26707
26731
|
this.cameraTween = null;
|
|
26708
26732
|
this.lookAtTween = null;
|
|
26733
|
+
this.activeTransition = null;
|
|
26709
26734
|
this.is2D = false;
|
|
26710
26735
|
}
|
|
26711
26736
|
animateTo(position, quaternion, duration = TweenSettings.DURATION) {
|
|
26712
|
-
|
|
26737
|
+
this.cancel();
|
|
26738
|
+
return new Promise((resolve) => {
|
|
26713
26739
|
const fromPosition = this.camera.position.clone();
|
|
26714
26740
|
const fromQuaternion = this.camera.quaternion.clone();
|
|
26715
26741
|
const toPosition = position.clone();
|
|
26716
26742
|
const toQuaternion = quaternion.clone();
|
|
26743
|
+
const transition = { resolve, toPosition, toQuaternion };
|
|
26744
|
+
this.activeTransition = transition;
|
|
26717
26745
|
const deltaPosition = toPosition.clone().sub(fromPosition);
|
|
26718
26746
|
const deltaDistance = deltaPosition.length();
|
|
26719
26747
|
const deltaQuaternion = toQuaternion.clone().multiply(fromQuaternion.clone().invert());
|
|
26720
26748
|
const deltaAngle = Math.acos(Math.min(1, deltaQuaternion.w));
|
|
26721
|
-
if (deltaDistance < 1 && deltaAngle < 1) {
|
|
26722
|
-
|
|
26749
|
+
if (duration <= 0 || deltaDistance < 1 && deltaAngle < 1) {
|
|
26750
|
+
this.camera.position.copy(toPosition);
|
|
26751
|
+
this.camera.quaternion.copy(toQuaternion);
|
|
26752
|
+
this.camera.updateMatrixWorld(true);
|
|
26753
|
+
this.activeTransition = null;
|
|
26754
|
+
resolve(true);
|
|
26723
26755
|
} else {
|
|
26724
26756
|
const fromLookAt = new Vector3(0, 0, -deltaDistance * 0.25).applyQuaternion(fromQuaternion).add(fromPosition);
|
|
26725
26757
|
const toLookAt = new Vector3(0, 0, -deltaDistance * 0.25).applyQuaternion(toQuaternion).add(toPosition);
|
|
@@ -26730,15 +26762,24 @@ class TransitionControls extends EventDispatcher {
|
|
|
26730
26762
|
this.lookAtTween = new Tween(this.lookAt).to(toLookAt, duration).easing(Easing.Quartic.InOut).onComplete(() => {
|
|
26731
26763
|
this.lookAt.copy(toLookAt);
|
|
26732
26764
|
this.lookAtTween = null;
|
|
26765
|
+
this.complete(transition);
|
|
26733
26766
|
}).start();
|
|
26734
26767
|
this.cameraTween = new Tween(this.camera).to({ position: toPosition, up: toUp }, duration).easing(Easing.Quartic.InOut).onComplete(() => {
|
|
26735
26768
|
this.camera.position.copy(toPosition);
|
|
26736
26769
|
this.cameraTween = null;
|
|
26737
|
-
|
|
26770
|
+
this.complete(transition);
|
|
26738
26771
|
}).start();
|
|
26739
26772
|
}
|
|
26740
26773
|
});
|
|
26741
26774
|
}
|
|
26775
|
+
complete(transition) {
|
|
26776
|
+
if (this.activeTransition !== transition || this.cameraTween || this.lookAtTween) return;
|
|
26777
|
+
this.camera.position.copy(transition.toPosition);
|
|
26778
|
+
this.camera.quaternion.copy(transition.toQuaternion);
|
|
26779
|
+
this.camera.updateMatrixWorld(true);
|
|
26780
|
+
this.activeTransition = null;
|
|
26781
|
+
transition.resolve(true);
|
|
26782
|
+
}
|
|
26742
26783
|
update(time) {
|
|
26743
26784
|
if (this.cameraUpTween) this.cameraUpTween.update(time);
|
|
26744
26785
|
if (this.cameraTween) this.cameraTween.update(time);
|
|
@@ -26748,6 +26789,8 @@ class TransitionControls extends EventDispatcher {
|
|
|
26748
26789
|
}
|
|
26749
26790
|
}
|
|
26750
26791
|
cancel() {
|
|
26792
|
+
const transition = this.activeTransition;
|
|
26793
|
+
this.activeTransition = null;
|
|
26751
26794
|
if (this.cameraTween) {
|
|
26752
26795
|
this.cameraTween.stop();
|
|
26753
26796
|
this.cameraTween = null;
|
|
@@ -26760,6 +26803,7 @@ class TransitionControls extends EventDispatcher {
|
|
|
26760
26803
|
this.cameraUpTween.stop();
|
|
26761
26804
|
this.cameraUpTween = null;
|
|
26762
26805
|
}
|
|
26806
|
+
transition == null ? void 0 : transition.resolve(false);
|
|
26763
26807
|
}
|
|
26764
26808
|
}
|
|
26765
26809
|
var sky_default$1 = "uniform vec3 sunPosition;uniform float rayleigh;uniform float turbidity;uniform float mieCoefficient;uniform vec3 up;varying vec3 vWorldPosition;varying vec3 vSunDirection;varying float vSunfade;varying vec3 vBetaR;varying vec3 vBetaM;varying float vSunE;const float e=2.71828182845904523536028747135266249775724709369995957;const float pi=3.141592653589793238462643383279502884197169;const vec3 lambda=vec3(680E-9,550E-9,450E-9);const vec3 totalRayleigh=vec3(5.804542996261093E-6,1.3562911419845635E-5,3.0265902468824876E-5);const float v=4.0;const vec3 K=vec3(0.686,0.678,0.666);const vec3 MieConst=vec3(1.8399918514433978E14,2.7798023919660528E14,4.0790479543861094E14);const float cutoffAngle=1.6110731556870734;const float steepness=1.5;const float EE=1000.0;float sunIntensity(float zenithAngleCos){zenithAngleCos=clamp(zenithAngleCos,-1.0,1.0);return EE*max(0.0,1.0-pow(e,-((cutoffAngle-acos(zenithAngleCos))/steepness)));}vec3 totalMie(float T){float c=(0.2*T)*10E-18;return 0.434*c*MieConst;}void main(){vec4 worldPosition=modelMatrix*vec4(position,1.0);vWorldPosition=worldPosition.xyz;gl_Position=projectionMatrix*modelViewMatrix*vec4(position,1.0);gl_Position.z=gl_Position.w;vSunDirection=normalize(sunPosition);vSunE=sunIntensity(dot(vSunDirection,up));vSunfade=1.0-clamp(1.0-exp((sunPosition.y/450000.0)),0.0,1.0);float rayleighCoefficient=rayleigh-(1.0*(1.0-vSunfade));vBetaR=totalRayleigh*rayleighCoefficient;vBetaM=totalMie(turbidity)*mieCoefficient;}";
|
|
@@ -27152,7 +27196,7 @@ class GeojsonLayer extends ContentLayer {
|
|
|
27152
27196
|
this.clear();
|
|
27153
27197
|
}
|
|
27154
27198
|
}
|
|
27155
|
-
const GAUSSIAN_FORMATS = /* @__PURE__ */ new Set(["ply", "sog"]);
|
|
27199
|
+
const GAUSSIAN_FORMATS = /* @__PURE__ */ new Set(["ply", "sog", "spz", "rad"]);
|
|
27156
27200
|
function geodeticToEcefPosition(longitude, latitude, altitude) {
|
|
27157
27201
|
const semiMajorAxis = 6378137;
|
|
27158
27202
|
const eccentricity = 0.081819190842622;
|
|
@@ -27189,7 +27233,7 @@ function validateGaussianSplatLayerDefinition(definition) {
|
|
|
27189
27233
|
}
|
|
27190
27234
|
requireNonEmptyString((_a3 = definition.data) == null ? void 0 : _a3.url, "data.url");
|
|
27191
27235
|
if (!GAUSSIAN_FORMATS.has((_b2 = definition.data) == null ? void 0 : _b2.format)) {
|
|
27192
|
-
throw new Error('data.format must be "ply" or "
|
|
27236
|
+
throw new Error('data.format must be "ply", "sog", "spz", or "rad".');
|
|
27193
27237
|
}
|
|
27194
27238
|
const renderOrder = ((_c = definition.options) == null ? void 0 : _c.renderOrder) ?? 0;
|
|
27195
27239
|
if (renderOrder !== 0) {
|
|
@@ -27261,7 +27305,9 @@ function makeGaussianSplatTransform(transform) {
|
|
|
27261
27305
|
}
|
|
27262
27306
|
const FORMAT_TYPES = {
|
|
27263
27307
|
ply: SplatFileType.PLY,
|
|
27264
|
-
sog: SplatFileType.PCSOGSZIP
|
|
27308
|
+
sog: SplatFileType.PCSOGSZIP,
|
|
27309
|
+
spz: SplatFileType.SPZ,
|
|
27310
|
+
rad: SplatFileType.RAD
|
|
27265
27311
|
};
|
|
27266
27312
|
function normalizeError(error) {
|
|
27267
27313
|
return error instanceof Error ? error : new Error(String(error));
|
|
@@ -27292,39 +27338,15 @@ class GaussianSplatLayer extends ContentLayer {
|
|
|
27292
27338
|
}
|
|
27293
27339
|
}
|
|
27294
27340
|
async load() {
|
|
27295
|
-
var _a3, _b2, _c, _d, _e2, _f, _g, _h, _i2;
|
|
27341
|
+
var _a3, _b2, _c, _d, _e2, _f, _g, _h, _i2, _j;
|
|
27296
27342
|
if (this.loadState === "loading" || this.loadState === "ready" || this.loadState === "disposed") return;
|
|
27297
27343
|
const attempt = ++this.loadAttempt;
|
|
27298
27344
|
this.loadState = "loading";
|
|
27299
|
-
this.abortController = new AbortController();
|
|
27300
27345
|
let mesh = null;
|
|
27301
27346
|
try {
|
|
27302
27347
|
(_b2 = (_a3 = this.callbacks).onStart) == null ? void 0 : _b2.call(_a3, this);
|
|
27303
27348
|
(_d = (_c = this.callbacks).ensureRenderer) == null ? void 0 : _d.call(_c);
|
|
27304
|
-
|
|
27305
|
-
if (!response.ok) {
|
|
27306
|
-
throw new Error(`Failed to load Gaussian splat: ${response.status} ${response.statusText}`);
|
|
27307
|
-
}
|
|
27308
|
-
if (!response.body) {
|
|
27309
|
-
throw new Error("Failed to load Gaussian splat: response body is unavailable.");
|
|
27310
|
-
}
|
|
27311
|
-
const contentLengthHeader = response.headers.get("Content-Length");
|
|
27312
|
-
const contentLength = contentLengthHeader === null ? void 0 : Number.parseInt(contentLengthHeader, 10);
|
|
27313
|
-
mesh = new SplatMesh({
|
|
27314
|
-
stream: response.body,
|
|
27315
|
-
streamLength: Number.isFinite(contentLength) && contentLength >= 0 ? contentLength : void 0,
|
|
27316
|
-
fileType: FORMAT_TYPES[this.definition.data.format],
|
|
27317
|
-
onProgress: (event) => {
|
|
27318
|
-
var _a4, _b3;
|
|
27319
|
-
if (this.loadState !== "disposed" && attempt === this.loadAttempt) {
|
|
27320
|
-
(_b3 = (_a4 = this.callbacks).onProgress) == null ? void 0 : _b3.call(_a4, this, {
|
|
27321
|
-
loaded: event.loaded,
|
|
27322
|
-
total: event.total,
|
|
27323
|
-
lengthComputable: event.lengthComputable
|
|
27324
|
-
});
|
|
27325
|
-
}
|
|
27326
|
-
}
|
|
27327
|
-
});
|
|
27349
|
+
mesh = this.definition.data.format === "rad" ? this.createPagedMesh() : await this.createDirectMesh(attempt);
|
|
27328
27350
|
mesh.layers.set(0);
|
|
27329
27351
|
mesh.matrix.copy(this.transformMatrix);
|
|
27330
27352
|
mesh.matrix.decompose(mesh.position, mesh.quaternion, mesh.scale);
|
|
@@ -27332,23 +27354,66 @@ class GaussianSplatLayer extends ContentLayer {
|
|
|
27332
27354
|
mesh.matrixWorldNeedsUpdate = true;
|
|
27333
27355
|
this.splatMesh = mesh;
|
|
27334
27356
|
this.add(mesh);
|
|
27335
|
-
|
|
27357
|
+
if (this.definition.data.format === "rad") {
|
|
27358
|
+
if (!((_e2 = mesh.paged) == null ? void 0 : _e2.getRadMeta)) {
|
|
27359
|
+
throw new Error("Failed to initialize paged RAD streaming.");
|
|
27360
|
+
}
|
|
27361
|
+
await Promise.all([mesh.initialized, mesh.paged.getRadMeta()]);
|
|
27362
|
+
} else {
|
|
27363
|
+
await mesh.initialized;
|
|
27364
|
+
}
|
|
27336
27365
|
if (this.loadState === "disposed" || attempt !== this.loadAttempt) {
|
|
27337
27366
|
this.disposeMesh(mesh);
|
|
27338
27367
|
return;
|
|
27339
27368
|
}
|
|
27340
27369
|
this.abortController = null;
|
|
27341
27370
|
this.loadState = "ready";
|
|
27342
|
-
(
|
|
27371
|
+
(_g = (_f = this.callbacks).onReady) == null ? void 0 : _g.call(_f, this);
|
|
27343
27372
|
} catch (error) {
|
|
27344
27373
|
this.disposeMesh(mesh);
|
|
27345
|
-
const aborted = (
|
|
27374
|
+
const aborted = (_h = this.abortController) == null ? void 0 : _h.signal.aborted;
|
|
27346
27375
|
this.abortController = null;
|
|
27347
27376
|
if (this.loadState === "disposed" || attempt !== this.loadAttempt || aborted) return;
|
|
27348
27377
|
this.loadState = "error";
|
|
27349
|
-
(
|
|
27378
|
+
(_j = (_i2 = this.callbacks).onError) == null ? void 0 : _j.call(_i2, this, normalizeError(error));
|
|
27350
27379
|
}
|
|
27351
27380
|
}
|
|
27381
|
+
createPagedMesh() {
|
|
27382
|
+
const paged = new PagedSplats({
|
|
27383
|
+
rootUrl: this.definition.data.url,
|
|
27384
|
+
fileType: FORMAT_TYPES[this.definition.data.format]
|
|
27385
|
+
});
|
|
27386
|
+
return new SplatMesh({
|
|
27387
|
+
paged
|
|
27388
|
+
});
|
|
27389
|
+
}
|
|
27390
|
+
async createDirectMesh(attempt) {
|
|
27391
|
+
this.abortController = new AbortController();
|
|
27392
|
+
const response = await fetch(this.definition.data.url, { signal: this.abortController.signal });
|
|
27393
|
+
if (!response.ok) {
|
|
27394
|
+
throw new Error(`Failed to load Gaussian splat: ${response.status} ${response.statusText}`);
|
|
27395
|
+
}
|
|
27396
|
+
if (!response.body) {
|
|
27397
|
+
throw new Error("Failed to load Gaussian splat: response body is unavailable.");
|
|
27398
|
+
}
|
|
27399
|
+
const contentLengthHeader = response.headers.get("Content-Length");
|
|
27400
|
+
const contentLength = contentLengthHeader === null ? void 0 : Number.parseInt(contentLengthHeader, 10);
|
|
27401
|
+
return new SplatMesh({
|
|
27402
|
+
stream: response.body,
|
|
27403
|
+
streamLength: Number.isFinite(contentLength) && contentLength >= 0 ? contentLength : void 0,
|
|
27404
|
+
fileType: FORMAT_TYPES[this.definition.data.format],
|
|
27405
|
+
onProgress: (event) => {
|
|
27406
|
+
var _a3, _b2;
|
|
27407
|
+
if (this.loadState !== "disposed" && attempt === this.loadAttempt) {
|
|
27408
|
+
(_b2 = (_a3 = this.callbacks).onProgress) == null ? void 0 : _b2.call(_a3, this, {
|
|
27409
|
+
loaded: event.loaded,
|
|
27410
|
+
total: event.total,
|
|
27411
|
+
lengthComputable: event.lengthComputable
|
|
27412
|
+
});
|
|
27413
|
+
}
|
|
27414
|
+
}
|
|
27415
|
+
});
|
|
27416
|
+
}
|
|
27352
27417
|
disposeMesh(mesh) {
|
|
27353
27418
|
if (!mesh || mesh.userData.gaussianSplatDisposed) return;
|
|
27354
27419
|
mesh.userData.gaussianSplatDisposed = true;
|
|
@@ -27396,12 +27461,17 @@ const ViewerEvents = (
|
|
|
27396
27461
|
}
|
|
27397
27462
|
);
|
|
27398
27463
|
class Viewer extends EventDispatcher {
|
|
27464
|
+
/**
|
|
27465
|
+
* @param {HTMLElement | null} container
|
|
27466
|
+
* @param {import('../main.js').ViewerOptions} [options]
|
|
27467
|
+
*/
|
|
27399
27468
|
constructor(container, options = {}) {
|
|
27400
27469
|
super();
|
|
27401
27470
|
this.isViewer = true;
|
|
27402
27471
|
this.type = "viewer";
|
|
27403
27472
|
this.disposed = false;
|
|
27404
27473
|
this.sparkRenderer = null;
|
|
27474
|
+
this.transparentBackground = options.transparentBackground ?? true;
|
|
27405
27475
|
Tokens.CESIUM = options.cesiumToken || void 0;
|
|
27406
27476
|
Tokens.GOOGLEMAPS = options.googleMapsToken || void 0;
|
|
27407
27477
|
this.state = new StateDispatcher({
|
|
@@ -27412,9 +27482,11 @@ class Viewer extends EventDispatcher {
|
|
|
27412
27482
|
});
|
|
27413
27483
|
this.renderer = new WebGLRenderer({
|
|
27414
27484
|
antialias: true,
|
|
27415
|
-
powerPreference: "high-performance"
|
|
27485
|
+
powerPreference: "high-performance",
|
|
27486
|
+
alpha: this.transparentBackground,
|
|
27487
|
+
premultipliedAlpha: true
|
|
27416
27488
|
});
|
|
27417
|
-
this.renderer.setClearColor(16777215, 1);
|
|
27489
|
+
this.renderer.setClearColor(this.transparentBackground ? 0 : 16777215, this.transparentBackground ? 0 : 1);
|
|
27418
27490
|
this.renderer.toneMapping = AgXToneMapping;
|
|
27419
27491
|
this.renderer.outputColorSpace = SRGBColorSpace;
|
|
27420
27492
|
this.renderer.toneMappingExposure = 1;
|
|
@@ -27449,6 +27521,7 @@ class Viewer extends EventDispatcher {
|
|
|
27449
27521
|
this.transitionControls = new TransitionControls(this.camera);
|
|
27450
27522
|
this.globeManager = new GlobeManager(this.scene, this.camera, this.renderer, { apiToken: Tokens.CESIUM, googleMapsToken: Tokens.GOOGLEMAPS });
|
|
27451
27523
|
if (this.globeManager.tiles) {
|
|
27524
|
+
this.globeManager.tiles.group.visible = !this.transparentBackground;
|
|
27452
27525
|
this.globeControls.setTilesRenderer(this.globeManager.tiles);
|
|
27453
27526
|
}
|
|
27454
27527
|
this.cameraCoords = {};
|
|
@@ -27492,6 +27565,7 @@ class Viewer extends EventDispatcher {
|
|
|
27492
27565
|
if (container) this.appendTo(container);
|
|
27493
27566
|
this.sky = new Sky();
|
|
27494
27567
|
this.sky.scale.setScalar(2e7);
|
|
27568
|
+
this.sky.visible = !this.transparentBackground;
|
|
27495
27569
|
this.scene.add(this.sky);
|
|
27496
27570
|
const phi = MathUtils.degToRad(80);
|
|
27497
27571
|
const theta = MathUtils.degToRad(180);
|
|
@@ -27551,7 +27625,7 @@ class Viewer extends EventDispatcher {
|
|
|
27551
27625
|
return coords;
|
|
27552
27626
|
}
|
|
27553
27627
|
setBackgroundColor(color) {
|
|
27554
|
-
this.renderer.setClearColor(color, 0);
|
|
27628
|
+
this.renderer.setClearColor(color, this.transparentBackground ? 0 : 1);
|
|
27555
27629
|
}
|
|
27556
27630
|
appendTo(container) {
|
|
27557
27631
|
this.container = container;
|
|
@@ -27847,8 +27921,8 @@ class Viewer extends EventDispatcher {
|
|
|
27847
27921
|
async alignCamera(lon, lat, alt, pitch = this.cameraCoords.pitch, yaw = this.cameraCoords.yaw, roll = this.cameraCoords.roll, duration = TweenSettings.DURATION) {
|
|
27848
27922
|
const targetPosition = new Vector3().fromArray(geodeticToEcefPosition$1(lon, lat, alt));
|
|
27849
27923
|
const targetQuaternion = geodeticToEcefRotation(lon, lat, pitch, yaw, roll);
|
|
27850
|
-
return this.transitionControls.animateTo(targetPosition, targetQuaternion, duration).then(() => {
|
|
27851
|
-
this.dispatchEvent({ type: ViewerEvents.TRANSITIONED, lon, lat, alt, pitch, yaw, roll });
|
|
27924
|
+
return this.transitionControls.animateTo(targetPosition, targetQuaternion, duration).then((completed) => {
|
|
27925
|
+
if (completed) this.dispatchEvent({ type: ViewerEvents.TRANSITIONED, lon, lat, alt, pitch, yaw, roll });
|
|
27852
27926
|
});
|
|
27853
27927
|
}
|
|
27854
27928
|
async focusCamera(lon, lat, alt, distance = 2e3, pitch = this.cameraCoords.pitch, duration = TweenSettings.DURATION) {
|
|
@@ -27856,8 +27930,8 @@ class Viewer extends EventDispatcher {
|
|
|
27856
27930
|
const targetQuaternion = geodeticToEcefRotation(lon, lat, pitch, 0, 0);
|
|
27857
27931
|
const direction = new Vector3(0, 0, 1).applyQuaternion(targetQuaternion);
|
|
27858
27932
|
targetPosition.addScaledVector(direction, distance);
|
|
27859
|
-
return this.transitionControls.animateTo(targetPosition, targetQuaternion, duration).then(() => {
|
|
27860
|
-
this.dispatchEvent({ type: ViewerEvents.TRANSITIONED, lon, lat, alt });
|
|
27933
|
+
return this.transitionControls.animateTo(targetPosition, targetQuaternion, duration).then((completed) => {
|
|
27934
|
+
if (completed) this.dispatchEvent({ type: ViewerEvents.TRANSITIONED, lon, lat, alt });
|
|
27861
27935
|
});
|
|
27862
27936
|
}
|
|
27863
27937
|
async angleCamera(pitch = this.cameraCoords.pitch, yaw = this.cameraCoords.yaw, duration = TweenSettings.DURATION) {
|
|
@@ -27868,17 +27942,17 @@ class Viewer extends EventDispatcher {
|
|
|
27868
27942
|
const targetQuaternion = geodeticToEcefRotation(lon, lat, pitch, yaw, 0);
|
|
27869
27943
|
const direction = new Vector3(0, 0, 1).applyQuaternion(targetQuaternion);
|
|
27870
27944
|
targetPosition.addScaledVector(direction, distance);
|
|
27871
|
-
return this.transitionControls.animateTo(targetPosition, targetQuaternion, duration).then(() => {
|
|
27872
|
-
this.dispatchEvent({ type: ViewerEvents.TRANSITIONED, lon, lat, alt });
|
|
27945
|
+
return this.transitionControls.animateTo(targetPosition, targetQuaternion, duration).then((completed) => {
|
|
27946
|
+
if (completed) this.dispatchEvent({ type: ViewerEvents.TRANSITIONED, lon, lat, alt });
|
|
27873
27947
|
});
|
|
27874
27948
|
}
|
|
27875
27949
|
setViewMode(mode = "3d") {
|
|
27876
27950
|
if (mode == "3d") {
|
|
27877
27951
|
this.globeControls.rotationSpeed = 1;
|
|
27878
|
-
this.angleCamera(-60, void 0, 500);
|
|
27952
|
+
return this.angleCamera(-60, void 0, 500);
|
|
27879
27953
|
} else {
|
|
27880
27954
|
this.globeControls.rotationSpeed = 0;
|
|
27881
|
-
this.angleCamera(-90, 0, 500);
|
|
27955
|
+
return this.angleCamera(-90, 0, 500);
|
|
27882
27956
|
}
|
|
27883
27957
|
}
|
|
27884
27958
|
exportScene() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@splnlss/3d-story-viewer",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -25,10 +25,15 @@
|
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
|
+
"patch:spark": "patch-package --error-on-fail && node scripts/check-spark-backport.mjs",
|
|
29
|
+
"predev": "yarn patch:spark",
|
|
28
30
|
"dev": "vite",
|
|
31
|
+
"prebuild": "yarn patch:spark",
|
|
29
32
|
"build": "vite build && tsc -p tsconfig.types.json",
|
|
30
33
|
"preview": "vite preview",
|
|
34
|
+
"pretest": "yarn patch:spark",
|
|
31
35
|
"test": "vitest run",
|
|
36
|
+
"pretest:browser": "yarn patch:spark",
|
|
32
37
|
"test:browser": "playwright test",
|
|
33
38
|
"test:all": "npm run test && npm run test:browser",
|
|
34
39
|
"pack:check": "node scripts/check-package-assets.mjs",
|
|
@@ -40,6 +45,8 @@
|
|
|
40
45
|
"@loaders.gl/gltf": "^4.3.4",
|
|
41
46
|
"@loaders.gl/polyfills": "^4.3.4",
|
|
42
47
|
"@playwright/test": "1.62.1",
|
|
48
|
+
"patch-package": "8.0.1",
|
|
49
|
+
"pngjs": "7.0.0",
|
|
43
50
|
"typescript": "5.9.3",
|
|
44
51
|
"vitest": "3.2.7"
|
|
45
52
|
},
|
|
@@ -49,6 +56,7 @@
|
|
|
49
56
|
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
|
50
57
|
"@tweenjs/tween.js": "^25.0.0",
|
|
51
58
|
"@vitejs/plugin-basic-ssl": "^1.2.0",
|
|
59
|
+
"dotenv": "^17.2.2",
|
|
52
60
|
"earcut": "^3.0.1",
|
|
53
61
|
"sass": "^1.83.4",
|
|
54
62
|
"stats.js": "^0.17.0",
|
|
@@ -57,7 +65,6 @@
|
|
|
57
65
|
"terser": "^5.37.0",
|
|
58
66
|
"three": "0.185.1",
|
|
59
67
|
"vite": "^6.0.5",
|
|
60
|
-
"vite-plugin-glsl": "^1.3.1"
|
|
61
|
-
"dotenv": "^17.2.2"
|
|
68
|
+
"vite-plugin-glsl": "^1.3.1"
|
|
62
69
|
}
|
|
63
70
|
}
|