@xeokit/xeokit-sdk 2.6.71 → 2.6.73

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.
@@ -1,7 +1,7 @@
1
1
  /**
2
- * xeokit-sdk v2.6.71
3
- * Commit: 7443626ab66b3eab0018b1ed0ee05d3bfa9f8eae
4
- * Built: 2025-03-21T09:02:29.217Z
2
+ * xeokit-sdk v2.6.73
3
+ * Commit: 3b3bb2ad8abfdf189cf4ba7f67d6798375772b7b
4
+ * Built: 2025-04-10T16:46:49.684Z
5
5
  */
6
6
 
7
7
  /** @private */
@@ -330,6 +330,7 @@ class ContextMenu {
330
330
  * @param {Boolean} [cfg.enabled=true] Whether this ````ContextMenu```` is initially enabled. {@link ContextMenu#show} does nothing while this is ````false````.
331
331
  * @param {Boolean} [cfg.hideOnMouseDown=true] Whether this ````ContextMenu```` automatically hides whenever we mouse-down or tap anywhere in the page.
332
332
  * @param {Boolean} [cfg.hideOnAction=true] Whether this ````ContextMenu```` automatically hides after we select a menu item. Se false if we want the menu to remain shown and show any updates to its item titles, after we've selected an item.
333
+ * @param {Node | undefined} [cfg.parentNode] Optional reference to an existing DOM Node (e.g. ShadowRoot), to which the menu's HTML element will be appended, defaults to ````document.body````.
333
334
  */
334
335
  constructor(cfg = {}) {
335
336
 
@@ -344,6 +345,7 @@ class ContextMenu {
344
345
  this._itemMap = {}; // Items mapped to their IDs
345
346
  this._shown = false; // True when the ContextMenu is visible
346
347
  this._nextId = 0;
348
+ this._parentNode = cfg.parentNode || document.body;
347
349
 
348
350
  /**
349
351
  * Subscriptions to events fired at this ContextMenu.
@@ -352,12 +354,12 @@ class ContextMenu {
352
354
  this._eventSubs = {};
353
355
 
354
356
  if (cfg.hideOnMouseDown !== false) {
355
- document.addEventListener("mousedown", (event) => {
357
+ this._parentNode.addEventListener("mousedown", (event) => {
356
358
  if (!event.target.classList.contains("xeokit-context-menu-item")) {
357
359
  this.hide();
358
360
  }
359
361
  });
360
- document.addEventListener("touchstart", this._canvasTouchStartHandler = (event) => {
362
+ this._parentNode.addEventListener("touchstart", this._canvasTouchStartHandler = (event) => {
361
363
  if (!event.target.classList.contains("xeokit-context-menu-item")) {
362
364
  this.hide();
363
365
  }
@@ -661,7 +663,10 @@ class ContextMenu {
661
663
  const groups = menu.groups;
662
664
  const html = [];
663
665
 
664
- html.push('<div class="xeokit-context-menu ' + menu.id + '" style="z-index:300000; position: absolute;">');
666
+ const menuElement= document.createElement("div");
667
+ menuElement.classList.add("xeokit-context-menu", menu.id);
668
+ menuElement.style.zIndex = 300000;
669
+ menuElement.style.position = "absolute";
665
670
 
666
671
  html.push('<ul>');
667
672
 
@@ -712,13 +717,10 @@ class ContextMenu {
712
717
  }
713
718
 
714
719
  html.push('</ul>');
715
- html.push('</div>');
716
720
 
717
721
  const htmlString = html.join("");
718
-
719
- document.body.insertAdjacentHTML('beforeend', htmlString);
720
-
721
- const menuElement = document.querySelector("." + menu.id);
722
+ menuElement.innerHTML = htmlString;
723
+ this._parentNode.appendChild(menuElement);
722
724
 
723
725
  menu.menuElement = menuElement;
724
726
 
@@ -752,7 +754,7 @@ class ContextMenu {
752
754
  const item = groupItems[j];
753
755
  const itemSubMenu = item.subMenu;
754
756
 
755
- item.itemElement = document.getElementById(item.id);
757
+ item.itemElement = this._parentNode.querySelector(`#${item.id}`);
756
758
 
757
759
  if (!item.itemElement) {
758
760
  console.error("ContextMenu item element not found: " + item.id);
@@ -11655,9 +11657,28 @@ const tmpVec4b = math.vec4();
11655
11657
  const tmpVec4c = math.vec4();
11656
11658
  const tmpVec4d = math.vec4();
11657
11659
  const tmpMat4 = math.mat4();
11660
+ const tmpRay = {
11661
+ origin: math.vec3(),
11662
+ direction: math.vec3()
11663
+ };
11658
11664
 
11659
11665
  const nop = () => { };
11660
11666
 
11667
+ const planeIntersect$1 = function(p0, n, origin, direction) {
11668
+ const t = (p0 - math.dotVec3(origin, n)) / math.dotVec3(direction, n);
11669
+ if (t < 0)
11670
+ {
11671
+ return null;
11672
+ }
11673
+ else
11674
+ {
11675
+ const worldPos = math.vec3();
11676
+ math.mulVec3Scalar(direction, t, worldPos);
11677
+ math.addVec3(origin, worldPos, worldPos);
11678
+ return worldPos;
11679
+ }
11680
+ };
11681
+
11661
11682
  function transformToNode(from, to, vec) {
11662
11683
  const fromRec = from.getBoundingClientRect();
11663
11684
  const toRec = to.getBoundingClientRect();
@@ -11919,9 +11940,15 @@ class Label3D {
11919
11940
  this._mid = math.vec3();
11920
11941
  this._end = math.vec3();
11921
11942
  this._yOff = 0;
11922
- this._betweenWires = false;
11923
11943
  this.__visible = true;
11924
11944
 
11945
+ this._updatePos = () => {
11946
+ toClipSpace(camera, this._start, tmpVec4a);
11947
+ math.mulVec4Scalar(tmpVec4a, 1.0 / tmpVec4a[3]);
11948
+ toCanvasSpace(scene.canvas.canvas, parentElement, tmpVec4a, tmpVec2a);
11949
+ this._label.setPos(tmpVec2a[0], tmpVec2a[1]);
11950
+ };
11951
+
11925
11952
  const setPosOnWire = (p0, p1, yOff) => {
11926
11953
  p0[0] += p1[0];
11927
11954
  p0[1] += p1[1];
@@ -11929,36 +11956,44 @@ class Label3D {
11929
11956
  this._label.setPos(p0[0], p0[1] + yOff);
11930
11957
  };
11931
11958
 
11932
- this._updatePositions = () => {
11933
- if (! this.__visible) {
11934
- return;
11959
+ this._updatePosBetween = () => {
11960
+ const visibleA = clipSegment(scene, parentElement, this._start, this._mid, tmpVec2a, tmpVec2b);
11961
+ const visibleB = clipSegment(scene, parentElement, this._end, this._mid, tmpVec2c, tmpVec2d);
11962
+ this._label.setCulled(! (visibleA || visibleB));
11963
+ if (visibleA && visibleB) {
11964
+ tmpVec2b[0] += tmpVec2d[0];
11965
+ tmpVec2b[1] += tmpVec2d[1];
11966
+ math.mulVec2Scalar(tmpVec2b, .5);
11967
+
11968
+ tmpVec2b[0] += tmpVec2a[0] + tmpVec2c[0];
11969
+ tmpVec2b[1] += tmpVec2a[1] + tmpVec2c[1];
11970
+ math.mulVec2Scalar(tmpVec2b, 1/3);
11971
+ this._label.setPos(tmpVec2b[0], tmpVec2b[1]);
11972
+ } else if (visibleA) {
11973
+ setPosOnWire(tmpVec2a, tmpVec2b, 0);
11974
+ } else if (visibleB) {
11975
+ setPosOnWire(tmpVec2c, tmpVec2d, 0);
11935
11976
  }
11936
- if (this._betweenWires) {
11937
- const visibleA = clipSegment(scene, parentElement, this._start, this._mid, tmpVec2a, tmpVec2b);
11938
- const visibleB = clipSegment(scene, parentElement, this._end, this._mid, tmpVec2c, tmpVec2d);
11939
- this._label.setCulled(! (visibleA || visibleB));
11940
- if (visibleA && visibleB) {
11941
- tmpVec2b[0] += tmpVec2d[0];
11942
- tmpVec2b[1] += tmpVec2d[1];
11943
- math.mulVec2Scalar(tmpVec2b, .5);
11944
-
11945
- tmpVec2b[0] += tmpVec2a[0] + tmpVec2c[0];
11946
- tmpVec2b[1] += tmpVec2a[1] + tmpVec2c[1];
11947
- math.mulVec2Scalar(tmpVec2b, 1/3);
11948
- this._label.setPos(tmpVec2b[0], tmpVec2b[1]);
11949
- } else if (visibleA) {
11950
- setPosOnWire(tmpVec2a, tmpVec2b, 0);
11951
- } else if (visibleB) {
11952
- setPosOnWire(tmpVec2c, tmpVec2d, 0);
11953
- }
11954
- } else {
11955
- const visible = (clipSegment(scene, parentElement, this._start, this._end, tmpVec2a, tmpVec2b)
11956
- &&
11957
- (math.distVec2(tmpVec2a, tmpVec2b) >= this._labelMinAxisLength));
11958
- this._label.setCulled(!visible);
11959
- if (visible) {
11960
- setPosOnWire(tmpVec2a, tmpVec2b, this._yOff);
11961
- }
11977
+ };
11978
+
11979
+ this._updatePosOnWire = () => {
11980
+ const visible = (clipSegment(scene, parentElement, this._start, this._end, tmpVec2a, tmpVec2b)
11981
+ &&
11982
+ (math.distVec2(tmpVec2a, tmpVec2b) >= this._labelMinAxisLength));
11983
+ this._label.setCulled(!visible);
11984
+ if (visible) {
11985
+ setPosOnWire(tmpVec2a, tmpVec2b, this._yOff);
11986
+ }
11987
+ };
11988
+
11989
+ let posUpdate = () => { };
11990
+ this._setUpdatePositions = (_posUpdate) => {
11991
+ posUpdate = _posUpdate;
11992
+ this._updatePositions();
11993
+ };
11994
+ this._updatePositions = () => {
11995
+ if (this.__visible) {
11996
+ posUpdate();
11962
11997
  }
11963
11998
  };
11964
11999
 
@@ -11976,21 +12011,24 @@ class Label3D {
11976
12011
  };
11977
12012
  }
11978
12013
 
12014
+ setPos(p0) {
12015
+ this._start.set(p0);
12016
+ this._setUpdatePositions(this._updatePos);
12017
+ }
12018
+
11979
12019
  setPosOnWire(p0, p1, yOff, labelMinAxisLength) {
11980
12020
  this._start.set(p0);
11981
12021
  this._end.set(p1);
11982
12022
  this._yOff = yOff;
11983
12023
  this._labelMinAxisLength = labelMinAxisLength;
11984
- this._betweenWires = false;
11985
- this._updatePositions();
12024
+ this._setUpdatePositions(this._updatePosOnWire);
11986
12025
  }
11987
12026
 
11988
12027
  setPosBetween(p0, p1, p2) {
11989
12028
  this._start.set(p0);
11990
12029
  this._mid.set(p1);
11991
12030
  this._end.set(p2);
11992
- this._betweenWires = true;
11993
- this._updatePositions();
12031
+ this._setUpdatePositions(this._updatePosBetween);
11994
12032
  }
11995
12033
 
11996
12034
  setFillColor(value) {
@@ -12093,6 +12131,51 @@ class Wire3D {
12093
12131
 
12094
12132
  }
12095
12133
 
12134
+ const marker3D = function(scene, color) {
12135
+ const marker = new Dot3D(scene, {}, scene.canvas.canvas.parentNode, {
12136
+ borderColor: "white",
12137
+ fillColor: color,
12138
+ zIndex: 100
12139
+ });
12140
+
12141
+ return {
12142
+ update: function(worldPos) {
12143
+ if (worldPos)
12144
+ {
12145
+ marker.worldPos = worldPos;
12146
+ }
12147
+ marker.setVisible(!!worldPos);
12148
+ },
12149
+
12150
+ setFillColor: c => marker.setFillColor(c),
12151
+ setHighlighted: h => marker.setHighlighted(h),
12152
+ getCanvasPos: () => marker.canvasPos,
12153
+ getWorldPos: () => marker.worldPos,
12154
+ destroy: () => marker.destroy()
12155
+ };
12156
+ };
12157
+
12158
+ const wire3D = function(scene, color) {
12159
+ const wire = new Wire3D(scene, scene.canvas.canvas.ownerDocument.body, {
12160
+ color: color,
12161
+ thickness: 1,
12162
+ thicknessClickable: 6 // TODO: Remove to make not clickable?
12163
+ });
12164
+ wire.setVisible(false);
12165
+ return {
12166
+ update: (startWorldPos, endWorldPos) => {
12167
+ if (endWorldPos)
12168
+ {
12169
+ wire.setEnds(startWorldPos, endWorldPos);
12170
+ }
12171
+ wire.setVisible(!!endWorldPos);
12172
+ },
12173
+
12174
+ setColor: c => wire.setColor(c),
12175
+ destroy: () => wire.destroy()
12176
+ };
12177
+ };
12178
+
12096
12179
  function activateDraggableDot(dot, cfg) {
12097
12180
  const extractCFG = function(propName, defaultValue) {
12098
12181
  if (propName in cfg) {
@@ -12407,6 +12490,482 @@ const touchPointSelector = function(viewer, pointerCircle, ray2WorldPos) {
12407
12490
  };
12408
12491
  };
12409
12492
 
12493
+ const triangulateEarClipping = function(planeCoords) {
12494
+ const polygonVertices = [ ];
12495
+ for (let i = 0; i < planeCoords.length; ++i)
12496
+ polygonVertices.push(i);
12497
+
12498
+ const isCCW = (function() {
12499
+ const ba = math.vec2();
12500
+ const bc = math.vec2();
12501
+
12502
+ let anglesSum = 0;
12503
+
12504
+ for (let i = 0; i < polygonVertices.length; ++i)
12505
+ {
12506
+ const a = planeCoords[polygonVertices[i]];
12507
+ const b = planeCoords[polygonVertices[(i + 1) % polygonVertices.length]];
12508
+ const c = planeCoords[polygonVertices[(i + 2) % polygonVertices.length]];
12509
+
12510
+ math.subVec2(a, b, ba);
12511
+ math.subVec2(c, b, bc);
12512
+
12513
+ const theta = math.dotVec2(ba, bc) / Math.sqrt(math.sqLenVec2(ba) * math.sqLenVec2(bc));
12514
+ const angle = Math.acos(Math.max(-1, Math.min(theta, 1)));
12515
+ const convex = (ba[0] * bc[1] - ba[1] * bc[0]) >= 0;
12516
+ anglesSum += convex ? angle : (2 * Math.PI - angle);
12517
+ }
12518
+
12519
+ return anglesSum < (polygonVertices.length * Math.PI);
12520
+ })();
12521
+
12522
+ const pointInTriangle = (function() {
12523
+ const sign = (p1, p2, p3) => {
12524
+ return (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1]);
12525
+ };
12526
+
12527
+ return (pt, v1, v2, v3) => {
12528
+ const d1 = sign(pt, v1, v2);
12529
+ const d2 = sign(pt, v2, v3);
12530
+ const d3 = sign(pt, v3, v1);
12531
+
12532
+ const has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0);
12533
+ const has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0);
12534
+
12535
+ return !(has_neg && has_pos);
12536
+ };
12537
+ })();
12538
+
12539
+ const baseTriangles = [ ];
12540
+
12541
+ const vertices = (isCCW ? polygonVertices : polygonVertices.slice(0).reverse()).map(i => ({ idx: i }));
12542
+ vertices.forEach((v, i) => {
12543
+ v.prev = vertices[(i - 1 + vertices.length) % vertices.length];
12544
+ v.next = vertices[(i + 1) % vertices.length];
12545
+ });
12546
+
12547
+ const ba = math.vec2();
12548
+ const bc = math.vec2();
12549
+
12550
+ while (vertices.length > 2) {
12551
+ let earIdx = 0;
12552
+ while (true) {
12553
+ if (earIdx >= vertices.length)
12554
+ {
12555
+ throw `isCCW = ${isCCW}; earIdx = ${earIdx}; len = ${vertices.length}`;
12556
+ }
12557
+ const v = vertices[earIdx];
12558
+
12559
+ const a = planeCoords[v.prev.idx];
12560
+ const b = planeCoords[v.idx];
12561
+ const c = planeCoords[v.next.idx];
12562
+
12563
+ math.subVec2(a, b, ba);
12564
+ math.subVec2(c, b, bc);
12565
+
12566
+ if (((ba[0] * bc[1] - ba[1] * bc[0]) >= 0) // a convex vertex
12567
+ &&
12568
+ vertices.every( // no other vertices inside
12569
+ vv => ((vv === v)
12570
+ ||
12571
+ (vv === v.prev)
12572
+ ||
12573
+ (vv === v.next)
12574
+ ||
12575
+ !pointInTriangle(planeCoords[vv.idx], a, b, c))))
12576
+ break;
12577
+ ++earIdx;
12578
+ }
12579
+
12580
+ const ear = vertices[earIdx];
12581
+ vertices.splice(earIdx, 1);
12582
+
12583
+ baseTriangles.push([ ear.idx, ear.next.idx, ear.prev.idx ]);
12584
+
12585
+ const prev = ear.prev;
12586
+ prev.next = ear.next;
12587
+ const next = ear.next;
12588
+ next.prev = ear.prev;
12589
+ }
12590
+
12591
+ return [ planeCoords, baseTriangles, isCCW ];
12592
+ };
12593
+
12594
+ const addMousePressListener = function(element, onChange) {
12595
+ const moveTolerance = 4;
12596
+
12597
+ const copyElementPos = (event, out) => {
12598
+ out[0] = event.clientX;
12599
+ out[1] = event.clientY;
12600
+ transformToNode(element.ownerDocument.documentElement, element, out);
12601
+ return out;
12602
+ };
12603
+
12604
+ let buttonDown = false;
12605
+
12606
+ const cleanups = [ ];
12607
+ const cleanup = () => cleanups.forEach(c => c());
12608
+
12609
+ const addElementEventListener = (type, listener) => {
12610
+ element.addEventListener(type, listener);
12611
+ cleanups.push(() => element.removeEventListener(type, listener));
12612
+ };
12613
+
12614
+ const downPos = math.vec2();
12615
+ addElementEventListener("mousedown", function(event) {
12616
+ if (event.which === 1) {
12617
+ buttonDown = true;
12618
+ onChange(copyElementPos(event, downPos));
12619
+ }
12620
+ });
12621
+
12622
+ addElementEventListener("mousemove", function(event) {
12623
+ copyElementPos(event, tmpVec2a);
12624
+ if (buttonDown && (math.distVec2(downPos, tmpVec2a) > moveTolerance)) {
12625
+ buttonDown = false;
12626
+ }
12627
+ if (buttonDown || (! event.buttons & 1)) {
12628
+ onChange(tmpVec2a);
12629
+ }
12630
+ });
12631
+
12632
+ addElementEventListener("mouseup", function(event) {
12633
+ if ((event.which === 1) && buttonDown) {
12634
+ const commit = onChange(copyElementPos(event, tmpVec2a));
12635
+ if (commit) {
12636
+ cleanup();
12637
+ commit();
12638
+ }
12639
+ }
12640
+ });
12641
+
12642
+ return cleanup;
12643
+ };
12644
+
12645
+ const addTouchPressListener = function(element, cameraControl, pointerCircle, onChange) {
12646
+ const longTouchTimeoutMs = 300;
12647
+ const moveTolerance = 20;
12648
+ const startPos = math.vec2();
12649
+
12650
+ const copyElementPos = (event, out) => {
12651
+ out[0] = event.clientX;
12652
+ out[1] = event.clientY;
12653
+ transformToNode(element.ownerDocument.documentElement, element, out);
12654
+ return out;
12655
+ };
12656
+
12657
+ let longTouchTimeout = null;
12658
+ let onSingleTouchMove = nop;
12659
+ let startTouchIdentifier;
12660
+
12661
+ const resetAction = function() {
12662
+ clearTimeout(longTouchTimeout);
12663
+ pointerCircle.stop();
12664
+ cameraControl.active = true;
12665
+ onSingleTouchMove = nop;
12666
+ startTouchIdentifier = null;
12667
+ };
12668
+
12669
+ const cleanups = [ ];
12670
+ const cleanup = () => cleanups.forEach(c => c());
12671
+
12672
+ const addElementEventListener = (type, listener) => {
12673
+ element.addEventListener(type, listener, {passive: true});
12674
+ cleanups.push(() => element.removeEventListener(type, listener));
12675
+ };
12676
+
12677
+ addElementEventListener("touchstart", function(event) {
12678
+ const touches = event.touches;
12679
+
12680
+ if (touches.length !== 1)
12681
+ {
12682
+ resetAction();
12683
+ onChange(null);
12684
+ }
12685
+ else
12686
+ {
12687
+ const touch = touches[0];
12688
+ copyElementPos(touch, startPos);
12689
+
12690
+ startTouchIdentifier = touch.identifier;
12691
+
12692
+ onSingleTouchMove = elementPos => {
12693
+ if (math.distVec2(startPos, elementPos) > moveTolerance)
12694
+ {
12695
+ resetAction();
12696
+ }
12697
+ };
12698
+
12699
+ longTouchTimeout = setTimeout(
12700
+ function() {
12701
+ pointerCircle.start(startPos);
12702
+
12703
+ longTouchTimeout = setTimeout(
12704
+ function() {
12705
+ pointerCircle.stop();
12706
+ cameraControl.active = false;
12707
+ onSingleTouchMove = onChange;
12708
+ onSingleTouchMove(startPos);
12709
+ },
12710
+ longTouchTimeoutMs);
12711
+ },
12712
+ 250);
12713
+ }
12714
+ });
12715
+
12716
+ // element.addEventListener("touchcancel", e => console.log("touchcancel", e), {passive: true});
12717
+
12718
+ addElementEventListener("touchmove", function(event) {
12719
+ const touch = [...event.changedTouches].find(e => e.identifier === startTouchIdentifier);
12720
+ if (touch)
12721
+ {
12722
+ onSingleTouchMove(copyElementPos(touch, tmpVec2a));
12723
+ }
12724
+ });
12725
+
12726
+ addElementEventListener("touchend", function(event) {
12727
+ const touch = [...event.changedTouches].find(e => e.identifier === startTouchIdentifier);
12728
+ if (touch)
12729
+ {
12730
+ const commit = onChange(copyElementPos(touch, tmpVec2a));
12731
+ resetAction();
12732
+ if (commit) {
12733
+ cleanup();
12734
+ commit();
12735
+ } else {
12736
+ onChange(null);
12737
+ }
12738
+ }
12739
+ });
12740
+
12741
+ return () => {
12742
+ resetAction();
12743
+ cleanup();
12744
+ };
12745
+ };
12746
+
12747
+ const startPolygonCreate = function(scene, pointerLens, addPressListener, pickRayResult, onChange, onConclude) {
12748
+ const canvas = scene.canvas.canvas;
12749
+
12750
+ const updatePointerLens = (pointerLens
12751
+ ? function(canvasPos, isSnapped) {
12752
+ pointerLens.visible = !! canvasPos;
12753
+ if (canvasPos)
12754
+ {
12755
+ pointerLens.canvasPos = canvasPos;
12756
+ pointerLens.snapped = !! isSnapped;
12757
+ }
12758
+ }
12759
+ : () => { });
12760
+
12761
+ const testLastSegmentIntersects = (function() {
12762
+ const onSegment = (p, q, r) => ((q[0] <= Math.max(p[0], r[0])) &&
12763
+ (q[0] >= Math.min(p[0], r[0])) &&
12764
+ (q[1] <= Math.max(p[1], r[1])) &&
12765
+ (q[1] >= Math.min(p[1], r[1])));
12766
+
12767
+ const orient = (p, q, r) => {
12768
+ const val = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1]);
12769
+ // collinear
12770
+ // clockwise
12771
+ // counterclockwise
12772
+ return ((val === 0) ? 0 : ((val > 0) ? 1 : 2));
12773
+ };
12774
+
12775
+ return function(pos2D, lastSegmentClosesLoop) {
12776
+ const s = lastSegmentClosesLoop ? 1 : 0;
12777
+ const a = pos2D[(pos2D.length - 2 + s) % pos2D.length];
12778
+ const b = pos2D[(pos2D.length - 1 + s) % pos2D.length];
12779
+
12780
+ for (let i = s; i < pos2D.length - 2 - 1 + s; ++i) {
12781
+ const c = pos2D[i];
12782
+ const d = pos2D[i + 1];
12783
+
12784
+ const o1 = orient(a, b, c);
12785
+ const o2 = orient(a, b, d);
12786
+ const o3 = orient(c, d, a);
12787
+ const o4 = orient(c, d, b);
12788
+
12789
+ if (((o1 !== o2) && (o3 !== o4)) || // General case
12790
+ ((o1 === 0) && onSegment(a, c, b)) || // a, b and c are collinear and c lies on segment ab
12791
+ ((o2 === 0) && onSegment(a, d, b)) || // a, b and d are collinear and d lies on segment ab
12792
+ ((o3 === 0) && onSegment(c, a, d)) || // c, d and a are collinear and a lies on segment cd
12793
+ ((o4 === 0) && onSegment(c, b, d))) // c, d and b are collinear and b lies on segment cd
12794
+ {
12795
+ return true;
12796
+ }
12797
+ }
12798
+
12799
+ return false;
12800
+ };
12801
+ })();
12802
+
12803
+ const getPlane = (points) => (points.length >= 3) && (function() {
12804
+ const u = math.normalizeVec3(math.subVec3(points[1], points[0], math.vec3()));
12805
+ const v20 = math.normalizeVec3(math.subVec3(points[2], points[0], tmpVec3a$2));
12806
+ const normal = math.normalizeVec3(math.cross3Vec3(u, v20, math.vec3()));
12807
+ const v = math.normalizeVec3(math.cross3Vec3(normal, u, math.vec3()));
12808
+ return {
12809
+ normal: normal,
12810
+ origin: math.vec3(points[0]),
12811
+ u: u,
12812
+ v: v
12813
+ };
12814
+ })();
12815
+
12816
+ const vertices = [ ];
12817
+ let currentInteraction;
12818
+
12819
+ (function selectNextPoint() {
12820
+ const plane = getPlane(vertices);
12821
+
12822
+ const canvasPos2Ray = (canvasPos, dst) => (math.canvasPosToWorldRay(canvas, scene.camera.viewMatrix, scene.camera.projMatrix, scene.camera.projection, canvasPos, dst.origin, dst.direction), dst);
12823
+
12824
+ const pickRay = (ray) => {
12825
+ const pickResult = pickRayResult(ray);
12826
+ const snapWorldPos = pickResult && pickResult.entity && ((! plane) || pickResult.snapped) && pickResult.worldPos;
12827
+ if (plane) {
12828
+ const originDistance = math.dotVec3(plane.normal, plane.origin);
12829
+ const snapPlaneDist = (snapWorldPos
12830
+ ? ((originDistance - math.dotVec3(snapWorldPos, plane.normal)))
12831
+ : window.Infinity);
12832
+ if (Math.abs(snapPlaneDist) < 0.0001) {
12833
+ const ret = math.vec3();
12834
+ return {
12835
+ worldPos: math.addVec3(snapWorldPos, math.mulVec3Scalar(plane.normal, snapPlaneDist, ret), ret),
12836
+ snapped: true
12837
+ };
12838
+ } else {
12839
+ return {
12840
+ worldPos: planeIntersect$1(originDistance, plane.normal, ray.origin, ray.direction),
12841
+ snapped: false
12842
+ };
12843
+ }
12844
+ } else {
12845
+ return {
12846
+ worldPos: snapWorldPos,
12847
+ snapped: pickResult && pickResult.snapped
12848
+ };
12849
+ }
12850
+ };
12851
+
12852
+ let placeVertex = false;
12853
+ const removePressListener = addPressListener(
12854
+ (inputCanvasPos) => {
12855
+ const rayPick = inputCanvasPos && pickRay(canvasPos2Ray(inputCanvasPos, tmpRay));
12856
+ const worldPos = rayPick && rayPick.worldPos;
12857
+ return onWorldPos(worldPos, inputCanvasPos, rayPick && rayPick.snapped);
12858
+ });
12859
+
12860
+ const onWorldPos = (worldPos, inputCanvasPos, rayPickSnapped) => {
12861
+ const canvasPos = worldPos ? scene.camera.projectWorldPos(worldPos) : inputCanvasPos;
12862
+ const firstMarker = (vertices.length > 0) && (function() {
12863
+ const v = vertices[0];
12864
+ return {
12865
+ canvasPos: scene.camera.projectWorldPos(v),
12866
+ worldPos: v
12867
+ };
12868
+ })();
12869
+ const snapToFirst = (vertices.length >= 3) && ((canvasPos && (math.distVec2(canvasPos, firstMarker.canvasPos) < 10))
12870
+ ||
12871
+ (worldPos && math.compareVec3(worldPos, firstMarker.worldPos)));
12872
+
12873
+ updatePointerLens(snapToFirst ? firstMarker.canvasPos : canvasPos, snapToFirst || rayPickSnapped);
12874
+
12875
+ const lastPointOverlaps = (inputCanvasPos
12876
+ &&
12877
+ ((! worldPos)
12878
+ ||
12879
+ ((vertices.length < 3)
12880
+ ? vertices.some(v => math.compareVec3(v, worldPos))
12881
+ : math.compareVec3(vertices[vertices.length - 1], worldPos))));
12882
+
12883
+ const points = vertices.concat(((! snapToFirst) && worldPos && (! lastPointOverlaps)) ? [worldPos] : []);
12884
+
12885
+ const curPlane = (! lastPointOverlaps) && (plane || getPlane(points));
12886
+
12887
+ const uvs = curPlane && points.map(p => {
12888
+ math.subVec3(p, curPlane.origin, tmpVec3a$2);
12889
+ return math.vec2([ math.dotVec3(tmpVec3a$2, curPlane.u), math.dotVec3(tmpVec3a$2, curPlane.v) ]);
12890
+ });
12891
+
12892
+ const isValid = (! lastPointOverlaps) && (! (uvs && testLastSegmentIntersects(uvs, snapToFirst)));
12893
+ const geometry = isValid && uvs && (snapToFirst || (! testLastSegmentIntersects(uvs, true))) && (function() {
12894
+ try {
12895
+ const [ baseVertices, baseTriangles, isCCW ] = triangulateEarClipping(uvs);
12896
+ return {
12897
+ faces: baseTriangles,
12898
+ vertices: baseVertices.map(uv => math.addVec3(
12899
+ curPlane.origin,
12900
+ math.addVec3(
12901
+ math.mulVec3Scalar(curPlane.u, uv[0], tmpVec3a$2),
12902
+ math.mulVec3Scalar(curPlane.v, uv[1], tmpVec3b$2),
12903
+ tmpVec3a$2),
12904
+ math.vec3()))
12905
+ };
12906
+ } catch (e) {
12907
+ console.warn("e", e);
12908
+ return false;
12909
+ }
12910
+ })();
12911
+
12912
+ onChange(points, snapToFirst, isValid, geometry);
12913
+
12914
+ return placeVertex = (isValid && (snapToFirst
12915
+ ? () => {
12916
+ updatePointerLens(null);
12917
+ onConclude();
12918
+ }
12919
+ : () => {
12920
+ vertices.push(math.vec3(worldPos));
12921
+ updatePointerLens(null);
12922
+ selectNextPoint();
12923
+ }));
12924
+ };
12925
+
12926
+ currentInteraction = {
12927
+ closePolygon: (() => {
12928
+ const commit = (vertices.length >= 3) && onWorldPos(vertices[0]);
12929
+ if (commit) {
12930
+ removePressListener();
12931
+ commit();
12932
+ }
12933
+ return !! commit;
12934
+ }),
12935
+ placeVertex: () => {
12936
+ if (placeVertex) {
12937
+ removePressListener();
12938
+ placeVertex();
12939
+ }
12940
+ return !!placeVertex;
12941
+ },
12942
+ popVertex: () => {
12943
+ if (vertices.length > 0) {
12944
+ removePressListener();
12945
+ vertices.pop();
12946
+ selectNextPoint();
12947
+ return true;
12948
+ } else {
12949
+ return false;
12950
+ }
12951
+ },
12952
+ removePressListener: removePressListener,
12953
+ updateOnChange: () => onWorldPos()
12954
+ };
12955
+ })();
12956
+
12957
+ return {
12958
+ cancel: () => {
12959
+ currentInteraction.removePressListener();
12960
+ updatePointerLens(null);
12961
+ },
12962
+ closePolygon: () => currentInteraction.closePolygon(),
12963
+ placeVertex: () => currentInteraction.placeVertex(),
12964
+ popVertex: () => currentInteraction.popVertex(),
12965
+ updateOnChange: () => currentInteraction.updateOnChange()
12966
+ };
12967
+ };
12968
+
12410
12969
  const tmpVec3a$1 = math.vec3();
12411
12970
  const tmpVec3b$1 = math.vec3();
12412
12971
 
@@ -14826,6 +15385,8 @@ const tempVec3a$M = math.vec3();
14826
15385
  const tempVec3b$B = math.vec3();
14827
15386
  const tempVec3c$w = math.vec3();
14828
15387
 
15388
+ const px = x => x + "px";
15389
+
14829
15390
  /**
14830
15391
  * A {@link Marker} with an HTML label attached to it, managed by an {@link AnnotationsPlugin}.
14831
15392
  *
@@ -15032,22 +15593,29 @@ class Annotation extends Marker {
15032
15593
  * @private
15033
15594
  */
15034
15595
  _updateWithCurWidths() {
15035
- const px = x => x + "px";
15036
15596
  const boundary = this.scene.canvas.boundary;
15037
15597
  const left = boundary[0] + this.canvasPos[0];
15038
15598
  const top = boundary[1] + this.canvasPos[1];
15039
- const markerWidth = this._curMarkerWidth;
15040
- const markerDir = (this._markerAlign === "right") ? -1 : ((this._markerAlign === "center") ? 0 : 1);
15041
- const markerCenter = left + markerDir * (markerWidth / 2 - 12);
15042
- this._marker.style.left = px(markerCenter - markerWidth / 2);
15043
- this._marker.style.top = px(top - 12);
15044
- this._marker.style["z-index"] = 90005 + Math.floor(this._viewPos[2]) + 1;
15045
-
15046
- const labelWidth = this._curLabelWidth;
15047
- const labelDir = Math.sign(this._labelPosition);
15048
- this._label.style.left = px(markerCenter + labelDir * (markerWidth / 2 + Math.abs(this._labelPosition) + labelWidth / 2) - labelWidth / 2);
15599
+ this._marker.style.top = px(top - 12);
15049
15600
  this._label.style.top = px(top - 17);
15050
- this._label.style["z-index"] = 90005 + Math.floor(this._viewPos[2]) + 1;
15601
+
15602
+ if (this._markerAlign === "legacy") {
15603
+ this._marker.style.left = px(left - 12);
15604
+ this._label.style.left = px(left + 40);
15605
+ } else {
15606
+ const markerWidth = this._curMarkerWidth;
15607
+ const markerDir = (this._markerAlign === "right") ? -1 : ((this._markerAlign === "center") ? 0 : 1);
15608
+ const markerCenter = left + markerDir * (markerWidth / 2 - 12);
15609
+ this._marker.style.left = px(markerCenter - markerWidth / 2);
15610
+
15611
+ const labelWidth = this._curLabelWidth;
15612
+ const labelDir = Math.sign(this._labelPosition);
15613
+ this._label.style.left = px(markerCenter + labelDir * (markerWidth / 2 + Math.abs(this._labelPosition) + labelWidth / 2) - labelWidth / 2);
15614
+ }
15615
+
15616
+ const zIndex = 90005 + Math.floor(this._viewPos[2]) + 1;
15617
+ this._marker.style["z-index"] = zIndex;
15618
+ this._label.style["z-index"] = zIndex;
15051
15619
  }
15052
15620
 
15053
15621
  /**
@@ -15078,7 +15646,8 @@ class Annotation extends Marker {
15078
15646
  * @private
15079
15647
  */
15080
15648
  _updatePosition() {
15081
- if (this._curMarkerWidth === undefined) {
15649
+ const isLegacy = this._markerAlign === "legacy";
15650
+ if ((! isLegacy) && (this._curMarkerWidth === undefined)) {
15082
15651
  this._updateIfWidthsChanged();
15083
15652
  } else {
15084
15653
  // Update position with cached width values
@@ -15086,7 +15655,9 @@ class Annotation extends Marker {
15086
15655
  // so they don't interfere with e.g. interactive scene manipulation
15087
15656
  this._updateWithCurWidths();
15088
15657
  window.clearTimeout(this._widthTimeout);
15089
- this._widthTimeout = window.setTimeout(() => this._updateIfWidthsChanged(), 500);
15658
+ if (! isLegacy) {
15659
+ this._widthTimeout = window.setTimeout(() => this._updateIfWidthsChanged(), 500);
15660
+ }
15090
15661
  }
15091
15662
  }
15092
15663
 
@@ -15124,10 +15695,10 @@ class Annotation extends Marker {
15124
15695
  /**
15125
15696
  * Sets the horizontal alignment of the Annotation's marker HTML.
15126
15697
  *
15127
- * @param {String} align Either "left", "center", "right" (default "left")
15698
+ * @param {String} align Either "left", "center", "right", "legacy" (default "left")
15128
15699
  */
15129
15700
  setMarkerAlign(align) {
15130
- const valid = [ "left", "center", "right" ];
15701
+ const valid = [ "left", "center", "right", "legacy" ];
15131
15702
  if (! valid.includes(align)) {
15132
15703
  this.error("Param 'align' should be one of: " + JSON.stringify(valid));
15133
15704
  } else {
@@ -26510,6 +27081,65 @@ class ReadableGeometry extends Geometry {
26510
27081
  return this._obb;
26511
27082
  }
26512
27083
 
27084
+ _getMetrics() {
27085
+ if (! ("_metrics" in this)) {
27086
+ switch (this._state.primitiveName) {
27087
+ case "solid":
27088
+ case "surface":
27089
+ case "triangles": {
27090
+ const indices = this._state.indices;
27091
+ const positions = this._state.positions;
27092
+ const getPos = (i, out) => {
27093
+ const idx = indices[i] * 3;
27094
+ for (let j = 0; j < 3; ++j) {
27095
+ out[j] = positions[idx + j];
27096
+ } return out;
27097
+ };
27098
+ const tmp = [ math.vec3(), math.vec3(), math.vec3(), math.vec3() ];
27099
+ let totalArea = 0;
27100
+ const centroid = math.vec3([ 0, 0, 0 ]);
27101
+ for (let i = 0; i < indices.length; i += 3) {
27102
+ const v0 = getPos(i, tmp[0]);
27103
+ const v1 = getPos(i+1, tmp[1]);
27104
+ const v2 = getPos(i+2, tmp[2]);
27105
+ math.addVec3(v0, v1, tmp[3]);
27106
+ math.addVec3(v2, tmp[3], tmp[3]);
27107
+ const faceArea = math.lenVec3(
27108
+ math.cross3Vec3(
27109
+ math.subVec3(v1, v0, tmp[1]),
27110
+ math.subVec3(v2, v0, tmp[2]),
27111
+ tmp[0])) / 2;
27112
+ totalArea += faceArea;
27113
+ math.mulVec3Scalar(tmp[3], faceArea, tmp[3]);
27114
+ math.addVec3(centroid, tmp[3], centroid);
27115
+ }
27116
+ this._metrics = { surfaceArea: totalArea, centroid: math.mulVec3Scalar(centroid, 1 / totalArea / 3, centroid) };
27117
+ break;
27118
+ }
27119
+ default:
27120
+ this._metrics = { surfaceArea: 0 };
27121
+ break;
27122
+ }
27123
+ }
27124
+ return this._metrics;
27125
+ }
27126
+
27127
+ /**
27128
+ * Returns the surface area of this Mesh.
27129
+ * @returns {number}
27130
+ */
27131
+ get surfaceArea() {
27132
+ return this._getMetrics().surfaceArea;
27133
+ }
27134
+
27135
+ /**
27136
+ * Returns the centroid of this Mesh.
27137
+ * @returns {number}
27138
+ */
27139
+ get centroid() {
27140
+ return this._getMetrics().centroid;
27141
+ }
27142
+
26513
27143
  /**
26514
27144
  * Approximate number of triangles in this ReadableGeometry.
26515
27145
  *
@@ -40058,7 +40688,7 @@ function buildPlaneGeometry(cfg = {}) {
40058
40688
  positions[offset + 1] = centerY;
40059
40689
  positions[offset + 2] = -z + centerZ;
40060
40690
 
40061
- normals[offset + 2] = -1;
40691
+ normals[offset + 1] = 1;
40062
40692
 
40063
40693
  uvs[offset2] = (ix) / planeX;
40064
40694
  uvs[offset2 + 1] = ((planeZ - iz) / planeZ);
@@ -43356,8 +43986,7 @@ class SectionCaps {
43356
43986
  if(!this._resourcesAllocated) {
43357
43987
  this._resourcesAllocated = true;
43358
43988
  this._sectionPlanes = [];
43359
- this._verticesMap = {};
43360
- this._indicesMap = {};
43989
+ this._sceneModelsData = {};
43361
43990
  this._dirtyMap = {};
43362
43991
  this._prevIntersectionModelsMap = {};
43363
43992
  this._sectionPlaneTimeout = null;
@@ -43372,7 +44001,8 @@ class SectionCaps {
43372
44001
  this._sectionPlanes.push(sectionPlane);
43373
44002
  sectionPlane.on('pos', onSectionPlaneUpdated);
43374
44003
  sectionPlane.on('dir', onSectionPlaneUpdated);
43375
- sectionPlane.once('destroyed', ((sectionPlane) => {
44004
+ sectionPlane.on('active', onSectionPlaneUpdated);
44005
+ sectionPlane.once('destroyed', (() => {
43376
44006
  const sectionPlaneId = sectionPlane.id;
43377
44007
  if (sectionPlaneId) {
43378
44008
  this._sectionPlanes = this._sectionPlanes.filter((sectionPlane) => sectionPlane.id !== sectionPlaneId);
@@ -43389,13 +44019,19 @@ class SectionCaps {
43389
44019
 
43390
44020
  this._onTick = this.scene.on("tick", () => {
43391
44021
  //on ticks we only check if there is a model that we have saved vertices for,
43392
- //but it's no more available on the scene
43393
- for(const key in this._verticesMap) {
43394
- if(!this.scene.models[key]){
43395
- delete this._verticesMap[key];
43396
- delete this._indicesMap[key];
43397
- this._update();
43398
- }
44022
+ //but it's no more available on the scene, or if its visibility changed
44023
+ let dirty = false;
44024
+ for(const sceneModelId in this._sceneModelsData) {
44025
+ if(!this.scene.models[sceneModelId]){
44026
+ delete this._sceneModelsData[sceneModelId];
44027
+ dirty = true;
44028
+ } else if (this._sceneModelsData[sceneModelId].visible !== (!!this.scene.models[sceneModelId].visible)) {
44029
+ this._sceneModelsData[sceneModelId].visible = !!this.scene.models[sceneModelId].visible;
44030
+ dirty = true;
44031
+ }
44032
+ }
44033
+ if (dirty) {
44034
+ this._update();
43399
44035
  }
43400
44036
  });
43401
44037
  }
@@ -43412,8 +44048,8 @@ class SectionCaps {
43412
44048
  this._deletePreviousModels();
43413
44049
  this._updateTimeout = setTimeout(() => {
43414
44050
  clearTimeout(this._updateTimeout);
43415
- const sceneModels = Object.keys(this.scene.models).map((key) => this.scene.models[key]);
43416
- this._addHatches(sceneModels, this._sectionPlanes);
44051
+ const sceneModels = Object.values(this.scene.models).filter(sceneModel => sceneModel.visible);
44052
+ this._addHatches(sceneModels, this._sectionPlanes.filter(sectionPlane => sectionPlane.active));
43417
44053
  this._setAllDirty(false);
43418
44054
  }, 100);
43419
44055
  }
@@ -43426,21 +44062,9 @@ class SectionCaps {
43426
44062
 
43427
44063
  _addHatches(sceneModels, planes) {
43428
44064
 
43429
- if (planes.length <= 0) return;
43430
-
43431
44065
  planes.forEach((plane) => {
43432
44066
  sceneModels.forEach((sceneModel) => {
43433
- //#region creating a plane equation
43434
- //we create a plane equation that will be used to slice through each triangle
43435
- const planeEquation = {
43436
- A: plane.dir[0],
43437
- B: plane.dir[1],
43438
- C: plane.dir[2],
43439
- D: -(plane.dir[0] * plane.pos[0] + plane.dir[1] * plane.pos[1] + plane.dir[2] * plane.pos[2])
43440
- };
43441
- //#endregion
43442
-
43443
- if(!this._doesPlaneIntersectBoundingBox(sceneModel.aabb, planeEquation)) return;
44067
+ if(!this._doesPlaneIntersectBoundingBox(sceneModel.aabb, plane)) return;
43444
44068
 
43445
44069
  if(!this._dirtyMap[sceneModel.id]) return;
43446
44070
 
@@ -43462,39 +44086,35 @@ class SectionCaps {
43462
44086
 
43463
44087
  const object = objects[objectId];
43464
44088
 
43465
- if(!this._doesPlaneIntersectBoundingBox(object.aabb, planeEquation)) return;
44089
+ if(!this._doesPlaneIntersectBoundingBox(object.aabb, plane)) return;
43466
44090
 
43467
- if(!this._verticesMap[sceneModel.id]) {
43468
- this._verticesMap[sceneModel.id] = new Map();
43469
- this._indicesMap[sceneModel.id] = new Map();
44091
+ if(!this._sceneModelsData[sceneModel.id]) {
44092
+ this._sceneModelsData[sceneModel.id] = {
44093
+ verticesMap: new Map(),
44094
+ indicesMap: new Map()
44095
+ };
43470
44096
  }
43471
44097
 
43472
- let vertices = [], indices = [];
44098
+ const sceneModelData = this._sceneModelsData[sceneModel.id];
43473
44099
 
43474
- if(!this._verticesMap[sceneModel.id].has(objectId)) {
44100
+ if(!sceneModelData.verticesMap.has(objectId)) {
43475
44101
  const isSolid = object.meshes[0].isSolid();
44102
+ const vertices = [ ];
44103
+ const indices = [ ];
43476
44104
  if(isSolid && object.capMaterial) {
43477
- object.getEachVertex((_vertices) => {
43478
- vertices.push(_vertices[0], _vertices[1], _vertices[2]);
43479
- });
43480
- object.getEachIndex((_indices) => {
43481
- indices.push(_indices);
43482
- });
44105
+ object.getEachVertex(v => vertices.push(v[0], v[1], v[2]));
44106
+ object.getEachIndex(i => indices.push(i));
43483
44107
  }
43484
- this._verticesMap[sceneModel.id].set(objectId, vertices);
43485
- this._indicesMap[sceneModel.id].set(objectId, indices);
44108
+ sceneModelData.verticesMap.set(objectId, vertices);
44109
+ sceneModelData.indicesMap.set(objectId, indices);
43486
44110
  }
43487
- else {
43488
- vertices = this._verticesMap[sceneModel.id].get(objectId);
43489
- indices = this._indicesMap[sceneModel.id].get(objectId);
43490
- }
43491
-
44111
+
44112
+ const vertices = sceneModelData.verticesMap.get(objectId);
44113
+ const indices = sceneModelData.indicesMap.get(objectId);
44114
+
43492
44115
  const capSegments = [];
43493
44116
  const vertCount = indices.length;
43494
-
43495
- // Preallocate intersection result array
43496
- const intersectionBuffer = new Float32Array(3);
43497
-
44117
+
43498
44118
  for (let i = 0; i < vertCount; i += 3) {
43499
44119
  // Reuse triangle buffer instead of creating new arrays
43500
44120
  for (let j = 0; j < 3; j++) {
@@ -43511,21 +44131,15 @@ class SectionCaps {
43511
44131
  for (let i = 0; i < 3; i++) {
43512
44132
  const p1 = triangle[i];
43513
44133
  const p2 = triangle[(i + 1) % 3];
43514
-
43515
- // Inline the distance calculations to avoid function calls
43516
- const d1 = planeEquation.A * p1[0] + planeEquation.B * p1[1] + planeEquation.C * p1[2] + planeEquation.D;
43517
- const d2 = planeEquation.A * p2[0] + planeEquation.B * p2[1] + planeEquation.C * p2[2] + planeEquation.D;
43518
-
44134
+
44135
+ const d1 = plane.dist + math.dotVec3(plane.dir, p1);
44136
+ const d2 = plane.dist + math.dotVec3(plane.dir, p2);
44137
+
43519
44138
  if (d1 * d2 > 0) continue;
43520
-
44139
+
43521
44140
  const t = -d1 / (d2 - d1);
43522
- // Reuse intersection buffer
43523
- intersectionBuffer[0] = p1[0] + t * (p2[0] - p1[0]);
43524
- intersectionBuffer[1] = p1[1] + t * (p2[1] - p1[1]);
43525
- intersectionBuffer[2] = p1[2] + t * (p2[2] - p1[2]);
43526
-
43527
- // Clone the buffer for storage
43528
- intersections.push(new Float32Array(intersectionBuffer));
44141
+
44142
+ intersections.push(math.lerpVec3(t, 0, 1, p1, p2, math.vec3()));
43529
44143
  }
43530
44144
 
43531
44145
  if(intersections.length === 2) capSegments.push(intersections);
@@ -43805,7 +44419,7 @@ class SectionCaps {
43805
44419
 
43806
44420
  }
43807
44421
 
43808
- _doesPlaneIntersectBoundingBox(bb, planeEquation) {
44422
+ _doesPlaneIntersectBoundingBox(bb, plane) {
43809
44423
  const min = [bb[0], bb[1], bb[2]];
43810
44424
  const max = [bb[3], bb[4], bb[5]];
43811
44425
 
@@ -43825,10 +44439,7 @@ class SectionCaps {
43825
44439
  let hasNegative = false;
43826
44440
 
43827
44441
  for (const corner of corners) {
43828
- const distance = planeEquation.A * corner[0] +
43829
- planeEquation.B * corner[1] +
43830
- planeEquation.C * corner[2] +
43831
- planeEquation.D;
44442
+ const distance = plane.dist + math.dotVec3(plane.dir, corner);
43832
44443
 
43833
44444
  if (distance > 0) hasPositive = true;
43834
44445
  if (distance < 0) hasNegative = true;
@@ -44323,13 +44934,12 @@ class Scene extends Component {
44323
44934
  * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing
44324
44935
  * responsiveness. It is important to consider that each SectionPlane imposes rendering performance, so it is recommended to set this value to a quantity that aligns with
44325
44936
  * your expected usage.
44326
- * @throws {String} Throws an exception when both canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.
44937
+ * @throws {String} Throws an exception when canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.
44327
44938
  */
44328
44939
  constructor(viewer, cfg = {}) {
44329
44940
 
44330
44941
  super(null, cfg);
44331
-
44332
- const canvas = cfg.canvasElement || document.getElementById(cfg.canvasId);
44942
+ const canvas = cfg.canvasElement || document.querySelector(`#${cfg.canvasId}`);
44333
44943
 
44334
44944
  if (!(canvas instanceof HTMLCanvasElement)) {
44335
44945
  throw "Mandatory config expected: valid canvasId or canvasElement";
@@ -123577,6 +124187,7 @@ function CubeTextureCanvas(viewer, navCubeScene, cfg = {}) {
123577
124187
  const cubeColor = "lightgrey";
123578
124188
  const cubeHighlightColor = cfg.hoverColor || "rgba(0,0,0,0.4)";
123579
124189
  const textColor = cfg.textColor || "black";
124190
+ const parentNode = cfg.canvasElement || document.body;
123580
124191
 
123581
124192
  const height = 500;
123582
124193
  const width = height + (height / 3);
@@ -123686,8 +124297,7 @@ function CubeTextureCanvas(viewer, navCubeScene, cfg = {}) {
123686
124297
  this._textureCanvas.style.visibility = "hidden";
123687
124298
  this._textureCanvas.style["z-index"] = 2000000;
123688
124299
 
123689
- const body = document.getElementsByTagName("body")[0];
123690
- body.appendChild(this._textureCanvas);
124300
+ parentNode.appendChild(this._textureCanvas);
123691
124301
 
123692
124302
  const context = this._textureCanvas.getContext("2d");
123693
124303
 
@@ -123957,7 +124567,7 @@ class NavCubePlugin extends Plugin {
123957
124567
  this._navCubeScene = new Scene(viewer, {
123958
124568
  canvasId: cfg.canvasId,
123959
124569
  canvasElement: cfg.canvasElement,
123960
- transparent: true
124570
+ transparent: true,
123961
124571
  });
123962
124572
 
123963
124573
  this._navCubeCanvas = this._navCubeScene.canvas.canvas;
@@ -124190,7 +124800,7 @@ class NavCubePlugin extends Plugin {
124190
124800
  }
124191
124801
  });
124192
124802
 
124193
- document.addEventListener("mouseup", self._onMouseUp = function (e) {
124803
+ self._navCubeCanvas.addEventListener("mouseup", self._onMouseUp = function (e) {
124194
124804
  if (e.which !== 1) {// Left button
124195
124805
  return;
124196
124806
  }
@@ -124207,7 +124817,7 @@ class NavCubePlugin extends Plugin {
124207
124817
  if (hit.uv) {
124208
124818
  var areaId = self._cubeTextureCanvas.getArea(hit.uv);
124209
124819
  if (areaId >= 0) {
124210
- document.body.style.cursor = "pointer";
124820
+ self._navCubeCanvas.style.cursor = "pointer";
124211
124821
  if (lastAreaId >= 0) {
124212
124822
  self._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);
124213
124823
  self._repaint();
@@ -124233,7 +124843,7 @@ class NavCubePlugin extends Plugin {
124233
124843
  self._repaint();
124234
124844
  lastAreaId = -1;
124235
124845
  }
124236
- document.body.style.cursor = "pointer";
124846
+ self._navCubeCanvas.style.cursor = "pointer";
124237
124847
  if (lastAreaId >= 0) {
124238
124848
  self._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);
124239
124849
  self._repaint();
@@ -124252,7 +124862,7 @@ class NavCubePlugin extends Plugin {
124252
124862
  }
124253
124863
  });
124254
124864
 
124255
- document.addEventListener("mousemove", self._onMouseMove = function (e) {
124865
+ self._navCubeCanvas.addEventListener("mousemove", self._onMouseMove = function (e) {
124256
124866
  if (lastAreaId >= 0) {
124257
124867
  self._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);
124258
124868
  self._repaint();
@@ -124264,7 +124874,7 @@ class NavCubePlugin extends Plugin {
124264
124874
  if (down) {
124265
124875
  var posX = e.clientX;
124266
124876
  var posY = e.clientY;
124267
- document.body.style.cursor = "move";
124877
+ self._navCubeCanvas.style.cursor = "move";
124268
124878
  actionMove(posX, posY);
124269
124879
  return;
124270
124880
  }
@@ -124278,7 +124888,7 @@ class NavCubePlugin extends Plugin {
124278
124888
  });
124279
124889
  if (hit) {
124280
124890
  if (hit.uv) {
124281
- document.body.style.cursor = "pointer";
124891
+ self._navCubeCanvas.style.cursor = "pointer";
124282
124892
  var areaId = self._cubeTextureCanvas.getArea(hit.uv);
124283
124893
  if (areaId === lastAreaId) {
124284
124894
  return;
@@ -124293,7 +124903,7 @@ class NavCubePlugin extends Plugin {
124293
124903
  }
124294
124904
  }
124295
124905
  } else {
124296
- document.body.style.cursor = "default";
124906
+ self._navCubeCanvas.style.cursor = "default";
124297
124907
  if (lastAreaId >= 0) {
124298
124908
  self._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);
124299
124909
  self._repaint();
@@ -124556,8 +125166,8 @@ class NavCubePlugin extends Plugin {
124556
125166
  this._navCubeCanvas.removeEventListener("mouseleave", this._onMouseLeave);
124557
125167
  this._navCubeCanvas.removeEventListener("mousedown", this._onMouseDown);
124558
125168
 
124559
- document.removeEventListener("mousemove", this._onMouseMove);
124560
- document.removeEventListener("mouseup", this._onMouseUp);
125169
+ this._navCubeCanvas.removeEventListener("mousemove", this._onMouseMove);
125170
+ this._navCubeCanvas.removeEventListener("mouseup", this._onMouseUp);
124561
125171
 
124562
125172
  this._navCubeCanvas = null;
124563
125173
  this._cubeTextureCanvas.destroy();
@@ -125951,8 +126561,8 @@ class Control {
125951
126561
  const canvasPos = math.vec2();
125952
126562
 
125953
126563
  const copyCanvasPos = (event, vec2) => {
125954
- vec2[0] = event.clientX;
125955
- vec2[1] = event.clientY;
126564
+ vec2[0] = event.pageX;
126565
+ vec2[1] = event.pageY;
125956
126566
  transformToNode(canvas.ownerDocument.documentElement, canvas, vec2);
125957
126567
  };
125958
126568
 
@@ -168432,151 +169042,6 @@ const hex2rgb = function(color) {
168432
169042
  return [ rgb(0), rgb(2), rgb(4) ];
168433
169043
  };
168434
169044
 
168435
- const triangulateEarClipping = function(planeCoords) {
168436
-
168437
- const polygonVertices = [ ];
168438
- for (let i = 0; i < planeCoords.length; ++i)
168439
- polygonVertices.push(i);
168440
-
168441
- const isCCW = (function() {
168442
- const ba = math.vec2();
168443
- const bc = math.vec2();
168444
-
168445
- let anglesSum = 0;
168446
-
168447
- for (let i = 0; i < polygonVertices.length; ++i)
168448
- {
168449
- const a = planeCoords[polygonVertices[i]];
168450
- const b = planeCoords[polygonVertices[(i + 1) % polygonVertices.length]];
168451
- const c = planeCoords[polygonVertices[(i + 2) % polygonVertices.length]];
168452
-
168453
- math.subVec2(a, b, ba);
168454
- math.subVec2(c, b, bc);
168455
-
168456
- const theta = math.dotVec2(ba, bc) / Math.sqrt(math.sqLenVec2(ba) * math.sqLenVec2(bc));
168457
- const angle = Math.acos(Math.max(-1, Math.min(theta, 1)));
168458
- const convex = (ba[0] * bc[1] - ba[1] * bc[0]) >= 0;
168459
- anglesSum += convex ? angle : (2 * Math.PI - angle);
168460
- }
168461
-
168462
- return anglesSum < (polygonVertices.length * Math.PI);
168463
- })();
168464
-
168465
- const pointInTriangle = (function() {
168466
- const sign = (p1, p2, p3) => {
168467
- return (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1]);
168468
- };
168469
-
168470
- return (pt, v1, v2, v3) => {
168471
- const d1 = sign(pt, v1, v2);
168472
- const d2 = sign(pt, v2, v3);
168473
- const d3 = sign(pt, v3, v1);
168474
-
168475
- const has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0);
168476
- const has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0);
168477
-
168478
- return !(has_neg && has_pos);
168479
- };
168480
- })();
168481
-
168482
- const baseTriangles = [ ];
168483
-
168484
- const vertices = (isCCW ? polygonVertices : polygonVertices.slice(0).reverse()).map(i => ({ idx: i }));
168485
- vertices.forEach((v, i) => {
168486
- v.prev = vertices[(i - 1 + vertices.length) % vertices.length];
168487
- v.next = vertices[(i + 1) % vertices.length];
168488
- });
168489
-
168490
- const ba = math.vec2();
168491
- const bc = math.vec2();
168492
-
168493
- while (vertices.length > 2) {
168494
- let earIdx = 0;
168495
- while (true) {
168496
- if (earIdx >= vertices.length)
168497
- {
168498
- throw `isCCW = ${isCCW}; earIdx = ${earIdx}; len = ${vertices.length}`;
168499
- }
168500
- const v = vertices[earIdx];
168501
-
168502
- const a = planeCoords[v.prev.idx];
168503
- const b = planeCoords[v.idx];
168504
- const c = planeCoords[v.next.idx];
168505
-
168506
- math.subVec2(a, b, ba);
168507
- math.subVec2(c, b, bc);
168508
-
168509
- if (((ba[0] * bc[1] - ba[1] * bc[0]) >= 0) // a convex vertex
168510
- &&
168511
- vertices.every( // no other vertices inside
168512
- vv => ((vv === v)
168513
- ||
168514
- (vv === v.prev)
168515
- ||
168516
- (vv === v.next)
168517
- ||
168518
- !pointInTriangle(planeCoords[vv.idx], a, b, c))))
168519
- break;
168520
- ++earIdx;
168521
- }
168522
-
168523
- const ear = vertices[earIdx];
168524
- vertices.splice(earIdx, 1);
168525
-
168526
- baseTriangles.push([ ear.idx, ear.next.idx, ear.prev.idx ]);
168527
-
168528
- const prev = ear.prev;
168529
- prev.next = ear.next;
168530
- const next = ear.next;
168531
- next.prev = ear.prev;
168532
- }
168533
-
168534
- return [ planeCoords, baseTriangles, isCCW ];
168535
- };
168536
-
168537
- const marker3D = function(scene, color) {
168538
- const marker = new Dot3D(scene, {}, scene.canvas.canvas.parentNode, {
168539
- borderColor: "white",
168540
- fillColor: color,
168541
- zIndex: 100
168542
- });
168543
-
168544
- return {
168545
- update: function(worldPos) {
168546
- if (worldPos)
168547
- {
168548
- marker.worldPos = worldPos;
168549
- }
168550
- marker.setVisible(!!worldPos);
168551
- },
168552
-
168553
- setHighlighted: h => marker.setHighlighted(h),
168554
- getCanvasPos: () => marker.canvasPos,
168555
- getWorldPos: () => marker.worldPos,
168556
- destroy: () => marker.destroy()
168557
- };
168558
- };
168559
-
168560
- const wire3D = function(scene, color, startWorldPos) {
168561
- const wire = new Wire3D(scene, scene.canvas.canvas.ownerDocument.body, {
168562
- color: color,
168563
- thickness: 1,
168564
- thicknessClickable: 6
168565
- });
168566
- wire.setVisible(false);
168567
- return {
168568
- update: endWorldPos => {
168569
- if (endWorldPos)
168570
- {
168571
- wire.setEnds(startWorldPos, endWorldPos);
168572
- }
168573
- wire.setVisible(!!endWorldPos);
168574
- },
168575
-
168576
- destroy: () => wire.destroy()
168577
- };
168578
- };
168579
-
168580
169045
  const basePolygon3D = function(scene, color, alpha) {
168581
169046
  let mesh = null;
168582
169047
 
@@ -169556,7 +170021,8 @@ const startPolysurfaceZoneCreateUI = function(scene, zoneAltitude, zoneHeight, z
169556
170021
 
169557
170022
  (function selectNextPoint(markers) {
169558
170023
  const marker = marker3D(scene, zoneColor);
169559
- const wire = (markers.length > 0) && wire3D(scene, zoneColor, markers[markers.length - 1].getWorldPos());
170024
+ const wire = (markers.length > 0) && wire3D(scene, zoneColor);
170025
+ const wireStart = wire && markers[markers.length - 1].getWorldPos();
169560
170026
 
169561
170027
  cleanups.push(() => {
169562
170028
  marker.destroy();
@@ -169616,7 +170082,7 @@ const startPolysurfaceZoneCreateUI = function(scene, zoneAltitude, zoneHeight, z
169616
170082
  () => {
169617
170083
  updatePointerLens(null);
169618
170084
  marker.update(null);
169619
- wire && wire.update(null);
170085
+ wire && wire.update(wireStart, null);
169620
170086
  basePolygon.updateBase((markers.length > 2) ? markers.map(m => m.getWorldPos()) : null);
169621
170087
  },
169622
170088
  (canvasPos, worldPos) => {
@@ -169624,7 +170090,7 @@ const startPolysurfaceZoneCreateUI = function(scene, zoneAltitude, zoneHeight, z
169624
170090
  firstMarker && firstMarker.setHighlighted(!! snappedFirst);
169625
170091
  updatePointerLens(snappedFirst ? snappedFirst.canvasPos : canvasPos);
169626
170092
  marker.update((! snappedFirst) && worldPos);
169627
- wire && wire.update(snappedFirst ? snappedFirst.worldPos : worldPos);
170093
+ wire && wire.update(wireStart, snappedFirst ? snappedFirst.worldPos : worldPos);
169628
170094
  if ((markers.length >= 2))
169629
170095
  {
169630
170096
  const pos = markers.map(m => m.getWorldPos()).concat(snappedFirst ? [] : [worldPos]);
@@ -169668,7 +170134,7 @@ const startPolysurfaceZoneCreateUI = function(scene, zoneAltitude, zoneHeight, z
169668
170134
  else
169669
170135
  {
169670
170136
  marker.update(worldPos);
169671
- wire && wire.update(worldPos);
170137
+ wire && wire.update(wireStart, worldPos);
169672
170138
  selectNextPoint(markers.concat(marker));
169673
170139
  }
169674
170140
  });
@@ -170103,4 +170569,4 @@ class ZoneTranslateTouchControl extends ZoneTranslateControl {
170103
170569
  }
170104
170570
  }
170105
170571
 
170106
- export { AlphaFormat, AmbientLight, AngleMeasurementEditMouseControl, AngleMeasurementEditTouchControl, AngleMeasurementsControl, AngleMeasurementsMouseControl, AngleMeasurementsPlugin, AngleMeasurementsTouchControl, AnnotationsPlugin, AxisGizmoPlugin, BCFViewpointsPlugin, Bitmap, ByteType, CameraMemento, CameraPath, CameraPathAnimation, CityJSONLoaderPlugin, ClampToEdgeWrapping, Component, CompressedMediaType, Configs, ContextMenu, CubicBezierCurve, Curve, CxConverterIFCLoaderPlugin, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DirLight, DistanceMeasurementEditControl, DistanceMeasurementEditMouseControl, DistanceMeasurementEditTouchControl, DistanceMeasurementsControl, DistanceMeasurementsMouseControl, DistanceMeasurementsPlugin, DistanceMeasurementsTouchControl, Dot3D, DotBIMDefaultDataSource, DotBIMLoaderPlugin, EdgeMaterial, EmphasisMaterial, FaceAlignedSectionPlanesPlugin, FastNavPlugin, FloatType, Fresnel, Frustum$1 as Frustum, FrustumPlane, GIFMediaType, GLTFDefaultDataSource, GLTFLoaderPlugin, HalfFloatType, ImagePlane, IntType, JPEGMediaType, KTX2TextureTranscoder, LASLoaderPlugin, Label3D, LambertMaterial, LightMap, LineSet, LinearEncoding, LinearFilter, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, Loader, LoadingManager, LocaleService, LuminanceAlphaFormat, LuminanceFormat, Map$1 as Map, Marker, MarqueePicker, MarqueePickerMouseControl, Mesh, MeshSurfaceArea, MeshVolume, MetallicMaterial, MirroredRepeatWrapping, ModelMemento, NavCubePlugin, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, Node$1 as Node, OBJLoaderPlugin, ObjectsKdTree3, ObjectsMemento, PNGMediaType, Path, PerformanceModel, PhongMaterial, PickResult, Plugin, PointLight, PointerCircle, PointerLens, QuadraticBezierCurve, Queue, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, ReadableGeometry, RedFormat, RedIntegerFormat, ReflectionMap, RepeatWrapping, STLDefaultDataSource, STLLoaderPlugin, SceneModel, SceneModelMesh, SceneModelTransform, SectionPlane, SectionPlanesPlugin, ShortType, Skybox, SkyboxesPlugin, SpecularMaterial, SplineCurve, SpriteMarker, StoreyViewsPlugin, Texture, TextureTranscoder, TreeViewPlugin, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VBOGeometry, ViewCullPlugin, Viewer, WebIFCLoaderPlugin, Wire3D, WorkerPool$1 as WorkerPool, XKTDefaultDataSource, XKTLoaderPlugin, XML3DLoaderPlugin, ZoneEditControl, ZoneEditMouseControl, ZoneEditTouchControl, ZoneTranslateControl, ZoneTranslateMouseControl, ZoneTranslateTouchControl, ZonesMouseControl, ZonesPlugin, ZonesPolysurfaceMouseControl, ZonesPolysurfaceTouchControl, ZonesTouchControl, activateDraggableDot, activateDraggableDots, buildBoxGeometry, buildBoxLinesGeometry, buildBoxLinesGeometryFromAABB, buildCylinderGeometry, buildGridGeometry, buildLineGeometry, buildPlaneGeometry, buildPolylineGeometry, buildPolylineGeometryFromCurve, buildSphereGeometry, buildTorusGeometry, buildVectorTextGeometry, createRTCViewMat, frustumIntersectsAABB3, getKTX2TextureTranscoder, getPlaneRTCPos, isTriangleMeshSolid, load3DSGeometry, loadOBJGeometry, math, meshSurfaceArea, meshVolume, os, rtcToWorldPos, sRGBEncoding, setFrustum, stats, touchPointSelector, transformToNode, utils, worldToRTCPos, worldToRTCPositions };
170572
+ export { AlphaFormat, AmbientLight, AngleMeasurementEditMouseControl, AngleMeasurementEditTouchControl, AngleMeasurementsControl, AngleMeasurementsMouseControl, AngleMeasurementsPlugin, AngleMeasurementsTouchControl, AnnotationsPlugin, AxisGizmoPlugin, BCFViewpointsPlugin, Bitmap, ByteType, CameraMemento, CameraPath, CameraPathAnimation, CityJSONLoaderPlugin, ClampToEdgeWrapping, Component, CompressedMediaType, Configs, ContextMenu, CubicBezierCurve, Curve, CxConverterIFCLoaderPlugin, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DirLight, DistanceMeasurementEditControl, DistanceMeasurementEditMouseControl, DistanceMeasurementEditTouchControl, DistanceMeasurementsControl, DistanceMeasurementsMouseControl, DistanceMeasurementsPlugin, DistanceMeasurementsTouchControl, Dot3D, DotBIMDefaultDataSource, DotBIMLoaderPlugin, EdgeMaterial, EmphasisMaterial, FaceAlignedSectionPlanesPlugin, FastNavPlugin, FloatType, Fresnel, Frustum$1 as Frustum, FrustumPlane, GIFMediaType, GLTFDefaultDataSource, GLTFLoaderPlugin, HalfFloatType, ImagePlane, IntType, JPEGMediaType, KTX2TextureTranscoder, LASLoaderPlugin, Label3D, LambertMaterial, LightMap, LineSet, LinearEncoding, LinearFilter, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, Loader, LoadingManager, LocaleService, LuminanceAlphaFormat, LuminanceFormat, Map$1 as Map, Marker, MarqueePicker, MarqueePickerMouseControl, Mesh, MeshSurfaceArea, MeshVolume, MetallicMaterial, MirroredRepeatWrapping, ModelMemento, NavCubePlugin, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, Node$1 as Node, OBJLoaderPlugin, ObjectsKdTree3, ObjectsMemento, PNGMediaType, Path, PerformanceModel, PhongMaterial, PickResult, Plugin, PointLight, PointerCircle, PointerLens, QuadraticBezierCurve, Queue, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, ReadableGeometry, RedFormat, RedIntegerFormat, ReflectionMap, RepeatWrapping, STLDefaultDataSource, STLLoaderPlugin, SceneModel, SceneModelMesh, SceneModelTransform, SectionPlane, SectionPlanesPlugin, ShortType, Skybox, SkyboxesPlugin, SpecularMaterial, SplineCurve, SpriteMarker, StoreyViewsPlugin, Texture, TextureTranscoder, TreeViewPlugin, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VBOGeometry, ViewCullPlugin, Viewer, WebIFCLoaderPlugin, Wire3D, WorkerPool$1 as WorkerPool, XKTDefaultDataSource, XKTLoaderPlugin, XML3DLoaderPlugin, ZoneEditControl, ZoneEditMouseControl, ZoneEditTouchControl, ZoneTranslateControl, ZoneTranslateMouseControl, ZoneTranslateTouchControl, ZonesMouseControl, ZonesPlugin, ZonesPolysurfaceMouseControl, ZonesPolysurfaceTouchControl, ZonesTouchControl, activateDraggableDot, activateDraggableDots, addMousePressListener, addTouchPressListener, buildBoxGeometry, buildBoxLinesGeometry, buildBoxLinesGeometryFromAABB, buildCylinderGeometry, buildGridGeometry, buildLineGeometry, buildPlaneGeometry, buildPolylineGeometry, buildPolylineGeometryFromCurve, buildSphereGeometry, buildTorusGeometry, buildVectorTextGeometry, createRTCViewMat, frustumIntersectsAABB3, getKTX2TextureTranscoder, getPlaneRTCPos, isTriangleMeshSolid, load3DSGeometry, loadOBJGeometry, marker3D, math, meshSurfaceArea, meshVolume, os, rtcToWorldPos, sRGBEncoding, setFrustum, startPolygonCreate, stats, touchPointSelector, transformToNode, triangulateEarClipping, utils, wire3D, worldToRTCPos, worldToRTCPositions };