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.
@@ -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
  ),
@@ -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
- if (intersects.length > 0) {
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: intersects[0].point.clone(),
1239
- distance: intersects[0].point.distanceTo(this.#camera.position),
1253
+ point: intersection.point.clone(),
1254
+ distance: intersection.point.distanceTo(this.#camera.position),
1240
1255
  };
1241
1256
  }
1242
1257
  return null;