@xeokit/xeokit-sdk 2.6.31 → 2.6.33

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.
@@ -1034,20 +1034,23 @@ class PointerLens {
1034
1034
  this._lensCursorDiv.style.pointerEvents = "none";
1035
1035
 
1036
1036
  this._lensContainer = document.createElement('div');
1037
+ this._lensContainerId = cfg.containerId || 'xeokit-lens';
1038
+ this._lensContainer.setAttribute("id", this._lensContainerId);
1039
+
1037
1040
  this._lensContainer.style.border = "1px solid black";
1038
1041
  this._lensContainer.style.background = "white";
1039
1042
  // this._lensContainer.style.opacity = "0";
1040
1043
  this._lensContainer.style.borderRadius = "50%";
1041
1044
  this._lensContainer.style.width = "300px";
1042
1045
  this._lensContainer.style.height = "300px";
1043
- this._lensContainer.style.marginTop = "85px";
1044
- this._lensContainer.style.marginLeft = "25px";
1046
+
1045
1047
  this._lensContainer.style.zIndex = "15000";
1046
1048
  this._lensContainer.style.position = "absolute";
1047
1049
  this._lensContainer.style.pointerEvents = "none";
1048
1050
  this._lensContainer.style.visibility = "hidden";
1049
1051
 
1050
1052
  this._lensCanvas = document.createElement('canvas');
1053
+ this._lensCanvas.id = `${this._lensContainerId}-canvas`;
1051
1054
  // this._lensCanvas.style.background = "darkblue";
1052
1055
  this._lensCanvas.style.borderRadius = "50%";
1053
1056
 
@@ -1064,7 +1067,12 @@ class PointerLens {
1064
1067
 
1065
1068
  this._canvasPos = null;
1066
1069
  this._snappedCanvasPos = null;
1067
- this._lensPosToggle = true;
1070
+ this._lensPosToggle = cfg.lensPosToggle || true;
1071
+ this._lensPosToggleAmount = cfg.lensPosToggleAmount || 85;
1072
+ this._lensPosMarginLeft = cfg.lensPosMarginLeft || 85;
1073
+ this._lensPosMarginTop = cfg.lensPosMarginTop || 25;
1074
+ this._lensContainer.style.marginTop = `${this._lensPosMarginTop}px`;
1075
+ this._lensContainer.style.marginLeft = `${this._lensPosMarginLeft}px`;
1068
1076
 
1069
1077
  this._zoomLevel = cfg.zoomLevel || 2;
1070
1078
 
@@ -1094,12 +1102,12 @@ class PointerLens {
1094
1102
  const pointerOnLens =
1095
1103
  this._canvasPos[0] < lensRect.right && this._canvasPos[0] > lensRect.left &&
1096
1104
  this._canvasPos[1] < lensRect.bottom && this._canvasPos[1] > lensRect.top;
1097
- this._lensContainer.style.marginLeft = `25px`;
1105
+ this._lensContainer.style.marginLeft = `${this._lensPosMarginLeft}px`;
1098
1106
  if (pointerOnLens) {
1099
1107
  if (this._lensPosToggle) {
1100
- this._lensContainer.style.marginTop = `${canvasRect.bottom - canvasRect.top - this._lensCanvas.height - 85}px`;
1108
+ this._lensContainer.style.marginTop = `${canvasRect.bottom - canvasRect.top - this._lensCanvas.height - this._lensPosToggleAmount}px`;
1101
1109
  } else {
1102
- this._lensContainer.style.marginTop = `85px`;
1110
+ this._lensContainer.style.marginTop = `${this._lensPosMarginTop}px`;
1103
1111
  }
1104
1112
  this._lensPosToggle = !this._lensPosToggle;
1105
1113
  }
@@ -9554,7 +9562,7 @@ class Dot {
9554
9562
  this._dotClickable = document.createElement('div');
9555
9563
  this._dotClickable.className += this._dotClickable.className ? ' viewer-ruler-dot-clickable' : 'viewer-ruler-dot-clickable';
9556
9564
 
9557
- this._visible = !!cfg.visible;
9565
+ this._visible = cfg.visible !== false;
9558
9566
  this._culled = false;
9559
9567
 
9560
9568
  var dot = this._dot;
@@ -9566,7 +9574,7 @@ class Dot {
9566
9574
  dotStyle["z-index"] = cfg.zIndex === undefined ? "40000005" : cfg.zIndex ;
9567
9575
  dotStyle.width = 8 + "px";
9568
9576
  dotStyle.height = 8 + "px";
9569
- dotStyle.visibility = cfg.visible !== false ? "visible" : "hidden";
9577
+ dotStyle.visibility = this._visible ? "visible" : "hidden";
9570
9578
  dotStyle.top = 0 + "px";
9571
9579
  dotStyle.left = 0 + "px";
9572
9580
  dotStyle["box-shadow"] = "0 2px 5px 0 #182A3D;";
@@ -19148,6 +19156,9 @@ const Renderer$1 = function (scene, options) {
19148
19156
  let drawableTypeInfo = {};
19149
19157
  let drawables = {};
19150
19158
 
19159
+ let postSortDrawableList = [];
19160
+ let postCullDrawableList = [];
19161
+
19151
19162
  let drawableListDirty = true;
19152
19163
  let stateSortDirty = true;
19153
19164
  let imageDirty = true;
@@ -19368,33 +19379,33 @@ const Renderer$1 = function (scene, options) {
19368
19379
  }
19369
19380
 
19370
19381
  function sortDrawableList() {
19382
+ let lenDrawableList = 0;
19371
19383
  for (let type in drawableTypeInfo) {
19372
19384
  if (drawableTypeInfo.hasOwnProperty(type)) {
19373
19385
  const drawableInfo = drawableTypeInfo[type];
19374
- if (drawableInfo.isStateSortable) {
19375
- drawableInfo.drawableListPreCull.sort(drawableInfo.stateSortCompare);
19386
+ const drawableListPreCull = drawableInfo.drawableListPreCull;
19387
+ for (let i = 0, len = drawableListPreCull.length; i < len; i++) {
19388
+ const drawable = drawableListPreCull[i];
19389
+ postSortDrawableList[lenDrawableList++] = drawable;
19376
19390
  }
19377
19391
  }
19378
19392
  }
19393
+ postSortDrawableList.length = lenDrawableList;
19394
+ postSortDrawableList.sort((a, b) => {
19395
+ return a.renderOrder - b.renderOrder;
19396
+ });
19379
19397
  }
19380
19398
 
19381
19399
  function cullDrawableList() {
19382
- for (let type in drawableTypeInfo) {
19383
- if (drawableTypeInfo.hasOwnProperty(type)) {
19384
- const drawableInfo = drawableTypeInfo[type];
19385
- const drawableListPreCull = drawableInfo.drawableListPreCull;
19386
- const drawableList = drawableInfo.drawableList;
19387
- let lenDrawableList = 0;
19388
- for (let i = 0, len = drawableListPreCull.length; i < len; i++) {
19389
- const drawable = drawableListPreCull[i];
19390
- drawable.rebuildRenderFlags();
19391
- if (!drawable.renderFlags.culled) {
19392
- drawableList[lenDrawableList++] = drawable;
19393
- }
19394
- }
19395
- drawableList.length = lenDrawableList;
19400
+ let lenDrawableList = 0;
19401
+ for (let i = 0, len = postSortDrawableList.length; i < len; i++) {
19402
+ const drawable = postSortDrawableList[i];
19403
+ drawable.rebuildRenderFlags();
19404
+ if (!drawable.renderFlags.culled) {
19405
+ postCullDrawableList[lenDrawableList++] = drawable;
19396
19406
  }
19397
19407
  }
19408
+ postCullDrawableList.length = lenDrawableList;
19398
19409
  }
19399
19410
 
19400
19411
  function draw(params) {
@@ -19470,25 +19481,16 @@ const Renderer$1 = function (scene, options) {
19470
19481
  if (params.clear !== false) {
19471
19482
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
19472
19483
  }
19484
+ for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
19473
19485
 
19474
- for (let type in drawableTypeInfo) {
19475
- if (drawableTypeInfo.hasOwnProperty(type)) {
19476
-
19477
- const drawableInfo = drawableTypeInfo[type];
19478
- const drawableList = drawableInfo.drawableList;
19479
-
19480
- for (let i = 0, len = drawableList.length; i < len; i++) {
19481
-
19482
- const drawable = drawableList[i];
19486
+ const drawable = postCullDrawableList[i];
19483
19487
 
19484
- if (drawable.culled === true || drawable.visible === false || !drawable.drawDepth || !drawable.saoEnabled) {
19485
- continue;
19486
- }
19488
+ if (drawable.culled === true || drawable.visible === false || !drawable.drawDepth || !drawable.saoEnabled) {
19489
+ continue;
19490
+ }
19487
19491
 
19488
- if (drawable.renderFlags.colorOpaque) {
19489
- drawable.drawDepth(frameCtx);
19490
- }
19491
- }
19492
+ if (drawable.renderFlags.colorOpaque) {
19493
+ drawable.drawDepth(frameCtx);
19492
19494
  }
19493
19495
  }
19494
19496
 
@@ -19627,7 +19629,6 @@ const Renderer$1 = function (scene, options) {
19627
19629
  }
19628
19630
 
19629
19631
  let i;
19630
- let len;
19631
19632
  let drawable;
19632
19633
 
19633
19634
  const startTime = Date.now();
@@ -19660,93 +19661,85 @@ const Renderer$1 = function (scene, options) {
19660
19661
  // Render normal opaque solids, defer others to bins to render after
19661
19662
  //------------------------------------------------------------------------------------------------------
19662
19663
 
19663
- for (let type in drawableTypeInfo) {
19664
- if (drawableTypeInfo.hasOwnProperty(type)) {
19665
-
19666
- const drawableInfo = drawableTypeInfo[type];
19667
- const drawableList = drawableInfo.drawableList;
19664
+ for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
19668
19665
 
19669
- for (i = 0, len = drawableList.length; i < len; i++) {
19666
+ drawable = postCullDrawableList[i];
19670
19667
 
19671
- drawable = drawableList[i];
19672
-
19673
- if (drawable.culled === true || drawable.visible === false) {
19674
- continue;
19675
- }
19668
+ if (drawable.culled === true || drawable.visible === false) {
19669
+ continue;
19670
+ }
19676
19671
 
19677
- const renderFlags = drawable.renderFlags;
19672
+ const renderFlags = drawable.renderFlags;
19678
19673
 
19679
- if (renderFlags.colorOpaque) {
19680
- if (saoEnabled && saoPossible && drawable.saoEnabled) {
19681
- normalDrawSAOBin[normalDrawSAOBinLen++] = drawable;
19682
- } else {
19683
- drawable.drawColorOpaque(frameCtx);
19684
- }
19685
- }
19674
+ if (renderFlags.colorOpaque) {
19675
+ if (saoEnabled && saoPossible && drawable.saoEnabled) {
19676
+ normalDrawSAOBin[normalDrawSAOBinLen++] = drawable;
19677
+ } else {
19678
+ drawable.drawColorOpaque(frameCtx);
19679
+ }
19680
+ }
19686
19681
 
19687
- if (transparentEnabled) {
19688
- if (renderFlags.colorTransparent) {
19689
- normalFillTransparentBin[normalFillTransparentBinLen++] = drawable;
19690
- }
19691
- }
19682
+ if (transparentEnabled) {
19683
+ if (renderFlags.colorTransparent) {
19684
+ normalFillTransparentBin[normalFillTransparentBinLen++] = drawable;
19685
+ }
19686
+ }
19692
19687
 
19693
- if (renderFlags.xrayedSilhouetteTransparent) {
19694
- xrayedFillTransparentBin[xrayedFillTransparentBinLen++] = drawable;
19695
- }
19688
+ if (renderFlags.xrayedSilhouetteTransparent) {
19689
+ xrayedFillTransparentBin[xrayedFillTransparentBinLen++] = drawable;
19690
+ }
19696
19691
 
19697
- if (renderFlags.xrayedSilhouetteOpaque) {
19698
- xrayedFillOpaqueBin[xrayedFillOpaqueBinLen++] = drawable;
19699
- }
19692
+ if (renderFlags.xrayedSilhouetteOpaque) {
19693
+ xrayedFillOpaqueBin[xrayedFillOpaqueBinLen++] = drawable;
19694
+ }
19700
19695
 
19701
- if (renderFlags.highlightedSilhouetteTransparent) {
19702
- highlightedFillTransparentBin[highlightedFillTransparentBinLen++] = drawable;
19703
- }
19696
+ if (renderFlags.highlightedSilhouetteTransparent) {
19697
+ highlightedFillTransparentBin[highlightedFillTransparentBinLen++] = drawable;
19698
+ }
19704
19699
 
19705
- if (renderFlags.highlightedSilhouetteOpaque) {
19706
- highlightedFillOpaqueBin[highlightedFillOpaqueBinLen++] = drawable;
19707
- }
19700
+ if (renderFlags.highlightedSilhouetteOpaque) {
19701
+ highlightedFillOpaqueBin[highlightedFillOpaqueBinLen++] = drawable;
19702
+ }
19708
19703
 
19709
- if (renderFlags.selectedSilhouetteTransparent) {
19710
- selectedFillTransparentBin[selectedFillTransparentBinLen++] = drawable;
19711
- }
19704
+ if (renderFlags.selectedSilhouetteTransparent) {
19705
+ selectedFillTransparentBin[selectedFillTransparentBinLen++] = drawable;
19706
+ }
19712
19707
 
19713
- if (renderFlags.selectedSilhouetteOpaque) {
19714
- selectedFillOpaqueBin[selectedFillOpaqueBinLen++] = drawable;
19715
- }
19708
+ if (renderFlags.selectedSilhouetteOpaque) {
19709
+ selectedFillOpaqueBin[selectedFillOpaqueBinLen++] = drawable;
19710
+ }
19716
19711
 
19717
- if (drawable.edges && edgesEnabled) {
19718
- if (renderFlags.edgesOpaque) {
19719
- normalEdgesOpaqueBin[normalEdgesOpaqueBinLen++] = drawable;
19720
- }
19712
+ if (drawable.edges && edgesEnabled) {
19713
+ if (renderFlags.edgesOpaque) {
19714
+ normalEdgesOpaqueBin[normalEdgesOpaqueBinLen++] = drawable;
19715
+ }
19721
19716
 
19722
- if (renderFlags.edgesTransparent) {
19723
- normalEdgesTransparentBin[normalEdgesTransparentBinLen++] = drawable;
19724
- }
19717
+ if (renderFlags.edgesTransparent) {
19718
+ normalEdgesTransparentBin[normalEdgesTransparentBinLen++] = drawable;
19719
+ }
19725
19720
 
19726
- if (renderFlags.selectedEdgesTransparent) {
19727
- selectedEdgesTransparentBin[selectedEdgesTransparentBinLen++] = drawable;
19728
- }
19721
+ if (renderFlags.selectedEdgesTransparent) {
19722
+ selectedEdgesTransparentBin[selectedEdgesTransparentBinLen++] = drawable;
19723
+ }
19729
19724
 
19730
- if (renderFlags.selectedEdgesOpaque) {
19731
- selectedEdgesOpaqueBin[selectedEdgesOpaqueBinLen++] = drawable;
19732
- }
19725
+ if (renderFlags.selectedEdgesOpaque) {
19726
+ selectedEdgesOpaqueBin[selectedEdgesOpaqueBinLen++] = drawable;
19727
+ }
19733
19728
 
19734
- if (renderFlags.xrayedEdgesTransparent) {
19735
- xrayEdgesTransparentBin[xrayEdgesTransparentBinLen++] = drawable;
19736
- }
19729
+ if (renderFlags.xrayedEdgesTransparent) {
19730
+ xrayEdgesTransparentBin[xrayEdgesTransparentBinLen++] = drawable;
19731
+ }
19737
19732
 
19738
- if (renderFlags.xrayedEdgesOpaque) {
19739
- xrayEdgesOpaqueBin[xrayEdgesOpaqueBinLen++] = drawable;
19740
- }
19733
+ if (renderFlags.xrayedEdgesOpaque) {
19734
+ xrayEdgesOpaqueBin[xrayEdgesOpaqueBinLen++] = drawable;
19735
+ }
19741
19736
 
19742
- if (renderFlags.highlightedEdgesTransparent) {
19743
- highlightedEdgesTransparentBin[highlightedEdgesTransparentBinLen++] = drawable;
19744
- }
19737
+ if (renderFlags.highlightedEdgesTransparent) {
19738
+ highlightedEdgesTransparentBin[highlightedEdgesTransparentBinLen++] = drawable;
19739
+ }
19745
19740
 
19746
- if (renderFlags.highlightedEdgesOpaque) {
19747
- highlightedEdgesOpaqueBin[highlightedEdgesOpaqueBinLen++] = drawable;
19748
- }
19749
- }
19741
+ if (renderFlags.highlightedEdgesOpaque) {
19742
+ highlightedEdgesOpaqueBin[highlightedEdgesOpaqueBinLen++] = drawable;
19750
19743
  }
19751
19744
  }
19752
19745
  }
@@ -20152,7 +20145,7 @@ const Renderer$1 = function (scene, options) {
20152
20145
  frameCtx.pickInvisible = !!params.pickInvisible;
20153
20146
  frameCtx.pickClipPos = [
20154
20147
  getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
20155
- getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight),
20148
+ getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight)
20156
20149
  ];
20157
20150
 
20158
20151
  gl.viewport(0, 0, 1, 1);
@@ -20165,30 +20158,23 @@ const Renderer$1 = function (scene, options) {
20165
20158
  const includeEntityIds = params.includeEntityIds;
20166
20159
  const excludeEntityIds = params.excludeEntityIds;
20167
20160
 
20168
- for (let type in drawableTypeInfo) {
20169
- if (drawableTypeInfo.hasOwnProperty(type)) {
20170
-
20171
- const drawableInfo = drawableTypeInfo[type];
20172
- const drawableList = drawableInfo.drawableList;
20173
-
20174
- for (let i = 0, len = drawableList.length; i < len; i++) {
20175
-
20176
- const drawable = drawableList[i];
20177
-
20178
- if (!drawable.drawPickMesh || (params.pickInvisible !== true && drawable.visible === false) || drawable.pickable === false) {
20179
- continue;
20180
- }
20181
- if (includeEntityIds && !includeEntityIds[drawable.id]) { // TODO: push this logic into drawable
20182
- continue;
20183
- }
20184
- if (excludeEntityIds && excludeEntityIds[drawable.id]) {
20185
- continue;
20186
- }
20187
-
20188
- drawable.drawPickMesh(frameCtx);
20189
- }
20161
+ for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
20162
+ const drawable = postCullDrawableList[i];
20163
+ if (drawable.culled === true || drawable.visible === false) {
20164
+ continue;
20165
+ }
20166
+ if (!drawable.drawPickMesh || (params.pickInvisible !== true && drawable.visible === false) || drawable.pickable === false) {
20167
+ continue;
20168
+ }
20169
+ if (includeEntityIds && !includeEntityIds[drawable.id]) { // TODO: push this logic into drawable
20170
+ continue;
20190
20171
  }
20172
+ if (excludeEntityIds && excludeEntityIds[drawable.id]) {
20173
+ continue;
20174
+ }
20175
+ drawable.drawPickMesh(frameCtx);
20191
20176
  }
20177
+
20192
20178
  const pix = pickBuffer.read(0, 0);
20193
20179
  const pickID = pix[0] + (pix[1] << 8) + (pix[2] << 16) + (pix[3] << 24);
20194
20180
 
@@ -20218,7 +20204,7 @@ const Renderer$1 = function (scene, options) {
20218
20204
  // frameCtx.pickInvisible = !!params.pickInvisible;
20219
20205
  frameCtx.pickClipPos = [
20220
20206
  getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
20221
- getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight),
20207
+ getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight)
20222
20208
  ];
20223
20209
 
20224
20210
  gl.viewport(0, 0, 1, 1);
@@ -20267,7 +20253,7 @@ const Renderer$1 = function (scene, options) {
20267
20253
  frameCtx.pickElementsOffset = pickable.pickElementsOffset;
20268
20254
  frameCtx.pickClipPos = [
20269
20255
  getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
20270
- getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight),
20256
+ getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight)
20271
20257
  ];
20272
20258
 
20273
20259
  gl.viewport(0, 0, 1, 1);
@@ -20332,15 +20318,14 @@ const Renderer$1 = function (scene, options) {
20332
20318
  function drawSnapInit(frameCtx) {
20333
20319
  frameCtx.snapPickLayerParams = [];
20334
20320
  frameCtx.snapPickLayerNumber = 0;
20335
- for (let type in drawableTypeInfo) {
20336
- const drawableInfo = drawableTypeInfo[type];
20337
- const drawableList = drawableInfo.drawableList;
20338
- for (let i = 0, len = drawableList.length; i < len; i++) {
20339
- const drawable = drawableList[i];
20340
- if (drawable.drawSnapInit) {
20341
- if (!drawable.culled && drawable.visible && drawable.pickable) {
20342
- drawable.drawSnapInit(frameCtx);
20343
- }
20321
+
20322
+ for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
20323
+
20324
+ const drawable = postCullDrawableList[i];
20325
+
20326
+ if (drawable.drawSnapInit) {
20327
+ if (!drawable.culled && drawable.visible && drawable.pickable) {
20328
+ drawable.drawSnapInit(frameCtx);
20344
20329
  }
20345
20330
  }
20346
20331
  }
@@ -20350,11 +20335,11 @@ const Renderer$1 = function (scene, options) {
20350
20335
  function drawSnap(frameCtx) {
20351
20336
  frameCtx.snapPickLayerParams = frameCtx.snapPickLayerParams || [];
20352
20337
  frameCtx.snapPickLayerNumber = frameCtx.snapPickLayerParams.length;
20353
- for (let type in drawableTypeInfo) {
20354
- const drawableInfo = drawableTypeInfo[type];
20355
- const drawableList = drawableInfo.drawableList;
20356
- for (let i = 0, len = drawableList.length; i < len; i++) {
20357
- const drawable = drawableList[i];
20338
+ for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
20339
+
20340
+ const drawable = postCullDrawableList[i];
20341
+
20342
+ if (drawable.drawSnapInit) {
20358
20343
  if (drawable.drawSnap) {
20359
20344
  if (!drawable.culled && drawable.visible && drawable.pickable) {
20360
20345
  drawable.drawSnap(frameCtx);
@@ -20744,19 +20729,16 @@ const Renderer$1 = function (scene, options) {
20744
20729
  gl.disable(gl.BLEND);
20745
20730
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
20746
20731
 
20747
- for (let type in drawableTypeInfo) {
20748
- if (drawableTypeInfo.hasOwnProperty(type)) {
20749
- const drawableInfo = drawableTypeInfo[type];
20750
- const drawableList = drawableInfo.drawableList;
20751
- for (let i = 0, len = drawableList.length; i < len; i++) {
20752
- const drawable = drawableList[i];
20753
- if (!drawable.drawOcclusion || drawable.culled === true || drawable.visible === false || drawable.pickable === false) { // TODO: Option to exclude transparent?
20754
- continue;
20755
- }
20756
20732
 
20757
- drawable.drawOcclusion(frameCtx);
20758
- }
20733
+ for (let i = 0, len = postCullDrawableList.length; i < len; i++) {
20734
+
20735
+ const drawable = postCullDrawableList[i];
20736
+
20737
+ if (!drawable.drawOcclusion || drawable.culled === true || drawable.visible === false || drawable.pickable === false) { // TODO: Option to exclude transparent?
20738
+ continue;
20759
20739
  }
20740
+
20741
+ drawable.drawOcclusion(frameCtx);
20760
20742
  }
20761
20743
 
20762
20744
  this._occlusionTester.drawMarkers(frameCtx);
@@ -50886,7 +50868,7 @@ class MeshVolume {
50886
50868
  volume += math.dotVec3(v1$1, v3$1);
50887
50869
  }
50888
50870
 
50889
- return volume;
50871
+ return volume / 6;
50890
50872
  }
50891
50873
  }
50892
50874
 
@@ -61410,7 +61392,7 @@ class VBOInstancingTrianglesLayer {
61410
61392
  */
61411
61393
  constructor(cfg) {
61412
61394
 
61413
- // console.info("Creating VBOInstancingTrianglesLayer");
61395
+ // console.info("Creating VBOInstancingTrianglesLayer");
61414
61396
 
61415
61397
  /**
61416
61398
  * Owner model
@@ -61752,7 +61734,9 @@ class VBOInstancingTrianglesLayer {
61752
61734
  && !!textureSet
61753
61735
  && !!textureSet.colorTexture;
61754
61736
 
61755
- this._state.geometry = null;
61737
+ if (!this.model.scene.readableGeometryEnabled) {
61738
+ this._state.geometry = null;
61739
+ }
61756
61740
 
61757
61741
  this._finalized = true;
61758
61742
  }
@@ -62079,11 +62063,11 @@ class VBOInstancingTrianglesLayer {
62079
62063
  this.model.error("portion not found: " + portionId);
62080
62064
  return;
62081
62065
  }
62082
- const positions = geometry.quantizedPositions;
62066
+ const positions = geometry.positionsCompressed;
62083
62067
  const origin = state.origin;
62084
- const offsetX = origin[0] ;
62085
- const offsetY = origin[1] ;
62086
- const offsetZ = origin[2] ;
62068
+ const offsetX = origin[0];
62069
+ const offsetY = origin[1];
62070
+ const offsetZ = origin[2];
62087
62071
  const worldPos = tempVec4a$7;
62088
62072
  const portionMatrix = portion.matrix;
62089
62073
  const sceneModelMatrix = this.model.matrix;
@@ -62159,7 +62143,7 @@ class VBOInstancingTrianglesLayer {
62159
62143
  return;
62160
62144
  }
62161
62145
  this._updateBackfaceCull(renderFlags, frameCtx);
62162
- const useAlphaCutoff = this._state.textureSet && (typeof(this._state.textureSet.alphaCutoff) === "number");
62146
+ const useAlphaCutoff = this._state.textureSet && (typeof (this._state.textureSet.alphaCutoff) === "number");
62163
62147
  if (frameCtx.withSAO && this.model.saoEnabled) {
62164
62148
  if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {
62165
62149
  if (this._renderers.pbrRendererWithSAO) {
@@ -65579,7 +65563,9 @@ class VBOInstancingLinesLayer {
65579
65563
  this._modelMatrixCol1 = [];
65580
65564
  this._modelMatrixCol2 = [];
65581
65565
  }
65582
- this._state.geometry = null;
65566
+ if (!this.model.scene.readableGeometryEnabled) {
65567
+ this._state.geometry = null;
65568
+ }
65583
65569
  this._finalized = true;
65584
65570
  }
65585
65571
 
@@ -87815,6 +87801,7 @@ function colorizeToRGB(color) {
87815
87801
  }
87816
87802
 
87817
87803
  const distVec3 = math.vec3();
87804
+ const tmpVec3 = math.vec3();
87818
87805
 
87819
87806
  const lengthWire = (x1, y1, x2, y2) => {
87820
87807
  var a = x1 - x2;
@@ -88125,6 +88112,44 @@ class DistanceMeasurement extends Component {
88125
88112
  this.labelsVisible = cfg.labelsVisible;
88126
88113
  this.labelsOnWires = cfg.labelsOnWires;
88127
88114
  this.useRotationAdjustment = cfg.useRotationAdjustment;
88115
+
88116
+ /**
88117
+ * @type {number[]}
88118
+ */
88119
+ this._axesBasis = [
88120
+ 1, 0, 0, 0,
88121
+ 0, 1, 0, 0,
88122
+ 0, 0, 1, 0,
88123
+ 0, 0, 0, 1,
88124
+ ];
88125
+ }
88126
+
88127
+ /**
88128
+ * Sets the axes basis for the measurement.
88129
+ *
88130
+ * The value is a 4x4 matrix where each column-vector defines an axis and must have unit length.
88131
+ *
88132
+ * This is the ```identity``` matrix by default, meaning the measurement axes are the same as the world axes.
88133
+ *
88134
+ * @param {number[]} value
88135
+ */
88136
+ set axesBasis(value) {
88137
+ this._axesBasis = value.slice();
88138
+ this._wpDirty = true;
88139
+ this._needUpdate(0); // No lag
88140
+ }
88141
+
88142
+ /**
88143
+ * Gets the axes basis for the measurement.
88144
+ *
88145
+ * The value is a 4x4 matrix where each column-vector defines an axis and must have unit length.
88146
+ *
88147
+ * This is the ```identity``` matrix by default, meaning the measurement axes are the same as the world axes.
88148
+ *
88149
+ * @type {number[]}
88150
+ */
88151
+ get axesBasis() {
88152
+ return this._axesBasis;
88128
88153
  }
88129
88154
 
88130
88155
  _update() {
@@ -88160,20 +88185,30 @@ class DistanceMeasurement extends Component {
88160
88185
  this._wp[15] = 1.0;
88161
88186
  }
88162
88187
  else {
88188
+ const delta = math.subVec3(
88189
+ this._targetWorld,
88190
+ this._originWorld,
88191
+ tmpVec3
88192
+ );
88193
+
88194
+ /**
88195
+ * The length detected for each measurement axis.
88196
+ */
88197
+ this._factors = math.transformVec3(this._axesBasis, delta);
88198
+
88163
88199
  this._wp[0] = this._originWorld[0];
88164
88200
  this._wp[1] = this._originWorld[1];
88165
88201
  this._wp[2] = this._originWorld[2];
88166
88202
  this._wp[3] = 1.0;
88167
88203
 
88168
- this._wp[4] = this._targetWorld[0];
88169
- this._wp[5] = this._originWorld[1];
88170
- this._wp[6] = this._originWorld[2];
88204
+ this._wp[4] = this._originWorld[0] + this._axesBasis[0]*this._factors[0];
88205
+ this._wp[5] = this._originWorld[1] + this._axesBasis[4]*this._factors[0];
88206
+ this._wp[6] = this._originWorld[2] + this._axesBasis[8]*this._factors[0];
88171
88207
  this._wp[7] = 1.0;
88172
88208
 
88173
- this._wp[8] = this._targetWorld[0];
88174
- this._wp[9] = this._targetWorld[1];
88175
- this._wp[10] = this._originWorld[2];
88176
- this._wp[11] = 1.0;
88209
+ this._wp[8] = this._originWorld[0] + this._axesBasis[0]*this._factors[0]+ this._axesBasis[1]*this._factors[1];
88210
+ this._wp[9] = this._originWorld[1] + this._axesBasis[4]*this._factors[0]+ this._axesBasis[5]*this._factors[1];
88211
+ this._wp[10] = this._originWorld[2] + this._axesBasis[8]*this._factors[0]+ this._axesBasis[9]*this._factors[1]; this._wp[11] = 1.0;
88177
88212
 
88178
88213
  this._wp[12] = this._targetWorld[0];
88179
88214
  this._wp[13] = this._targetWorld[1];
@@ -88334,14 +88369,14 @@ class DistanceMeasurement extends Component {
88334
88369
  }
88335
88370
 
88336
88371
  if (!this._xAxisLabelCulled) {
88337
- this._xAxisLabel.setText(tilde + Math.abs((this._targetWorld[0] - this._originWorld[0]) * scale).toFixed(2) + unitAbbrev);
88372
+ this._xAxisLabel.setText(tilde + Math.abs(this._factors[0] * scale).toFixed(2) + unitAbbrev);
88338
88373
  this._xAxisLabel.setCulled(!this.axisVisible);
88339
88374
  } else {
88340
88375
  this._xAxisLabel.setCulled(true);
88341
88376
  }
88342
88377
 
88343
88378
  if (!this._yAxisLabelCulled) {
88344
- this._yAxisLabel.setText(tilde + Math.abs((this._targetWorld[1] - this._originWorld[1]) * scale).toFixed(2) + unitAbbrev);
88379
+ this._yAxisLabel.setText(tilde + Math.abs(this._factors[1] * scale).toFixed(2) + unitAbbrev);
88345
88380
  this._yAxisLabel.setCulled(!this.axisVisible);
88346
88381
  } else {
88347
88382
  this._yAxisLabel.setCulled(true);
@@ -88354,7 +88389,7 @@ class DistanceMeasurement extends Component {
88354
88389
  }
88355
88390
  else {
88356
88391
  this._zAxisLabel.setPrefix("Z");
88357
- this._zAxisLabel.setText(tilde + Math.abs((this._targetWorld[2] - this._originWorld[2]) * scale).toFixed(2) + unitAbbrev);
88392
+ this._zAxisLabel.setText(tilde + Math.abs(this._factors[2] * scale).toFixed(2) + unitAbbrev);
88358
88393
  }
88359
88394
  this._zAxisLabel.setCulled(!this.axisVisible);
88360
88395
  } else {
@@ -132473,6 +132508,9 @@ class XKTLoaderPlugin extends Plugin {
132473
132508
  * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable
132474
132509
  * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point
132475
132510
  * primitives. Only works while {@link DTX#enabled} is also ````true````.
132511
+ * @param {Number} [params.renderOrder=0] Specifies the rendering order for the model. This is used to control the order in which
132512
+ * SceneModels are drawn when they have transparent objects, to give control over the order in which those objects are blended within the transparent
132513
+ * render pass.
132476
132514
  * @returns {Entity} Entity representing the model, which will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#models}.
132477
132515
  */
132478
132516
  load(params = {}) {
@@ -132522,7 +132560,8 @@ class XKTLoaderPlugin extends Plugin {
132522
132560
  origin: params.origin,
132523
132561
  disableVertexWelding: params.disableVertexWelding || false,
132524
132562
  disableIndexRebucketing: params.disableIndexRebucketing || false,
132525
- dtxEnabled: params.dtxEnabled
132563
+ dtxEnabled: params.dtxEnabled,
132564
+ renderOrder: params.renderOrder
132526
132565
  }));
132527
132566
 
132528
132567
  const modelId = sceneModel.id; // In case ID was auto-generated
@@ -139728,10 +139767,9 @@ const basePolygon3D = function(scene, color, alpha) {
139728
139767
  };
139729
139768
  };
139730
139769
 
139731
- const startAAZoneCreateUI = function(scene, zoneAltitude, zoneHeight, zoneColor, zoneAlpha, pointerLens, zonesPlugin, select3dPoint, onZoneCreated) {
139732
- const marker1 = marker3D(scene, zoneColor);
139733
- const marker2 = marker3D(scene, zoneColor);
139734
- const basePolygon = basePolygon3D(scene, zoneColor, zoneAlpha);
139770
+ const startAARectCreateUI = function(scene, markersColor, pointerLens, select3dPoint, withPoints, onPointsSelected) {
139771
+ const marker1 = marker3D(scene, markersColor);
139772
+ const marker2 = marker3D(scene, markersColor);
139735
139773
 
139736
139774
  const updatePointerLens = (pointerLens
139737
139775
  ? function(canvasPos) {
@@ -139759,29 +139797,14 @@ const startAAZoneCreateUI = function(scene, zoneAltitude, zoneHeight, zoneColor,
139759
139797
  function() {
139760
139798
  updatePointerLens(null);
139761
139799
  marker2.update(null);
139762
- basePolygon.updateBase(null);
139800
+ withPoints(null);
139763
139801
  },
139764
139802
  function(canvasPos, point2WorldPos) {
139765
139803
  updatePointerLens(canvasPos);
139766
139804
  marker2.update(point2WorldPos);
139767
-
139768
- if (math.distVec3(point1WorldPos, point2WorldPos) > 0.01)
139769
- {
139770
- const min = (idx) => Math.min(point1WorldPos[idx], point2WorldPos[idx]);
139771
- const max = (idx) => Math.max(point1WorldPos[idx], point2WorldPos[idx]);
139772
-
139773
- const xmin = min(0);
139774
- const ymin = min(1);
139775
- const zmin = min(2);
139776
- const xmax = max(0);
139777
- max(1);
139778
- const zmax = max(2);
139779
-
139780
- basePolygon.updateBase([ [ xmin, ymin, zmax ], [ xmax, ymin, zmax ],
139781
- [ xmax, ymin, zmin ], [ xmin, ymin, zmin ] ]);
139782
- }
139783
- else
139784
- basePolygon.updateBase(null);
139805
+ withPoints((math.distVec3(point1WorldPos, point2WorldPos) > 0.01)
139806
+ &&
139807
+ [ point1WorldPos, point2WorldPos ]);
139785
139808
  },
139786
139809
  function(point2CanvasPos, point2WorldPos) {
139787
139810
  // `marker2.update' makes sure marker's position has been updated from its default [0,0,0]
@@ -139791,35 +139814,9 @@ const startAAZoneCreateUI = function(scene, zoneAltitude, zoneHeight, zoneColor,
139791
139814
 
139792
139815
  marker1.destroy();
139793
139816
  marker2.destroy();
139794
- basePolygon.destroy();
139795
139817
  updatePointerLens(null);
139796
139818
 
139797
- const min = (idx) => Math.min(point1WorldPos[idx], point2WorldPos[idx]);
139798
- const max = (idx) => Math.max(point1WorldPos[idx], point2WorldPos[idx]);
139799
-
139800
- const xmin = min(0);
139801
- const zmin = min(2);
139802
- const xmax = max(0);
139803
- const zmax = max(2);
139804
-
139805
- const zone = zonesPlugin.createZone(
139806
- {
139807
- id: math.createUUID(),
139808
- geometry: {
139809
- planeCoordinates: [
139810
- [ xmin, zmax ],
139811
- [ xmax, zmax ],
139812
- [ xmax, zmin ],
139813
- [ xmin, zmin ]
139814
- ],
139815
- altitude: zoneAltitude,
139816
- height: zoneHeight
139817
- },
139818
- alpha: zoneAlpha,
139819
- color: zoneColor
139820
- });
139821
-
139822
- onZoneCreated(zone);
139819
+ onPointsSelected([ point1WorldPos, point2WorldPos ]);
139823
139820
  });
139824
139821
  });
139825
139822
 
@@ -139828,7 +139825,6 @@ const startAAZoneCreateUI = function(scene, zoneAltitude, zoneHeight, zoneColor,
139828
139825
  deactivatePointSelection();
139829
139826
  marker1.destroy();
139830
139827
  marker2.destroy();
139831
- basePolygon.destroy();
139832
139828
  updatePointerLens(null);
139833
139829
  }
139834
139830
  };
@@ -140488,6 +140484,34 @@ class Zone extends Component {
140488
140484
  }
140489
140485
  }
140490
140486
 
140487
+ const createAAZoneFromPoints = function(pos1, pos2, zoneAltitude, zoneHeight, zoneColor, zoneAlpha, zonesPlugin) {
140488
+
140489
+ const min = (idx) => Math.min(pos1[idx], pos2[idx]);
140490
+ const max = (idx) => Math.max(pos1[idx], pos2[idx]);
140491
+
140492
+ const xmin = min(0);
140493
+ const zmin = min(2);
140494
+ const xmax = max(0);
140495
+ const zmax = max(2);
140496
+
140497
+ return zonesPlugin.createZone(
140498
+ {
140499
+ id: math.createUUID(),
140500
+ geometry: {
140501
+ planeCoordinates: [
140502
+ [ xmin, zmax ],
140503
+ [ xmax, zmax ],
140504
+ [ xmax, zmin ],
140505
+ [ xmin, zmin ]
140506
+ ],
140507
+ altitude: zoneAltitude,
140508
+ height: zoneHeight
140509
+ },
140510
+ alpha: zoneAlpha,
140511
+ color: zoneColor
140512
+ });
140513
+ };
140514
+
140491
140515
  /**
140492
140516
  * Creates {@link Zone}s in a {@link ZonesPlugin} from mouse input.
140493
140517
  *
@@ -140518,7 +140542,7 @@ class Zone extends Component {
140518
140542
  * const zonesControl = new ZonesMouseControl(Zones)
140519
140543
  * ````
140520
140544
  */
140521
- class ZonesMouseControl extends Component {
140545
+ class ZonesAAZoneControl extends Component {
140522
140546
 
140523
140547
  /**
140524
140548
  * Creates a ZonesMouseControl bound to the given ZonesPlugin.
@@ -140527,11 +140551,12 @@ class ZonesMouseControl extends Component {
140527
140551
  * @param [cfg] Configuration
140528
140552
  * @param {PointerLens} [cfg.pointerLens] A PointerLens to use to provide a magnified view of the cursor when snapping is enabled.
140529
140553
  */
140530
- constructor(zonesPlugin, cfg = {}) {
140554
+ constructor(zonesPlugin, cfg, createSelect3dPoint) {
140531
140555
  super(zonesPlugin.viewer.scene);
140532
140556
 
140533
140557
  this.zonesPlugin = zonesPlugin;
140534
140558
  this.pointerLens = cfg.pointerLens;
140559
+ this.createSelect3dPoint = createSelect3dPoint;
140535
140560
  this._deactivate = null;
140536
140561
  }
140537
140562
 
@@ -140568,16 +140593,35 @@ class ZonesMouseControl extends Component {
140568
140593
  const scene = viewer.scene;
140569
140594
  const self = this;
140570
140595
 
140571
- const select3dPoint = mousePointSelector(
140572
- viewer,
140573
- function(origin, direction) {
140574
- return planeIntersect(zoneAltitude, math.vec3([ 0, 1, 0 ]), origin, direction);
140575
- });
140596
+ const select3dPoint = this.createSelect3dPoint(viewer, (origin, direction) => planeIntersect(zoneAltitude, math.vec3([ 0, 1, 0 ]), origin, direction));
140576
140597
 
140577
140598
  (function rec() {
140578
- self._deactivate = startAAZoneCreateUI(
140579
- scene, zoneAltitude, zoneHeight, zoneColor, zoneAlpha, self.pointerLens, zonesPlugin, select3dPoint,
140580
- zone => {
140599
+ const basePolygon = basePolygon3D(scene, zoneColor, zoneAlpha);
140600
+ const deactivate = startAARectCreateUI(
140601
+ scene, zoneColor, self.pointerLens, select3dPoint,
140602
+ points => {
140603
+ if (points) {
140604
+ const p0 = points[0];
140605
+ const p1 = points[1];
140606
+ const min = (idx) => Math.min(p0[idx], p1[idx]);
140607
+ const max = (idx) => Math.max(p0[idx], p1[idx]);
140608
+
140609
+ const xmin = min(0);
140610
+ const ymin = min(1);
140611
+ const zmin = min(2);
140612
+ const xmax = max(0);
140613
+ max(1);
140614
+ const zmax = max(2);
140615
+
140616
+ basePolygon.updateBase([ [ xmin, ymin, zmax ], [ xmax, ymin, zmax ],
140617
+ [ xmax, ymin, zmin ], [ xmin, ymin, zmin ] ]);
140618
+ } else {
140619
+ basePolygon.updateBase(null);
140620
+ }
140621
+ },
140622
+ points => {
140623
+ basePolygon.destroy();
140624
+ const zone = createAAZoneFromPoints(points[0], points[1], zoneAltitude, zoneHeight, zoneColor, zoneAlpha, zonesPlugin);
140581
140625
  let reactivate = true;
140582
140626
  self._deactivate = () => { reactivate = false; };
140583
140627
  self.fire("zoneEnd", zone);
@@ -140586,6 +140630,10 @@ class ZonesMouseControl extends Component {
140586
140630
  rec();
140587
140631
  }
140588
140632
  }).deactivate;
140633
+ self._deactivate = () => {
140634
+ deactivate();
140635
+ basePolygon.destroy();
140636
+ };
140589
140637
  })();
140590
140638
  }
140591
140639
 
@@ -140608,6 +140656,30 @@ class ZonesMouseControl extends Component {
140608
140656
  }
140609
140657
  }
140610
140658
 
140659
+ class ZonesMouseControl extends ZonesAAZoneControl {
140660
+ constructor(zonesPlugin, cfg = {}) {
140661
+ super(
140662
+ zonesPlugin,
140663
+ cfg,
140664
+ (viewer, ray2WorldPos) => mousePointSelector(viewer, ray2WorldPos));
140665
+ }
140666
+ }
140667
+ class ZonesTouchControl extends ZonesAAZoneControl {
140668
+ constructor(zonesPlugin, cfg = {}) {
140669
+ const pointerCircle = new PointerCircle(zonesPlugin.viewer);
140670
+ super(
140671
+ zonesPlugin,
140672
+ cfg,
140673
+ (viewer, ray2WorldPos) => touchPointSelector(viewer, pointerCircle, ray2WorldPos));
140674
+ this.pointerCircle = pointerCircle;
140675
+ }
140676
+
140677
+ destroy() {
140678
+ this.pointerCircle.destroy();
140679
+ super.destroy();
140680
+ }
140681
+ }
140682
+
140611
140683
  /**
140612
140684
  * ZonesPlugin documentation to be added, mostly compatible with DistanceMeasurementsPlugin.
140613
140685
  */
@@ -140722,86 +140794,6 @@ class ZonesPlugin extends Plugin {
140722
140794
  }
140723
140795
  }
140724
140796
 
140725
- class ZonesTouchControl extends Component {
140726
-
140727
- constructor(zonesPlugin, cfg = {}) {
140728
- super(zonesPlugin.viewer.scene);
140729
-
140730
- this.zonesPlugin = zonesPlugin;
140731
- this.pointerLens = cfg.pointerLens;
140732
- this.pointerCircle = new PointerCircle(zonesPlugin.viewer);
140733
- this._deactivate = null;
140734
- }
140735
-
140736
- get active() {
140737
- return !! this._deactivate;
140738
- }
140739
-
140740
- activate(zoneAltitude, zoneHeight, zoneColor, zoneAlpha) {
140741
-
140742
- if (typeof(zoneAltitude) === "object" && (zoneAltitude !== null)) {
140743
- const params = zoneAltitude;
140744
- const param = (name, defaultValue) => {
140745
- if (name in params) {
140746
- return params[name];
140747
- } else if (defaultValue !== undefined) {
140748
- return defaultValue;
140749
- } else {
140750
- throw "config missing: " + name;
140751
- }
140752
- };
140753
-
140754
- zoneAltitude = param("altitude");
140755
- zoneHeight = param("height");
140756
- zoneColor = param("color", "#008000");
140757
- zoneAlpha = param("alpha", 0.5);
140758
- }
140759
-
140760
- if (this._deactivate) {
140761
- return;
140762
- }
140763
-
140764
- const zonesPlugin = this.zonesPlugin;
140765
- const viewer = zonesPlugin.viewer;
140766
- const scene = viewer.scene;
140767
- const self = this;
140768
-
140769
- const select3dPoint = touchPointSelector(
140770
- viewer,
140771
- this.pointerCircle,
140772
- function(origin, direction) {
140773
- return planeIntersect(zoneAltitude, math.vec3([ 0, 1, 0 ]), origin, direction);
140774
- });
140775
-
140776
- (function rec() {
140777
- self._deactivate = startAAZoneCreateUI(
140778
- scene, zoneAltitude, zoneHeight, zoneColor, zoneAlpha, self.pointerLens, zonesPlugin, select3dPoint,
140779
- zone => {
140780
- let reactivate = true;
140781
- self._deactivate = () => { reactivate = false; };
140782
- self.fire("zoneEnd", zone);
140783
- if (reactivate)
140784
- {
140785
- rec();
140786
- }
140787
- }).deactivate;
140788
- })();
140789
- }
140790
-
140791
- deactivate() {
140792
- if (this._deactivate)
140793
- {
140794
- this._deactivate();
140795
- this._deactivate = null;
140796
- }
140797
- }
140798
-
140799
- destroy() {
140800
- this.deactivate();
140801
- super.destroy();
140802
- }
140803
- }
140804
-
140805
140797
  const startPolysurfaceZoneCreateUI = function(scene, zoneAltitude, zoneHeight, zoneColor, zoneAlpha, pointerLens, zonesPlugin, select3dPoint, onZoneCreated) {
140806
140798
  const updatePointerLens = (pointerLens
140807
140799
  ? function(canvasPos) {