3dtiles-inspector 0.2.6 → 0.2.8
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/CHANGELOG.md +18 -0
- package/dist/inspector-assets/viewer/app.js +175 -195
- package/package.json +2 -2
- package/src/server/saveTransform.js +2 -0
- package/src/server/saveTransformHandler.js +2 -0
- package/src/server/splatCrop/gaussianPrimitives.js +48 -0
- package/src/server/splatCrop/gltfResource.js +4 -4
- package/src/server/splatCrop/index.js +21 -3
- package/src/server/splatCrop/traversal.js +239 -42
- package/src/server/splatCrop/worker.js +20 -2
- package/src/server/splatCrop/workerPool.js +37 -2
- package/src/viewer/app.js +2 -1
- package/src/viewer/scene/tiles.js +2 -2
- package/src/viewer/transform/geometricError.js +98 -13
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,24 @@ The format is based on Keep a Changelog and this project follows Semantic Versio
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.2.8] - 2026-05-13
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed save-time crop memory spikes on large tilesets by limiting concurrent Gaussian Splat resource processing based on CPU parallelism, capped at 8 workers.
|
|
14
|
+
- Fixed viewer stalls when many tiles are loaded by avoiding repeated tileset-wide leaf geometric-error scans during tile preprocessing.
|
|
15
|
+
|
|
16
|
+
## [0.2.7] - 2026-05-10
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Changed crop saves to remove local orphaned Gaussian Splat `.glb` / `.gltf` resources and private external buffers after fully cropped content is pruned from the tileset.
|
|
21
|
+
- Updated `3d-tiles-rendererjs-3dgs-plugin` from `0.1.5` to `0.1.7`.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Fixed cropped Gaussian Splat resources keeping stale glTF accessor counts after SPZ data is rewritten, which could make Cesium fail while generating splat textures.
|
|
26
|
+
|
|
9
27
|
## [0.2.6] - 2026-05-05
|
|
10
28
|
|
|
11
29
|
### Added
|
|
@@ -43855,6 +43855,12 @@ async function buildGaussianMeshSource(descriptor, abortSignal) {
|
|
|
43855
43855
|
}
|
|
43856
43856
|
return { extSplats };
|
|
43857
43857
|
}
|
|
43858
|
+
function isXrPresenting(renderer) {
|
|
43859
|
+
return renderer.xr.isPresenting;
|
|
43860
|
+
}
|
|
43861
|
+
function getUpdateSourceCamera(renderer, camera, xrPresenting = isXrPresenting(renderer)) {
|
|
43862
|
+
return xrPresenting ? renderer.xr.getCamera() : camera;
|
|
43863
|
+
}
|
|
43858
43864
|
function ensureCameraClone(cached, source) {
|
|
43859
43865
|
if (!cached || cached.constructor !== source.constructor) {
|
|
43860
43866
|
return source.clone();
|
|
@@ -43862,111 +43868,11 @@ function ensureCameraClone(cached, source) {
|
|
|
43862
43868
|
cached.copy(source, false);
|
|
43863
43869
|
return cached;
|
|
43864
43870
|
}
|
|
43865
|
-
function
|
|
43866
|
-
|
|
43867
|
-
while (ancestor) {
|
|
43868
|
-
if (ancestor instanceof SplatMesh || isGaussianSplat(ancestor)) {
|
|
43869
|
-
return true;
|
|
43870
|
-
}
|
|
43871
|
-
ancestor = ancestor.parent;
|
|
43872
|
-
}
|
|
43873
|
-
return false;
|
|
43874
|
-
}
|
|
43875
|
-
function isGlobalSplatEdit(node) {
|
|
43876
|
-
return node instanceof SplatEdit && !hasGaussianSplatAncestor(node);
|
|
43877
|
-
}
|
|
43878
|
-
function isCameraRelativeNode(node) {
|
|
43879
|
-
return isGaussianSplat(node) || isGlobalSplatEdit(node);
|
|
43880
|
-
}
|
|
43881
|
-
function hasCameraRelativeRootAncestor(node) {
|
|
43882
|
-
let ancestor = node.parent;
|
|
43883
|
-
while (ancestor) {
|
|
43884
|
-
if (isCameraRelativeNode(ancestor)) {
|
|
43885
|
-
return true;
|
|
43886
|
-
}
|
|
43887
|
-
ancestor = ancestor.parent;
|
|
43888
|
-
}
|
|
43889
|
-
return false;
|
|
43890
|
-
}
|
|
43891
|
-
function cloneSplatRootSnapshot(node) {
|
|
43892
|
-
return {
|
|
43893
|
-
kind: "splat",
|
|
43894
|
-
opacity: node.opacity,
|
|
43895
|
-
matrixWorld: node.matrixWorld.clone()
|
|
43896
|
-
};
|
|
43897
|
-
}
|
|
43898
|
-
function cloneSplatEditSdfSnapshot(sdf) {
|
|
43899
|
-
return {
|
|
43900
|
-
uuid: sdf.uuid,
|
|
43901
|
-
matrixWorld: sdf.matrixWorld.clone(),
|
|
43902
|
-
type: sdf.type,
|
|
43903
|
-
invert: sdf.invert,
|
|
43904
|
-
opacity: sdf.opacity,
|
|
43905
|
-
color: sdf.color.clone(),
|
|
43906
|
-
radius: sdf.radius,
|
|
43907
|
-
displace: sdf.displace.clone(),
|
|
43908
|
-
scale: sdf.scale.clone()
|
|
43909
|
-
};
|
|
43910
|
-
}
|
|
43911
|
-
function cloneSplatEditRootSnapshot(edit) {
|
|
43912
|
-
edit.updateMatrixWorld(true);
|
|
43913
|
-
const sdfs = [];
|
|
43914
|
-
const sourceSdfs = edit.sdfs;
|
|
43915
|
-
if (sourceSdfs != null) {
|
|
43916
|
-
for (const sdf of sourceSdfs) {
|
|
43917
|
-
sdf.updateMatrixWorld(true);
|
|
43918
|
-
sdfs.push(cloneSplatEditSdfSnapshot(sdf));
|
|
43919
|
-
}
|
|
43920
|
-
} else {
|
|
43921
|
-
edit.traverseVisible((child) => {
|
|
43922
|
-
if (child instanceof SplatEditSdf) {
|
|
43923
|
-
child.updateMatrixWorld(true);
|
|
43924
|
-
sdfs.push(cloneSplatEditSdfSnapshot(child));
|
|
43925
|
-
}
|
|
43926
|
-
});
|
|
43927
|
-
}
|
|
43928
|
-
return {
|
|
43929
|
-
kind: "edit",
|
|
43930
|
-
matrixWorld: edit.matrixWorld.clone(),
|
|
43931
|
-
ordering: edit.ordering,
|
|
43932
|
-
rgbaBlendMode: edit.rgbaBlendMode,
|
|
43933
|
-
sdfSmooth: edit.sdfSmooth,
|
|
43934
|
-
softEdge: edit.softEdge,
|
|
43935
|
-
invert: edit.invert,
|
|
43936
|
-
sdfs
|
|
43937
|
-
};
|
|
43938
|
-
}
|
|
43939
|
-
function cloneCameraRelativeRootSnapshot(node) {
|
|
43940
|
-
return node instanceof SplatEdit ? cloneSplatEditRootSnapshot(node) : cloneSplatRootSnapshot(node);
|
|
43941
|
-
}
|
|
43942
|
-
function areSplatRootStatesEqual(a2, b5) {
|
|
43943
|
-
return a2.opacity === b5.opacity && a2.matrixWorld.equals(b5.matrixWorld);
|
|
43944
|
-
}
|
|
43945
|
-
function areSplatEditSdfStatesEqual(a2, b5) {
|
|
43946
|
-
return a2.uuid === b5.uuid && a2.type === b5.type && a2.invert === b5.invert && a2.opacity === b5.opacity && a2.radius === b5.radius && a2.matrixWorld.equals(b5.matrixWorld) && a2.color.equals(b5.color) && a2.displace.equals(b5.displace) && a2.scale.equals(b5.scale);
|
|
43871
|
+
function isGaussianSplatNode(node) {
|
|
43872
|
+
return node instanceof SplatMesh || isGaussianSplat(node);
|
|
43947
43873
|
}
|
|
43948
|
-
function
|
|
43949
|
-
|
|
43950
|
-
return false;
|
|
43951
|
-
}
|
|
43952
|
-
for (let i = 0; i < a2.sdfs.length; i++) {
|
|
43953
|
-
if (!areSplatEditSdfStatesEqual(a2.sdfs[i], b5.sdfs[i])) {
|
|
43954
|
-
return false;
|
|
43955
|
-
}
|
|
43956
|
-
}
|
|
43957
|
-
return true;
|
|
43958
|
-
}
|
|
43959
|
-
function areCameraRelativeRootStatesEqual(a2, b5) {
|
|
43960
|
-
if (a2 === b5) {
|
|
43961
|
-
return true;
|
|
43962
|
-
}
|
|
43963
|
-
if (!a2 || !b5 || a2.kind !== b5.kind) {
|
|
43964
|
-
return false;
|
|
43965
|
-
}
|
|
43966
|
-
if (a2.kind === "splat") {
|
|
43967
|
-
return b5.kind === "splat" && areSplatRootStatesEqual(a2, b5);
|
|
43968
|
-
}
|
|
43969
|
-
return b5.kind === "edit" && areSplatEditRootStatesEqual(a2, b5);
|
|
43874
|
+
function isCameraRelativeEdit(node, hasGaussianSplatAncestor) {
|
|
43875
|
+
return node instanceof SplatEdit && !hasGaussianSplatAncestor;
|
|
43970
43876
|
}
|
|
43971
43877
|
function normalizeSparkRendererOptions(host, includeCustomDefaults = true) {
|
|
43972
43878
|
const source = host.sparkRendererOptions ?? {};
|
|
@@ -44154,7 +44060,7 @@ function isGaussianSplat(object) {
|
|
|
44154
44060
|
function isGaussianSplatScene(scene) {
|
|
44155
44061
|
return Boolean(scene?.userData?.gaussianSplatScene);
|
|
44156
44062
|
}
|
|
44157
|
-
var _translation, _rotation, _scale, _identityMatrix2, _tempNodeMatrix, _textDecoder, _identityMatrix22, _cameraInverseWorldMatrix, _parentInverseWorldMatrix, _rebasedLocalMatrix, _displayFrameInverseWorldMatrix, _relativeRenderCameraMatrix,
|
|
44063
|
+
var _translation, _rotation, _scale, _identityMatrix2, _tempNodeMatrix, _textDecoder, _identityMatrix22, _cameraInverseWorldMatrix, _parentInverseWorldMatrix, _rebasedLocalMatrix, _displayFrameInverseWorldMatrix, _relativeRenderCameraMatrix, _updateCamera, _renderCamera, _cameraWorldSnapshot, _lastXrHandledFrame, _rebasedRootsPool, _rebasedRootsCount, _hadRebasedLastFrame, _CameraRelativeSparkRenderer_instances, updateSparkIfNeeded_fn, getUpdateCamera_fn, getRenderCamera_fn, rebaseCameraRelativeRoots_fn, visitVisibleCameraRelativeRoots_fn, rebaseCameraRelativeRoot_fn, restoreCameraRelativeRoots_fn, _a2, CameraRelativeSparkRenderer, _sharedSparkManagersByScene, _sharedSparkManagersByRenderer, CUSTOM_DEFAULT_OPTIONS, _sparkRenderer, _scene, _sparkRendererOptions, _notifyHandle, _disposeHandle, _tilesRenderers, _disposed, _SharedSparkRendererManager_instances, dispose_fn, stopScheduledNotifications_fn, scheduleSortUpdatedNotification_fn, waitForSortAndDispose_fn, _a3, SharedSparkRendererManager, SPARK_RENDERER_OPTION_KEYS, MAX_GAUSSIAN_MESH_INIT_CONCURRENCY, _sceneMatrix, _gaussianFadeValueWatched, _host, _sparkManager, _GaussianSplatPlugin_instances, disposeSplatScene_fn, getSplatMeshes_fn, createMeshForDescriptor_fn, _a4, GaussianSplatPlugin;
|
|
44158
44064
|
var init_dist = __esm({
|
|
44159
44065
|
"node_modules/3d-tiles-rendererjs-3dgs-plugin/dist/index.js"() {
|
|
44160
44066
|
init_spark_module();
|
|
@@ -44175,10 +44081,6 @@ var init_dist = __esm({
|
|
|
44175
44081
|
_rebasedLocalMatrix = new Matrix4();
|
|
44176
44082
|
_displayFrameInverseWorldMatrix = new Matrix4();
|
|
44177
44083
|
_relativeRenderCameraMatrix = new Matrix4();
|
|
44178
|
-
_cameraWorldPosition = new Vector3();
|
|
44179
|
-
_cameraWorldDirection = new Vector3();
|
|
44180
|
-
_cameraPositionEpsilonSq = 1e-6;
|
|
44181
|
-
_cameraDirectionDotThreshold = 1 - 1e-3;
|
|
44182
44084
|
CameraRelativeSparkRenderer = (_a2 = class extends SparkRenderer {
|
|
44183
44085
|
constructor(renderer, options = {}) {
|
|
44184
44086
|
super({
|
|
@@ -44190,11 +44092,8 @@ var init_dist = __esm({
|
|
|
44190
44092
|
__privateAdd(this, _CameraRelativeSparkRenderer_instances);
|
|
44191
44093
|
__privateAdd(this, _updateCamera, null);
|
|
44192
44094
|
__privateAdd(this, _renderCamera, null);
|
|
44193
|
-
__privateAdd(this,
|
|
44194
|
-
__privateAdd(this,
|
|
44195
|
-
__privateAdd(this, _hasLastCameraPose, false);
|
|
44196
|
-
__privateAdd(this, _lastRootStates, /* @__PURE__ */ new Map());
|
|
44197
|
-
__privateAdd(this, _currentRootStates, /* @__PURE__ */ new Map());
|
|
44095
|
+
__privateAdd(this, _cameraWorldSnapshot, new Matrix4());
|
|
44096
|
+
__privateAdd(this, _lastXrHandledFrame, -1);
|
|
44198
44097
|
__privateAdd(this, _rebasedRootsPool, []);
|
|
44199
44098
|
__privateAdd(this, _rebasedRootsCount, 0);
|
|
44200
44099
|
__privateAdd(this, _hadRebasedLastFrame, false);
|
|
@@ -44203,56 +44102,64 @@ var init_dist = __esm({
|
|
|
44203
44102
|
};
|
|
44204
44103
|
}
|
|
44205
44104
|
onBeforeRender(renderer, scene, camera) {
|
|
44206
|
-
|
|
44207
|
-
const
|
|
44105
|
+
const xrPresenting = isXrPresenting(renderer);
|
|
44106
|
+
const updateSourceCamera = getUpdateSourceCamera(
|
|
44107
|
+
renderer,
|
|
44108
|
+
camera,
|
|
44109
|
+
xrPresenting
|
|
44110
|
+
);
|
|
44111
|
+
if (!xrPresenting) {
|
|
44112
|
+
camera.updateMatrixWorld(true);
|
|
44113
|
+
}
|
|
44114
|
+
const rebasedCount = __privateMethod(this, _CameraRelativeSparkRenderer_instances, rebaseCameraRelativeRoots_fn).call(this, scene, updateSourceCamera);
|
|
44208
44115
|
const hasRebased = rebasedCount > 0;
|
|
44116
|
+
const renderFrame = renderer.info.render.frame;
|
|
44117
|
+
const shouldHandleFrameState = !xrPresenting || __privateGet(this, _lastXrHandledFrame) !== renderFrame;
|
|
44209
44118
|
try {
|
|
44210
|
-
if (
|
|
44211
|
-
|
|
44119
|
+
if (shouldHandleFrameState) {
|
|
44120
|
+
__privateSet(this, _lastXrHandledFrame, renderFrame);
|
|
44121
|
+
}
|
|
44122
|
+
if ((hasRebased || __privateGet(this, _hadRebasedLastFrame)) && shouldHandleFrameState) {
|
|
44123
|
+
const updateCamera = __privateMethod(this, _CameraRelativeSparkRenderer_instances, getUpdateCamera_fn).call(this, updateSourceCamera);
|
|
44212
44124
|
const prevDisplay = this.display;
|
|
44213
44125
|
const prevCurrent = this.current;
|
|
44214
|
-
const cameraWorldSnapshot =
|
|
44215
|
-
|
|
44126
|
+
const cameraWorldSnapshot = __privateGet(this, _cameraWorldSnapshot).copy(
|
|
44127
|
+
updateSourceCamera.matrixWorld
|
|
44128
|
+
);
|
|
44129
|
+
void __privateMethod(this, _CameraRelativeSparkRenderer_instances, updateSparkIfNeeded_fn).call(this, {
|
|
44216
44130
|
scene,
|
|
44217
44131
|
camera: updateCamera
|
|
44132
|
+
}).catch((error) => {
|
|
44133
|
+
console.error(
|
|
44134
|
+
"CameraRelativeSparkRenderer: Spark update failed",
|
|
44135
|
+
error
|
|
44136
|
+
);
|
|
44218
44137
|
});
|
|
44219
|
-
const updateAccepted = this.current !== prevCurrent || this.display !== prevDisplay;
|
|
44220
44138
|
if (this.current !== prevCurrent) {
|
|
44221
44139
|
this.current.viewToWorld.copy(cameraWorldSnapshot);
|
|
44222
44140
|
}
|
|
44223
44141
|
if (this.display !== prevDisplay) {
|
|
44224
44142
|
this.display.viewToWorld.copy(cameraWorldSnapshot);
|
|
44225
44143
|
}
|
|
44226
|
-
if (updateAccepted) {
|
|
44227
|
-
__privateGet(this, _lastCameraPosition).copy(_cameraWorldPosition);
|
|
44228
|
-
__privateGet(this, _lastCameraDirection).copy(_cameraWorldDirection);
|
|
44229
|
-
__privateSet(this, _hasLastCameraPose, true);
|
|
44230
|
-
__privateSet(this, _lastRootStates, new Map(__privateGet(this, _currentRootStates)));
|
|
44231
|
-
}
|
|
44232
44144
|
}
|
|
44233
|
-
|
|
44145
|
+
if (shouldHandleFrameState) {
|
|
44146
|
+
__privateSet(this, _hadRebasedLastFrame, hasRebased);
|
|
44147
|
+
}
|
|
44234
44148
|
const renderCamera = hasRebased ? __privateMethod(this, _CameraRelativeSparkRenderer_instances, getRenderCamera_fn).call(this, camera) : camera;
|
|
44235
44149
|
super.onBeforeRender(renderer, scene, renderCamera);
|
|
44236
44150
|
} finally {
|
|
44237
44151
|
__privateMethod(this, _CameraRelativeSparkRenderer_instances, restoreCameraRelativeRoots_fn).call(this);
|
|
44238
44152
|
}
|
|
44239
44153
|
}
|
|
44240
|
-
}, _updateCamera = new WeakMap(), _renderCamera = new WeakMap(),
|
|
44241
|
-
|
|
44242
|
-
camera
|
|
44243
|
-
|
|
44244
|
-
|
|
44245
|
-
|
|
44246
|
-
|
|
44247
|
-
|
|
44248
|
-
|
|
44249
|
-
if (!areCameraRelativeRootStatesEqual(state, last.get(uuid))) {
|
|
44250
|
-
rootsChanged = true;
|
|
44251
|
-
break;
|
|
44252
|
-
}
|
|
44253
|
-
}
|
|
44254
|
-
}
|
|
44255
|
-
return poseChanged || rootsChanged;
|
|
44154
|
+
}, _updateCamera = new WeakMap(), _renderCamera = new WeakMap(), _cameraWorldSnapshot = new WeakMap(), _lastXrHandledFrame = new WeakMap(), _rebasedRootsPool = new WeakMap(), _rebasedRootsCount = new WeakMap(), _hadRebasedLastFrame = new WeakMap(), _CameraRelativeSparkRenderer_instances = new WeakSet(), updateSparkIfNeeded_fn = function({
|
|
44155
|
+
scene,
|
|
44156
|
+
camera
|
|
44157
|
+
}) {
|
|
44158
|
+
return this.updateInternal({
|
|
44159
|
+
scene,
|
|
44160
|
+
camera,
|
|
44161
|
+
autoUpdate: true
|
|
44162
|
+
});
|
|
44256
44163
|
}, /**
|
|
44257
44164
|
* Identity camera for the update pass - makes Spark treat
|
|
44258
44165
|
* the camera's own frame as the reference frame.
|
|
@@ -44291,55 +44198,63 @@ var init_dist = __esm({
|
|
|
44291
44198
|
return renderCamera;
|
|
44292
44199
|
}, rebaseCameraRelativeRoots_fn = function(scene, camera) {
|
|
44293
44200
|
__privateSet(this, _rebasedRootsCount, 0);
|
|
44294
|
-
__privateGet(this, _currentRootStates).clear();
|
|
44295
44201
|
_cameraInverseWorldMatrix.copy(camera.matrixWorld).invert();
|
|
44296
|
-
|
|
44297
|
-
if (!isCameraRelativeNode(node)) {
|
|
44298
|
-
return;
|
|
44299
|
-
}
|
|
44300
|
-
__privateGet(this, _currentRootStates).set(
|
|
44301
|
-
node.uuid,
|
|
44302
|
-
cloneCameraRelativeRootSnapshot(node)
|
|
44303
|
-
);
|
|
44304
|
-
if (hasCameraRelativeRootAncestor(node)) {
|
|
44305
|
-
return;
|
|
44306
|
-
}
|
|
44307
|
-
const idx = __privateWrapper(this, _rebasedRootsCount)._++;
|
|
44308
|
-
const pool = __privateGet(this, _rebasedRootsPool);
|
|
44309
|
-
if (idx >= pool.length) {
|
|
44310
|
-
pool.push({
|
|
44311
|
-
target: node,
|
|
44312
|
-
originalMatrix: node.matrix.clone(),
|
|
44313
|
-
originalMatrixAutoUpdate: node.matrixAutoUpdate
|
|
44314
|
-
});
|
|
44315
|
-
} else {
|
|
44316
|
-
const entry = pool[idx];
|
|
44317
|
-
entry.target = node;
|
|
44318
|
-
entry.originalMatrix.copy(node.matrix);
|
|
44319
|
-
entry.originalMatrixAutoUpdate = node.matrixAutoUpdate;
|
|
44320
|
-
}
|
|
44321
|
-
const parent2 = node.parent;
|
|
44322
|
-
if (!parent2 || parent2 === scene) {
|
|
44323
|
-
_rebasedLocalMatrix.copy(_cameraInverseWorldMatrix).multiply(node.matrixWorld);
|
|
44324
|
-
} else {
|
|
44325
|
-
_rebasedLocalMatrix.copy(_parentInverseWorldMatrix.copy(parent2.matrixWorld).invert()).multiply(_cameraInverseWorldMatrix).multiply(node.matrixWorld);
|
|
44326
|
-
}
|
|
44327
|
-
node.matrixAutoUpdate = false;
|
|
44328
|
-
node.matrix.copy(_rebasedLocalMatrix);
|
|
44329
|
-
node.matrixWorldNeedsUpdate = true;
|
|
44330
|
-
node.updateMatrixWorld(true);
|
|
44331
|
-
});
|
|
44202
|
+
__privateMethod(this, _CameraRelativeSparkRenderer_instances, visitVisibleCameraRelativeRoots_fn).call(this, scene, scene, false, false);
|
|
44332
44203
|
return __privateGet(this, _rebasedRootsCount);
|
|
44204
|
+
}, visitVisibleCameraRelativeRoots_fn = function(node, scene, hasGaussianSplatAncestor, hasCameraRelativeAncestor) {
|
|
44205
|
+
if (!node.visible) {
|
|
44206
|
+
return;
|
|
44207
|
+
}
|
|
44208
|
+
const isSplatNode = isGaussianSplatNode(node);
|
|
44209
|
+
const isCameraRelativeNode = isSplatNode || isCameraRelativeEdit(node, hasGaussianSplatAncestor);
|
|
44210
|
+
if (isCameraRelativeNode && !hasCameraRelativeAncestor) {
|
|
44211
|
+
__privateMethod(this, _CameraRelativeSparkRenderer_instances, rebaseCameraRelativeRoot_fn).call(this, node);
|
|
44212
|
+
}
|
|
44213
|
+
const nextHasGaussianSplatAncestor = hasGaussianSplatAncestor || isSplatNode;
|
|
44214
|
+
const nextHasCameraRelativeAncestor = hasCameraRelativeAncestor || isCameraRelativeNode;
|
|
44215
|
+
const { children } = node;
|
|
44216
|
+
for (let i = 0, l = children.length; i < l; i++) {
|
|
44217
|
+
__privateMethod(this, _CameraRelativeSparkRenderer_instances, visitVisibleCameraRelativeRoots_fn).call(this, children[i], scene, nextHasGaussianSplatAncestor, nextHasCameraRelativeAncestor);
|
|
44218
|
+
}
|
|
44219
|
+
}, rebaseCameraRelativeRoot_fn = function(node) {
|
|
44220
|
+
const idx = __privateWrapper(this, _rebasedRootsCount)._++;
|
|
44221
|
+
const pool = __privateGet(this, _rebasedRootsPool);
|
|
44222
|
+
if (idx >= pool.length) {
|
|
44223
|
+
pool.push({
|
|
44224
|
+
target: node,
|
|
44225
|
+
originalMatrix: node.matrix.clone(),
|
|
44226
|
+
originalMatrixAutoUpdate: node.matrixAutoUpdate
|
|
44227
|
+
});
|
|
44228
|
+
} else {
|
|
44229
|
+
const entry = pool[idx];
|
|
44230
|
+
entry.target = node;
|
|
44231
|
+
entry.originalMatrix.copy(node.matrix);
|
|
44232
|
+
entry.originalMatrixAutoUpdate = node.matrixAutoUpdate;
|
|
44233
|
+
}
|
|
44234
|
+
const parent2 = node.parent;
|
|
44235
|
+
if (!parent2) {
|
|
44236
|
+
_rebasedLocalMatrix.copy(_cameraInverseWorldMatrix).multiply(node.matrixWorld);
|
|
44237
|
+
} else {
|
|
44238
|
+
_rebasedLocalMatrix.copy(_parentInverseWorldMatrix.copy(parent2.matrixWorld).invert()).multiply(_cameraInverseWorldMatrix).multiply(node.matrixWorld);
|
|
44239
|
+
}
|
|
44240
|
+
node.matrixAutoUpdate = false;
|
|
44241
|
+
node.matrix.copy(_rebasedLocalMatrix);
|
|
44242
|
+
node.matrixWorldNeedsUpdate = true;
|
|
44243
|
+
node.updateMatrixWorld(true);
|
|
44333
44244
|
}, restoreCameraRelativeRoots_fn = function() {
|
|
44334
44245
|
const pool = __privateGet(this, _rebasedRootsPool);
|
|
44335
44246
|
for (let i = __privateGet(this, _rebasedRootsCount) - 1; i >= 0; i--) {
|
|
44336
44247
|
const { target, originalMatrix, originalMatrixAutoUpdate } = pool[i];
|
|
44248
|
+
if (!target) continue;
|
|
44337
44249
|
target.matrix.copy(originalMatrix);
|
|
44338
44250
|
target.matrixAutoUpdate = originalMatrixAutoUpdate;
|
|
44339
44251
|
target.matrixWorldNeedsUpdate = true;
|
|
44340
44252
|
}
|
|
44341
44253
|
for (let i = 0; i < __privateGet(this, _rebasedRootsCount); i++) {
|
|
44342
|
-
pool[i].target
|
|
44254
|
+
pool[i].target?.updateMatrixWorld(true);
|
|
44255
|
+
}
|
|
44256
|
+
for (let i = __privateGet(this, _rebasedRootsCount); i < pool.length; i++) {
|
|
44257
|
+
pool[i].target = null;
|
|
44343
44258
|
}
|
|
44344
44259
|
}, _a2);
|
|
44345
44260
|
_sharedSparkManagersByScene = /* @__PURE__ */ new WeakMap();
|
|
@@ -45373,6 +45288,9 @@ function createGeometricErrorController({
|
|
|
45373
45288
|
getTiles
|
|
45374
45289
|
}) {
|
|
45375
45290
|
const originalTileGeometricErrors = /* @__PURE__ */ new WeakMap();
|
|
45291
|
+
let knownTileChildCounts = /* @__PURE__ */ new WeakMap();
|
|
45292
|
+
let cachedGlobalLeafGeometricError = null;
|
|
45293
|
+
let cachedGlobalLeafGeometricErrorRoot = null;
|
|
45376
45294
|
let geometricErrorScaleExponent = 0;
|
|
45377
45295
|
let geometricErrorScale = 1;
|
|
45378
45296
|
let lastSavedGeometricErrorScale = 1;
|
|
@@ -45385,6 +45303,39 @@ function createGeometricErrorController({
|
|
|
45385
45303
|
function getEffectiveGeometricErrorLayerScale() {
|
|
45386
45304
|
return lastSavedGeometricErrorLayerScale * geometricErrorLayerScale;
|
|
45387
45305
|
}
|
|
45306
|
+
function getTilesRoot() {
|
|
45307
|
+
return getTiles()?.root || null;
|
|
45308
|
+
}
|
|
45309
|
+
function getCachedGlobalLeafGeometricError() {
|
|
45310
|
+
const root = getTilesRoot();
|
|
45311
|
+
if (cachedGlobalLeafGeometricErrorRoot !== root) {
|
|
45312
|
+
cachedGlobalLeafGeometricErrorRoot = root;
|
|
45313
|
+
cachedGlobalLeafGeometricError = null;
|
|
45314
|
+
knownTileChildCounts = /* @__PURE__ */ new WeakMap();
|
|
45315
|
+
}
|
|
45316
|
+
return cachedGlobalLeafGeometricError;
|
|
45317
|
+
}
|
|
45318
|
+
function setCachedGlobalLeafGeometricError(leafGeometricError) {
|
|
45319
|
+
cachedGlobalLeafGeometricErrorRoot = getTilesRoot();
|
|
45320
|
+
cachedGlobalLeafGeometricError = leafGeometricError;
|
|
45321
|
+
}
|
|
45322
|
+
function clearCachedGlobalLeafGeometricError() {
|
|
45323
|
+
cachedGlobalLeafGeometricError = null;
|
|
45324
|
+
}
|
|
45325
|
+
function trackTileChildCount(tile, children) {
|
|
45326
|
+
knownTileChildCounts.set(tile, children.length);
|
|
45327
|
+
}
|
|
45328
|
+
function invalidateLeafCacheIfParentChildrenChanged(parentTile) {
|
|
45329
|
+
if (!parentTile || typeof parentTile !== "object") {
|
|
45330
|
+
return;
|
|
45331
|
+
}
|
|
45332
|
+
const children = Array.isArray(parentTile.children) ? parentTile.children : [];
|
|
45333
|
+
const knownChildCount = knownTileChildCounts.get(parentTile);
|
|
45334
|
+
if (cachedGlobalLeafGeometricError !== null && knownChildCount !== children.length) {
|
|
45335
|
+
clearCachedGlobalLeafGeometricError();
|
|
45336
|
+
}
|
|
45337
|
+
trackTileChildCount(parentTile, children);
|
|
45338
|
+
}
|
|
45388
45339
|
function updateTilesetErrorTarget() {
|
|
45389
45340
|
const tiles = getTiles();
|
|
45390
45341
|
if (!tiles) {
|
|
@@ -45423,6 +45374,7 @@ function createGeometricErrorController({
|
|
|
45423
45374
|
visited.add(tile);
|
|
45424
45375
|
let leafGeometricError = null;
|
|
45425
45376
|
const children = Array.isArray(tile.children) ? tile.children : [];
|
|
45377
|
+
trackTileChildCount(tile, children);
|
|
45426
45378
|
for (const child of children) {
|
|
45427
45379
|
const childLeafGeometricError = getKnownTileLeafGeometricError(
|
|
45428
45380
|
child,
|
|
@@ -45435,31 +45387,58 @@ function createGeometricErrorController({
|
|
|
45435
45387
|
visited.delete(tile);
|
|
45436
45388
|
return leafGeometricError === null ? originalGeometricError : leafGeometricError;
|
|
45437
45389
|
}
|
|
45438
|
-
function getGlobalTileLeafGeometricError(tile) {
|
|
45390
|
+
function getGlobalTileLeafGeometricError(tile, { forceRefresh = false } = {}) {
|
|
45391
|
+
if (!forceRefresh) {
|
|
45392
|
+
const cachedLeafGeometricError = getCachedGlobalLeafGeometricError();
|
|
45393
|
+
if (cachedLeafGeometricError !== null) {
|
|
45394
|
+
return cachedLeafGeometricError;
|
|
45395
|
+
}
|
|
45396
|
+
}
|
|
45439
45397
|
const tiles = getTiles();
|
|
45440
45398
|
const rootLeafGeometricError = tiles?.root ? getKnownTileLeafGeometricError(tiles.root) : null;
|
|
45399
|
+
if (tiles?.root && tile === tiles.root) {
|
|
45400
|
+
setCachedGlobalLeafGeometricError(rootLeafGeometricError);
|
|
45401
|
+
return rootLeafGeometricError;
|
|
45402
|
+
}
|
|
45441
45403
|
const tileLeafGeometricError = getKnownTileLeafGeometricError(tile);
|
|
45404
|
+
let leafGeometricError = null;
|
|
45442
45405
|
if (rootLeafGeometricError === null) {
|
|
45443
|
-
|
|
45444
|
-
}
|
|
45445
|
-
|
|
45446
|
-
|
|
45406
|
+
leafGeometricError = tileLeafGeometricError;
|
|
45407
|
+
} else if (tileLeafGeometricError === null) {
|
|
45408
|
+
leafGeometricError = rootLeafGeometricError;
|
|
45409
|
+
} else {
|
|
45410
|
+
leafGeometricError = Math.min(
|
|
45411
|
+
rootLeafGeometricError,
|
|
45412
|
+
tileLeafGeometricError
|
|
45413
|
+
);
|
|
45447
45414
|
}
|
|
45448
|
-
|
|
45415
|
+
setCachedGlobalLeafGeometricError(leafGeometricError);
|
|
45416
|
+
return leafGeometricError;
|
|
45449
45417
|
}
|
|
45450
|
-
function applyLayerScaleToTile(tile, leafGeometricError =
|
|
45418
|
+
function applyLayerScaleToTile(tile, leafGeometricError = null, parentTile = null) {
|
|
45419
|
+
invalidateLeafCacheIfParentChildrenChanged(parentTile);
|
|
45451
45420
|
const originalGeometricError = getOriginalTileGeometricError(tile);
|
|
45452
|
-
if (originalGeometricError === null
|
|
45421
|
+
if (originalGeometricError === null) {
|
|
45422
|
+
return;
|
|
45423
|
+
}
|
|
45424
|
+
const layerScale = getEffectiveGeometricErrorLayerScale();
|
|
45425
|
+
if (layerScale === 1) {
|
|
45426
|
+
tile.geometricError = originalGeometricError;
|
|
45427
|
+
return;
|
|
45428
|
+
}
|
|
45429
|
+
const effectiveLeafGeometricError = leafGeometricError ?? getGlobalTileLeafGeometricError(tile);
|
|
45430
|
+
if (effectiveLeafGeometricError === null) {
|
|
45453
45431
|
return;
|
|
45454
45432
|
}
|
|
45455
|
-
tile.geometricError =
|
|
45433
|
+
tile.geometricError = effectiveLeafGeometricError + (originalGeometricError - effectiveLeafGeometricError) * layerScale;
|
|
45456
45434
|
}
|
|
45457
45435
|
function applyLayerScaleToTileset() {
|
|
45458
45436
|
const tiles = getTiles();
|
|
45459
45437
|
if (!tiles) {
|
|
45460
45438
|
return;
|
|
45461
45439
|
}
|
|
45462
|
-
const
|
|
45440
|
+
const layerScale = getEffectiveGeometricErrorLayerScale();
|
|
45441
|
+
const leafGeometricError = layerScale === 1 ? null : getGlobalTileLeafGeometricError(tiles.root, { forceRefresh: true });
|
|
45463
45442
|
tiles.traverse(
|
|
45464
45443
|
(tile) => {
|
|
45465
45444
|
applyLayerScaleToTile(tile, leafGeometricError);
|
|
@@ -63334,8 +63313,8 @@ function createTerrainGlobeTiles(options) {
|
|
|
63334
63313
|
function createGeometricErrorLayerScalePlugin(preprocessNode) {
|
|
63335
63314
|
return {
|
|
63336
63315
|
name: "GeometricErrorLayerScalePlugin",
|
|
63337
|
-
preprocessNode(tile) {
|
|
63338
|
-
preprocessNode(tile);
|
|
63316
|
+
preprocessNode(tile, tilesetDir, parentTile) {
|
|
63317
|
+
preprocessNode(tile, null, parentTile);
|
|
63339
63318
|
}
|
|
63340
63319
|
};
|
|
63341
63320
|
}
|
|
@@ -71652,10 +71631,11 @@ var require_app = __commonJS({
|
|
|
71652
71631
|
const processedSplatResources = Number(
|
|
71653
71632
|
payload.processedSplatResources || 0
|
|
71654
71633
|
);
|
|
71634
|
+
const deletedSplatFiles = Number(payload.deletedSplatFiles || 0);
|
|
71655
71635
|
cropController.clearAll();
|
|
71656
71636
|
loadTileset(TILESET_URL, { frameOnLoad: false });
|
|
71657
71637
|
setStatus(
|
|
71658
|
-
`Saved transform and deleted ${deletedSplats} cropped splats from ${processedSplatResources} splat resource${processedSplatResources === 1 ? "" : "s"}. Reloading tileset.`
|
|
71638
|
+
`Saved transform and deleted ${deletedSplats} cropped splats from ${processedSplatResources} splat resource${processedSplatResources === 1 ? "" : "s"}${deletedSplatFiles > 0 ? `, removing ${deletedSplatFiles} orphaned file${deletedSplatFiles === 1 ? "" : "s"}` : ""}. Reloading tileset.`
|
|
71659
71639
|
);
|
|
71660
71640
|
} else {
|
|
71661
71641
|
setStatus(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "3dtiles-inspector",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Inspect, align, and save local 3D Tiles root transforms in an interactive browser session.",
|
|
5
5
|
"author": "William Liu <lyz15972107087@gmail.com>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"3d-tiles-renderer": "0.4.24",
|
|
58
|
-
"3d-tiles-rendererjs-3dgs-plugin": "0.1.
|
|
58
|
+
"3d-tiles-rendererjs-3dgs-plugin": "0.1.7",
|
|
59
59
|
"cesium": "1.140.0",
|
|
60
60
|
"esbuild": "^0.25.11"
|
|
61
61
|
},
|
|
@@ -471,6 +471,8 @@ async function saveViewerTransform(
|
|
|
471
471
|
return {
|
|
472
472
|
transform: nextRoot,
|
|
473
473
|
deletedSplats: cropResult.deletedSplats,
|
|
474
|
+
deletedSplatFiles: cropResult.deletedSplatFiles,
|
|
475
|
+
failedSplatFileDeletes: cropResult.failedSplatFileDeletes,
|
|
474
476
|
processedSplatResources: cropResult.processedSplatResources,
|
|
475
477
|
};
|
|
476
478
|
}
|
|
@@ -23,6 +23,8 @@ function createSaveTransformResponsePayload(
|
|
|
23
23
|
transform: saveResult.transform,
|
|
24
24
|
geometricErrorLayerScale: normalizedGeometricErrorLayerScale,
|
|
25
25
|
geometricErrorScale: normalizedGeometricErrorScale,
|
|
26
|
+
deletedSplatFiles: saveResult.deletedSplatFiles,
|
|
27
|
+
failedSplatFileDeletes: saveResult.failedSplatFileDeletes,
|
|
26
28
|
deletedSplats: saveResult.deletedSplats,
|
|
27
29
|
processedSplatResources: saveResult.processedSplatResources,
|
|
28
30
|
};
|
|
@@ -239,6 +239,53 @@ function removeMeshPrimitives(resource, descriptors) {
|
|
|
239
239
|
return removed;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
function updateGaussianPrimitiveAccessorCounts(resource, descriptors, count) {
|
|
243
|
+
if (!Number.isInteger(count) || count < 0) {
|
|
244
|
+
throw new InspectorError('Gaussian accessor count must be a non-negative integer.');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const updatedAccessors = new Set();
|
|
248
|
+
descriptors.forEach((descriptor) => {
|
|
249
|
+
if (
|
|
250
|
+
!Number.isInteger(descriptor.meshIndex) ||
|
|
251
|
+
!Number.isInteger(descriptor.primitiveIndex)
|
|
252
|
+
) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const primitive =
|
|
257
|
+
resource.json.meshes?.[descriptor.meshIndex]?.primitives?.[
|
|
258
|
+
descriptor.primitiveIndex
|
|
259
|
+
];
|
|
260
|
+
const attributes = primitive?.attributes;
|
|
261
|
+
if (!attributes || typeof attributes !== 'object') {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
Object.values(attributes).forEach((accessorIndex) => {
|
|
266
|
+
if (
|
|
267
|
+
!Number.isInteger(accessorIndex) ||
|
|
268
|
+
accessorIndex < 0 ||
|
|
269
|
+
accessorIndex >= (resource.json.accessors?.length || 0)
|
|
270
|
+
) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const accessor = resource.json.accessors[accessorIndex];
|
|
275
|
+
if (!accessor || typeof accessor !== 'object') {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (accessor.count !== count) {
|
|
280
|
+
accessor.count = count;
|
|
281
|
+
updatedAccessors.add(accessorIndex);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
return updatedAccessors.size;
|
|
287
|
+
}
|
|
288
|
+
|
|
242
289
|
module.exports = {
|
|
243
290
|
collectGaussianPrimitiveDescriptors,
|
|
244
291
|
getRootUpRotationMatrix,
|
|
@@ -247,4 +294,5 @@ module.exports = {
|
|
|
247
294
|
hasNonGaussianScenePrimitives,
|
|
248
295
|
hasScenePrimitives,
|
|
249
296
|
removeMeshPrimitives,
|
|
297
|
+
updateGaussianPrimitiveAccessorCounts,
|
|
250
298
|
};
|
|
@@ -70,7 +70,7 @@ function parseGlb(filePath) {
|
|
|
70
70
|
if (chunkType === GLB_JSON_CHUNK_TYPE) {
|
|
71
71
|
json = JSON.parse(chunk.toString('utf8').replace(/\0+$/g, '').trimEnd());
|
|
72
72
|
} else if (chunkType === GLB_BIN_CHUNK_TYPE && !bin) {
|
|
73
|
-
bin =
|
|
73
|
+
bin = chunk;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
offset = chunkEnd;
|
|
@@ -190,7 +190,7 @@ function loadResourceBuffer(resource, bufferIndex) {
|
|
|
190
190
|
`${resource.filePath}.buffers[${bufferIndex}].uri`,
|
|
191
191
|
);
|
|
192
192
|
resource.dataUriMetadata.set(bufferIndex, metadata);
|
|
193
|
-
record = { bytes
|
|
193
|
+
record = { bytes, dataUri: true };
|
|
194
194
|
} else {
|
|
195
195
|
const bufferPath = resolveLocalUri(
|
|
196
196
|
path.dirname(resource.filePath),
|
|
@@ -205,7 +205,7 @@ function loadResourceBuffer(resource, bufferIndex) {
|
|
|
205
205
|
}
|
|
206
206
|
} else if (resource.type === 'glb' && bufferIndex === 0) {
|
|
207
207
|
record = {
|
|
208
|
-
bytes:
|
|
208
|
+
bytes: resource.embeddedBin || Buffer.alloc(0),
|
|
209
209
|
embedded: true,
|
|
210
210
|
};
|
|
211
211
|
} else {
|
|
@@ -322,7 +322,7 @@ function applyBufferReplacements(resource, bufferIndex, replacements) {
|
|
|
322
322
|
|
|
323
323
|
replacements.forEach((replacement) => {
|
|
324
324
|
parts.push(record.bytes.subarray(cursor, replacement.start));
|
|
325
|
-
parts.push(
|
|
325
|
+
parts.push(replacement.bytes);
|
|
326
326
|
cursor = replacement.end;
|
|
327
327
|
});
|
|
328
328
|
|