@xeokit/xeokit-sdk 2.6.61 → 2.6.63

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.
Files changed (25) hide show
  1. package/dist/xeokit-sdk.cjs.js +123 -51
  2. package/dist/xeokit-sdk.es.js +123 -51
  3. package/dist/xeokit-sdk.es5.js +89 -87
  4. package/dist/xeokit-sdk.min.cjs.js +5 -5
  5. package/dist/xeokit-sdk.min.es.js +5 -5
  6. package/dist/xeokit-sdk.min.es5.js +4 -4
  7. package/package.json +2 -1
  8. package/src/extras/ContextMenu/ContextMenu.js +11 -4
  9. package/src/plugins/AnnotationsPlugin/Annotation.js +3 -3
  10. package/src/plugins/ZonesPlugin/ZonesPlugin.js +14 -14
  11. package/src/plugins/lib/html/MenuEvent.js +17 -4
  12. package/src/viewer/metadata/MetaScene.js +2 -2
  13. package/src/viewer/scene/CameraControl/lib/handlers/KeyboardPanRotateDollyHandler.js +10 -0
  14. package/src/viewer/scene/CameraControl/lib/handlers/MousePanRotateDollyHandler.js +10 -0
  15. package/src/viewer/scene/CameraControl/lib/handlers/MousePickHandler.js +1 -1
  16. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesColorRenderer.js +19 -4
  17. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesEdgesColorRenderer.js +11 -2
  18. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesEdgesRenderer.js +11 -2
  19. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSilhouetteRenderer.js +9 -2
  20. package/src/viewer/scene/model/vbo/VBORenderer.js +2 -2
  21. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesBatchingRenderer.js +3 -1
  22. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapRenderer.js +5 -3
  23. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesInstancingRenderer.js +3 -1
  24. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapRenderer.js +6 -4
  25. package/src/viewer/scene/webgl/Renderer.js +6 -2
@@ -784,12 +784,19 @@ class ContextMenu {
784
784
  subMenuElement.getBoundingClientRect();
785
785
 
786
786
  const subMenuWidth = 200; // TODO
787
- const showOnLeft = ((itemRect.right + subMenuWidth) > window.innerWidth);
787
+ const showOnRight = (itemRect.right + subMenuWidth) < window.innerWidth;
788
+ const showOnLeft = (itemRect.left - subMenuWidth) > 0;
788
789
 
789
- if (showOnLeft) {
790
- self._showMenu(subMenu.id, itemRect.left - subMenuWidth, itemRect.top - 1);
791
- } else {
790
+ if(showOnRight)
792
791
  self._showMenu(subMenu.id, itemRect.right - 5, itemRect.top - 1);
792
+ else if (showOnLeft)
793
+ self._showMenu(subMenu.id, itemRect.left - subMenuWidth, itemRect.top - 1);
794
+ else {
795
+ const spaceOnLeft = itemRect.left, spaceOnRight = window.innerWidth - itemRect.right;
796
+ if(spaceOnRight > spaceOnLeft)
797
+ self._showMenu(subMenu.id, itemRect.right - 5 - (subMenuWidth - spaceOnRight), itemRect.top - 1);
798
+ else
799
+ self._showMenu(subMenu.id, itemRect.left - spaceOnLeft, itemRect.top - 1);
793
800
  }
794
801
 
795
802
  lastSubMenu = subMenu;
@@ -9593,14 +9600,17 @@ function addContextMenuListener(elem, callback) {
9593
9600
 
9594
9601
  const touchStartHandler = (event) => {
9595
9602
  event.preventDefault();
9596
- const touch = event.touches[0];
9597
- startX = touch.clientX;
9598
- startY = touch.clientY;
9599
-
9603
+
9600
9604
  if (timeout) {
9601
9605
  clearTimeout(timeout);
9602
9606
  timeout = null;
9603
9607
  }
9608
+ // If more than one finger touches the screen, cancel the timeout
9609
+ if (event.touches.length > 1) return;
9610
+
9611
+ const touch = event.touches[0];
9612
+ startX = touch.clientX;
9613
+ startY = touch.clientY;
9604
9614
 
9605
9615
  timeout = setTimeout(() => {
9606
9616
  event.clientX = touch.clientX;
@@ -9611,6 +9621,14 @@ function addContextMenuListener(elem, callback) {
9611
9621
  }, longPressTimer);
9612
9622
  };
9613
9623
 
9624
+ const globalTouchStartHandler = (event) => {
9625
+ // Cancel timeout if multiple touches are detected anywhere on the screen
9626
+ if (event.touches.length > 1 && timeout) {
9627
+ clearTimeout(timeout);
9628
+ timeout = null;
9629
+ }
9630
+ };
9631
+
9614
9632
  const touchMoveHandler = (event) => {
9615
9633
  if (!timeout) return;
9616
9634
  const touch = event.touches[0];
@@ -9641,6 +9659,7 @@ function addContextMenuListener(elem, callback) {
9641
9659
  elem.addEventListener('touchstart', touchStartHandler);
9642
9660
  elem.addEventListener('touchmove', touchMoveHandler);
9643
9661
  elem.addEventListener('touchend', touchEndHandler);
9662
+ window.addEventListener('touchstart', globalTouchStartHandler);
9644
9663
  } else {
9645
9664
  elem.addEventListener('contextmenu', contextMenuHandler);
9646
9665
  }
@@ -9650,6 +9669,7 @@ function addContextMenuListener(elem, callback) {
9650
9669
  elem.removeEventListener('touchstart', touchStartHandler);
9651
9670
  elem.removeEventListener('touchmove', touchMoveHandler);
9652
9671
  elem.removeEventListener('touchend', touchEndHandler);
9672
+ window.removeEventListener('touchstart', globalTouchStartHandler);
9653
9673
  } else {
9654
9674
  elem.removeEventListener('contextmenu', contextMenuHandler);
9655
9675
  }
@@ -14773,10 +14793,10 @@ class Annotation extends Marker {
14773
14793
  this._marker.addEventListener("click", this._onMouseClickedExternalMarker = () => {
14774
14794
  this.plugin.fire("markerClicked", this);
14775
14795
  });
14776
- this._onContextMenuExtenalMarker = () => {
14796
+ this._onContextMenuExternalMarker = () => {
14777
14797
  this.plugin.fire("contextmenu", this);
14778
14798
  };
14779
- this._onContextMenuExtenalMarkerRemover = addContextMenuListener(this._markerHTML, this._onContextMenuExtenalMarker);
14799
+ this._onContextMenuExternalMarkerRemover = addContextMenuListener(this._marker, this._onContextMenuExternalMarker);
14780
14800
  this._marker.addEventListener("mouseenter", this._onMouseEnterExternalMarker = () => {
14781
14801
  this.plugin.fire("markerMouseEnter", this);
14782
14802
  });
@@ -15147,7 +15167,7 @@ class Annotation extends Marker {
15147
15167
  this._marker = null;
15148
15168
  } else {
15149
15169
  this._marker.removeEventListener("click", this._onMouseClickedExternalMarker);
15150
- this._onContextMenuExtenalMarkerRemover();
15170
+ this._onContextMenuExternalMarkerRemover();
15151
15171
  this._marker.removeEventListener("mouseenter", this._onMouseEnterExternalMarker);
15152
15172
  this._marker.removeEventListener("mouseleave", this._onMouseLeaveExternalMarker);
15153
15173
  this._marker = null;
@@ -19392,6 +19412,8 @@ function getExtension (gl, name) {
19392
19412
  return extension;
19393
19413
  }
19394
19414
 
19415
+ const vec3_0 = math.vec3([0,0,0]);
19416
+
19395
19417
  /**
19396
19418
  * @private
19397
19419
  */
@@ -20070,9 +20092,11 @@ const Renderer$1 = function (scene, options) {
20070
20092
  // Transparent color fill
20071
20093
 
20072
20094
  if (normalFillTransparentBinLen > 0) {
20095
+ const eye = frameCtx.pickOrigin || scene.camera.eye;
20096
+ const byDist = normalFillTransparentBin.map(d => ({ drawable: d, distSq: math.distVec3(d.origin || vec3_0, eye) }));
20097
+ byDist.sort((a, b) => b.distSq - a.distSq);
20073
20098
  for (i = 0; i < normalFillTransparentBinLen; i++) {
20074
- drawable = normalFillTransparentBin[i];
20075
- drawable.drawColorTransparent(frameCtx);
20099
+ byDist[i].drawable.drawColorTransparent(frameCtx);
20076
20100
  }
20077
20101
  }
20078
20102
 
@@ -52154,7 +52178,7 @@ class VBORenderer {
52154
52178
  }
52155
52179
 
52156
52180
  if (this._instancing) {
52157
- if (this._edges) {
52181
+ if (this._edges && state.edgeIndicesBuf) {
52158
52182
  state.edgeIndicesBuf.bind();
52159
52183
  } else {
52160
52184
  if (state.indicesBuf) {
@@ -52162,7 +52186,7 @@ class VBORenderer {
52162
52186
  }
52163
52187
  }
52164
52188
  } else {
52165
- if (this._edges) {
52189
+ if (this._edges && state.edgeIndicesBuf) {
52166
52190
  state.edgeIndicesBuf.bind();
52167
52191
  } else {
52168
52192
  if (state.indicesBuf) {
@@ -52429,7 +52453,9 @@ class TrianglesBatchingRenderer extends VBORenderer {
52429
52453
  } = drawCfg;
52430
52454
 
52431
52455
  if (this._edges) {
52432
- gl.drawElements(gl.LINES, state.edgeIndicesBuf.numItems, state.edgeIndicesBuf.itemType, 0);
52456
+ if (state.edgeIndicesBuf) {
52457
+ gl.drawElements(gl.LINES, state.edgeIndicesBuf.numItems, state.edgeIndicesBuf.itemType, 0);
52458
+ }
52433
52459
  } else {
52434
52460
  const count = frameCtx.pickElementsCount || state.indicesBuf.numItems;
52435
52461
  const offset = frameCtx.pickElementsOffset ? frameCtx.pickElementsOffset * state.indicesBuf.itemByteSize : 0;
@@ -55594,9 +55620,11 @@ class TrianglesSnapRenderer$1 extends VBORenderer{
55594
55620
  //=============================================================
55595
55621
 
55596
55622
  if (frameCtx.snapMode === "edge") {
55597
- state.edgeIndicesBuf.bind();
55598
- gl.drawElements(gl.LINES, state.edgeIndicesBuf.numItems, state.edgeIndicesBuf.itemType, 0);
55599
- state.edgeIndicesBuf.unbind(); // needed?
55623
+ if (state.edgeIndicesBuf) {
55624
+ state.edgeIndicesBuf.bind();
55625
+ gl.drawElements(gl.LINES, state.edgeIndicesBuf.numItems, state.edgeIndicesBuf.itemType, 0);
55626
+ state.edgeIndicesBuf.unbind(); // needed?
55627
+ }
55600
55628
  } else {
55601
55629
  gl.drawArrays(gl.POINTS, 0, state.positionsBuf.numItems);
55602
55630
  }
@@ -57765,7 +57793,9 @@ class TrianglesInstancingRenderer extends VBORenderer {
57765
57793
  } = drawCfg;
57766
57794
 
57767
57795
  if (this._edges) {
57768
- gl.drawElementsInstanced(gl.LINES, state.edgeIndicesBuf.numItems, state.edgeIndicesBuf.itemType, 0, state.numInstances);
57796
+ if (state.edgeIndicesBuf) {
57797
+ gl.drawElementsInstanced(gl.LINES, state.edgeIndicesBuf.numItems, state.edgeIndicesBuf.itemType, 0, state.numInstances);
57798
+ }
57769
57799
  } else {
57770
57800
  gl.drawElementsInstanced(gl.TRIANGLES, state.indicesBuf.numItems, state.indicesBuf.itemType, 0, state.numInstances);
57771
57801
 
@@ -61057,10 +61087,12 @@ class TrianglesSnapRenderer extends VBORenderer {
61057
61087
  this._aFlags.bindArrayBuffer(state.flagsBuf);
61058
61088
  gl.vertexAttribDivisor(this._aFlags.location, 1);
61059
61089
 
61060
- if (frameCtx.snapMode === "edge") {
61061
- state.edgeIndicesBuf.bind();
61062
- gl.drawElementsInstanced(gl.LINES, state.edgeIndicesBuf.numItems, state.edgeIndicesBuf.itemType, 0, state.numInstances);
61063
- state.edgeIndicesBuf.unbind(); // needed?
61090
+ if (frameCtx.snapMode === "edge" ) {
61091
+ if (state.edgeIndicesBuf) {
61092
+ state.edgeIndicesBuf.bind();
61093
+ gl.drawElementsInstanced(gl.LINES, state.edgeIndicesBuf.numItems, state.edgeIndicesBuf.itemType, 0, state.numInstances);
61094
+ state.edgeIndicesBuf.unbind(); // needed?
61095
+ }
61064
61096
  } else {
61065
61097
  gl.drawArraysInstanced(gl.POINTS, 0, state.positionsBuf.numItems, state.numInstances);
61066
61098
  }
@@ -73107,6 +73139,10 @@ class DTXTrianglesColorRenderer {
73107
73139
  const sectionPlanes = scene._sectionPlanesState.sectionPlanes;
73108
73140
  const baseIndex = dataTextureLayer.layerIndex * numSectionPlanes;
73109
73141
  const renderFlags = model.renderFlags;
73142
+ if (scene.crossSections) {
73143
+ gl.uniform4fv(this._uSliceColor, scene.crossSections.sliceColor);
73144
+ gl.uniform1f(this._uSliceThickness, scene.crossSections.sliceThickness);
73145
+ }
73110
73146
  for (let sectionPlaneIndex = 0; sectionPlaneIndex < numAllocatedSectionPlanes; sectionPlaneIndex++) {
73111
73147
  const sectionPlaneUniforms = this._uSectionPlanes[sectionPlaneIndex];
73112
73148
  if (sectionPlaneUniforms) {
@@ -73244,6 +73280,11 @@ class DTXTrianglesColorRenderer {
73244
73280
  this._uTexturePerPolygonIdPortionIds = "uTexturePerPolygonIdPortionIds";
73245
73281
  this._uTexturePerObjectMatrix= "uTexturePerObjectMatrix";
73246
73282
  this._uCameraEyeRtc = program.getLocation("uCameraEyeRtc");
73283
+
73284
+ if (scene.crossSections) {
73285
+ this._uSliceColor = program.getLocation("sliceColor");
73286
+ this._uSliceThickness = program.getLocation("sliceThickness");
73287
+ }
73247
73288
  }
73248
73289
 
73249
73290
  _bindProgram(frameCtx) {
@@ -73560,11 +73601,14 @@ class DTXTrianglesColorRenderer {
73560
73601
  src.push("uniform vec3 sectionPlanePos" + i + ";");
73561
73602
  src.push("uniform vec3 sectionPlaneDir" + i + ";");
73562
73603
  }
73604
+ src.push("uniform float sliceThickness;");
73605
+ src.push("uniform vec4 sliceColor;");
73563
73606
  }
73564
73607
  src.push("in vec4 vColor;");
73565
73608
  src.push("out vec4 outColor;");
73566
73609
  src.push("void main(void) {");
73567
-
73610
+ src.push(" vec4 newColor;");
73611
+ src.push(" newColor = vColor;");
73568
73612
  if (clipping) {
73569
73613
  src.push(" bool clippable = vFlags2 > 0u;");
73570
73614
  src.push(" if (clippable) {");
@@ -73574,9 +73618,12 @@ class DTXTrianglesColorRenderer {
73574
73618
  src.push(" dist += clamp(dot(-sectionPlaneDir" + i + ".xyz, vWorldPosition.xyz - sectionPlanePos" + i + ".xyz), 0.0, 1000.0);");
73575
73619
  src.push("}");
73576
73620
  }
73577
- src.push(" if (dist > 0.0) { ");
73621
+ src.push(" if (dist > sliceThickness) { ");
73578
73622
  src.push(" discard;");
73579
73623
  src.push(" }");
73624
+ src.push(" if (dist > 0.0) { ");
73625
+ src.push(" newColor = sliceColor;");
73626
+ src.push(" }");
73580
73627
  src.push("}");
73581
73628
  }
73582
73629
 
@@ -73594,9 +73641,9 @@ class DTXTrianglesColorRenderer {
73594
73641
  src.push(" float blendFactor = uSAOParams[3];");
73595
73642
  src.push(" vec2 uv = vec2(gl_FragCoord.x / viewportWidth, gl_FragCoord.y / viewportHeight);");
73596
73643
  src.push(" float ambient = smoothstep(blendCutoff, 1.0, unpackRGBToFloat(texture(uOcclusionTexture, uv))) * blendFactor;");
73597
- src.push(" outColor = vec4(vColor.rgb * ambient, 1.0);");
73644
+ src.push(" outColor = vec4(newColor.rgb * ambient, 1.0);");
73598
73645
  } else {
73599
- src.push(" outColor = vColor;");
73646
+ src.push(" outColor = newColor;");
73600
73647
  }
73601
73648
 
73602
73649
  src.push("}");
@@ -74038,10 +74085,14 @@ class DTXTrianglesSilhouetteRenderer {
74038
74085
  src.push("uniform vec3 sectionPlanePos" + i + ";");
74039
74086
  src.push("uniform vec3 sectionPlaneDir" + i + ";");
74040
74087
  }
74088
+ src.push("uniform float sliceThickness;");
74089
+ src.push("uniform vec4 sliceColor;");
74041
74090
  }
74042
74091
  src.push("uniform vec4 color;");
74043
74092
  src.push("out vec4 outColor;");
74044
74093
  src.push("void main(void) {");
74094
+ src.push(" vec4 newColor;");
74095
+ src.push(" newColor = color;");
74045
74096
  if (clipping) {
74046
74097
  src.push(" bool clippable = vFlags2 > 0u;");
74047
74098
  src.push(" if (clippable) {");
@@ -74051,15 +74102,18 @@ class DTXTrianglesSilhouetteRenderer {
74051
74102
  src.push(" dist += clamp(dot(-sectionPlaneDir" + i + ".xyz, vWorldPosition.xyz - sectionPlanePos" + i + ".xyz), 0.0, 1000.0);");
74052
74103
  src.push("}");
74053
74104
  }
74054
- src.push(" if (dist > 0.0) { ");
74105
+ src.push(" if (dist > sliceThickness) { ");
74055
74106
  src.push(" discard;");
74056
74107
  src.push(" }");
74108
+ src.push(" if (dist > 0.0) { ");
74109
+ src.push(" newColor = sliceColor;");
74110
+ src.push(" }");
74057
74111
  src.push("}");
74058
74112
  }
74059
74113
  if (scene.logarithmicDepthBufferEnabled) {
74060
74114
  src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;");
74061
74115
  }
74062
- src.push(" outColor = color;");
74116
+ src.push(" outColor = newColor;");
74063
74117
  src.push("}");
74064
74118
  return src;
74065
74119
  }
@@ -74458,10 +74512,14 @@ class DTXTrianglesEdgesRenderer {
74458
74512
  src.push("uniform vec3 sectionPlanePos" + i + ";");
74459
74513
  src.push("uniform vec3 sectionPlaneDir" + i + ";");
74460
74514
  }
74515
+ src.push("uniform float sliceThickness;");
74516
+ src.push("uniform vec4 sliceColor;");
74461
74517
  }
74462
74518
  src.push("in vec4 vColor;");
74463
74519
  src.push("out vec4 outColor;");
74464
74520
  src.push("void main(void) {");
74521
+ src.push(" vec4 newColor;");
74522
+ src.push(" newColor = vColor;");
74465
74523
  if (clipping) {
74466
74524
  src.push(" bool clippable = vFlags2 > 0u;");
74467
74525
  src.push(" if (clippable) {");
@@ -74471,13 +74529,18 @@ class DTXTrianglesEdgesRenderer {
74471
74529
  src.push(" dist += clamp(dot(-sectionPlaneDir" + i + ".xyz, vWorldPosition.xyz - sectionPlanePos" + i + ".xyz), 0.0, 1000.0);");
74472
74530
  src.push("}");
74473
74531
  }
74474
- src.push(" if (dist > 0.0) { discard; }");
74532
+ src.push(" if (dist > sliceThickness) { ");
74533
+ src.push(" discard;");
74534
+ src.push(" }");
74535
+ src.push(" if (dist > 0.0) { ");
74536
+ src.push(" newColor = sliceColor;");
74537
+ src.push(" }");
74475
74538
  src.push("}");
74476
74539
  }
74477
74540
  if (scene.logarithmicDepthBufferEnabled) {
74478
74541
  src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;");
74479
74542
  }
74480
- src.push(" outColor = vColor;");
74543
+ src.push(" outColor = newColor;");
74481
74544
  src.push("}");
74482
74545
  return src;
74483
74546
  }
@@ -74867,10 +74930,14 @@ class DTXTrianglesEdgesColorRenderer {
74867
74930
  src.push("uniform vec3 sectionPlanePos" + i + ";");
74868
74931
  src.push("uniform vec3 sectionPlaneDir" + i + ";");
74869
74932
  }
74933
+ src.push("uniform float sliceThickness;");
74934
+ src.push("uniform vec4 sliceColor;");
74870
74935
  }
74871
74936
  src.push("in vec4 vColor;");
74872
74937
  src.push("out vec4 outColor;");
74873
74938
  src.push("void main(void) {");
74939
+ src.push(" vec4 newColor;");
74940
+ src.push(" newColor = vColor;");
74874
74941
  if (clipping) {
74875
74942
  src.push(" bool clippable = vFlags2 > 0u;");
74876
74943
  src.push(" if (clippable) {");
@@ -74880,13 +74947,18 @@ class DTXTrianglesEdgesColorRenderer {
74880
74947
  src.push(" dist += clamp(dot(-sectionPlaneDir" + i + ".xyz, vWorldPosition.xyz - sectionPlanePos" + i + ".xyz), 0.0, 1000.0);");
74881
74948
  src.push("}");
74882
74949
  }
74883
- src.push(" if (dist > 0.0) { discard; }");
74950
+ src.push(" if (dist > sliceThickness) { ");
74951
+ src.push(" discard;");
74952
+ src.push(" }");
74953
+ src.push(" if (dist > 0.0) { ");
74954
+ src.push(" newColor = sliceColor;");
74955
+ src.push(" }");
74884
74956
  src.push("}");
74885
74957
  }
74886
74958
  if (scene.logarithmicDepthBufferEnabled) {
74887
74959
  src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;");
74888
74960
  }
74889
- src.push(" outColor = vColor;");
74961
+ src.push(" outColor = newColor;");
74890
74962
  src.push("}");
74891
74963
  return src;
74892
74964
  }
@@ -97733,7 +97805,7 @@ class MousePickHandler {
97733
97805
 
97734
97806
  this._timeout = setTimeout(() => {
97735
97807
 
97736
- if (firstClickPickResult && firstClickPickResult.worldPos) {
97808
+ if (firstClickPickResult) {
97737
97809
 
97738
97810
  cameraControl.fire("picked", firstClickPickResult, true);
97739
97811
 
@@ -101925,8 +101997,8 @@ class MetaScene {
101925
101997
 
101926
101998
  for (let modelId in this.metaModels) {
101927
101999
  const metaModel = this.metaModels[modelId];
101928
- for (let i = 0, len = metaModel.metaObjects.length; i < len; i++) {
101929
- const metaObject = metaModel.metaObjects[i];
102000
+ for (let objectId in metaModel.metaObjects) {
102001
+ const metaObject = metaModel.metaObjects[objectId];
101930
102002
  metaObject.metaModels.push(metaModel);
101931
102003
  }
101932
102004
  }
@@ -140850,8 +140922,21 @@ class Zone extends Component {
140850
140922
  }
140851
140923
 
140852
140924
 
140853
- const positions = [].concat(...pos);
140925
+ const min = idx => Math.min(...pos.map(p => p[idx]));
140926
+ const max = idx => Math.max(...pos.map(p => p[idx]));
140927
+
140928
+ const xmin = min(0);
140929
+ const ymin = min(1);
140930
+ const zmin = min(2);
140931
+ const xmax = max(0);
140932
+ const ymax = max(1);
140933
+ const zmax = max(2);
140934
+
140935
+ this._center = math.vec3([ (xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2 ]);
140936
+
140937
+ const positions = [].concat(...pos.map(p => math.subVec3(p, this._center, p)));
140854
140938
  this._zoneMesh = new Mesh(scene, {
140939
+ origin: this._center,
140855
140940
  edges: this._edges,
140856
140941
  geometry: new ReadableGeometry(
140857
140942
  scene,
@@ -140892,19 +140977,6 @@ class Zone extends Component {
140892
140977
  }
140893
140978
 
140894
140979
  this._metrics = null;
140895
-
140896
-
140897
- const min = idx => Math.min(...pos.map(p => p[idx]));
140898
- const max = idx => Math.max(...pos.map(p => p[idx]));
140899
-
140900
- const xmin = min(0);
140901
- const ymin = min(1);
140902
- const zmin = min(2);
140903
- const xmax = max(0);
140904
- const ymax = max(1);
140905
- const zmax = max(2);
140906
-
140907
- this._center = math.vec3([ (xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2 ]);
140908
140980
  }
140909
140981
 
140910
140982
  get baseArea() {