@xeokit/xeokit-sdk 2.6.60 → 2.6.62

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/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@xeokit/xeokit-sdk",
3
- "version": "2.6.60",
3
+ "version": "2.6.62",
4
4
  "description": "Web Programming Toolkit for 3D/2D BIM and AEC Graphics",
5
5
  "module": "./dist/xeokit-sdk.es.js",
6
6
  "main": "./dist/xeokit-sdk.cjs.js",
7
7
  "types": "./types/index.d.ts",
8
+
8
9
  "scripts": {
9
10
  "build": "rollup --config rollup.config.js; rollup --config rollup.minified.config.js",
10
11
  "dev-build": "rollup --config rollup.dev.config.js",
@@ -738,12 +738,19 @@ class ContextMenu {
738
738
  const menuRect = subMenuElement.getBoundingClientRect();
739
739
 
740
740
  const subMenuWidth = 200; // TODO
741
- const showOnLeft = ((itemRect.right + subMenuWidth) > window.innerWidth);
741
+ const showOnRight = (itemRect.right + subMenuWidth) < window.innerWidth;
742
+ const showOnLeft = (itemRect.left - subMenuWidth) > 0;
742
743
 
743
- if (showOnLeft) {
744
- self._showMenu(subMenu.id, itemRect.left - subMenuWidth, itemRect.top - 1);
745
- } else {
744
+ if(showOnRight)
746
745
  self._showMenu(subMenu.id, itemRect.right - 5, itemRect.top - 1);
746
+ else if (showOnLeft)
747
+ self._showMenu(subMenu.id, itemRect.left - subMenuWidth, itemRect.top - 1);
748
+ else {
749
+ const spaceOnLeft = itemRect.left, spaceOnRight = window.innerWidth - itemRect.right;
750
+ if(spaceOnRight > spaceOnLeft)
751
+ self._showMenu(subMenu.id, itemRect.right - 5 - (subMenuWidth - spaceOnRight), itemRect.top - 1);
752
+ else
753
+ self._showMenu(subMenu.id, itemRect.left - spaceOnLeft, itemRect.top - 1);
747
754
  }
748
755
 
749
756
  lastSubMenu = subMenu;
@@ -46,10 +46,10 @@ class Annotation extends Marker {
46
46
  this._marker.addEventListener("click", this._onMouseClickedExternalMarker = () => {
47
47
  this.plugin.fire("markerClicked", this);
48
48
  });
49
- this._onContextMenuExtenalMarker = () => {
49
+ this._onContextMenuExternalMarker = () => {
50
50
  this.plugin.fire("contextmenu", this);
51
51
  }
52
- this._onContextMenuExtenalMarkerRemover = addContextMenuListener(this._markerHTML, this._onContextMenuExtenalMarker);
52
+ this._onContextMenuExternalMarkerRemover = addContextMenuListener(this._marker, this._onContextMenuExternalMarker);
53
53
  this._marker.addEventListener("mouseenter", this._onMouseEnterExternalMarker = () => {
54
54
  this.plugin.fire("markerMouseEnter", this);
55
55
  });
@@ -420,7 +420,7 @@ class Annotation extends Marker {
420
420
  this._marker = null;
421
421
  } else {
422
422
  this._marker.removeEventListener("click", this._onMouseClickedExternalMarker);
423
- this._onContextMenuExtenalMarkerRemover();
423
+ this._onContextMenuExternalMarkerRemover();
424
424
  this._marker.removeEventListener("mouseenter", this._onMouseEnterExternalMarker);
425
425
  this._marker.removeEventListener("mouseleave", this._onMouseLeaveExternalMarker);
426
426
  this._marker = null;
@@ -119,7 +119,7 @@ class FastNavPlugin extends Plugin {
119
119
  this._hideEdges = cfg.hideEdges !== false;
120
120
  this._hideTransparentObjects = !!cfg.hideTransparentObjects;
121
121
  this._scaleCanvasResolution = !!cfg.scaleCanvasResolution;
122
- this._defaultScaleCanvasResolutionFactor = cfg.defaultScaleCanvasResolutionFactor || 1.0;
122
+ this._defaultScaleCanvasResolutionFactor = cfg.defaultScaleCanvasResolutionFactor;
123
123
  this._scaleCanvasResolutionFactor = cfg.scaleCanvasResolutionFactor || 0.6;
124
124
  this._delayBeforeRestore = (cfg.delayBeforeRestore !== false);
125
125
  this._delayBeforeRestoreSeconds = cfg.delayBeforeRestoreSeconds || 0.5;
@@ -135,6 +135,7 @@ class FastNavPlugin extends Plugin {
135
135
  viewer.scene._renderer.setSAOEnabled(!this._hideSAO);
136
136
  viewer.scene._renderer.setTransparentEnabled(!this._hideTransparentObjects);
137
137
  viewer.scene._renderer.setEdgesEnabled(!this._hideEdges);
138
+ this._originalCanvasResolutionScale = viewer.scene.canvas.resolutionScale;
138
139
  if (this._scaleCanvasResolution) {
139
140
  viewer.scene.canvas.resolutionScale = this._scaleCanvasResolutionFactor;
140
141
  } else {
@@ -145,7 +146,7 @@ class FastNavPlugin extends Plugin {
145
146
  };
146
147
 
147
148
  const switchToHighQuality = () => {
148
- viewer.scene.canvas.resolutionScale = this._defaultScaleCanvasResolutionFactor;
149
+ viewer.scene.canvas.resolutionScale = this._defaultScaleCanvasResolutionFactor || this._originalCanvasResolutionScale || 1.0;
149
150
  viewer.scene._renderer.setEdgesEnabled(true);
150
151
  viewer.scene._renderer.setColorTextureEnabled(true);
151
152
  viewer.scene._renderer.setPBREnabled(true);
@@ -350,7 +351,7 @@ class FastNavPlugin extends Plugin {
350
351
  * @param {Number} defaultScaleCanvasResolutionFactor Factor by scale canvas resolution when we stop interacting with the viewer.
351
352
  */
352
353
  set defaultScaleCanvasResolutionFactor(defaultScaleCanvasResolutionFactor) {
353
- this._defaultScaleCanvasResolutionFactor = defaultScaleCanvasResolutionFactor || 1.0;
354
+ this._defaultScaleCanvasResolutionFactor = defaultScaleCanvasResolutionFactor;
354
355
  }
355
356
 
356
357
  /**
@@ -362,6 +362,7 @@ export class TreeViewPlugin extends Plugin {
362
362
  * @param {Boolean} [cfg.pruneEmptyNodes=true] When true, will not contain nodes that don't have content in the {@link Scene}. These are nodes whose {@link MetaObject}s don't have {@link Entity}s.
363
363
  * @param {RenderService} [cfg.renderService] Optional {@link RenderService} to use. Defaults to the {@link TreeViewPlugin}'s default {@link RenderService}.
364
364
  * @param {Boolean} [cfg.showIndeterminate=false] When true, will show indeterminate state for checkboxes when some but not all child nodes are checked
365
+ * @param {Boolean} [cfg.showProjectNode=false] When true, will show top level project node when hierarchy is set to "storeys"
365
366
  */
366
367
  constructor(viewer, cfg = {}) {
367
368
 
@@ -414,6 +415,7 @@ export class TreeViewPlugin extends Plugin {
414
415
  this._showListItemElementId = null;
415
416
  this._renderService = cfg.renderService || new RenderService();
416
417
  this._showIndeterminate = cfg.showIndeterminate ?? false;
418
+ this._showProjectNode = cfg.showProjectNode ?? false;
417
419
 
418
420
  if (!this._renderService) {
419
421
  throw new Error('TreeViewPlugin: no render service set');
@@ -968,11 +970,11 @@ export class TreeViewPlugin extends Plugin {
968
970
  _createStoreysNodes() {
969
971
  const rootMetaObjects = this._viewer.metaScene.rootMetaObjects;
970
972
  for (let id in rootMetaObjects) {
971
- this._createStoreysNodes2(rootMetaObjects[id], null, null, null);
973
+ this._createStoreysNodes2(rootMetaObjects[id], null, null, null, null);
972
974
  }
973
975
  }
974
976
 
975
- _createStoreysNodes2(metaObject, buildingNode, storeyNode, typeNodes) {
977
+ _createStoreysNodes2(metaObject, projectNode, buildingNode, storeyNode, typeNodes) {
976
978
  if (this._pruneEmptyNodes && (metaObject._countEntities === 0)) {
977
979
  return;
978
980
  }
@@ -980,20 +982,41 @@ export class TreeViewPlugin extends Plugin {
980
982
  const metaObjectName = metaObject.name;
981
983
  const children = metaObject.children;
982
984
  const objectId = metaObject.id;
983
- if (metaObjectType === "IfcBuilding") {
985
+
986
+ if (this._showProjectNode && metaObjectType === 'IfcProject') {
987
+ projectNode = {
988
+ nodeId: `${this._id}-${objectId}`,
989
+ objectId,
990
+ title: (metaObject.metaModels.length === 0) ? metaObjectName : this._rootNames[metaObject.metaModels[0].id] || ((metaObjectName && metaObjectName !== "" && metaObjectName !== "Undefined" && metaObjectName !== "Default") ? metaObjectName : metaObjectType),
991
+ type: metaObjectType,
992
+ parent: null,
993
+ numEntities: 0,
994
+ numVisibleEntities: 0,
995
+ checked: false,
996
+ xrayed: false,
997
+ children: [],
998
+ };
999
+ this._rootNodes.push(projectNode);
1000
+ this._objectNodes[projectNode.objectId] = projectNode;
1001
+ this._nodeNodes[projectNode.nodeId] = projectNode;
1002
+ } else if (metaObjectType === "IfcBuilding") {
984
1003
  buildingNode = {
985
1004
  nodeId: `${this._id}-${objectId}`,
986
1005
  objectId: objectId,
987
1006
  title: (metaObject.metaModels.length === 0) ? metaObjectName : this._rootNames[metaObject.metaModels[0].id] || ((metaObjectName && metaObjectName !== "" && metaObjectName !== "Undefined" && metaObjectName !== "Default") ? metaObjectName : metaObjectType),
988
1007
  type: metaObjectType,
989
- parent: null,
1008
+ parent: projectNode,
990
1009
  numEntities: 0,
991
1010
  numVisibleEntities: 0,
992
1011
  checked: false,
993
1012
  xrayed: false,
994
1013
  children: []
995
1014
  };
996
- this._rootNodes.push(buildingNode);
1015
+ if (projectNode) {
1016
+ projectNode.children.push(buildingNode);
1017
+ } else {
1018
+ this._rootNodes.push(buildingNode);
1019
+ }
997
1020
  this._objectNodes[buildingNode.objectId] = buildingNode;
998
1021
  this._nodeNodes[buildingNode.nodeId] = buildingNode;
999
1022
  } else if (metaObjectType === "IfcBuildingStorey") {
@@ -1063,7 +1086,7 @@ export class TreeViewPlugin extends Plugin {
1063
1086
  if (children) {
1064
1087
  for (let i = 0, len = children.length; i < len; i++) {
1065
1088
  const childMetaObject = children[i];
1066
- this._createStoreysNodes2(childMetaObject, buildingNode, storeyNode, typeNodes);
1089
+ this._createStoreysNodes2(childMetaObject, projectNode, buildingNode, storeyNode, typeNodes);
1067
1090
  }
1068
1091
  }
1069
1092
  }
@@ -482,8 +482,21 @@ class Zone extends Component {
482
482
  }
483
483
 
484
484
 
485
- const positions = [].concat(...pos);
485
+ const min = idx => Math.min(...pos.map(p => p[idx]));
486
+ const max = idx => Math.max(...pos.map(p => p[idx]));
487
+
488
+ const xmin = min(0);
489
+ const ymin = min(1);
490
+ const zmin = min(2);
491
+ const xmax = max(0);
492
+ const ymax = max(1);
493
+ const zmax = max(2);
494
+
495
+ this._center = math.vec3([ (xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2 ]);
496
+
497
+ const positions = [].concat(...pos.map(p => math.subVec3(p, this._center, p)));
486
498
  this._zoneMesh = new Mesh(scene, {
499
+ origin: this._center,
487
500
  edges: this._edges,
488
501
  geometry: new ReadableGeometry(
489
502
  scene,
@@ -524,19 +537,6 @@ class Zone extends Component {
524
537
  }
525
538
 
526
539
  this._metrics = null;
527
-
528
-
529
- const min = idx => Math.min(...pos.map(p => p[idx]));
530
- const max = idx => Math.max(...pos.map(p => p[idx]));
531
-
532
- const xmin = min(0);
533
- const ymin = min(1);
534
- const zmin = min(2);
535
- const xmax = max(0);
536
- const ymax = max(1);
537
- const zmax = max(2);
538
-
539
- this._center = math.vec3([ (xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2 ]);
540
540
  }
541
541
 
542
542
  get baseArea() {
@@ -10,14 +10,17 @@ export function addContextMenuListener(elem, callback) {
10
10
 
11
11
  const touchStartHandler = (event) => {
12
12
  event.preventDefault();
13
- const touch = event.touches[0];
14
- startX = touch.clientX;
15
- startY = touch.clientY;
16
-
13
+
17
14
  if (timeout) {
18
15
  clearTimeout(timeout);
19
16
  timeout = null;
20
17
  }
18
+ // If more than one finger touches the screen, cancel the timeout
19
+ if (event.touches.length > 1) return;
20
+
21
+ const touch = event.touches[0];
22
+ startX = touch.clientX;
23
+ startY = touch.clientY;
21
24
 
22
25
  timeout = setTimeout(() => {
23
26
  event.clientX = touch.clientX;
@@ -28,6 +31,14 @@ export function addContextMenuListener(elem, callback) {
28
31
  }, longPressTimer);
29
32
  };
30
33
 
34
+ const globalTouchStartHandler = (event) => {
35
+ // Cancel timeout if multiple touches are detected anywhere on the screen
36
+ if (event.touches.length > 1 && timeout) {
37
+ clearTimeout(timeout);
38
+ timeout = null;
39
+ }
40
+ };
41
+
31
42
  const touchMoveHandler = (event) => {
32
43
  if (!timeout) return;
33
44
  const touch = event.touches[0];
@@ -58,6 +69,7 @@ export function addContextMenuListener(elem, callback) {
58
69
  elem.addEventListener('touchstart', touchStartHandler);
59
70
  elem.addEventListener('touchmove', touchMoveHandler);
60
71
  elem.addEventListener('touchend', touchEndHandler);
72
+ window.addEventListener('touchstart', globalTouchStartHandler);
61
73
  } else {
62
74
  elem.addEventListener('contextmenu', contextMenuHandler);
63
75
  }
@@ -67,6 +79,7 @@ export function addContextMenuListener(elem, callback) {
67
79
  elem.removeEventListener('touchstart', touchStartHandler);
68
80
  elem.removeEventListener('touchmove', touchMoveHandler);
69
81
  elem.removeEventListener('touchend', touchEndHandler);
82
+ window.removeEventListener('touchstart', globalTouchStartHandler);
70
83
  } else {
71
84
  elem.removeEventListener('contextmenu', contextMenuHandler);
72
85
  }
@@ -253,8 +253,8 @@ class MetaScene {
253
253
 
254
254
  for (let modelId in this.metaModels) {
255
255
  const metaModel = this.metaModels[modelId];
256
- for (let i = 0, len = metaModel.metaObjects.length; i < len; i++) {
257
- const metaObject = metaModel.metaObjects[i];
256
+ for (let objectId in metaModel.metaObjects) {
257
+ const metaObject = metaModel.metaObjects[objectId];
258
258
  metaObject.metaModels.push(metaModel);
259
259
  }
260
260
  }
@@ -272,7 +272,7 @@ class MousePickHandler {
272
272
 
273
273
  this._timeout = setTimeout(() => {
274
274
 
275
- if (firstClickPickResult && firstClickPickResult.worldPos) {
275
+ if (firstClickPickResult) {
276
276
 
277
277
  cameraControl.fire("picked", firstClickPickResult, true);
278
278
 
@@ -110,6 +110,10 @@ export class DTXTrianglesColorRenderer {
110
110
  const sectionPlanes = scene._sectionPlanesState.sectionPlanes;
111
111
  const baseIndex = dataTextureLayer.layerIndex * numSectionPlanes;
112
112
  const renderFlags = model.renderFlags;
113
+ if (scene.crossSections) {
114
+ gl.uniform4fv(this._uSliceColor, scene.crossSections.sliceColor);
115
+ gl.uniform1f(this._uSliceThickness, scene.crossSections.sliceThickness);
116
+ }
113
117
  for (let sectionPlaneIndex = 0; sectionPlaneIndex < numAllocatedSectionPlanes; sectionPlaneIndex++) {
114
118
  const sectionPlaneUniforms = this._uSectionPlanes[sectionPlaneIndex];
115
119
  if (sectionPlaneUniforms) {
@@ -247,6 +251,11 @@ export class DTXTrianglesColorRenderer {
247
251
  this._uTexturePerPolygonIdPortionIds = "uTexturePerPolygonIdPortionIds";
248
252
  this._uTexturePerObjectMatrix= "uTexturePerObjectMatrix";
249
253
  this._uCameraEyeRtc = program.getLocation("uCameraEyeRtc");
254
+
255
+ if (scene.crossSections) {
256
+ this._uSliceColor = program.getLocation("sliceColor");
257
+ this._uSliceThickness = program.getLocation("sliceThickness");
258
+ }
250
259
  }
251
260
 
252
261
  _bindProgram(frameCtx) {
@@ -563,11 +572,14 @@ export class DTXTrianglesColorRenderer {
563
572
  src.push("uniform vec3 sectionPlanePos" + i + ";");
564
573
  src.push("uniform vec3 sectionPlaneDir" + i + ";");
565
574
  }
575
+ src.push("uniform float sliceThickness;");
576
+ src.push("uniform vec4 sliceColor;");
566
577
  }
567
578
  src.push("in vec4 vColor;");
568
579
  src.push("out vec4 outColor;");
569
580
  src.push("void main(void) {");
570
-
581
+ src.push(" vec4 newColor;");
582
+ src.push(" newColor = vColor;");
571
583
  if (clipping) {
572
584
  src.push(" bool clippable = vFlags2 > 0u;");
573
585
  src.push(" if (clippable) {");
@@ -577,9 +589,12 @@ export class DTXTrianglesColorRenderer {
577
589
  src.push(" dist += clamp(dot(-sectionPlaneDir" + i + ".xyz, vWorldPosition.xyz - sectionPlanePos" + i + ".xyz), 0.0, 1000.0);");
578
590
  src.push("}");
579
591
  }
580
- src.push(" if (dist > 0.0) { ");
592
+ src.push(" if (dist > sliceThickness) { ");
581
593
  src.push(" discard;")
582
594
  src.push(" }");
595
+ src.push(" if (dist > 0.0) { ");
596
+ src.push(" newColor = sliceColor;");
597
+ src.push(" }");
583
598
  src.push("}");
584
599
  }
585
600
 
@@ -597,9 +612,9 @@ export class DTXTrianglesColorRenderer {
597
612
  src.push(" float blendFactor = uSAOParams[3];");
598
613
  src.push(" vec2 uv = vec2(gl_FragCoord.x / viewportWidth, gl_FragCoord.y / viewportHeight);");
599
614
  src.push(" float ambient = smoothstep(blendCutoff, 1.0, unpackRGBToFloat(texture(uOcclusionTexture, uv))) * blendFactor;");
600
- src.push(" outColor = vec4(vColor.rgb * ambient, 1.0);");
615
+ src.push(" outColor = vec4(newColor.rgb * ambient, 1.0);");
601
616
  } else {
602
- src.push(" outColor = vColor;");
617
+ src.push(" outColor = newColor;");
603
618
  }
604
619
 
605
620
  src.push("}");
@@ -377,10 +377,14 @@ export class DTXTrianglesEdgesColorRenderer {
377
377
  src.push("uniform vec3 sectionPlanePos" + i + ";");
378
378
  src.push("uniform vec3 sectionPlaneDir" + i + ";");
379
379
  }
380
+ src.push("uniform float sliceThickness;");
381
+ src.push("uniform vec4 sliceColor;");
380
382
  }
381
383
  src.push("in vec4 vColor;");
382
384
  src.push("out vec4 outColor;");
383
385
  src.push("void main(void) {");
386
+ src.push(" vec4 newColor;");
387
+ src.push(" newColor = vColor;");
384
388
  if (clipping) {
385
389
  src.push(" bool clippable = vFlags2 > 0u;");
386
390
  src.push(" if (clippable) {");
@@ -390,13 +394,18 @@ export class DTXTrianglesEdgesColorRenderer {
390
394
  src.push(" dist += clamp(dot(-sectionPlaneDir" + i + ".xyz, vWorldPosition.xyz - sectionPlanePos" + i + ".xyz), 0.0, 1000.0);");
391
395
  src.push("}");
392
396
  }
393
- src.push(" if (dist > 0.0) { discard; }");
397
+ src.push(" if (dist > sliceThickness) { ");
398
+ src.push(" discard;")
399
+ src.push(" }");
400
+ src.push(" if (dist > 0.0) { ");
401
+ src.push(" newColor = sliceColor;");
402
+ src.push(" }");
394
403
  src.push("}");
395
404
  }
396
405
  if (scene.logarithmicDepthBufferEnabled) {
397
406
  src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;");
398
407
  }
399
- src.push(" outColor = vColor;");
408
+ src.push(" outColor = newColor;");
400
409
  src.push("}");
401
410
  return src;
402
411
  }
@@ -385,10 +385,14 @@ export class DTXTrianglesEdgesRenderer {
385
385
  src.push("uniform vec3 sectionPlanePos" + i + ";");
386
386
  src.push("uniform vec3 sectionPlaneDir" + i + ";");
387
387
  }
388
+ src.push("uniform float sliceThickness;");
389
+ src.push("uniform vec4 sliceColor;");
388
390
  }
389
391
  src.push("in vec4 vColor;");
390
392
  src.push("out vec4 outColor;");
391
393
  src.push("void main(void) {");
394
+ src.push(" vec4 newColor;");
395
+ src.push(" newColor = vColor;");
392
396
  if (clipping) {
393
397
  src.push(" bool clippable = vFlags2 > 0u;");
394
398
  src.push(" if (clippable) {");
@@ -398,13 +402,18 @@ export class DTXTrianglesEdgesRenderer {
398
402
  src.push(" dist += clamp(dot(-sectionPlaneDir" + i + ".xyz, vWorldPosition.xyz - sectionPlanePos" + i + ".xyz), 0.0, 1000.0);");
399
403
  src.push("}");
400
404
  }
401
- src.push(" if (dist > 0.0) { discard; }");
405
+ src.push(" if (dist > sliceThickness) { ");
406
+ src.push(" discard;")
407
+ src.push(" }");
408
+ src.push(" if (dist > 0.0) { ");
409
+ src.push(" newColor = sliceColor;");
410
+ src.push(" }");
402
411
  src.push("}");
403
412
  }
404
413
  if (scene.logarithmicDepthBufferEnabled) {
405
414
  src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;");
406
415
  }
407
- src.push(" outColor = vColor;");
416
+ src.push(" outColor = newColor;");
408
417
  src.push("}");
409
418
  return src;
410
419
  }
@@ -426,10 +426,14 @@ export class DTXTrianglesSilhouetteRenderer {
426
426
  src.push("uniform vec3 sectionPlanePos" + i + ";");
427
427
  src.push("uniform vec3 sectionPlaneDir" + i + ";");
428
428
  }
429
+ src.push("uniform float sliceThickness;");
430
+ src.push("uniform vec4 sliceColor;");
429
431
  }
430
432
  src.push("uniform vec4 color;");
431
433
  src.push("out vec4 outColor;");
432
434
  src.push("void main(void) {");
435
+ src.push(" vec4 newColor;");
436
+ src.push(" newColor = color;");
433
437
  if (clipping) {
434
438
  src.push(" bool clippable = vFlags2 > 0u;");
435
439
  src.push(" if (clippable) {");
@@ -439,15 +443,18 @@ export class DTXTrianglesSilhouetteRenderer {
439
443
  src.push(" dist += clamp(dot(-sectionPlaneDir" + i + ".xyz, vWorldPosition.xyz - sectionPlanePos" + i + ".xyz), 0.0, 1000.0);");
440
444
  src.push("}");
441
445
  }
442
- src.push(" if (dist > 0.0) { ");
446
+ src.push(" if (dist > sliceThickness) { ");
443
447
  src.push(" discard;")
444
448
  src.push(" }");
449
+ src.push(" if (dist > 0.0) { ");
450
+ src.push(" newColor = sliceColor;");
451
+ src.push(" }");
445
452
  src.push("}");
446
453
  }
447
454
  if (scene.logarithmicDepthBufferEnabled) {
448
455
  src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;");
449
456
  }
450
- src.push(" outColor = color;");
457
+ src.push(" outColor = newColor;");
451
458
  src.push("}");
452
459
  return src;
453
460
  }
@@ -11,6 +11,8 @@ import {SAODepthLimitedBlurRenderer} from "./sao/SAODepthLimitedBlurRenderer.js"
11
11
  import {RenderBufferManager} from "./RenderBufferManager.js";
12
12
  import {getExtension} from "./getExtension.js";
13
13
 
14
+ const vec3_0 = math.vec3([0,0,0]);
15
+
14
16
  /**
15
17
  * @private
16
18
  */
@@ -713,9 +715,11 @@ const Renderer = function (scene, options) {
713
715
  // Transparent color fill
714
716
 
715
717
  if (normalFillTransparentBinLen > 0) {
718
+ const eye = frameCtx.pickOrigin || scene.camera.eye;
719
+ const byDist = normalFillTransparentBin.map(d => ({ drawable: d, distSq: math.distVec3(d.origin || vec3_0, eye) }));
720
+ byDist.sort((a, b) => b.distSq - a.distSq);
716
721
  for (i = 0; i < normalFillTransparentBinLen; i++) {
717
- drawable = normalFillTransparentBin[i];
718
- drawable.drawColorTransparent(frameCtx);
722
+ byDist[i].drawable.drawColorTransparent(frameCtx);
719
723
  }
720
724
  }
721
725