3dtiles-inspector 0.2.13 → 0.2.15
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 +25 -0
- package/README.md +11 -4
- package/dist/inspector-assets/viewer/app.js +4673 -787
- package/package.json +3 -3
- package/src/server/splatCrop/gaussianPrimitives.js +37 -7
- package/src/server/splatCrop/index.js +10 -2
- package/src/server/splatCrop/normalize.js +43 -6
- package/src/server/splatCrop/traversal.js +162 -0
- package/src/server/splatCrop/worker.js +43 -8
- package/src/server/splatCrop/workerPool.js +2 -0
- package/src/server/viewerHtml.js +54 -10
- package/src/viewer/app.js +16 -1
- package/src/viewer/dom/cropUi.js +50 -0
- package/src/viewer/dom/elements.js +8 -0
- package/src/viewer/dom/events.js +63 -0
- package/src/viewer/scene/cameraController.js +18 -3
- package/src/viewer/screenSelection/cropController.js +578 -6
- package/src/viewer/screenSelection/index.js +15 -2
- package/src/viewer/screenSelection/sdf.js +51 -6
- package/src/viewer/screenSelection/state.js +1 -0
- package/src/viewer/transform/geoCamera.js +1 -1
- package/src/viewer/transform/transformModeController.js +19 -2
package/src/viewer/dom/cropUi.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export function updateCropControls({
|
|
2
2
|
activeScreenSelectionId,
|
|
3
3
|
elements,
|
|
4
|
+
keepSphere,
|
|
5
|
+
onKeepSphereRemove,
|
|
6
|
+
onKeepSphereSelect,
|
|
4
7
|
onScreenSelectionRemove,
|
|
5
8
|
onScreenSelectionSelect,
|
|
6
9
|
pendingScreenSelectionMode,
|
|
@@ -14,8 +17,16 @@ export function updateCropControls({
|
|
|
14
17
|
cropScreenCancelButton,
|
|
15
18
|
cropScreenConfirmButton,
|
|
16
19
|
cropScreenSelectButton,
|
|
20
|
+
keepSphereCancelButton,
|
|
21
|
+
keepSphereConfirmButton,
|
|
22
|
+
keepSphereCreateButton,
|
|
23
|
+
keepSphereListEl,
|
|
24
|
+
keepSphereRadiusTrackEl,
|
|
25
|
+
keepSphereRadiusValueEl,
|
|
17
26
|
} = elements;
|
|
18
27
|
const hasPendingScreenSelection = pendingScreenSelections.length > 0;
|
|
28
|
+
const hasKeepSphere = !!keepSphere;
|
|
29
|
+
const hasPendingKeepSphere = hasKeepSphere && !keepSphere.confirmed;
|
|
19
30
|
|
|
20
31
|
cropScreenSelectButton.disabled =
|
|
21
32
|
!tilesetHasGaussianSplats || hasPendingScreenSelection;
|
|
@@ -28,6 +39,33 @@ export function updateCropControls({
|
|
|
28
39
|
cropCountValueEl.textContent = String(
|
|
29
40
|
screenSelections.length + pendingScreenSelections.length,
|
|
30
41
|
);
|
|
42
|
+
keepSphereCreateButton.disabled =
|
|
43
|
+
!tilesetHasGaussianSplats || hasKeepSphere;
|
|
44
|
+
keepSphereConfirmButton.disabled =
|
|
45
|
+
!tilesetHasGaussianSplats || !hasPendingKeepSphere;
|
|
46
|
+
keepSphereCancelButton.disabled =
|
|
47
|
+
!tilesetHasGaussianSplats || !hasPendingKeepSphere;
|
|
48
|
+
keepSphereRadiusTrackEl.classList.toggle('disabled', !hasKeepSphere);
|
|
49
|
+
keepSphereRadiusTrackEl.setAttribute(
|
|
50
|
+
'aria-disabled',
|
|
51
|
+
hasKeepSphere ? 'false' : 'true',
|
|
52
|
+
);
|
|
53
|
+
keepSphereRadiusValueEl.textContent = hasKeepSphere
|
|
54
|
+
? formatRadius(keepSphere.worldRadius)
|
|
55
|
+
: 'None';
|
|
56
|
+
|
|
57
|
+
keepSphereListEl.replaceChildren();
|
|
58
|
+
if (hasKeepSphere) {
|
|
59
|
+
keepSphereListEl.appendChild(
|
|
60
|
+
createSelectionControl({
|
|
61
|
+
active: keepSphere.id === activeScreenSelectionId,
|
|
62
|
+
label: keepSphere.confirmed ? 'Crop Sphere' : 'Pending',
|
|
63
|
+
onScreenSelectionRemove: onKeepSphereRemove,
|
|
64
|
+
onScreenSelectionSelect: onKeepSphereSelect,
|
|
65
|
+
selection: keepSphere,
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
31
69
|
|
|
32
70
|
cropListEl.replaceChildren();
|
|
33
71
|
pendingScreenSelections.forEach((selection) => {
|
|
@@ -57,6 +95,18 @@ export function updateCropControls({
|
|
|
57
95
|
});
|
|
58
96
|
}
|
|
59
97
|
|
|
98
|
+
function formatRadius(radius) {
|
|
99
|
+
const value = Number(radius);
|
|
100
|
+
if (!Number.isFinite(value)) {
|
|
101
|
+
return 'None';
|
|
102
|
+
}
|
|
103
|
+
const abs = Math.abs(value);
|
|
104
|
+
if (abs > 0 && (abs < 0.001 || abs >= 1000000)) {
|
|
105
|
+
return value.toExponential(3).replace(/\.?0+e/, 'e');
|
|
106
|
+
}
|
|
107
|
+
return (abs < 1 ? value.toFixed(3) : value.toFixed(2)).replace(/\.?0+$/, '');
|
|
108
|
+
}
|
|
109
|
+
|
|
60
110
|
function createSelectionControl({
|
|
61
111
|
active,
|
|
62
112
|
label,
|
|
@@ -11,6 +11,14 @@ export function getViewerElements() {
|
|
|
11
11
|
cropScreenCancelButton: document.getElementById('crop-screen-cancel'),
|
|
12
12
|
cropScreenConfirmButton: document.getElementById('crop-screen-confirm'),
|
|
13
13
|
cropScreenSelectButton: document.getElementById('crop-screen-select'),
|
|
14
|
+
keepSphereCancelButton: document.getElementById('keep-sphere-cancel'),
|
|
15
|
+
keepSphereConfirmButton: document.getElementById('keep-sphere-confirm'),
|
|
16
|
+
keepSphereCreateButton: document.getElementById('keep-sphere-create'),
|
|
17
|
+
keepSphereListEl: document.getElementById('keep-sphere-list'),
|
|
18
|
+
keepSphereRadiusTrackEl: document.getElementById('keep-sphere-radius'),
|
|
19
|
+
keepSphereRadiusValueEl: document.getElementById(
|
|
20
|
+
'keep-sphere-radius-value',
|
|
21
|
+
),
|
|
14
22
|
geometricErrorLayerScaleInput: document.getElementById(
|
|
15
23
|
'geometric-error-layer-scale',
|
|
16
24
|
),
|
package/src/viewer/dom/events.js
CHANGED
|
@@ -19,6 +19,10 @@ export function bindViewerEvents({
|
|
|
19
19
|
cropScreenCancelButton,
|
|
20
20
|
cropScreenConfirmButton,
|
|
21
21
|
cropScreenSelectButton,
|
|
22
|
+
keepSphereCancelButton,
|
|
23
|
+
keepSphereConfirmButton,
|
|
24
|
+
keepSphereCreateButton,
|
|
25
|
+
keepSphereRadiusTrackEl,
|
|
22
26
|
geometricErrorLayerScaleInput,
|
|
23
27
|
geometricErrorScaleInput,
|
|
24
28
|
moveCameraToCoordinateButton,
|
|
@@ -36,6 +40,7 @@ export function bindViewerEvents({
|
|
|
36
40
|
} = elements;
|
|
37
41
|
|
|
38
42
|
let uniformScaleTrackPointerId = null;
|
|
43
|
+
let keepSphereRadiusTrackPointerId = null;
|
|
39
44
|
|
|
40
45
|
function setUniformScaleStatus() {
|
|
41
46
|
setStatus(
|
|
@@ -151,6 +156,64 @@ export function bindViewerEvents({
|
|
|
151
156
|
'click',
|
|
152
157
|
handlers.cancelCropScreenSelection,
|
|
153
158
|
);
|
|
159
|
+
keepSphereCreateButton.addEventListener('click', handlers.createKeepSphere);
|
|
160
|
+
keepSphereConfirmButton.addEventListener('click', handlers.confirmKeepSphere);
|
|
161
|
+
keepSphereCancelButton.addEventListener('click', handlers.cancelKeepSphere);
|
|
162
|
+
keepSphereRadiusTrackEl.addEventListener('pointerdown', (event) => {
|
|
163
|
+
if (event.button !== 0 || keepSphereRadiusTrackEl.classList.contains('disabled')) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
event.preventDefault();
|
|
168
|
+
keepSphereRadiusTrackPointerId = event.pointerId;
|
|
169
|
+
keepSphereRadiusTrackEl.focus();
|
|
170
|
+
keepSphereRadiusTrackEl.classList.add('dragging');
|
|
171
|
+
keepSphereRadiusTrackEl.setPointerCapture(event.pointerId);
|
|
172
|
+
handlers.beginKeepSphereRadiusTrackDrag(event.clientX);
|
|
173
|
+
});
|
|
174
|
+
keepSphereRadiusTrackEl.addEventListener('pointermove', (event) => {
|
|
175
|
+
if (event.pointerId !== keepSphereRadiusTrackPointerId) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
handlers.setKeepSphereRadiusFromTrackClientX(event.clientX);
|
|
180
|
+
});
|
|
181
|
+
keepSphereRadiusTrackEl.addEventListener('pointerup', (event) => {
|
|
182
|
+
if (event.pointerId !== keepSphereRadiusTrackPointerId) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
keepSphereRadiusTrackPointerId = null;
|
|
187
|
+
keepSphereRadiusTrackEl.classList.remove('dragging');
|
|
188
|
+
keepSphereRadiusTrackEl.releasePointerCapture(event.pointerId);
|
|
189
|
+
handlers.endKeepSphereRadiusTrackDrag({ commit: true });
|
|
190
|
+
});
|
|
191
|
+
keepSphereRadiusTrackEl.addEventListener('pointercancel', (event) => {
|
|
192
|
+
if (event.pointerId !== keepSphereRadiusTrackPointerId) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
keepSphereRadiusTrackPointerId = null;
|
|
197
|
+
keepSphereRadiusTrackEl.classList.remove('dragging');
|
|
198
|
+
keepSphereRadiusTrackEl.releasePointerCapture(event.pointerId);
|
|
199
|
+
handlers.endKeepSphereRadiusTrackDrag();
|
|
200
|
+
});
|
|
201
|
+
keepSphereRadiusTrackEl.addEventListener('keydown', (event) => {
|
|
202
|
+
let handled = true;
|
|
203
|
+
const step = event.shiftKey ? 1 : 0.1;
|
|
204
|
+
|
|
205
|
+
if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') {
|
|
206
|
+
handlers.nudgeKeepSphereRadiusExponent(-step);
|
|
207
|
+
} else if (event.key === 'ArrowRight' || event.key === 'ArrowUp') {
|
|
208
|
+
handlers.nudgeKeepSphereRadiusExponent(step);
|
|
209
|
+
} else {
|
|
210
|
+
handled = false;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (handled) {
|
|
214
|
+
event.preventDefault();
|
|
215
|
+
}
|
|
216
|
+
});
|
|
154
217
|
toolbarToggleButton.addEventListener(
|
|
155
218
|
'click',
|
|
156
219
|
handlers.toggleToolbarVisibility,
|
|
@@ -380,6 +380,7 @@ class CameraController extends EventDispatcher {
|
|
|
380
380
|
#lastTime;
|
|
381
381
|
#hit;
|
|
382
382
|
#pointerDownFilter;
|
|
383
|
+
#raycastHitFilter;
|
|
383
384
|
#zoomTimeout;
|
|
384
385
|
constructor(renderer, scene, camera, options = {}) {
|
|
385
386
|
super();
|
|
@@ -417,6 +418,10 @@ class CameraController extends EventDispatcher {
|
|
|
417
418
|
typeof options.pointerDownFilter === 'function'
|
|
418
419
|
? options.pointerDownFilter
|
|
419
420
|
: null;
|
|
421
|
+
this.#raycastHitFilter =
|
|
422
|
+
typeof options.raycastHitFilter === 'function'
|
|
423
|
+
? options.raycastHitFilter
|
|
424
|
+
: null;
|
|
420
425
|
this.#zoomTimeout = null;
|
|
421
426
|
this.init();
|
|
422
427
|
}
|
|
@@ -483,6 +488,10 @@ class CameraController extends EventDispatcher {
|
|
|
483
488
|
this.#resetState();
|
|
484
489
|
this.#pointerTracker.reset();
|
|
485
490
|
}
|
|
491
|
+
setRaycastHitFilter(filter) {
|
|
492
|
+
this.#raycastHitFilter = typeof filter === 'function' ? filter : null;
|
|
493
|
+
this.#resetState();
|
|
494
|
+
}
|
|
486
495
|
init() {
|
|
487
496
|
this.#domElement.style.touchAction = 'none';
|
|
488
497
|
this.#pivotMesh.raycast = () => {};
|
|
@@ -1233,10 +1242,16 @@ class CameraController extends EventDispatcher {
|
|
|
1233
1242
|
const targets = Array.isArray(objects) ? objects : [objects];
|
|
1234
1243
|
if (targets.length === 0) return null;
|
|
1235
1244
|
const intersects = raycaster.intersectObjects(targets, true);
|
|
1236
|
-
|
|
1245
|
+
for (const intersection of intersects) {
|
|
1246
|
+
if (
|
|
1247
|
+
this.#raycastHitFilter &&
|
|
1248
|
+
!this.#raycastHitFilter(intersection, raycaster)
|
|
1249
|
+
) {
|
|
1250
|
+
continue;
|
|
1251
|
+
}
|
|
1237
1252
|
return {
|
|
1238
|
-
point:
|
|
1239
|
-
distance:
|
|
1253
|
+
point: intersection.point.clone(),
|
|
1254
|
+
distance: intersection.point.distanceTo(this.#camera.position),
|
|
1240
1255
|
};
|
|
1241
1256
|
}
|
|
1242
1257
|
return null;
|