3dtiles-inspector 0.2.0 → 0.2.1
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 +7 -0
- package/README.md +3 -3
- package/dist/inspector-assets/viewer/app.js +4 -4
- package/package.json +1 -1
- package/src/server/viewerHtml.js +131 -88
- package/src/viewer/dom/cropUi.js +14 -11
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,13 @@ The format is based on Keep a Changelog and this project follows Semantic Versio
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.2.1] - 2026-05-03
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Renamed the crop selection action to `Select Region` and show pending or newest crop regions first in the list.
|
|
14
|
+
- Kept the Save/status controls fixed at the bottom of the sidebar, moved `Reset` into the Transform controls, and tightened sidebar behavior on narrow screens.
|
|
15
|
+
|
|
9
16
|
## [0.2.0] - 2026-05-03
|
|
10
17
|
|
|
11
18
|
### Added
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
|
-
`3dtiles-inspector` is a Node.js package and CLI for opening a local 3D Tiles tileset in a browser inspector, adjusting the root transform, tuning
|
|
13
|
+
`3dtiles-inspector` is a Node.js package and CLI for opening a local 3D Tiles tileset in a browser inspector, adjusting the root transform, tuning geometric-error scaling, cropping supported 3D Gaussian Splat tilesets, and saving the result back to disk.
|
|
14
14
|
|
|
15
15
|
Requires Node.js 18 or newer.
|
|
16
16
|
|
|
@@ -93,7 +93,7 @@ const {
|
|
|
93
93
|
- `Geometric Error` scaling from `1/16x` to `16x`
|
|
94
94
|
- `Layer Multiplier` scaling from `1/8x` to `8x` for each tile's geometric-error difference from the tileset's global leaf baseline
|
|
95
95
|
- `Crop Regions` for drawing screen-space exclude regions on 3D Gaussian Splat tilesets
|
|
96
|
-
- `Save` to persist
|
|
96
|
+
- `Save` to persist root transform edits, geometric-error scaling, and confirmed crop regions back to disk
|
|
97
97
|
|
|
98
98
|
### Crop Regions
|
|
99
99
|
|
|
@@ -101,7 +101,7 @@ const {
|
|
|
101
101
|
|
|
102
102
|
The basic workflow is:
|
|
103
103
|
|
|
104
|
-
1. Click `
|
|
104
|
+
1. Click `Select Region` and drag a rectangle over the splats to remove.
|
|
105
105
|
2. Drag the far-plane handle to set how deep the crop region extends into the scene.
|
|
106
106
|
3. Click `Confirm` to add the region to the save list, or `Cancel` to discard the pending rectangle.
|
|
107
107
|
4. Select a confirmed region row if you need to adjust its 3D far plane with the transform handle.
|
|
@@ -68903,22 +68903,22 @@ function updateCropControls({
|
|
|
68903
68903
|
screenSelections.length + pendingScreenSelections.length
|
|
68904
68904
|
);
|
|
68905
68905
|
cropListEl.replaceChildren();
|
|
68906
|
-
|
|
68906
|
+
pendingScreenSelections.forEach((selection) => {
|
|
68907
68907
|
cropListEl.appendChild(
|
|
68908
68908
|
createSelectionControl({
|
|
68909
68909
|
active: selection.id === activeScreenSelectionId,
|
|
68910
|
-
label:
|
|
68910
|
+
label: "Pending",
|
|
68911
68911
|
onScreenSelectionRemove,
|
|
68912
68912
|
onScreenSelectionSelect,
|
|
68913
68913
|
selection
|
|
68914
68914
|
})
|
|
68915
68915
|
);
|
|
68916
68916
|
});
|
|
68917
|
-
|
|
68917
|
+
screenSelections.map((selection, index) => ({ label: `Region ${index + 1}`, selection })).reverse().forEach(({ label, selection }) => {
|
|
68918
68918
|
cropListEl.appendChild(
|
|
68919
68919
|
createSelectionControl({
|
|
68920
68920
|
active: selection.id === activeScreenSelectionId,
|
|
68921
|
-
label
|
|
68921
|
+
label,
|
|
68922
68922
|
onScreenSelectionRemove,
|
|
68923
68923
|
onScreenSelectionSelect,
|
|
68924
68924
|
selection
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "3dtiles-inspector",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
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",
|
package/src/server/viewerHtml.js
CHANGED
|
@@ -167,8 +167,8 @@ function buildViewerHtml(viewerConfig) {
|
|
|
167
167
|
|
|
168
168
|
.toolbar {
|
|
169
169
|
display: grid;
|
|
170
|
-
|
|
171
|
-
gap:
|
|
170
|
+
grid-template-rows: minmax(0, 1fr) auto;
|
|
171
|
+
gap: 0;
|
|
172
172
|
padding: 10px 14px;
|
|
173
173
|
border: 1px solid rgba(22, 50, 79, 0.12);
|
|
174
174
|
border-top: 0;
|
|
@@ -177,8 +177,7 @@ function buildViewerHtml(viewerConfig) {
|
|
|
177
177
|
box-shadow: 0 18px 44px rgba(33, 52, 73, 0.16);
|
|
178
178
|
backdrop-filter: blur(14px);
|
|
179
179
|
min-height: 0;
|
|
180
|
-
overflow
|
|
181
|
-
overscroll-behavior: contain;
|
|
180
|
+
overflow: hidden;
|
|
182
181
|
transition:
|
|
183
182
|
opacity 160ms ease,
|
|
184
183
|
transform 160ms ease;
|
|
@@ -215,8 +214,8 @@ function buildViewerHtml(viewerConfig) {
|
|
|
215
214
|
.toolbar-dock.collapsed .toolbar-toggle {
|
|
216
215
|
justify-self: start;
|
|
217
216
|
width: auto;
|
|
218
|
-
min-height:
|
|
219
|
-
padding:
|
|
217
|
+
min-height: 32px;
|
|
218
|
+
padding: 4px 12px 5px;
|
|
220
219
|
border-radius: 999px;
|
|
221
220
|
color: #506377;
|
|
222
221
|
background: rgba(255, 255, 255, 0.94);
|
|
@@ -249,6 +248,35 @@ function buildViewerHtml(viewerConfig) {
|
|
|
249
248
|
linear-gradient(180deg, rgba(255, 255, 255, 0.78), rgba(243, 247, 251, 0.9));
|
|
250
249
|
}
|
|
251
250
|
|
|
251
|
+
.toolbar-scroll {
|
|
252
|
+
display: grid;
|
|
253
|
+
align-content: start;
|
|
254
|
+
gap: 8px;
|
|
255
|
+
min-height: 0;
|
|
256
|
+
overflow-y: auto;
|
|
257
|
+
overscroll-behavior: contain;
|
|
258
|
+
padding-bottom: 8px;
|
|
259
|
+
scrollbar-color: rgba(93, 115, 139, 0.45) transparent;
|
|
260
|
+
scrollbar-width: thin;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.toolbar-scroll::-webkit-scrollbar {
|
|
264
|
+
width: 6px;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.toolbar-scroll::-webkit-scrollbar-track {
|
|
268
|
+
background: transparent;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.toolbar-scroll::-webkit-scrollbar-thumb {
|
|
272
|
+
border-radius: 999px;
|
|
273
|
+
background: rgba(93, 115, 139, 0.32);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.toolbar-scroll::-webkit-scrollbar-thumb:hover {
|
|
277
|
+
background: rgba(93, 115, 139, 0.48);
|
|
278
|
+
}
|
|
279
|
+
|
|
252
280
|
.toolbar-section-header {
|
|
253
281
|
display: flex;
|
|
254
282
|
align-items: flex-start;
|
|
@@ -521,6 +549,11 @@ function buildViewerHtml(viewerConfig) {
|
|
|
521
549
|
.status-panel {
|
|
522
550
|
display: grid;
|
|
523
551
|
gap: 10px;
|
|
552
|
+
margin-top: 8px;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.status-panel .status-actions {
|
|
556
|
+
grid-template-columns: 1fr;
|
|
524
557
|
}
|
|
525
558
|
|
|
526
559
|
.status-actions {
|
|
@@ -544,12 +577,14 @@ function buildViewerHtml(viewerConfig) {
|
|
|
544
577
|
}
|
|
545
578
|
|
|
546
579
|
.tile-runtime-stats {
|
|
547
|
-
right:
|
|
548
|
-
bottom:
|
|
549
|
-
left:
|
|
580
|
+
right: 50%;
|
|
581
|
+
bottom: 5px;
|
|
582
|
+
left: auto;
|
|
550
583
|
flex-wrap: wrap;
|
|
551
|
-
justify-content:
|
|
552
|
-
|
|
584
|
+
justify-content: center;
|
|
585
|
+
width: max-content;
|
|
586
|
+
max-width: calc(100vw - 32px);
|
|
587
|
+
transform: translateX(50%);
|
|
553
588
|
}
|
|
554
589
|
|
|
555
590
|
.runtime-stat {
|
|
@@ -564,15 +599,21 @@ function buildViewerHtml(viewerConfig) {
|
|
|
564
599
|
|
|
565
600
|
.toolbar-dock {
|
|
566
601
|
top: auto;
|
|
567
|
-
bottom:
|
|
602
|
+
bottom: 32px;
|
|
568
603
|
right: 16px;
|
|
569
604
|
left: 16px;
|
|
570
605
|
width: auto;
|
|
571
|
-
max-height: min(78vh,
|
|
606
|
+
max-height: min(calc(78vh - 26px), 614px);
|
|
572
607
|
}
|
|
573
608
|
|
|
574
609
|
.toolbar {
|
|
575
|
-
max-height: min(calc(78vh -
|
|
610
|
+
max-height: min(calc(78vh - 70px), 570px);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
.toolbar-dock.collapsed .toolbar-toggle {
|
|
614
|
+
justify-self: center;
|
|
615
|
+
min-height: 28px;
|
|
616
|
+
padding: 3px 12px 4px;
|
|
576
617
|
}
|
|
577
618
|
|
|
578
619
|
.coordinate-actions button,
|
|
@@ -627,90 +668,92 @@ function buildViewerHtml(viewerConfig) {
|
|
|
627
668
|
Hide Sidebar
|
|
628
669
|
</button>
|
|
629
670
|
<div id="toolbar" class="toolbar">
|
|
630
|
-
<div class="toolbar-
|
|
631
|
-
<div class="toolbar-section-
|
|
632
|
-
<
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
<
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
<div class="toolbar-section">
|
|
641
|
-
<div class="toolbar-section-header">
|
|
642
|
-
<p class="toolbar-section-title">Transform</p>
|
|
643
|
-
</div>
|
|
644
|
-
<div class="transform-actions">
|
|
645
|
-
<button id="translate" type="button">Translate</button>
|
|
646
|
-
<button id="rotate" type="button">Rotate</button>
|
|
647
|
-
<button id="set-position" class="full-span" type="button">Set Position</button>
|
|
648
|
-
</div>
|
|
649
|
-
</div>
|
|
650
|
-
<div class="toolbar-section">
|
|
651
|
-
<div class="toolbar-section-header">
|
|
652
|
-
<p class="toolbar-section-title">Coordinate</p>
|
|
653
|
-
</div>
|
|
654
|
-
<div class="coordinate-grid">
|
|
655
|
-
<label><span>Latitude</span><input id="latitude" type="number" step="any" value="0" /></label>
|
|
656
|
-
<label><span>Longitude</span><input id="longitude" type="number" step="any" value="0" /></label>
|
|
657
|
-
<label><span>Height</span><input id="height" type="number" step="any" value="0" /></label>
|
|
658
|
-
</div>
|
|
659
|
-
<div class="coordinate-actions">
|
|
660
|
-
<button id="move-camera-to-coordinate" class="wide" type="button">Move Camera</button>
|
|
661
|
-
<button id="move-tiles-to-coordinate" class="wide" type="button">Move Tiles</button>
|
|
671
|
+
<div class="toolbar-scroll">
|
|
672
|
+
<div class="toolbar-section" data-save-lock-exempt>
|
|
673
|
+
<div class="toolbar-section-header">
|
|
674
|
+
<p class="toolbar-section-title">Canvas</p>
|
|
675
|
+
</div>
|
|
676
|
+
<div class="coordinate-actions">
|
|
677
|
+
<button id="terrain" class="wide" type="button">Terrain</button>
|
|
678
|
+
<button id="bounding-volume" class="wide" type="button">Bounding Volume</button>
|
|
679
|
+
<button id="move-to-tiles" type="button">Move To Tiles</button>
|
|
680
|
+
</div>
|
|
662
681
|
</div>
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
682
|
+
<div class="toolbar-section">
|
|
683
|
+
<div class="toolbar-section-header">
|
|
684
|
+
<p class="toolbar-section-title">Transform</p>
|
|
685
|
+
</div>
|
|
686
|
+
<div class="transform-actions">
|
|
687
|
+
<button id="translate" type="button">Translate</button>
|
|
688
|
+
<button id="rotate" type="button">Rotate</button>
|
|
689
|
+
<button id="set-position" type="button">Set Position</button>
|
|
690
|
+
<button id="reset" type="button">Reset</button>
|
|
691
|
+
</div>
|
|
667
692
|
</div>
|
|
668
|
-
<
|
|
669
|
-
<div class="
|
|
670
|
-
<
|
|
671
|
-
<p id="geometric-error-value" class="toolbar-value">x1.00</p>
|
|
693
|
+
<div class="toolbar-section">
|
|
694
|
+
<div class="toolbar-section-header">
|
|
695
|
+
<p class="toolbar-section-title">Coordinate</p>
|
|
672
696
|
</div>
|
|
673
|
-
<
|
|
674
|
-
id="
|
|
675
|
-
type="
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
</label>
|
|
682
|
-
<label class="range-field">
|
|
683
|
-
<div class="range-field-header">
|
|
684
|
-
<span>Layer Multiplier</span>
|
|
685
|
-
<p id="geometric-error-layer-value" class="toolbar-value">x1.00</p>
|
|
697
|
+
<div class="coordinate-grid">
|
|
698
|
+
<label><span>Latitude</span><input id="latitude" type="number" step="any" value="0" /></label>
|
|
699
|
+
<label><span>Longitude</span><input id="longitude" type="number" step="any" value="0" /></label>
|
|
700
|
+
<label><span>Height</span><input id="height" type="number" step="any" value="0" /></label>
|
|
701
|
+
</div>
|
|
702
|
+
<div class="coordinate-actions">
|
|
703
|
+
<button id="move-camera-to-coordinate" class="wide" type="button">Move Camera</button>
|
|
704
|
+
<button id="move-tiles-to-coordinate" class="wide" type="button">Move Tiles</button>
|
|
686
705
|
</div>
|
|
687
|
-
<input
|
|
688
|
-
id="geometric-error-layer-scale"
|
|
689
|
-
type="range"
|
|
690
|
-
min="-3"
|
|
691
|
-
max="3"
|
|
692
|
-
step="0.1"
|
|
693
|
-
value="0"
|
|
694
|
-
/>
|
|
695
|
-
</label>
|
|
696
|
-
</div>
|
|
697
|
-
<div id="crop-section" class="toolbar-section" hidden>
|
|
698
|
-
<div class="toolbar-section-header">
|
|
699
|
-
<p class="toolbar-section-title">Crop Regions</p>
|
|
700
|
-
<p id="crop-count-value" class="toolbar-value">0</p>
|
|
701
706
|
</div>
|
|
702
|
-
<div class="
|
|
703
|
-
<
|
|
707
|
+
<div class="toolbar-section">
|
|
708
|
+
<div class="toolbar-section-header">
|
|
709
|
+
<p class="toolbar-section-title">LOD</p>
|
|
710
|
+
</div>
|
|
711
|
+
<label class="range-field">
|
|
712
|
+
<div class="range-field-header">
|
|
713
|
+
<span>Geometric Error</span>
|
|
714
|
+
<p id="geometric-error-value" class="toolbar-value">x1.00</p>
|
|
715
|
+
</div>
|
|
716
|
+
<input
|
|
717
|
+
id="geometric-error-scale"
|
|
718
|
+
type="range"
|
|
719
|
+
min="-4"
|
|
720
|
+
max="4"
|
|
721
|
+
step="0.1"
|
|
722
|
+
value="0"
|
|
723
|
+
/>
|
|
724
|
+
</label>
|
|
725
|
+
<label class="range-field">
|
|
726
|
+
<div class="range-field-header">
|
|
727
|
+
<span>Layer Multiplier</span>
|
|
728
|
+
<p id="geometric-error-layer-value" class="toolbar-value">x1.00</p>
|
|
729
|
+
</div>
|
|
730
|
+
<input
|
|
731
|
+
id="geometric-error-layer-scale"
|
|
732
|
+
type="range"
|
|
733
|
+
min="-3"
|
|
734
|
+
max="3"
|
|
735
|
+
step="0.1"
|
|
736
|
+
value="0"
|
|
737
|
+
/>
|
|
738
|
+
</label>
|
|
704
739
|
</div>
|
|
705
|
-
<div id="crop-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
740
|
+
<div id="crop-section" class="toolbar-section" hidden>
|
|
741
|
+
<div class="toolbar-section-header">
|
|
742
|
+
<p class="toolbar-section-title">Crop Regions</p>
|
|
743
|
+
<p id="crop-count-value" class="toolbar-value">0</p>
|
|
744
|
+
</div>
|
|
745
|
+
<div class="coordinate-actions">
|
|
746
|
+
<button id="crop-screen-select" class="wide" type="button">Select Region</button>
|
|
747
|
+
</div>
|
|
748
|
+
<div id="crop-list" class="crop-list"></div>
|
|
749
|
+
<div class="status-actions">
|
|
750
|
+
<button id="crop-screen-confirm" type="button">Confirm</button>
|
|
751
|
+
<button id="crop-screen-cancel" type="button">Cancel</button>
|
|
752
|
+
</div>
|
|
709
753
|
</div>
|
|
710
754
|
</div>
|
|
711
755
|
<div class="toolbar-section status-panel">
|
|
712
756
|
<div class="status-actions">
|
|
713
|
-
<button id="reset" type="button">Reset</button>
|
|
714
757
|
<button id="save" class="save" type="button">Save</button>
|
|
715
758
|
</div>
|
|
716
759
|
<progress id="save-progress" class="save-progress" max="100" value="0" hidden></progress>
|
package/src/viewer/dom/cropUi.js
CHANGED
|
@@ -30,17 +30,6 @@ export function updateCropControls({
|
|
|
30
30
|
);
|
|
31
31
|
|
|
32
32
|
cropListEl.replaceChildren();
|
|
33
|
-
screenSelections.forEach((selection, index) => {
|
|
34
|
-
cropListEl.appendChild(
|
|
35
|
-
createSelectionControl({
|
|
36
|
-
active: selection.id === activeScreenSelectionId,
|
|
37
|
-
label: `Region ${index + 1}`,
|
|
38
|
-
onScreenSelectionRemove,
|
|
39
|
-
onScreenSelectionSelect,
|
|
40
|
-
selection,
|
|
41
|
-
}),
|
|
42
|
-
);
|
|
43
|
-
});
|
|
44
33
|
pendingScreenSelections.forEach((selection) => {
|
|
45
34
|
cropListEl.appendChild(
|
|
46
35
|
createSelectionControl({
|
|
@@ -52,6 +41,20 @@ export function updateCropControls({
|
|
|
52
41
|
}),
|
|
53
42
|
);
|
|
54
43
|
});
|
|
44
|
+
screenSelections
|
|
45
|
+
.map((selection, index) => ({ label: `Region ${index + 1}`, selection }))
|
|
46
|
+
.reverse()
|
|
47
|
+
.forEach(({ label, selection }) => {
|
|
48
|
+
cropListEl.appendChild(
|
|
49
|
+
createSelectionControl({
|
|
50
|
+
active: selection.id === activeScreenSelectionId,
|
|
51
|
+
label,
|
|
52
|
+
onScreenSelectionRemove,
|
|
53
|
+
onScreenSelectionSelect,
|
|
54
|
+
selection,
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
57
|
+
});
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
function createSelectionControl({
|