3dtiles-inspector 0.2.17 → 0.2.18

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 CHANGED
@@ -6,6 +6,15 @@ The format is based on Keep a Changelog and this project follows Semantic Versio
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.2.18] - 2026-07-16
10
+
11
+ ### Fixed
12
+
13
+ - Fixed reversed-depth render ordering for transform controls, crop guides,
14
+ and crop-sphere wireframes with Three.js 0.185.x.
15
+ - Fixed translate, rotate, and scale edits not updating already loaded tiles
16
+ with Three.js 0.185.x.
17
+
9
18
  ## [0.2.17] - 2026-07-16
10
19
 
11
20
  ### Changed
@@ -65710,6 +65710,15 @@ var init_TransformControls = __esm({
65710
65710
  }
65711
65711
  });
65712
65712
 
65713
+ // src/viewer/scene/renderOrder.js
65714
+ function getDepthAwareRenderOrder(renderOrder, reversedDepthBuffer) {
65715
+ return reversedDepthBuffer ? -renderOrder : renderOrder;
65716
+ }
65717
+ var init_renderOrder = __esm({
65718
+ "src/viewer/scene/renderOrder.js"() {
65719
+ }
65720
+ });
65721
+
65713
65722
  // src/viewer/scene/transformControls.js
65714
65723
  function forceOverlayMaterial(material) {
65715
65724
  if (!material) {
@@ -65723,10 +65732,14 @@ function forceOverlayMaterial(material) {
65723
65732
  material.depthWrite = false;
65724
65733
  material.needsUpdate = true;
65725
65734
  }
65726
- function forceOverlayRendering(object) {
65727
- object.renderOrder = TRANSFORM_CONTROL_RENDER_ORDER;
65735
+ function forceOverlayRendering(object, reversedDepthBuffer) {
65736
+ const renderOrder = getDepthAwareRenderOrder(
65737
+ TRANSFORM_CONTROL_RENDER_ORDER,
65738
+ reversedDepthBuffer
65739
+ );
65740
+ object.renderOrder = renderOrder;
65728
65741
  object.traverse((entry) => {
65729
- entry.renderOrder = TRANSFORM_CONTROL_RENDER_ORDER;
65742
+ entry.renderOrder = renderOrder;
65730
65743
  forceOverlayMaterial(entry.material);
65731
65744
  });
65732
65745
  }
@@ -65736,13 +65749,14 @@ function createViewerTransformControls({
65736
65749
  domElement,
65737
65750
  scene,
65738
65751
  transformHandle,
65752
+ reversedDepthBuffer,
65739
65753
  callbacks,
65740
65754
  getSyncingTransformHandle
65741
65755
  }) {
65742
65756
  const transformControls = new TransformControls(camera, domElement);
65743
65757
  const transformControlsHelper = typeof transformControls.getHelper === "function" ? transformControls.getHelper() : null;
65744
65758
  if (transformControlsHelper) {
65745
- forceOverlayRendering(transformControlsHelper);
65759
+ forceOverlayRendering(transformControlsHelper, reversedDepthBuffer);
65746
65760
  }
65747
65761
  transformControls.setMode("translate");
65748
65762
  transformControls.setSpace("local");
@@ -65773,7 +65787,8 @@ var TRANSFORM_CONTROL_RENDER_ORDER;
65773
65787
  var init_transformControls = __esm({
65774
65788
  "src/viewer/scene/transformControls.js"() {
65775
65789
  init_TransformControls();
65776
- TRANSFORM_CONTROL_RENDER_ORDER = 1000002;
65790
+ init_renderOrder();
65791
+ TRANSFORM_CONTROL_RENDER_ORDER = 1000003;
65777
65792
  }
65778
65793
  });
65779
65794
 
@@ -67917,7 +67932,7 @@ function createFarHandleMaterial({ depthTest, opacity = 1 }) {
67917
67932
  transparent: opacity < 1
67918
67933
  });
67919
67934
  }
67920
- function createScreenSelectionFarHandle(selection) {
67935
+ function createScreenSelectionFarHandle(selection, reversedDepthBuffer = false) {
67921
67936
  const handle = new Group();
67922
67937
  const solidMaterial = createFarHandleMaterial({
67923
67938
  depthTest: true
@@ -67939,18 +67954,25 @@ function createScreenSelectionFarHandle(selection) {
67939
67954
  const overlayGrid = new LineSegments(gridGeometry, overlayMaterial);
67940
67955
  const solidGuide = new LineSegments(guideGeometry, solidGuideMaterial);
67941
67956
  const overlayGuide = new LineSegments(guideGeometry, overlayGuideMaterial);
67957
+ const solidRenderOrder = getDepthAwareRenderOrder(
67958
+ SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER,
67959
+ reversedDepthBuffer
67960
+ );
67961
+ const overlayRenderOrder = getDepthAwareRenderOrder(
67962
+ SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER + 1,
67963
+ reversedDepthBuffer
67964
+ );
67942
67965
  handle.name = `Screen Selection ${selection.id} Far`;
67943
- handle.renderOrder = SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER;
67944
67966
  handle.userData.screenSelectionFarHandle = true;
67945
67967
  handle.userData.screenSelectionId = selection.id;
67946
67968
  solidGrid.name = `${handle.name} Grid`;
67947
- solidGrid.renderOrder = SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER;
67969
+ solidGrid.renderOrder = solidRenderOrder;
67948
67970
  overlayGrid.name = `${handle.name} Grid Overlay`;
67949
- overlayGrid.renderOrder = SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER + 1;
67971
+ overlayGrid.renderOrder = overlayRenderOrder;
67950
67972
  solidGuide.name = `${handle.name} Guide`;
67951
- solidGuide.renderOrder = SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER;
67973
+ solidGuide.renderOrder = solidRenderOrder;
67952
67974
  overlayGuide.name = `${handle.name} Guide Overlay`;
67953
- overlayGuide.renderOrder = SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER + 1;
67975
+ overlayGuide.renderOrder = overlayRenderOrder;
67954
67976
  handle.add(solidGrid, solidGuide, overlayGrid, overlayGuide);
67955
67977
  selection.farHandle = handle;
67956
67978
  selection.farHandleGridGeometry = gridGeometry;
@@ -68033,6 +68055,7 @@ var init_farHandle = __esm({
68033
68055
  init_three_module();
68034
68056
  init_state();
68035
68057
  init_geometry();
68058
+ init_renderOrder();
68036
68059
  }
68037
68060
  });
68038
68061
 
@@ -68836,6 +68859,7 @@ function createCropController({
68836
68859
  rectEl,
68837
68860
  scene,
68838
68861
  screenSelectionSplatEdit,
68862
+ reversedDepthBuffer,
68839
68863
  setStatus,
68840
68864
  setTransformMode,
68841
68865
  syncTransformControlsState,
@@ -69028,11 +69052,18 @@ function createCropController({
69028
69052
  });
69029
69053
  const visibleWireframe = new LineSegments(geometry, visibleMaterial);
69030
69054
  const overlayWireframe = new LineSegments(geometry, overlayMaterial);
69031
- visibleWireframe.renderOrder = KEEP_SPHERE_WIREFRAME_RENDER_ORDER;
69032
- overlayWireframe.renderOrder = KEEP_SPHERE_WIREFRAME_RENDER_ORDER + 1;
69055
+ const visibleRenderOrder = getDepthAwareRenderOrder(
69056
+ KEEP_SPHERE_WIREFRAME_RENDER_ORDER,
69057
+ reversedDepthBuffer
69058
+ );
69059
+ const overlayRenderOrder = getDepthAwareRenderOrder(
69060
+ KEEP_SPHERE_WIREFRAME_RENDER_ORDER + 1,
69061
+ reversedDepthBuffer
69062
+ );
69063
+ visibleWireframe.renderOrder = visibleRenderOrder;
69064
+ overlayWireframe.renderOrder = overlayRenderOrder;
69033
69065
  group.add(visibleWireframe);
69034
69066
  group.add(overlayWireframe);
69035
- group.renderOrder = KEEP_SPHERE_WIREFRAME_RENDER_ORDER;
69036
69067
  group.userData.keepSphereHandle = true;
69037
69068
  group.userData.screenSelectionId = selection.id;
69038
69069
  selection.wireframe = group;
@@ -69255,7 +69286,9 @@ function createCropController({
69255
69286
  }
69256
69287
  entries.forEach(({ selection }) => {
69257
69288
  if (!selection.farHandle) {
69258
- scene.add(createScreenSelectionFarHandle(selection));
69289
+ scene.add(
69290
+ createScreenSelectionFarHandle(selection, reversedDepthBuffer)
69291
+ );
69259
69292
  }
69260
69293
  });
69261
69294
  syncWorldState();
@@ -70137,6 +70170,7 @@ var init_cropController = __esm({
70137
70170
  init_editOverlay();
70138
70171
  init_cropUi();
70139
70172
  init_utils();
70173
+ init_renderOrder();
70140
70174
  CAMERA_POSITION_EPSILON_SQ = 1e-12;
70141
70175
  CAMERA_QUATERNION_EPSILON = 1e-10;
70142
70176
  CAMERA_PROJECTION_EPSILON = 1e-10;
@@ -70204,7 +70238,7 @@ function refreshLoadedTileSceneMatrices(tilesRenderer) {
70204
70238
  }
70205
70239
  tilesRenderer.forEachLoadedModel((loadedScene) => {
70206
70240
  if (typeof loadedScene.updateWorldMatrix === "function") {
70207
- loadedScene.updateWorldMatrix(false, true);
70241
+ loadedScene.updateWorldMatrix(false, true, true);
70208
70242
  } else {
70209
70243
  loadedScene.updateMatrixWorld(true);
70210
70244
  }
@@ -70842,6 +70876,7 @@ var require_app = __commonJS({
70842
70876
  domElement: renderer.domElement,
70843
70877
  scene,
70844
70878
  transformHandle,
70879
+ reversedDepthBuffer: renderer.capabilities.reversedDepthBuffer,
70845
70880
  callbacks: {
70846
70881
  onObjectChange: (object) => cropController?.handleTransformControlObjectChange(object) ?? false,
70847
70882
  onRootObjectChange: (matrix) => {
@@ -70943,6 +70978,7 @@ var require_app = __commonJS({
70943
70978
  rectEl: screenSelectionRectEl,
70944
70979
  scene,
70945
70980
  screenSelectionSplatEdit,
70981
+ reversedDepthBuffer: renderer.capabilities.reversedDepthBuffer,
70946
70982
  setStatus,
70947
70983
  setTransformMode: (mode) => transformModeController.setMode(mode),
70948
70984
  syncTransformControlsState: () => transformModeController.syncControls(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "3dtiles-inspector",
3
- "version": "0.2.17",
3
+ "version": "0.2.18",
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/viewer/app.js CHANGED
@@ -230,6 +230,7 @@ const { transformControls, transformControlsHelper } =
230
230
  domElement: renderer.domElement,
231
231
  scene,
232
232
  transformHandle,
233
+ reversedDepthBuffer: renderer.capabilities.reversedDepthBuffer,
233
234
  callbacks: {
234
235
  onObjectChange: (object) =>
235
236
  cropController?.handleTransformControlObjectChange(object) ?? false,
@@ -344,6 +345,7 @@ cropController = createCropController({
344
345
  rectEl: screenSelectionRectEl,
345
346
  scene,
346
347
  screenSelectionSplatEdit,
348
+ reversedDepthBuffer: renderer.capabilities.reversedDepthBuffer,
347
349
  setStatus,
348
350
  setTransformMode: (mode) => transformModeController.setMode(mode),
349
351
  syncTransformControlsState: () => transformModeController.syncControls(),
@@ -0,0 +1,5 @@
1
+ export function getDepthAwareRenderOrder(renderOrder, reversedDepthBuffer) {
2
+ // Three.js reverses each completed render list in reversed-depth mode, so
3
+ // explicit renderOrder priorities must use the opposite numeric direction.
4
+ return reversedDepthBuffer ? -renderOrder : renderOrder;
5
+ }
@@ -1,6 +1,7 @@
1
1
  import { TransformControls } from 'three/addons/controls/TransformControls.js';
2
+ import { getDepthAwareRenderOrder } from './renderOrder.js';
2
3
 
3
- const TRANSFORM_CONTROL_RENDER_ORDER = 1000002;
4
+ const TRANSFORM_CONTROL_RENDER_ORDER = 1000003;
4
5
 
5
6
  function forceOverlayMaterial(material) {
6
7
  if (!material) {
@@ -17,10 +18,14 @@ function forceOverlayMaterial(material) {
17
18
  material.needsUpdate = true;
18
19
  }
19
20
 
20
- function forceOverlayRendering(object) {
21
- object.renderOrder = TRANSFORM_CONTROL_RENDER_ORDER;
21
+ function forceOverlayRendering(object, reversedDepthBuffer) {
22
+ const renderOrder = getDepthAwareRenderOrder(
23
+ TRANSFORM_CONTROL_RENDER_ORDER,
24
+ reversedDepthBuffer,
25
+ );
26
+ object.renderOrder = renderOrder;
22
27
  object.traverse((entry) => {
23
- entry.renderOrder = TRANSFORM_CONTROL_RENDER_ORDER;
28
+ entry.renderOrder = renderOrder;
24
29
  forceOverlayMaterial(entry.material);
25
30
  });
26
31
  }
@@ -31,6 +36,7 @@ export function createViewerTransformControls({
31
36
  domElement,
32
37
  scene,
33
38
  transformHandle,
39
+ reversedDepthBuffer,
34
40
  callbacks,
35
41
  getSyncingTransformHandle,
36
42
  }) {
@@ -41,7 +47,7 @@ export function createViewerTransformControls({
41
47
  : null;
42
48
 
43
49
  if (transformControlsHelper) {
44
- forceOverlayRendering(transformControlsHelper);
50
+ forceOverlayRendering(transformControlsHelper, reversedDepthBuffer);
45
51
  }
46
52
  transformControls.setMode('translate');
47
53
  transformControls.setSpace('local');
@@ -48,6 +48,7 @@ import {
48
48
  } from './editOverlay.js';
49
49
  import { updateCropControls } from '../dom/cropUi.js';
50
50
  import { mouseToCoords, setRaycasterFromCamera } from '../utils.js';
51
+ import { getDepthAwareRenderOrder } from '../scene/renderOrder.js';
51
52
 
52
53
  const CAMERA_POSITION_EPSILON_SQ = 1e-12;
53
54
  const CAMERA_QUATERNION_EPSILON = 1e-10;
@@ -180,6 +181,7 @@ export function createCropController({
180
181
  rectEl,
181
182
  scene,
182
183
  screenSelectionSplatEdit,
184
+ reversedDepthBuffer,
183
185
  setStatus,
184
186
  setTransformMode,
185
187
  syncTransformControlsState,
@@ -413,11 +415,20 @@ export function createCropController({
413
415
  });
414
416
  const visibleWireframe = new LineSegments(geometry, visibleMaterial);
415
417
  const overlayWireframe = new LineSegments(geometry, overlayMaterial);
416
- visibleWireframe.renderOrder = KEEP_SPHERE_WIREFRAME_RENDER_ORDER;
417
- overlayWireframe.renderOrder = KEEP_SPHERE_WIREFRAME_RENDER_ORDER + 1;
418
+ const visibleRenderOrder = getDepthAwareRenderOrder(
419
+ KEEP_SPHERE_WIREFRAME_RENDER_ORDER,
420
+ reversedDepthBuffer,
421
+ );
422
+ const overlayRenderOrder = getDepthAwareRenderOrder(
423
+ KEEP_SPHERE_WIREFRAME_RENDER_ORDER + 1,
424
+ reversedDepthBuffer,
425
+ );
426
+ visibleWireframe.renderOrder = visibleRenderOrder;
427
+ overlayWireframe.renderOrder = overlayRenderOrder;
428
+ // Group.renderOrder becomes groupOrder and sorts before child renderOrder.
429
+ // Leave the transform root at its default so controls can render last.
418
430
  group.add(visibleWireframe);
419
431
  group.add(overlayWireframe);
420
- group.renderOrder = KEEP_SPHERE_WIREFRAME_RENDER_ORDER;
421
432
  group.userData.keepSphereHandle = true;
422
433
  group.userData.screenSelectionId = selection.id;
423
434
  selection.wireframe = group;
@@ -677,7 +688,9 @@ export function createCropController({
677
688
 
678
689
  entries.forEach(({ selection }) => {
679
690
  if (!selection.farHandle) {
680
- scene.add(createScreenSelectionFarHandle(selection));
691
+ scene.add(
692
+ createScreenSelectionFarHandle(selection, reversedDepthBuffer),
693
+ );
681
694
  }
682
695
  });
683
696
  syncWorldState();
@@ -25,6 +25,7 @@ import {
25
25
  getSelectionTransformDelta,
26
26
  normalizeFarPlaneAxes,
27
27
  } from './geometry.js';
28
+ import { getDepthAwareRenderOrder } from '../scene/renderOrder.js';
28
29
 
29
30
  function pushFarHandleSegment(vertices, start, end) {
30
31
  vertices.push(start[0], start[1], start[2] || 0, end[0], end[1], end[2] || 0);
@@ -179,7 +180,10 @@ function createFarHandleMaterial({ depthTest, opacity = 1 }) {
179
180
  });
180
181
  }
181
182
 
182
- export function createScreenSelectionFarHandle(selection) {
183
+ export function createScreenSelectionFarHandle(
184
+ selection,
185
+ reversedDepthBuffer = false,
186
+ ) {
183
187
  const handle = new Group();
184
188
  const solidMaterial = createFarHandleMaterial({
185
189
  depthTest: true,
@@ -201,19 +205,28 @@ export function createScreenSelectionFarHandle(selection) {
201
205
  const overlayGrid = new LineSegments(gridGeometry, overlayMaterial);
202
206
  const solidGuide = new LineSegments(guideGeometry, solidGuideMaterial);
203
207
  const overlayGuide = new LineSegments(guideGeometry, overlayGuideMaterial);
208
+ const solidRenderOrder = getDepthAwareRenderOrder(
209
+ SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER,
210
+ reversedDepthBuffer,
211
+ );
212
+ const overlayRenderOrder = getDepthAwareRenderOrder(
213
+ SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER + 1,
214
+ reversedDepthBuffer,
215
+ );
204
216
 
205
217
  handle.name = `Screen Selection ${selection.id} Far`;
206
- handle.renderOrder = SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER;
218
+ // Keep the Group at the default order so its groupOrder does not override
219
+ // the child material priorities below.
207
220
  handle.userData.screenSelectionFarHandle = true;
208
221
  handle.userData.screenSelectionId = selection.id;
209
222
  solidGrid.name = `${handle.name} Grid`;
210
- solidGrid.renderOrder = SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER;
223
+ solidGrid.renderOrder = solidRenderOrder;
211
224
  overlayGrid.name = `${handle.name} Grid Overlay`;
212
- overlayGrid.renderOrder = SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER + 1;
225
+ overlayGrid.renderOrder = overlayRenderOrder;
213
226
  solidGuide.name = `${handle.name} Guide`;
214
- solidGuide.renderOrder = SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER;
227
+ solidGuide.renderOrder = solidRenderOrder;
215
228
  overlayGuide.name = `${handle.name} Guide Overlay`;
216
- overlayGuide.renderOrder = SCREEN_SELECTION_FAR_HANDLE_RENDER_ORDER + 1;
229
+ overlayGuide.renderOrder = overlayRenderOrder;
217
230
  handle.add(solidGrid, solidGuide, overlayGrid, overlayGuide);
218
231
  selection.farHandle = handle;
219
232
  selection.farHandleGridGeometry = gridGeometry;
@@ -70,7 +70,8 @@ export function refreshLoadedTileSceneMatrices(tilesRenderer) {
70
70
 
71
71
  tilesRenderer.forEachLoadedModel((loadedScene) => {
72
72
  if (typeof loadedScene.updateWorldMatrix === 'function') {
73
- loadedScene.updateWorldMatrix(false, true);
73
+ // Three.js r185 only recomputes clean, static matrices when forced.
74
+ loadedScene.updateWorldMatrix(false, true, true);
74
75
  } else {
75
76
  loadedScene.updateMatrixWorld(true);
76
77
  }